aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k
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/m68k
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/m68k')
-rw-r--r--arch/m68k/Kconfig670
-rw-r--r--arch/m68k/Kconfig.debug5
-rw-r--r--arch/m68k/Makefile126
-rw-r--r--arch/m68k/amiga/Makefile7
-rw-r--r--arch/m68k/amiga/amiga_ksyms.c36
-rw-r--r--arch/m68k/amiga/amiints.c520
-rw-r--r--arch/m68k/amiga/amisound.c113
-rw-r--r--arch/m68k/amiga/chipram.c133
-rw-r--r--arch/m68k/amiga/cia.c180
-rw-r--r--arch/m68k/amiga/config.c1007
-rw-r--r--arch/m68k/amiga/pcmcia.c113
-rw-r--r--arch/m68k/apollo/Makefile5
-rw-r--r--arch/m68k/apollo/config.c305
-rw-r--r--arch/m68k/apollo/dma.c50
-rw-r--r--arch/m68k/apollo/dn_ints.c125
-rw-r--r--arch/m68k/atari/Makefile10
-rw-r--r--arch/m68k/atari/ataints.c648
-rw-r--r--arch/m68k/atari/atari_ksyms.c35
-rw-r--r--arch/m68k/atari/atasound.c109
-rw-r--r--arch/m68k/atari/atasound.h33
-rw-r--r--arch/m68k/atari/config.c726
-rw-r--r--arch/m68k/atari/debug.c347
-rw-r--r--arch/m68k/atari/hades-pci.c444
-rw-r--r--arch/m68k/atari/stdma.c196
-rw-r--r--arch/m68k/atari/stram.c1247
-rw-r--r--arch/m68k/atari/time.c348
-rw-r--r--arch/m68k/bvme6000/Makefile5
-rw-r--r--arch/m68k/bvme6000/bvmeints.c160
-rw-r--r--arch/m68k/bvme6000/config.c380
-rw-r--r--arch/m68k/bvme6000/rtc.c182
-rw-r--r--arch/m68k/configs/amiga_defconfig968
-rw-r--r--arch/m68k/configs/apollo_defconfig825
-rw-r--r--arch/m68k/configs/atari_defconfig880
-rw-r--r--arch/m68k/configs/bvme6000_defconfig824
-rw-r--r--arch/m68k/configs/hp300_defconfig824
-rw-r--r--arch/m68k/configs/mac_defconfig903
-rw-r--r--arch/m68k/configs/mvme147_defconfig843
-rw-r--r--arch/m68k/configs/mvme16x_defconfig842
-rw-r--r--arch/m68k/configs/q40_defconfig915
-rw-r--r--arch/m68k/configs/sun3_defconfig831
-rw-r--r--arch/m68k/configs/sun3x_defconfig841
-rw-r--r--arch/m68k/defconfig629
-rw-r--r--arch/m68k/fpsp040/Makefile16
-rw-r--r--arch/m68k/fpsp040/README30
-rw-r--r--arch/m68k/fpsp040/bindec.S920
-rw-r--r--arch/m68k/fpsp040/binstr.S140
-rw-r--r--arch/m68k/fpsp040/bugfix.S496
-rw-r--r--arch/m68k/fpsp040/decbin.S506
-rw-r--r--arch/m68k/fpsp040/do_func.S559
-rw-r--r--arch/m68k/fpsp040/fpsp.h348
-rw-r--r--arch/m68k/fpsp040/gen_except.S468
-rw-r--r--arch/m68k/fpsp040/get_op.S676
-rw-r--r--arch/m68k/fpsp040/kernel_ex.S494
-rw-r--r--arch/m68k/fpsp040/res_func.S2040
-rw-r--r--arch/m68k/fpsp040/round.S649
-rw-r--r--arch/m68k/fpsp040/sacos.S115
-rw-r--r--arch/m68k/fpsp040/sasin.S104
-rw-r--r--arch/m68k/fpsp040/satan.S478
-rw-r--r--arch/m68k/fpsp040/satanh.S104
-rw-r--r--arch/m68k/fpsp040/scale.S371
-rw-r--r--arch/m68k/fpsp040/scosh.S132
-rw-r--r--arch/m68k/fpsp040/setox.S865
-rw-r--r--arch/m68k/fpsp040/sgetem.S141
-rw-r--r--arch/m68k/fpsp040/sint.S247
-rw-r--r--arch/m68k/fpsp040/skeleton.S516
-rw-r--r--arch/m68k/fpsp040/slog2.S188
-rw-r--r--arch/m68k/fpsp040/slogn.S592
-rw-r--r--arch/m68k/fpsp040/smovecr.S162
-rw-r--r--arch/m68k/fpsp040/srem_mod.S422
-rw-r--r--arch/m68k/fpsp040/ssin.S746
-rw-r--r--arch/m68k/fpsp040/ssinh.S135
-rw-r--r--arch/m68k/fpsp040/stan.S455
-rw-r--r--arch/m68k/fpsp040/stanh.S185
-rw-r--r--arch/m68k/fpsp040/sto_res.S98
-rw-r--r--arch/m68k/fpsp040/stwotox.S427
-rw-r--r--arch/m68k/fpsp040/tbldo.S554
-rw-r--r--arch/m68k/fpsp040/util.S748
-rw-r--r--arch/m68k/fpsp040/x_bsun.S47
-rw-r--r--arch/m68k/fpsp040/x_fline.S104
-rw-r--r--arch/m68k/fpsp040/x_operr.S356
-rw-r--r--arch/m68k/fpsp040/x_ovfl.S186
-rw-r--r--arch/m68k/fpsp040/x_snan.S277
-rw-r--r--arch/m68k/fpsp040/x_store.S256
-rw-r--r--arch/m68k/fpsp040/x_unfl.S269
-rw-r--r--arch/m68k/fpsp040/x_unimp.S77
-rw-r--r--arch/m68k/fpsp040/x_unsupp.S83
-rw-r--r--arch/m68k/hp300/Makefile5
-rw-r--r--arch/m68k/hp300/README.hp30014
-rw-r--r--arch/m68k/hp300/config.c279
-rw-r--r--arch/m68k/hp300/hp300map.map252
-rw-r--r--arch/m68k/hp300/ints.c175
-rw-r--r--arch/m68k/hp300/ints.h9
-rw-r--r--arch/m68k/hp300/ksyms.c9
-rw-r--r--arch/m68k/hp300/reboot.S16
-rw-r--r--arch/m68k/hp300/time.c78
-rw-r--r--arch/m68k/hp300/time.h4
-rw-r--r--arch/m68k/ifpsp060/CHANGES120
-rw-r--r--arch/m68k/ifpsp060/MISC201
-rw-r--r--arch/m68k/ifpsp060/Makefile10
-rw-r--r--arch/m68k/ifpsp060/README71
-rw-r--r--arch/m68k/ifpsp060/TEST.DOC208
-rw-r--r--arch/m68k/ifpsp060/fplsp.doc231
-rw-r--r--arch/m68k/ifpsp060/fplsp.sa1946
-rw-r--r--arch/m68k/ifpsp060/fpsp.doc295
-rw-r--r--arch/m68k/ifpsp060/fpsp.sa3401
-rw-r--r--arch/m68k/ifpsp060/fskeleton.S342
-rw-r--r--arch/m68k/ifpsp060/ftest.sa371
-rw-r--r--arch/m68k/ifpsp060/ilsp.doc150
-rw-r--r--arch/m68k/ifpsp060/ilsp.sa101
-rw-r--r--arch/m68k/ifpsp060/iskeleton.S349
-rw-r--r--arch/m68k/ifpsp060/isp.doc218
-rw-r--r--arch/m68k/ifpsp060/isp.sa392
-rw-r--r--arch/m68k/ifpsp060/itest.sa1281
-rw-r--r--arch/m68k/ifpsp060/os.S396
-rw-r--r--arch/m68k/ifpsp060/pfpsp.sa1730
-rw-r--r--arch/m68k/ifpsp060/src/README-SRC12
-rw-r--r--arch/m68k/ifpsp060/src/fplsp.S10980
-rw-r--r--arch/m68k/ifpsp060/src/fpsp.S24785
-rw-r--r--arch/m68k/ifpsp060/src/ftest.S1456
-rw-r--r--arch/m68k/ifpsp060/src/ilsp.S932
-rw-r--r--arch/m68k/ifpsp060/src/isp.S4299
-rw-r--r--arch/m68k/ifpsp060/src/itest.S6386
-rw-r--r--arch/m68k/ifpsp060/src/pfpsp.S14745
-rw-r--r--arch/m68k/kernel/Makefile18
-rw-r--r--arch/m68k/kernel/asm-offsets.c109
-rw-r--r--arch/m68k/kernel/bios32.c515
-rw-r--r--arch/m68k/kernel/entry.S712
-rw-r--r--arch/m68k/kernel/head.S3940
-rw-r--r--arch/m68k/kernel/ints.c281
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c88
-rw-r--r--arch/m68k/kernel/module.c128
-rw-r--r--arch/m68k/kernel/process.c405
-rw-r--r--arch/m68k/kernel/ptrace.c393
-rw-r--r--arch/m68k/kernel/semaphore.c133
-rw-r--r--arch/m68k/kernel/setup.c545
-rw-r--r--arch/m68k/kernel/signal.c1025
-rw-r--r--arch/m68k/kernel/sun3-head.S104
-rw-r--r--arch/m68k/kernel/sys_m68k.c671
-rw-r--r--arch/m68k/kernel/time.c187
-rw-r--r--arch/m68k/kernel/traps.c1227
-rw-r--r--arch/m68k/kernel/vmlinux-std.lds95
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds95
-rw-r--r--arch/m68k/kernel/vmlinux.lds.S11
-rw-r--r--arch/m68k/lib/Makefile8
-rw-r--r--arch/m68k/lib/ashldi3.c62
-rw-r--r--arch/m68k/lib/ashrdi3.c63
-rw-r--r--arch/m68k/lib/checksum.c422
-rw-r--r--arch/m68k/lib/lshrdi3.c62
-rw-r--r--arch/m68k/lib/memcmp.c11
-rw-r--r--arch/m68k/lib/memcpy.c75
-rw-r--r--arch/m68k/lib/memset.c68
-rw-r--r--arch/m68k/lib/muldi3.c63
-rw-r--r--arch/m68k/lib/semaphore.S53
-rw-r--r--arch/m68k/mac/Makefile6
-rw-r--r--arch/m68k/mac/baboon.c126
-rw-r--r--arch/m68k/mac/bootparse.c122
-rw-r--r--arch/m68k/mac/config.c902
-rw-r--r--arch/m68k/mac/debug.c398
-rw-r--r--arch/m68k/mac/iop.c714
-rw-r--r--arch/m68k/mac/mac_ksyms.c8
-rw-r--r--arch/m68k/mac/mac_penguin.S75
-rw-r--r--arch/m68k/mac/macboing.c309
-rw-r--r--arch/m68k/mac/macints.c760
-rw-r--r--arch/m68k/mac/misc.c651
-rw-r--r--arch/m68k/mac/oss.c301
-rw-r--r--arch/m68k/mac/psc.c197
-rw-r--r--arch/m68k/mac/via.c619
-rw-r--r--arch/m68k/math-emu/Makefile11
-rw-r--r--arch/m68k/math-emu/fp_arith.c701
-rw-r--r--arch/m68k/math-emu/fp_arith.h52
-rw-r--r--arch/m68k/math-emu/fp_cond.S334
-rw-r--r--arch/m68k/math-emu/fp_decode.h417
-rw-r--r--arch/m68k/math-emu/fp_emu.h146
-rw-r--r--arch/m68k/math-emu/fp_entry.S325
-rw-r--r--arch/m68k/math-emu/fp_log.c223
-rw-r--r--arch/m68k/math-emu/fp_move.S244
-rw-r--r--arch/m68k/math-emu/fp_movem.S368
-rw-r--r--arch/m68k/math-emu/fp_scan.S478
-rw-r--r--arch/m68k/math-emu/fp_trig.c183
-rw-r--r--arch/m68k/math-emu/fp_trig.h32
-rw-r--r--arch/m68k/math-emu/fp_util.S1455
-rw-r--r--arch/m68k/math-emu/multi_arith.h819
-rw-r--r--arch/m68k/mm/Makefile8
-rw-r--r--arch/m68k/mm/fault.c219
-rw-r--r--arch/m68k/mm/hwtest.c85
-rw-r--r--arch/m68k/mm/init.c147
-rw-r--r--arch/m68k/mm/kmap.c361
-rw-r--r--arch/m68k/mm/memory.c471
-rw-r--r--arch/m68k/mm/motorola.c285
-rw-r--r--arch/m68k/mm/sun3kmap.c156
-rw-r--r--arch/m68k/mm/sun3mmu.c102
-rw-r--r--arch/m68k/mvme147/147ints.c145
-rw-r--r--arch/m68k/mvme147/Makefile5
-rw-r--r--arch/m68k/mvme147/config.c229
-rw-r--r--arch/m68k/mvme16x/16xints.c149
-rw-r--r--arch/m68k/mvme16x/Makefile5
-rw-r--r--arch/m68k/mvme16x/config.c286
-rw-r--r--arch/m68k/mvme16x/mvme16x_ksyms.c6
-rw-r--r--arch/m68k/mvme16x/rtc.c172
-rw-r--r--arch/m68k/q40/Makefile5
-rw-r--r--arch/m68k/q40/README138
-rw-r--r--arch/m68k/q40/config.c365
-rw-r--r--arch/m68k/q40/q40ints.c476
-rw-r--r--arch/m68k/sun3/Makefile7
-rw-r--r--arch/m68k/sun3/config.c188
-rw-r--r--arch/m68k/sun3/dvma.c71
-rw-r--r--arch/m68k/sun3/idprom.c129
-rw-r--r--arch/m68k/sun3/intersil.c76
-rw-r--r--arch/m68k/sun3/leds.c13
-rw-r--r--arch/m68k/sun3/mmu_emu.c427
-rw-r--r--arch/m68k/sun3/prom/Makefile7
-rw-r--r--arch/m68k/sun3/prom/console.c174
-rw-r--r--arch/m68k/sun3/prom/init.c89
-rw-r--r--arch/m68k/sun3/prom/misc.c94
-rw-r--r--arch/m68k/sun3/prom/printf.c61
-rw-r--r--arch/m68k/sun3/sbus.c27
-rw-r--r--arch/m68k/sun3/sun3_ksyms.c13
-rw-r--r--arch/m68k/sun3/sun3dvma.c379
-rw-r--r--arch/m68k/sun3/sun3ints.c265
-rw-r--r--arch/m68k/sun3x/Makefile5
-rw-r--r--arch/m68k/sun3x/config.c99
-rw-r--r--arch/m68k/sun3x/dvma.c208
-rw-r--r--arch/m68k/sun3x/prom.c166
-rw-r--r--arch/m68k/sun3x/time.c103
-rw-r--r--arch/m68k/sun3x/time.h19
-rw-r--r--arch/m68k/tools/amiga/Makefile11
-rw-r--r--arch/m68k/tools/amiga/dmesg.c69
227 files changed, 140481 insertions, 0 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
new file mode 100644
index 000000000000..d0713c7d9f0a
--- /dev/null
+++ b/arch/m68k/Kconfig
@@ -0,0 +1,670 @@
1#
2# For a description of the syntax of this configuration file,
3# see Documentation/kbuild/kconfig-language.txt.
4#
5config M68K
6 bool
7 default y
8
9config MMU
10 bool
11 default y
12
13config UID16
14 bool
15 default y
16
17config RWSEM_GENERIC_SPINLOCK
18 bool
19 default y
20
21config RWSEM_XCHGADD_ALGORITHM
22 bool
23
24config GENERIC_CALIBRATE_DELAY
25 bool
26 default y
27
28mainmenu "Linux/68k Kernel Configuration"
29
30source "init/Kconfig"
31
32menu "Platform dependent setup"
33
34config EISA
35 bool
36 ---help---
37 The Extended Industry Standard Architecture (EISA) bus was
38 developed as an open alternative to the IBM MicroChannel bus.
39
40 The EISA bus provided some of the features of the IBM MicroChannel
41 bus while maintaining backward compatibility with cards made for
42 the older ISA bus. The EISA bus saw limited use between 1988 and
43 1995 when it was made obsolete by the PCI bus.
44
45 Say Y here if you are building a kernel for an EISA-based machine.
46
47 Otherwise, say N.
48
49config MCA
50 bool
51 help
52 MicroChannel Architecture is found in some IBM PS/2 machines and
53 laptops. It is a bus system similar to PCI or ISA. See
54 <file:Documentation/mca.txt> (and especially the web page given
55 there) before attempting to build an MCA bus kernel.
56
57config PCMCIA
58 tristate
59 ---help---
60 Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
61 computer. These are credit-card size devices such as network cards,
62 modems or hard drives often used with laptops computers. There are
63 actually two varieties of these cards: the older 16 bit PCMCIA cards
64 and the newer 32 bit CardBus cards. If you want to use CardBus
65 cards, you need to say Y here and also to "CardBus support" below.
66
67 To use your PC-cards, you will need supporting software from David
68 Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
69 for location). Please also read the PCMCIA-HOWTO, available from
70 <http://www.tldp.org/docs.html#howto>.
71
72 To compile this driver as modules, choose M here: the
73 modules will be called pcmcia_core and ds.
74
75config SUN3
76 bool "Sun3 support"
77 select M68020
78 select MMU_SUN3 if MMU
79 help
80 This option enables support for the Sun 3 series of workstations
81 (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
82 that all other hardware types must be disabled, as Sun 3 kernels
83 are incompatible with all other m68k targets (including Sun 3x!).
84
85 If you don't want to compile a kernel exclusively for a Sun 3, say N.
86
87config AMIGA
88 bool "Amiga support"
89 depends on !MMU_SUN3
90 help
91 This option enables support for the Amiga series of computers. If
92 you plan to use this kernel on an Amiga, say Y here and browse the
93 material available in <file:Documentation/m68k>; otherwise say N.
94
95config ATARI
96 bool "Atari support"
97 depends on !MMU_SUN3
98 help
99 This option enables support for the 68000-based Atari series of
100 computers (including the TT, Falcon and Medusa). If you plan to use
101 this kernel on an Atari, say Y here and browse the material
102 available in <file:Documentation/m68k>; otherwise say N.
103
104config HADES
105 bool "Hades support"
106 depends on ATARI && BROKEN
107 help
108 This option enables support for the Hades Atari clone. If you plan
109 to use this kernel on a Hades, say Y here; otherwise say N.
110
111config PCI
112 bool
113 depends on HADES
114 default y
115 help
116 Find out whether you have a PCI motherboard. PCI is the name of a
117 bus system, i.e. the way the CPU talks to the other stuff inside
118 your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
119 VESA. If you have PCI, say Y, otherwise N.
120
121 The PCI-HOWTO, available from
122 <http://www.tldp.org/docs.html#howto>, contains valuable
123 information about which PCI hardware does work under Linux and which
124 doesn't.
125
126config MAC
127 bool "Macintosh support"
128 depends on !MMU_SUN3
129 help
130 This option enables support for the Apple Macintosh series of
131 computers (yes, there is experimental support now, at least for part
132 of the series).
133
134 Say N unless you're willing to code the remaining necessary support.
135 ;)
136
137config NUBUS
138 bool
139 depends on MAC
140 default y
141
142config M68K_L2_CACHE
143 bool
144 depends on MAC
145 default y
146
147config APOLLO
148 bool "Apollo support"
149 depends on !MMU_SUN3
150 help
151 Say Y here if you want to run Linux on an MC680x0-based Apollo
152 Domain workstation such as the DN3500.
153
154config VME
155 bool "VME (Motorola and BVM) support"
156 depends on !MMU_SUN3
157 help
158 Say Y here if you want to build a kernel for a 680x0 based VME
159 board. Boards currently supported include Motorola boards MVME147,
160 MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and
161 BVME6000 boards from BVM Ltd are also supported.
162
163config MVME147
164 bool "MVME147 support"
165 depends on VME
166 help
167 Say Y to include support for early Motorola VME boards. This will
168 build a kernel which can run on MVME147 single-board computers. If
169 you select this option you will have to select the appropriate
170 drivers for SCSI, Ethernet and serial ports later on.
171
172config MVME16x
173 bool "MVME162, 166 and 167 support"
174 depends on VME
175 help
176 Say Y to include support for Motorola VME boards. This will build a
177 kernel which can run on MVME162, MVME166, MVME167, MVME172, and
178 MVME177 boards. If you select this option you will have to select
179 the appropriate drivers for SCSI, Ethernet and serial ports later
180 on.
181
182config BVME6000
183 bool "BVME4000 and BVME6000 support"
184 depends on VME
185 help
186 Say Y to include support for VME boards from BVM Ltd. This will
187 build a kernel which can run on BVME4000 and BVME6000 boards. If
188 you select this option you will have to select the appropriate
189 drivers for SCSI, Ethernet and serial ports later on.
190
191config HP300
192 bool "HP9000/300 and HP9000/400 support"
193 depends on !MMU_SUN3
194 help
195 This option enables support for the HP9000/300 and HP9000/400 series
196 of workstations. Support for these machines is still somewhat
197 experimental. If you plan to try to use the kernel on such a machine
198 say Y here.
199 Everybody else says N.
200
201config DIO
202 bool "DIO bus support"
203 depends on HP300
204 default y
205 help
206 Say Y here to enable support for the "DIO" expansion bus used in
207 HP300 machines. If you are using such a system you almost certainly
208 want this.
209
210config SUN3X
211 bool "Sun3x support"
212 depends on !MMU_SUN3
213 select M68030
214 help
215 This option enables support for the Sun 3x series of workstations.
216 Be warned that this support is very experimental.
217 Note that Sun 3x kernels are not compatible with Sun 3 hardware.
218 General Linux information on the Sun 3x series (now discontinued)
219 is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
220
221 If you don't want to compile a kernel for a Sun 3x, say N.
222
223config Q40
224 bool "Q40/Q60 support"
225 depends on !MMU_SUN3
226 help
227 The Q40 is a Motorola 68040-based successor to the Sinclair QL
228 manufactured in Germany. There is an official Q40 home page at
229 <http://www.q40.de/>. This option enables support for the Q40 and
230 Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
231 emulation.
232
233comment "Processor type"
234
235config M68020
236 bool "68020 support"
237 help
238 If you anticipate running this kernel on a computer with a MC68020
239 processor, say Y. Otherwise, say N. Note that the 68020 requires a
240 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
241 Sun 3, which provides its own version.
242
243config M68030
244 bool "68030 support"
245 depends on !MMU_SUN3
246 help
247 If you anticipate running this kernel on a computer with a MC68030
248 processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
249 work, as it does not include an MMU (Memory Management Unit).
250
251config M68040
252 bool "68040 support"
253 depends on !MMU_SUN3
254 help
255 If you anticipate running this kernel on a computer with a MC68LC040
256 or MC68040 processor, say Y. Otherwise, say N. Note that an
257 MC68EC040 will not work, as it does not include an MMU (Memory
258 Management Unit).
259
260config M68060
261 bool "68060 support"
262 depends on !MMU_SUN3
263 help
264 If you anticipate running this kernel on a computer with a MC68060
265 processor, say Y. Otherwise, say N.
266
267config MMU_MOTOROLA
268 bool
269 depends on MMU && !MMU_SUN3
270 default y
271
272config MMU_SUN3
273 bool
274
275config M68KFPU_EMU
276 bool "Math emulation support (EXPERIMENTAL)"
277 depends on EXPERIMENTAL
278 help
279 At some point in the future, this will cause floating-point math
280 instructions to be emulated by the kernel on machines that lack a
281 floating-point math coprocessor. Thrill-seekers and chronically
282 sleep-deprived psychotic hacker types can say Y now, everyone else
283 should probably wait a while.
284
285config M68KFPU_EMU_EXTRAPREC
286 bool "Math emulation extra precision"
287 depends on M68KFPU_EMU
288 help
289 The fpu uses normally a few bit more during calculations for
290 correct rounding, the emulator can (often) do the same but this
291 extra calculation can cost quite some time, so you can disable
292 it here. The emulator will then "only" calculate with a 64 bit
293 mantissa and round slightly incorrect, what is more then enough
294 for normal usage.
295
296config M68KFPU_EMU_ONLY
297 bool "Math emulation only kernel"
298 depends on M68KFPU_EMU
299 help
300 This option prevents any floating-point instructions from being
301 compiled into the kernel, thereby the kernel doesn't save any
302 floating point context anymore during task switches, so this
303 kernel will only be usable on machines without a floating-point
304 math coprocessor. This makes the kernel a bit faster as no tests
305 needs to be executed whether a floating-point instruction in the
306 kernel should be executed or not.
307
308config ADVANCED
309 bool "Advanced configuration options"
310 ---help---
311 This gives you access to some advanced options for the CPU. The
312 defaults should be fine for most users, but these options may make
313 it possible for you to improve performance somewhat if you know what
314 you are doing.
315
316 Note that the answer to this question won't directly affect the
317 kernel: saying N will just cause the configurator to skip all
318 the questions about these options.
319
320 Most users should say N to this question.
321
322config RMW_INSNS
323 bool "Use read-modify-write instructions"
324 depends on ADVANCED
325 ---help---
326 This allows to use certain instructions that work with indivisible
327 read-modify-write bus cycles. While this is faster than the
328 workaround of disabling interrupts, it can conflict with DMA
329 ( = direct memory access) on many Amiga systems, and it is also said
330 to destabilize other machines. It is very likely that this will
331 cause serious problems on any Amiga or Atari Medusa if set. The only
332 configuration where it should work are 68030-based Ataris, where it
333 apparently improves performance. But you've been warned! Unless you
334 really know what you are doing, say N. Try Y only if you're quite
335 adventurous.
336
337config SINGLE_MEMORY_CHUNK
338 bool "Use one physical chunk of memory only"
339 depends on ADVANCED && !SUN3
340 help
341 Ignore all but the first contiguous chunk of physical memory for VM
342 purposes. This will save a few bytes kernel size and may speed up
343 some operations. Say N if not sure.
344
345config 060_WRITETHROUGH
346 bool "Use write-through caching for 68060 supervisor accesses"
347 depends on ADVANCED && M68060
348 ---help---
349 The 68060 generally uses copyback caching of recently accessed data.
350 Copyback caching means that memory writes will be held in an on-chip
351 cache and only written back to memory some time later. Saying Y
352 here will force supervisor (kernel) accesses to use writethrough
353 caching. Writethrough caching means that data is written to memory
354 straight away, so that cache and memory data always agree.
355 Writethrough caching is less efficient, but is needed for some
356 drivers on 68060 based systems where the 68060 bus snooping signal
357 is hardwired on. The 53c710 SCSI driver is known to suffer from
358 this problem.
359
360endmenu
361
362menu "General setup"
363
364source "fs/Kconfig.binfmt"
365
366config ZORRO
367 bool "Amiga Zorro (AutoConfig) bus support"
368 depends on AMIGA
369 help
370 This enables support for the Zorro bus in the Amiga. If you have
371 expansion cards in your Amiga that conform to the Amiga
372 AutoConfig(tm) specification, say Y, otherwise N. Note that even
373 expansion cards that do not fit in the Zorro slots but fit in e.g.
374 the CPU slot may fall in this category, so you have to say Y to let
375 Linux use these.
376
377config AMIGA_PCMCIA
378 bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
379 depends on AMIGA && EXPERIMENTAL
380 help
381 Include support in the kernel for pcmcia on Amiga 1200 and Amiga
382 600. If you intend to use pcmcia cards say Y; otherwise say N.
383
384config STRAM_SWAP
385 bool "Support for ST-RAM as swap space"
386 depends on ATARI && BROKEN
387 ---help---
388 Some Atari 68k machines (including the 520STF and 1020STE) divide
389 their addressable memory into ST and TT sections. The TT section
390 (up to 512MB) is the main memory; the ST section (up to 4MB) is
391 accessible to the built-in graphics board, runs slower, and is
392 present mainly for backward compatibility with older machines.
393
394 This enables support for using (parts of) ST-RAM as swap space,
395 instead of as normal system memory. This can first enhance system
396 performance if you have lots of alternate RAM (compared to the size
397 of ST-RAM), because executable code always will reside in faster
398 memory. ST-RAM will remain as ultra-fast swap space. On the other
399 hand, it allows much improved dynamic allocations of ST-RAM buffers
400 for device driver modules (e.g. floppy, ACSI, SLM printer, DMA
401 sound). The probability that such allocations at module load time
402 fail is drastically reduced.
403
404config STRAM_PROC
405 bool "ST-RAM statistics in /proc"
406 depends on ATARI
407 help
408 Say Y here to report ST-RAM usage statistics in /proc/stram. See
409 the help for CONFIG_STRAM_SWAP for discussion of ST-RAM and its
410 uses.
411
412config HEARTBEAT
413 bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
414 default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
415 help
416 Use the power-on LED on your machine as a load meter. The exact
417 behavior is platform-dependent, but normally the flash frequency is
418 a hyperbolic function of the 5-minute load average.
419
420# We have a dedicated heartbeat LED. :-)
421config PROC_HARDWARE
422 bool "/proc/hardware support"
423 help
424 Say Y here to support the /proc/hardware file, which gives you
425 access to information about the machine you're running on,
426 including the model, CPU, MMU, clock speed, BogoMIPS rating,
427 and memory size.
428
429config ISA
430 bool
431 depends on Q40 || AMIGA_PCMCIA || GG2
432 default y
433 help
434 Find out whether you have ISA slots on your motherboard. ISA is the
435 name of a bus system, i.e. the way the CPU talks to the other stuff
436 inside your box. Other bus systems are PCI, EISA, MicroChannel
437 (MCA) or VESA. ISA is an older system, now being displaced by PCI;
438 newer boards don't support it. If you have ISA, say Y, otherwise N.
439
440config GENERIC_ISA_DMA
441 bool
442 depends on Q40 || AMIGA_PCMCIA || GG2
443 default y
444
445source "drivers/pci/Kconfig"
446
447source "drivers/zorro/Kconfig"
448
449endmenu
450
451source "drivers/Kconfig"
452
453menu "Character devices"
454
455config ATARI_MFPSER
456 tristate "Atari MFP serial support"
457 depends on ATARI
458 ---help---
459 If you like to use the MFP serial ports ("Modem1", "Serial1") under
460 Linux, say Y. The driver equally supports all kinds of MFP serial
461 ports and automatically detects whether Serial1 is available.
462
463 To compile this driver as a module, choose M here.
464
465 Note for Falcon users: You also have an MFP port, it's just not
466 wired to the outside... But you could use the port under Linux.
467
468config ATARI_SCC
469 tristate "Atari SCC serial support"
470 depends on ATARI
471 ---help---
472 If you have serial ports based on a Zilog SCC chip (Modem2, Serial2,
473 LAN) and like to use them under Linux, say Y. All built-in SCC's are
474 supported (TT, MegaSTE, Falcon), and also the ST-ESCC. If you have
475 two connectors for channel A (Serial2 and LAN), they are visible as
476 two separate devices.
477
478 To compile this driver as a module, choose M here.
479
480config ATARI_SCC_DMA
481 bool "Atari SCC serial DMA support"
482 depends on ATARI_SCC
483 help
484 This enables DMA support for receiving data on channel A of the SCC.
485 If you have a TT you may say Y here and read
486 drivers/char/atari_SCC.README. All other users should say N here,
487 because only the TT has SCC-DMA, even if your machine keeps claiming
488 so at boot time.
489
490config ATARI_MIDI
491 tristate "Atari MIDI serial support"
492 depends on ATARI
493 help
494 If you want to use your Atari's MIDI port in Linux, say Y.
495
496 To compile this driver as a module, choose M here.
497
498config ATARI_DSP56K
499 tristate "Atari DSP56k support (EXPERIMENTAL)"
500 depends on ATARI && EXPERIMENTAL
501 help
502 If you want to be able to use the DSP56001 in Falcons, say Y. This
503 driver is still experimental, and if you don't know what it is, or
504 if you don't have this processor, just say N.
505
506 To compile this driver as a module, choose M here.
507
508config AMIGA_BUILTIN_SERIAL
509 tristate "Amiga builtin serial support"
510 depends on AMIGA
511 help
512 If you want to use your Amiga's built-in serial port in Linux,
513 answer Y.
514
515 To compile this driver as a module, choose M here.
516
517config WHIPPET_SERIAL
518 tristate "Hisoft Whippet PCMCIA serial support"
519 depends on AMIGA_PCMCIA
520 help
521 HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
522 is no listing for the Whippet in their Amiga section.
523
524config MULTIFACE_III_TTY
525 tristate "Multiface Card III serial support"
526 depends on AMIGA
527 help
528 If you want to use a Multiface III card's serial port in Linux,
529 answer Y.
530
531 To compile this driver as a module, choose M here.
532
533config GVPIOEXT
534 tristate "GVP IO-Extender support"
535 depends on PARPORT=n && ZORRO
536 help
537 If you want to use a GVP IO-Extender serial card in Linux, say Y.
538 Otherwise, say N.
539
540config GVPIOEXT_LP
541 tristate "GVP IO-Extender parallel printer support"
542 depends on GVPIOEXT
543 help
544 Say Y to enable driving a printer from the parallel port on your
545 GVP IO-Extender card, N otherwise.
546
547config GVPIOEXT_PLIP
548 tristate "GVP IO-Extender PLIP support"
549 depends on GVPIOEXT
550 help
551 Say Y to enable doing IP over the parallel port on your GVP
552 IO-Extender card, N otherwise.
553
554config MAC_SCC
555 tristate "Macintosh serial support"
556 depends on MAC
557
558config MAC_HID
559 bool
560 depends on INPUT_ADBHID
561 default y
562
563config MAC_ADBKEYCODES
564 bool "Support for ADB raw keycodes"
565 depends on INPUT_ADBHID
566 help
567 This provides support for sending raw ADB keycodes to console
568 devices. This is the default up to 2.4.0, but in future this may be
569 phased out in favor of generic Linux keycodes. If you say Y here,
570 you can dynamically switch via the
571 /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
572 sysctl and with the "keyboard_sends_linux_keycodes=" kernel
573 argument.
574
575 If unsure, say Y here.
576
577config ADB_KEYBOARD
578 bool "Support for ADB keyboard (old driver)"
579 depends on MAC && !INPUT_ADBHID
580 help
581 This option allows you to use an ADB keyboard attached to your
582 machine. Note that this disables any other (ie. PS/2) keyboard
583 support, even if your machine is physically capable of using both at
584 the same time.
585
586 If you use an ADB keyboard (4 pin connector), say Y here.
587 If you use a PS/2 keyboard (6 pin connector), say N here.
588
589config HPDCA
590 tristate "HP DCA serial support"
591 depends on DIO && SERIAL_8250
592 help
593 If you want to use the internal "DCA" serial ports on an HP300
594 machine, say Y here.
595
596config HPAPCI
597 tristate "HP APCI serial support"
598 depends on HP300 && SERIAL_8250 && EXPERIMENTAL
599 help
600 If you want to use the internal "APCI" serial ports on an HP400
601 machine, say Y here.
602
603config MVME147_SCC
604 bool "SCC support for MVME147 serial ports"
605 depends on MVME147
606 help
607 This is the driver for the serial ports on the Motorola MVME147
608 boards. Everyone using one of these boards should say Y here.
609
610config SERIAL167
611 bool "CD2401 support for MVME166/7 serial ports"
612 depends on MVME16x && BROKEN
613 help
614 This is the driver for the serial ports on the Motorola MVME166,
615 167, and 172 boards. Everyone using one of these boards should say
616 Y here.
617
618config MVME162_SCC
619 bool "SCC support for MVME162 serial ports"
620 depends on MVME16x
621 help
622 This is the driver for the serial ports on the Motorola MVME162 and
623 172 boards. Everyone using one of these boards should say Y here.
624
625config BVME6000_SCC
626 bool "SCC support for BVME6000 serial ports"
627 depends on BVME6000
628 help
629 This is the driver for the serial ports on the BVME4000 and BVME6000
630 boards from BVM Ltd. Everyone using one of these boards should say
631 Y here.
632
633config DN_SERIAL
634 bool "Support for DN serial port (dummy)"
635 depends on APOLLO
636
637config SERIAL_CONSOLE
638 bool "Support for serial port console"
639 depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
640 ---help---
641 If you say Y here, it will be possible to use a serial port as the
642 system console (the system console is the device which receives all
643 kernel messages and warnings and which allows logins in single user
644 mode). This could be useful if some terminal or printer is connected
645 to that serial port.
646
647 Even if you say Y here, the currently visible virtual console
648 (/dev/tty0) will still be used as the system console by default, but
649 you can alter that using a kernel command line option such as
650 "console=ttyS1". (Try "man bootparam" or see the documentation of
651 your boot loader (lilo or loadlin) about how to pass options to the
652 kernel at boot time.)
653
654 If you don't have a VGA card installed and you say Y here, the
655 kernel will automatically use the first serial line, /dev/ttyS0, as
656 system console.
657
658 If unsure, say N.
659
660endmenu
661
662source "fs/Kconfig"
663
664source "arch/m68k/Kconfig.debug"
665
666source "security/Kconfig"
667
668source "crypto/Kconfig"
669
670source "lib/Kconfig"
diff --git a/arch/m68k/Kconfig.debug b/arch/m68k/Kconfig.debug
new file mode 100644
index 000000000000..f53b6d5300e5
--- /dev/null
+++ b/arch/m68k/Kconfig.debug
@@ -0,0 +1,5 @@
1menu "Kernel hacking"
2
3source "lib/Kconfig.debug"
4
5endmenu
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
new file mode 100644
index 000000000000..466e7407afc7
--- /dev/null
+++ b/arch/m68k/Makefile
@@ -0,0 +1,126 @@
1#
2# m68k/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 Hamish Macdonald
14#
15
16# test for cross compiling
17COMPILE_ARCH = $(shell uname -m)
18
19# override top level makefile
20AS += -m68020
21LDFLAGS := -m m68kelf
22ifneq ($(COMPILE_ARCH),$(ARCH))
23 # prefix for cross-compiling binaries
24 CROSS_COMPILE = m68k-linux-
25endif
26
27ifdef CONFIG_SUN3
28LDFLAGS_vmlinux = -N
29endif
30
31CHECKFLAGS += -D__mc68000__
32
33# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
34CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
35
36# enable processor switch if compiled only for a single cpu
37ifndef CONFIG_M68020
38ifndef CONFIG_M68030
39
40ifndef CONFIG_M68060
41CFLAGS := $(CFLAGS) -m68040
42endif
43
44ifndef CONFIG_M68040
45CFLAGS := $(CFLAGS) -m68060
46endif
47
48endif
49endif
50
51ifdef CONFIG_KGDB
52# If configured for kgdb support, include debugging infos and keep the
53# frame pointer
54CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
55endif
56
57ifndef CONFIG_SUN3
58head-y := arch/m68k/kernel/head.o
59else
60head-y := arch/m68k/kernel/sun3-head.o
61endif
62
63core-y += arch/m68k/kernel/ arch/m68k/mm/
64libs-y += arch/m68k/lib/
65
66core-$(CONFIG_Q40) += arch/m68k/q40/
67core-$(CONFIG_AMIGA) += arch/m68k/amiga/
68core-$(CONFIG_ATARI) += arch/m68k/atari/
69core-$(CONFIG_MAC) += arch/m68k/mac/
70core-$(CONFIG_HP300) += arch/m68k/hp300/
71core-$(CONFIG_APOLLO) += arch/m68k/apollo/
72core-$(CONFIG_MVME147) += arch/m68k/mvme147/
73core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/
74core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/
75core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/
76core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/
77core-$(CONFIG_M68040) += arch/m68k/fpsp040/
78core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
79core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
80
81all: zImage
82
83lilo: vmlinux
84 if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
85 if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
86 cat vmlinux > $(INSTALL_PATH)/vmlinux
87 cp System.map $(INSTALL_PATH)/System.map
88 if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
89
90zImage compressed: vmlinux.gz
91
92vmlinux.gz: vmlinux
93
94ifndef CONFIG_KGDB
95 cp vmlinux vmlinux.tmp
96 $(STRIP) vmlinux.tmp
97 gzip -9c vmlinux.tmp >vmlinux.gz
98 rm vmlinux.tmp
99else
100 gzip -9c vmlinux >vmlinux.gz
101endif
102
103bzImage: vmlinux.bz2
104
105vmlinux.bz2: vmlinux
106
107ifndef CONFIG_KGDB
108 cp vmlinux vmlinux.tmp
109 $(STRIP) vmlinux.tmp
110 bzip2 -1c vmlinux.tmp >vmlinux.bz2
111 rm vmlinux.tmp
112else
113 bzip2 -1c vmlinux >vmlinux.bz2
114endif
115
116prepare: include/asm-$(ARCH)/offsets.h
117CLEAN_FILES += include/asm-$(ARCH)/offsets.h
118
119arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
120 include/config/MARKER
121
122include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
123 $(call filechk,gen-asm-offsets)
124
125archclean:
126 rm -f vmlinux.gz vmlinux.bz2
diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
new file mode 100644
index 000000000000..8b415651edee
--- /dev/null
+++ b/arch/m68k/amiga/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for Linux arch/m68k/amiga source directory
3#
4
5obj-y := config.o amiints.o cia.o chipram.o amisound.o amiga_ksyms.o
6
7obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
new file mode 100644
index 000000000000..b7bd84c73ea7
--- /dev/null
+++ b/arch/m68k/amiga/amiga_ksyms.c
@@ -0,0 +1,36 @@
1#include <linux/config.h>
2#include <linux/module.h>
3#include <linux/types.h>
4#include <asm/ptrace.h>
5#include <asm/amigahw.h>
6#include <asm/amigaints.h>
7#include <asm/amipcmcia.h>
8
9extern volatile u_short amiga_audio_min_period;
10extern u_short amiga_audio_period;
11
12/*
13 * Add things here when you find the need for it.
14 */
15EXPORT_SYMBOL(amiga_model);
16EXPORT_SYMBOL(amiga_chipset);
17EXPORT_SYMBOL(amiga_hw_present);
18EXPORT_SYMBOL(amiga_eclock);
19EXPORT_SYMBOL(amiga_colorclock);
20EXPORT_SYMBOL(amiga_chip_alloc);
21EXPORT_SYMBOL(amiga_chip_free);
22EXPORT_SYMBOL(amiga_chip_avail);
23EXPORT_SYMBOL(amiga_chip_size);
24EXPORT_SYMBOL(amiga_audio_period);
25EXPORT_SYMBOL(amiga_audio_min_period);
26EXPORT_SYMBOL(amiga_do_irq);
27EXPORT_SYMBOL(amiga_do_irq_list);
28
29#ifdef CONFIG_AMIGA_PCMCIA
30 EXPORT_SYMBOL(pcmcia_reset);
31 EXPORT_SYMBOL(pcmcia_copy_tuple);
32 EXPORT_SYMBOL(pcmcia_program_voltage);
33 EXPORT_SYMBOL(pcmcia_access_speed);
34 EXPORT_SYMBOL(pcmcia_write_enable);
35 EXPORT_SYMBOL(pcmcia_write_disable);
36#endif
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
new file mode 100644
index 000000000000..d9edf2d1a492
--- /dev/null
+++ b/arch/m68k/amiga/amiints.c
@@ -0,0 +1,520 @@
1/*
2 * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive
6 * for more details.
7 *
8 * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
9 * this sources where it makes sense (VERTB/PORTS/EXTER) and you must
10 * be careful that dev_id for this sources is unique since this the
11 * only possibility to distinguish between different handlers for
12 * free_irq. irq lists also have different irq flags:
13 * - IRQ_FLG_FAST: handler is inserted at top of list (after other
14 * fast handlers)
15 * - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
16 * they're executed irq level is set to the previous
17 * one, but handlers don't need to be reentrant, if
18 * reentrance occurred, slow handlers will be just
19 * called again.
20 * The whole interrupt handling for CIAs is moved to cia.c
21 * /Roman Zippel
22 *
23 * 07/08/99: rewamp of the interrupt handling - we now have two types of
24 * interrupts, normal and fast handlers, fast handlers being
25 * marked with SA_INTERRUPT and runs with all other interrupts
26 * disabled. Normal interrupts disable their own source but
27 * run with all other interrupt sources enabled.
28 * PORTS and EXTER interrupts are always shared even if the
29 * drivers do not explicitly mark this when calling
30 * request_irq which they really should do.
31 * This is similar to the way interrupts are handled on all
32 * other architectures and makes a ton of sense besides
33 * having the advantage of making it easier to share
34 * drivers.
35 * /Jes
36 */
37
38#include <linux/types.h>
39#include <linux/kernel.h>
40#include <linux/sched.h>
41#include <linux/kernel_stat.h>
42#include <linux/init.h>
43#include <linux/errno.h>
44#include <linux/seq_file.h>
45
46#include <asm/system.h>
47#include <asm/irq.h>
48#include <asm/traps.h>
49#include <asm/amigahw.h>
50#include <asm/amigaints.h>
51#include <asm/amipcmcia.h>
52
53extern int cia_request_irq(struct ciabase *base,int irq,
54 irqreturn_t (*handler)(int, void *, struct pt_regs *),
55 unsigned long flags, const char *devname, void *dev_id);
56extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
57extern void cia_init_IRQ(struct ciabase *base);
58extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p);
59
60/* irq node variables for amiga interrupt sources */
61static irq_node_t *ami_irq_list[AMI_STD_IRQS];
62
63static unsigned short amiga_intena_vals[AMI_STD_IRQS] = {
64 [IRQ_AMIGA_VERTB] = IF_VERTB,
65 [IRQ_AMIGA_COPPER] = IF_COPER,
66 [IRQ_AMIGA_AUD0] = IF_AUD0,
67 [IRQ_AMIGA_AUD1] = IF_AUD1,
68 [IRQ_AMIGA_AUD2] = IF_AUD2,
69 [IRQ_AMIGA_AUD3] = IF_AUD3,
70 [IRQ_AMIGA_BLIT] = IF_BLIT,
71 [IRQ_AMIGA_DSKSYN] = IF_DSKSYN,
72 [IRQ_AMIGA_DSKBLK] = IF_DSKBLK,
73 [IRQ_AMIGA_RBF] = IF_RBF,
74 [IRQ_AMIGA_TBE] = IF_TBE,
75 [IRQ_AMIGA_SOFT] = IF_SOFT,
76 [IRQ_AMIGA_PORTS] = IF_PORTS,
77 [IRQ_AMIGA_EXTER] = IF_EXTER
78};
79static const unsigned char ami_servers[AMI_STD_IRQS] = {
80 [IRQ_AMIGA_VERTB] = 1,
81 [IRQ_AMIGA_PORTS] = 1,
82 [IRQ_AMIGA_EXTER] = 1
83};
84
85static short ami_ablecount[AMI_IRQS];
86
87static irqreturn_t ami_badint(int irq, void *dev_id, struct pt_regs *fp)
88{
89 num_spurious += 1;
90 return IRQ_NONE;
91}
92
93/*
94 * void amiga_init_IRQ(void)
95 *
96 * Parameters: None
97 *
98 * Returns: Nothing
99 *
100 * This function should be called during kernel startup to initialize
101 * the amiga IRQ handling routines.
102 */
103
104void __init amiga_init_IRQ(void)
105{
106 int i;
107
108 /* initialize handlers */
109 for (i = 0; i < AMI_STD_IRQS; i++) {
110 if (ami_servers[i]) {
111 ami_irq_list[i] = NULL;
112 } else {
113 ami_irq_list[i] = new_irq_node();
114 ami_irq_list[i]->handler = ami_badint;
115 ami_irq_list[i]->flags = 0;
116 ami_irq_list[i]->dev_id = NULL;
117 ami_irq_list[i]->devname = NULL;
118 ami_irq_list[i]->next = NULL;
119 }
120 }
121 for (i = 0; i < AMI_IRQS; i++)
122 ami_ablecount[i] = 0;
123
124 /* turn off PCMCIA interrupts */
125 if (AMIGAHW_PRESENT(PCMCIA))
126 gayle.inten = GAYLE_IRQ_IDE;
127
128 /* turn off all interrupts and enable the master interrupt bit */
129 custom.intena = 0x7fff;
130 custom.intreq = 0x7fff;
131 custom.intena = IF_SETCLR | IF_INTEN;
132
133 cia_init_IRQ(&ciaa_base);
134 cia_init_IRQ(&ciab_base);
135}
136
137static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node)
138{
139 unsigned long flags;
140 irq_node_t *cur;
141
142 if (!node->dev_id)
143 printk("%s: Warning: dev_id of %s is zero\n",
144 __FUNCTION__, node->devname);
145
146 local_irq_save(flags);
147
148 cur = *list;
149
150 if (node->flags & SA_INTERRUPT) {
151 if (node->flags & SA_SHIRQ)
152 return -EBUSY;
153 /*
154 * There should never be more than one
155 */
156 while (cur && cur->flags & SA_INTERRUPT) {
157 list = &cur->next;
158 cur = cur->next;
159 }
160 } else {
161 while (cur) {
162 list = &cur->next;
163 cur = cur->next;
164 }
165 }
166
167 node->next = cur;
168 *list = node;
169
170 local_irq_restore(flags);
171 return 0;
172}
173
174static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
175{
176 unsigned long flags;
177 irq_node_t *node;
178
179 local_irq_save(flags);
180
181 for (node = *list; node; list = &node->next, node = *list) {
182 if (node->dev_id == dev_id) {
183 *list = node->next;
184 /* Mark it as free. */
185 node->handler = NULL;
186 local_irq_restore(flags);
187 return;
188 }
189 }
190 local_irq_restore(flags);
191 printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
192}
193
194/*
195 * amiga_request_irq : add an interrupt service routine for a particular
196 * machine specific interrupt source.
197 * If the addition was successful, it returns 0.
198 */
199
200int amiga_request_irq(unsigned int irq,
201 irqreturn_t (*handler)(int, void *, struct pt_regs *),
202 unsigned long flags, const char *devname, void *dev_id)
203{
204 irq_node_t *node;
205 int error = 0;
206
207 if (irq >= AMI_IRQS) {
208 printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
209 irq, devname);
210 return -ENXIO;
211 }
212
213 if (irq >= IRQ_AMIGA_AUTO)
214 return cpu_request_irq(irq - IRQ_AMIGA_AUTO, handler,
215 flags, devname, dev_id);
216
217 if (irq >= IRQ_AMIGA_CIAB)
218 return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
219 handler, flags, devname, dev_id);
220
221 if (irq >= IRQ_AMIGA_CIAA)
222 return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
223 handler, flags, devname, dev_id);
224
225 /*
226 * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared,
227 * we could add a check here for the SA_SHIRQ flag but all drivers
228 * should be aware of sharing anyway.
229 */
230 if (ami_servers[irq]) {
231 if (!(node = new_irq_node()))
232 return -ENOMEM;
233 node->handler = handler;
234 node->flags = flags;
235 node->dev_id = dev_id;
236 node->devname = devname;
237 node->next = NULL;
238 error = amiga_insert_irq(&ami_irq_list[irq], node);
239 } else {
240 ami_irq_list[irq]->handler = handler;
241 ami_irq_list[irq]->flags = flags;
242 ami_irq_list[irq]->dev_id = dev_id;
243 ami_irq_list[irq]->devname = devname;
244 }
245
246 /* enable the interrupt */
247 if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
248 custom.intena = IF_SETCLR | amiga_intena_vals[irq];
249
250 return error;
251}
252
253void amiga_free_irq(unsigned int irq, void *dev_id)
254{
255 if (irq >= AMI_IRQS) {
256 printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
257 return;
258 }
259
260 if (irq >= IRQ_AMIGA_AUTO)
261 cpu_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
262
263 if (irq >= IRQ_AMIGA_CIAB) {
264 cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id);
265 return;
266 }
267
268 if (irq >= IRQ_AMIGA_CIAA) {
269 cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
270 return;
271 }
272
273 if (ami_servers[irq]) {
274 amiga_delete_irq(&ami_irq_list[irq], dev_id);
275 /* if server list empty, disable the interrupt */
276 if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
277 custom.intena = amiga_intena_vals[irq];
278 } else {
279 if (ami_irq_list[irq]->dev_id != dev_id)
280 printk("%s: removing probably wrong IRQ %d from %s\n",
281 __FUNCTION__, irq, ami_irq_list[irq]->devname);
282 ami_irq_list[irq]->handler = ami_badint;
283 ami_irq_list[irq]->flags = 0;
284 ami_irq_list[irq]->dev_id = NULL;
285 ami_irq_list[irq]->devname = NULL;
286 custom.intena = amiga_intena_vals[irq];
287 }
288}
289
290/*
291 * Enable/disable a particular machine specific interrupt source.
292 * Note that this may affect other interrupts in case of a shared interrupt.
293 * This function should only be called for a _very_ short time to change some
294 * internal data, that may not be changed by the interrupt at the same time.
295 * ami_(enable|disable)_irq calls may also be nested.
296 */
297
298void amiga_enable_irq(unsigned int irq)
299{
300 if (irq >= AMI_IRQS) {
301 printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
302 return;
303 }
304
305 if (--ami_ablecount[irq])
306 return;
307
308 /* No action for auto-vector interrupts */
309 if (irq >= IRQ_AMIGA_AUTO){
310 printk("%s: Trying to enable auto-vector IRQ %i\n",
311 __FUNCTION__, irq - IRQ_AMIGA_AUTO);
312 return;
313 }
314
315 if (irq >= IRQ_AMIGA_CIAB) {
316 cia_set_irq(&ciab_base, (1 << (irq - IRQ_AMIGA_CIAB)));
317 cia_able_irq(&ciab_base, CIA_ICR_SETCLR |
318 (1 << (irq - IRQ_AMIGA_CIAB)));
319 return;
320 }
321
322 if (irq >= IRQ_AMIGA_CIAA) {
323 cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA)));
324 cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
325 (1 << (irq - IRQ_AMIGA_CIAA)));
326 return;
327 }
328
329 /* enable the interrupt */
330 custom.intena = IF_SETCLR | amiga_intena_vals[irq];
331}
332
333void amiga_disable_irq(unsigned int irq)
334{
335 if (irq >= AMI_IRQS) {
336 printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
337 return;
338 }
339
340 if (ami_ablecount[irq]++)
341 return;
342
343 /* No action for auto-vector interrupts */
344 if (irq >= IRQ_AMIGA_AUTO) {
345 printk("%s: Trying to disable auto-vector IRQ %i\n",
346 __FUNCTION__, irq - IRQ_AMIGA_AUTO);
347 return;
348 }
349
350 if (irq >= IRQ_AMIGA_CIAB) {
351 cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
352 return;
353 }
354
355 if (irq >= IRQ_AMIGA_CIAA) {
356 cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
357 return;
358 }
359
360 /* disable the interrupt */
361 custom.intena = amiga_intena_vals[irq];
362}
363
364inline void amiga_do_irq(int irq, struct pt_regs *fp)
365{
366 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
367 ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
368}
369
370void amiga_do_irq_list(int irq, struct pt_regs *fp)
371{
372 irq_node_t *node;
373
374 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
375
376 custom.intreq = amiga_intena_vals[irq];
377
378 for (node = ami_irq_list[irq]; node; node = node->next)
379 node->handler(irq, node->dev_id, fp);
380}
381
382/*
383 * The builtin Amiga hardware interrupt handlers.
384 */
385
386static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp)
387{
388 unsigned short ints = custom.intreqr & custom.intenar;
389
390 /* if serial transmit buffer empty, interrupt */
391 if (ints & IF_TBE) {
392 custom.intreq = IF_TBE;
393 amiga_do_irq(IRQ_AMIGA_TBE, fp);
394 }
395
396 /* if floppy disk transfer complete, interrupt */
397 if (ints & IF_DSKBLK) {
398 custom.intreq = IF_DSKBLK;
399 amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
400 }
401
402 /* if software interrupt set, interrupt */
403 if (ints & IF_SOFT) {
404 custom.intreq = IF_SOFT;
405 amiga_do_irq(IRQ_AMIGA_SOFT, fp);
406 }
407 return IRQ_HANDLED;
408}
409
410static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp)
411{
412 unsigned short ints = custom.intreqr & custom.intenar;
413
414 /* if a blitter interrupt */
415 if (ints & IF_BLIT) {
416 custom.intreq = IF_BLIT;
417 amiga_do_irq(IRQ_AMIGA_BLIT, fp);
418 }
419
420 /* if a copper interrupt */
421 if (ints & IF_COPER) {
422 custom.intreq = IF_COPER;
423 amiga_do_irq(IRQ_AMIGA_COPPER, fp);
424 }
425
426 /* if a vertical blank interrupt */
427 if (ints & IF_VERTB)
428 amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
429 return IRQ_HANDLED;
430}
431
432static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp)
433{
434 unsigned short ints = custom.intreqr & custom.intenar;
435
436 /* if audio 0 interrupt */
437 if (ints & IF_AUD0) {
438 custom.intreq = IF_AUD0;
439 amiga_do_irq(IRQ_AMIGA_AUD0, fp);
440 }
441
442 /* if audio 1 interrupt */
443 if (ints & IF_AUD1) {
444 custom.intreq = IF_AUD1;
445 amiga_do_irq(IRQ_AMIGA_AUD1, fp);
446 }
447
448 /* if audio 2 interrupt */
449 if (ints & IF_AUD2) {
450 custom.intreq = IF_AUD2;
451 amiga_do_irq(IRQ_AMIGA_AUD2, fp);
452 }
453
454 /* if audio 3 interrupt */
455 if (ints & IF_AUD3) {
456 custom.intreq = IF_AUD3;
457 amiga_do_irq(IRQ_AMIGA_AUD3, fp);
458 }
459 return IRQ_HANDLED;
460}
461
462static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp)
463{
464 unsigned short ints = custom.intreqr & custom.intenar;
465
466 /* if serial receive buffer full interrupt */
467 if (ints & IF_RBF) {
468 /* acknowledge of IF_RBF must be done by the serial interrupt */
469 amiga_do_irq(IRQ_AMIGA_RBF, fp);
470 }
471
472 /* if a disk sync interrupt */
473 if (ints & IF_DSKSYN) {
474 custom.intreq = IF_DSKSYN;
475 amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
476 }
477 return IRQ_HANDLED;
478}
479
480static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp)
481{
482 panic ("level 7 interrupt received\n");
483}
484
485irqreturn_t (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
486 [0] = ami_badint,
487 [1] = ami_int1,
488 [2] = ami_badint,
489 [3] = ami_int3,
490 [4] = ami_int4,
491 [5] = ami_int5,
492 [6] = ami_badint,
493 [7] = ami_int7
494};
495
496int show_amiga_interrupts(struct seq_file *p, void *v)
497{
498 int i;
499 irq_node_t *node;
500
501 for (i = 0; i < AMI_STD_IRQS; i++) {
502 if (!(node = ami_irq_list[i]))
503 continue;
504 seq_printf(p, "ami %2d: %10u ", i,
505 kstat_cpu(0).irqs[SYS_IRQS + i]);
506 do {
507 if (node->flags & SA_INTERRUPT)
508 seq_puts(p, "F ");
509 else
510 seq_puts(p, " ");
511 seq_printf(p, "%s\n", node->devname);
512 if ((node = node->next))
513 seq_puts(p, " ");
514 } while (node);
515 }
516
517 cia_get_irq_list(&ciaa_base, p);
518 cia_get_irq_list(&ciab_base, p);
519 return 0;
520}
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
new file mode 100644
index 000000000000..cb5d93630467
--- /dev/null
+++ b/arch/m68k/amiga/amisound.c
@@ -0,0 +1,113 @@
1/*
2 * linux/arch/m68k/amiga/amisound.c
3 *
4 * amiga sound driver for Linux/m68k
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/config.h>
12#include <linux/jiffies.h>
13#include <linux/timer.h>
14#include <linux/init.h>
15#include <linux/string.h>
16
17#include <asm/system.h>
18#include <asm/amigahw.h>
19
20static unsigned short *snd_data;
21static const signed char sine_data[] = {
22 0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
23 0, -39, -75, -103, -121, -127, -121, -103, -75, -39
24};
25#define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0]))
26
27 /*
28 * The minimum period for audio may be modified by the frame buffer
29 * device since it depends on htotal (for OCS/ECS/AGA)
30 */
31
32volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
33
34#define MAX_PERIOD (65535)
35
36
37 /*
38 * Current period (set by dmasound.c)
39 */
40
41unsigned short amiga_audio_period = MAX_PERIOD;
42
43static unsigned long clock_constant;
44
45void __init amiga_init_sound(void)
46{
47 static struct resource beep_res = { .name = "Beep" };
48
49 snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res);
50 if (!snd_data) {
51 printk (KERN_CRIT "amiga init_sound: failed to allocate chipmem\n");
52 return;
53 }
54 memcpy (snd_data, sine_data, sizeof(sine_data));
55
56 /* setup divisor */
57 clock_constant = (amiga_colorclock+DATA_SIZE/2)/DATA_SIZE;
58
59 /* without amifb, turn video off and enable high quality sound */
60#ifndef CONFIG_FB_AMIGA
61 amifb_video_off();
62#endif
63}
64
65static void nosound( unsigned long ignored );
66static struct timer_list sound_timer = TIMER_INITIALIZER(nosound, 0, 0);
67
68void amiga_mksound( unsigned int hz, unsigned int ticks )
69{
70 unsigned long flags;
71
72 if (!snd_data)
73 return;
74
75 local_irq_save(flags);
76 del_timer( &sound_timer );
77
78 if (hz > 20 && hz < 32767) {
79 unsigned long period = (clock_constant / hz);
80
81 if (period < amiga_audio_min_period)
82 period = amiga_audio_min_period;
83 if (period > MAX_PERIOD)
84 period = MAX_PERIOD;
85
86 /* setup pointer to data, period, length and volume */
87 custom.aud[2].audlc = snd_data;
88 custom.aud[2].audlen = sizeof(sine_data)/2;
89 custom.aud[2].audper = (unsigned short)period;
90 custom.aud[2].audvol = 32; /* 50% of maxvol */
91
92 if (ticks) {
93 sound_timer.expires = jiffies + ticks;
94 add_timer( &sound_timer );
95 }
96
97 /* turn on DMA for audio channel 2 */
98 custom.dmacon = DMAF_SETCLR | DMAF_AUD2;
99
100 } else
101 nosound( 0 );
102
103 local_irq_restore(flags);
104}
105
106
107static void nosound( unsigned long ignored )
108{
109 /* turn off DMA for audio channel 2 */
110 custom.dmacon = DMAF_AUD2;
111 /* restore period to previous value after beeping */
112 custom.aud[2].audper = amiga_audio_period;
113}
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
new file mode 100644
index 000000000000..558d5fd2d2ba
--- /dev/null
+++ b/arch/m68k/amiga/chipram.c
@@ -0,0 +1,133 @@
1/*
2** linux/amiga/chipram.c
3**
4** Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org>
5** - 64-bit aligned allocations for full AGA compatibility
6**
7** Rewritten 15/9/2000 by Geert to use resource management
8*/
9
10#include <linux/config.h>
11#include <linux/types.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/ioport.h>
15#include <linux/slab.h>
16#include <linux/string.h>
17#include <asm/page.h>
18#include <asm/amigahw.h>
19
20unsigned long amiga_chip_size;
21
22static struct resource chipram_res = {
23 .name = "Chip RAM", .start = CHIP_PHYSADDR
24};
25static unsigned long chipavail;
26
27
28void __init amiga_chip_init(void)
29{
30 if (!AMIGAHW_PRESENT(CHIP_RAM))
31 return;
32
33#ifndef CONFIG_APUS_FAST_EXCEPT
34 /*
35 * Remove the first 4 pages where PPC exception handlers will be located
36 */
37 amiga_chip_size -= 0x4000;
38#endif
39 chipram_res.end = amiga_chip_size-1;
40 request_resource(&iomem_resource, &chipram_res);
41
42 chipavail = amiga_chip_size;
43}
44
45
46void *amiga_chip_alloc(unsigned long size, const char *name)
47{
48 struct resource *res;
49
50 /* round up */
51 size = PAGE_ALIGN(size);
52
53#ifdef DEBUG
54 printk("amiga_chip_alloc: allocate %ld bytes\n", size);
55#endif
56 res = kmalloc(sizeof(struct resource), GFP_KERNEL);
57 if (!res)
58 return NULL;
59 memset(res, 0, sizeof(struct resource));
60 res->name = name;
61
62 if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
63 kfree(res);
64 return NULL;
65 }
66 chipavail -= size;
67#ifdef DEBUG
68 printk("amiga_chip_alloc: returning %lx\n", res->start);
69#endif
70 return (void *)ZTWO_VADDR(res->start);
71}
72
73
74 /*
75 * Warning:
76 * amiga_chip_alloc_res is meant only for drivers that need to allocate
77 * Chip RAM before kmalloc() is functional. As a consequence, those
78 * drivers must not free that Chip RAM afterwards.
79 */
80
81void * __init amiga_chip_alloc_res(unsigned long size, struct resource *res)
82{
83 unsigned long start;
84
85 /* round up */
86 size = PAGE_ALIGN(size);
87 /* dmesg into chipmem prefers memory at the safe end */
88 start = CHIP_PHYSADDR + chipavail - size;
89
90#ifdef DEBUG
91 printk("amiga_chip_alloc_res: allocate %ld bytes\n", size);
92#endif
93 if (allocate_resource(&chipram_res, res, size, start, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
94 printk("amiga_chip_alloc_res: first alloc failed!\n");
95 if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0)
96 return NULL;
97 }
98 chipavail -= size;
99#ifdef DEBUG
100 printk("amiga_chip_alloc_res: returning %lx\n", res->start);
101#endif
102 return (void *)ZTWO_VADDR(res->start);
103}
104
105void amiga_chip_free(void *ptr)
106{
107 unsigned long start = ZTWO_PADDR(ptr);
108 struct resource **p, *res;
109 unsigned long size;
110
111 for (p = &chipram_res.child; (res = *p); p = &res->sibling) {
112 if (res->start != start)
113 continue;
114 *p = res->sibling;
115 size = res->end-start;
116#ifdef DEBUG
117 printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr);
118#endif
119 chipavail += size;
120 kfree(res);
121 return;
122 }
123 printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
124}
125
126
127unsigned long amiga_chip_avail(void)
128{
129#ifdef DEBUG
130 printk("amiga_chip_avail : %ld bytes\n", chipavail);
131#endif
132 return chipavail;
133}
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
new file mode 100644
index 000000000000..7d55682615e3
--- /dev/null
+++ b/arch/m68k/amiga/cia.c
@@ -0,0 +1,180 @@
1/*
2 * linux/arch/m68k/amiga/cia.c - CIA support
3 *
4 * Copyright (C) 1996 Roman Zippel
5 *
6 * The concept of some functions bases on the original Amiga OS function
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/errno.h>
17#include <linux/kernel_stat.h>
18#include <linux/init.h>
19#include <linux/seq_file.h>
20#include <linux/interrupt.h>
21
22#include <asm/irq.h>
23#include <asm/amigahw.h>
24#include <asm/amigaints.h>
25
26struct ciabase {
27 volatile struct CIA *cia;
28 unsigned char icr_mask, icr_data;
29 unsigned short int_mask;
30 int handler_irq, cia_irq, server_irq;
31 char *name;
32 irq_handler_t irq_list[CIA_IRQS];
33} ciaa_base = {
34 .cia = &ciaa,
35 .int_mask = IF_PORTS,
36 .handler_irq = IRQ_AMIGA_AUTO_2,
37 .cia_irq = IRQ_AMIGA_CIAA,
38 .server_irq = IRQ_AMIGA_PORTS,
39 .name = "CIAA handler"
40}, ciab_base = {
41 .cia = &ciab,
42 .int_mask = IF_EXTER,
43 .handler_irq = IRQ_AMIGA_AUTO_6,
44 .cia_irq = IRQ_AMIGA_CIAB,
45 .server_irq = IRQ_AMIGA_EXTER,
46 .name = "CIAB handler"
47};
48
49/*
50 * Cause or clear CIA interrupts, return old interrupt status.
51 */
52
53unsigned char cia_set_irq(struct ciabase *base, unsigned char mask)
54{
55 unsigned char old;
56
57 old = (base->icr_data |= base->cia->icr);
58 if (mask & CIA_ICR_SETCLR)
59 base->icr_data |= mask;
60 else
61 base->icr_data &= ~mask;
62 if (base->icr_data & base->icr_mask)
63 custom.intreq = IF_SETCLR | base->int_mask;
64 return old & base->icr_mask;
65}
66
67/*
68 * Enable or disable CIA interrupts, return old interrupt mask,
69 * interrupts will only be enabled if a handler exists
70 */
71
72unsigned char cia_able_irq(struct ciabase *base, unsigned char mask)
73{
74 unsigned char old, tmp;
75 int i;
76
77 old = base->icr_mask;
78 base->icr_data |= base->cia->icr;
79 base->cia->icr = mask;
80 if (mask & CIA_ICR_SETCLR)
81 base->icr_mask |= mask;
82 else
83 base->icr_mask &= ~mask;
84 base->icr_mask &= CIA_ICR_ALL;
85 for (i = 0, tmp = 1; i < CIA_IRQS; i++, tmp <<= 1) {
86 if ((tmp & base->icr_mask) && !base->irq_list[i].handler) {
87 base->icr_mask &= ~tmp;
88 base->cia->icr = tmp;
89 }
90 }
91 if (base->icr_data & base->icr_mask)
92 custom.intreq = IF_SETCLR | base->int_mask;
93 return old;
94}
95
96int cia_request_irq(struct ciabase *base, unsigned int irq,
97 irqreturn_t (*handler)(int, void *, struct pt_regs *),
98 unsigned long flags, const char *devname, void *dev_id)
99{
100 unsigned char mask;
101
102 base->irq_list[irq].handler = handler;
103 base->irq_list[irq].flags = flags;
104 base->irq_list[irq].dev_id = dev_id;
105 base->irq_list[irq].devname = devname;
106
107 /* enable the interrupt */
108 mask = 1 << irq;
109 cia_set_irq(base, mask);
110 cia_able_irq(base, CIA_ICR_SETCLR | mask);
111 return 0;
112}
113
114void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id)
115{
116 if (base->irq_list[irq].dev_id != dev_id)
117 printk("%s: removing probably wrong IRQ %i from %s\n",
118 __FUNCTION__, base->cia_irq + irq,
119 base->irq_list[irq].devname);
120
121 base->irq_list[irq].handler = NULL;
122 base->irq_list[irq].flags = 0;
123
124 cia_able_irq(base, 1 << irq);
125}
126
127static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp)
128{
129 struct ciabase *base = (struct ciabase *)dev_id;
130 int mach_irq, i;
131 unsigned char ints;
132
133 mach_irq = base->cia_irq;
134 irq = SYS_IRQS + mach_irq;
135 ints = cia_set_irq(base, CIA_ICR_ALL);
136 custom.intreq = base->int_mask;
137 for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) {
138 if (ints & 1) {
139 kstat_cpu(0).irqs[irq]++;
140 base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp);
141 }
142 ints >>= 1;
143 }
144 amiga_do_irq_list(base->server_irq, fp);
145 return IRQ_HANDLED;
146}
147
148void __init cia_init_IRQ(struct ciabase *base)
149{
150 int i;
151
152 /* init isr handlers */
153 for (i = 0; i < CIA_IRQS; i++) {
154 base->irq_list[i].handler = NULL;
155 base->irq_list[i].flags = 0;
156 }
157
158 /* clear any pending interrupt and turn off all interrupts */
159 cia_set_irq(base, CIA_ICR_ALL);
160 cia_able_irq(base, CIA_ICR_ALL);
161
162 /* install CIA handler */
163 request_irq(base->handler_irq, cia_handler, 0, base->name, base);
164
165 custom.intena = IF_SETCLR | base->int_mask;
166}
167
168int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
169{
170 int i, j;
171
172 j = base->cia_irq;
173 for (i = 0; i < CIA_IRQS; i++) {
174 seq_printf(p, "cia %2d: %10d ", j + i,
175 kstat_cpu(0).irqs[SYS_IRQS + j + i]);
176 seq_puts(p, " ");
177 seq_printf(p, "%s\n", base->irq_list[i].devname);
178 }
179 return 0;
180}
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
new file mode 100644
index 000000000000..4775e18a78f0
--- /dev/null
+++ b/arch/m68k/amiga/config.c
@@ -0,0 +1,1007 @@
1/*
2 * linux/arch/m68k/amiga/config.c
3 *
4 * Copyright (C) 1993 Hamish Macdonald
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11/*
12 * Miscellaneous Amiga stuff
13 */
14
15#include <linux/config.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/mm.h>
19#include <linux/tty.h>
20#include <linux/console.h>
21#include <linux/rtc.h>
22#include <linux/init.h>
23#include <linux/vt_kern.h>
24#include <linux/delay.h>
25#include <linux/interrupt.h>
26#ifdef CONFIG_ZORRO
27#include <linux/zorro.h>
28#endif
29
30#include <asm/bootinfo.h>
31#include <asm/setup.h>
32#include <asm/system.h>
33#include <asm/pgtable.h>
34#include <asm/amigahw.h>
35#include <asm/amigaints.h>
36#include <asm/irq.h>
37#include <asm/rtc.h>
38#include <asm/machdep.h>
39#include <asm/io.h>
40
41unsigned long amiga_model;
42unsigned long amiga_eclock;
43unsigned long amiga_masterclock;
44unsigned long amiga_colorclock;
45unsigned long amiga_chipset;
46unsigned char amiga_vblank;
47unsigned char amiga_psfreq;
48struct amiga_hw_present amiga_hw_present;
49
50static char s_a500[] __initdata = "A500";
51static char s_a500p[] __initdata = "A500+";
52static char s_a600[] __initdata = "A600";
53static char s_a1000[] __initdata = "A1000";
54static char s_a1200[] __initdata = "A1200";
55static char s_a2000[] __initdata = "A2000";
56static char s_a2500[] __initdata = "A2500";
57static char s_a3000[] __initdata = "A3000";
58static char s_a3000t[] __initdata = "A3000T";
59static char s_a3000p[] __initdata = "A3000+";
60static char s_a4000[] __initdata = "A4000";
61static char s_a4000t[] __initdata = "A4000T";
62static char s_cdtv[] __initdata = "CDTV";
63static char s_cd32[] __initdata = "CD32";
64static char s_draco[] __initdata = "Draco";
65static char *amiga_models[] __initdata = {
66 [AMI_500-AMI_500] = s_a500,
67 [AMI_500PLUS-AMI_500] = s_a500p,
68 [AMI_600-AMI_500] = s_a600,
69 [AMI_1000-AMI_500] = s_a1000,
70 [AMI_1200-AMI_500] = s_a1200,
71 [AMI_2000-AMI_500] = s_a2000,
72 [AMI_2500-AMI_500] = s_a2500,
73 [AMI_3000-AMI_500] = s_a3000,
74 [AMI_3000T-AMI_500] = s_a3000t,
75 [AMI_3000PLUS-AMI_500] = s_a3000p,
76 [AMI_4000-AMI_500] = s_a4000,
77 [AMI_4000T-AMI_500] = s_a4000t,
78 [AMI_CDTV-AMI_500] = s_cdtv,
79 [AMI_CD32-AMI_500] = s_cd32,
80 [AMI_DRACO-AMI_500] = s_draco,
81};
82
83static char amiga_model_name[13] = "Amiga ";
84
85extern char m68k_debug_device[];
86
87static void amiga_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
88/* amiga specific irq functions */
89extern void amiga_init_IRQ (void);
90extern irqreturn_t (*amiga_default_handler[]) (int, void *, struct pt_regs *);
91extern int amiga_request_irq (unsigned int irq,
92 irqreturn_t (*handler)(int, void *, struct pt_regs *),
93 unsigned long flags, const char *devname,
94 void *dev_id);
95extern void amiga_free_irq (unsigned int irq, void *dev_id);
96extern void amiga_enable_irq (unsigned int);
97extern void amiga_disable_irq (unsigned int);
98static void amiga_get_model(char *model);
99static int amiga_get_hardware_list(char *buffer);
100extern int show_amiga_interrupts (struct seq_file *, void *);
101/* amiga specific timer functions */
102static unsigned long amiga_gettimeoffset (void);
103static int a3000_hwclk (int, struct rtc_time *);
104static int a2000_hwclk (int, struct rtc_time *);
105static int amiga_set_clock_mmss (unsigned long);
106static unsigned int amiga_get_ss (void);
107extern void amiga_mksound( unsigned int count, unsigned int ticks );
108#ifdef CONFIG_AMIGA_FLOPPY
109extern void amiga_floppy_setup(char *, int *);
110#endif
111static void amiga_reset (void);
112extern void amiga_init_sound(void);
113static void amiga_savekmsg_init(void);
114static void amiga_mem_console_write(struct console *co, const char *b,
115 unsigned int count);
116void amiga_serial_console_write(struct console *co, const char *s,
117 unsigned int count);
118static void amiga_debug_init(void);
119#ifdef CONFIG_HEARTBEAT
120static void amiga_heartbeat(int on);
121#endif
122
123static struct console amiga_console_driver = {
124 .name = "debug",
125 .flags = CON_PRINTBUFFER,
126 .index = -1,
127};
128
129
130 /*
131 * Motherboard Resources present in all Amiga models
132 */
133
134static struct {
135 struct resource _ciab, _ciaa, _custom, _kickstart;
136} mb_resources = {
137 ._ciab = {
138 .name = "CIA B", .start = 0x00bfd000, .end = 0x00bfdfff
139 },
140 ._ciaa = {
141 .name = "CIA A", .start = 0x00bfe000, .end = 0x00bfefff
142 },
143 ._custom = {
144 .name = "Custom I/O", .start = 0x00dff000, .end = 0x00dfffff
145 },
146 ._kickstart = {
147 .name = "Kickstart ROM", .start = 0x00f80000, .end = 0x00ffffff
148 }
149};
150
151static struct resource rtc_resource = {
152 .start = 0x00dc0000, .end = 0x00dcffff
153};
154
155static struct resource ram_resource[NUM_MEMINFO];
156
157
158 /*
159 * Parse an Amiga-specific record in the bootinfo
160 */
161
162int amiga_parse_bootinfo(const struct bi_record *record)
163{
164 int unknown = 0;
165 const unsigned long *data = record->data;
166
167 switch (record->tag) {
168 case BI_AMIGA_MODEL:
169 amiga_model = *data;
170 break;
171
172 case BI_AMIGA_ECLOCK:
173 amiga_eclock = *data;
174 break;
175
176 case BI_AMIGA_CHIPSET:
177 amiga_chipset = *data;
178 break;
179
180 case BI_AMIGA_CHIP_SIZE:
181 amiga_chip_size = *(const int *)data;
182 break;
183
184 case BI_AMIGA_VBLANK:
185 amiga_vblank = *(const unsigned char *)data;
186 break;
187
188 case BI_AMIGA_PSFREQ:
189 amiga_psfreq = *(const unsigned char *)data;
190 break;
191
192 case BI_AMIGA_AUTOCON:
193#ifdef CONFIG_ZORRO
194 if (zorro_num_autocon < ZORRO_NUM_AUTO) {
195 const struct ConfigDev *cd = (struct ConfigDev *)data;
196 struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
197 dev->rom = cd->cd_Rom;
198 dev->slotaddr = cd->cd_SlotAddr;
199 dev->slotsize = cd->cd_SlotSize;
200 dev->resource.start = (unsigned long)cd->cd_BoardAddr;
201 dev->resource.end = dev->resource.start+cd->cd_BoardSize-1;
202 } else
203 printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
204#endif /* CONFIG_ZORRO */
205 break;
206
207 case BI_AMIGA_SERPER:
208 /* serial port period: ignored here */
209 break;
210
211 default:
212 unknown = 1;
213 }
214 return(unknown);
215}
216
217 /*
218 * Identify builtin hardware
219 */
220
221static void __init amiga_identify(void)
222{
223 /* Fill in some default values, if necessary */
224 if (amiga_eclock == 0)
225 amiga_eclock = 709379;
226
227 memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
228
229 printk("Amiga hardware found: ");
230 if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
231 printk("[%s] ", amiga_models[amiga_model-AMI_500]);
232 strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
233 }
234
235 switch(amiga_model) {
236 case AMI_UNKNOWN:
237 goto Generic;
238
239 case AMI_600:
240 case AMI_1200:
241 AMIGAHW_SET(A1200_IDE);
242 AMIGAHW_SET(PCMCIA);
243 case AMI_500:
244 case AMI_500PLUS:
245 case AMI_1000:
246 case AMI_2000:
247 case AMI_2500:
248 AMIGAHW_SET(A2000_CLK); /* Is this correct for all models? */
249 goto Generic;
250
251 case AMI_3000:
252 case AMI_3000T:
253 AMIGAHW_SET(AMBER_FF);
254 AMIGAHW_SET(MAGIC_REKICK);
255 /* fall through */
256 case AMI_3000PLUS:
257 AMIGAHW_SET(A3000_SCSI);
258 AMIGAHW_SET(A3000_CLK);
259 AMIGAHW_SET(ZORRO3);
260 goto Generic;
261
262 case AMI_4000T:
263 AMIGAHW_SET(A4000_SCSI);
264 /* fall through */
265 case AMI_4000:
266 AMIGAHW_SET(A4000_IDE);
267 AMIGAHW_SET(A3000_CLK);
268 AMIGAHW_SET(ZORRO3);
269 goto Generic;
270
271 case AMI_CDTV:
272 case AMI_CD32:
273 AMIGAHW_SET(CD_ROM);
274 AMIGAHW_SET(A2000_CLK); /* Is this correct? */
275 goto Generic;
276
277 Generic:
278 AMIGAHW_SET(AMI_VIDEO);
279 AMIGAHW_SET(AMI_BLITTER);
280 AMIGAHW_SET(AMI_AUDIO);
281 AMIGAHW_SET(AMI_FLOPPY);
282 AMIGAHW_SET(AMI_KEYBOARD);
283 AMIGAHW_SET(AMI_MOUSE);
284 AMIGAHW_SET(AMI_SERIAL);
285 AMIGAHW_SET(AMI_PARALLEL);
286 AMIGAHW_SET(CHIP_RAM);
287 AMIGAHW_SET(PAULA);
288
289 switch(amiga_chipset) {
290 case CS_OCS:
291 case CS_ECS:
292 case CS_AGA:
293 switch (custom.deniseid & 0xf) {
294 case 0x0c:
295 AMIGAHW_SET(DENISE_HR);
296 break;
297 case 0x08:
298 AMIGAHW_SET(LISA);
299 break;
300 }
301 break;
302 default:
303 AMIGAHW_SET(DENISE);
304 break;
305 }
306 switch ((custom.vposr>>8) & 0x7f) {
307 case 0x00:
308 AMIGAHW_SET(AGNUS_PAL);
309 break;
310 case 0x10:
311 AMIGAHW_SET(AGNUS_NTSC);
312 break;
313 case 0x20:
314 case 0x21:
315 AMIGAHW_SET(AGNUS_HR_PAL);
316 break;
317 case 0x30:
318 case 0x31:
319 AMIGAHW_SET(AGNUS_HR_NTSC);
320 break;
321 case 0x22:
322 case 0x23:
323 AMIGAHW_SET(ALICE_PAL);
324 break;
325 case 0x32:
326 case 0x33:
327 AMIGAHW_SET(ALICE_NTSC);
328 break;
329 }
330 AMIGAHW_SET(ZORRO);
331 break;
332
333 case AMI_DRACO:
334 panic("No support for Draco yet");
335
336 default:
337 panic("Unknown Amiga Model");
338 }
339
340#define AMIGAHW_ANNOUNCE(name, str) \
341 if (AMIGAHW_PRESENT(name)) \
342 printk(str)
343
344 AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
345 AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
346 AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
347 AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
348 AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
349 AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
350 AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
351 AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
352 AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
353 AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
354 AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
355 AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
356 AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
357 AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
358 AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
359 AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
360 AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
361 AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
362 AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
363 AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
364 AMIGAHW_ANNOUNCE(LISA, "LISA ");
365 AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
366 AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
367 AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
368 AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
369 AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
370 AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
371 AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
372 AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
373 if (AMIGAHW_PRESENT(ZORRO))
374 printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
375 printk("\n");
376
377#undef AMIGAHW_ANNOUNCE
378}
379
380 /*
381 * Setup the Amiga configuration info
382 */
383
384void __init config_amiga(void)
385{
386 int i;
387
388 amiga_debug_init();
389 amiga_identify();
390
391 /* Yuk, we don't have PCI memory */
392 iomem_resource.name = "Memory";
393 for (i = 0; i < 4; i++)
394 request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
395
396 mach_sched_init = amiga_sched_init;
397 mach_init_IRQ = amiga_init_IRQ;
398 mach_default_handler = &amiga_default_handler;
399 mach_request_irq = amiga_request_irq;
400 mach_free_irq = amiga_free_irq;
401 enable_irq = amiga_enable_irq;
402 disable_irq = amiga_disable_irq;
403 mach_get_model = amiga_get_model;
404 mach_get_hardware_list = amiga_get_hardware_list;
405 mach_get_irq_list = show_amiga_interrupts;
406 mach_gettimeoffset = amiga_gettimeoffset;
407 if (AMIGAHW_PRESENT(A3000_CLK)){
408 mach_hwclk = a3000_hwclk;
409 rtc_resource.name = "A3000 RTC";
410 request_resource(&iomem_resource, &rtc_resource);
411 }
412 else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
413 mach_hwclk = a2000_hwclk;
414 rtc_resource.name = "A2000 RTC";
415 request_resource(&iomem_resource, &rtc_resource);
416 }
417
418 mach_max_dma_address = 0xffffffff; /*
419 * default MAX_DMA=0xffffffff
420 * on all machines. If we don't
421 * do so, the SCSI code will not
422 * be able to allocate any mem
423 * for transfers, unless we are
424 * dealing with a Z2 mem only
425 * system. /Jes
426 */
427
428 mach_set_clock_mmss = amiga_set_clock_mmss;
429 mach_get_ss = amiga_get_ss;
430#ifdef CONFIG_AMIGA_FLOPPY
431 mach_floppy_setup = amiga_floppy_setup;
432#endif
433 mach_reset = amiga_reset;
434#ifdef CONFIG_DUMMY_CONSOLE
435 conswitchp = &dummy_con;
436#endif
437#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
438 mach_beep = amiga_mksound;
439#endif
440
441#ifdef CONFIG_HEARTBEAT
442 mach_heartbeat = amiga_heartbeat;
443#endif
444
445 /* Fill in the clock values (based on the 700 kHz E-Clock) */
446 amiga_masterclock = 40*amiga_eclock; /* 28 MHz */
447 amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */
448
449 /* clear all DMA bits */
450 custom.dmacon = DMAF_ALL;
451 /* ensure that the DMA master bit is set */
452 custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
453
454 /* don't use Z2 RAM as system memory on Z3 capable machines */
455 if (AMIGAHW_PRESENT(ZORRO3)) {
456 int i, j;
457 u32 disabled_z2mem = 0;
458 for (i = 0; i < m68k_num_memory; i++)
459 if (m68k_memory[i].addr < 16*1024*1024) {
460 if (i == 0) {
461 /* don't cut off the branch we're sitting on */
462 printk("Warning: kernel runs in Zorro II memory\n");
463 continue;
464 }
465 disabled_z2mem += m68k_memory[i].size;
466 m68k_num_memory--;
467 for (j = i; j < m68k_num_memory; j++)
468 m68k_memory[j] = m68k_memory[j+1];
469 i--;
470 }
471 if (disabled_z2mem)
472 printk("%dK of Zorro II memory will not be used as system memory\n",
473 disabled_z2mem>>10);
474 }
475
476 /* request all RAM */
477 for (i = 0; i < m68k_num_memory; i++) {
478 ram_resource[i].name =
479 (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
480 (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
481 "16-bit Slow RAM";
482 ram_resource[i].start = m68k_memory[i].addr;
483 ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
484 request_resource(&iomem_resource, &ram_resource[i]);
485 }
486
487 /* initialize chipram allocator */
488 amiga_chip_init ();
489
490 /* debugging using chipram */
491 if (!strcmp( m68k_debug_device, "mem" )){
492 if (!AMIGAHW_PRESENT(CHIP_RAM))
493 printk("Warning: no chipram present for debugging\n");
494 else {
495 amiga_savekmsg_init();
496 amiga_console_driver.write = amiga_mem_console_write;
497 register_console(&amiga_console_driver);
498 }
499 }
500
501 /* our beloved beeper */
502 if (AMIGAHW_PRESENT(AMI_AUDIO))
503 amiga_init_sound();
504
505 /*
506 * if it is an A3000, set the magic bit that forces
507 * a hard rekick
508 */
509 if (AMIGAHW_PRESENT(MAGIC_REKICK))
510 *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
511}
512
513static unsigned short jiffy_ticks;
514
515static void __init amiga_sched_init(irqreturn_t (*timer_routine)(int, void *,
516 struct pt_regs *))
517{
518 static struct resource sched_res = {
519 .name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
520 };
521 jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
522
523 if (request_resource(&mb_resources._ciab, &sched_res))
524 printk("Cannot allocate ciab.ta{lo,hi}\n");
525 ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */
526 ciab.talo = jiffy_ticks % 256;
527 ciab.tahi = jiffy_ticks / 256;
528
529 /* install interrupt service routine for CIAB Timer A
530 *
531 * Please don't change this to use ciaa, as it interferes with the
532 * SCSI code. We'll have to take a look at this later
533 */
534 request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL);
535 /* start timer */
536 ciab.cra |= 0x11;
537}
538
539#define TICK_SIZE 10000
540
541/* This is always executed with interrupts disabled. */
542static unsigned long amiga_gettimeoffset (void)
543{
544 unsigned short hi, lo, hi2;
545 unsigned long ticks, offset = 0;
546
547 /* read CIA B timer A current value */
548 hi = ciab.tahi;
549 lo = ciab.talo;
550 hi2 = ciab.tahi;
551
552 if (hi != hi2) {
553 lo = ciab.talo;
554 hi = hi2;
555 }
556
557 ticks = hi << 8 | lo;
558
559 if (ticks > jiffy_ticks / 2)
560 /* check for pending interrupt */
561 if (cia_set_irq(&ciab_base, 0) & CIA_ICR_TA)
562 offset = 10000;
563
564 ticks = jiffy_ticks - ticks;
565 ticks = (10000 * ticks) / jiffy_ticks;
566
567 return ticks + offset;
568}
569
570static int a3000_hwclk(int op, struct rtc_time *t)
571{
572 tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD;
573
574 if (!op) { /* read */
575 t->tm_sec = tod_3000.second1 * 10 + tod_3000.second2;
576 t->tm_min = tod_3000.minute1 * 10 + tod_3000.minute2;
577 t->tm_hour = tod_3000.hour1 * 10 + tod_3000.hour2;
578 t->tm_mday = tod_3000.day1 * 10 + tod_3000.day2;
579 t->tm_wday = tod_3000.weekday;
580 t->tm_mon = tod_3000.month1 * 10 + tod_3000.month2 - 1;
581 t->tm_year = tod_3000.year1 * 10 + tod_3000.year2;
582 if (t->tm_year <= 69)
583 t->tm_year += 100;
584 } else {
585 tod_3000.second1 = t->tm_sec / 10;
586 tod_3000.second2 = t->tm_sec % 10;
587 tod_3000.minute1 = t->tm_min / 10;
588 tod_3000.minute2 = t->tm_min % 10;
589 tod_3000.hour1 = t->tm_hour / 10;
590 tod_3000.hour2 = t->tm_hour % 10;
591 tod_3000.day1 = t->tm_mday / 10;
592 tod_3000.day2 = t->tm_mday % 10;
593 if (t->tm_wday != -1)
594 tod_3000.weekday = t->tm_wday;
595 tod_3000.month1 = (t->tm_mon + 1) / 10;
596 tod_3000.month2 = (t->tm_mon + 1) % 10;
597 if (t->tm_year >= 100)
598 t->tm_year -= 100;
599 tod_3000.year1 = t->tm_year / 10;
600 tod_3000.year2 = t->tm_year % 10;
601 }
602
603 tod_3000.cntrl1 = TOD3000_CNTRL1_FREE;
604
605 return 0;
606}
607
608static int a2000_hwclk(int op, struct rtc_time *t)
609{
610 int cnt = 5;
611
612 tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
613
614 while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
615 {
616 tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
617 udelay(70);
618 tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
619 }
620
621 if (!cnt)
622 printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1);
623
624 if (!op) { /* read */
625 t->tm_sec = tod_2000.second1 * 10 + tod_2000.second2;
626 t->tm_min = tod_2000.minute1 * 10 + tod_2000.minute2;
627 t->tm_hour = (tod_2000.hour1 & 3) * 10 + tod_2000.hour2;
628 t->tm_mday = tod_2000.day1 * 10 + tod_2000.day2;
629 t->tm_wday = tod_2000.weekday;
630 t->tm_mon = tod_2000.month1 * 10 + tod_2000.month2 - 1;
631 t->tm_year = tod_2000.year1 * 10 + tod_2000.year2;
632 if (t->tm_year <= 69)
633 t->tm_year += 100;
634
635 if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)){
636 if (!(tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12)
637 t->tm_hour = 0;
638 else if ((tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour != 12)
639 t->tm_hour += 12;
640 }
641 } else {
642 tod_2000.second1 = t->tm_sec / 10;
643 tod_2000.second2 = t->tm_sec % 10;
644 tod_2000.minute1 = t->tm_min / 10;
645 tod_2000.minute2 = t->tm_min % 10;
646 if (tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)
647 tod_2000.hour1 = t->tm_hour / 10;
648 else if (t->tm_hour >= 12)
649 tod_2000.hour1 = TOD2000_HOUR1_PM +
650 (t->tm_hour - 12) / 10;
651 else
652 tod_2000.hour1 = t->tm_hour / 10;
653 tod_2000.hour2 = t->tm_hour % 10;
654 tod_2000.day1 = t->tm_mday / 10;
655 tod_2000.day2 = t->tm_mday % 10;
656 if (t->tm_wday != -1)
657 tod_2000.weekday = t->tm_wday;
658 tod_2000.month1 = (t->tm_mon + 1) / 10;
659 tod_2000.month2 = (t->tm_mon + 1) % 10;
660 if (t->tm_year >= 100)
661 t->tm_year -= 100;
662 tod_2000.year1 = t->tm_year / 10;
663 tod_2000.year2 = t->tm_year % 10;
664 }
665
666 tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
667
668 return 0;
669}
670
671static int amiga_set_clock_mmss (unsigned long nowtime)
672{
673 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
674
675 if (AMIGAHW_PRESENT(A3000_CLK)) {
676 tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD;
677
678 tod_3000.second1 = real_seconds / 10;
679 tod_3000.second2 = real_seconds % 10;
680 tod_3000.minute1 = real_minutes / 10;
681 tod_3000.minute2 = real_minutes % 10;
682
683 tod_3000.cntrl1 = TOD3000_CNTRL1_FREE;
684 } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
685 int cnt = 5;
686
687 tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
688
689 while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
690 {
691 tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
692 udelay(70);
693 tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
694 }
695
696 if (!cnt)
697 printk(KERN_INFO "set_clock_mmss: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1);
698
699 tod_2000.second1 = real_seconds / 10;
700 tod_2000.second2 = real_seconds % 10;
701 tod_2000.minute1 = real_minutes / 10;
702 tod_2000.minute2 = real_minutes % 10;
703
704 tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
705 }
706
707 return 0;
708}
709
710static unsigned int amiga_get_ss( void )
711{
712 unsigned int s;
713
714 if (AMIGAHW_PRESENT(A3000_CLK)) {
715 tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD;
716 s = tod_3000.second1 * 10 + tod_3000.second2;
717 tod_3000.cntrl1 = TOD3000_CNTRL1_FREE;
718 } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
719 s = tod_2000.second1 * 10 + tod_2000.second2;
720 }
721 return s;
722}
723
724static NORET_TYPE void amiga_reset( void )
725 ATTRIB_NORET;
726
727static void amiga_reset (void)
728{
729 unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
730 unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label);
731
732 local_irq_disable();
733 if (CPU_IS_040_OR_060)
734 /* Setup transparent translation registers for mapping
735 * of 16 MB kernel segment before disabling translation
736 */
737 __asm__ __volatile__
738 ("movel %0,%/d0\n\t"
739 "andl #0xff000000,%/d0\n\t"
740 "orw #0xe020,%/d0\n\t" /* map 16 MB, enable, cacheable */
741 ".chip 68040\n\t"
742 "movec %%d0,%%itt0\n\t"
743 "movec %%d0,%%dtt0\n\t"
744 ".chip 68k\n\t"
745 "jmp %0@\n\t"
746 : /* no outputs */
747 : "a" (jmp_addr040));
748 else
749 /* for 680[23]0, just disable translation and jump to the physical
750 * address of the label
751 */
752 __asm__ __volatile__
753 ("pmove %/tc,%@\n\t"
754 "bclr #7,%@\n\t"
755 "pmove %@,%/tc\n\t"
756 "jmp %0@\n\t"
757 : /* no outputs */
758 : "a" (jmp_addr));
759 jmp_addr_label040:
760 /* disable translation on '040 now */
761 __asm__ __volatile__
762 ("moveq #0,%/d0\n\t"
763 ".chip 68040\n\t"
764 "movec %%d0,%%tc\n\t" /* disable MMU */
765 ".chip 68k\n\t"
766 : /* no outputs */
767 : /* no inputs */
768 : "d0");
769
770 jmp_addr_label:
771 /* pickup reset address from AmigaOS ROM, reset devices and jump
772 * to reset address
773 */
774 __asm__ __volatile__
775 ("movew #0x2700,%/sr\n\t"
776 "leal 0x01000000,%/a0\n\t"
777 "subl %/a0@(-0x14),%/a0\n\t"
778 "movel %/a0@(4),%/a0\n\t"
779 "subql #2,%/a0\n\t"
780 "bra 1f\n\t"
781 /* align on a longword boundary */
782 __ALIGN_STR "\n"
783 "1:\n\t"
784 "reset\n\t"
785 "jmp %/a0@" : /* Just that gcc scans it for % escapes */ );
786
787 for (;;);
788
789}
790
791
792 /*
793 * Debugging
794 */
795
796#define SAVEKMSG_MAXMEM 128*1024
797
798#define SAVEKMSG_MAGIC1 0x53415645 /* 'SAVE' */
799#define SAVEKMSG_MAGIC2 0x4B4D5347 /* 'KMSG' */
800
801struct savekmsg {
802 unsigned long magic1; /* SAVEKMSG_MAGIC1 */
803 unsigned long magic2; /* SAVEKMSG_MAGIC2 */
804 unsigned long magicptr; /* address of magic1 */
805 unsigned long size;
806 char data[0];
807};
808
809static struct savekmsg *savekmsg;
810
811static void amiga_mem_console_write(struct console *co, const char *s,
812 unsigned int count)
813{
814 if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
815 memcpy(savekmsg->data+savekmsg->size, s, count);
816 savekmsg->size += count;
817 }
818}
819
820static void amiga_savekmsg_init(void)
821{
822 static struct resource debug_res = { .name = "Debug" };
823
824 savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
825 savekmsg->magic1 = SAVEKMSG_MAGIC1;
826 savekmsg->magic2 = SAVEKMSG_MAGIC2;
827 savekmsg->magicptr = ZTWO_PADDR(savekmsg);
828 savekmsg->size = 0;
829}
830
831static void amiga_serial_putc(char c)
832{
833 custom.serdat = (unsigned char)c | 0x100;
834 while (!(custom.serdatr & 0x2000))
835 ;
836}
837
838void amiga_serial_console_write(struct console *co, const char *s,
839 unsigned int count)
840{
841 while (count--) {
842 if (*s == '\n')
843 amiga_serial_putc('\r');
844 amiga_serial_putc(*s++);
845 }
846}
847
848#ifdef CONFIG_SERIAL_CONSOLE
849void amiga_serial_puts(const char *s)
850{
851 amiga_serial_console_write(NULL, s, strlen(s));
852}
853
854int amiga_serial_console_wait_key(struct console *co)
855{
856 int ch;
857
858 while (!(custom.intreqr & IF_RBF))
859 barrier();
860 ch = custom.serdatr & 0xff;
861 /* clear the interrupt, so that another character can be read */
862 custom.intreq = IF_RBF;
863 return ch;
864}
865
866void amiga_serial_gets(struct console *co, char *s, int len)
867{
868 int ch, cnt = 0;
869
870 while (1) {
871 ch = amiga_serial_console_wait_key(co);
872
873 /* Check for backspace. */
874 if (ch == 8 || ch == 127) {
875 if (cnt == 0) {
876 amiga_serial_putc('\007');
877 continue;
878 }
879 cnt--;
880 amiga_serial_puts("\010 \010");
881 continue;
882 }
883
884 /* Check for enter. */
885 if (ch == 10 || ch == 13)
886 break;
887
888 /* See if line is too long. */
889 if (cnt >= len + 1) {
890 amiga_serial_putc(7);
891 cnt--;
892 continue;
893 }
894
895 /* Store and echo character. */
896 s[cnt++] = ch;
897 amiga_serial_putc(ch);
898 }
899 /* Print enter. */
900 amiga_serial_puts("\r\n");
901 s[cnt] = 0;
902}
903#endif
904
905static void __init amiga_debug_init(void)
906{
907 if (!strcmp( m68k_debug_device, "ser" )) {
908 /* no initialization required (?) */
909 amiga_console_driver.write = amiga_serial_console_write;
910 register_console(&amiga_console_driver);
911 }
912}
913
914#ifdef CONFIG_HEARTBEAT
915static void amiga_heartbeat(int on)
916{
917 if (on)
918 ciaa.pra &= ~2;
919 else
920 ciaa.pra |= 2;
921}
922#endif
923
924 /*
925 * Amiga specific parts of /proc
926 */
927
928static void amiga_get_model(char *model)
929{
930 strcpy(model, amiga_model_name);
931}
932
933
934static int amiga_get_hardware_list(char *buffer)
935{
936 int len = 0;
937
938 if (AMIGAHW_PRESENT(CHIP_RAM))
939 len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
940 len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
941 amiga_psfreq, amiga_eclock);
942 if (AMIGAHW_PRESENT(AMI_VIDEO)) {
943 char *type;
944 switch(amiga_chipset) {
945 case CS_OCS:
946 type = "OCS";
947 break;
948 case CS_ECS:
949 type = "ECS";
950 break;
951 case CS_AGA:
952 type = "AGA";
953 break;
954 default:
955 type = "Old or Unknown";
956 break;
957 }
958 len += sprintf(buffer+len, "Graphics:\t%s\n", type);
959 }
960
961#define AMIGAHW_ANNOUNCE(name, str) \
962 if (AMIGAHW_PRESENT(name)) \
963 len += sprintf (buffer+len, "\t%s\n", str)
964
965 len += sprintf (buffer + len, "Detected hardware:\n");
966
967 AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
968 AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
969 AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
970 AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
971 AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
972 AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
973 AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
974 AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
975 AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
976 AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
977 AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
978 AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
979 AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
980 AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
981 AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
982 AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
983 AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
984 AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
985 AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
986 AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
987 AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
988 AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
989 AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
990 AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
991 AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
992 AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
993 AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
994 AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
995 AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
996#ifdef CONFIG_ZORRO
997 if (AMIGAHW_PRESENT(ZORRO))
998 len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion "
999 "Device%s\n",
1000 AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
1001 zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
1002#endif /* CONFIG_ZORRO */
1003
1004#undef AMIGAHW_ANNOUNCE
1005
1006 return(len);
1007}
diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
new file mode 100644
index 000000000000..fc57c6e72acf
--- /dev/null
+++ b/arch/m68k/amiga/pcmcia.c
@@ -0,0 +1,113 @@
1/*
2** asm-m68k/pcmcia.c -- Amiga Linux PCMCIA support
3** most information was found by disassembling card.resource
4** I'm still looking for an official doc !
5**
6** Copyright 1997 by Alain Malek
7**
8** This file is subject to the terms and conditions of the GNU General Public
9** License. See the file COPYING in the main directory of this archive
10** for more details.
11**
12** Created: 12/10/97 by Alain Malek
13*/
14
15#include <linux/types.h>
16#include <linux/jiffies.h>
17#include <linux/timer.h>
18#include <asm/amigayle.h>
19#include <asm/amipcmcia.h>
20
21/* gayle config byte for program voltage and access speed */
22static unsigned char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS;
23
24void pcmcia_reset(void)
25{
26 unsigned long reset_start_time = jiffies;
27 unsigned char b;
28
29 gayle_reset = 0x00;
30 while (time_before(jiffies, reset_start_time + 1*HZ/100));
31 b = gayle_reset;
32}
33
34
35/* copy a tuple, including tuple header. return nb bytes copied */
36/* be carefull as this may trigger a GAYLE_IRQ_WR interrupt ! */
37
38int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
39{
40 unsigned char id, *dest;
41 int cnt, pos, len;
42
43 dest = tuple;
44 pos = 0;
45
46 id = gayle_attribute[pos];
47
48 while((id != CISTPL_END) && (pos < 0x10000)) {
49 len = (int)gayle_attribute[pos+2] + 2;
50 if (id == tuple_id) {
51 len = (len > max_len)?max_len:len;
52 for (cnt = 0; cnt < len; cnt++) {
53 *dest++ = gayle_attribute[pos+(cnt<<1)];
54 }
55
56 return len;
57 }
58 pos += len<<1;
59 id = gayle_attribute[pos];
60 }
61
62 return 0;
63}
64
65void pcmcia_program_voltage(int voltage)
66{
67 unsigned char v;
68
69 switch (voltage) {
70 case PCMCIA_0V:
71 v = GAYLE_CFG_0V;
72 break;
73 case PCMCIA_5V:
74 v = GAYLE_CFG_5V;
75 break;
76 case PCMCIA_12V:
77 v = GAYLE_CFG_12V;
78 break;
79 default:
80 v = GAYLE_CFG_0V;
81 }
82
83 cfg_byte = (cfg_byte & 0xfc) | v;
84 gayle.config = cfg_byte;
85
86}
87
88void pcmcia_access_speed(int speed)
89{
90 unsigned char s;
91
92 if (speed <= PCMCIA_SPEED_100NS)
93 s = GAYLE_CFG_100NS;
94 else if (speed <= PCMCIA_SPEED_150NS)
95 s = GAYLE_CFG_150NS;
96 else if (speed <= PCMCIA_SPEED_250NS)
97 s = GAYLE_CFG_250NS;
98 else
99 s = GAYLE_CFG_720NS;
100
101 cfg_byte = (cfg_byte & 0xf3) | s;
102 gayle.config = cfg_byte;
103}
104
105void pcmcia_write_enable(void)
106{
107 gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
108}
109
110void pcmcia_write_disable(void)
111{
112 gayle.cardstatus = 0;
113}
diff --git a/arch/m68k/apollo/Makefile b/arch/m68k/apollo/Makefile
new file mode 100644
index 000000000000..39264f3b6ad6
--- /dev/null
+++ b/arch/m68k/apollo/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/amiga source directory
3#
4
5obj-y := config.o dn_ints.o dma.o
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
new file mode 100644
index 000000000000..264929471253
--- /dev/null
+++ b/arch/m68k/apollo/config.c
@@ -0,0 +1,305 @@
1#include <linux/config.h>
2#include <linux/types.h>
3#include <linux/kernel.h>
4#include <linux/mm.h>
5#include <linux/tty.h>
6#include <linux/console.h>
7#include <linux/rtc.h>
8#include <linux/vt_kern.h>
9#include <linux/interrupt.h>
10
11#include <asm/setup.h>
12#include <asm/bootinfo.h>
13#include <asm/system.h>
14#include <asm/pgtable.h>
15#include <asm/apollohw.h>
16#include <asm/irq.h>
17#include <asm/rtc.h>
18#include <asm/machdep.h>
19
20u_long sio01_physaddr;
21u_long sio23_physaddr;
22u_long rtc_physaddr;
23u_long pica_physaddr;
24u_long picb_physaddr;
25u_long cpuctrl_physaddr;
26u_long timer_physaddr;
27u_long apollo_model;
28
29extern void dn_sched_init(irqreturn_t (*handler)(int,void *,struct pt_regs *));
30extern void dn_init_IRQ(void);
31extern int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
32extern void dn_free_irq(unsigned int irq, void *dev_id);
33extern void dn_enable_irq(unsigned int);
34extern void dn_disable_irq(unsigned int);
35extern int show_dn_interrupts(struct seq_file *, void *);
36extern unsigned long dn_gettimeoffset(void);
37extern int dn_dummy_hwclk(int, struct rtc_time *);
38extern int dn_dummy_set_clock_mmss(unsigned long);
39extern void dn_dummy_reset(void);
40extern void dn_dummy_waitbut(void);
41extern struct fb_info *dn_fb_init(long *);
42extern void dn_dummy_debug_init(void);
43extern void dn_dummy_video_setup(char *,int *);
44extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp);
45#ifdef CONFIG_HEARTBEAT
46static void dn_heartbeat(int on);
47#endif
48static irqreturn_t dn_timer_int(int irq,void *, struct pt_regs *);
49static irqreturn_t (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL;
50static void dn_get_model(char *model);
51static const char *apollo_models[] = {
52 [APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)",
53 [APOLLO_DN3010-APOLLO_DN3000] = "DN3010 (Otter)",
54 [APOLLO_DN3500-APOLLO_DN3000] = "DN3500 (Cougar II)",
55 [APOLLO_DN4000-APOLLO_DN3000] = "DN4000 (Mink)",
56 [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)"
57};
58
59int apollo_parse_bootinfo(const struct bi_record *record) {
60
61 int unknown = 0;
62 const unsigned long *data = record->data;
63
64 switch(record->tag) {
65 case BI_APOLLO_MODEL:
66 apollo_model=*data;
67 break;
68
69 default:
70 unknown=1;
71 }
72
73 return unknown;
74}
75
76void dn_setup_model(void) {
77
78
79 printk("Apollo hardware found: ");
80 printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]);
81
82 switch(apollo_model) {
83 case APOLLO_UNKNOWN:
84 panic("Unknown apollo model");
85 break;
86 case APOLLO_DN3000:
87 case APOLLO_DN3010:
88 sio01_physaddr=SAU8_SIO01_PHYSADDR;
89 rtc_physaddr=SAU8_RTC_PHYSADDR;
90 pica_physaddr=SAU8_PICA;
91 picb_physaddr=SAU8_PICB;
92 cpuctrl_physaddr=SAU8_CPUCTRL;
93 timer_physaddr=SAU8_TIMER;
94 break;
95 case APOLLO_DN4000:
96 sio01_physaddr=SAU7_SIO01_PHYSADDR;
97 sio23_physaddr=SAU7_SIO23_PHYSADDR;
98 rtc_physaddr=SAU7_RTC_PHYSADDR;
99 pica_physaddr=SAU7_PICA;
100 picb_physaddr=SAU7_PICB;
101 cpuctrl_physaddr=SAU7_CPUCTRL;
102 timer_physaddr=SAU7_TIMER;
103 break;
104 case APOLLO_DN4500:
105 panic("Apollo model not yet supported");
106 break;
107 case APOLLO_DN3500:
108 sio01_physaddr=SAU7_SIO01_PHYSADDR;
109 sio23_physaddr=SAU7_SIO23_PHYSADDR;
110 rtc_physaddr=SAU7_RTC_PHYSADDR;
111 pica_physaddr=SAU7_PICA;
112 picb_physaddr=SAU7_PICB;
113 cpuctrl_physaddr=SAU7_CPUCTRL;
114 timer_physaddr=SAU7_TIMER;
115 break;
116 default:
117 panic("Undefined apollo model");
118 break;
119 }
120
121
122}
123
124int dn_serial_console_wait_key(struct console *co) {
125
126 while(!(sio01.srb_csrb & 1))
127 barrier();
128 return sio01.rhrb_thrb;
129}
130
131void dn_serial_console_write (struct console *co, const char *str,unsigned int count)
132{
133 while(count--) {
134 if (*str == '\n') {
135 sio01.rhrb_thrb = (unsigned char)'\r';
136 while (!(sio01.srb_csrb & 0x4))
137 ;
138 }
139 sio01.rhrb_thrb = (unsigned char)*str++;
140 while (!(sio01.srb_csrb & 0x4))
141 ;
142 }
143}
144
145void dn_serial_print (const char *str)
146{
147 while (*str) {
148 if (*str == '\n') {
149 sio01.rhrb_thrb = (unsigned char)'\r';
150 while (!(sio01.srb_csrb & 0x4))
151 ;
152 }
153 sio01.rhrb_thrb = (unsigned char)*str++;
154 while (!(sio01.srb_csrb & 0x4))
155 ;
156 }
157}
158
159void config_apollo(void) {
160
161 int i;
162
163 dn_setup_model();
164
165 mach_sched_init=dn_sched_init; /* */
166 mach_init_IRQ=dn_init_IRQ;
167 mach_default_handler=NULL;
168 mach_request_irq = dn_request_irq;
169 mach_free_irq = dn_free_irq;
170 enable_irq = dn_enable_irq;
171 disable_irq = dn_disable_irq;
172 mach_get_irq_list = show_dn_interrupts;
173 mach_gettimeoffset = dn_gettimeoffset;
174 mach_max_dma_address = 0xffffffff;
175 mach_hwclk = dn_dummy_hwclk; /* */
176 mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */
177 mach_process_int = dn_process_int;
178 mach_reset = dn_dummy_reset; /* */
179#ifdef CONFIG_DUMMY_CONSOLE
180 conswitchp = &dummy_con;
181#endif
182#ifdef CONFIG_HEARTBEAT
183 mach_heartbeat = dn_heartbeat;
184#endif
185 mach_get_model = dn_get_model;
186
187 cpuctrl=0xaa00;
188
189 /* clear DMA translation table */
190 for(i=0;i<0x400;i++)
191 addr_xlat_map[i]=0;
192
193}
194
195irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) {
196
197 volatile unsigned char x;
198
199 sched_timer_handler(irq,dev_id,fp);
200
201 x=*(volatile unsigned char *)(timer+3);
202 x=*(volatile unsigned char *)(timer+5);
203
204 return IRQ_HANDLED;
205}
206
207void dn_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) {
208
209 /* program timer 1 */
210 *(volatile unsigned char *)(timer+3)=0x01;
211 *(volatile unsigned char *)(timer+1)=0x40;
212 *(volatile unsigned char *)(timer+5)=0x09;
213 *(volatile unsigned char *)(timer+7)=0xc4;
214
215 /* enable IRQ of PIC B */
216 *(volatile unsigned char *)(pica+1)&=(~8);
217
218#if 0
219 printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
220 printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
221#endif
222
223 sched_timer_handler=timer_routine;
224 request_irq(0,dn_timer_int,0,NULL,NULL);
225
226}
227
228unsigned long dn_gettimeoffset(void) {
229
230 return 0xdeadbeef;
231
232}
233
234int dn_dummy_hwclk(int op, struct rtc_time *t) {
235
236
237 if(!op) { /* read */
238 t->tm_sec=rtc->second;
239 t->tm_min=rtc->minute;
240 t->tm_hour=rtc->hours;
241 t->tm_mday=rtc->day_of_month;
242 t->tm_wday=rtc->day_of_week;
243 t->tm_mon=rtc->month;
244 t->tm_year=rtc->year;
245 } else {
246 rtc->second=t->tm_sec;
247 rtc->minute=t->tm_min;
248 rtc->hours=t->tm_hour;
249 rtc->day_of_month=t->tm_mday;
250 if(t->tm_wday!=-1)
251 rtc->day_of_week=t->tm_wday;
252 rtc->month=t->tm_mon;
253 rtc->year=t->tm_year;
254 }
255
256 return 0;
257
258}
259
260int dn_dummy_set_clock_mmss(unsigned long nowtime) {
261
262 printk("set_clock_mmss\n");
263
264 return 0;
265
266}
267
268void dn_dummy_reset(void) {
269
270 dn_serial_print("The end !\n");
271
272 for(;;);
273
274}
275
276void dn_dummy_waitbut(void) {
277
278 dn_serial_print("waitbut\n");
279
280}
281
282static void dn_get_model(char *model)
283{
284 strcpy(model, "Apollo ");
285 if (apollo_model >= APOLLO_DN3000 && apollo_model <= APOLLO_DN4500)
286 strcat(model, apollo_models[apollo_model - APOLLO_DN3000]);
287}
288
289#ifdef CONFIG_HEARTBEAT
290static int dn_cpuctrl=0xff00;
291
292static void dn_heartbeat(int on) {
293
294 if(on) {
295 dn_cpuctrl&=~0x100;
296 cpuctrl=dn_cpuctrl;
297 }
298 else {
299 dn_cpuctrl&=~0x100;
300 dn_cpuctrl|=0x100;
301 cpuctrl=dn_cpuctrl;
302 }
303}
304#endif
305
diff --git a/arch/m68k/apollo/dma.c b/arch/m68k/apollo/dma.c
new file mode 100644
index 000000000000..aed8be177ef1
--- /dev/null
+++ b/arch/m68k/apollo/dma.c
@@ -0,0 +1,50 @@
1#include <linux/types.h>
2#include <linux/kernel.h>
3#include <linux/mm.h>
4#include <linux/kd.h>
5#include <linux/tty.h>
6#include <linux/console.h>
7
8#include <asm/setup.h>
9#include <asm/bootinfo.h>
10#include <asm/system.h>
11#include <asm/pgtable.h>
12#include <asm/apollodma.h>
13#include <asm/io.h>
14
15/* note only works for 16 Bit 1 page DMA's */
16
17static unsigned short next_free_xlat_entry=0;
18
19unsigned short dma_map_page(unsigned long phys_addr,int count,int type) {
20
21 unsigned long page_aligned_addr=phys_addr & (~((1<<12)-1));
22 unsigned short start_map_addr=page_aligned_addr >> 10;
23 unsigned short free_xlat_entry, *xlat_map_entry;
24 int i;
25
26 free_xlat_entry=next_free_xlat_entry;
27 for(i=0,xlat_map_entry=addr_xlat_map+(free_xlat_entry<<2);i<8;i++,xlat_map_entry++) {
28#if 0
29 printk("phys_addr: %x, page_aligned_addr: %x, start_map_addr: %x\n",phys_addr,page_aligned_addr,start_map_addr+i);
30#endif
31 out_be16(xlat_map_entry, start_map_addr+i);
32 }
33
34 next_free_xlat_entry+=2;
35 if(next_free_xlat_entry>125)
36 next_free_xlat_entry=0;
37
38#if 0
39 printk("next_free_xlat_entry: %d\n",next_free_xlat_entry);
40#endif
41
42 return free_xlat_entry<<10;
43}
44
45void dma_unmap_page(unsigned short dma_addr) {
46
47 return ;
48
49}
50
diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c
new file mode 100644
index 000000000000..a31259359a12
--- /dev/null
+++ b/arch/m68k/apollo/dn_ints.c
@@ -0,0 +1,125 @@
1#include <linux/types.h>
2#include <linux/kernel.h>
3#include <linux/jiffies.h>
4#include <linux/kernel_stat.h>
5#include <linux/timer.h>
6
7#include <asm/system.h>
8#include <asm/irq.h>
9#include <asm/traps.h>
10#include <asm/page.h>
11#include <asm/machdep.h>
12#include <asm/apollohw.h>
13#include <asm/errno.h>
14
15static irq_handler_t dn_irqs[16];
16
17irqreturn_t dn_process_int(int irq, struct pt_regs *fp)
18{
19 irqreturn_t res = IRQ_NONE;
20
21 if(dn_irqs[irq-160].handler) {
22 res = dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp);
23 } else {
24 printk("spurious irq %d occurred\n",irq);
25 }
26
27 *(volatile unsigned char *)(pica)=0x20;
28 *(volatile unsigned char *)(picb)=0x20;
29
30 return res;
31}
32
33void dn_init_IRQ(void) {
34
35 int i;
36
37 for(i=0;i<16;i++) {
38 dn_irqs[i].handler=NULL;
39 dn_irqs[i].flags=IRQ_FLG_STD;
40 dn_irqs[i].dev_id=NULL;
41 dn_irqs[i].devname=NULL;
42 }
43
44}
45
46int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) {
47
48 if((irq<0) || (irq>15)) {
49 printk("Trying to request invalid IRQ\n");
50 return -ENXIO;
51 }
52
53 if(!dn_irqs[irq].handler) {
54 dn_irqs[irq].handler=handler;
55 dn_irqs[irq].flags=IRQ_FLG_STD;
56 dn_irqs[irq].dev_id=dev_id;
57 dn_irqs[irq].devname=devname;
58 if(irq<8)
59 *(volatile unsigned char *)(pica+1)&=~(1<<irq);
60 else
61 *(volatile unsigned char *)(picb+1)&=~(1<<(irq-8));
62
63 return 0;
64 }
65 else {
66 printk("Trying to request already assigned irq %d\n",irq);
67 return -ENXIO;
68 }
69
70}
71
72void dn_free_irq(unsigned int irq, void *dev_id) {
73
74 if((irq<0) || (irq>15)) {
75 printk("Trying to free invalid IRQ\n");
76 return ;
77 }
78
79 if(irq<8)
80 *(volatile unsigned char *)(pica+1)|=(1<<irq);
81 else
82 *(volatile unsigned char *)(picb+1)|=(1<<(irq-8));
83
84 dn_irqs[irq].handler=NULL;
85 dn_irqs[irq].flags=IRQ_FLG_STD;
86 dn_irqs[irq].dev_id=NULL;
87 dn_irqs[irq].devname=NULL;
88
89 return ;
90
91}
92
93void dn_enable_irq(unsigned int irq) {
94
95 printk("dn enable irq\n");
96
97}
98
99void dn_disable_irq(unsigned int irq) {
100
101 printk("dn disable irq\n");
102
103}
104
105int show_dn_interrupts(struct seq_file *p, void *v) {
106
107 printk("dn get irq list\n");
108
109 return 0;
110
111}
112
113struct fb_info *dn_dummy_fb_init(long *mem_start) {
114
115 printk("fb init\n");
116
117 return NULL;
118
119}
120
121void dn_dummy_video_setup(char *options,int *ints) {
122
123 printk("no video yet\n");
124
125}
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
new file mode 100644
index 000000000000..8cb6236b39db
--- /dev/null
+++ b/arch/m68k/atari/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for Linux arch/m68k/atari source directory
3#
4
5obj-y := config.o time.o debug.o ataints.o stdma.o \
6 atasound.o stram.o atari_ksyms.o
7
8ifeq ($(CONFIG_PCI),y)
9obj-$(CONFIG_HADES) += hades-pci.o
10endif
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
new file mode 100644
index 000000000000..076f47917842
--- /dev/null
+++ b/arch/m68k/atari/ataints.c
@@ -0,0 +1,648 @@
1/*
2 * arch/m68k/atari/ataints.c -- Atari Linux interrupt handling code
3 *
4 * 5/2/94 Roman Hodek:
5 * Added support for TT interrupts; setup for TT SCU (may someone has
6 * twiddled there and we won't get the right interrupts :-()
7 *
8 * Major change: The device-independent code in m68k/ints.c didn't know
9 * about non-autovec ints yet. It hardcoded the number of possible ints to
10 * 7 (IRQ1...IRQ7). But the Atari has lots of non-autovec ints! I made the
11 * number of possible ints a constant defined in interrupt.h, which is
12 * 47 for the Atari. So we can call request_irq() for all Atari interrupts
13 * just the normal way. Additionally, all vectors >= 48 are initialized to
14 * call trap() instead of inthandler(). This must be changed here, too.
15 *
16 * 1995-07-16 Lars Brinkhoff <f93labr@dd.chalmers.se>:
17 * Corrected a bug in atari_add_isr() which rejected all SCC
18 * interrupt sources if there were no TT MFP!
19 *
20 * 12/13/95: New interface functions atari_level_triggered_int() and
21 * atari_register_vme_int() as support for level triggered VME interrupts.
22 *
23 * 02/12/96: (Roman)
24 * Total rewrite of Atari interrupt handling, for new scheme see comments
25 * below.
26 *
27 * 1996-09-03 lars brinkhoff <f93labr@dd.chalmers.se>:
28 * Added new function atari_unregister_vme_int(), and
29 * modified atari_register_vme_int() as well as IS_VALID_INTNO()
30 * to work with it.
31 *
32 * This file is subject to the terms and conditions of the GNU General Public
33 * License. See the file COPYING in the main directory of this archive
34 * for more details.
35 *
36 */
37
38#include <linux/types.h>
39#include <linux/kernel.h>
40#include <linux/kernel_stat.h>
41#include <linux/init.h>
42#include <linux/seq_file.h>
43
44#include <asm/system.h>
45#include <asm/traps.h>
46
47#include <asm/atarihw.h>
48#include <asm/atariints.h>
49#include <asm/atari_stdma.h>
50#include <asm/irq.h>
51#include <asm/entry.h>
52
53
54/*
55 * Atari interrupt handling scheme:
56 * --------------------------------
57 *
58 * All interrupt source have an internal number (defined in
59 * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
60 * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
61 * be allocated by atari_register_vme_int().
62 *
63 * Each interrupt can be of three types:
64 *
65 * - SLOW: The handler runs with all interrupts enabled, except the one it
66 * was called by (to avoid reentering). This should be the usual method.
67 * But it is currently possible only for MFP ints, since only the MFP
68 * offers an easy way to mask interrupts.
69 *
70 * - FAST: The handler runs with all interrupts disabled. This should be used
71 * only for really fast handlers, that just do actions immediately
72 * necessary, and let the rest do a bottom half or task queue.
73 *
74 * - PRIORITIZED: The handler can be interrupted by higher-level ints
75 * (greater IPL, no MFP priorities!). This is the method of choice for ints
76 * which should be slow, but are not from a MFP.
77 *
78 * The feature of more than one handler for one int source is still there, but
79 * only applicable if all handers are of the same type. To not slow down
80 * processing of ints with only one handler by the chaining feature, the list
81 * calling function atari_call_irq_list() is only plugged in at the time the
82 * second handler is registered.
83 *
84 * Implementation notes: For fast-as-possible int handling, there are separate
85 * entry points for each type (slow/fast/prio). The assembler handler calls
86 * the irq directly in the usual case, no C wrapper is involved. In case of
87 * multiple handlers, atari_call_irq_list() is registered as handler and calls
88 * in turn the real irq's. To ease access from assembler level to the irq
89 * function pointer and accompanying data, these two are stored in a separate
90 * array, irq_handler[]. The rest of data (type, name) are put into a second
91 * array, irq_param, that is accessed from C only. For each slow interrupt (32
92 * in all) there are separate handler functions, which makes it possible to
93 * hard-code the MFP register address and value, are necessary to mask the
94 * int. If there'd be only one generic function, lots of calculations would be
95 * needed to determine MFP register and int mask from the vector number :-(
96 *
97 * Furthermore, slow ints may not lower the IPL below its previous value
98 * (before the int happened). This is needed so that an int of class PRIO, on
99 * that this int may be stacked, cannot be reentered. This feature is
100 * implemented as follows: If the stack frame format is 1 (throwaway), the int
101 * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
102 * 2, which still blocks the HSYNC, but no interrupts of interest. If the
103 * frame format is 0, the int is nested, and the old IPL value can be found in
104 * the sr copy in the frame.
105 */
106
107
108#define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES)
109
110typedef void (*asm_irq_handler)(void);
111
112struct irqhandler {
113 irqreturn_t (*handler)(int, void *, struct pt_regs *);
114 void *dev_id;
115};
116
117struct irqparam {
118 unsigned long flags;
119 const char *devname;
120};
121
122/*
123 * Array with irq's and their parameter data. This array is accessed from low
124 * level assembler code, so an element size of 8 allows usage of index scaling
125 * addressing mode.
126 */
127static struct irqhandler irq_handler[NUM_INT_SOURCES];
128
129/*
130 * This array hold the rest of parameters of int handlers: type
131 * (slow,fast,prio) and the name of the handler. These values are only
132 * accessed from C
133 */
134static struct irqparam irq_param[NUM_INT_SOURCES];
135
136/*
137 * Bitmap for free interrupt vector numbers
138 * (new vectors starting from 0x70 can be allocated by
139 * atari_register_vme_int())
140 */
141static int free_vme_vec_bitmap;
142
143/* check for valid int number (complex, sigh...) */
144#define IS_VALID_INTNO(n) \
145 ((n) > 0 && \
146 /* autovec and ST-MFP ok anyway */ \
147 (((n) < TTMFP_SOURCE_BASE) || \
148 /* TT-MFP ok if present */ \
149 ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE && \
150 ATARIHW_PRESENT(TT_MFP)) || \
151 /* SCC ok if present and number even */ \
152 ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE && \
153 !((n) & 1) && ATARIHW_PRESENT(SCC)) || \
154 /* greater numbers ok if they are registered VME vectors */ \
155 ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
156 free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
157
158
159/*
160 * Here start the assembler entry points for interrupts
161 */
162
163#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
164
165#define BUILD_SLOW_IRQ(n) \
166asmlinkage void IRQ_NAME(n); \
167/* Dummy function to allow asm with operands. */ \
168void atari_slow_irq_##n##_dummy (void) { \
169__asm__ (__ALIGN_STR "\n" \
170"atari_slow_irq_" #n "_handler:\t" \
171" addl %6,%5\n" /* preempt_count() += HARDIRQ_OFFSET */ \
172 SAVE_ALL_INT "\n" \
173 GET_CURRENT(%%d0) "\n" \
174" andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \
175 /* get old IPL from stack frame */ \
176" bfextu %%sp@(%c2){#5,#3},%%d0\n" \
177" movew %%sr,%%d1\n" \
178" bfins %%d0,%%d1{#21,#3}\n" \
179" movew %%d1,%%sr\n" /* set IPL = previous value */ \
180" addql #1,%a0\n" \
181" lea %a1,%%a0\n" \
182" pea %%sp@\n" /* push addr of frame */ \
183" movel %%a0@(4),%%sp@-\n" /* push handler data */ \
184" pea (%c3+8)\n" /* push int number */ \
185" movel %%a0@,%%a0\n" \
186" jbsr %%a0@\n" /* call the handler */ \
187" addql #8,%%sp\n" \
188" addql #4,%%sp\n" \
189" orw #0x0600,%%sr\n" \
190" andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \
191" orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \
192" jbra ret_from_interrupt\n" \
193 : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]), \
194 "n" (PT_OFF_SR), "n" (n), \
195 "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a) \
196 : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)), \
197 "m" (preempt_count()), "di" (HARDIRQ_OFFSET) \
198); \
199 for (;;); /* fake noreturn */ \
200}
201
202BUILD_SLOW_IRQ(0);
203BUILD_SLOW_IRQ(1);
204BUILD_SLOW_IRQ(2);
205BUILD_SLOW_IRQ(3);
206BUILD_SLOW_IRQ(4);
207BUILD_SLOW_IRQ(5);
208BUILD_SLOW_IRQ(6);
209BUILD_SLOW_IRQ(7);
210BUILD_SLOW_IRQ(8);
211BUILD_SLOW_IRQ(9);
212BUILD_SLOW_IRQ(10);
213BUILD_SLOW_IRQ(11);
214BUILD_SLOW_IRQ(12);
215BUILD_SLOW_IRQ(13);
216BUILD_SLOW_IRQ(14);
217BUILD_SLOW_IRQ(15);
218BUILD_SLOW_IRQ(16);
219BUILD_SLOW_IRQ(17);
220BUILD_SLOW_IRQ(18);
221BUILD_SLOW_IRQ(19);
222BUILD_SLOW_IRQ(20);
223BUILD_SLOW_IRQ(21);
224BUILD_SLOW_IRQ(22);
225BUILD_SLOW_IRQ(23);
226BUILD_SLOW_IRQ(24);
227BUILD_SLOW_IRQ(25);
228BUILD_SLOW_IRQ(26);
229BUILD_SLOW_IRQ(27);
230BUILD_SLOW_IRQ(28);
231BUILD_SLOW_IRQ(29);
232BUILD_SLOW_IRQ(30);
233BUILD_SLOW_IRQ(31);
234
235asm_irq_handler slow_handlers[32] = {
236 [0] = atari_slow_irq_0_handler,
237 [1] = atari_slow_irq_1_handler,
238 [2] = atari_slow_irq_2_handler,
239 [3] = atari_slow_irq_3_handler,
240 [4] = atari_slow_irq_4_handler,
241 [5] = atari_slow_irq_5_handler,
242 [6] = atari_slow_irq_6_handler,
243 [7] = atari_slow_irq_7_handler,
244 [8] = atari_slow_irq_8_handler,
245 [9] = atari_slow_irq_9_handler,
246 [10] = atari_slow_irq_10_handler,
247 [11] = atari_slow_irq_11_handler,
248 [12] = atari_slow_irq_12_handler,
249 [13] = atari_slow_irq_13_handler,
250 [14] = atari_slow_irq_14_handler,
251 [15] = atari_slow_irq_15_handler,
252 [16] = atari_slow_irq_16_handler,
253 [17] = atari_slow_irq_17_handler,
254 [18] = atari_slow_irq_18_handler,
255 [19] = atari_slow_irq_19_handler,
256 [20] = atari_slow_irq_20_handler,
257 [21] = atari_slow_irq_21_handler,
258 [22] = atari_slow_irq_22_handler,
259 [23] = atari_slow_irq_23_handler,
260 [24] = atari_slow_irq_24_handler,
261 [25] = atari_slow_irq_25_handler,
262 [26] = atari_slow_irq_26_handler,
263 [27] = atari_slow_irq_27_handler,
264 [28] = atari_slow_irq_28_handler,
265 [29] = atari_slow_irq_29_handler,
266 [30] = atari_slow_irq_30_handler,
267 [31] = atari_slow_irq_31_handler
268};
269
270asmlinkage void atari_fast_irq_handler( void );
271asmlinkage void atari_prio_irq_handler( void );
272
273/* Dummy function to allow asm with operands. */
274void atari_fast_prio_irq_dummy (void) {
275__asm__ (__ALIGN_STR "\n"
276"atari_fast_irq_handler:\n\t"
277 "orw #0x700,%%sr\n" /* disable all interrupts */
278"atari_prio_irq_handler:\n\t"
279 "addl %3,%2\n\t" /* preempt_count() += HARDIRQ_OFFSET */
280 SAVE_ALL_INT "\n\t"
281 GET_CURRENT(%%d0) "\n\t"
282 /* get vector number from stack frame and convert to source */
283 "bfextu %%sp@(%c1){#4,#10},%%d0\n\t"
284 "subw #(0x40-8),%%d0\n\t"
285 "jpl 1f\n\t"
286 "addw #(0x40-8-0x18),%%d0\n"
287 "1:\tlea %a0,%%a0\n\t"
288 "addql #1,%%a0@(%%d0:l:4)\n\t"
289 "lea irq_handler,%%a0\n\t"
290 "lea %%a0@(%%d0:l:8),%%a0\n\t"
291 "pea %%sp@\n\t" /* push frame address */
292 "movel %%a0@(4),%%sp@-\n\t" /* push handler data */
293 "movel %%d0,%%sp@-\n\t" /* push int number */
294 "movel %%a0@,%%a0\n\t"
295 "jsr %%a0@\n\t" /* and call the handler */
296 "addql #8,%%sp\n\t"
297 "addql #4,%%sp\n\t"
298 "jbra ret_from_interrupt"
299 : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
300 "m" (preempt_count()), "di" (HARDIRQ_OFFSET)
301);
302 for (;;);
303}
304
305/* GK:
306 * HBL IRQ handler for Falcon. Nobody needs it :-)
307 * ++andreas: raise ipl to disable further HBLANK interrupts.
308 */
309asmlinkage void falcon_hblhandler(void);
310asm(".text\n"
311__ALIGN_STR "\n\t"
312"falcon_hblhandler:\n\t"
313 "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */
314 "rte");
315
316/* Defined in entry.S; only increments 'num_spurious' */
317asmlinkage void bad_interrupt(void);
318
319extern void atari_microwire_cmd( int cmd );
320
321extern int atari_SCC_reset_done;
322
323/*
324 * void atari_init_IRQ (void)
325 *
326 * Parameters: None
327 *
328 * Returns: Nothing
329 *
330 * This function should be called during kernel startup to initialize
331 * the atari IRQ handling routines.
332 */
333
334void __init atari_init_IRQ(void)
335{
336 int i;
337
338 /* initialize the vector table */
339 for (i = 0; i < NUM_INT_SOURCES; ++i) {
340 vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_interrupt;
341 }
342
343 /* Initialize the MFP(s) */
344
345#ifdef ATARI_USE_SOFTWARE_EOI
346 mfp.vec_adr = 0x48; /* Software EOI-Mode */
347#else
348 mfp.vec_adr = 0x40; /* Automatic EOI-Mode */
349#endif
350 mfp.int_en_a = 0x00; /* turn off MFP-Ints */
351 mfp.int_en_b = 0x00;
352 mfp.int_mk_a = 0xff; /* no Masking */
353 mfp.int_mk_b = 0xff;
354
355 if (ATARIHW_PRESENT(TT_MFP)) {
356#ifdef ATARI_USE_SOFTWARE_EOI
357 tt_mfp.vec_adr = 0x58; /* Software EOI-Mode */
358#else
359 tt_mfp.vec_adr = 0x50; /* Automatic EOI-Mode */
360#endif
361 tt_mfp.int_en_a = 0x00; /* turn off MFP-Ints */
362 tt_mfp.int_en_b = 0x00;
363 tt_mfp.int_mk_a = 0xff; /* no Masking */
364 tt_mfp.int_mk_b = 0xff;
365 }
366
367 if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) {
368 scc.cha_a_ctrl = 9;
369 MFPDELAY();
370 scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */
371 }
372
373 if (ATARIHW_PRESENT(SCU)) {
374 /* init the SCU if present */
375 tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and
376 * disable HSYNC interrupts (who
377 * needs them?) MFP and SCC are
378 * enabled in VME mask
379 */
380 tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */
381 }
382 else {
383 /* If no SCU and no Hades, the HSYNC interrupt needs to be
384 * disabled this way. (Else _inthandler in kernel/sys_call.S
385 * gets overruns)
386 */
387
388 if (!MACH_IS_HADES)
389 vectors[VEC_INT2] = falcon_hblhandler;
390 }
391
392 if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
393 /* Initialize the LM1992 Sound Controller to enable
394 the PSG sound. This is misplaced here, it should
395 be in an atasound_init(), that doesn't exist yet. */
396 atari_microwire_cmd(MW_LM1992_PSG_HIGH);
397 }
398
399 stdma_init();
400
401 /* Initialize the PSG: all sounds off, both ports output */
402 sound_ym.rd_data_reg_sel = 7;
403 sound_ym.wd_data = 0xff;
404}
405
406
407static irqreturn_t atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp )
408{
409 irq_node_t *node;
410
411 for (node = (irq_node_t *)dev_id; node; node = node->next)
412 node->handler(irq, node->dev_id, fp);
413 return IRQ_HANDLED;
414}
415
416
417/*
418 * atari_request_irq : add an interrupt service routine for a particular
419 * machine specific interrupt source.
420 * If the addition was successful, it returns 0.
421 */
422
423int atari_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
424 unsigned long flags, const char *devname, void *dev_id)
425{
426 int vector;
427 unsigned long oflags = flags;
428
429 /*
430 * The following is a hack to make some PCI card drivers work,
431 * which set the SA_SHIRQ flag.
432 */
433
434 flags &= ~SA_SHIRQ;
435
436 if (flags == SA_INTERRUPT) {
437 printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n",
438 __FUNCTION__, devname);
439 flags = IRQ_TYPE_SLOW;
440 }
441 if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) {
442 printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n",
443 __FUNCTION__, flags, oflags, devname);
444 return -EINVAL;
445 }
446 if (!IS_VALID_INTNO(irq)) {
447 printk ("%s: Unknown irq %d requested from %s\n",
448 __FUNCTION__, irq, devname);
449 return -ENXIO;
450 }
451 vector = IRQ_SOURCE_TO_VECTOR(irq);
452
453 /*
454 * Check type/source combination: slow ints are (currently)
455 * only possible for MFP-interrupts.
456 */
457 if (flags == IRQ_TYPE_SLOW &&
458 (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) {
459 printk ("%s: Slow irq requested for non-MFP source %d from %s\n",
460 __FUNCTION__, irq, devname);
461 return -EINVAL;
462 }
463
464 if (vectors[vector] == bad_interrupt) {
465 /* int has no handler yet */
466 irq_handler[irq].handler = handler;
467 irq_handler[irq].dev_id = dev_id;
468 irq_param[irq].flags = flags;
469 irq_param[irq].devname = devname;
470 vectors[vector] =
471 (flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] :
472 (flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler :
473 atari_prio_irq_handler;
474 /* If MFP int, also enable and umask it */
475 atari_turnon_irq(irq);
476 atari_enable_irq(irq);
477
478 return 0;
479 }
480 else if (irq_param[irq].flags == flags) {
481 /* old handler is of same type -> handlers can be chained */
482 irq_node_t *node;
483 unsigned long flags;
484
485 local_irq_save(flags);
486
487 if (irq_handler[irq].handler != atari_call_irq_list) {
488 /* Only one handler yet, make a node for this first one */
489 if (!(node = new_irq_node()))
490 return -ENOMEM;
491 node->handler = irq_handler[irq].handler;
492 node->dev_id = irq_handler[irq].dev_id;
493 node->devname = irq_param[irq].devname;
494 node->next = NULL;
495
496 irq_handler[irq].handler = atari_call_irq_list;
497 irq_handler[irq].dev_id = node;
498 irq_param[irq].devname = "chained";
499 }
500
501 if (!(node = new_irq_node()))
502 return -ENOMEM;
503 node->handler = handler;
504 node->dev_id = dev_id;
505 node->devname = devname;
506 /* new handlers are put in front of the queue */
507 node->next = irq_handler[irq].dev_id;
508 irq_handler[irq].dev_id = node;
509
510 local_irq_restore(flags);
511 return 0;
512 } else {
513 printk ("%s: Irq %d allocated by other type int (call from %s)\n",
514 __FUNCTION__, irq, devname);
515 return -EBUSY;
516 }
517}
518
519void atari_free_irq(unsigned int irq, void *dev_id)
520{
521 unsigned long flags;
522 int vector;
523 irq_node_t **list, *node;
524
525 if (!IS_VALID_INTNO(irq)) {
526 printk("%s: Unknown irq %d\n", __FUNCTION__, irq);
527 return;
528 }
529
530 vector = IRQ_SOURCE_TO_VECTOR(irq);
531 if (vectors[vector] == bad_interrupt)
532 goto not_found;
533
534 local_irq_save(flags);
535
536 if (irq_handler[irq].handler != atari_call_irq_list) {
537 /* It's the only handler for the interrupt */
538 if (irq_handler[irq].dev_id != dev_id) {
539 local_irq_restore(flags);
540 goto not_found;
541 }
542 irq_handler[irq].handler = NULL;
543 irq_handler[irq].dev_id = NULL;
544 irq_param[irq].devname = NULL;
545 vectors[vector] = bad_interrupt;
546 /* If MFP int, also disable it */
547 atari_disable_irq(irq);
548 atari_turnoff_irq(irq);
549
550 local_irq_restore(flags);
551 return;
552 }
553
554 /* The interrupt is chained, find the irq on the list */
555 for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) {
556 if ((*list)->dev_id == dev_id) break;
557 }
558 if (!*list) {
559 local_irq_restore(flags);
560 goto not_found;
561 }
562
563 (*list)->handler = NULL; /* Mark it as free for reallocation */
564 *list = (*list)->next;
565
566 /* If there's now only one handler, unchain the interrupt, i.e. plug in
567 * the handler directly again and omit atari_call_irq_list */
568 node = (irq_node_t *)irq_handler[irq].dev_id;
569 if (node && !node->next) {
570 irq_handler[irq].handler = node->handler;
571 irq_handler[irq].dev_id = node->dev_id;
572 irq_param[irq].devname = node->devname;
573 node->handler = NULL; /* Mark it as free for reallocation */
574 }
575
576 local_irq_restore(flags);
577 return;
578
579not_found:
580 printk("%s: tried to remove invalid irq\n", __FUNCTION__);
581 return;
582}
583
584
585/*
586 * atari_register_vme_int() returns the number of a free interrupt vector for
587 * hardware with a programmable int vector (probably a VME board).
588 */
589
590unsigned long atari_register_vme_int(void)
591{
592 int i;
593
594 for(i = 0; i < 32; i++)
595 if((free_vme_vec_bitmap & (1 << i)) == 0)
596 break;
597
598 if(i == 16)
599 return 0;
600
601 free_vme_vec_bitmap |= 1 << i;
602 return (VME_SOURCE_BASE + i);
603}
604
605
606void atari_unregister_vme_int(unsigned long irq)
607{
608 if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
609 irq -= VME_SOURCE_BASE;
610 free_vme_vec_bitmap &= ~(1 << irq);
611 }
612}
613
614
615int show_atari_interrupts(struct seq_file *p, void *v)
616{
617 int i;
618
619 for (i = 0; i < NUM_INT_SOURCES; ++i) {
620 if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
621 continue;
622 if (i < STMFP_SOURCE_BASE)
623 seq_printf(p, "auto %2d: %10u ",
624 i, kstat_cpu(0).irqs[i]);
625 else
626 seq_printf(p, "vec $%02x: %10u ",
627 IRQ_SOURCE_TO_VECTOR(i),
628 kstat_cpu(0).irqs[i]);
629
630 if (irq_handler[i].handler != atari_call_irq_list) {
631 seq_printf(p, "%s\n", irq_param[i].devname);
632 }
633 else {
634 irq_node_t *n;
635 for( n = (irq_node_t *)irq_handler[i].dev_id; n; n = n->next ) {
636 seq_printf(p, "%s\n", n->devname);
637 if (n->next)
638 seq_puts(p, " " );
639 }
640 }
641 }
642 if (num_spurious)
643 seq_printf(p, "spurio.: %10u\n", num_spurious);
644
645 return 0;
646}
647
648
diff --git a/arch/m68k/atari/atari_ksyms.c b/arch/m68k/atari/atari_ksyms.c
new file mode 100644
index 000000000000..a04757151538
--- /dev/null
+++ b/arch/m68k/atari/atari_ksyms.c
@@ -0,0 +1,35 @@
1#include <linux/module.h>
2
3#include <asm/ptrace.h>
4#include <asm/traps.h>
5#include <asm/atarihw.h>
6#include <asm/atariints.h>
7#include <asm/atarikb.h>
8#include <asm/atari_joystick.h>
9#include <asm/atari_stdma.h>
10#include <asm/atari_stram.h>
11
12extern void atari_microwire_cmd( int cmd );
13extern int atari_MFP_init_done;
14extern int atari_SCC_init_done;
15extern int atari_SCC_reset_done;
16
17EXPORT_SYMBOL(atari_mch_cookie);
18EXPORT_SYMBOL(atari_mch_type);
19EXPORT_SYMBOL(atari_hw_present);
20EXPORT_SYMBOL(atari_switches);
21EXPORT_SYMBOL(atari_dont_touch_floppy_select);
22EXPORT_SYMBOL(atari_register_vme_int);
23EXPORT_SYMBOL(atari_unregister_vme_int);
24EXPORT_SYMBOL(stdma_lock);
25EXPORT_SYMBOL(stdma_release);
26EXPORT_SYMBOL(stdma_others_waiting);
27EXPORT_SYMBOL(stdma_islocked);
28EXPORT_SYMBOL(atari_stram_alloc);
29EXPORT_SYMBOL(atari_stram_free);
30
31EXPORT_SYMBOL(atari_MFP_init_done);
32EXPORT_SYMBOL(atari_SCC_init_done);
33EXPORT_SYMBOL(atari_SCC_reset_done);
34
35EXPORT_SYMBOL(atari_microwire_cmd);
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
new file mode 100644
index 000000000000..ee04250eb56b
--- /dev/null
+++ b/arch/m68k/atari/atasound.c
@@ -0,0 +1,109 @@
1/*
2 * linux/arch/m68k/atari/atasound.c
3 *
4 * ++Geert: Moved almost all stuff to linux/drivers/sound/
5 *
6 * The author of atari_nosound, atari_mksound and atari_microwire_cmd is
7 * unknown. (++roman: That's me... :-)
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 * 1998-05-31 ++andreas: atari_mksound rewritten to always use the envelope,
14 * no timer, atari_nosound removed.
15 *
16 */
17
18
19#include <linux/sched.h>
20#include <linux/timer.h>
21#include <linux/major.h>
22#include <linux/fcntl.h>
23#include <linux/errno.h>
24#include <linux/mm.h>
25
26#include <asm/atarihw.h>
27#include <asm/system.h>
28#include <asm/irq.h>
29#include <asm/pgtable.h>
30#include <asm/atariints.h>
31
32
33/*
34 * stuff from the old atasound.c
35 */
36
37void atari_microwire_cmd (int cmd)
38{
39 tt_microwire.mask = 0x7ff;
40 tt_microwire.data = MW_LM1992_ADDR | cmd;
41
42 /* Busy wait for data being completely sent :-( */
43 while( tt_microwire.mask != 0x7ff)
44 ;
45}
46
47
48/* PSG base frequency */
49#define PSG_FREQ 125000
50/* PSG envelope base frequency times 10 */
51#define PSG_ENV_FREQ_10 78125
52
53void atari_mksound (unsigned int hz, unsigned int ticks)
54{
55 /* Generates sound of some frequency for some number of clock
56 ticks. */
57 unsigned long flags;
58 unsigned char tmp;
59 int period;
60
61 local_irq_save(flags);
62
63
64 /* Disable generator A in mixer control. */
65 sound_ym.rd_data_reg_sel = 7;
66 tmp = sound_ym.rd_data_reg_sel;
67 tmp |= 011;
68 sound_ym.wd_data = tmp;
69
70 if (hz) {
71 /* Convert from frequency value to PSG period value (base
72 frequency 125 kHz). */
73
74 period = PSG_FREQ / hz;
75
76 if (period > 0xfff) period = 0xfff;
77
78 /* Set generator A frequency to hz. */
79 sound_ym.rd_data_reg_sel = 0;
80 sound_ym.wd_data = period & 0xff;
81 sound_ym.rd_data_reg_sel = 1;
82 sound_ym.wd_data = (period >> 8) & 0xf;
83 if (ticks) {
84 /* Set length of envelope (max 8 sec). */
85 int length = (ticks * PSG_ENV_FREQ_10) / HZ / 10;
86
87 if (length > 0xffff) length = 0xffff;
88 sound_ym.rd_data_reg_sel = 11;
89 sound_ym.wd_data = length & 0xff;
90 sound_ym.rd_data_reg_sel = 12;
91 sound_ym.wd_data = length >> 8;
92 /* Envelope form: max -> min single. */
93 sound_ym.rd_data_reg_sel = 13;
94 sound_ym.wd_data = 0;
95 /* Use envelope for generator A. */
96 sound_ym.rd_data_reg_sel = 8;
97 sound_ym.wd_data = 0x10;
98 } else {
99 /* Set generator A level to maximum, no envelope. */
100 sound_ym.rd_data_reg_sel = 8;
101 sound_ym.wd_data = 15;
102 }
103 /* Turn on generator A in mixer control. */
104 sound_ym.rd_data_reg_sel = 7;
105 tmp &= ~1;
106 sound_ym.wd_data = tmp;
107 }
108 local_irq_restore(flags);
109}
diff --git a/arch/m68k/atari/atasound.h b/arch/m68k/atari/atasound.h
new file mode 100644
index 000000000000..1362762b8c0f
--- /dev/null
+++ b/arch/m68k/atari/atasound.h
@@ -0,0 +1,33 @@
1/*
2 * Minor numbers for the sound driver.
3 *
4 * Unfortunately Creative called the codec chip of SB as a DSP. For this
5 * reason the /dev/dsp is reserved for digitized audio use. There is a
6 * device for true DSP processors but it will be called something else.
7 * In v3.0 it's /dev/sndproc but this could be a temporary solution.
8 */
9
10#define SND_NDEVS 256 /* Number of supported devices */
11#define SND_DEV_CTL 0 /* Control port /dev/mixer */
12#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
13 synthesizer and MIDI output) */
14#define SND_DEV_MIDIN 2 /* Raw midi access */
15#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */
16#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
17#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
18#define SND_DEV_STATUS 6 /* /dev/sndstat */
19/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
20#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
21#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
22#define SND_DEV_PSS SND_DEV_SNDPROC
23
24#define DSP_DEFAULT_SPEED 8000
25
26#define ON 1
27#define OFF 0
28
29#define MAX_AUDIO_DEV 5
30#define MAX_MIXER_DEV 2
31#define MAX_SYNTH_DEV 3
32#define MAX_MIDI_DEV 6
33#define MAX_TIMER_DEV 3
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
new file mode 100644
index 000000000000..9261d2deeaf5
--- /dev/null
+++ b/arch/m68k/atari/config.c
@@ -0,0 +1,726 @@
1/*
2 * linux/arch/m68k/atari/config.c
3 *
4 * Copyright (C) 1994 Bjoern Brauel
5 *
6 * 5/2/94 Roman Hodek:
7 * Added setting of time_adj to get a better clock.
8 *
9 * 5/14/94 Roman Hodek:
10 * gettod() for TT
11 *
12 * 5/15/94 Roman Hodek:
13 * hard_reset_now() for Atari (and others?)
14 *
15 * 94/12/30 Andreas Schwab:
16 * atari_sched_init fixed to get precise clock.
17 *
18 * This file is subject to the terms and conditions of the GNU General Public
19 * License. See the file COPYING in the main directory of this archive
20 * for more details.
21 */
22
23/*
24 * Miscellaneous atari stuff
25 */
26
27#include <linux/config.h>
28#include <linux/types.h>
29#include <linux/mm.h>
30#include <linux/console.h>
31#include <linux/init.h>
32#include <linux/delay.h>
33#include <linux/ioport.h>
34#include <linux/vt_kern.h>
35
36#include <asm/bootinfo.h>
37#include <asm/setup.h>
38#include <asm/atarihw.h>
39#include <asm/atariints.h>
40#include <asm/atari_stram.h>
41#include <asm/system.h>
42#include <asm/machdep.h>
43#include <asm/hwtest.h>
44#include <asm/io.h>
45
46u_long atari_mch_cookie;
47u_long atari_mch_type;
48struct atari_hw_present atari_hw_present;
49u_long atari_switches;
50int atari_dont_touch_floppy_select;
51int atari_rtc_year_offset;
52
53/* local function prototypes */
54static void atari_reset( void );
55#ifdef CONFIG_ATARI_FLOPPY
56extern void atari_floppy_setup(char *, int *);
57#endif
58static void atari_get_model(char *model);
59static int atari_get_hardware_list(char *buffer);
60
61/* atari specific irq functions */
62extern void atari_init_IRQ (void);
63extern int atari_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
64 unsigned long flags, const char *devname, void *dev_id);
65extern void atari_free_irq (unsigned int irq, void *dev_id);
66extern void atari_enable_irq (unsigned int);
67extern void atari_disable_irq (unsigned int);
68extern int show_atari_interrupts (struct seq_file *, void *);
69extern void atari_mksound( unsigned int count, unsigned int ticks );
70#ifdef CONFIG_HEARTBEAT
71static void atari_heartbeat( int on );
72#endif
73
74/* atari specific timer functions (in time.c) */
75extern void atari_sched_init(irqreturn_t (*)(int, void *, struct pt_regs *));
76extern unsigned long atari_gettimeoffset (void);
77extern int atari_mste_hwclk (int, struct rtc_time *);
78extern int atari_tt_hwclk (int, struct rtc_time *);
79extern int atari_mste_set_clock_mmss (unsigned long);
80extern int atari_tt_set_clock_mmss (unsigned long);
81
82/* atari specific debug functions (in debug.c) */
83extern void atari_debug_init(void);
84
85
86/* I've moved hwreg_present() and hwreg_present_bywrite() out into
87 * mm/hwtest.c, to avoid having multiple copies of the same routine
88 * in the kernel [I wanted them in hp300 and they were already used
89 * in the nubus code. NB: I don't have an Atari so this might (just
90 * conceivably) break something.
91 * I've preserved the #if 0 version of hwreg_present_bywrite() here
92 * for posterity.
93 * -- Peter Maydell <pmaydell@chiark.greenend.org.uk>, 05/1998
94 */
95
96#if 0
97static int __init
98hwreg_present_bywrite(volatile void *regp, unsigned char val)
99{
100 int ret;
101 long save_sp, save_vbr;
102 static long tmp_vectors[3] = { [2] = (long)&&after_test };
103
104 __asm__ __volatile__
105 ( "movec %/vbr,%2\n\t" /* save vbr value */
106 "movec %4,%/vbr\n\t" /* set up temporary vectors */
107 "movel %/sp,%1\n\t" /* save sp */
108 "moveq #0,%0\n\t" /* assume not present */
109 "moveb %5,%3@\n\t" /* write the hardware reg */
110 "cmpb %3@,%5\n\t" /* compare it */
111 "seq %0" /* comes here only if reg */
112 /* is present */
113 : "=d&" (ret), "=r&" (save_sp), "=r&" (save_vbr)
114 : "a" (regp), "r" (tmp_vectors), "d" (val)
115 );
116 after_test:
117 __asm__ __volatile__
118 ( "movel %0,%/sp\n\t" /* restore sp */
119 "movec %1,%/vbr" /* restore vbr */
120 : : "r" (save_sp), "r" (save_vbr) : "sp"
121 );
122
123 return( ret );
124}
125#endif
126
127
128/* ++roman: This is a more elaborate test for an SCC chip, since the plain
129 * Medusa board generates DTACK at the SCC's standard addresses, but a SCC
130 * board in the Medusa is possible. Also, the addresses where the ST_ESCC
131 * resides generate DTACK without the chip, too.
132 * The method is to write values into the interrupt vector register, that
133 * should be readable without trouble (from channel A!).
134 */
135
136static int __init scc_test( volatile char *ctla )
137{
138 if (!hwreg_present( ctla ))
139 return( 0 );
140 MFPDELAY();
141
142 *ctla = 2; MFPDELAY();
143 *ctla = 0x40; MFPDELAY();
144
145 *ctla = 2; MFPDELAY();
146 if (*ctla != 0x40) return( 0 );
147 MFPDELAY();
148
149 *ctla = 2; MFPDELAY();
150 *ctla = 0x60; MFPDELAY();
151
152 *ctla = 2; MFPDELAY();
153 if (*ctla != 0x60) return( 0 );
154
155 return( 1 );
156}
157
158
159 /*
160 * Parse an Atari-specific record in the bootinfo
161 */
162
163int __init atari_parse_bootinfo(const struct bi_record *record)
164{
165 int unknown = 0;
166 const u_long *data = record->data;
167
168 switch (record->tag) {
169 case BI_ATARI_MCH_COOKIE:
170 atari_mch_cookie = *data;
171 break;
172 case BI_ATARI_MCH_TYPE:
173 atari_mch_type = *data;
174 break;
175 default:
176 unknown = 1;
177 }
178 return(unknown);
179}
180
181
182/* Parse the Atari-specific switches= option. */
183void __init atari_switches_setup( const char *str, unsigned len )
184{
185 char switches[len+1];
186 char *p;
187 int ovsc_shift;
188 char *args = switches;
189
190 /* copy string to local array, strsep works destructively... */
191 strlcpy( switches, str, sizeof(switches) );
192 atari_switches = 0;
193
194 /* parse the options */
195 while ((p = strsep(&args, ",")) != NULL) {
196 if (!*p) continue;
197 ovsc_shift = 0;
198 if (strncmp( p, "ov_", 3 ) == 0) {
199 p += 3;
200 ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
201 }
202
203 if (strcmp( p, "ikbd" ) == 0) {
204 /* RTS line of IKBD ACIA */
205 atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
206 }
207 else if (strcmp( p, "midi" ) == 0) {
208 /* RTS line of MIDI ACIA */
209 atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
210 }
211 else if (strcmp( p, "snd6" ) == 0) {
212 atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
213 }
214 else if (strcmp( p, "snd7" ) == 0) {
215 atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
216 }
217 }
218}
219
220
221 /*
222 * Setup the Atari configuration info
223 */
224
225void __init config_atari(void)
226{
227 unsigned short tos_version;
228
229 memset(&atari_hw_present, 0, sizeof(atari_hw_present));
230
231 atari_debug_init();
232
233 ioport_resource.end = 0xFFFFFFFF; /* Change size of I/O space from 64KB
234 to 4GB. */
235
236 mach_sched_init = atari_sched_init;
237 mach_init_IRQ = atari_init_IRQ;
238 mach_request_irq = atari_request_irq;
239 mach_free_irq = atari_free_irq;
240 enable_irq = atari_enable_irq;
241 disable_irq = atari_disable_irq;
242 mach_get_model = atari_get_model;
243 mach_get_hardware_list = atari_get_hardware_list;
244 mach_get_irq_list = show_atari_interrupts;
245 mach_gettimeoffset = atari_gettimeoffset;
246 mach_reset = atari_reset;
247#ifdef CONFIG_ATARI_FLOPPY
248 mach_floppy_setup = atari_floppy_setup;
249#endif
250#ifdef CONFIG_DUMMY_CONSOLE
251 conswitchp = &dummy_con;
252#endif
253 mach_max_dma_address = 0xffffff;
254#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
255 mach_beep = atari_mksound;
256#endif
257#ifdef CONFIG_HEARTBEAT
258 mach_heartbeat = atari_heartbeat;
259#endif
260
261 /* Set switches as requested by the user */
262 if (atari_switches & ATARI_SWITCH_IKBD)
263 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
264 if (atari_switches & ATARI_SWITCH_MIDI)
265 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
266 if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
267 sound_ym.rd_data_reg_sel = 14;
268 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
269 ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
270 ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
271 }
272
273 /* ++bjoern:
274 * Determine hardware present
275 */
276
277 printk( "Atari hardware found: " );
278 if (MACH_IS_MEDUSA || MACH_IS_HADES) {
279 /* There's no Atari video hardware on the Medusa, but all the
280 * addresses below generate a DTACK so no bus error occurs! */
281 }
282 else if (hwreg_present( f030_xreg )) {
283 ATARIHW_SET(VIDEL_SHIFTER);
284 printk( "VIDEL " );
285 /* This is a temporary hack: If there is Falcon video
286 * hardware, we assume that the ST-DMA serves SCSI instead of
287 * ACSI. In the future, there should be a better method for
288 * this...
289 */
290 ATARIHW_SET(ST_SCSI);
291 printk( "STDMA-SCSI " );
292 }
293 else if (hwreg_present( tt_palette )) {
294 ATARIHW_SET(TT_SHIFTER);
295 printk( "TT_SHIFTER " );
296 }
297 else if (hwreg_present( &shifter.bas_hi )) {
298 if (hwreg_present( &shifter.bas_lo ) &&
299 (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
300 ATARIHW_SET(EXTD_SHIFTER);
301 printk( "EXTD_SHIFTER " );
302 }
303 else {
304 ATARIHW_SET(STND_SHIFTER);
305 printk( "STND_SHIFTER " );
306 }
307 }
308 if (hwreg_present( &mfp.par_dt_reg )) {
309 ATARIHW_SET(ST_MFP);
310 printk( "ST_MFP " );
311 }
312 if (hwreg_present( &tt_mfp.par_dt_reg )) {
313 ATARIHW_SET(TT_MFP);
314 printk( "TT_MFP " );
315 }
316 if (hwreg_present( &tt_scsi_dma.dma_addr_hi )) {
317 ATARIHW_SET(SCSI_DMA);
318 printk( "TT_SCSI_DMA " );
319 }
320 if (!MACH_IS_HADES && hwreg_present( &st_dma.dma_hi )) {
321 ATARIHW_SET(STND_DMA);
322 printk( "STND_DMA " );
323 }
324 if (MACH_IS_MEDUSA || /* The ST-DMA address registers aren't readable
325 * on all Medusas, so the test below may fail */
326 (hwreg_present( &st_dma.dma_vhi ) &&
327 (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
328 st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
329 (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
330 st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
331 ATARIHW_SET(EXTD_DMA);
332 printk( "EXTD_DMA " );
333 }
334 if (hwreg_present( &tt_scsi.scsi_data )) {
335 ATARIHW_SET(TT_SCSI);
336 printk( "TT_SCSI " );
337 }
338 if (hwreg_present( &sound_ym.rd_data_reg_sel )) {
339 ATARIHW_SET(YM_2149);
340 printk( "YM2149 " );
341 }
342 if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
343 hwreg_present( &tt_dmasnd.ctrl )) {
344 ATARIHW_SET(PCM_8BIT);
345 printk( "PCM " );
346 }
347 if (!MACH_IS_HADES && hwreg_present( &falcon_codec.unused5 )) {
348 ATARIHW_SET(CODEC);
349 printk( "CODEC " );
350 }
351 if (hwreg_present( &dsp56k_host_interface.icr )) {
352 ATARIHW_SET(DSP56K);
353 printk( "DSP56K " );
354 }
355 if (hwreg_present( &tt_scc_dma.dma_ctrl ) &&
356#if 0
357 /* This test sucks! Who knows some better? */
358 (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
359 (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
360#else
361 !MACH_IS_MEDUSA && !MACH_IS_HADES
362#endif
363 ) {
364 ATARIHW_SET(SCC_DMA);
365 printk( "SCC_DMA " );
366 }
367 if (scc_test( &scc.cha_a_ctrl )) {
368 ATARIHW_SET(SCC);
369 printk( "SCC " );
370 }
371 if (scc_test( &st_escc.cha_b_ctrl )) {
372 ATARIHW_SET( ST_ESCC );
373 printk( "ST_ESCC " );
374 }
375 if (MACH_IS_HADES)
376 {
377 ATARIHW_SET( VME );
378 printk( "VME " );
379 }
380 else if (hwreg_present( &tt_scu.sys_mask )) {
381 ATARIHW_SET(SCU);
382 /* Assume a VME bus if there's a SCU */
383 ATARIHW_SET( VME );
384 printk( "VME SCU " );
385 }
386 if (hwreg_present( (void *)(0xffff9210) )) {
387 ATARIHW_SET(ANALOG_JOY);
388 printk( "ANALOG_JOY " );
389 }
390 if (!MACH_IS_HADES && hwreg_present( blitter.halftone )) {
391 ATARIHW_SET(BLITTER);
392 printk( "BLITTER " );
393 }
394 if (hwreg_present((void *)0xfff00039)) {
395 ATARIHW_SET(IDE);
396 printk( "IDE " );
397 }
398#if 1 /* This maybe wrong */
399 if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
400 hwreg_present( &tt_microwire.data ) &&
401 hwreg_present( &tt_microwire.mask ) &&
402 (tt_microwire.mask = 0x7ff,
403 udelay(1),
404 tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
405 udelay(1),
406 tt_microwire.data != 0)) {
407 ATARIHW_SET(MICROWIRE);
408 while (tt_microwire.mask != 0x7ff) ;
409 printk( "MICROWIRE " );
410 }
411#endif
412 if (hwreg_present( &tt_rtc.regsel )) {
413 ATARIHW_SET(TT_CLK);
414 printk( "TT_CLK " );
415 mach_hwclk = atari_tt_hwclk;
416 mach_set_clock_mmss = atari_tt_set_clock_mmss;
417 }
418 if (!MACH_IS_HADES && hwreg_present( &mste_rtc.sec_ones)) {
419 ATARIHW_SET(MSTE_CLK);
420 printk( "MSTE_CLK ");
421 mach_hwclk = atari_mste_hwclk;
422 mach_set_clock_mmss = atari_mste_set_clock_mmss;
423 }
424 if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
425 hwreg_present( &dma_wd.fdc_speed ) &&
426 hwreg_write( &dma_wd.fdc_speed, 0 )) {
427 ATARIHW_SET(FDCSPEED);
428 printk( "FDC_SPEED ");
429 }
430 if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
431 ATARIHW_SET(ACSI);
432 printk( "ACSI " );
433 }
434 printk("\n");
435
436 if (CPU_IS_040_OR_060)
437 /* Now it seems to be safe to turn of the tt0 transparent
438 * translation (the one that must not be turned off in
439 * head.S...)
440 */
441 __asm__ volatile ("moveq #0,%/d0\n\t"
442 ".chip 68040\n\t"
443 "movec %%d0,%%itt0\n\t"
444 "movec %%d0,%%dtt0\n\t"
445 ".chip 68k"
446 : /* no outputs */
447 : /* no inputs */
448 : "d0");
449
450 /* allocator for memory that must reside in st-ram */
451 atari_stram_init ();
452
453 /* Set up a mapping for the VMEbus address region:
454 *
455 * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
456 * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
457 * 0xfe000000 virt., because this can be done with a single
458 * transparent translation. On the 68040, lots of often unused
459 * page tables would be needed otherwise. On a MegaSTE or similar,
460 * the highest byte is stripped off by hardware due to the 24 bit
461 * design of the bus.
462 */
463
464 if (CPU_IS_020_OR_030) {
465 unsigned long tt1_val;
466 tt1_val = 0xfe008543; /* Translate 0xfexxxxxx, enable, cache
467 * inhibit, read and write, FDC mask = 3,
468 * FDC val = 4 -> Supervisor only */
469 __asm__ __volatile__ ( ".chip 68030\n\t"
470 "pmove %0@,%/tt1\n\t"
471 ".chip 68k"
472 : : "a" (&tt1_val) );
473 }
474 else {
475 __asm__ __volatile__
476 ( "movel %0,%/d0\n\t"
477 ".chip 68040\n\t"
478 "movec %%d0,%%itt1\n\t"
479 "movec %%d0,%%dtt1\n\t"
480 ".chip 68k"
481 :
482 : "g" (0xfe00a040) /* Translate 0xfexxxxxx, enable,
483 * supervisor only, non-cacheable/
484 * serialized, writable */
485 : "d0" );
486
487 }
488
489 /* Fetch tos version at Physical 2 */
490 /* We my not be able to access this address if the kernel is
491 loaded to st ram, since the first page is unmapped. On the
492 Medusa this is always the case and there is nothing we can do
493 about this, so we just assume the smaller offset. For the TT
494 we use the fact that in head.S we have set up a mapping
495 0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
496 in the last 16MB of the address space. */
497 tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
498 0xfff : *(unsigned short *)0xff000002;
499 atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
500}
501
502#ifdef CONFIG_HEARTBEAT
503static void atari_heartbeat( int on )
504{
505 unsigned char tmp;
506 unsigned long flags;
507
508 if (atari_dont_touch_floppy_select)
509 return;
510
511 local_irq_save(flags);
512 sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
513 tmp = sound_ym.rd_data_reg_sel;
514 sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
515 local_irq_restore(flags);
516}
517#endif
518
519/* ++roman:
520 *
521 * This function does a reset on machines that lack the ability to
522 * assert the processor's _RESET signal somehow via hardware. It is
523 * based on the fact that you can find the initial SP and PC values
524 * after a reset at physical addresses 0 and 4. This works pretty well
525 * for Atari machines, since the lowest 8 bytes of physical memory are
526 * really ROM (mapped by hardware). For other 680x0 machines: don't
527 * know if it works...
528 *
529 * To get the values at addresses 0 and 4, the MMU better is turned
530 * off first. After that, we have to jump into physical address space
531 * (the PC before the pmove statement points to the virtual address of
532 * the code). Getting that physical address is not hard, but the code
533 * becomes a bit complex since I've tried to ensure that the jump
534 * statement after the pmove is in the cache already (otherwise the
535 * processor can't fetch it!). For that, the code first jumps to the
536 * jump statement with the (virtual) address of the pmove section in
537 * an address register . The jump statement is surely in the cache
538 * now. After that, that physical address of the reset code is loaded
539 * into the same address register, pmove is done and the same jump
540 * statements goes to the reset code. Since there are not many
541 * statements between the two jumps, I hope it stays in the cache.
542 *
543 * The C code makes heavy use of the GCC features that you can get the
544 * address of a C label. No hope to compile this with another compiler
545 * than GCC!
546 */
547
548/* ++andreas: no need for complicated code, just depend on prefetch */
549
550static void atari_reset (void)
551{
552 long tc_val = 0;
553 long reset_addr;
554
555 /* On the Medusa, phys. 0x4 may contain garbage because it's no
556 ROM. See above for explanation why we cannot use PTOV(4). */
557 reset_addr = MACH_IS_HADES ? 0x7fe00030 :
558 MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
559 *(unsigned long *) 0xff000004;
560
561 /* reset ACIA for switch off OverScan, if it's active */
562 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
563 acia.key_ctrl = ACIA_RESET;
564 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
565 acia.mid_ctrl = ACIA_RESET;
566
567 /* processor independent: turn off interrupts and reset the VBR;
568 * the caches must be left enabled, else prefetching the final jump
569 * instruction doesn't work. */
570 local_irq_disable();
571 __asm__ __volatile__
572 ("moveq #0,%/d0\n\t"
573 "movec %/d0,%/vbr"
574 : : : "d0" );
575
576 if (CPU_IS_040_OR_060) {
577 unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
578 if (CPU_IS_060) {
579 /* 68060: clear PCR to turn off superscalar operation */
580 __asm__ __volatile__
581 ("moveq #0,%/d0\n\t"
582 ".chip 68060\n\t"
583 "movec %%d0,%%pcr\n\t"
584 ".chip 68k"
585 : : : "d0" );
586 }
587
588 __asm__ __volatile__
589 ("movel %0,%/d0\n\t"
590 "andl #0xff000000,%/d0\n\t"
591 "orw #0xe020,%/d0\n\t" /* map 16 MB, enable, cacheable */
592 ".chip 68040\n\t"
593 "movec %%d0,%%itt0\n\t"
594 "movec %%d0,%%dtt0\n\t"
595 ".chip 68k\n\t"
596 "jmp %0@\n\t"
597 : /* no outputs */
598 : "a" (jmp_addr040)
599 : "d0" );
600 jmp_addr_label040:
601 __asm__ __volatile__
602 ("moveq #0,%/d0\n\t"
603 "nop\n\t"
604 ".chip 68040\n\t"
605 "cinva %%bc\n\t"
606 "nop\n\t"
607 "pflusha\n\t"
608 "nop\n\t"
609 "movec %%d0,%%tc\n\t"
610 "nop\n\t"
611 /* the following setup of transparent translations is needed on the
612 * Afterburner040 to successfully reboot. Other machines shouldn't
613 * care about a different tt regs setup, they also didn't care in
614 * the past that the regs weren't turned off. */
615 "movel #0xffc000,%%d0\n\t" /* whole insn space cacheable */
616 "movec %%d0,%%itt0\n\t"
617 "movec %%d0,%%itt1\n\t"
618 "orw #0x40,%/d0\n\t" /* whole data space non-cacheable/ser. */
619 "movec %%d0,%%dtt0\n\t"
620 "movec %%d0,%%dtt1\n\t"
621 ".chip 68k\n\t"
622 "jmp %0@"
623 : /* no outputs */
624 : "a" (reset_addr)
625 : "d0");
626 }
627 else
628 __asm__ __volatile__
629 ("pmove %0@,%/tc\n\t"
630 "jmp %1@"
631 : /* no outputs */
632 : "a" (&tc_val), "a" (reset_addr));
633}
634
635
636static void atari_get_model(char *model)
637{
638 strcpy(model, "Atari ");
639 switch (atari_mch_cookie >> 16) {
640 case ATARI_MCH_ST:
641 if (ATARIHW_PRESENT(MSTE_CLK))
642 strcat (model, "Mega ST");
643 else
644 strcat (model, "ST");
645 break;
646 case ATARI_MCH_STE:
647 if (MACH_IS_MSTE)
648 strcat (model, "Mega STE");
649 else
650 strcat (model, "STE");
651 break;
652 case ATARI_MCH_TT:
653 if (MACH_IS_MEDUSA)
654 /* Medusa has TT _MCH cookie */
655 strcat (model, "Medusa");
656 else if (MACH_IS_HADES)
657 strcat(model, "Hades");
658 else
659 strcat (model, "TT");
660 break;
661 case ATARI_MCH_FALCON:
662 strcat (model, "Falcon");
663 if (MACH_IS_AB40)
664 strcat (model, " (with Afterburner040)");
665 break;
666 default:
667 sprintf (model + strlen (model), "(unknown mach cookie 0x%lx)",
668 atari_mch_cookie);
669 break;
670 }
671}
672
673
674static int atari_get_hardware_list(char *buffer)
675{
676 int len = 0, i;
677
678 for (i = 0; i < m68k_num_memory; i++)
679 len += sprintf (buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
680 m68k_memory[i].size >> 20, m68k_memory[i].addr,
681 (m68k_memory[i].addr & 0xff000000 ?
682 "alternate RAM" : "ST-RAM"));
683
684#define ATARIHW_ANNOUNCE(name,str) \
685 if (ATARIHW_PRESENT(name)) \
686 len += sprintf (buffer + len, "\t%s\n", str)
687
688 len += sprintf (buffer + len, "Detected hardware:\n");
689 ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
690 ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
691 ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
692 ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
693 ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
694 ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
695 ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
696 ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
697 ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
698 ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
699 ATARIHW_ANNOUNCE(IDE, "IDE Interface");
700 ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
701 ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
702 ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
703 ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
704 ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
705 ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
706 ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
707 ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
708 ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
709 ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
710 ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
711 ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
712 ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
713 ATARIHW_ANNOUNCE(SCU, "System Control Unit");
714 ATARIHW_ANNOUNCE(BLITTER, "Blitter");
715 ATARIHW_ANNOUNCE(VME, "VME Bus");
716 ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
717
718 return(len);
719}
720
721/*
722 * Local variables:
723 * c-indent-level: 4
724 * tab-width: 8
725 * End:
726 */
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
new file mode 100644
index 000000000000..ace05f79d968
--- /dev/null
+++ b/arch/m68k/atari/debug.c
@@ -0,0 +1,347 @@
1/*
2 * linux/arch/m68k/atari/debug.c
3 *
4 * Atari debugging and serial console stuff
5 *
6 * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/config.h>
14#include <linux/types.h>
15#include <linux/tty.h>
16#include <linux/console.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19
20#include <asm/atarihw.h>
21#include <asm/atariints.h>
22
23extern char m68k_debug_device[];
24
25/* Flag that Modem1 port is already initialized and used */
26int atari_MFP_init_done;
27/* Flag that Modem1 port is already initialized and used */
28int atari_SCC_init_done;
29/* Can be set somewhere, if a SCC master reset has already be done and should
30 * not be repeated; used by kgdb */
31int atari_SCC_reset_done;
32
33static struct console atari_console_driver = {
34 .name = "debug",
35 .flags = CON_PRINTBUFFER,
36 .index = -1,
37};
38
39
40static inline void ata_mfp_out (char c)
41{
42 while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
43 barrier ();
44 mfp.usart_dta = c;
45}
46
47void atari_mfp_console_write (struct console *co, const char *str,
48 unsigned int count)
49{
50 while (count--) {
51 if (*str == '\n')
52 ata_mfp_out( '\r' );
53 ata_mfp_out( *str++ );
54 }
55}
56
57static inline void ata_scc_out (char c)
58{
59 do {
60 MFPDELAY();
61 } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
62 MFPDELAY();
63 scc.cha_b_data = c;
64}
65
66void atari_scc_console_write (struct console *co, const char *str,
67 unsigned int count)
68{
69 while (count--) {
70 if (*str == '\n')
71 ata_scc_out( '\r' );
72 ata_scc_out( *str++ );
73 }
74}
75
76static inline void ata_midi_out (char c)
77{
78 while (!(acia.mid_ctrl & ACIA_TDRE)) /* wait for tx buf empty */
79 barrier ();
80 acia.mid_data = c;
81}
82
83void atari_midi_console_write (struct console *co, const char *str,
84 unsigned int count)
85{
86 while (count--) {
87 if (*str == '\n')
88 ata_midi_out( '\r' );
89 ata_midi_out( *str++ );
90 }
91}
92
93static int ata_par_out (char c)
94{
95 unsigned char tmp;
96 /* This a some-seconds timeout in case no printer is connected */
97 unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
98
99 while( (mfp.par_dt_reg & 1) && --i ) /* wait for BUSY == L */
100 ;
101 if (!i) return( 0 );
102
103 sound_ym.rd_data_reg_sel = 15; /* select port B */
104 sound_ym.wd_data = c; /* put char onto port */
105 sound_ym.rd_data_reg_sel = 14; /* select port A */
106 tmp = sound_ym.rd_data_reg_sel;
107 sound_ym.wd_data = tmp & ~0x20; /* set strobe L */
108 MFPDELAY(); /* wait a bit */
109 sound_ym.wd_data = tmp | 0x20; /* set strobe H */
110 return( 1 );
111}
112
113static void atari_par_console_write (struct console *co, const char *str,
114 unsigned int count)
115{
116 static int printer_present = 1;
117
118 if (!printer_present)
119 return;
120
121 while (count--) {
122 if (*str == '\n')
123 if (!ata_par_out( '\r' )) {
124 printer_present = 0;
125 return;
126 }
127 if (!ata_par_out( *str++ )) {
128 printer_present = 0;
129 return;
130 }
131 }
132}
133
134#ifdef CONFIG_SERIAL_CONSOLE
135int atari_mfp_console_wait_key(struct console *co)
136{
137 while( !(mfp.rcv_stat & 0x80) ) /* wait for rx buf filled */
138 barrier();
139 return( mfp.usart_dta );
140}
141
142int atari_scc_console_wait_key(struct console *co)
143{
144 do {
145 MFPDELAY();
146 } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
147 MFPDELAY();
148 return( scc.cha_b_data );
149}
150
151int atari_midi_console_wait_key(struct console *co)
152{
153 while( !(acia.mid_ctrl & ACIA_RDRF) ) /* wait for rx buf filled */
154 barrier();
155 return( acia.mid_data );
156}
157#endif
158
159/* The following two functions do a quick'n'dirty initialization of the MFP or
160 * SCC serial ports. They're used by the debugging interface, kgdb, and the
161 * serial console code. */
162#ifndef CONFIG_SERIAL_CONSOLE
163static void __init atari_init_mfp_port( int cflag )
164#else
165void atari_init_mfp_port( int cflag )
166#endif
167{
168 /* timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
169 * bps, resp., and work only correct if there's a RSVE or RSSPEED */
170 static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
171 int baud = cflag & CBAUD;
172 int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
173 int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
174
175 if (cflag & CBAUDEX)
176 baud += B38400;
177 if (baud < B1200 || baud > B38400+2)
178 baud = B9600; /* use default 9600bps for non-implemented rates */
179 baud -= B1200; /* baud_table[] starts at 1200bps */
180
181 mfp.trn_stat &= ~0x01; /* disable TX */
182 mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
183 mfp.tim_ct_cd &= 0x70; /* stop timer D */
184 mfp.tim_dt_d = baud_table[baud];
185 mfp.tim_ct_cd |= 0x01; /* start timer D, 1:4 */
186 mfp.trn_stat |= 0x01; /* enable TX */
187
188 atari_MFP_init_done = 1;
189}
190
191#define SCC_WRITE(reg,val) \
192 do { \
193 scc.cha_b_ctrl = (reg); \
194 MFPDELAY(); \
195 scc.cha_b_ctrl = (val); \
196 MFPDELAY(); \
197 } while(0)
198
199/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
200 * delay of ~ 60us. */
201#define LONG_DELAY() \
202 do { \
203 int i; \
204 for( i = 100; i > 0; --i ) \
205 MFPDELAY(); \
206 } while(0)
207
208#ifndef CONFIG_SERIAL_CONSOLE
209static void __init atari_init_scc_port( int cflag )
210#else
211void atari_init_scc_port( int cflag )
212#endif
213{
214 extern int atari_SCC_reset_done;
215 static int clksrc_table[9] =
216 /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
217 { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
218 static int brgsrc_table[9] =
219 /* reg 14: 0 = RTxC, 2 = PCLK */
220 { 2, 2, 2, 2, 2, 2, 0, 2, 2 };
221 static int clkmode_table[9] =
222 /* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
223 { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
224 static int div_table[9] =
225 /* reg12 (BRG low) */
226 { 208, 138, 103, 50, 24, 11, 1, 0, 0 };
227
228 int baud = cflag & CBAUD;
229 int clksrc, clkmode, div, reg3, reg5;
230
231 if (cflag & CBAUDEX)
232 baud += B38400;
233 if (baud < B1200 || baud > B38400+2)
234 baud = B9600; /* use default 9600bps for non-implemented rates */
235 baud -= B1200; /* tables starts at 1200bps */
236
237 clksrc = clksrc_table[baud];
238 clkmode = clkmode_table[baud];
239 div = div_table[baud];
240 if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
241 /* special treatment for TT, where rates >= 38400 are done via TRxC */
242 clksrc = 0x28; /* TRxC */
243 clkmode = baud == 6 ? 0xc0 :
244 baud == 7 ? 0x80 : /* really 76800bps */
245 0x40; /* really 153600bps */
246 div = 0;
247 }
248
249 reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
250 reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
251
252 (void)scc.cha_b_ctrl; /* reset reg pointer */
253 SCC_WRITE( 9, 0xc0 ); /* reset */
254 LONG_DELAY(); /* extra delay after WR9 access */
255 SCC_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
256 0x04 /* 1 stopbit */ |
257 clkmode );
258 SCC_WRITE( 3, reg3 );
259 SCC_WRITE( 5, reg5 );
260 SCC_WRITE( 9, 0 ); /* no interrupts */
261 LONG_DELAY(); /* extra delay after WR9 access */
262 SCC_WRITE( 10, 0 ); /* NRZ mode */
263 SCC_WRITE( 11, clksrc ); /* main clock source */
264 SCC_WRITE( 12, div ); /* BRG value */
265 SCC_WRITE( 13, 0 ); /* BRG high byte */
266 SCC_WRITE( 14, brgsrc_table[baud] );
267 SCC_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) );
268 SCC_WRITE( 3, reg3 | 1 );
269 SCC_WRITE( 5, reg5 | 8 );
270
271 atari_SCC_reset_done = 1;
272 atari_SCC_init_done = 1;
273}
274
275#ifndef CONFIG_SERIAL_CONSOLE
276static void __init atari_init_midi_port( int cflag )
277#else
278void atari_init_midi_port( int cflag )
279#endif
280{
281 int baud = cflag & CBAUD;
282 int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
283 /* warning 7N1 isn't possible! (instead 7O2 is used...) */
284 int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
285 int div;
286
287 /* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
288 * default) the standard MIDI speed 31250. */
289 if (cflag & CBAUDEX)
290 baud += B38400;
291 if (baud == B4800)
292 div = ACIA_DIV64; /* really 7812.5 bps */
293 else if (baud == B38400+2 /* 115200 */)
294 div = ACIA_DIV1; /* really 500 kbps (does that work??) */
295 else
296 div = ACIA_DIV16; /* 31250 bps, standard for MIDI */
297
298 /* RTS low, ints disabled */
299 acia.mid_ctrl = div | csize | parity |
300 ((atari_switches & ATARI_SWITCH_MIDI) ?
301 ACIA_RHTID : ACIA_RLTID);
302}
303
304void __init atari_debug_init(void)
305{
306 if (!strcmp( m68k_debug_device, "ser" )) {
307 /* defaults to ser2 for a Falcon and ser1 otherwise */
308 strcpy( m68k_debug_device, MACH_IS_FALCON ? "ser2" : "ser1" );
309
310 }
311
312 if (!strcmp( m68k_debug_device, "ser1" )) {
313 /* ST-MFP Modem1 serial port */
314 atari_init_mfp_port( B9600|CS8 );
315 atari_console_driver.write = atari_mfp_console_write;
316 }
317 else if (!strcmp( m68k_debug_device, "ser2" )) {
318 /* SCC Modem2 serial port */
319 atari_init_scc_port( B9600|CS8 );
320 atari_console_driver.write = atari_scc_console_write;
321 }
322 else if (!strcmp( m68k_debug_device, "midi" )) {
323 /* MIDI port */
324 atari_init_midi_port( B9600|CS8 );
325 atari_console_driver.write = atari_midi_console_write;
326 }
327 else if (!strcmp( m68k_debug_device, "par" )) {
328 /* parallel printer */
329 atari_turnoff_irq( IRQ_MFP_BUSY ); /* avoid ints */
330 sound_ym.rd_data_reg_sel = 7; /* select mixer control */
331 sound_ym.wd_data = 0xff; /* sound off, ports are output */
332 sound_ym.rd_data_reg_sel = 15; /* select port B */
333 sound_ym.wd_data = 0; /* no char */
334 sound_ym.rd_data_reg_sel = 14; /* select port A */
335 sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
336 atari_console_driver.write = atari_par_console_write;
337 }
338 if (atari_console_driver.write)
339 register_console(&atari_console_driver);
340}
341
342/*
343 * Local variables:
344 * c-indent-level: 4
345 * tab-width: 8
346 * End:
347 */
diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c
new file mode 100644
index 000000000000..8888debf71ec
--- /dev/null
+++ b/arch/m68k/atari/hades-pci.c
@@ -0,0 +1,444 @@
1/*
2 * hades-pci.c - Hardware specific PCI BIOS functions the Hades Atari clone.
3 *
4 * Written by Wout Klaren.
5 */
6
7#include <linux/config.h>
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <asm/io.h>
11
12#if 0
13# define DBG_DEVS(args) printk args
14#else
15# define DBG_DEVS(args)
16#endif
17
18#if defined(CONFIG_PCI) && defined(CONFIG_HADES)
19
20#include <linux/slab.h>
21#include <linux/mm.h>
22#include <linux/pci.h>
23
24#include <asm/atarihw.h>
25#include <asm/atariints.h>
26#include <asm/byteorder.h>
27#include <asm/pci.h>
28
29#define HADES_MEM_BASE 0x80000000
30#define HADES_MEM_SIZE 0x20000000
31#define HADES_CONFIG_BASE 0xA0000000
32#define HADES_CONFIG_SIZE 0x10000000
33#define HADES_IO_BASE 0xB0000000
34#define HADES_IO_SIZE 0x10000000
35#define HADES_VIRT_IO_SIZE 0x00010000 /* Only 64k is remapped and actually used. */
36
37#define N_SLOTS 4 /* Number of PCI slots. */
38
39static const char pci_mem_name[] = "PCI memory space";
40static const char pci_io_name[] = "PCI I/O space";
41static const char pci_config_name[] = "PCI config space";
42
43static struct resource config_space = {
44 .name = pci_config_name,
45 .start = HADES_CONFIG_BASE,
46 .end = HADES_CONFIG_BASE + HADES_CONFIG_SIZE - 1
47};
48static struct resource io_space = {
49 .name = pci_io_name,
50 .start = HADES_IO_BASE,
51 .end = HADES_IO_BASE + HADES_IO_SIZE - 1
52};
53
54static const unsigned long pci_conf_base_phys[] = {
55 0xA0080000, 0xA0040000, 0xA0020000, 0xA0010000
56};
57static unsigned long pci_conf_base_virt[N_SLOTS];
58static unsigned long pci_io_base_virt;
59
60/*
61 * static void *mk_conf_addr(unsigned char bus, unsigned char device_fn,
62 * unsigned char where)
63 *
64 * Calculate the address of the PCI configuration area of the given
65 * device.
66 *
67 * BUG: boards with multiple functions are probably not correctly
68 * supported.
69 */
70
71static void *mk_conf_addr(struct pci_dev *dev, int where)
72{
73 int device = dev->devfn >> 3, function = dev->devfn & 7;
74 void *result;
75
76 DBG_DEVS(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p)\n",
77 dev->bus->number, dev->devfn, where, pci_addr));
78
79 if (device > 3)
80 {
81 DBG_DEVS(("mk_conf_addr: device (%d) > 3, returning NULL\n", device));
82 return NULL;
83 }
84
85 if (dev->bus->number != 0)
86 {
87 DBG_DEVS(("mk_conf_addr: bus (%d) > 0, returning NULL\n", device));
88 return NULL;
89 }
90
91 result = (void *) (pci_conf_base_virt[device] | (function << 8) | (where));
92 DBG_DEVS(("mk_conf_addr: returning pci_addr 0x%lx\n", (unsigned long) result));
93 return result;
94}
95
96static int hades_read_config_byte(struct pci_dev *dev, int where, u8 *value)
97{
98 volatile unsigned char *pci_addr;
99
100 *value = 0xff;
101
102 if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL)
103 return PCIBIOS_DEVICE_NOT_FOUND;
104
105 *value = *pci_addr;
106
107 return PCIBIOS_SUCCESSFUL;
108}
109
110static int hades_read_config_word(struct pci_dev *dev, int where, u16 *value)
111{
112 volatile unsigned short *pci_addr;
113
114 *value = 0xffff;
115
116 if (where & 0x1)
117 return PCIBIOS_BAD_REGISTER_NUMBER;
118
119 if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL)
120 return PCIBIOS_DEVICE_NOT_FOUND;
121
122 *value = le16_to_cpu(*pci_addr);
123
124 return PCIBIOS_SUCCESSFUL;
125}
126
127static int hades_read_config_dword(struct pci_dev *dev, int where, u32 *value)
128{
129 volatile unsigned int *pci_addr;
130 unsigned char header_type;
131 int result;
132
133 *value = 0xffffffff;
134
135 if (where & 0x3)
136 return PCIBIOS_BAD_REGISTER_NUMBER;
137
138 if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL)
139 return PCIBIOS_DEVICE_NOT_FOUND;
140
141 *value = le32_to_cpu(*pci_addr);
142
143 /*
144 * Check if the value is an address on the bus. If true, add the
145 * base address of the PCI memory or PCI I/O area on the Hades.
146 */
147
148 if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE,
149 &header_type)) != PCIBIOS_SUCCESSFUL)
150 return result;
151
152 if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) ||
153 ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) &&
154 (where <= PCI_BASE_ADDRESS_5))))
155 {
156 if ((*value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
157 {
158 /*
159 * Base address register that contains an I/O address. If the
160 * address is valid on the Hades (0 <= *value < HADES_VIRT_IO_SIZE),
161 * add 'pci_io_base_virt' to the value.
162 */
163
164 if (*value < HADES_VIRT_IO_SIZE)
165 *value += pci_io_base_virt;
166 }
167 else
168 {
169 /*
170 * Base address register that contains an memory address. If the
171 * address is valid on the Hades (0 <= *value < HADES_MEM_SIZE),
172 * add HADES_MEM_BASE to the value.
173 */
174
175 if (*value == 0)
176 {
177 /*
178 * Base address is 0. Test if this base
179 * address register is used.
180 */
181
182 *pci_addr = 0xffffffff;
183 if (*pci_addr != 0)
184 {
185 *pci_addr = *value;
186 if (*value < HADES_MEM_SIZE)
187 *value += HADES_MEM_BASE;
188 }
189 }
190 else
191 {
192 if (*value < HADES_MEM_SIZE)
193 *value += HADES_MEM_BASE;
194 }
195 }
196 }
197
198 return PCIBIOS_SUCCESSFUL;
199}
200
201static int hades_write_config_byte(struct pci_dev *dev, int where, u8 value)
202{
203 volatile unsigned char *pci_addr;
204
205 if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL)
206 return PCIBIOS_DEVICE_NOT_FOUND;
207
208 *pci_addr = value;
209
210 return PCIBIOS_SUCCESSFUL;
211}
212
213static int hades_write_config_word(struct pci_dev *dev, int where, u16 value)
214{
215 volatile unsigned short *pci_addr;
216
217 if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL)
218 return PCIBIOS_DEVICE_NOT_FOUND;
219
220 *pci_addr = cpu_to_le16(value);
221
222 return PCIBIOS_SUCCESSFUL;
223}
224
225static int hades_write_config_dword(struct pci_dev *dev, int where, u32 value)
226{
227 volatile unsigned int *pci_addr;
228 unsigned char header_type;
229 int result;
230
231 if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL)
232 return PCIBIOS_DEVICE_NOT_FOUND;
233
234 /*
235 * Check if the value is an address on the bus. If true, subtract the
236 * base address of the PCI memory or PCI I/O area on the Hades.
237 */
238
239 if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE,
240 &header_type)) != PCIBIOS_SUCCESSFUL)
241 return result;
242
243 if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) ||
244 ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) &&
245 (where <= PCI_BASE_ADDRESS_5))))
246 {
247 if ((value & PCI_BASE_ADDRESS_SPACE) ==
248 PCI_BASE_ADDRESS_SPACE_IO)
249 {
250 /*
251 * I/O address. Check if the address is valid address on
252 * the Hades (pci_io_base_virt <= value < pci_io_base_virt +
253 * HADES_VIRT_IO_SIZE) or if the value is 0xffffffff. If not
254 * true do not write the base address register. If it is a
255 * valid base address subtract 'pci_io_base_virt' from the value.
256 */
257
258 if ((value >= pci_io_base_virt) && (value < (pci_io_base_virt +
259 HADES_VIRT_IO_SIZE)))
260 value -= pci_io_base_virt;
261 else
262 {
263 if (value != 0xffffffff)
264 return PCIBIOS_SET_FAILED;
265 }
266 }
267 else
268 {
269 /*
270 * Memory address. Check if the address is valid address on
271 * the Hades (HADES_MEM_BASE <= value < HADES_MEM_BASE + HADES_MEM_SIZE) or
272 * if the value is 0xffffffff. If not true do not write
273 * the base address register. If it is a valid base address
274 * subtract HADES_MEM_BASE from the value.
275 */
276
277 if ((value >= HADES_MEM_BASE) && (value < (HADES_MEM_BASE + HADES_MEM_SIZE)))
278 value -= HADES_MEM_BASE;
279 else
280 {
281 if (value != 0xffffffff)
282 return PCIBIOS_SET_FAILED;
283 }
284 }
285 }
286
287 *pci_addr = cpu_to_le32(value);
288
289 return PCIBIOS_SUCCESSFUL;
290}
291
292/*
293 * static inline void hades_fixup(void)
294 *
295 * Assign IRQ numbers as used by Linux to the interrupt pins
296 * of the PCI cards.
297 */
298
299static void __init hades_fixup(int pci_modify)
300{
301 char irq_tab[4] = {
302 [0] = IRQ_TT_MFP_IO0, /* Slot 0. */
303 [1] = IRQ_TT_MFP_IO1, /* Slot 1. */
304 [2] = IRQ_TT_MFP_SCC, /* Slot 2. */
305 [3] = IRQ_TT_MFP_SCSIDMA /* Slot 3. */
306 };
307 struct pci_dev *dev = NULL;
308 unsigned char slot;
309
310 /*
311 * Go through all devices, fixing up irqs as we see fit:
312 */
313
314 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
315 {
316 if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
317 {
318 slot = PCI_SLOT(dev->devfn); /* Determine slot number. */
319 dev->irq = irq_tab[slot];
320 if (pci_modify)
321 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
322 }
323 }
324}
325
326/*
327 * static void hades_conf_device(struct pci_dev *dev)
328 *
329 * Machine dependent Configure the given device.
330 *
331 * Parameters:
332 *
333 * dev - the pci device.
334 */
335
336static void __init hades_conf_device(struct pci_dev *dev)
337{
338 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0);
339}
340
341static struct pci_ops hades_pci_ops = {
342 .read_byte = hades_read_config_byte,
343 .read_word = hades_read_config_word,
344 .read_dword = hades_read_config_dword,
345 .write_byte = hades_write_config_byte,
346 .write_word = hades_write_config_word,
347 .write_dword = hades_write_config_dword
348};
349
350/*
351 * struct pci_bus_info *init_hades_pci(void)
352 *
353 * Machine specific initialisation:
354 *
355 * - Allocate and initialise a 'pci_bus_info' structure
356 * - Initialise hardware
357 *
358 * Result: pointer to 'pci_bus_info' structure.
359 */
360
361struct pci_bus_info * __init init_hades_pci(void)
362{
363 struct pci_bus_info *bus;
364 int i;
365
366 /*
367 * Remap I/O and configuration space.
368 */
369
370 pci_io_base_virt = (unsigned long) ioremap(HADES_IO_BASE, HADES_VIRT_IO_SIZE);
371
372 for (i = 0; i < N_SLOTS; i++)
373 pci_conf_base_virt[i] = (unsigned long) ioremap(pci_conf_base_phys[i], 0x10000);
374
375 /*
376 * Allocate memory for bus info structure.
377 */
378
379 bus = kmalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
380 if (!bus)
381 return NULL;
382 memset(bus, 0, sizeof(struct pci_bus_info));
383
384 /*
385 * Claim resources. The m68k has no separate I/O space, both
386 * PCI memory space and PCI I/O space are in memory space. Therefore
387 * the I/O resources are requested in memory space as well.
388 */
389
390 if (request_resource(&iomem_resource, &config_space) != 0)
391 {
392 kfree(bus);
393 return NULL;
394 }
395
396 if (request_resource(&iomem_resource, &io_space) != 0)
397 {
398 release_resource(&config_space);
399 kfree(bus);
400 return NULL;
401 }
402
403 bus->mem_space.start = HADES_MEM_BASE;
404 bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
405 bus->mem_space.name = pci_mem_name;
406#if 1
407 if (request_resource(&iomem_resource, &bus->mem_space) != 0)
408 {
409 release_resource(&io_space);
410 release_resource(&config_space);
411 kfree(bus);
412 return NULL;
413 }
414#endif
415 bus->io_space.start = pci_io_base_virt;
416 bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
417 bus->io_space.name = pci_io_name;
418#if 1
419 if (request_resource(&ioport_resource, &bus->io_space) != 0)
420 {
421 release_resource(&bus->mem_space);
422 release_resource(&io_space);
423 release_resource(&config_space);
424 kfree(bus);
425 return NULL;
426 }
427#endif
428 /*
429 * Set hardware dependent functions.
430 */
431
432 bus->m68k_pci_ops = &hades_pci_ops;
433 bus->fixup = hades_fixup;
434 bus->conf_device = hades_conf_device;
435
436 /*
437 * Select high to low edge for PCI interrupts.
438 */
439
440 tt_mfp.active_edge &= ~0x27;
441
442 return bus;
443}
444#endif
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
new file mode 100644
index 000000000000..288f5e6a124e
--- /dev/null
+++ b/arch/m68k/atari/stdma.c
@@ -0,0 +1,196 @@
1/*
2 * linux/arch/m68k/atari/stmda.c
3 *
4 * Copyright (C) 1994 Roman Hodek
5 *
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive
9 * for more details.
10 */
11
12
13/* This file contains some function for controlling the access to the */
14/* ST-DMA chip that may be shared between devices. Currently we have: */
15/* TT: Floppy and ACSI bus */
16/* Falcon: Floppy and SCSI */
17/* */
18/* The controlling functions set up a wait queue for access to the */
19/* ST-DMA chip. Callers to stdma_lock() that cannot granted access are */
20/* put onto a queue and waked up later if the owner calls */
21/* stdma_release(). Additionally, the caller gives his interrupt */
22/* service routine to stdma_lock(). */
23/* */
24/* On the Falcon, the IDE bus uses just the ACSI/Floppy interrupt, but */
25/* not the ST-DMA chip itself. So falhd.c needs not to lock the */
26/* chip. The interrupt is routed to falhd.c if IDE is configured, the */
27/* model is a Falcon and the interrupt was caused by the HD controller */
28/* (can be determined by looking at its status register). */
29
30
31#include <linux/types.h>
32#include <linux/kdev_t.h>
33#include <linux/genhd.h>
34#include <linux/sched.h>
35#include <linux/init.h>
36#include <linux/interrupt.h>
37#include <linux/wait.h>
38
39#include <asm/atari_stdma.h>
40#include <asm/atariints.h>
41#include <asm/atarihw.h>
42#include <asm/io.h>
43#include <asm/irq.h>
44
45static int stdma_locked; /* the semaphore */
46 /* int func to be called */
47static irqreturn_t (*stdma_isr)(int, void *, struct pt_regs *);
48static void *stdma_isr_data; /* data passed to isr */
49static DECLARE_WAIT_QUEUE_HEAD(stdma_wait); /* wait queue for ST-DMA */
50
51
52
53
54/***************************** Prototypes *****************************/
55
56static irqreturn_t stdma_int (int irq, void *dummy, struct pt_regs *fp);
57
58/************************* End of Prototypes **************************/
59
60
61
62/*
63 * Function: void stdma_lock( isrfunc isr, void *data )
64 *
65 * Purpose: Tries to get a lock on the ST-DMA chip that is used by more
66 * then one device driver. Waits on stdma_wait until lock is free.
67 * stdma_lock() may not be called from an interrupt! You have to
68 * get the lock in your main routine and release it when your
69 * request is finished.
70 *
71 * Inputs: A interrupt function that is called until the lock is
72 * released.
73 *
74 * Returns: nothing
75 *
76 */
77
78void stdma_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *),
79 void *data)
80{
81 unsigned long flags;
82
83 local_irq_save(flags); /* protect lock */
84
85 /* Since the DMA is used for file system purposes, we
86 have to sleep uninterruptible (there may be locked
87 buffers) */
88 wait_event(stdma_wait, !stdma_locked);
89
90 stdma_locked = 1;
91 stdma_isr = handler;
92 stdma_isr_data = data;
93 local_irq_restore(flags);
94}
95
96
97/*
98 * Function: void stdma_release( void )
99 *
100 * Purpose: Releases the lock on the ST-DMA chip.
101 *
102 * Inputs: none
103 *
104 * Returns: nothing
105 *
106 */
107
108void stdma_release(void)
109{
110 unsigned long flags;
111
112 local_irq_save(flags);
113
114 stdma_locked = 0;
115 stdma_isr = NULL;
116 stdma_isr_data = NULL;
117 wake_up(&stdma_wait);
118
119 local_irq_restore(flags);
120}
121
122
123/*
124 * Function: int stdma_others_waiting( void )
125 *
126 * Purpose: Check if someone waits for the ST-DMA lock.
127 *
128 * Inputs: none
129 *
130 * Returns: 0 if no one is waiting, != 0 otherwise
131 *
132 */
133
134int stdma_others_waiting(void)
135{
136 return waitqueue_active(&stdma_wait);
137}
138
139
140/*
141 * Function: int stdma_islocked( void )
142 *
143 * Purpose: Check if the ST-DMA is currently locked.
144 * Note: Returned status is only valid if ints are disabled while calling and
145 * as long as they remain disabled.
146 * If called with ints enabled, status can change only from locked to
147 * unlocked, because ints may not lock the ST-DMA.
148 *
149 * Inputs: none
150 *
151 * Returns: != 0 if locked, 0 otherwise
152 *
153 */
154
155int stdma_islocked(void)
156{
157 return stdma_locked;
158}
159
160
161/*
162 * Function: void stdma_init( void )
163 *
164 * Purpose: Initialize the ST-DMA chip access controlling.
165 * It sets up the interrupt and its service routine. The int is registered
166 * as slow int, client devices have to live with that (no problem
167 * currently).
168 *
169 * Inputs: none
170 *
171 * Return: nothing
172 *
173 */
174
175void __init stdma_init(void)
176{
177 stdma_isr = NULL;
178 request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW,
179 "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
180}
181
182
183/*
184 * Function: void stdma_int()
185 *
186 * Purpose: The interrupt routine for the ST-DMA. It calls the isr
187 * registered by stdma_lock().
188 *
189 */
190
191static irqreturn_t stdma_int(int irq, void *dummy, struct pt_regs *fp)
192{
193 if (stdma_isr)
194 (*stdma_isr)(irq, stdma_isr_data, fp);
195 return IRQ_HANDLED;
196}
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
new file mode 100644
index 000000000000..5a3c106b40c8
--- /dev/null
+++ b/arch/m68k/atari/stram.c
@@ -0,0 +1,1247 @@
1/*
2 * arch/m68k/atari/stram.c: Functions for ST-RAM allocations
3 *
4 * Copyright 1994-97 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/config.h>
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/mm.h>
15#include <linux/kdev_t.h>
16#include <linux/major.h>
17#include <linux/init.h>
18#include <linux/swap.h>
19#include <linux/slab.h>
20#include <linux/vmalloc.h>
21#include <linux/pagemap.h>
22#include <linux/shm.h>
23#include <linux/bootmem.h>
24#include <linux/mount.h>
25#include <linux/blkdev.h>
26
27#include <asm/setup.h>
28#include <asm/machdep.h>
29#include <asm/page.h>
30#include <asm/pgtable.h>
31#include <asm/atarihw.h>
32#include <asm/atari_stram.h>
33#include <asm/io.h>
34#include <asm/semaphore.h>
35
36#include <linux/swapops.h>
37
38#undef DEBUG
39
40#ifdef DEBUG
41#define DPRINTK(fmt,args...) printk( fmt, ##args )
42#else
43#define DPRINTK(fmt,args...)
44#endif
45
46#if defined(CONFIG_PROC_FS) && defined(CONFIG_STRAM_PROC)
47/* abbrev for the && above... */
48#define DO_PROC
49#include <linux/proc_fs.h>
50#endif
51
52/* Pre-swapping comments:
53 *
54 * ++roman:
55 *
56 * New version of ST-Ram buffer allocation. Instead of using the
57 * 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000
58 * (1 MB granularity!), such buffers are reserved like this:
59 *
60 * - If the kernel resides in ST-Ram anyway, we can take the buffer
61 * from behind the current kernel data space the normal way
62 * (incrementing start_mem).
63 *
64 * - If the kernel is in TT-Ram, stram_init() initializes start and
65 * end of the available region. Buffers are allocated from there
66 * and mem_init() later marks the such used pages as reserved.
67 * Since each TT-Ram chunk is at least 4 MB in size, I hope there
68 * won't be an overrun of the ST-Ram region by normal kernel data
69 * space.
70 *
71 * For that, ST-Ram may only be allocated while kernel initialization
72 * is going on, or exactly: before mem_init() is called. There is also
73 * no provision now for freeing ST-Ram buffers. It seems that isn't
74 * really needed.
75 *
76 */
77
78/*
79 * New Nov 1997: Use ST-RAM as swap space!
80 *
81 * In the past, there were often problems with modules that require ST-RAM
82 * buffers. Such drivers have to use __get_dma_pages(), which unfortunately
83 * often isn't very successful in allocating more than 1 page :-( [1] The net
84 * result was that most of the time you couldn't insmod such modules (ataflop,
85 * ACSI, SCSI on Falcon, Atari internal framebuffer, not to speak of acsi_slm,
86 * which needs a 1 MB buffer... :-).
87 *
88 * To overcome this limitation, ST-RAM can now be turned into a very
89 * high-speed swap space. If a request for an ST-RAM buffer comes, the kernel
90 * now tries to unswap some pages on that swap device to make some free (and
91 * contiguous) space. This works much better in comparison to
92 * __get_dma_pages(), since used swap pages can be selectively freed by either
93 * moving them to somewhere else in swap space, or by reading them back into
94 * system memory. Ok, there operation of unswapping isn't really cheap (for
95 * each page, one has to go through the page tables of all processes), but it
96 * doesn't happen that often (only when allocation ST-RAM, i.e. when loading a
97 * module that needs ST-RAM). But it at least makes it possible to load such
98 * modules!
99 *
100 * It could also be that overall system performance increases a bit due to
101 * ST-RAM swapping, since slow ST-RAM isn't used anymore for holding data or
102 * executing code in. It's then just a (very fast, compared to disk) back
103 * storage for not-so-often needed data. (But this effect must be compared
104 * with the loss of total memory...) Don't know if the effect is already
105 * visible on a TT, where the speed difference between ST- and TT-RAM isn't
106 * that dramatic, but it should on machines where TT-RAM is really much faster
107 * (e.g. Afterburner).
108 *
109 * [1]: __get_free_pages() does a fine job if you only want one page, but if
110 * you want more (contiguous) pages, it can give you such a block only if
111 * there's already a free one. The algorithm can't try to free buffers or swap
112 * out something in order to make more free space, since all that page-freeing
113 * mechanisms work "target-less", i.e. they just free something, but not in a
114 * specific place. I.e., __get_free_pages() can't do anything to free
115 * *adjacent* pages :-( This situation becomes even worse for DMA memory,
116 * since the freeing algorithms are also blind to DMA capability of pages.
117 */
118
119/* 1998-10-20: ++andreas
120 unswap_by_move disabled because it does not handle swapped shm pages.
121*/
122
123/* 2000-05-01: ++andreas
124 Integrated with bootmem. Remove all traces of unswap_by_move.
125*/
126
127#ifdef CONFIG_STRAM_SWAP
128#define ALIGN_IF_SWAP(x) PAGE_ALIGN(x)
129#else
130#define ALIGN_IF_SWAP(x) (x)
131#endif
132
133/* get index of swap page at address 'addr' */
134#define SWAP_NR(addr) (((addr) - swap_start) >> PAGE_SHIFT)
135
136/* get address of swap page #'nr' */
137#define SWAP_ADDR(nr) (swap_start + ((nr) << PAGE_SHIFT))
138
139/* get number of pages for 'n' bytes (already page-aligned) */
140#define N_PAGES(n) ((n) >> PAGE_SHIFT)
141
142/* The following two numbers define the maximum fraction of ST-RAM in total
143 * memory, below that the kernel would automatically use ST-RAM as swap
144 * space. This decision can be overridden with stram_swap= */
145#define MAX_STRAM_FRACTION_NOM 1
146#define MAX_STRAM_FRACTION_DENOM 3
147
148/* Start and end (virtual) of ST-RAM */
149static void *stram_start, *stram_end;
150
151/* set after memory_init() executed and allocations via start_mem aren't
152 * possible anymore */
153static int mem_init_done;
154
155/* set if kernel is in ST-RAM */
156static int kernel_in_stram;
157
158typedef struct stram_block {
159 struct stram_block *next;
160 void *start;
161 unsigned long size;
162 unsigned flags;
163 const char *owner;
164} BLOCK;
165
166/* values for flags field */
167#define BLOCK_FREE 0x01 /* free structure in the BLOCKs pool */
168#define BLOCK_KMALLOCED 0x02 /* structure allocated by kmalloc() */
169#define BLOCK_GFP 0x08 /* block allocated with __get_dma_pages() */
170#define BLOCK_INSWAP 0x10 /* block allocated in swap space */
171
172/* list of allocated blocks */
173static BLOCK *alloc_list;
174
175/* We can't always use kmalloc() to allocate BLOCK structures, since
176 * stram_alloc() can be called rather early. So we need some pool of
177 * statically allocated structures. 20 of them is more than enough, so in most
178 * cases we never should need to call kmalloc(). */
179#define N_STATIC_BLOCKS 20
180static BLOCK static_blocks[N_STATIC_BLOCKS];
181
182#ifdef CONFIG_STRAM_SWAP
183/* max. number of bytes to use for swapping
184 * 0 = no ST-RAM swapping
185 * -1 = do swapping (to whole ST-RAM) if it's less than MAX_STRAM_FRACTION of
186 * total memory
187 */
188static int max_swap_size = -1;
189
190/* start and end of swapping area */
191static void *swap_start, *swap_end;
192
193/* The ST-RAM's swap info structure */
194static struct swap_info_struct *stram_swap_info;
195
196/* The ST-RAM's swap type */
197static int stram_swap_type;
198
199/* Semaphore for get_stram_region. */
200static DECLARE_MUTEX(stram_swap_sem);
201
202/* major and minor device number of the ST-RAM device; for the major, we use
203 * the same as Amiga z2ram, which is really similar and impossible on Atari,
204 * and for the minor a relatively odd number to avoid the user creating and
205 * using that device. */
206#define STRAM_MAJOR Z2RAM_MAJOR
207#define STRAM_MINOR 13
208
209/* Some impossible pointer value */
210#define MAGIC_FILE_P (struct file *)0xffffdead
211
212#ifdef DO_PROC
213static unsigned stat_swap_read;
214static unsigned stat_swap_write;
215static unsigned stat_swap_force;
216#endif /* DO_PROC */
217
218#endif /* CONFIG_STRAM_SWAP */
219
220/***************************** Prototypes *****************************/
221
222#ifdef CONFIG_STRAM_SWAP
223static int swap_init(void *start_mem, void *swap_data);
224static void *get_stram_region( unsigned long n_pages );
225static void free_stram_region( unsigned long offset, unsigned long n_pages
226 );
227static int in_some_region(void *addr);
228static unsigned long find_free_region( unsigned long n_pages, unsigned long
229 *total_free, unsigned long
230 *region_free );
231static void do_stram_request(request_queue_t *);
232static int stram_open( struct inode *inode, struct file *filp );
233static int stram_release( struct inode *inode, struct file *filp );
234static void reserve_region(void *start, void *end);
235#endif
236static BLOCK *add_region( void *addr, unsigned long size );
237static BLOCK *find_region( void *addr );
238static int remove_region( BLOCK *block );
239
240/************************* End of Prototypes **************************/
241
242
243/* ------------------------------------------------------------------------ */
244/* Public Interface */
245/* ------------------------------------------------------------------------ */
246
247/*
248 * This init function is called very early by atari/config.c
249 * It initializes some internal variables needed for stram_alloc()
250 */
251void __init atari_stram_init(void)
252{
253 int i;
254
255 /* initialize static blocks */
256 for( i = 0; i < N_STATIC_BLOCKS; ++i )
257 static_blocks[i].flags = BLOCK_FREE;
258
259 /* determine whether kernel code resides in ST-RAM (then ST-RAM is the
260 * first memory block at virtual 0x0) */
261 stram_start = phys_to_virt(0);
262 kernel_in_stram = (stram_start == 0);
263
264 for( i = 0; i < m68k_num_memory; ++i ) {
265 if (m68k_memory[i].addr == 0) {
266 /* skip first 2kB or page (supervisor-only!) */
267 stram_end = stram_start + m68k_memory[i].size;
268 return;
269 }
270 }
271 /* Should never come here! (There is always ST-Ram!) */
272 panic( "atari_stram_init: no ST-RAM found!" );
273}
274
275
276/*
277 * This function is called from setup_arch() to reserve the pages needed for
278 * ST-RAM management.
279 */
280void __init atari_stram_reserve_pages(void *start_mem)
281{
282#ifdef CONFIG_STRAM_SWAP
283 /* if max_swap_size is negative (i.e. no stram_swap= option given),
284 * determine at run time whether to use ST-RAM swapping */
285 if (max_swap_size < 0)
286 /* Use swapping if ST-RAM doesn't make up more than MAX_STRAM_FRACTION
287 * of total memory. In that case, the max. size is set to 16 MB,
288 * because ST-RAM can never be bigger than that.
289 * Also, never use swapping on a Hades, there's no separate ST-RAM in
290 * that machine. */
291 max_swap_size =
292 (!MACH_IS_HADES &&
293 (N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <=
294 ((unsigned long)high_memory>>PAGE_SHIFT)*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
295 DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size );
296#endif
297
298 /* always reserve first page of ST-RAM, the first 2 kB are
299 * supervisor-only! */
300 if (!kernel_in_stram)
301 reserve_bootmem (0, PAGE_SIZE);
302
303#ifdef CONFIG_STRAM_SWAP
304 {
305 void *swap_data;
306
307 start_mem = (void *) PAGE_ALIGN ((unsigned long) start_mem);
308 /* determine first page to use as swap: if the kernel is
309 in TT-RAM, this is the first page of (usable) ST-RAM;
310 otherwise just use the end of kernel data (= start_mem) */
311 swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : start_mem;
312 /* decrement by one page, rest of kernel assumes that first swap page
313 * is always reserved and maybe doesn't handle swp_entry == 0
314 * correctly */
315 swap_start -= PAGE_SIZE;
316 swap_end = stram_end;
317 if (swap_end-swap_start > max_swap_size)
318 swap_end = swap_start + max_swap_size;
319 DPRINTK( "atari_stram_reserve_pages: swapping enabled; "
320 "swap=%p-%p\n", swap_start, swap_end);
321
322 /* reserve some amount of memory for maintainance of
323 * swapping itself: one page for each 2048 (PAGE_SIZE/2)
324 * swap pages. (2 bytes for each page) */
325 swap_data = start_mem;
326 start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
327 >> (PAGE_SHIFT-1)) << PAGE_SHIFT;
328 /* correct swap_start if necessary */
329 if (swap_start + PAGE_SIZE == swap_data)
330 swap_start = start_mem - PAGE_SIZE;
331
332 if (!swap_init( start_mem, swap_data )) {
333 printk( KERN_ERR "ST-RAM swap space initialization failed\n" );
334 max_swap_size = 0;
335 return;
336 }
337 /* reserve region for swapping meta-data */
338 reserve_region(swap_data, start_mem);
339 /* reserve swapping area itself */
340 reserve_region(swap_start + PAGE_SIZE, swap_end);
341
342 /*
343 * If the whole ST-RAM is used for swapping, there are no allocatable
344 * dma pages left. But unfortunately, some shared parts of the kernel
345 * (particularly the SCSI mid-level) call __get_dma_pages()
346 * unconditionally :-( These calls then fail, and scsi.c even doesn't
347 * check for NULL return values and just crashes. The quick fix for
348 * this (instead of doing much clean up work in the SCSI code) is to
349 * pretend all pages are DMA-able by setting mach_max_dma_address to
350 * ULONG_MAX. This doesn't change any functionality so far, since
351 * get_dma_pages() shouldn't be used on Atari anyway anymore (better
352 * use atari_stram_alloc()), and the Atari SCSI drivers don't need DMA
353 * memory. But unfortunately there's now no kind of warning (even not
354 * a NULL return value) if you use get_dma_pages() nevertheless :-(
355 * You just will get non-DMA-able memory...
356 */
357 mach_max_dma_address = 0xffffffff;
358 }
359#endif
360}
361
362void atari_stram_mem_init_hook (void)
363{
364 mem_init_done = 1;
365}
366
367
368/*
369 * This is main public interface: somehow allocate a ST-RAM block
370 * There are three strategies:
371 *
372 * - If we're before mem_init(), we have to make a static allocation. The
373 * region is taken in the kernel data area (if the kernel is in ST-RAM) or
374 * from the start of ST-RAM (if the kernel is in TT-RAM) and added to the
375 * rsvd_stram_* region. The ST-RAM is somewhere in the middle of kernel
376 * address space in the latter case.
377 *
378 * - If mem_init() already has been called and ST-RAM swapping is enabled,
379 * try to get the memory from the (pseudo) swap-space, either free already
380 * or by moving some other pages out of the swap.
381 *
382 * - If mem_init() already has been called, and ST-RAM swapping is not
383 * enabled, the only possibility is to try with __get_dma_pages(). This has
384 * the disadvantage that it's very hard to get more than 1 page, and it is
385 * likely to fail :-(
386 *
387 */
388void *atari_stram_alloc(long size, const char *owner)
389{
390 void *addr = NULL;
391 BLOCK *block;
392 int flags;
393
394 DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
395
396 size = ALIGN_IF_SWAP(size);
397 DPRINTK( "atari_stram_alloc: rounded size = %08lx\n", size );
398#ifdef CONFIG_STRAM_SWAP
399 if (max_swap_size) {
400 /* If swapping is active: make some free space in the swap
401 "device". */
402 DPRINTK( "atari_stram_alloc: after mem_init, swapping ok, "
403 "calling get_region\n" );
404 addr = get_stram_region( N_PAGES(size) );
405 flags = BLOCK_INSWAP;
406 }
407 else
408#endif
409 if (!mem_init_done)
410 return alloc_bootmem_low(size);
411 else {
412 /* After mem_init() and no swapping: can only resort to
413 * __get_dma_pages() */
414 addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
415 flags = BLOCK_GFP;
416 DPRINTK( "atari_stram_alloc: after mem_init, swapping off, "
417 "get_pages=%p\n", addr );
418 }
419
420 if (addr) {
421 if (!(block = add_region( addr, size ))) {
422 /* out of memory for BLOCK structure :-( */
423 DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
424 "freeing again\n" );
425#ifdef CONFIG_STRAM_SWAP
426 if (flags == BLOCK_INSWAP)
427 free_stram_region( SWAP_NR(addr), N_PAGES(size) );
428 else
429#endif
430 free_pages((unsigned long)addr, get_order(size));
431 return( NULL );
432 }
433 block->owner = owner;
434 block->flags |= flags;
435 }
436 return( addr );
437}
438
439void atari_stram_free( void *addr )
440
441{
442 BLOCK *block;
443
444 DPRINTK( "atari_stram_free(addr=%p)\n", addr );
445
446 if (!(block = find_region( addr ))) {
447 printk( KERN_ERR "Attempt to free non-allocated ST-RAM block at %p "
448 "from %p\n", addr, __builtin_return_address(0) );
449 return;
450 }
451 DPRINTK( "atari_stram_free: found block (%p): size=%08lx, owner=%s, "
452 "flags=%02x\n", block, block->size, block->owner, block->flags );
453
454#ifdef CONFIG_STRAM_SWAP
455 if (!max_swap_size) {
456#endif
457 if (block->flags & BLOCK_GFP) {
458 DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
459 get_order(block->size));
460 free_pages((unsigned long)addr, get_order(block->size));
461 }
462 else
463 goto fail;
464#ifdef CONFIG_STRAM_SWAP
465 }
466 else if (block->flags & BLOCK_INSWAP) {
467 DPRINTK( "atari_stram_free: is swap-alloced\n" );
468 free_stram_region( SWAP_NR(block->start), N_PAGES(block->size) );
469 }
470 else
471 goto fail;
472#endif
473 remove_region( block );
474 return;
475
476 fail:
477 printk( KERN_ERR "atari_stram_free: cannot free block at %p "
478 "(called from %p)\n", addr, __builtin_return_address(0) );
479}
480
481
482#ifdef CONFIG_STRAM_SWAP
483
484
485/* ------------------------------------------------------------------------ */
486/* Main Swapping Functions */
487/* ------------------------------------------------------------------------ */
488
489
490/*
491 * Initialize ST-RAM swap device
492 * (lots copied and modified from sys_swapon() in mm/swapfile.c)
493 */
494static int __init swap_init(void *start_mem, void *swap_data)
495{
496 static struct dentry fake_dentry;
497 static struct vfsmount fake_vfsmnt;
498 struct swap_info_struct *p;
499 struct inode swap_inode;
500 unsigned int type;
501 void *addr;
502 int i, j, k, prev;
503
504 DPRINTK("swap_init(start_mem=%p, swap_data=%p)\n",
505 start_mem, swap_data);
506
507 /* need at least one page for swapping to (and this also isn't very
508 * much... :-) */
509 if (swap_end - swap_start < 2*PAGE_SIZE) {
510 printk( KERN_WARNING "stram_swap_init: swap space too small\n" );
511 return( 0 );
512 }
513
514 /* find free slot in swap_info */
515 for( p = swap_info, type = 0; type < nr_swapfiles; type++, p++ )
516 if (!(p->flags & SWP_USED))
517 break;
518 if (type >= MAX_SWAPFILES) {
519 printk( KERN_WARNING "stram_swap_init: max. number of "
520 "swap devices exhausted\n" );
521 return( 0 );
522 }
523 if (type >= nr_swapfiles)
524 nr_swapfiles = type+1;
525
526 stram_swap_info = p;
527 stram_swap_type = type;
528
529 /* fake some dir cache entries to give us some name in /dev/swaps */
530 fake_dentry.d_parent = &fake_dentry;
531 fake_dentry.d_name.name = "stram (internal)";
532 fake_dentry.d_name.len = 16;
533 fake_vfsmnt.mnt_parent = &fake_vfsmnt;
534
535 p->flags = SWP_USED;
536 p->swap_file = &fake_dentry;
537 p->swap_vfsmnt = &fake_vfsmnt;
538 p->swap_map = swap_data;
539 p->cluster_nr = 0;
540 p->next = -1;
541 p->prio = 0x7ff0; /* a rather high priority, but not the higest
542 * to give the user a chance to override */
543
544 /* call stram_open() directly, avoids at least the overhead in
545 * constructing a dummy file structure... */
546 swap_inode.i_rdev = MKDEV( STRAM_MAJOR, STRAM_MINOR );
547 stram_open( &swap_inode, MAGIC_FILE_P );
548 p->max = SWAP_NR(swap_end);
549
550 /* initialize swap_map: set regions that are already allocated or belong
551 * to kernel data space to SWAP_MAP_BAD, otherwise to free */
552 j = 0; /* # of free pages */
553 k = 0; /* # of already allocated pages (from pre-mem_init stram_alloc()) */
554 p->lowest_bit = 0;
555 p->highest_bit = 0;
556 for( i = 1, addr = SWAP_ADDR(1); i < p->max;
557 i++, addr += PAGE_SIZE ) {
558 if (in_some_region( addr )) {
559 p->swap_map[i] = SWAP_MAP_BAD;
560 ++k;
561 }
562 else if (kernel_in_stram && addr < start_mem ) {
563 p->swap_map[i] = SWAP_MAP_BAD;
564 }
565 else {
566 p->swap_map[i] = 0;
567 ++j;
568 if (!p->lowest_bit) p->lowest_bit = i;
569 p->highest_bit = i;
570 }
571 }
572 /* first page always reserved (and doesn't really belong to swap space) */
573 p->swap_map[0] = SWAP_MAP_BAD;
574
575 /* now swapping to this device ok */
576 p->pages = j + k;
577 swap_list_lock();
578 nr_swap_pages += j;
579 p->flags = SWP_WRITEOK;
580
581 /* insert swap space into swap_list */
582 prev = -1;
583 for (i = swap_list.head; i >= 0; i = swap_info[i].next) {
584 if (p->prio >= swap_info[i].prio) {
585 break;
586 }
587 prev = i;
588 }
589 p->next = i;
590 if (prev < 0) {
591 swap_list.head = swap_list.next = p - swap_info;
592 } else {
593 swap_info[prev].next = p - swap_info;
594 }
595 swap_list_unlock();
596
597 printk( KERN_INFO "Using %dk (%d pages) of ST-RAM as swap space.\n",
598 p->pages << 2, p->pages );
599 return( 1 );
600}
601
602
603/*
604 * The swap entry has been read in advance, and we return 1 to indicate
605 * that the page has been used or is no longer needed.
606 *
607 * Always set the resulting pte to be nowrite (the same as COW pages
608 * after one process has exited). We don't know just how many PTEs will
609 * share this swap entry, so be cautious and let do_wp_page work out
610 * what to do if a write is requested later.
611 */
612static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
613 address, pte_t *dir, swp_entry_t entry,
614 struct page *page)
615{
616 pte_t pte = *dir;
617
618 if (pte_none(pte))
619 return;
620 if (pte_present(pte)) {
621 /* If this entry is swap-cached, then page must already
622 hold the right address for any copies in physical
623 memory */
624 if (pte_page(pte) != page)
625 return;
626 /* We will be removing the swap cache in a moment, so... */
627 set_pte(dir, pte_mkdirty(pte));
628 return;
629 }
630 if (pte_val(pte) != entry.val)
631 return;
632
633 DPRINTK("unswap_pte: replacing entry %08lx by new page %p",
634 entry.val, page);
635 set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
636 swap_free(entry);
637 get_page(page);
638 inc_mm_counter(vma->vm_mm, rss);
639}
640
641static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
642 unsigned long address, unsigned long size,
643 unsigned long offset, swp_entry_t entry,
644 struct page *page)
645{
646 pte_t * pte;
647 unsigned long end;
648
649 if (pmd_none(*dir))
650 return;
651 if (pmd_bad(*dir)) {
652 pmd_ERROR(*dir);
653 pmd_clear(dir);
654 return;
655 }
656 pte = pte_offset_kernel(dir, address);
657 offset += address & PMD_MASK;
658 address &= ~PMD_MASK;
659 end = address + size;
660 if (end > PMD_SIZE)
661 end = PMD_SIZE;
662 do {
663 unswap_pte(vma, offset+address-vma->vm_start, pte, entry, page);
664 address += PAGE_SIZE;
665 pte++;
666 } while (address < end);
667}
668
669static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
670 unsigned long address, unsigned long size,
671 swp_entry_t entry, struct page *page)
672{
673 pmd_t * pmd;
674 unsigned long offset, end;
675
676 if (pgd_none(*dir))
677 return;
678 if (pgd_bad(*dir)) {
679 pgd_ERROR(*dir);
680 pgd_clear(dir);
681 return;
682 }
683 pmd = pmd_offset(dir, address);
684 offset = address & PGDIR_MASK;
685 address &= ~PGDIR_MASK;
686 end = address + size;
687 if (end > PGDIR_SIZE)
688 end = PGDIR_SIZE;
689 do {
690 unswap_pmd(vma, pmd, address, end - address, offset, entry,
691 page);
692 address = (address + PMD_SIZE) & PMD_MASK;
693 pmd++;
694 } while (address < end);
695}
696
697static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir,
698 swp_entry_t entry, struct page *page)
699{
700 unsigned long start = vma->vm_start, end = vma->vm_end;
701
702 do {
703 unswap_pgd(vma, pgdir, start, end - start, entry, page);
704 start = (start + PGDIR_SIZE) & PGDIR_MASK;
705 pgdir++;
706 } while (start < end);
707}
708
709static void unswap_process(struct mm_struct * mm, swp_entry_t entry,
710 struct page *page)
711{
712 struct vm_area_struct* vma;
713
714 /*
715 * Go through process' page directory.
716 */
717 if (!mm)
718 return;
719 for (vma = mm->mmap; vma; vma = vma->vm_next) {
720 pgd_t * pgd = pgd_offset(mm, vma->vm_start);
721 unswap_vma(vma, pgd, entry, page);
722 }
723}
724
725
726static int unswap_by_read(unsigned short *map, unsigned long max,
727 unsigned long start, unsigned long n_pages)
728{
729 struct task_struct *p;
730 struct page *page;
731 swp_entry_t entry;
732 unsigned long i;
733
734 DPRINTK( "unswapping %lu..%lu by reading in\n",
735 start, start+n_pages-1 );
736
737 for( i = start; i < start+n_pages; ++i ) {
738 if (map[i] == SWAP_MAP_BAD) {
739 printk( KERN_ERR "get_stram_region: page %lu already "
740 "reserved??\n", i );
741 continue;
742 }
743
744 if (map[i]) {
745 entry = swp_entry(stram_swap_type, i);
746 DPRINTK("unswap: map[i=%lu]=%u nr_swap=%ld\n",
747 i, map[i], nr_swap_pages);
748
749 swap_device_lock(stram_swap_info);
750 map[i]++;
751 swap_device_unlock(stram_swap_info);
752 /* Get a page for the entry, using the existing
753 swap cache page if there is one. Otherwise,
754 get a clean page and read the swap into it. */
755 page = read_swap_cache_async(entry, NULL, 0);
756 if (!page) {
757 swap_free(entry);
758 return -ENOMEM;
759 }
760 read_lock(&tasklist_lock);
761 for_each_process(p)
762 unswap_process(p->mm, entry, page);
763 read_unlock(&tasklist_lock);
764 shmem_unuse(entry, page);
765 /* Now get rid of the extra reference to the
766 temporary page we've been using. */
767 if (PageSwapCache(page))
768 delete_from_swap_cache(page);
769 __free_page(page);
770 #ifdef DO_PROC
771 stat_swap_force++;
772 #endif
773 }
774
775 DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%ld\n",
776 i, map[i], nr_swap_pages );
777 swap_list_lock();
778 swap_device_lock(stram_swap_info);
779 map[i] = SWAP_MAP_BAD;
780 if (stram_swap_info->lowest_bit == i)
781 stram_swap_info->lowest_bit++;
782 if (stram_swap_info->highest_bit == i)
783 stram_swap_info->highest_bit--;
784 --nr_swap_pages;
785 swap_device_unlock(stram_swap_info);
786 swap_list_unlock();
787 }
788
789 return 0;
790}
791
792/*
793 * reserve a region in ST-RAM swap space for an allocation
794 */
795static void *get_stram_region( unsigned long n_pages )
796{
797 unsigned short *map = stram_swap_info->swap_map;
798 unsigned long max = stram_swap_info->max;
799 unsigned long start, total_free, region_free;
800 int err;
801 void *ret = NULL;
802
803 DPRINTK( "get_stram_region(n_pages=%lu)\n", n_pages );
804
805 down(&stram_swap_sem);
806
807 /* disallow writing to the swap device now */
808 stram_swap_info->flags = SWP_USED;
809
810 /* find a region of n_pages pages in the swap space including as much free
811 * pages as possible (and excluding any already-reserved pages). */
812 if (!(start = find_free_region( n_pages, &total_free, &region_free )))
813 goto end;
814 DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n",
815 start, region_free );
816
817 err = unswap_by_read(map, max, start, n_pages);
818 if (err)
819 goto end;
820
821 ret = SWAP_ADDR(start);
822 end:
823 /* allow using swap device again */
824 stram_swap_info->flags = SWP_WRITEOK;
825 up(&stram_swap_sem);
826 DPRINTK( "get_stram_region: returning %p\n", ret );
827 return( ret );
828}
829
830
831/*
832 * free a reserved region in ST-RAM swap space
833 */
834static void free_stram_region( unsigned long offset, unsigned long n_pages )
835{
836 unsigned short *map = stram_swap_info->swap_map;
837
838 DPRINTK( "free_stram_region(offset=%lu,n_pages=%lu)\n", offset, n_pages );
839
840 if (offset < 1 || offset + n_pages > stram_swap_info->max) {
841 printk( KERN_ERR "free_stram_region: Trying to free non-ST-RAM\n" );
842 return;
843 }
844
845 swap_list_lock();
846 swap_device_lock(stram_swap_info);
847 /* un-reserve the freed pages */
848 for( ; n_pages > 0; ++offset, --n_pages ) {
849 if (map[offset] != SWAP_MAP_BAD)
850 printk( KERN_ERR "free_stram_region: Swap page %lu was not "
851 "reserved\n", offset );
852 map[offset] = 0;
853 }
854
855 /* update swapping meta-data */
856 if (offset < stram_swap_info->lowest_bit)
857 stram_swap_info->lowest_bit = offset;
858 if (offset+n_pages-1 > stram_swap_info->highest_bit)
859 stram_swap_info->highest_bit = offset+n_pages-1;
860 if (stram_swap_info->prio > swap_info[swap_list.next].prio)
861 swap_list.next = swap_list.head;
862 nr_swap_pages += n_pages;
863 swap_device_unlock(stram_swap_info);
864 swap_list_unlock();
865}
866
867
868/* ------------------------------------------------------------------------ */
869/* Utility Functions for Swapping */
870/* ------------------------------------------------------------------------ */
871
872
873/* is addr in some of the allocated regions? */
874static int in_some_region(void *addr)
875{
876 BLOCK *p;
877
878 for( p = alloc_list; p; p = p->next ) {
879 if (p->start <= addr && addr < p->start + p->size)
880 return( 1 );
881 }
882 return( 0 );
883}
884
885
886static unsigned long find_free_region(unsigned long n_pages,
887 unsigned long *total_free,
888 unsigned long *region_free)
889{
890 unsigned short *map = stram_swap_info->swap_map;
891 unsigned long max = stram_swap_info->max;
892 unsigned long head, tail, max_start;
893 long nfree, max_free;
894
895 /* first scan the swap space for a suitable place for the allocation */
896 head = 1;
897 max_start = 0;
898 max_free = -1;
899 *total_free = 0;
900
901 start_over:
902 /* increment tail until final window size reached, and count free pages */
903 nfree = 0;
904 for( tail = head; tail-head < n_pages && tail < max; ++tail ) {
905 if (map[tail] == SWAP_MAP_BAD) {
906 head = tail+1;
907 goto start_over;
908 }
909 if (!map[tail]) {
910 ++nfree;
911 ++*total_free;
912 }
913 }
914 if (tail-head < n_pages)
915 goto out;
916 if (nfree > max_free) {
917 max_start = head;
918 max_free = nfree;
919 if (max_free >= n_pages)
920 /* don't need more free pages... :-) */
921 goto out;
922 }
923
924 /* now shift the window and look for the area where as much pages as
925 * possible are free */
926 while( tail < max ) {
927 nfree -= (map[head++] == 0);
928 if (map[tail] == SWAP_MAP_BAD) {
929 head = tail+1;
930 goto start_over;
931 }
932 if (!map[tail]) {
933 ++nfree;
934 ++*total_free;
935 }
936 ++tail;
937 if (nfree > max_free) {
938 max_start = head;
939 max_free = nfree;
940 if (max_free >= n_pages)
941 /* don't need more free pages... :-) */
942 goto out;
943 }
944 }
945
946 out:
947 if (max_free < 0) {
948 printk( KERN_NOTICE "get_stram_region: ST-RAM too full or fragmented "
949 "-- can't allocate %lu pages\n", n_pages );
950 return( 0 );
951 }
952
953 *region_free = max_free;
954 return( max_start );
955}
956
957
958/* setup parameters from command line */
959void __init stram_swap_setup(char *str, int *ints)
960{
961 if (ints[0] >= 1)
962 max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK;
963}
964
965
966/* ------------------------------------------------------------------------ */
967/* ST-RAM device */
968/* ------------------------------------------------------------------------ */
969
970static int refcnt;
971
972static void do_stram_request(request_queue_t *q)
973{
974 struct request *req;
975
976 while ((req = elv_next_request(q)) != NULL) {
977 void *start = swap_start + (req->sector << 9);
978 unsigned long len = req->current_nr_sectors << 9;
979 if ((start + len) > swap_end) {
980 printk( KERN_ERR "stram: bad access beyond end of device: "
981 "block=%ld, count=%d\n",
982 req->sector,
983 req->current_nr_sectors );
984 end_request(req, 0);
985 continue;
986 }
987
988 if (req->cmd == READ) {
989 memcpy(req->buffer, start, len);
990#ifdef DO_PROC
991 stat_swap_read += N_PAGES(len);
992#endif
993 }
994 else {
995 memcpy(start, req->buffer, len);
996#ifdef DO_PROC
997 stat_swap_write += N_PAGES(len);
998#endif
999 }
1000 end_request(req, 1);
1001 }
1002}
1003
1004
1005static int stram_open( struct inode *inode, struct file *filp )
1006{
1007 if (filp != MAGIC_FILE_P) {
1008 printk( KERN_NOTICE "Only kernel can open ST-RAM device\n" );
1009 return( -EPERM );
1010 }
1011 if (refcnt)
1012 return( -EBUSY );
1013 ++refcnt;
1014 return( 0 );
1015}
1016
1017static int stram_release( struct inode *inode, struct file *filp )
1018{
1019 if (filp != MAGIC_FILE_P) {
1020 printk( KERN_NOTICE "Only kernel can close ST-RAM device\n" );
1021 return( -EPERM );
1022 }
1023 if (refcnt > 0)
1024 --refcnt;
1025 return( 0 );
1026}
1027
1028
1029static struct block_device_operations stram_fops = {
1030 .open = stram_open,
1031 .release = stram_release,
1032};
1033
1034static struct gendisk *stram_disk;
1035static struct request_queue *stram_queue;
1036static DEFINE_SPINLOCK(stram_lock);
1037
1038int __init stram_device_init(void)
1039{
1040 if (!MACH_IS_ATARI)
1041 /* no point in initializing this, I hope */
1042 return -ENXIO;
1043
1044 if (!max_swap_size)
1045 /* swapping not enabled */
1046 return -ENXIO;
1047 stram_disk = alloc_disk(1);
1048 if (!stram_disk)
1049 return -ENOMEM;
1050
1051 if (register_blkdev(STRAM_MAJOR, "stram")) {
1052 put_disk(stram_disk);
1053 return -ENXIO;
1054 }
1055
1056 stram_queue = blk_init_queue(do_stram_request, &stram_lock);
1057 if (!stram_queue) {
1058 unregister_blkdev(STRAM_MAJOR, "stram");
1059 put_disk(stram_disk);
1060 return -ENOMEM;
1061 }
1062
1063 stram_disk->major = STRAM_MAJOR;
1064 stram_disk->first_minor = STRAM_MINOR;
1065 stram_disk->fops = &stram_fops;
1066 stram_disk->queue = stram_queue;
1067 sprintf(stram_disk->disk_name, "stram");
1068 set_capacity(stram_disk, (swap_end - swap_start)/512);
1069 add_disk(stram_disk);
1070 return 0;
1071}
1072
1073
1074
1075/* ------------------------------------------------------------------------ */
1076/* Misc Utility Functions */
1077/* ------------------------------------------------------------------------ */
1078
1079/* reserve a range of pages */
1080static void reserve_region(void *start, void *end)
1081{
1082 reserve_bootmem (virt_to_phys(start), end - start);
1083}
1084
1085#endif /* CONFIG_STRAM_SWAP */
1086
1087
1088/* ------------------------------------------------------------------------ */
1089/* Region Management */
1090/* ------------------------------------------------------------------------ */
1091
1092
1093/* insert a region into the alloced list (sorted) */
1094static BLOCK *add_region( void *addr, unsigned long size )
1095{
1096 BLOCK **p, *n = NULL;
1097 int i;
1098
1099 for( i = 0; i < N_STATIC_BLOCKS; ++i ) {
1100 if (static_blocks[i].flags & BLOCK_FREE) {
1101 n = &static_blocks[i];
1102 n->flags = 0;
1103 break;
1104 }
1105 }
1106 if (!n && mem_init_done) {
1107 /* if statics block pool exhausted and we can call kmalloc() already
1108 * (after mem_init()), try that */
1109 n = kmalloc( sizeof(BLOCK), GFP_KERNEL );
1110 if (n)
1111 n->flags = BLOCK_KMALLOCED;
1112 }
1113 if (!n) {
1114 printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" );
1115 return( NULL );
1116 }
1117 n->start = addr;
1118 n->size = size;
1119
1120 for( p = &alloc_list; *p; p = &((*p)->next) )
1121 if ((*p)->start > addr) break;
1122 n->next = *p;
1123 *p = n;
1124
1125 return( n );
1126}
1127
1128
1129/* find a region (by start addr) in the alloced list */
1130static BLOCK *find_region( void *addr )
1131{
1132 BLOCK *p;
1133
1134 for( p = alloc_list; p; p = p->next ) {
1135 if (p->start == addr)
1136 return( p );
1137 if (p->start > addr)
1138 break;
1139 }
1140 return( NULL );
1141}
1142
1143
1144/* remove a block from the alloced list */
1145static int remove_region( BLOCK *block )
1146{
1147 BLOCK **p;
1148
1149 for( p = &alloc_list; *p; p = &((*p)->next) )
1150 if (*p == block) break;
1151 if (!*p)
1152 return( 0 );
1153
1154 *p = block->next;
1155 if (block->flags & BLOCK_KMALLOCED)
1156 kfree( block );
1157 else
1158 block->flags |= BLOCK_FREE;
1159 return( 1 );
1160}
1161
1162
1163
1164/* ------------------------------------------------------------------------ */
1165/* /proc statistics file stuff */
1166/* ------------------------------------------------------------------------ */
1167
1168#ifdef DO_PROC
1169
1170#define PRINT_PROC(fmt,args...) len += sprintf( buf+len, fmt, ##args )
1171
1172int get_stram_list( char *buf )
1173{
1174 int len = 0;
1175 BLOCK *p;
1176#ifdef CONFIG_STRAM_SWAP
1177 int i;
1178 unsigned short *map = stram_swap_info->swap_map;
1179 unsigned long max = stram_swap_info->max;
1180 unsigned free = 0, used = 0, rsvd = 0;
1181#endif
1182
1183#ifdef CONFIG_STRAM_SWAP
1184 if (max_swap_size) {
1185 for( i = 1; i < max; ++i ) {
1186 if (!map[i])
1187 ++free;
1188 else if (map[i] == SWAP_MAP_BAD)
1189 ++rsvd;
1190 else
1191 ++used;
1192 }
1193 PRINT_PROC(
1194 "Total ST-RAM: %8u kB\n"
1195 "Total ST-RAM swap: %8lu kB\n"
1196 "Free swap: %8u kB\n"
1197 "Used swap: %8u kB\n"
1198 "Allocated swap: %8u kB\n"
1199 "Swap Reads: %8u\n"
1200 "Swap Writes: %8u\n"
1201 "Swap Forced Reads: %8u\n",
1202 (stram_end - stram_start) >> 10,
1203 (max-1) << (PAGE_SHIFT-10),
1204 free << (PAGE_SHIFT-10),
1205 used << (PAGE_SHIFT-10),
1206 rsvd << (PAGE_SHIFT-10),
1207 stat_swap_read,
1208 stat_swap_write,
1209 stat_swap_force );
1210 }
1211 else {
1212#endif
1213 PRINT_PROC( "ST-RAM swapping disabled\n" );
1214 PRINT_PROC("Total ST-RAM: %8u kB\n",
1215 (stram_end - stram_start) >> 10);
1216#ifdef CONFIG_STRAM_SWAP
1217 }
1218#endif
1219
1220 PRINT_PROC( "Allocated regions:\n" );
1221 for( p = alloc_list; p; p = p->next ) {
1222 if (len + 50 >= PAGE_SIZE)
1223 break;
1224 PRINT_PROC("0x%08lx-0x%08lx: %s (",
1225 virt_to_phys(p->start),
1226 virt_to_phys(p->start+p->size-1),
1227 p->owner);
1228 if (p->flags & BLOCK_GFP)
1229 PRINT_PROC( "page-alloced)\n" );
1230 else if (p->flags & BLOCK_INSWAP)
1231 PRINT_PROC( "in swap)\n" );
1232 else
1233 PRINT_PROC( "??)\n" );
1234 }
1235
1236 return( len );
1237}
1238
1239#endif
1240
1241
1242/*
1243 * Local variables:
1244 * c-indent-level: 4
1245 * tab-width: 4
1246 * End:
1247 */
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
new file mode 100644
index 000000000000..6df7fb60dfea
--- /dev/null
+++ b/arch/m68k/atari/time.c
@@ -0,0 +1,348 @@
1/*
2 * linux/arch/m68k/atari/time.c
3 *
4 * Atari time and real time clock stuff
5 *
6 * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/types.h>
14#include <linux/mc146818rtc.h>
15#include <linux/interrupt.h>
16#include <linux/init.h>
17#include <linux/rtc.h>
18#include <linux/bcd.h>
19
20#include <asm/atariints.h>
21
22void __init
23atari_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
24{
25 /* set Timer C data Register */
26 mfp.tim_dt_c = INT_TICKS;
27 /* start timer C, div = 1:100 */
28 mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
29 /* install interrupt service routine for MFP Timer C */
30 request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
31 "timer", timer_routine);
32}
33
34/* ++andreas: gettimeoffset fixed to check for pending interrupt */
35
36#define TICK_SIZE 10000
37
38/* This is always executed with interrupts disabled. */
39unsigned long atari_gettimeoffset (void)
40{
41 unsigned long ticks, offset = 0;
42
43 /* read MFP timer C current value */
44 ticks = mfp.tim_dt_c;
45 /* The probability of underflow is less than 2% */
46 if (ticks > INT_TICKS - INT_TICKS / 50)
47 /* Check for pending timer interrupt */
48 if (mfp.int_pn_b & (1 << 5))
49 offset = TICK_SIZE;
50
51 ticks = INT_TICKS - ticks;
52 ticks = ticks * 10000L / INT_TICKS;
53
54 return ticks + offset;
55}
56
57
58static void mste_read(struct MSTE_RTC *val)
59{
60#define COPY(v) val->v=(mste_rtc.v & 0xf)
61 do {
62 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
63 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
64 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
65 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
66 COPY(year_tens) ;
67 /* prevent from reading the clock while it changed */
68 } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
69#undef COPY
70}
71
72static void mste_write(struct MSTE_RTC *val)
73{
74#define COPY(v) mste_rtc.v=val->v
75 do {
76 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
77 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
78 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
79 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
80 COPY(year_tens) ;
81 /* prevent from writing the clock while it changed */
82 } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
83#undef COPY
84}
85
86#define RTC_READ(reg) \
87 ({ unsigned char __val; \
88 (void) atari_writeb(reg,&tt_rtc.regsel); \
89 __val = tt_rtc.data; \
90 __val; \
91 })
92
93#define RTC_WRITE(reg,val) \
94 do { \
95 atari_writeb(reg,&tt_rtc.regsel); \
96 tt_rtc.data = (val); \
97 } while(0)
98
99
100#define HWCLK_POLL_INTERVAL 5
101
102int atari_mste_hwclk( int op, struct rtc_time *t )
103{
104 int hour, year;
105 int hr24=0;
106 struct MSTE_RTC val;
107
108 mste_rtc.mode=(mste_rtc.mode | 1);
109 hr24=mste_rtc.mon_tens & 1;
110 mste_rtc.mode=(mste_rtc.mode & ~1);
111
112 if (op) {
113 /* write: prepare values */
114
115 val.sec_ones = t->tm_sec % 10;
116 val.sec_tens = t->tm_sec / 10;
117 val.min_ones = t->tm_min % 10;
118 val.min_tens = t->tm_min / 10;
119 hour = t->tm_hour;
120 if (!hr24) {
121 if (hour > 11)
122 hour += 20 - 12;
123 if (hour == 0 || hour == 20)
124 hour += 12;
125 }
126 val.hr_ones = hour % 10;
127 val.hr_tens = hour / 10;
128 val.day_ones = t->tm_mday % 10;
129 val.day_tens = t->tm_mday / 10;
130 val.mon_ones = (t->tm_mon+1) % 10;
131 val.mon_tens = (t->tm_mon+1) / 10;
132 year = t->tm_year - 80;
133 val.year_ones = year % 10;
134 val.year_tens = year / 10;
135 val.weekday = t->tm_wday;
136 mste_write(&val);
137 mste_rtc.mode=(mste_rtc.mode | 1);
138 val.year_ones = (year % 4); /* leap year register */
139 mste_rtc.mode=(mste_rtc.mode & ~1);
140 }
141 else {
142 mste_read(&val);
143 t->tm_sec = val.sec_ones + val.sec_tens * 10;
144 t->tm_min = val.min_ones + val.min_tens * 10;
145 hour = val.hr_ones + val.hr_tens * 10;
146 if (!hr24) {
147 if (hour == 12 || hour == 12 + 20)
148 hour -= 12;
149 if (hour >= 20)
150 hour += 12 - 20;
151 }
152 t->tm_hour = hour;
153 t->tm_mday = val.day_ones + val.day_tens * 10;
154 t->tm_mon = val.mon_ones + val.mon_tens * 10 - 1;
155 t->tm_year = val.year_ones + val.year_tens * 10 + 80;
156 t->tm_wday = val.weekday;
157 }
158 return 0;
159}
160
161int atari_tt_hwclk( int op, struct rtc_time *t )
162{
163 int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0;
164 unsigned long flags;
165 unsigned char ctrl;
166 int pm = 0;
167
168 ctrl = RTC_READ(RTC_CONTROL); /* control registers are
169 * independent from the UIP */
170
171 if (op) {
172 /* write: prepare values */
173
174 sec = t->tm_sec;
175 min = t->tm_min;
176 hour = t->tm_hour;
177 day = t->tm_mday;
178 mon = t->tm_mon + 1;
179 year = t->tm_year - atari_rtc_year_offset;
180 wday = t->tm_wday + (t->tm_wday >= 0);
181
182 if (!(ctrl & RTC_24H)) {
183 if (hour > 11) {
184 pm = 0x80;
185 if (hour != 12)
186 hour -= 12;
187 }
188 else if (hour == 0)
189 hour = 12;
190 }
191
192 if (!(ctrl & RTC_DM_BINARY)) {
193 BIN_TO_BCD(sec);
194 BIN_TO_BCD(min);
195 BIN_TO_BCD(hour);
196 BIN_TO_BCD(day);
197 BIN_TO_BCD(mon);
198 BIN_TO_BCD(year);
199 if (wday >= 0) BIN_TO_BCD(wday);
200 }
201 }
202
203 /* Reading/writing the clock registers is a bit critical due to
204 * the regular update cycle of the RTC. While an update is in
205 * progress, registers 0..9 shouldn't be touched.
206 * The problem is solved like that: If an update is currently in
207 * progress (the UIP bit is set), the process sleeps for a while
208 * (50ms). This really should be enough, since the update cycle
209 * normally needs 2 ms.
210 * If the UIP bit reads as 0, we have at least 244 usecs until the
211 * update starts. This should be enough... But to be sure,
212 * additionally the RTC_SET bit is set to prevent an update cycle.
213 */
214
215 while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
216 current->state = TASK_INTERRUPTIBLE;
217 schedule_timeout(HWCLK_POLL_INTERVAL);
218 }
219
220 local_irq_save(flags);
221 RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
222 if (!op) {
223 sec = RTC_READ( RTC_SECONDS );
224 min = RTC_READ( RTC_MINUTES );
225 hour = RTC_READ( RTC_HOURS );
226 day = RTC_READ( RTC_DAY_OF_MONTH );
227 mon = RTC_READ( RTC_MONTH );
228 year = RTC_READ( RTC_YEAR );
229 wday = RTC_READ( RTC_DAY_OF_WEEK );
230 }
231 else {
232 RTC_WRITE( RTC_SECONDS, sec );
233 RTC_WRITE( RTC_MINUTES, min );
234 RTC_WRITE( RTC_HOURS, hour + pm);
235 RTC_WRITE( RTC_DAY_OF_MONTH, day );
236 RTC_WRITE( RTC_MONTH, mon );
237 RTC_WRITE( RTC_YEAR, year );
238 if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday );
239 }
240 RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET );
241 local_irq_restore(flags);
242
243 if (!op) {
244 /* read: adjust values */
245
246 if (hour & 0x80) {
247 hour &= ~0x80;
248 pm = 1;
249 }
250
251 if (!(ctrl & RTC_DM_BINARY)) {
252 BCD_TO_BIN(sec);
253 BCD_TO_BIN(min);
254 BCD_TO_BIN(hour);
255 BCD_TO_BIN(day);
256 BCD_TO_BIN(mon);
257 BCD_TO_BIN(year);
258 BCD_TO_BIN(wday);
259 }
260
261 if (!(ctrl & RTC_24H)) {
262 if (!pm && hour == 12)
263 hour = 0;
264 else if (pm && hour != 12)
265 hour += 12;
266 }
267
268 t->tm_sec = sec;
269 t->tm_min = min;
270 t->tm_hour = hour;
271 t->tm_mday = day;
272 t->tm_mon = mon - 1;
273 t->tm_year = year + atari_rtc_year_offset;
274 t->tm_wday = wday - 1;
275 }
276
277 return( 0 );
278}
279
280
281int atari_mste_set_clock_mmss (unsigned long nowtime)
282{
283 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
284 struct MSTE_RTC val;
285 unsigned char rtc_minutes;
286
287 mste_read(&val);
288 rtc_minutes= val.min_ones + val.min_tens * 10;
289 if ((rtc_minutes < real_minutes
290 ? real_minutes - rtc_minutes
291 : rtc_minutes - real_minutes) < 30)
292 {
293 val.sec_ones = real_seconds % 10;
294 val.sec_tens = real_seconds / 10;
295 val.min_ones = real_minutes % 10;
296 val.min_tens = real_minutes / 10;
297 mste_write(&val);
298 }
299 else
300 return -1;
301 return 0;
302}
303
304int atari_tt_set_clock_mmss (unsigned long nowtime)
305{
306 int retval = 0;
307 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
308 unsigned char save_control, save_freq_select, rtc_minutes;
309
310 save_control = RTC_READ (RTC_CONTROL); /* tell the clock it's being set */
311 RTC_WRITE (RTC_CONTROL, save_control | RTC_SET);
312
313 save_freq_select = RTC_READ (RTC_FREQ_SELECT); /* stop and reset prescaler */
314 RTC_WRITE (RTC_FREQ_SELECT, save_freq_select | RTC_DIV_RESET2);
315
316 rtc_minutes = RTC_READ (RTC_MINUTES);
317 if (!(save_control & RTC_DM_BINARY))
318 BCD_TO_BIN (rtc_minutes);
319
320 /* Since we're only adjusting minutes and seconds, don't interfere
321 with hour overflow. This avoids messing with unknown time zones
322 but requires your RTC not to be off by more than 30 minutes. */
323 if ((rtc_minutes < real_minutes
324 ? real_minutes - rtc_minutes
325 : rtc_minutes - real_minutes) < 30)
326 {
327 if (!(save_control & RTC_DM_BINARY))
328 {
329 BIN_TO_BCD (real_seconds);
330 BIN_TO_BCD (real_minutes);
331 }
332 RTC_WRITE (RTC_SECONDS, real_seconds);
333 RTC_WRITE (RTC_MINUTES, real_minutes);
334 }
335 else
336 retval = -1;
337
338 RTC_WRITE (RTC_FREQ_SELECT, save_freq_select);
339 RTC_WRITE (RTC_CONTROL, save_control);
340 return retval;
341}
342
343/*
344 * Local variables:
345 * c-indent-level: 4
346 * tab-width: 8
347 * End:
348 */
diff --git a/arch/m68k/bvme6000/Makefile b/arch/m68k/bvme6000/Makefile
new file mode 100644
index 000000000000..2348e6ceed1e
--- /dev/null
+++ b/arch/m68k/bvme6000/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/bvme6000 source directory
3#
4
5obj-y := config.o bvmeints.o rtc.o
diff --git a/arch/m68k/bvme6000/bvmeints.c b/arch/m68k/bvme6000/bvmeints.c
new file mode 100644
index 000000000000..298a8df02664
--- /dev/null
+++ b/arch/m68k/bvme6000/bvmeints.c
@@ -0,0 +1,160 @@
1/*
2 * arch/m68k/bvme6000/bvmeints.c
3 *
4 * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk]
5 *
6 * based on amiints.c -- Amiga Linux interrupt handling code
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file README.legal in the main directory of this archive
10 * for more details.
11 *
12 */
13
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/seq_file.h>
18
19#include <asm/ptrace.h>
20#include <asm/system.h>
21#include <asm/irq.h>
22#include <asm/traps.h>
23
24static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp);
25
26/*
27 * This should ideally be 4 elements only, for speed.
28 */
29
30static struct {
31 irqreturn_t (*handler)(int, void *, struct pt_regs *);
32 unsigned long flags;
33 void *dev_id;
34 const char *devname;
35 unsigned count;
36} irq_tab[256];
37
38/*
39 * void bvme6000_init_IRQ (void)
40 *
41 * Parameters: None
42 *
43 * Returns: Nothing
44 *
45 * This function is called during kernel startup to initialize
46 * the bvme6000 IRQ handling routines.
47 */
48
49void bvme6000_init_IRQ (void)
50{
51 int i;
52
53 for (i = 0; i < 256; i++) {
54 irq_tab[i].handler = bvme6000_defhand;
55 irq_tab[i].flags = IRQ_FLG_STD;
56 irq_tab[i].dev_id = NULL;
57 irq_tab[i].devname = NULL;
58 irq_tab[i].count = 0;
59 }
60}
61
62int bvme6000_request_irq(unsigned int irq,
63 irqreturn_t (*handler)(int, void *, struct pt_regs *),
64 unsigned long flags, const char *devname, void *dev_id)
65{
66 if (irq > 255) {
67 printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
68 return -ENXIO;
69 }
70#if 0
71 /* Nothing special about auto-vectored devices for the BVME6000,
72 * but treat it specially to avoid changes elsewhere.
73 */
74
75 if (irq >= VEC_INT1 && irq <= VEC_INT7)
76 return cpu_request_irq(irq - VEC_SPUR, handler, flags,
77 devname, dev_id);
78#endif
79 if (!(irq_tab[irq].flags & IRQ_FLG_STD)) {
80 if (irq_tab[irq].flags & IRQ_FLG_LOCK) {
81 printk("%s: IRQ %d from %s is not replaceable\n",
82 __FUNCTION__, irq, irq_tab[irq].devname);
83 return -EBUSY;
84 }
85 if (flags & IRQ_FLG_REPLACE) {
86 printk("%s: %s can't replace IRQ %d from %s\n",
87 __FUNCTION__, devname, irq, irq_tab[irq].devname);
88 return -EBUSY;
89 }
90 }
91 irq_tab[irq].handler = handler;
92 irq_tab[irq].flags = flags;
93 irq_tab[irq].dev_id = dev_id;
94 irq_tab[irq].devname = devname;
95 return 0;
96}
97
98void bvme6000_free_irq(unsigned int irq, void *dev_id)
99{
100 if (irq > 255) {
101 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
102 return;
103 }
104#if 0
105 if (irq >= VEC_INT1 && irq <= VEC_INT7) {
106 cpu_free_irq(irq - VEC_SPUR, dev_id);
107 return;
108 }
109#endif
110 if (irq_tab[irq].dev_id != dev_id)
111 printk("%s: Removing probably wrong IRQ %d from %s\n",
112 __FUNCTION__, irq, irq_tab[irq].devname);
113
114 irq_tab[irq].handler = bvme6000_defhand;
115 irq_tab[irq].flags = IRQ_FLG_STD;
116 irq_tab[irq].dev_id = NULL;
117 irq_tab[irq].devname = NULL;
118}
119
120irqreturn_t bvme6000_process_int (unsigned long vec, struct pt_regs *fp)
121{
122 if (vec > 255) {
123 printk ("bvme6000_process_int: Illegal vector %ld", vec);
124 return IRQ_NONE;
125 } else {
126 irq_tab[vec].count++;
127 irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
128 return IRQ_HANDLED;
129 }
130}
131
132int show_bvme6000_interrupts(struct seq_file *p, void *v)
133{
134 int i;
135
136 for (i = 0; i < 256; i++) {
137 if (irq_tab[i].count)
138 seq_printf(p, "Vec 0x%02x: %8d %s\n",
139 i, irq_tab[i].count,
140 irq_tab[i].devname ? irq_tab[i].devname : "free");
141 }
142 return 0;
143}
144
145
146static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp)
147{
148 printk ("Unknown interrupt 0x%02x\n", irq);
149 return IRQ_NONE;
150}
151
152void bvme6000_enable_irq (unsigned int irq)
153{
154}
155
156
157void bvme6000_disable_irq (unsigned int irq)
158{
159}
160
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
new file mode 100644
index 000000000000..3ffc84f9c291
--- /dev/null
+++ b/arch/m68k/bvme6000/config.c
@@ -0,0 +1,380 @@
1/*
2 * arch/m68k/bvme6000/config.c
3 *
4 * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk]
5 *
6 * Based on:
7 *
8 * linux/amiga/config.c
9 *
10 * Copyright (C) 1993 Hamish Macdonald
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file README.legal in the main directory of this archive
14 * for more details.
15 */
16
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/mm.h>
20#include <linux/tty.h>
21#include <linux/console.h>
22#include <linux/linkage.h>
23#include <linux/init.h>
24#include <linux/major.h>
25#include <linux/genhd.h>
26#include <linux/rtc.h>
27#include <linux/interrupt.h>
28
29#include <asm/bootinfo.h>
30#include <asm/system.h>
31#include <asm/pgtable.h>
32#include <asm/setup.h>
33#include <asm/irq.h>
34#include <asm/traps.h>
35#include <asm/rtc.h>
36#include <asm/machdep.h>
37#include <asm/bvme6000hw.h>
38
39extern irqreturn_t bvme6000_process_int (int level, struct pt_regs *regs);
40extern void bvme6000_init_IRQ (void);
41extern void bvme6000_free_irq (unsigned int, void *);
42extern int show_bvme6000_interrupts(struct seq_file *, void *);
43extern void bvme6000_enable_irq (unsigned int);
44extern void bvme6000_disable_irq (unsigned int);
45static void bvme6000_get_model(char *model);
46static int bvme6000_get_hardware_list(char *buffer);
47extern int bvme6000_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
48extern void bvme6000_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
49extern unsigned long bvme6000_gettimeoffset (void);
50extern int bvme6000_hwclk (int, struct rtc_time *);
51extern int bvme6000_set_clock_mmss (unsigned long);
52extern void bvme6000_reset (void);
53extern void bvme6000_waitbut(void);
54void bvme6000_set_vectors (void);
55
56static unsigned char bcd2bin (unsigned char b);
57static unsigned char bin2bcd (unsigned char b);
58
59/* Save tick handler routine pointer, will point to do_timer() in
60 * kernel/sched.c, called via bvme6000_process_int() */
61
62static irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
63
64
65int bvme6000_parse_bootinfo(const struct bi_record *bi)
66{
67 if (bi->tag == BI_VME_TYPE)
68 return 0;
69 else
70 return 1;
71}
72
73void bvme6000_reset(void)
74{
75 volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
76
77 printk ("\r\n\nCalled bvme6000_reset\r\n"
78 "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r");
79 /* The string of returns is to delay the reset until the whole
80 * message is output. */
81 /* Enable the watchdog, via PIT port C bit 4 */
82
83 pit->pcddr |= 0x10; /* WDOG enable */
84
85 while(1)
86 ;
87}
88
89static void bvme6000_get_model(char *model)
90{
91 sprintf(model, "BVME%d000", m68k_cputype == CPU_68060 ? 6 : 4);
92}
93
94
95/* No hardware options on BVME6000? */
96
97static int bvme6000_get_hardware_list(char *buffer)
98{
99 *buffer = '\0';
100 return 0;
101}
102
103
104void __init config_bvme6000(void)
105{
106 volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
107
108 /* Board type is only set by newer versions of vmelilo/tftplilo */
109 if (!vme_brdtype) {
110 if (m68k_cputype == CPU_68060)
111 vme_brdtype = VME_TYPE_BVME6000;
112 else
113 vme_brdtype = VME_TYPE_BVME4000;
114 }
115#if 0
116 /* Call bvme6000_set_vectors() so ABORT will work, along with BVMBug
117 * debugger. Note trap_init() will splat the abort vector, but
118 * bvme6000_init_IRQ() will put it back again. Hopefully. */
119
120 bvme6000_set_vectors();
121#endif
122
123 mach_max_dma_address = 0xffffffff;
124 mach_sched_init = bvme6000_sched_init;
125 mach_init_IRQ = bvme6000_init_IRQ;
126 mach_gettimeoffset = bvme6000_gettimeoffset;
127 mach_hwclk = bvme6000_hwclk;
128 mach_set_clock_mmss = bvme6000_set_clock_mmss;
129 mach_reset = bvme6000_reset;
130 mach_free_irq = bvme6000_free_irq;
131 mach_process_int = bvme6000_process_int;
132 mach_get_irq_list = show_bvme6000_interrupts;
133 mach_request_irq = bvme6000_request_irq;
134 enable_irq = bvme6000_enable_irq;
135 disable_irq = bvme6000_disable_irq;
136 mach_get_model = bvme6000_get_model;
137 mach_get_hardware_list = bvme6000_get_hardware_list;
138
139 printk ("Board is %sconfigured as a System Controller\n",
140 *config_reg_ptr & BVME_CONFIG_SW1 ? "" : "not ");
141
142 /* Now do the PIT configuration */
143
144 pit->pgcr = 0x00; /* Unidirectional 8 bit, no handshake for now */
145 pit->psrr = 0x18; /* PIACK and PIRQ fucntions enabled */
146 pit->pacr = 0x00; /* Sub Mode 00, H2 i/p, no DMA */
147 pit->padr = 0x00; /* Just to be tidy! */
148 pit->paddr = 0x00; /* All inputs for now (safest) */
149 pit->pbcr = 0x80; /* Sub Mode 1x, H4 i/p, no DMA */
150 pit->pbdr = 0xbc | (*config_reg_ptr & BVME_CONFIG_SW1 ? 0 : 0x40);
151 /* PRI, SYSCON?, Level3, SCC clks from xtal */
152 pit->pbddr = 0xf3; /* Mostly outputs */
153 pit->pcdr = 0x01; /* PA transceiver disabled */
154 pit->pcddr = 0x03; /* WDOG disable */
155
156 /* Disable snooping for Ethernet and VME accesses */
157
158 bvme_acr_addrctl = 0;
159}
160
161
162irqreturn_t bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp)
163{
164 unsigned long *new = (unsigned long *)vectors;
165 unsigned long *old = (unsigned long *)0xf8000000;
166
167 /* Wait for button release */
168 while (*(volatile unsigned char *)BVME_LOCAL_IRQ_STAT & BVME_ABORT_STATUS)
169 ;
170
171 *(new+4) = *(old+4); /* Illegal instruction */
172 *(new+9) = *(old+9); /* Trace */
173 *(new+47) = *(old+47); /* Trap #15 */
174 *(new+0x1f) = *(old+0x1f); /* ABORT switch */
175 return IRQ_HANDLED;
176}
177
178
179static irqreturn_t bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp)
180{
181 volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
182 unsigned char msr = rtc->msr & 0xc0;
183
184 rtc->msr = msr | 0x20; /* Ack the interrupt */
185
186 return tick_handler(irq, dev_id, fp);
187}
188
189/*
190 * Set up the RTC timer 1 to mode 2, so T1 output toggles every 5ms
191 * (40000 x 125ns). It will interrupt every 10ms, when T1 goes low.
192 * So, when reading the elapsed time, you should read timer1,
193 * subtract it from 39999, and then add 40000 if T1 is high.
194 * That gives you the number of 125ns ticks in to the 10ms period,
195 * so divide by 8 to get the microsecond result.
196 */
197
198void bvme6000_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
199{
200 volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
201 unsigned char msr = rtc->msr & 0xc0;
202
203 rtc->msr = 0; /* Ensure timer registers accessible */
204
205 tick_handler = timer_routine;
206 if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0,
207 "timer", bvme6000_timer_int))
208 panic ("Couldn't register timer int");
209
210 rtc->t1cr_omr = 0x04; /* Mode 2, ext clk */
211 rtc->t1msb = 39999 >> 8;
212 rtc->t1lsb = 39999 & 0xff;
213 rtc->irr_icr1 &= 0xef; /* Route timer 1 to INTR pin */
214 rtc->msr = 0x40; /* Access int.cntrl, etc */
215 rtc->pfr_icr0 = 0x80; /* Just timer 1 ints enabled */
216 rtc->irr_icr1 = 0;
217 rtc->t1cr_omr = 0x0a; /* INTR+T1 active lo, push-pull */
218 rtc->t0cr_rtmr &= 0xdf; /* Stop timers in standby */
219 rtc->msr = 0; /* Access timer 1 control */
220 rtc->t1cr_omr = 0x05; /* Mode 2, ext clk, GO */
221
222 rtc->msr = msr;
223
224 if (request_irq(BVME_IRQ_ABORT, bvme6000_abort_int, 0,
225 "abort", bvme6000_abort_int))
226 panic ("Couldn't register abort int");
227}
228
229
230/* This is always executed with interrupts disabled. */
231
232/*
233 * NOTE: Don't accept any readings within 5us of rollover, as
234 * the T1INT bit may be a little slow getting set. There is also
235 * a fault in the chip, meaning that reads may produce invalid
236 * results...
237 */
238
239unsigned long bvme6000_gettimeoffset (void)
240{
241 volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
242 volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
243 unsigned char msr = rtc->msr & 0xc0;
244 unsigned char t1int, t1op;
245 unsigned long v = 800000, ov;
246
247 rtc->msr = 0; /* Ensure timer registers accessible */
248
249 do {
250 ov = v;
251 t1int = rtc->msr & 0x20;
252 t1op = pit->pcdr & 0x04;
253 rtc->t1cr_omr |= 0x40; /* Latch timer1 */
254 v = rtc->t1msb << 8; /* Read timer1 */
255 v |= rtc->t1lsb; /* Read timer1 */
256 } while (t1int != (rtc->msr & 0x20) ||
257 t1op != (pit->pcdr & 0x04) ||
258 abs(ov-v) > 80 ||
259 v > 39960);
260
261 v = 39999 - v;
262 if (!t1op) /* If in second half cycle.. */
263 v += 40000;
264 v /= 8; /* Convert ticks to microseconds */
265 if (t1int)
266 v += 10000; /* Int pending, + 10ms */
267 rtc->msr = msr;
268
269 return v;
270}
271
272static unsigned char bcd2bin (unsigned char b)
273{
274 return ((b>>4)*10 + (b&15));
275}
276
277static unsigned char bin2bcd (unsigned char b)
278{
279 return (((b/10)*16) + (b%10));
280}
281
282
283/*
284 * Looks like op is non-zero for setting the clock, and zero for
285 * reading the clock.
286 *
287 * struct hwclk_time {
288 * unsigned sec; 0..59
289 * unsigned min; 0..59
290 * unsigned hour; 0..23
291 * unsigned day; 1..31
292 * unsigned mon; 0..11
293 * unsigned year; 00...
294 * int wday; 0..6, 0 is Sunday, -1 means unknown/don't set
295 * };
296 */
297
298int bvme6000_hwclk(int op, struct rtc_time *t)
299{
300 volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
301 unsigned char msr = rtc->msr & 0xc0;
302
303 rtc->msr = 0x40; /* Ensure clock and real-time-mode-register
304 * are accessible */
305 if (op)
306 { /* Write.... */
307 rtc->t0cr_rtmr = t->tm_year%4;
308 rtc->bcd_tenms = 0;
309 rtc->bcd_sec = bin2bcd(t->tm_sec);
310 rtc->bcd_min = bin2bcd(t->tm_min);
311 rtc->bcd_hr = bin2bcd(t->tm_hour);
312 rtc->bcd_dom = bin2bcd(t->tm_mday);
313 rtc->bcd_mth = bin2bcd(t->tm_mon + 1);
314 rtc->bcd_year = bin2bcd(t->tm_year%100);
315 if (t->tm_wday >= 0)
316 rtc->bcd_dow = bin2bcd(t->tm_wday+1);
317 rtc->t0cr_rtmr = t->tm_year%4 | 0x08;
318 }
319 else
320 { /* Read.... */
321 do {
322 t->tm_sec = bcd2bin(rtc->bcd_sec);
323 t->tm_min = bcd2bin(rtc->bcd_min);
324 t->tm_hour = bcd2bin(rtc->bcd_hr);
325 t->tm_mday = bcd2bin(rtc->bcd_dom);
326 t->tm_mon = bcd2bin(rtc->bcd_mth)-1;
327 t->tm_year = bcd2bin(rtc->bcd_year);
328 if (t->tm_year < 70)
329 t->tm_year += 100;
330 t->tm_wday = bcd2bin(rtc->bcd_dow)-1;
331 } while (t->tm_sec != bcd2bin(rtc->bcd_sec));
332 }
333
334 rtc->msr = msr;
335
336 return 0;
337}
338
339/*
340 * Set the minutes and seconds from seconds value 'nowtime'. Fail if
341 * clock is out by > 30 minutes. Logic lifted from atari code.
342 * Algorithm is to wait for the 10ms register to change, and then to
343 * wait a short while, and then set it.
344 */
345
346int bvme6000_set_clock_mmss (unsigned long nowtime)
347{
348 int retval = 0;
349 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
350 unsigned char rtc_minutes, rtc_tenms;
351 volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
352 unsigned char msr = rtc->msr & 0xc0;
353 unsigned long flags;
354 volatile int i;
355
356 rtc->msr = 0; /* Ensure clock accessible */
357 rtc_minutes = bcd2bin (rtc->bcd_min);
358
359 if ((rtc_minutes < real_minutes
360 ? real_minutes - rtc_minutes
361 : rtc_minutes - real_minutes) < 30)
362 {
363 local_irq_save(flags);
364 rtc_tenms = rtc->bcd_tenms;
365 while (rtc_tenms == rtc->bcd_tenms)
366 ;
367 for (i = 0; i < 1000; i++)
368 ;
369 rtc->bcd_min = bin2bcd(real_minutes);
370 rtc->bcd_sec = bin2bcd(real_seconds);
371 local_irq_restore(flags);
372 }
373 else
374 retval = -1;
375
376 rtc->msr = msr;
377
378 return retval;
379}
380
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
new file mode 100644
index 000000000000..c6b2a410bf9a
--- /dev/null
+++ b/arch/m68k/bvme6000/rtc.c
@@ -0,0 +1,182 @@
1/*
2 * Real Time Clock interface for Linux on the BVME6000
3 *
4 * Based on the PC driver by Paul Gortmaker.
5 */
6
7#define RTC_VERSION "1.00"
8
9#include <linux/types.h>
10#include <linux/errno.h>
11#include <linux/miscdevice.h>
12#include <linux/slab.h>
13#include <linux/ioport.h>
14#include <linux/fcntl.h>
15#include <linux/init.h>
16#include <linux/poll.h>
17#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
18#include <linux/smp_lock.h>
19#include <asm/bvme6000hw.h>
20
21#include <asm/io.h>
22#include <asm/uaccess.h>
23#include <asm/system.h>
24#include <asm/setup.h>
25
26/*
27 * We sponge a minor off of the misc major. No need slurping
28 * up another valuable major dev number for this. If you add
29 * an ioctl, make sure you don't conflict with SPARC's RTC
30 * ioctls.
31 */
32
33#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
34#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
35
36static unsigned char days_in_mo[] =
37{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
38
39static char rtc_status;
40
41static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
42 unsigned long arg)
43{
44 volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
45 unsigned char msr;
46 unsigned long flags;
47 struct rtc_time wtime;
48
49 switch (cmd) {
50 case RTC_RD_TIME: /* Read the time/date from RTC */
51 {
52 local_irq_save(flags);
53 /* Ensure clock and real-time-mode-register are accessible */
54 msr = rtc->msr & 0xc0;
55 rtc->msr = 0x40;
56 memset(&wtime, 0, sizeof(struct rtc_time));
57 do {
58 wtime.tm_sec = BCD2BIN(rtc->bcd_sec);
59 wtime.tm_min = BCD2BIN(rtc->bcd_min);
60 wtime.tm_hour = BCD2BIN(rtc->bcd_hr);
61 wtime.tm_mday = BCD2BIN(rtc->bcd_dom);
62 wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1;
63 wtime.tm_year = BCD2BIN(rtc->bcd_year);
64 if (wtime.tm_year < 70)
65 wtime.tm_year += 100;
66 wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
67 } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec));
68 rtc->msr = msr;
69 local_irq_restore(flags);
70 return copy_to_user((void *)arg, &wtime, sizeof wtime) ?
71 -EFAULT : 0;
72 }
73 case RTC_SET_TIME: /* Set the RTC */
74 {
75 struct rtc_time rtc_tm;
76 unsigned char mon, day, hrs, min, sec, leap_yr;
77 unsigned int yrs;
78
79 if (!capable(CAP_SYS_ADMIN))
80 return -EACCES;
81
82 if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
83 sizeof(struct rtc_time)))
84 return -EFAULT;
85
86 yrs = rtc_tm.tm_year;
87 if (yrs < 1900)
88 yrs += 1900;
89 mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
90 day = rtc_tm.tm_mday;
91 hrs = rtc_tm.tm_hour;
92 min = rtc_tm.tm_min;
93 sec = rtc_tm.tm_sec;
94
95 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
96
97 if ((mon > 12) || (mon < 1) || (day == 0))
98 return -EINVAL;
99
100 if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
101 return -EINVAL;
102
103 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
104 return -EINVAL;
105
106 if (yrs >= 2070)
107 return -EINVAL;
108
109 local_irq_save(flags);
110 /* Ensure clock and real-time-mode-register are accessible */
111 msr = rtc->msr & 0xc0;
112 rtc->msr = 0x40;
113
114 rtc->t0cr_rtmr = yrs%4;
115 rtc->bcd_tenms = 0;
116 rtc->bcd_sec = BIN2BCD(sec);
117 rtc->bcd_min = BIN2BCD(min);
118 rtc->bcd_hr = BIN2BCD(hrs);
119 rtc->bcd_dom = BIN2BCD(day);
120 rtc->bcd_mth = BIN2BCD(mon);
121 rtc->bcd_year = BIN2BCD(yrs%100);
122 if (rtc_tm.tm_wday >= 0)
123 rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1);
124 rtc->t0cr_rtmr = yrs%4 | 0x08;
125
126 rtc->msr = msr;
127 local_irq_restore(flags);
128 return 0;
129 }
130 default:
131 return -EINVAL;
132 }
133}
134
135/*
136 * We enforce only one user at a time here with the open/close.
137 * Also clear the previous interrupt data on an open, and clean
138 * up things on a close.
139 */
140
141static int rtc_open(struct inode *inode, struct file *file)
142{
143 if(rtc_status)
144 return -EBUSY;
145
146 rtc_status = 1;
147 return 0;
148}
149
150static int rtc_release(struct inode *inode, struct file *file)
151{
152 lock_kernel();
153 rtc_status = 0;
154 unlock_kernel();
155 return 0;
156}
157
158/*
159 * The various file operations we support.
160 */
161
162static struct file_operations rtc_fops = {
163 .ioctl = rtc_ioctl,
164 .open = rtc_open,
165 .release = rtc_release,
166};
167
168static struct miscdevice rtc_dev = {
169 .minor = RTC_MINOR,
170 .name = "rtc",
171 .fops = &rtc_fops
172};
173
174int __init rtc_DP8570A_init(void)
175{
176 if (!MACH_IS_BVME6000)
177 return -ENODEV;
178
179 printk(KERN_INFO "DP8570A Real Time Clock Driver v%s\n", RTC_VERSION);
180 return misc_register(&rtc_dev);
181}
182
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
new file mode 100644
index 000000000000..c1b23336450b
--- /dev/null
+++ b/arch/m68k/configs/amiga_defconfig
@@ -0,0 +1,968 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:22:54 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-amiga"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62CONFIG_AMIGA=y
63# CONFIG_ATARI is not set
64# CONFIG_MAC is not set
65# CONFIG_APOLLO is not set
66# CONFIG_VME is not set
67# CONFIG_HP300 is not set
68# CONFIG_SUN3X is not set
69# CONFIG_Q40 is not set
70
71#
72# Processor type
73#
74CONFIG_M68020=y
75CONFIG_M68030=y
76CONFIG_M68040=y
77CONFIG_M68060=y
78CONFIG_MMU_MOTOROLA=y
79CONFIG_M68KFPU_EMU=y
80CONFIG_M68KFPU_EMU_EXTRAPREC=y
81# CONFIG_M68KFPU_EMU_ONLY is not set
82# CONFIG_ADVANCED is not set
83
84#
85# General setup
86#
87CONFIG_BINFMT_ELF=y
88CONFIG_BINFMT_AOUT=m
89CONFIG_BINFMT_MISC=m
90CONFIG_ZORRO=y
91CONFIG_AMIGA_PCMCIA=y
92# CONFIG_HEARTBEAT is not set
93CONFIG_PROC_HARDWARE=y
94CONFIG_ISA=y
95CONFIG_GENERIC_ISA_DMA=y
96CONFIG_ZORRO_NAMES=y
97
98#
99# Device Drivers
100#
101
102#
103# Generic Driver Options
104#
105CONFIG_STANDALONE=y
106CONFIG_PREVENT_FIRMWARE_BUILD=y
107# CONFIG_DEBUG_DRIVER is not set
108
109#
110# Memory Technology Devices (MTD)
111#
112# CONFIG_MTD is not set
113
114#
115# Parallel port support
116#
117CONFIG_PARPORT=m
118# CONFIG_PARPORT_PC is not set
119CONFIG_PARPORT_AMIGA=m
120CONFIG_PARPORT_MFC3=m
121# CONFIG_PARPORT_OTHER is not set
122CONFIG_PARPORT_1284=y
123
124#
125# Plug and Play support
126#
127# CONFIG_PNP is not set
128
129#
130# Block devices
131#
132CONFIG_AMIGA_FLOPPY=y
133CONFIG_AMIGA_Z2RAM=y
134# CONFIG_BLK_DEV_XD is not set
135# CONFIG_PARIDE is not set
136CONFIG_BLK_DEV_LOOP=y
137CONFIG_BLK_DEV_CRYPTOLOOP=m
138CONFIG_BLK_DEV_NBD=m
139CONFIG_BLK_DEV_RAM=y
140CONFIG_BLK_DEV_RAM_COUNT=16
141CONFIG_BLK_DEV_RAM_SIZE=4096
142CONFIG_BLK_DEV_INITRD=y
143CONFIG_INITRAMFS_SOURCE=""
144CONFIG_CDROM_PKTCDVD=m
145CONFIG_CDROM_PKTCDVD_BUFFERS=8
146# CONFIG_CDROM_PKTCDVD_WCACHE is not set
147
148#
149# IO Schedulers
150#
151CONFIG_IOSCHED_NOOP=y
152CONFIG_IOSCHED_AS=y
153CONFIG_IOSCHED_DEADLINE=y
154CONFIG_IOSCHED_CFQ=y
155
156#
157# ATA/ATAPI/MFM/RLL support
158#
159CONFIG_IDE=y
160CONFIG_BLK_DEV_IDE=y
161
162#
163# Please see Documentation/ide.txt for help/info on IDE drives
164#
165# CONFIG_BLK_DEV_IDE_SATA is not set
166CONFIG_BLK_DEV_IDEDISK=y
167# CONFIG_IDEDISK_MULTI_MODE is not set
168CONFIG_BLK_DEV_IDECD=y
169CONFIG_BLK_DEV_IDETAPE=m
170CONFIG_BLK_DEV_IDEFLOPPY=m
171# CONFIG_BLK_DEV_IDESCSI is not set
172# CONFIG_IDE_TASK_IOCTL is not set
173
174#
175# IDE chipset support/bugfixes
176#
177CONFIG_IDE_GENERIC=y
178# CONFIG_IDE_ARM is not set
179CONFIG_BLK_DEV_GAYLE=y
180CONFIG_BLK_DEV_IDEDOUBLER=y
181CONFIG_BLK_DEV_BUDDHA=y
182# CONFIG_IDE_CHIPSETS is not set
183# CONFIG_BLK_DEV_IDEDMA is not set
184# CONFIG_IDEDMA_AUTO is not set
185# CONFIG_BLK_DEV_HD is not set
186
187#
188# SCSI device support
189#
190CONFIG_SCSI=y
191CONFIG_SCSI_PROC_FS=y
192
193#
194# SCSI support type (disk, tape, CD-ROM)
195#
196CONFIG_BLK_DEV_SD=y
197CONFIG_CHR_DEV_ST=m
198CONFIG_CHR_DEV_OSST=m
199CONFIG_BLK_DEV_SR=y
200CONFIG_BLK_DEV_SR_VENDOR=y
201CONFIG_CHR_DEV_SG=m
202
203#
204# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
205#
206# CONFIG_SCSI_MULTI_LUN is not set
207CONFIG_SCSI_CONSTANTS=y
208# CONFIG_SCSI_LOGGING is not set
209
210#
211# SCSI Transport Attributes
212#
213# CONFIG_SCSI_SPI_ATTRS is not set
214# CONFIG_SCSI_FC_ATTRS is not set
215
216#
217# SCSI low-level drivers
218#
219# CONFIG_SCSI_7000FASST is not set
220# CONFIG_SCSI_AHA152X is not set
221# CONFIG_SCSI_AHA1542 is not set
222# CONFIG_SCSI_AIC7XXX_OLD is not set
223# CONFIG_SCSI_IN2000 is not set
224# CONFIG_SCSI_SATA is not set
225# CONFIG_SCSI_BUSLOGIC is not set
226# CONFIG_SCSI_DTC3280 is not set
227# CONFIG_SCSI_EATA is not set
228# CONFIG_SCSI_EATA_PIO is not set
229# CONFIG_SCSI_FUTURE_DOMAIN is not set
230# CONFIG_SCSI_GDTH is not set
231# CONFIG_SCSI_GENERIC_NCR5380 is not set
232# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
233# CONFIG_SCSI_PPA is not set
234# CONFIG_SCSI_IMM is not set
235# CONFIG_SCSI_NCR53C406A is not set
236# CONFIG_SCSI_PAS16 is not set
237# CONFIG_SCSI_PSI240I is not set
238# CONFIG_SCSI_QLOGIC_FAS is not set
239# CONFIG_SCSI_SYM53C416 is not set
240# CONFIG_SCSI_T128 is not set
241# CONFIG_SCSI_U14_34F is not set
242# CONFIG_SCSI_DEBUG is not set
243CONFIG_A3000_SCSI=y
244CONFIG_A2091_SCSI=y
245CONFIG_GVP11_SCSI=y
246CONFIG_CYBERSTORM_SCSI=y
247CONFIG_CYBERSTORMII_SCSI=y
248CONFIG_BLZ2060_SCSI=y
249CONFIG_BLZ1230_SCSI=y
250CONFIG_FASTLANE_SCSI=y
251CONFIG_OKTAGON_SCSI=y
252
253#
254# Old CD-ROM drivers (not SCSI, not IDE)
255#
256# CONFIG_CD_NO_IDESCSI is not set
257
258#
259# Multi-device support (RAID and LVM)
260#
261CONFIG_MD=y
262CONFIG_BLK_DEV_MD=m
263CONFIG_MD_LINEAR=m
264CONFIG_MD_RAID0=m
265CONFIG_MD_RAID1=m
266# CONFIG_MD_RAID10 is not set
267CONFIG_MD_RAID5=m
268CONFIG_MD_RAID6=m
269CONFIG_MD_MULTIPATH=m
270# CONFIG_MD_FAULTY is not set
271CONFIG_BLK_DEV_DM=m
272CONFIG_DM_CRYPT=m
273CONFIG_DM_SNAPSHOT=m
274CONFIG_DM_MIRROR=m
275CONFIG_DM_ZERO=m
276
277#
278# Fusion MPT device support
279#
280
281#
282# IEEE 1394 (FireWire) support
283#
284
285#
286# I2O device support
287#
288
289#
290# Networking support
291#
292CONFIG_NET=y
293
294#
295# Networking options
296#
297CONFIG_PACKET=y
298# CONFIG_PACKET_MMAP is not set
299CONFIG_NETLINK_DEV=y
300CONFIG_UNIX=y
301CONFIG_NET_KEY=y
302CONFIG_INET=y
303# CONFIG_IP_MULTICAST is not set
304# CONFIG_IP_ADVANCED_ROUTER is not set
305# CONFIG_IP_PNP is not set
306CONFIG_NET_IPIP=m
307CONFIG_NET_IPGRE=m
308# CONFIG_ARPD is not set
309CONFIG_SYN_COOKIES=y
310CONFIG_INET_AH=m
311CONFIG_INET_ESP=m
312CONFIG_INET_IPCOMP=m
313CONFIG_INET_TUNNEL=m
314CONFIG_IP_TCPDIAG=m
315CONFIG_IP_TCPDIAG_IPV6=y
316
317#
318# IP: Virtual Server Configuration
319#
320# CONFIG_IP_VS is not set
321CONFIG_IPV6=m
322CONFIG_IPV6_PRIVACY=y
323CONFIG_INET6_AH=m
324CONFIG_INET6_ESP=m
325CONFIG_INET6_IPCOMP=m
326CONFIG_INET6_TUNNEL=m
327CONFIG_IPV6_TUNNEL=m
328CONFIG_NETFILTER=y
329# CONFIG_NETFILTER_DEBUG is not set
330
331#
332# IP: Netfilter Configuration
333#
334CONFIG_IP_NF_CONNTRACK=m
335# CONFIG_IP_NF_CT_ACCT is not set
336CONFIG_IP_NF_CONNTRACK_MARK=y
337# CONFIG_IP_NF_CT_PROTO_SCTP is not set
338CONFIG_IP_NF_FTP=m
339CONFIG_IP_NF_IRC=m
340CONFIG_IP_NF_TFTP=m
341CONFIG_IP_NF_AMANDA=m
342CONFIG_IP_NF_QUEUE=m
343CONFIG_IP_NF_IPTABLES=m
344CONFIG_IP_NF_MATCH_LIMIT=m
345CONFIG_IP_NF_MATCH_IPRANGE=m
346CONFIG_IP_NF_MATCH_MAC=m
347CONFIG_IP_NF_MATCH_PKTTYPE=m
348CONFIG_IP_NF_MATCH_MARK=m
349CONFIG_IP_NF_MATCH_MULTIPORT=m
350CONFIG_IP_NF_MATCH_TOS=m
351CONFIG_IP_NF_MATCH_RECENT=m
352CONFIG_IP_NF_MATCH_ECN=m
353CONFIG_IP_NF_MATCH_DSCP=m
354CONFIG_IP_NF_MATCH_AH_ESP=m
355CONFIG_IP_NF_MATCH_LENGTH=m
356CONFIG_IP_NF_MATCH_TTL=m
357CONFIG_IP_NF_MATCH_TCPMSS=m
358CONFIG_IP_NF_MATCH_HELPER=m
359CONFIG_IP_NF_MATCH_STATE=m
360CONFIG_IP_NF_MATCH_CONNTRACK=m
361CONFIG_IP_NF_MATCH_OWNER=m
362CONFIG_IP_NF_MATCH_ADDRTYPE=m
363CONFIG_IP_NF_MATCH_REALM=m
364# CONFIG_IP_NF_MATCH_SCTP is not set
365# CONFIG_IP_NF_MATCH_COMMENT is not set
366CONFIG_IP_NF_MATCH_CONNMARK=m
367CONFIG_IP_NF_MATCH_HASHLIMIT=m
368CONFIG_IP_NF_FILTER=m
369CONFIG_IP_NF_TARGET_REJECT=m
370CONFIG_IP_NF_TARGET_LOG=m
371CONFIG_IP_NF_TARGET_ULOG=m
372CONFIG_IP_NF_TARGET_TCPMSS=m
373CONFIG_IP_NF_NAT=m
374CONFIG_IP_NF_NAT_NEEDED=y
375CONFIG_IP_NF_TARGET_MASQUERADE=m
376CONFIG_IP_NF_TARGET_REDIRECT=m
377CONFIG_IP_NF_TARGET_NETMAP=m
378CONFIG_IP_NF_TARGET_SAME=m
379CONFIG_IP_NF_NAT_SNMP_BASIC=m
380CONFIG_IP_NF_NAT_IRC=m
381CONFIG_IP_NF_NAT_FTP=m
382CONFIG_IP_NF_NAT_TFTP=m
383CONFIG_IP_NF_NAT_AMANDA=m
384CONFIG_IP_NF_MANGLE=m
385CONFIG_IP_NF_TARGET_TOS=m
386CONFIG_IP_NF_TARGET_ECN=m
387CONFIG_IP_NF_TARGET_DSCP=m
388CONFIG_IP_NF_TARGET_MARK=m
389CONFIG_IP_NF_TARGET_CLASSIFY=m
390CONFIG_IP_NF_TARGET_CONNMARK=m
391# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
392CONFIG_IP_NF_RAW=m
393CONFIG_IP_NF_TARGET_NOTRACK=m
394CONFIG_IP_NF_ARPTABLES=m
395CONFIG_IP_NF_ARPFILTER=m
396CONFIG_IP_NF_ARP_MANGLE=m
397CONFIG_IP_NF_COMPAT_IPCHAINS=m
398CONFIG_IP_NF_COMPAT_IPFWADM=m
399
400#
401# IPv6: Netfilter Configuration
402#
403CONFIG_IP6_NF_QUEUE=m
404CONFIG_IP6_NF_IPTABLES=m
405CONFIG_IP6_NF_MATCH_LIMIT=m
406CONFIG_IP6_NF_MATCH_MAC=m
407CONFIG_IP6_NF_MATCH_RT=m
408CONFIG_IP6_NF_MATCH_OPTS=m
409CONFIG_IP6_NF_MATCH_FRAG=m
410CONFIG_IP6_NF_MATCH_HL=m
411CONFIG_IP6_NF_MATCH_MULTIPORT=m
412CONFIG_IP6_NF_MATCH_OWNER=m
413CONFIG_IP6_NF_MATCH_MARK=m
414CONFIG_IP6_NF_MATCH_IPV6HEADER=m
415CONFIG_IP6_NF_MATCH_AHESP=m
416CONFIG_IP6_NF_MATCH_LENGTH=m
417CONFIG_IP6_NF_MATCH_EUI64=m
418CONFIG_IP6_NF_FILTER=m
419CONFIG_IP6_NF_TARGET_LOG=m
420CONFIG_IP6_NF_MANGLE=m
421CONFIG_IP6_NF_TARGET_MARK=m
422CONFIG_IP6_NF_RAW=m
423CONFIG_XFRM=y
424CONFIG_XFRM_USER=m
425
426#
427# SCTP Configuration (EXPERIMENTAL)
428#
429CONFIG_IP_SCTP=m
430# CONFIG_SCTP_DBG_MSG is not set
431# CONFIG_SCTP_DBG_OBJCNT is not set
432# CONFIG_SCTP_HMAC_NONE is not set
433# CONFIG_SCTP_HMAC_SHA1 is not set
434CONFIG_SCTP_HMAC_MD5=y
435# CONFIG_ATM is not set
436# CONFIG_BRIDGE is not set
437# CONFIG_VLAN_8021Q is not set
438# CONFIG_DECNET is not set
439CONFIG_LLC=m
440# CONFIG_LLC2 is not set
441CONFIG_IPX=m
442# CONFIG_IPX_INTERN is not set
443CONFIG_ATALK=m
444# CONFIG_DEV_APPLETALK is not set
445# CONFIG_X25 is not set
446# CONFIG_LAPB is not set
447# CONFIG_NET_DIVERT is not set
448# CONFIG_ECONET is not set
449# CONFIG_WAN_ROUTER is not set
450
451#
452# QoS and/or fair queueing
453#
454# CONFIG_NET_SCHED is not set
455CONFIG_NET_CLS_ROUTE=y
456
457#
458# Network testing
459#
460# CONFIG_NET_PKTGEN is not set
461CONFIG_NETPOLL=y
462# CONFIG_NETPOLL_RX is not set
463# CONFIG_NETPOLL_TRAP is not set
464CONFIG_NET_POLL_CONTROLLER=y
465# CONFIG_HAMRADIO is not set
466# CONFIG_IRDA is not set
467# CONFIG_BT is not set
468CONFIG_NETDEVICES=y
469CONFIG_DUMMY=m
470# CONFIG_BONDING is not set
471CONFIG_EQUALIZER=m
472# CONFIG_TUN is not set
473# CONFIG_ETHERTAP is not set
474
475#
476# ARCnet devices
477#
478# CONFIG_ARCNET is not set
479
480#
481# Ethernet (10 or 100Mbit)
482#
483CONFIG_NET_ETHERNET=y
484CONFIG_MII=m
485CONFIG_ARIADNE=m
486CONFIG_A2065=m
487CONFIG_HYDRA=m
488CONFIG_ZORRO8390=m
489CONFIG_APNE=m
490# CONFIG_NET_VENDOR_3COM is not set
491# CONFIG_LANCE is not set
492# CONFIG_NET_VENDOR_SMC is not set
493# CONFIG_NET_VENDOR_RACAL is not set
494# CONFIG_AT1700 is not set
495# CONFIG_DEPCA is not set
496# CONFIG_HP100 is not set
497# CONFIG_NET_ISA is not set
498# CONFIG_NET_PCI is not set
499# CONFIG_NET_POCKET is not set
500
501#
502# Ethernet (1000 Mbit)
503#
504
505#
506# Ethernet (10000 Mbit)
507#
508
509#
510# Token Ring devices
511#
512# CONFIG_TR is not set
513
514#
515# Wireless LAN (non-hamradio)
516#
517# CONFIG_NET_RADIO is not set
518
519#
520# Wan interfaces
521#
522# CONFIG_WAN is not set
523CONFIG_PLIP=m
524CONFIG_PPP=m
525# CONFIG_PPP_MULTILINK is not set
526CONFIG_PPP_FILTER=y
527CONFIG_PPP_ASYNC=m
528CONFIG_PPP_SYNC_TTY=m
529CONFIG_PPP_DEFLATE=m
530CONFIG_PPP_BSDCOMP=m
531CONFIG_PPPOE=m
532CONFIG_SLIP=m
533CONFIG_SLIP_COMPRESSED=y
534CONFIG_SLIP_SMART=y
535CONFIG_SLIP_MODE_SLIP6=y
536CONFIG_SHAPER=m
537CONFIG_NETCONSOLE=m
538
539#
540# ISDN subsystem
541#
542# CONFIG_ISDN is not set
543
544#
545# Telephony Support
546#
547# CONFIG_PHONE is not set
548
549#
550# Input device support
551#
552CONFIG_INPUT=y
553
554#
555# Userland interfaces
556#
557CONFIG_INPUT_MOUSEDEV=y
558CONFIG_INPUT_MOUSEDEV_PSAUX=y
559CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
560CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
561# CONFIG_INPUT_JOYDEV is not set
562# CONFIG_INPUT_TSDEV is not set
563# CONFIG_INPUT_EVDEV is not set
564# CONFIG_INPUT_EVBUG is not set
565
566#
567# Input I/O drivers
568#
569# CONFIG_GAMEPORT is not set
570CONFIG_SOUND_GAMEPORT=y
571CONFIG_SERIO=m
572CONFIG_SERIO_SERPORT=m
573# CONFIG_SERIO_CT82C710 is not set
574# CONFIG_SERIO_PARKBD is not set
575# CONFIG_SERIO_RAW is not set
576
577#
578# Input Device Drivers
579#
580CONFIG_INPUT_KEYBOARD=y
581# CONFIG_KEYBOARD_ATKBD is not set
582# CONFIG_KEYBOARD_SUNKBD is not set
583# CONFIG_KEYBOARD_LKKBD is not set
584# CONFIG_KEYBOARD_XTKBD is not set
585# CONFIG_KEYBOARD_NEWTON is not set
586CONFIG_KEYBOARD_AMIGA=y
587CONFIG_INPUT_MOUSE=y
588# CONFIG_MOUSE_PS2 is not set
589# CONFIG_MOUSE_SERIAL is not set
590# CONFIG_MOUSE_INPORT is not set
591# CONFIG_MOUSE_LOGIBM is not set
592# CONFIG_MOUSE_PC110PAD is not set
593CONFIG_MOUSE_AMIGA=y
594# CONFIG_MOUSE_VSXXXAA is not set
595CONFIG_INPUT_JOYSTICK=y
596# CONFIG_JOYSTICK_IFORCE is not set
597# CONFIG_JOYSTICK_WARRIOR is not set
598# CONFIG_JOYSTICK_MAGELLAN is not set
599# CONFIG_JOYSTICK_SPACEORB is not set
600# CONFIG_JOYSTICK_SPACEBALL is not set
601# CONFIG_JOYSTICK_STINGER is not set
602# CONFIG_JOYSTICK_TWIDDLER is not set
603# CONFIG_JOYSTICK_DB9 is not set
604# CONFIG_JOYSTICK_GAMECON is not set
605# CONFIG_JOYSTICK_TURBOGRAFX is not set
606CONFIG_JOYSTICK_AMIGA=m
607# CONFIG_INPUT_TOUCHSCREEN is not set
608# CONFIG_INPUT_MISC is not set
609
610#
611# Character devices
612#
613CONFIG_VT=y
614CONFIG_VT_CONSOLE=y
615CONFIG_HW_CONSOLE=y
616# CONFIG_SERIAL_NONSTANDARD is not set
617CONFIG_A2232=m
618
619#
620# Serial drivers
621#
622# CONFIG_SERIAL_8250 is not set
623
624#
625# Non-8250 serial port support
626#
627CONFIG_UNIX98_PTYS=y
628CONFIG_LEGACY_PTYS=y
629CONFIG_LEGACY_PTY_COUNT=256
630CONFIG_PRINTER=m
631# CONFIG_LP_CONSOLE is not set
632# CONFIG_PPDEV is not set
633# CONFIG_TIPAR is not set
634
635#
636# IPMI
637#
638# CONFIG_IPMI_HANDLER is not set
639
640#
641# Watchdog Cards
642#
643# CONFIG_WATCHDOG is not set
644CONFIG_GEN_RTC=m
645CONFIG_GEN_RTC_X=y
646# CONFIG_DTLK is not set
647# CONFIG_R3964 is not set
648
649#
650# Ftape, the floppy tape device driver
651#
652# CONFIG_DRM is not set
653# CONFIG_RAW_DRIVER is not set
654
655#
656# I2C support
657#
658# CONFIG_I2C is not set
659
660#
661# Dallas's 1-wire bus
662#
663# CONFIG_W1 is not set
664
665#
666# Misc devices
667#
668
669#
670# Multimedia devices
671#
672# CONFIG_VIDEO_DEV is not set
673
674#
675# Digital Video Broadcasting Devices
676#
677# CONFIG_DVB is not set
678
679#
680# Graphics support
681#
682CONFIG_FB=y
683CONFIG_FB_MODE_HELPERS=y
684# CONFIG_FB_TILEBLITTING is not set
685CONFIG_FB_CIRRUS=m
686CONFIG_FB_AMIGA=y
687CONFIG_FB_AMIGA_OCS=y
688CONFIG_FB_AMIGA_ECS=y
689CONFIG_FB_AMIGA_AGA=y
690CONFIG_FB_FM2=y
691# CONFIG_FB_VIRTUAL is not set
692
693#
694# Console display driver support
695#
696CONFIG_DUMMY_CONSOLE=y
697CONFIG_FRAMEBUFFER_CONSOLE=y
698# CONFIG_FONTS is not set
699CONFIG_FONT_8x8=y
700CONFIG_FONT_8x16=y
701CONFIG_FONT_PEARL_8x8=y
702
703#
704# Logo configuration
705#
706CONFIG_LOGO=y
707CONFIG_LOGO_LINUX_MONO=y
708CONFIG_LOGO_LINUX_VGA16=y
709CONFIG_LOGO_LINUX_CLUT224=y
710
711#
712# Sound
713#
714CONFIG_SOUND=m
715CONFIG_DMASOUND_PAULA=m
716CONFIG_DMASOUND=m
717
718#
719# USB support
720#
721# CONFIG_USB_ARCH_HAS_HCD is not set
722# CONFIG_USB_ARCH_HAS_OHCI is not set
723
724#
725# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
726#
727
728#
729# USB Gadget Support
730#
731# CONFIG_USB_GADGET is not set
732
733#
734# MMC/SD Card support
735#
736# CONFIG_MMC is not set
737
738#
739# Character devices
740#
741CONFIG_AMIGA_BUILTIN_SERIAL=y
742# CONFIG_WHIPPET_SERIAL is not set
743CONFIG_MULTIFACE_III_TTY=m
744# CONFIG_SERIAL_CONSOLE is not set
745
746#
747# File systems
748#
749CONFIG_EXT2_FS=y
750# CONFIG_EXT2_FS_XATTR is not set
751CONFIG_EXT3_FS=y
752# CONFIG_EXT3_FS_XATTR is not set
753CONFIG_JBD=y
754# CONFIG_JBD_DEBUG is not set
755CONFIG_REISERFS_FS=m
756# CONFIG_REISERFS_CHECK is not set
757# CONFIG_REISERFS_PROC_INFO is not set
758# CONFIG_REISERFS_FS_XATTR is not set
759CONFIG_JFS_FS=m
760# CONFIG_JFS_POSIX_ACL is not set
761# CONFIG_JFS_DEBUG is not set
762# CONFIG_JFS_STATISTICS is not set
763CONFIG_FS_POSIX_ACL=y
764CONFIG_XFS_FS=m
765# CONFIG_XFS_RT is not set
766# CONFIG_XFS_QUOTA is not set
767# CONFIG_XFS_SECURITY is not set
768# CONFIG_XFS_POSIX_ACL is not set
769CONFIG_MINIX_FS=y
770# CONFIG_ROMFS_FS is not set
771CONFIG_QUOTA=y
772# CONFIG_QFMT_V1 is not set
773# CONFIG_QFMT_V2 is not set
774CONFIG_QUOTACTL=y
775CONFIG_DNOTIFY=y
776CONFIG_AUTOFS_FS=m
777CONFIG_AUTOFS4_FS=m
778
779#
780# CD-ROM/DVD Filesystems
781#
782CONFIG_ISO9660_FS=y
783CONFIG_JOLIET=y
784CONFIG_ZISOFS=y
785CONFIG_ZISOFS_FS=y
786CONFIG_UDF_FS=m
787CONFIG_UDF_NLS=y
788
789#
790# DOS/FAT/NT Filesystems
791#
792CONFIG_FAT_FS=m
793CONFIG_MSDOS_FS=m
794CONFIG_VFAT_FS=m
795CONFIG_FAT_DEFAULT_CODEPAGE=437
796CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
797# CONFIG_NTFS_FS is not set
798
799#
800# Pseudo filesystems
801#
802CONFIG_PROC_FS=y
803CONFIG_PROC_KCORE=y
804CONFIG_SYSFS=y
805# CONFIG_DEVFS_FS is not set
806# CONFIG_DEVPTS_FS_XATTR is not set
807CONFIG_TMPFS=y
808# CONFIG_TMPFS_XATTR is not set
809# CONFIG_HUGETLB_PAGE is not set
810CONFIG_RAMFS=y
811
812#
813# Miscellaneous filesystems
814#
815# CONFIG_ADFS_FS is not set
816CONFIG_AFFS_FS=y
817CONFIG_HFS_FS=m
818CONFIG_HFSPLUS_FS=m
819# CONFIG_BEFS_FS is not set
820# CONFIG_BFS_FS is not set
821# CONFIG_EFS_FS is not set
822CONFIG_CRAMFS=m
823# CONFIG_VXFS_FS is not set
824CONFIG_HPFS_FS=m
825# CONFIG_QNX4FS_FS is not set
826CONFIG_SYSV_FS=m
827CONFIG_UFS_FS=m
828# CONFIG_UFS_FS_WRITE is not set
829
830#
831# Network File Systems
832#
833CONFIG_NFS_FS=m
834CONFIG_NFS_V3=y
835CONFIG_NFS_V4=y
836# CONFIG_NFS_DIRECTIO is not set
837CONFIG_NFSD=m
838CONFIG_NFSD_V3=y
839CONFIG_NFSD_V4=y
840CONFIG_NFSD_TCP=y
841CONFIG_LOCKD=m
842CONFIG_LOCKD_V4=y
843CONFIG_EXPORTFS=m
844CONFIG_SUNRPC=m
845CONFIG_SUNRPC_GSS=m
846CONFIG_RPCSEC_GSS_KRB5=m
847# CONFIG_RPCSEC_GSS_SPKM3 is not set
848CONFIG_SMB_FS=m
849CONFIG_SMB_NLS_DEFAULT=y
850CONFIG_SMB_NLS_REMOTE="cp437"
851# CONFIG_CIFS is not set
852CONFIG_NCP_FS=m
853# CONFIG_NCPFS_PACKET_SIGNING is not set
854# CONFIG_NCPFS_IOCTL_LOCKING is not set
855# CONFIG_NCPFS_STRONG is not set
856CONFIG_NCPFS_NFS_NS=y
857CONFIG_NCPFS_OS2_NS=y
858# CONFIG_NCPFS_SMALLDOS is not set
859CONFIG_NCPFS_NLS=y
860# CONFIG_NCPFS_EXTRAS is not set
861CONFIG_CODA_FS=m
862# CONFIG_CODA_FS_OLD_API is not set
863# CONFIG_AFS_FS is not set
864
865#
866# Partition Types
867#
868# CONFIG_PARTITION_ADVANCED is not set
869CONFIG_AMIGA_PARTITION=y
870CONFIG_MSDOS_PARTITION=y
871
872#
873# Native Language Support
874#
875CONFIG_NLS=y
876CONFIG_NLS_DEFAULT="iso8859-1"
877CONFIG_NLS_CODEPAGE_437=y
878CONFIG_NLS_CODEPAGE_737=m
879CONFIG_NLS_CODEPAGE_775=m
880CONFIG_NLS_CODEPAGE_850=m
881CONFIG_NLS_CODEPAGE_852=m
882CONFIG_NLS_CODEPAGE_855=m
883CONFIG_NLS_CODEPAGE_857=m
884CONFIG_NLS_CODEPAGE_860=m
885CONFIG_NLS_CODEPAGE_861=m
886CONFIG_NLS_CODEPAGE_862=m
887CONFIG_NLS_CODEPAGE_863=m
888CONFIG_NLS_CODEPAGE_864=m
889CONFIG_NLS_CODEPAGE_865=m
890CONFIG_NLS_CODEPAGE_866=m
891CONFIG_NLS_CODEPAGE_869=m
892CONFIG_NLS_CODEPAGE_936=m
893CONFIG_NLS_CODEPAGE_950=m
894CONFIG_NLS_CODEPAGE_932=m
895CONFIG_NLS_CODEPAGE_949=m
896CONFIG_NLS_CODEPAGE_874=m
897CONFIG_NLS_ISO8859_8=m
898CONFIG_NLS_CODEPAGE_1250=m
899CONFIG_NLS_CODEPAGE_1251=m
900CONFIG_NLS_ASCII=m
901CONFIG_NLS_ISO8859_1=y
902CONFIG_NLS_ISO8859_2=m
903CONFIG_NLS_ISO8859_3=m
904CONFIG_NLS_ISO8859_4=m
905CONFIG_NLS_ISO8859_5=m
906CONFIG_NLS_ISO8859_6=m
907CONFIG_NLS_ISO8859_7=m
908CONFIG_NLS_ISO8859_9=m
909CONFIG_NLS_ISO8859_13=m
910CONFIG_NLS_ISO8859_14=m
911CONFIG_NLS_ISO8859_15=m
912CONFIG_NLS_KOI8_R=m
913CONFIG_NLS_KOI8_U=m
914CONFIG_NLS_UTF8=m
915
916#
917# Kernel hacking
918#
919CONFIG_DEBUG_KERNEL=y
920CONFIG_MAGIC_SYSRQ=y
921# CONFIG_SCHEDSTATS is not set
922# CONFIG_DEBUG_SLAB is not set
923# CONFIG_DEBUG_KOBJECT is not set
924# CONFIG_DEBUG_BUGVERBOSE is not set
925# CONFIG_DEBUG_INFO is not set
926
927#
928# Security options
929#
930# CONFIG_KEYS is not set
931# CONFIG_SECURITY is not set
932
933#
934# Cryptographic options
935#
936CONFIG_CRYPTO=y
937CONFIG_CRYPTO_HMAC=y
938CONFIG_CRYPTO_NULL=m
939CONFIG_CRYPTO_MD4=m
940CONFIG_CRYPTO_MD5=m
941CONFIG_CRYPTO_SHA1=m
942CONFIG_CRYPTO_SHA256=m
943CONFIG_CRYPTO_SHA512=m
944# CONFIG_CRYPTO_WP512 is not set
945CONFIG_CRYPTO_DES=m
946CONFIG_CRYPTO_BLOWFISH=m
947CONFIG_CRYPTO_TWOFISH=m
948CONFIG_CRYPTO_SERPENT=m
949CONFIG_CRYPTO_AES=m
950CONFIG_CRYPTO_CAST5=m
951CONFIG_CRYPTO_CAST6=m
952CONFIG_CRYPTO_TEA=m
953CONFIG_CRYPTO_ARC4=m
954CONFIG_CRYPTO_KHAZAD=m
955CONFIG_CRYPTO_ANUBIS=m
956CONFIG_CRYPTO_DEFLATE=m
957CONFIG_CRYPTO_MICHAEL_MIC=m
958CONFIG_CRYPTO_CRC32C=m
959CONFIG_CRYPTO_TEST=m
960
961#
962# Library routines
963#
964CONFIG_CRC_CCITT=m
965CONFIG_CRC32=y
966CONFIG_LIBCRC32C=m
967CONFIG_ZLIB_INFLATE=y
968CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
new file mode 100644
index 000000000000..648361b544c0
--- /dev/null
+++ b/arch/m68k/configs/apollo_defconfig
@@ -0,0 +1,825 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:22:58 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-apollo"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63# CONFIG_ATARI is not set
64# CONFIG_MAC is not set
65CONFIG_APOLLO=y
66# CONFIG_VME is not set
67# CONFIG_HP300 is not set
68# CONFIG_SUN3X is not set
69# CONFIG_Q40 is not set
70
71#
72# Processor type
73#
74CONFIG_M68020=y
75CONFIG_M68030=y
76CONFIG_M68040=y
77CONFIG_M68060=y
78CONFIG_MMU_MOTOROLA=y
79CONFIG_M68KFPU_EMU=y
80CONFIG_M68KFPU_EMU_EXTRAPREC=y
81# CONFIG_M68KFPU_EMU_ONLY is not set
82# CONFIG_ADVANCED is not set
83
84#
85# General setup
86#
87CONFIG_BINFMT_ELF=y
88CONFIG_BINFMT_AOUT=m
89CONFIG_BINFMT_MISC=m
90CONFIG_HEARTBEAT=y
91CONFIG_PROC_HARDWARE=y
92
93#
94# Device Drivers
95#
96
97#
98# Generic Driver Options
99#
100CONFIG_STANDALONE=y
101CONFIG_PREVENT_FIRMWARE_BUILD=y
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#
112# CONFIG_PARPORT is not set
113
114#
115# Plug and Play support
116#
117
118#
119# Block devices
120#
121CONFIG_BLK_DEV_LOOP=y
122CONFIG_BLK_DEV_CRYPTOLOOP=m
123CONFIG_BLK_DEV_NBD=m
124CONFIG_BLK_DEV_RAM=y
125CONFIG_BLK_DEV_RAM_COUNT=16
126CONFIG_BLK_DEV_RAM_SIZE=4096
127CONFIG_BLK_DEV_INITRD=y
128CONFIG_INITRAMFS_SOURCE=""
129CONFIG_CDROM_PKTCDVD=m
130CONFIG_CDROM_PKTCDVD_BUFFERS=8
131# CONFIG_CDROM_PKTCDVD_WCACHE is not set
132
133#
134# IO Schedulers
135#
136CONFIG_IOSCHED_NOOP=y
137CONFIG_IOSCHED_AS=y
138CONFIG_IOSCHED_DEADLINE=y
139CONFIG_IOSCHED_CFQ=y
140
141#
142# ATA/ATAPI/MFM/RLL support
143#
144# CONFIG_IDE is not set
145
146#
147# SCSI device support
148#
149CONFIG_SCSI=y
150CONFIG_SCSI_PROC_FS=y
151
152#
153# SCSI support type (disk, tape, CD-ROM)
154#
155CONFIG_BLK_DEV_SD=y
156CONFIG_CHR_DEV_ST=m
157# CONFIG_CHR_DEV_OSST is not set
158CONFIG_BLK_DEV_SR=y
159CONFIG_BLK_DEV_SR_VENDOR=y
160CONFIG_CHR_DEV_SG=m
161
162#
163# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
164#
165# CONFIG_SCSI_MULTI_LUN is not set
166CONFIG_SCSI_CONSTANTS=y
167# CONFIG_SCSI_LOGGING is not set
168
169#
170# SCSI Transport Attributes
171#
172# CONFIG_SCSI_SPI_ATTRS is not set
173# CONFIG_SCSI_FC_ATTRS is not set
174
175#
176# SCSI low-level drivers
177#
178# CONFIG_SCSI_SATA is not set
179# CONFIG_SCSI_DEBUG is not set
180
181#
182# Multi-device support (RAID and LVM)
183#
184CONFIG_MD=y
185CONFIG_BLK_DEV_MD=m
186CONFIG_MD_LINEAR=m
187CONFIG_MD_RAID0=m
188CONFIG_MD_RAID1=m
189# CONFIG_MD_RAID10 is not set
190CONFIG_MD_RAID5=m
191CONFIG_MD_RAID6=m
192CONFIG_MD_MULTIPATH=m
193# CONFIG_MD_FAULTY is not set
194CONFIG_BLK_DEV_DM=m
195CONFIG_DM_CRYPT=m
196CONFIG_DM_SNAPSHOT=m
197CONFIG_DM_MIRROR=m
198CONFIG_DM_ZERO=m
199
200#
201# Fusion MPT device support
202#
203
204#
205# IEEE 1394 (FireWire) support
206#
207
208#
209# I2O device support
210#
211
212#
213# Networking support
214#
215CONFIG_NET=y
216
217#
218# Networking options
219#
220CONFIG_PACKET=y
221# CONFIG_PACKET_MMAP is not set
222CONFIG_NETLINK_DEV=y
223CONFIG_UNIX=y
224CONFIG_NET_KEY=y
225CONFIG_INET=y
226# CONFIG_IP_MULTICAST is not set
227# CONFIG_IP_ADVANCED_ROUTER is not set
228CONFIG_IP_PNP=y
229CONFIG_IP_PNP_DHCP=y
230CONFIG_IP_PNP_BOOTP=y
231CONFIG_IP_PNP_RARP=y
232CONFIG_NET_IPIP=m
233CONFIG_NET_IPGRE=m
234# CONFIG_ARPD is not set
235CONFIG_SYN_COOKIES=y
236CONFIG_INET_AH=m
237CONFIG_INET_ESP=m
238CONFIG_INET_IPCOMP=m
239CONFIG_INET_TUNNEL=m
240CONFIG_IP_TCPDIAG=m
241CONFIG_IP_TCPDIAG_IPV6=y
242
243#
244# IP: Virtual Server Configuration
245#
246# CONFIG_IP_VS is not set
247CONFIG_IPV6=m
248CONFIG_IPV6_PRIVACY=y
249CONFIG_INET6_AH=m
250CONFIG_INET6_ESP=m
251CONFIG_INET6_IPCOMP=m
252CONFIG_INET6_TUNNEL=m
253CONFIG_IPV6_TUNNEL=m
254CONFIG_NETFILTER=y
255# CONFIG_NETFILTER_DEBUG is not set
256
257#
258# IP: Netfilter Configuration
259#
260CONFIG_IP_NF_CONNTRACK=m
261# CONFIG_IP_NF_CT_ACCT is not set
262CONFIG_IP_NF_CONNTRACK_MARK=y
263# CONFIG_IP_NF_CT_PROTO_SCTP is not set
264CONFIG_IP_NF_FTP=m
265CONFIG_IP_NF_IRC=m
266CONFIG_IP_NF_TFTP=m
267CONFIG_IP_NF_AMANDA=m
268CONFIG_IP_NF_QUEUE=m
269CONFIG_IP_NF_IPTABLES=m
270CONFIG_IP_NF_MATCH_LIMIT=m
271CONFIG_IP_NF_MATCH_IPRANGE=m
272CONFIG_IP_NF_MATCH_MAC=m
273CONFIG_IP_NF_MATCH_PKTTYPE=m
274CONFIG_IP_NF_MATCH_MARK=m
275CONFIG_IP_NF_MATCH_MULTIPORT=m
276CONFIG_IP_NF_MATCH_TOS=m
277CONFIG_IP_NF_MATCH_RECENT=m
278CONFIG_IP_NF_MATCH_ECN=m
279CONFIG_IP_NF_MATCH_DSCP=m
280CONFIG_IP_NF_MATCH_AH_ESP=m
281CONFIG_IP_NF_MATCH_LENGTH=m
282CONFIG_IP_NF_MATCH_TTL=m
283CONFIG_IP_NF_MATCH_TCPMSS=m
284CONFIG_IP_NF_MATCH_HELPER=m
285CONFIG_IP_NF_MATCH_STATE=m
286CONFIG_IP_NF_MATCH_CONNTRACK=m
287CONFIG_IP_NF_MATCH_OWNER=m
288CONFIG_IP_NF_MATCH_ADDRTYPE=m
289CONFIG_IP_NF_MATCH_REALM=m
290# CONFIG_IP_NF_MATCH_SCTP is not set
291# CONFIG_IP_NF_MATCH_COMMENT is not set
292CONFIG_IP_NF_MATCH_CONNMARK=m
293CONFIG_IP_NF_MATCH_HASHLIMIT=m
294CONFIG_IP_NF_FILTER=m
295CONFIG_IP_NF_TARGET_REJECT=m
296CONFIG_IP_NF_TARGET_LOG=m
297CONFIG_IP_NF_TARGET_ULOG=m
298CONFIG_IP_NF_TARGET_TCPMSS=m
299CONFIG_IP_NF_NAT=m
300CONFIG_IP_NF_NAT_NEEDED=y
301CONFIG_IP_NF_TARGET_MASQUERADE=m
302CONFIG_IP_NF_TARGET_REDIRECT=m
303CONFIG_IP_NF_TARGET_NETMAP=m
304CONFIG_IP_NF_TARGET_SAME=m
305CONFIG_IP_NF_NAT_SNMP_BASIC=m
306CONFIG_IP_NF_NAT_IRC=m
307CONFIG_IP_NF_NAT_FTP=m
308CONFIG_IP_NF_NAT_TFTP=m
309CONFIG_IP_NF_NAT_AMANDA=m
310CONFIG_IP_NF_MANGLE=m
311CONFIG_IP_NF_TARGET_TOS=m
312CONFIG_IP_NF_TARGET_ECN=m
313CONFIG_IP_NF_TARGET_DSCP=m
314CONFIG_IP_NF_TARGET_MARK=m
315CONFIG_IP_NF_TARGET_CLASSIFY=m
316CONFIG_IP_NF_TARGET_CONNMARK=m
317# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
318CONFIG_IP_NF_RAW=m
319CONFIG_IP_NF_TARGET_NOTRACK=m
320CONFIG_IP_NF_ARPTABLES=m
321CONFIG_IP_NF_ARPFILTER=m
322CONFIG_IP_NF_ARP_MANGLE=m
323CONFIG_IP_NF_COMPAT_IPCHAINS=m
324CONFIG_IP_NF_COMPAT_IPFWADM=m
325
326#
327# IPv6: Netfilter Configuration
328#
329CONFIG_IP6_NF_QUEUE=m
330CONFIG_IP6_NF_IPTABLES=m
331CONFIG_IP6_NF_MATCH_LIMIT=m
332CONFIG_IP6_NF_MATCH_MAC=m
333CONFIG_IP6_NF_MATCH_RT=m
334CONFIG_IP6_NF_MATCH_OPTS=m
335CONFIG_IP6_NF_MATCH_FRAG=m
336CONFIG_IP6_NF_MATCH_HL=m
337CONFIG_IP6_NF_MATCH_MULTIPORT=m
338CONFIG_IP6_NF_MATCH_OWNER=m
339CONFIG_IP6_NF_MATCH_MARK=m
340CONFIG_IP6_NF_MATCH_IPV6HEADER=m
341CONFIG_IP6_NF_MATCH_AHESP=m
342CONFIG_IP6_NF_MATCH_LENGTH=m
343CONFIG_IP6_NF_MATCH_EUI64=m
344CONFIG_IP6_NF_FILTER=m
345CONFIG_IP6_NF_TARGET_LOG=m
346CONFIG_IP6_NF_MANGLE=m
347CONFIG_IP6_NF_TARGET_MARK=m
348CONFIG_IP6_NF_RAW=m
349CONFIG_XFRM=y
350CONFIG_XFRM_USER=m
351
352#
353# SCTP Configuration (EXPERIMENTAL)
354#
355CONFIG_IP_SCTP=m
356# CONFIG_SCTP_DBG_MSG is not set
357# CONFIG_SCTP_DBG_OBJCNT is not set
358# CONFIG_SCTP_HMAC_NONE is not set
359# CONFIG_SCTP_HMAC_SHA1 is not set
360CONFIG_SCTP_HMAC_MD5=y
361# CONFIG_ATM is not set
362# CONFIG_BRIDGE is not set
363# CONFIG_VLAN_8021Q is not set
364# CONFIG_DECNET is not set
365CONFIG_LLC=m
366# CONFIG_LLC2 is not set
367CONFIG_IPX=m
368# CONFIG_IPX_INTERN is not set
369CONFIG_ATALK=m
370# CONFIG_DEV_APPLETALK is not set
371# CONFIG_X25 is not set
372# CONFIG_LAPB is not set
373# CONFIG_NET_DIVERT is not set
374# CONFIG_ECONET is not set
375# CONFIG_WAN_ROUTER is not set
376
377#
378# QoS and/or fair queueing
379#
380# CONFIG_NET_SCHED is not set
381CONFIG_NET_CLS_ROUTE=y
382
383#
384# Network testing
385#
386# CONFIG_NET_PKTGEN is not set
387CONFIG_NETPOLL=y
388# CONFIG_NETPOLL_RX is not set
389# CONFIG_NETPOLL_TRAP is not set
390CONFIG_NET_POLL_CONTROLLER=y
391# CONFIG_HAMRADIO is not set
392# CONFIG_IRDA is not set
393# CONFIG_BT is not set
394CONFIG_NETDEVICES=y
395CONFIG_DUMMY=m
396# CONFIG_BONDING is not set
397CONFIG_EQUALIZER=m
398# CONFIG_TUN is not set
399# CONFIG_ETHERTAP is not set
400
401#
402# Ethernet (10 or 100Mbit)
403#
404CONFIG_NET_ETHERNET=y
405CONFIG_MII=m
406CONFIG_APOLLO_ELPLUS=y
407
408#
409# Ethernet (1000 Mbit)
410#
411
412#
413# Ethernet (10000 Mbit)
414#
415
416#
417# Token Ring devices
418#
419
420#
421# Wireless LAN (non-hamradio)
422#
423# CONFIG_NET_RADIO is not set
424
425#
426# Wan interfaces
427#
428# CONFIG_WAN is not set
429CONFIG_PPP=m
430# CONFIG_PPP_MULTILINK is not set
431CONFIG_PPP_FILTER=y
432CONFIG_PPP_ASYNC=m
433CONFIG_PPP_SYNC_TTY=m
434CONFIG_PPP_DEFLATE=m
435CONFIG_PPP_BSDCOMP=m
436CONFIG_PPPOE=m
437CONFIG_SLIP=m
438CONFIG_SLIP_COMPRESSED=y
439CONFIG_SLIP_SMART=y
440CONFIG_SLIP_MODE_SLIP6=y
441CONFIG_SHAPER=m
442CONFIG_NETCONSOLE=m
443
444#
445# ISDN subsystem
446#
447# CONFIG_ISDN is not set
448
449#
450# Telephony Support
451#
452# CONFIG_PHONE is not set
453
454#
455# Input device support
456#
457CONFIG_INPUT=y
458
459#
460# Userland interfaces
461#
462CONFIG_INPUT_MOUSEDEV=y
463CONFIG_INPUT_MOUSEDEV_PSAUX=y
464CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
465CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
466# CONFIG_INPUT_JOYDEV is not set
467# CONFIG_INPUT_TSDEV is not set
468# CONFIG_INPUT_EVDEV is not set
469# CONFIG_INPUT_EVBUG is not set
470
471#
472# Input I/O drivers
473#
474# CONFIG_GAMEPORT is not set
475CONFIG_SOUND_GAMEPORT=y
476CONFIG_SERIO=m
477CONFIG_SERIO_SERPORT=m
478# CONFIG_SERIO_CT82C710 is not set
479# CONFIG_SERIO_RAW is not set
480
481#
482# Input Device Drivers
483#
484CONFIG_INPUT_KEYBOARD=y
485# CONFIG_KEYBOARD_ATKBD is not set
486# CONFIG_KEYBOARD_SUNKBD is not set
487# CONFIG_KEYBOARD_LKKBD is not set
488# CONFIG_KEYBOARD_XTKBD is not set
489# CONFIG_KEYBOARD_NEWTON is not set
490CONFIG_INPUT_MOUSE=y
491CONFIG_MOUSE_PS2=m
492CONFIG_MOUSE_SERIAL=m
493# CONFIG_MOUSE_VSXXXAA is not set
494# CONFIG_INPUT_JOYSTICK is not set
495# CONFIG_INPUT_TOUCHSCREEN is not set
496# CONFIG_INPUT_MISC is not set
497
498#
499# Character devices
500#
501CONFIG_VT=y
502CONFIG_VT_CONSOLE=y
503CONFIG_HW_CONSOLE=y
504# CONFIG_SERIAL_NONSTANDARD is not set
505
506#
507# Serial drivers
508#
509# CONFIG_SERIAL_8250 is not set
510
511#
512# Non-8250 serial port support
513#
514CONFIG_UNIX98_PTYS=y
515CONFIG_LEGACY_PTYS=y
516CONFIG_LEGACY_PTY_COUNT=256
517
518#
519# IPMI
520#
521# CONFIG_IPMI_HANDLER is not set
522
523#
524# Watchdog Cards
525#
526# CONFIG_WATCHDOG is not set
527CONFIG_GEN_RTC=y
528CONFIG_GEN_RTC_X=y
529# CONFIG_DTLK is not set
530# CONFIG_R3964 is not set
531
532#
533# Ftape, the floppy tape device driver
534#
535# CONFIG_DRM is not set
536# CONFIG_RAW_DRIVER is not set
537
538#
539# I2C support
540#
541# CONFIG_I2C is not set
542
543#
544# Dallas's 1-wire bus
545#
546# CONFIG_W1 is not set
547
548#
549# Misc devices
550#
551
552#
553# Multimedia devices
554#
555# CONFIG_VIDEO_DEV is not set
556
557#
558# Digital Video Broadcasting Devices
559#
560# CONFIG_DVB is not set
561
562#
563# Graphics support
564#
565# CONFIG_FB is not set
566
567#
568# Console display driver support
569#
570CONFIG_DUMMY_CONSOLE=y
571
572#
573# Sound
574#
575# CONFIG_SOUND is not set
576
577#
578# USB support
579#
580# CONFIG_USB_ARCH_HAS_HCD is not set
581# CONFIG_USB_ARCH_HAS_OHCI is not set
582
583#
584# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
585#
586
587#
588# USB Gadget Support
589#
590# CONFIG_USB_GADGET is not set
591
592#
593# MMC/SD Card support
594#
595# CONFIG_MMC is not set
596
597#
598# Character devices
599#
600CONFIG_DN_SERIAL=y
601CONFIG_SERIAL_CONSOLE=y
602
603#
604# File systems
605#
606CONFIG_EXT2_FS=y
607# CONFIG_EXT2_FS_XATTR is not set
608CONFIG_EXT3_FS=y
609# CONFIG_EXT3_FS_XATTR is not set
610CONFIG_JBD=y
611# CONFIG_JBD_DEBUG is not set
612CONFIG_REISERFS_FS=m
613# CONFIG_REISERFS_CHECK is not set
614# CONFIG_REISERFS_PROC_INFO is not set
615# CONFIG_REISERFS_FS_XATTR is not set
616CONFIG_JFS_FS=m
617# CONFIG_JFS_POSIX_ACL is not set
618# CONFIG_JFS_DEBUG is not set
619# CONFIG_JFS_STATISTICS is not set
620CONFIG_FS_POSIX_ACL=y
621CONFIG_XFS_FS=m
622# CONFIG_XFS_RT is not set
623# CONFIG_XFS_QUOTA is not set
624# CONFIG_XFS_SECURITY is not set
625# CONFIG_XFS_POSIX_ACL is not set
626CONFIG_MINIX_FS=y
627# CONFIG_ROMFS_FS is not set
628CONFIG_QUOTA=y
629# CONFIG_QFMT_V1 is not set
630# CONFIG_QFMT_V2 is not set
631CONFIG_QUOTACTL=y
632CONFIG_DNOTIFY=y
633CONFIG_AUTOFS_FS=m
634CONFIG_AUTOFS4_FS=m
635
636#
637# CD-ROM/DVD Filesystems
638#
639CONFIG_ISO9660_FS=y
640CONFIG_JOLIET=y
641CONFIG_ZISOFS=y
642CONFIG_ZISOFS_FS=y
643CONFIG_UDF_FS=m
644CONFIG_UDF_NLS=y
645
646#
647# DOS/FAT/NT Filesystems
648#
649CONFIG_FAT_FS=y
650CONFIG_MSDOS_FS=y
651CONFIG_VFAT_FS=m
652CONFIG_FAT_DEFAULT_CODEPAGE=437
653CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
654# CONFIG_NTFS_FS is not set
655
656#
657# Pseudo filesystems
658#
659CONFIG_PROC_FS=y
660CONFIG_PROC_KCORE=y
661CONFIG_SYSFS=y
662# CONFIG_DEVFS_FS is not set
663# CONFIG_DEVPTS_FS_XATTR is not set
664CONFIG_TMPFS=y
665# CONFIG_TMPFS_XATTR is not set
666# CONFIG_HUGETLB_PAGE is not set
667CONFIG_RAMFS=y
668
669#
670# Miscellaneous filesystems
671#
672# CONFIG_ADFS_FS is not set
673CONFIG_AFFS_FS=m
674CONFIG_HFS_FS=m
675CONFIG_HFSPLUS_FS=m
676# CONFIG_BEFS_FS is not set
677# CONFIG_BFS_FS is not set
678# CONFIG_EFS_FS is not set
679CONFIG_CRAMFS=m
680# CONFIG_VXFS_FS is not set
681CONFIG_HPFS_FS=m
682# CONFIG_QNX4FS_FS is not set
683CONFIG_SYSV_FS=m
684CONFIG_UFS_FS=m
685# CONFIG_UFS_FS_WRITE is not set
686
687#
688# Network File Systems
689#
690CONFIG_NFS_FS=y
691CONFIG_NFS_V3=y
692CONFIG_NFS_V4=y
693# CONFIG_NFS_DIRECTIO is not set
694CONFIG_NFSD=m
695CONFIG_NFSD_V3=y
696CONFIG_NFSD_V4=y
697CONFIG_NFSD_TCP=y
698CONFIG_ROOT_NFS=y
699CONFIG_LOCKD=y
700CONFIG_LOCKD_V4=y
701CONFIG_EXPORTFS=m
702CONFIG_SUNRPC=y
703CONFIG_SUNRPC_GSS=y
704CONFIG_RPCSEC_GSS_KRB5=y
705# CONFIG_RPCSEC_GSS_SPKM3 is not set
706CONFIG_SMB_FS=m
707CONFIG_SMB_NLS_DEFAULT=y
708CONFIG_SMB_NLS_REMOTE="cp437"
709# CONFIG_CIFS is not set
710CONFIG_NCP_FS=m
711# CONFIG_NCPFS_PACKET_SIGNING is not set
712# CONFIG_NCPFS_IOCTL_LOCKING is not set
713# CONFIG_NCPFS_STRONG is not set
714CONFIG_NCPFS_NFS_NS=y
715CONFIG_NCPFS_OS2_NS=y
716# CONFIG_NCPFS_SMALLDOS is not set
717CONFIG_NCPFS_NLS=y
718# CONFIG_NCPFS_EXTRAS is not set
719CONFIG_CODA_FS=m
720# CONFIG_CODA_FS_OLD_API is not set
721# CONFIG_AFS_FS is not set
722
723#
724# Partition Types
725#
726# CONFIG_PARTITION_ADVANCED is not set
727CONFIG_MSDOS_PARTITION=y
728
729#
730# Native Language Support
731#
732CONFIG_NLS=y
733CONFIG_NLS_DEFAULT="iso8859-1"
734CONFIG_NLS_CODEPAGE_437=y
735CONFIG_NLS_CODEPAGE_737=m
736CONFIG_NLS_CODEPAGE_775=m
737CONFIG_NLS_CODEPAGE_850=m
738CONFIG_NLS_CODEPAGE_852=m
739CONFIG_NLS_CODEPAGE_855=m
740CONFIG_NLS_CODEPAGE_857=m
741CONFIG_NLS_CODEPAGE_860=m
742CONFIG_NLS_CODEPAGE_861=m
743CONFIG_NLS_CODEPAGE_862=m
744CONFIG_NLS_CODEPAGE_863=m
745CONFIG_NLS_CODEPAGE_864=m
746CONFIG_NLS_CODEPAGE_865=m
747CONFIG_NLS_CODEPAGE_866=m
748CONFIG_NLS_CODEPAGE_869=m
749CONFIG_NLS_CODEPAGE_936=m
750CONFIG_NLS_CODEPAGE_950=m
751CONFIG_NLS_CODEPAGE_932=m
752CONFIG_NLS_CODEPAGE_949=m
753CONFIG_NLS_CODEPAGE_874=m
754CONFIG_NLS_ISO8859_8=m
755CONFIG_NLS_CODEPAGE_1250=m
756CONFIG_NLS_CODEPAGE_1251=m
757CONFIG_NLS_ASCII=m
758CONFIG_NLS_ISO8859_1=y
759CONFIG_NLS_ISO8859_2=m
760CONFIG_NLS_ISO8859_3=m
761CONFIG_NLS_ISO8859_4=m
762CONFIG_NLS_ISO8859_5=m
763CONFIG_NLS_ISO8859_6=m
764CONFIG_NLS_ISO8859_7=m
765CONFIG_NLS_ISO8859_9=m
766CONFIG_NLS_ISO8859_13=m
767CONFIG_NLS_ISO8859_14=m
768CONFIG_NLS_ISO8859_15=m
769CONFIG_NLS_KOI8_R=m
770CONFIG_NLS_KOI8_U=m
771CONFIG_NLS_UTF8=m
772
773#
774# Kernel hacking
775#
776CONFIG_DEBUG_KERNEL=y
777CONFIG_MAGIC_SYSRQ=y
778# CONFIG_SCHEDSTATS is not set
779# CONFIG_DEBUG_SLAB is not set
780# CONFIG_DEBUG_KOBJECT is not set
781# CONFIG_DEBUG_BUGVERBOSE is not set
782# CONFIG_DEBUG_INFO is not set
783
784#
785# Security options
786#
787# CONFIG_KEYS is not set
788# CONFIG_SECURITY is not set
789
790#
791# Cryptographic options
792#
793CONFIG_CRYPTO=y
794CONFIG_CRYPTO_HMAC=y
795CONFIG_CRYPTO_NULL=m
796CONFIG_CRYPTO_MD4=m
797CONFIG_CRYPTO_MD5=y
798CONFIG_CRYPTO_SHA1=m
799CONFIG_CRYPTO_SHA256=m
800CONFIG_CRYPTO_SHA512=m
801# CONFIG_CRYPTO_WP512 is not set
802CONFIG_CRYPTO_DES=y
803CONFIG_CRYPTO_BLOWFISH=m
804CONFIG_CRYPTO_TWOFISH=m
805CONFIG_CRYPTO_SERPENT=m
806CONFIG_CRYPTO_AES=m
807CONFIG_CRYPTO_CAST5=m
808CONFIG_CRYPTO_CAST6=m
809CONFIG_CRYPTO_TEA=m
810CONFIG_CRYPTO_ARC4=m
811CONFIG_CRYPTO_KHAZAD=m
812CONFIG_CRYPTO_ANUBIS=m
813CONFIG_CRYPTO_DEFLATE=m
814CONFIG_CRYPTO_MICHAEL_MIC=m
815CONFIG_CRYPTO_CRC32C=m
816CONFIG_CRYPTO_TEST=m
817
818#
819# Library routines
820#
821CONFIG_CRC_CCITT=m
822CONFIG_CRC32=y
823CONFIG_LIBCRC32C=m
824CONFIG_ZLIB_INFLATE=y
825CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
new file mode 100644
index 000000000000..1fb25c0b3e95
--- /dev/null
+++ b/arch/m68k/configs/atari_defconfig
@@ -0,0 +1,880 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:23:11 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-atari"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63CONFIG_ATARI=y
64# CONFIG_MAC is not set
65# CONFIG_APOLLO is not set
66# CONFIG_VME is not set
67# CONFIG_HP300 is not set
68# CONFIG_SUN3X is not set
69# CONFIG_Q40 is not set
70
71#
72# Processor type
73#
74CONFIG_M68020=y
75CONFIG_M68030=y
76CONFIG_M68040=y
77CONFIG_M68060=y
78CONFIG_MMU_MOTOROLA=y
79CONFIG_M68KFPU_EMU=y
80CONFIG_M68KFPU_EMU_EXTRAPREC=y
81# CONFIG_M68KFPU_EMU_ONLY is not set
82# CONFIG_ADVANCED is not set
83
84#
85# General setup
86#
87CONFIG_BINFMT_ELF=y
88CONFIG_BINFMT_AOUT=m
89CONFIG_BINFMT_MISC=m
90CONFIG_STRAM_PROC=y
91CONFIG_HEARTBEAT=y
92CONFIG_PROC_HARDWARE=y
93
94#
95# Device Drivers
96#
97
98#
99# Generic Driver Options
100#
101CONFIG_STANDALONE=y
102CONFIG_PREVENT_FIRMWARE_BUILD=y
103# CONFIG_DEBUG_DRIVER is not set
104
105#
106# Memory Technology Devices (MTD)
107#
108# CONFIG_MTD is not set
109
110#
111# Parallel port support
112#
113CONFIG_PARPORT=m
114# CONFIG_PARPORT_PC is not set
115CONFIG_PARPORT_ATARI=m
116# CONFIG_PARPORT_OTHER is not set
117CONFIG_PARPORT_1284=y
118
119#
120# Plug and Play support
121#
122
123#
124# Block devices
125#
126CONFIG_ATARI_FLOPPY=y
127# CONFIG_PARIDE is not set
128CONFIG_BLK_DEV_LOOP=y
129CONFIG_BLK_DEV_CRYPTOLOOP=m
130CONFIG_BLK_DEV_NBD=m
131CONFIG_BLK_DEV_RAM=y
132CONFIG_BLK_DEV_RAM_COUNT=16
133CONFIG_BLK_DEV_RAM_SIZE=4096
134CONFIG_BLK_DEV_INITRD=y
135CONFIG_INITRAMFS_SOURCE=""
136CONFIG_CDROM_PKTCDVD=m
137CONFIG_CDROM_PKTCDVD_BUFFERS=8
138# CONFIG_CDROM_PKTCDVD_WCACHE is not set
139
140#
141# IO Schedulers
142#
143CONFIG_IOSCHED_NOOP=y
144CONFIG_IOSCHED_AS=y
145CONFIG_IOSCHED_DEADLINE=y
146CONFIG_IOSCHED_CFQ=y
147
148#
149# ATA/ATAPI/MFM/RLL support
150#
151CONFIG_IDE=y
152CONFIG_BLK_DEV_IDE=y
153
154#
155# Please see Documentation/ide.txt for help/info on IDE drives
156#
157# CONFIG_BLK_DEV_IDE_SATA is not set
158CONFIG_BLK_DEV_IDEDISK=y
159# CONFIG_IDEDISK_MULTI_MODE is not set
160CONFIG_BLK_DEV_IDECD=y
161CONFIG_BLK_DEV_IDETAPE=m
162CONFIG_BLK_DEV_IDEFLOPPY=m
163# CONFIG_BLK_DEV_IDESCSI is not set
164# CONFIG_IDE_TASK_IOCTL is not set
165
166#
167# IDE chipset support/bugfixes
168#
169CONFIG_IDE_GENERIC=y
170# CONFIG_IDE_ARM is not set
171CONFIG_BLK_DEV_FALCON_IDE=y
172# CONFIG_BLK_DEV_IDEDMA is not set
173# CONFIG_IDEDMA_AUTO is not set
174# CONFIG_BLK_DEV_HD is not set
175
176#
177# SCSI device support
178#
179CONFIG_SCSI=y
180CONFIG_SCSI_PROC_FS=y
181
182#
183# SCSI support type (disk, tape, CD-ROM)
184#
185CONFIG_BLK_DEV_SD=y
186CONFIG_CHR_DEV_ST=m
187# CONFIG_CHR_DEV_OSST is not set
188CONFIG_BLK_DEV_SR=y
189CONFIG_BLK_DEV_SR_VENDOR=y
190CONFIG_CHR_DEV_SG=m
191
192#
193# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
194#
195# CONFIG_SCSI_MULTI_LUN is not set
196CONFIG_SCSI_CONSTANTS=y
197# CONFIG_SCSI_LOGGING is not set
198
199#
200# SCSI Transport Attributes
201#
202# CONFIG_SCSI_SPI_ATTRS is not set
203# CONFIG_SCSI_FC_ATTRS is not set
204
205#
206# SCSI low-level drivers
207#
208# CONFIG_SCSI_SATA is not set
209# CONFIG_SCSI_PPA is not set
210# CONFIG_SCSI_IMM is not set
211# CONFIG_SCSI_DEBUG is not set
212
213#
214# Multi-device support (RAID and LVM)
215#
216CONFIG_MD=y
217CONFIG_BLK_DEV_MD=m
218CONFIG_MD_LINEAR=m
219CONFIG_MD_RAID0=m
220CONFIG_MD_RAID1=m
221# CONFIG_MD_RAID10 is not set
222CONFIG_MD_RAID5=m
223CONFIG_MD_RAID6=m
224CONFIG_MD_MULTIPATH=m
225# CONFIG_MD_FAULTY is not set
226CONFIG_BLK_DEV_DM=m
227CONFIG_DM_CRYPT=m
228CONFIG_DM_SNAPSHOT=m
229CONFIG_DM_MIRROR=m
230CONFIG_DM_ZERO=m
231
232#
233# Fusion MPT device support
234#
235
236#
237# IEEE 1394 (FireWire) support
238#
239
240#
241# I2O device support
242#
243
244#
245# Networking support
246#
247CONFIG_NET=y
248
249#
250# Networking options
251#
252CONFIG_PACKET=y
253# CONFIG_PACKET_MMAP is not set
254CONFIG_NETLINK_DEV=y
255CONFIG_UNIX=y
256CONFIG_NET_KEY=y
257CONFIG_INET=y
258# CONFIG_IP_MULTICAST is not set
259# CONFIG_IP_ADVANCED_ROUTER is not set
260# CONFIG_IP_PNP is not set
261CONFIG_NET_IPIP=m
262CONFIG_NET_IPGRE=m
263# CONFIG_ARPD is not set
264CONFIG_SYN_COOKIES=y
265CONFIG_INET_AH=m
266CONFIG_INET_ESP=m
267CONFIG_INET_IPCOMP=m
268CONFIG_INET_TUNNEL=m
269CONFIG_IP_TCPDIAG=m
270CONFIG_IP_TCPDIAG_IPV6=y
271
272#
273# IP: Virtual Server Configuration
274#
275# CONFIG_IP_VS is not set
276CONFIG_IPV6=m
277CONFIG_IPV6_PRIVACY=y
278CONFIG_INET6_AH=m
279CONFIG_INET6_ESP=m
280CONFIG_INET6_IPCOMP=m
281CONFIG_INET6_TUNNEL=m
282CONFIG_IPV6_TUNNEL=m
283CONFIG_NETFILTER=y
284# CONFIG_NETFILTER_DEBUG is not set
285
286#
287# IP: Netfilter Configuration
288#
289CONFIG_IP_NF_CONNTRACK=m
290# CONFIG_IP_NF_CT_ACCT is not set
291CONFIG_IP_NF_CONNTRACK_MARK=y
292# CONFIG_IP_NF_CT_PROTO_SCTP is not set
293CONFIG_IP_NF_FTP=m
294CONFIG_IP_NF_IRC=m
295CONFIG_IP_NF_TFTP=m
296CONFIG_IP_NF_AMANDA=m
297CONFIG_IP_NF_QUEUE=m
298CONFIG_IP_NF_IPTABLES=m
299CONFIG_IP_NF_MATCH_LIMIT=m
300CONFIG_IP_NF_MATCH_IPRANGE=m
301CONFIG_IP_NF_MATCH_MAC=m
302CONFIG_IP_NF_MATCH_PKTTYPE=m
303CONFIG_IP_NF_MATCH_MARK=m
304CONFIG_IP_NF_MATCH_MULTIPORT=m
305CONFIG_IP_NF_MATCH_TOS=m
306CONFIG_IP_NF_MATCH_RECENT=m
307CONFIG_IP_NF_MATCH_ECN=m
308CONFIG_IP_NF_MATCH_DSCP=m
309CONFIG_IP_NF_MATCH_AH_ESP=m
310CONFIG_IP_NF_MATCH_LENGTH=m
311CONFIG_IP_NF_MATCH_TTL=m
312CONFIG_IP_NF_MATCH_TCPMSS=m
313CONFIG_IP_NF_MATCH_HELPER=m
314CONFIG_IP_NF_MATCH_STATE=m
315CONFIG_IP_NF_MATCH_CONNTRACK=m
316CONFIG_IP_NF_MATCH_OWNER=m
317CONFIG_IP_NF_MATCH_ADDRTYPE=m
318CONFIG_IP_NF_MATCH_REALM=m
319# CONFIG_IP_NF_MATCH_SCTP is not set
320# CONFIG_IP_NF_MATCH_COMMENT is not set
321CONFIG_IP_NF_MATCH_CONNMARK=m
322CONFIG_IP_NF_MATCH_HASHLIMIT=m
323CONFIG_IP_NF_FILTER=m
324CONFIG_IP_NF_TARGET_REJECT=m
325CONFIG_IP_NF_TARGET_LOG=m
326CONFIG_IP_NF_TARGET_ULOG=m
327CONFIG_IP_NF_TARGET_TCPMSS=m
328CONFIG_IP_NF_NAT=m
329CONFIG_IP_NF_NAT_NEEDED=y
330CONFIG_IP_NF_TARGET_MASQUERADE=m
331CONFIG_IP_NF_TARGET_REDIRECT=m
332CONFIG_IP_NF_TARGET_NETMAP=m
333CONFIG_IP_NF_TARGET_SAME=m
334CONFIG_IP_NF_NAT_SNMP_BASIC=m
335CONFIG_IP_NF_NAT_IRC=m
336CONFIG_IP_NF_NAT_FTP=m
337CONFIG_IP_NF_NAT_TFTP=m
338CONFIG_IP_NF_NAT_AMANDA=m
339CONFIG_IP_NF_MANGLE=m
340CONFIG_IP_NF_TARGET_TOS=m
341CONFIG_IP_NF_TARGET_ECN=m
342CONFIG_IP_NF_TARGET_DSCP=m
343CONFIG_IP_NF_TARGET_MARK=m
344CONFIG_IP_NF_TARGET_CLASSIFY=m
345CONFIG_IP_NF_TARGET_CONNMARK=m
346# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
347CONFIG_IP_NF_RAW=m
348CONFIG_IP_NF_TARGET_NOTRACK=m
349CONFIG_IP_NF_ARPTABLES=m
350CONFIG_IP_NF_ARPFILTER=m
351CONFIG_IP_NF_ARP_MANGLE=m
352CONFIG_IP_NF_COMPAT_IPCHAINS=m
353CONFIG_IP_NF_COMPAT_IPFWADM=m
354
355#
356# IPv6: Netfilter Configuration
357#
358CONFIG_IP6_NF_QUEUE=m
359CONFIG_IP6_NF_IPTABLES=m
360CONFIG_IP6_NF_MATCH_LIMIT=m
361CONFIG_IP6_NF_MATCH_MAC=m
362CONFIG_IP6_NF_MATCH_RT=m
363CONFIG_IP6_NF_MATCH_OPTS=m
364CONFIG_IP6_NF_MATCH_FRAG=m
365CONFIG_IP6_NF_MATCH_HL=m
366CONFIG_IP6_NF_MATCH_MULTIPORT=m
367CONFIG_IP6_NF_MATCH_OWNER=m
368CONFIG_IP6_NF_MATCH_MARK=m
369CONFIG_IP6_NF_MATCH_IPV6HEADER=m
370CONFIG_IP6_NF_MATCH_AHESP=m
371CONFIG_IP6_NF_MATCH_LENGTH=m
372CONFIG_IP6_NF_MATCH_EUI64=m
373CONFIG_IP6_NF_FILTER=m
374CONFIG_IP6_NF_TARGET_LOG=m
375CONFIG_IP6_NF_MANGLE=m
376CONFIG_IP6_NF_TARGET_MARK=m
377CONFIG_IP6_NF_RAW=m
378CONFIG_XFRM=y
379CONFIG_XFRM_USER=m
380
381#
382# SCTP Configuration (EXPERIMENTAL)
383#
384CONFIG_IP_SCTP=m
385# CONFIG_SCTP_DBG_MSG is not set
386# CONFIG_SCTP_DBG_OBJCNT is not set
387# CONFIG_SCTP_HMAC_NONE is not set
388# CONFIG_SCTP_HMAC_SHA1 is not set
389CONFIG_SCTP_HMAC_MD5=y
390# CONFIG_ATM is not set
391# CONFIG_BRIDGE is not set
392# CONFIG_VLAN_8021Q is not set
393# CONFIG_DECNET is not set
394CONFIG_LLC=m
395# CONFIG_LLC2 is not set
396CONFIG_IPX=m
397# CONFIG_IPX_INTERN is not set
398CONFIG_ATALK=m
399# CONFIG_DEV_APPLETALK is not set
400# CONFIG_X25 is not set
401# CONFIG_LAPB is not set
402# CONFIG_NET_DIVERT is not set
403# CONFIG_ECONET is not set
404# CONFIG_WAN_ROUTER is not set
405
406#
407# QoS and/or fair queueing
408#
409# CONFIG_NET_SCHED is not set
410CONFIG_NET_CLS_ROUTE=y
411
412#
413# Network testing
414#
415# CONFIG_NET_PKTGEN is not set
416CONFIG_NETPOLL=y
417# CONFIG_NETPOLL_RX is not set
418# CONFIG_NETPOLL_TRAP is not set
419CONFIG_NET_POLL_CONTROLLER=y
420# CONFIG_HAMRADIO is not set
421# CONFIG_IRDA is not set
422# CONFIG_BT is not set
423CONFIG_NETDEVICES=y
424CONFIG_DUMMY=m
425# CONFIG_BONDING is not set
426CONFIG_EQUALIZER=m
427# CONFIG_TUN is not set
428# CONFIG_ETHERTAP is not set
429
430#
431# Ethernet (10 or 100Mbit)
432#
433CONFIG_NET_ETHERNET=y
434CONFIG_MII=m
435CONFIG_ATARILANCE=m
436
437#
438# Ethernet (1000 Mbit)
439#
440
441#
442# Ethernet (10000 Mbit)
443#
444
445#
446# Token Ring devices
447#
448
449#
450# Wireless LAN (non-hamradio)
451#
452# CONFIG_NET_RADIO is not set
453
454#
455# Wan interfaces
456#
457# CONFIG_WAN is not set
458# CONFIG_PLIP is not set
459CONFIG_PPP=m
460# CONFIG_PPP_MULTILINK is not set
461CONFIG_PPP_FILTER=y
462CONFIG_PPP_ASYNC=m
463CONFIG_PPP_SYNC_TTY=m
464CONFIG_PPP_DEFLATE=m
465CONFIG_PPP_BSDCOMP=m
466CONFIG_PPPOE=m
467CONFIG_SLIP=m
468CONFIG_SLIP_COMPRESSED=y
469CONFIG_SLIP_SMART=y
470CONFIG_SLIP_MODE_SLIP6=y
471CONFIG_SHAPER=m
472CONFIG_NETCONSOLE=m
473
474#
475# ISDN subsystem
476#
477# CONFIG_ISDN is not set
478
479#
480# Telephony Support
481#
482# CONFIG_PHONE is not set
483
484#
485# Input device support
486#
487CONFIG_INPUT=y
488
489#
490# Userland interfaces
491#
492CONFIG_INPUT_MOUSEDEV=y
493CONFIG_INPUT_MOUSEDEV_PSAUX=y
494CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
495CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
496# CONFIG_INPUT_JOYDEV is not set
497# CONFIG_INPUT_TSDEV is not set
498# CONFIG_INPUT_EVDEV is not set
499# CONFIG_INPUT_EVBUG is not set
500
501#
502# Input I/O drivers
503#
504# CONFIG_GAMEPORT is not set
505CONFIG_SOUND_GAMEPORT=y
506CONFIG_SERIO=y
507CONFIG_SERIO_SERPORT=y
508# CONFIG_SERIO_CT82C710 is not set
509# CONFIG_SERIO_PARKBD is not set
510# CONFIG_SERIO_RAW is not set
511
512#
513# Input Device Drivers
514#
515CONFIG_INPUT_KEYBOARD=y
516CONFIG_KEYBOARD_ATKBD=y
517# CONFIG_KEYBOARD_SUNKBD is not set
518# CONFIG_KEYBOARD_LKKBD is not set
519# CONFIG_KEYBOARD_XTKBD is not set
520# CONFIG_KEYBOARD_NEWTON is not set
521CONFIG_INPUT_MOUSE=y
522CONFIG_MOUSE_PS2=y
523# CONFIG_MOUSE_SERIAL is not set
524# CONFIG_MOUSE_VSXXXAA is not set
525# CONFIG_INPUT_JOYSTICK is not set
526# CONFIG_INPUT_TOUCHSCREEN is not set
527CONFIG_INPUT_MISC=y
528CONFIG_INPUT_M68K_BEEP=m
529CONFIG_INPUT_UINPUT=m
530
531#
532# Character devices
533#
534CONFIG_VT=y
535CONFIG_VT_CONSOLE=y
536CONFIG_HW_CONSOLE=y
537# CONFIG_SERIAL_NONSTANDARD is not set
538
539#
540# Serial drivers
541#
542# CONFIG_SERIAL_8250 is not set
543
544#
545# Non-8250 serial port support
546#
547CONFIG_UNIX98_PTYS=y
548CONFIG_LEGACY_PTYS=y
549CONFIG_LEGACY_PTY_COUNT=256
550CONFIG_PRINTER=m
551# CONFIG_LP_CONSOLE is not set
552# CONFIG_PPDEV is not set
553# CONFIG_TIPAR is not set
554
555#
556# IPMI
557#
558# CONFIG_IPMI_HANDLER is not set
559
560#
561# Watchdog Cards
562#
563# CONFIG_WATCHDOG is not set
564CONFIG_NVRAM=y
565CONFIG_GEN_RTC=y
566CONFIG_GEN_RTC_X=y
567# CONFIG_DTLK is not set
568# CONFIG_R3964 is not set
569
570#
571# Ftape, the floppy tape device driver
572#
573# CONFIG_DRM is not set
574# CONFIG_RAW_DRIVER is not set
575
576#
577# I2C support
578#
579# CONFIG_I2C is not set
580
581#
582# Dallas's 1-wire bus
583#
584# CONFIG_W1 is not set
585
586#
587# Misc devices
588#
589
590#
591# Multimedia devices
592#
593# CONFIG_VIDEO_DEV is not set
594
595#
596# Digital Video Broadcasting Devices
597#
598# CONFIG_DVB is not set
599
600#
601# Graphics support
602#
603CONFIG_FB=y
604CONFIG_FB_MODE_HELPERS=y
605# CONFIG_FB_TILEBLITTING is not set
606# CONFIG_FB_ATY is not set
607# CONFIG_FB_VIRTUAL is not set
608
609#
610# Console display driver support
611#
612CONFIG_DUMMY_CONSOLE=y
613CONFIG_FRAMEBUFFER_CONSOLE=y
614# CONFIG_FONTS is not set
615CONFIG_FONT_8x8=y
616CONFIG_FONT_8x16=y
617
618#
619# Logo configuration
620#
621# CONFIG_LOGO is not set
622
623#
624# Sound
625#
626CONFIG_SOUND=m
627CONFIG_DMASOUND_ATARI=m
628CONFIG_DMASOUND=m
629
630#
631# USB support
632#
633# CONFIG_USB_ARCH_HAS_HCD is not set
634# CONFIG_USB_ARCH_HAS_OHCI is not set
635
636#
637# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
638#
639
640#
641# USB Gadget Support
642#
643# CONFIG_USB_GADGET is not set
644
645#
646# MMC/SD Card support
647#
648# CONFIG_MMC is not set
649
650#
651# Character devices
652#
653CONFIG_ATARI_MFPSER=m
654CONFIG_ATARI_SCC=y
655CONFIG_ATARI_SCC_DMA=y
656CONFIG_ATARI_MIDI=m
657CONFIG_ATARI_DSP56K=m
658# CONFIG_SERIAL_CONSOLE 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
669CONFIG_REISERFS_FS=m
670# CONFIG_REISERFS_CHECK is not set
671CONFIG_REISERFS_PROC_INFO=y
672# CONFIG_REISERFS_FS_XATTR is not set
673CONFIG_JFS_FS=m
674# CONFIG_JFS_POSIX_ACL is not set
675# CONFIG_JFS_DEBUG is not set
676# CONFIG_JFS_STATISTICS is not set
677CONFIG_XFS_FS=m
678# CONFIG_XFS_RT is not set
679# CONFIG_XFS_QUOTA is not set
680# CONFIG_XFS_SECURITY is not set
681# CONFIG_XFS_POSIX_ACL is not set
682CONFIG_MINIX_FS=y
683# CONFIG_ROMFS_FS is not set
684CONFIG_QUOTA=y
685# CONFIG_QFMT_V1 is not set
686# CONFIG_QFMT_V2 is not set
687CONFIG_QUOTACTL=y
688CONFIG_DNOTIFY=y
689CONFIG_AUTOFS_FS=m
690CONFIG_AUTOFS4_FS=m
691
692#
693# CD-ROM/DVD Filesystems
694#
695CONFIG_ISO9660_FS=y
696CONFIG_JOLIET=y
697CONFIG_ZISOFS=y
698CONFIG_ZISOFS_FS=y
699CONFIG_UDF_FS=m
700CONFIG_UDF_NLS=y
701
702#
703# DOS/FAT/NT Filesystems
704#
705CONFIG_FAT_FS=y
706CONFIG_MSDOS_FS=y
707CONFIG_VFAT_FS=m
708CONFIG_FAT_DEFAULT_CODEPAGE=437
709CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
710# CONFIG_NTFS_FS is not set
711
712#
713# Pseudo filesystems
714#
715CONFIG_PROC_FS=y
716CONFIG_PROC_KCORE=y
717CONFIG_SYSFS=y
718# CONFIG_DEVFS_FS is not set
719# CONFIG_DEVPTS_FS_XATTR is not set
720CONFIG_TMPFS=y
721# CONFIG_TMPFS_XATTR is not set
722# CONFIG_HUGETLB_PAGE is not set
723CONFIG_RAMFS=y
724
725#
726# Miscellaneous filesystems
727#
728# CONFIG_ADFS_FS is not set
729CONFIG_AFFS_FS=m
730CONFIG_HFS_FS=m
731CONFIG_HFSPLUS_FS=m
732# CONFIG_BEFS_FS is not set
733# CONFIG_BFS_FS is not set
734# CONFIG_EFS_FS is not set
735CONFIG_CRAMFS=m
736# CONFIG_VXFS_FS is not set
737CONFIG_HPFS_FS=m
738# CONFIG_QNX4FS_FS is not set
739CONFIG_SYSV_FS=m
740CONFIG_UFS_FS=m
741# CONFIG_UFS_FS_WRITE is not set
742
743#
744# Network File Systems
745#
746CONFIG_NFS_FS=m
747CONFIG_NFS_V3=y
748# CONFIG_NFS_V4 is not set
749# CONFIG_NFS_DIRECTIO is not set
750CONFIG_NFSD=m
751CONFIG_NFSD_V3=y
752# CONFIG_NFSD_V4 is not set
753CONFIG_NFSD_TCP=y
754CONFIG_LOCKD=m
755CONFIG_LOCKD_V4=y
756CONFIG_EXPORTFS=m
757CONFIG_SUNRPC=m
758# CONFIG_RPCSEC_GSS_KRB5 is not set
759# CONFIG_RPCSEC_GSS_SPKM3 is not set
760CONFIG_SMB_FS=m
761CONFIG_SMB_NLS_DEFAULT=y
762CONFIG_SMB_NLS_REMOTE="cp437"
763# CONFIG_CIFS is not set
764CONFIG_NCP_FS=m
765# CONFIG_NCPFS_PACKET_SIGNING is not set
766# CONFIG_NCPFS_IOCTL_LOCKING is not set
767# CONFIG_NCPFS_STRONG is not set
768CONFIG_NCPFS_NFS_NS=y
769CONFIG_NCPFS_OS2_NS=y
770# CONFIG_NCPFS_SMALLDOS is not set
771CONFIG_NCPFS_NLS=y
772# CONFIG_NCPFS_EXTRAS is not set
773CONFIG_CODA_FS=m
774# CONFIG_CODA_FS_OLD_API is not set
775# CONFIG_AFS_FS is not set
776
777#
778# Partition Types
779#
780# CONFIG_PARTITION_ADVANCED is not set
781CONFIG_ATARI_PARTITION=y
782CONFIG_MSDOS_PARTITION=y
783
784#
785# Native Language Support
786#
787CONFIG_NLS=y
788CONFIG_NLS_DEFAULT="iso8859-1"
789CONFIG_NLS_CODEPAGE_437=y
790CONFIG_NLS_CODEPAGE_737=m
791CONFIG_NLS_CODEPAGE_775=m
792CONFIG_NLS_CODEPAGE_850=m
793CONFIG_NLS_CODEPAGE_852=m
794CONFIG_NLS_CODEPAGE_855=m
795CONFIG_NLS_CODEPAGE_857=m
796CONFIG_NLS_CODEPAGE_860=m
797CONFIG_NLS_CODEPAGE_861=m
798CONFIG_NLS_CODEPAGE_862=m
799CONFIG_NLS_CODEPAGE_863=m
800CONFIG_NLS_CODEPAGE_864=m
801CONFIG_NLS_CODEPAGE_865=m
802CONFIG_NLS_CODEPAGE_866=m
803CONFIG_NLS_CODEPAGE_869=m
804CONFIG_NLS_CODEPAGE_936=m
805CONFIG_NLS_CODEPAGE_950=m
806CONFIG_NLS_CODEPAGE_932=m
807CONFIG_NLS_CODEPAGE_949=m
808CONFIG_NLS_CODEPAGE_874=m
809CONFIG_NLS_ISO8859_8=m
810CONFIG_NLS_CODEPAGE_1250=m
811CONFIG_NLS_CODEPAGE_1251=m
812CONFIG_NLS_ASCII=m
813CONFIG_NLS_ISO8859_1=y
814CONFIG_NLS_ISO8859_2=m
815CONFIG_NLS_ISO8859_3=m
816CONFIG_NLS_ISO8859_4=m
817CONFIG_NLS_ISO8859_5=m
818CONFIG_NLS_ISO8859_6=m
819CONFIG_NLS_ISO8859_7=m
820CONFIG_NLS_ISO8859_9=m
821CONFIG_NLS_ISO8859_13=m
822CONFIG_NLS_ISO8859_14=m
823CONFIG_NLS_ISO8859_15=m
824CONFIG_NLS_KOI8_R=m
825CONFIG_NLS_KOI8_U=m
826CONFIG_NLS_UTF8=m
827
828#
829# Kernel hacking
830#
831CONFIG_DEBUG_KERNEL=y
832CONFIG_MAGIC_SYSRQ=y
833# CONFIG_SCHEDSTATS is not set
834# CONFIG_DEBUG_SLAB is not set
835# CONFIG_DEBUG_KOBJECT is not set
836# CONFIG_DEBUG_BUGVERBOSE is not set
837# CONFIG_DEBUG_INFO is not set
838
839#
840# Security options
841#
842# CONFIG_KEYS is not set
843# CONFIG_SECURITY is not set
844
845#
846# Cryptographic options
847#
848CONFIG_CRYPTO=y
849CONFIG_CRYPTO_HMAC=y
850CONFIG_CRYPTO_NULL=m
851CONFIG_CRYPTO_MD4=m
852CONFIG_CRYPTO_MD5=m
853CONFIG_CRYPTO_SHA1=m
854CONFIG_CRYPTO_SHA256=m
855CONFIG_CRYPTO_SHA512=m
856# CONFIG_CRYPTO_WP512 is not set
857CONFIG_CRYPTO_DES=m
858CONFIG_CRYPTO_BLOWFISH=m
859CONFIG_CRYPTO_TWOFISH=m
860CONFIG_CRYPTO_SERPENT=m
861CONFIG_CRYPTO_AES=m
862CONFIG_CRYPTO_CAST5=m
863CONFIG_CRYPTO_CAST6=m
864CONFIG_CRYPTO_TEA=m
865CONFIG_CRYPTO_ARC4=m
866CONFIG_CRYPTO_KHAZAD=m
867CONFIG_CRYPTO_ANUBIS=m
868CONFIG_CRYPTO_DEFLATE=m
869CONFIG_CRYPTO_MICHAEL_MIC=m
870CONFIG_CRYPTO_CRC32C=m
871CONFIG_CRYPTO_TEST=m
872
873#
874# Library routines
875#
876CONFIG_CRC_CCITT=m
877CONFIG_CRC32=y
878CONFIG_LIBCRC32C=m
879CONFIG_ZLIB_INFLATE=y
880CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
new file mode 100644
index 000000000000..f1f2cf027100
--- /dev/null
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -0,0 +1,824 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:23:15 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-bvme6000"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63# CONFIG_ATARI is not set
64# CONFIG_MAC is not set
65# CONFIG_APOLLO is not set
66CONFIG_VME=y
67# CONFIG_MVME147 is not set
68# CONFIG_MVME16x is not set
69CONFIG_BVME6000=y
70# CONFIG_HP300 is not set
71# CONFIG_SUN3X is not set
72# CONFIG_Q40 is not set
73
74#
75# Processor type
76#
77# CONFIG_M68020 is not set
78# CONFIG_M68030 is not set
79CONFIG_M68040=y
80CONFIG_M68060=y
81CONFIG_MMU_MOTOROLA=y
82# CONFIG_M68KFPU_EMU is not set
83# CONFIG_ADVANCED is not set
84
85#
86# General setup
87#
88CONFIG_BINFMT_ELF=y
89CONFIG_BINFMT_AOUT=m
90CONFIG_BINFMT_MISC=m
91CONFIG_PROC_HARDWARE=y
92
93#
94# Device Drivers
95#
96
97#
98# Generic Driver Options
99#
100CONFIG_STANDALONE=y
101CONFIG_PREVENT_FIRMWARE_BUILD=y
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#
112# CONFIG_PARPORT is not set
113
114#
115# Plug and Play support
116#
117
118#
119# Block devices
120#
121CONFIG_BLK_DEV_LOOP=y
122CONFIG_BLK_DEV_CRYPTOLOOP=m
123CONFIG_BLK_DEV_NBD=m
124CONFIG_BLK_DEV_RAM=y
125CONFIG_BLK_DEV_RAM_COUNT=16
126CONFIG_BLK_DEV_RAM_SIZE=4096
127CONFIG_BLK_DEV_INITRD=y
128CONFIG_INITRAMFS_SOURCE=""
129CONFIG_CDROM_PKTCDVD=m
130CONFIG_CDROM_PKTCDVD_BUFFERS=8
131# CONFIG_CDROM_PKTCDVD_WCACHE is not set
132
133#
134# IO Schedulers
135#
136CONFIG_IOSCHED_NOOP=y
137CONFIG_IOSCHED_AS=y
138CONFIG_IOSCHED_DEADLINE=y
139CONFIG_IOSCHED_CFQ=y
140
141#
142# ATA/ATAPI/MFM/RLL support
143#
144# CONFIG_IDE is not set
145
146#
147# SCSI device support
148#
149CONFIG_SCSI=y
150CONFIG_SCSI_PROC_FS=y
151
152#
153# SCSI support type (disk, tape, CD-ROM)
154#
155CONFIG_BLK_DEV_SD=y
156CONFIG_CHR_DEV_ST=m
157# CONFIG_CHR_DEV_OSST is not set
158CONFIG_BLK_DEV_SR=y
159CONFIG_BLK_DEV_SR_VENDOR=y
160CONFIG_CHR_DEV_SG=m
161
162#
163# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
164#
165# CONFIG_SCSI_MULTI_LUN is not set
166CONFIG_SCSI_CONSTANTS=y
167# CONFIG_SCSI_LOGGING is not set
168
169#
170# SCSI Transport Attributes
171#
172# CONFIG_SCSI_SPI_ATTRS is not set
173# CONFIG_SCSI_FC_ATTRS is not set
174
175#
176# SCSI low-level drivers
177#
178# CONFIG_SCSI_SATA is not set
179# CONFIG_SCSI_DEBUG is not set
180
181#
182# Multi-device support (RAID and LVM)
183#
184CONFIG_MD=y
185CONFIG_BLK_DEV_MD=m
186CONFIG_MD_LINEAR=m
187CONFIG_MD_RAID0=m
188CONFIG_MD_RAID1=m
189# CONFIG_MD_RAID10 is not set
190CONFIG_MD_RAID5=m
191CONFIG_MD_RAID6=m
192CONFIG_MD_MULTIPATH=m
193# CONFIG_MD_FAULTY is not set
194CONFIG_BLK_DEV_DM=m
195CONFIG_DM_CRYPT=m
196CONFIG_DM_SNAPSHOT=m
197CONFIG_DM_MIRROR=m
198CONFIG_DM_ZERO=m
199
200#
201# Fusion MPT device support
202#
203
204#
205# IEEE 1394 (FireWire) support
206#
207
208#
209# I2O device support
210#
211
212#
213# Networking support
214#
215CONFIG_NET=y
216
217#
218# Networking options
219#
220CONFIG_PACKET=y
221# CONFIG_PACKET_MMAP is not set
222CONFIG_NETLINK_DEV=y
223CONFIG_UNIX=y
224CONFIG_NET_KEY=y
225CONFIG_INET=y
226# CONFIG_IP_MULTICAST is not set
227# CONFIG_IP_ADVANCED_ROUTER is not set
228CONFIG_IP_PNP=y
229CONFIG_IP_PNP_DHCP=y
230CONFIG_IP_PNP_BOOTP=y
231CONFIG_IP_PNP_RARP=y
232CONFIG_NET_IPIP=m
233CONFIG_NET_IPGRE=m
234# CONFIG_ARPD is not set
235CONFIG_SYN_COOKIES=y
236CONFIG_INET_AH=m
237CONFIG_INET_ESP=m
238CONFIG_INET_IPCOMP=m
239CONFIG_INET_TUNNEL=m
240CONFIG_IP_TCPDIAG=m
241CONFIG_IP_TCPDIAG_IPV6=y
242
243#
244# IP: Virtual Server Configuration
245#
246# CONFIG_IP_VS is not set
247CONFIG_IPV6=m
248CONFIG_IPV6_PRIVACY=y
249CONFIG_INET6_AH=m
250CONFIG_INET6_ESP=m
251CONFIG_INET6_IPCOMP=m
252CONFIG_INET6_TUNNEL=m
253CONFIG_IPV6_TUNNEL=m
254CONFIG_NETFILTER=y
255# CONFIG_NETFILTER_DEBUG is not set
256
257#
258# IP: Netfilter Configuration
259#
260CONFIG_IP_NF_CONNTRACK=m
261# CONFIG_IP_NF_CT_ACCT is not set
262CONFIG_IP_NF_CONNTRACK_MARK=y
263# CONFIG_IP_NF_CT_PROTO_SCTP is not set
264CONFIG_IP_NF_FTP=m
265CONFIG_IP_NF_IRC=m
266CONFIG_IP_NF_TFTP=m
267CONFIG_IP_NF_AMANDA=m
268CONFIG_IP_NF_QUEUE=m
269CONFIG_IP_NF_IPTABLES=m
270CONFIG_IP_NF_MATCH_LIMIT=m
271CONFIG_IP_NF_MATCH_IPRANGE=m
272CONFIG_IP_NF_MATCH_MAC=m
273CONFIG_IP_NF_MATCH_PKTTYPE=m
274CONFIG_IP_NF_MATCH_MARK=m
275CONFIG_IP_NF_MATCH_MULTIPORT=m
276CONFIG_IP_NF_MATCH_TOS=m
277CONFIG_IP_NF_MATCH_RECENT=m
278CONFIG_IP_NF_MATCH_ECN=m
279CONFIG_IP_NF_MATCH_DSCP=m
280CONFIG_IP_NF_MATCH_AH_ESP=m
281CONFIG_IP_NF_MATCH_LENGTH=m
282CONFIG_IP_NF_MATCH_TTL=m
283CONFIG_IP_NF_MATCH_TCPMSS=m
284CONFIG_IP_NF_MATCH_HELPER=m
285CONFIG_IP_NF_MATCH_STATE=m
286CONFIG_IP_NF_MATCH_CONNTRACK=m
287CONFIG_IP_NF_MATCH_OWNER=m
288CONFIG_IP_NF_MATCH_ADDRTYPE=m
289CONFIG_IP_NF_MATCH_REALM=m
290# CONFIG_IP_NF_MATCH_SCTP is not set
291# CONFIG_IP_NF_MATCH_COMMENT is not set
292CONFIG_IP_NF_MATCH_CONNMARK=m
293CONFIG_IP_NF_MATCH_HASHLIMIT=m
294CONFIG_IP_NF_FILTER=m
295CONFIG_IP_NF_TARGET_REJECT=m
296CONFIG_IP_NF_TARGET_LOG=m
297CONFIG_IP_NF_TARGET_ULOG=m
298CONFIG_IP_NF_TARGET_TCPMSS=m
299CONFIG_IP_NF_NAT=m
300CONFIG_IP_NF_NAT_NEEDED=y
301CONFIG_IP_NF_TARGET_MASQUERADE=m
302CONFIG_IP_NF_TARGET_REDIRECT=m
303CONFIG_IP_NF_TARGET_NETMAP=m
304CONFIG_IP_NF_TARGET_SAME=m
305CONFIG_IP_NF_NAT_SNMP_BASIC=m
306CONFIG_IP_NF_NAT_IRC=m
307CONFIG_IP_NF_NAT_FTP=m
308CONFIG_IP_NF_NAT_TFTP=m
309CONFIG_IP_NF_NAT_AMANDA=m
310CONFIG_IP_NF_MANGLE=m
311CONFIG_IP_NF_TARGET_TOS=m
312CONFIG_IP_NF_TARGET_ECN=m
313CONFIG_IP_NF_TARGET_DSCP=m
314CONFIG_IP_NF_TARGET_MARK=m
315CONFIG_IP_NF_TARGET_CLASSIFY=m
316CONFIG_IP_NF_TARGET_CONNMARK=m
317# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
318CONFIG_IP_NF_RAW=m
319CONFIG_IP_NF_TARGET_NOTRACK=m
320CONFIG_IP_NF_ARPTABLES=m
321CONFIG_IP_NF_ARPFILTER=m
322CONFIG_IP_NF_ARP_MANGLE=m
323CONFIG_IP_NF_COMPAT_IPCHAINS=m
324CONFIG_IP_NF_COMPAT_IPFWADM=m
325
326#
327# IPv6: Netfilter Configuration
328#
329CONFIG_IP6_NF_QUEUE=m
330CONFIG_IP6_NF_IPTABLES=m
331CONFIG_IP6_NF_MATCH_LIMIT=m
332CONFIG_IP6_NF_MATCH_MAC=m
333CONFIG_IP6_NF_MATCH_RT=m
334CONFIG_IP6_NF_MATCH_OPTS=m
335CONFIG_IP6_NF_MATCH_FRAG=m
336CONFIG_IP6_NF_MATCH_HL=m
337CONFIG_IP6_NF_MATCH_MULTIPORT=m
338CONFIG_IP6_NF_MATCH_OWNER=m
339CONFIG_IP6_NF_MATCH_MARK=m
340CONFIG_IP6_NF_MATCH_IPV6HEADER=m
341CONFIG_IP6_NF_MATCH_AHESP=m
342CONFIG_IP6_NF_MATCH_LENGTH=m
343CONFIG_IP6_NF_MATCH_EUI64=m
344CONFIG_IP6_NF_FILTER=m
345CONFIG_IP6_NF_TARGET_LOG=m
346CONFIG_IP6_NF_MANGLE=m
347CONFIG_IP6_NF_TARGET_MARK=m
348CONFIG_IP6_NF_RAW=m
349CONFIG_XFRM=y
350CONFIG_XFRM_USER=m
351
352#
353# SCTP Configuration (EXPERIMENTAL)
354#
355CONFIG_IP_SCTP=m
356# CONFIG_SCTP_DBG_MSG is not set
357# CONFIG_SCTP_DBG_OBJCNT is not set
358# CONFIG_SCTP_HMAC_NONE is not set
359# CONFIG_SCTP_HMAC_SHA1 is not set
360CONFIG_SCTP_HMAC_MD5=y
361# CONFIG_ATM is not set
362# CONFIG_BRIDGE is not set
363# CONFIG_VLAN_8021Q is not set
364# CONFIG_DECNET is not set
365CONFIG_LLC=m
366# CONFIG_LLC2 is not set
367# CONFIG_IPX is not set
368CONFIG_ATALK=m
369# CONFIG_DEV_APPLETALK is not set
370# CONFIG_X25 is not set
371# CONFIG_LAPB is not set
372# CONFIG_NET_DIVERT is not set
373# CONFIG_ECONET is not set
374# CONFIG_WAN_ROUTER is not set
375
376#
377# QoS and/or fair queueing
378#
379# CONFIG_NET_SCHED is not set
380CONFIG_NET_CLS_ROUTE=y
381
382#
383# Network testing
384#
385# CONFIG_NET_PKTGEN is not set
386CONFIG_NETPOLL=y
387# CONFIG_NETPOLL_RX is not set
388# CONFIG_NETPOLL_TRAP is not set
389CONFIG_NET_POLL_CONTROLLER=y
390# CONFIG_HAMRADIO is not set
391# CONFIG_IRDA is not set
392# CONFIG_BT is not set
393CONFIG_NETDEVICES=y
394CONFIG_DUMMY=m
395# CONFIG_BONDING is not set
396CONFIG_EQUALIZER=m
397# CONFIG_TUN is not set
398# CONFIG_ETHERTAP is not set
399
400#
401# Ethernet (10 or 100Mbit)
402#
403CONFIG_NET_ETHERNET=y
404CONFIG_MII=m
405CONFIG_BVME6000_NET=y
406
407#
408# Ethernet (1000 Mbit)
409#
410
411#
412# Ethernet (10000 Mbit)
413#
414
415#
416# Token Ring devices
417#
418
419#
420# Wireless LAN (non-hamradio)
421#
422# CONFIG_NET_RADIO is not set
423
424#
425# Wan interfaces
426#
427# CONFIG_WAN is not set
428CONFIG_PPP=m
429# CONFIG_PPP_MULTILINK is not set
430# CONFIG_PPP_FILTER is not set
431CONFIG_PPP_ASYNC=m
432CONFIG_PPP_SYNC_TTY=m
433CONFIG_PPP_DEFLATE=m
434CONFIG_PPP_BSDCOMP=m
435CONFIG_PPPOE=m
436CONFIG_SLIP=m
437CONFIG_SLIP_COMPRESSED=y
438CONFIG_SLIP_SMART=y
439CONFIG_SLIP_MODE_SLIP6=y
440CONFIG_SHAPER=m
441CONFIG_NETCONSOLE=m
442
443#
444# ISDN subsystem
445#
446# CONFIG_ISDN is not set
447
448#
449# Telephony Support
450#
451# CONFIG_PHONE is not set
452
453#
454# Input device support
455#
456CONFIG_INPUT=y
457
458#
459# Userland interfaces
460#
461CONFIG_INPUT_MOUSEDEV=y
462CONFIG_INPUT_MOUSEDEV_PSAUX=y
463CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
464CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
465# CONFIG_INPUT_JOYDEV is not set
466# CONFIG_INPUT_TSDEV is not set
467# CONFIG_INPUT_EVDEV is not set
468# CONFIG_INPUT_EVBUG is not set
469
470#
471# Input I/O drivers
472#
473# CONFIG_GAMEPORT is not set
474CONFIG_SOUND_GAMEPORT=y
475CONFIG_SERIO=m
476CONFIG_SERIO_SERPORT=m
477# CONFIG_SERIO_CT82C710 is not set
478# CONFIG_SERIO_RAW is not set
479
480#
481# Input Device Drivers
482#
483CONFIG_INPUT_KEYBOARD=y
484# CONFIG_KEYBOARD_ATKBD is not set
485# CONFIG_KEYBOARD_SUNKBD is not set
486# CONFIG_KEYBOARD_LKKBD is not set
487# CONFIG_KEYBOARD_XTKBD is not set
488# CONFIG_KEYBOARD_NEWTON is not set
489CONFIG_INPUT_MOUSE=y
490CONFIG_MOUSE_PS2=m
491CONFIG_MOUSE_SERIAL=m
492# CONFIG_MOUSE_VSXXXAA is not set
493# CONFIG_INPUT_JOYSTICK is not set
494# CONFIG_INPUT_TOUCHSCREEN is not set
495# CONFIG_INPUT_MISC is not set
496
497#
498# Character devices
499#
500CONFIG_VT=y
501CONFIG_VT_CONSOLE=y
502CONFIG_HW_CONSOLE=y
503# CONFIG_SERIAL_NONSTANDARD is not set
504
505#
506# Serial drivers
507#
508# CONFIG_SERIAL_8250 is not set
509
510#
511# Non-8250 serial port support
512#
513CONFIG_UNIX98_PTYS=y
514CONFIG_LEGACY_PTYS=y
515CONFIG_LEGACY_PTY_COUNT=256
516
517#
518# IPMI
519#
520# CONFIG_IPMI_HANDLER is not set
521
522#
523# Watchdog Cards
524#
525# CONFIG_WATCHDOG is not set
526CONFIG_GEN_RTC=m
527CONFIG_GEN_RTC_X=y
528# CONFIG_DTLK is not set
529# CONFIG_R3964 is not set
530
531#
532# Ftape, the floppy tape device driver
533#
534# CONFIG_DRM is not set
535# CONFIG_RAW_DRIVER is not set
536
537#
538# I2C support
539#
540# CONFIG_I2C is not set
541
542#
543# Dallas's 1-wire bus
544#
545# CONFIG_W1 is not set
546
547#
548# Misc devices
549#
550
551#
552# Multimedia devices
553#
554# CONFIG_VIDEO_DEV is not set
555
556#
557# Digital Video Broadcasting Devices
558#
559# CONFIG_DVB is not set
560
561#
562# Graphics support
563#
564# CONFIG_FB is not set
565
566#
567# Console display driver support
568#
569CONFIG_DUMMY_CONSOLE=y
570
571#
572# Sound
573#
574# CONFIG_SOUND is not set
575
576#
577# USB support
578#
579# CONFIG_USB_ARCH_HAS_HCD is not set
580# CONFIG_USB_ARCH_HAS_OHCI is not set
581
582#
583# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
584#
585
586#
587# USB Gadget Support
588#
589# CONFIG_USB_GADGET is not set
590
591#
592# MMC/SD Card support
593#
594# CONFIG_MMC is not set
595
596#
597# Character devices
598#
599CONFIG_BVME6000_SCC=y
600CONFIG_SERIAL_CONSOLE=y
601
602#
603# File systems
604#
605CONFIG_EXT2_FS=y
606# CONFIG_EXT2_FS_XATTR is not set
607CONFIG_EXT3_FS=y
608# CONFIG_EXT3_FS_XATTR is not set
609CONFIG_JBD=y
610# CONFIG_JBD_DEBUG is not set
611CONFIG_REISERFS_FS=m
612# CONFIG_REISERFS_CHECK is not set
613# CONFIG_REISERFS_PROC_INFO is not set
614# CONFIG_REISERFS_FS_XATTR is not set
615CONFIG_JFS_FS=m
616# CONFIG_JFS_POSIX_ACL is not set
617# CONFIG_JFS_DEBUG is not set
618# CONFIG_JFS_STATISTICS is not set
619CONFIG_FS_POSIX_ACL=y
620CONFIG_XFS_FS=m
621# CONFIG_XFS_RT is not set
622# CONFIG_XFS_QUOTA is not set
623# CONFIG_XFS_SECURITY is not set
624# CONFIG_XFS_POSIX_ACL is not set
625CONFIG_MINIX_FS=y
626# CONFIG_ROMFS_FS is not set
627CONFIG_QUOTA=y
628# CONFIG_QFMT_V1 is not set
629# CONFIG_QFMT_V2 is not set
630CONFIG_QUOTACTL=y
631CONFIG_DNOTIFY=y
632CONFIG_AUTOFS_FS=m
633CONFIG_AUTOFS4_FS=m
634
635#
636# CD-ROM/DVD Filesystems
637#
638CONFIG_ISO9660_FS=y
639CONFIG_JOLIET=y
640CONFIG_ZISOFS=y
641CONFIG_ZISOFS_FS=y
642CONFIG_UDF_FS=m
643CONFIG_UDF_NLS=y
644
645#
646# DOS/FAT/NT Filesystems
647#
648CONFIG_FAT_FS=y
649CONFIG_MSDOS_FS=y
650CONFIG_VFAT_FS=m
651CONFIG_FAT_DEFAULT_CODEPAGE=437
652CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
653# CONFIG_NTFS_FS is not set
654
655#
656# Pseudo filesystems
657#
658CONFIG_PROC_FS=y
659CONFIG_PROC_KCORE=y
660CONFIG_SYSFS=y
661# CONFIG_DEVFS_FS is not set
662# CONFIG_DEVPTS_FS_XATTR is not set
663CONFIG_TMPFS=y
664# CONFIG_TMPFS_XATTR is not set
665# CONFIG_HUGETLB_PAGE is not set
666CONFIG_RAMFS=y
667
668#
669# Miscellaneous filesystems
670#
671# CONFIG_ADFS_FS is not set
672CONFIG_AFFS_FS=m
673CONFIG_HFS_FS=m
674CONFIG_HFSPLUS_FS=m
675# CONFIG_BEFS_FS is not set
676# CONFIG_BFS_FS is not set
677# CONFIG_EFS_FS is not set
678CONFIG_CRAMFS=m
679# CONFIG_VXFS_FS is not set
680CONFIG_HPFS_FS=m
681# CONFIG_QNX4FS_FS is not set
682CONFIG_SYSV_FS=m
683CONFIG_UFS_FS=m
684# CONFIG_UFS_FS_WRITE is not set
685
686#
687# Network File Systems
688#
689CONFIG_NFS_FS=y
690CONFIG_NFS_V3=y
691CONFIG_NFS_V4=y
692# CONFIG_NFS_DIRECTIO is not set
693CONFIG_NFSD=m
694CONFIG_NFSD_V3=y
695CONFIG_NFSD_V4=y
696CONFIG_NFSD_TCP=y
697CONFIG_ROOT_NFS=y
698CONFIG_LOCKD=y
699CONFIG_LOCKD_V4=y
700CONFIG_EXPORTFS=m
701CONFIG_SUNRPC=y
702CONFIG_SUNRPC_GSS=y
703CONFIG_RPCSEC_GSS_KRB5=y
704# CONFIG_RPCSEC_GSS_SPKM3 is not set
705CONFIG_SMB_FS=m
706CONFIG_SMB_NLS_DEFAULT=y
707CONFIG_SMB_NLS_REMOTE="cp437"
708# CONFIG_CIFS is not set
709CONFIG_NCP_FS=m
710# CONFIG_NCPFS_PACKET_SIGNING is not set
711# CONFIG_NCPFS_IOCTL_LOCKING is not set
712# CONFIG_NCPFS_STRONG is not set
713CONFIG_NCPFS_NFS_NS=y
714CONFIG_NCPFS_OS2_NS=y
715# CONFIG_NCPFS_SMALLDOS is not set
716CONFIG_NCPFS_NLS=y
717# CONFIG_NCPFS_EXTRAS is not set
718CONFIG_CODA_FS=m
719# CONFIG_CODA_FS_OLD_API is not set
720# CONFIG_AFS_FS is not set
721
722#
723# Partition Types
724#
725# CONFIG_PARTITION_ADVANCED is not set
726CONFIG_MSDOS_PARTITION=y
727
728#
729# Native Language Support
730#
731CONFIG_NLS=y
732CONFIG_NLS_DEFAULT="iso8859-1"
733CONFIG_NLS_CODEPAGE_437=y
734CONFIG_NLS_CODEPAGE_737=m
735CONFIG_NLS_CODEPAGE_775=m
736CONFIG_NLS_CODEPAGE_850=m
737CONFIG_NLS_CODEPAGE_852=m
738CONFIG_NLS_CODEPAGE_855=m
739CONFIG_NLS_CODEPAGE_857=m
740CONFIG_NLS_CODEPAGE_860=m
741CONFIG_NLS_CODEPAGE_861=m
742CONFIG_NLS_CODEPAGE_862=m
743CONFIG_NLS_CODEPAGE_863=m
744CONFIG_NLS_CODEPAGE_864=m
745CONFIG_NLS_CODEPAGE_865=m
746CONFIG_NLS_CODEPAGE_866=m
747CONFIG_NLS_CODEPAGE_869=m
748CONFIG_NLS_CODEPAGE_936=m
749CONFIG_NLS_CODEPAGE_950=m
750CONFIG_NLS_CODEPAGE_932=m
751CONFIG_NLS_CODEPAGE_949=m
752CONFIG_NLS_CODEPAGE_874=m
753CONFIG_NLS_ISO8859_8=m
754CONFIG_NLS_CODEPAGE_1250=m
755CONFIG_NLS_CODEPAGE_1251=m
756CONFIG_NLS_ASCII=m
757CONFIG_NLS_ISO8859_1=y
758CONFIG_NLS_ISO8859_2=m
759CONFIG_NLS_ISO8859_3=m
760CONFIG_NLS_ISO8859_4=m
761CONFIG_NLS_ISO8859_5=m
762CONFIG_NLS_ISO8859_6=m
763CONFIG_NLS_ISO8859_7=m
764CONFIG_NLS_ISO8859_9=m
765CONFIG_NLS_ISO8859_13=m
766CONFIG_NLS_ISO8859_14=m
767CONFIG_NLS_ISO8859_15=m
768CONFIG_NLS_KOI8_R=m
769CONFIG_NLS_KOI8_U=m
770CONFIG_NLS_UTF8=m
771
772#
773# Kernel hacking
774#
775CONFIG_DEBUG_KERNEL=y
776CONFIG_MAGIC_SYSRQ=y
777# CONFIG_SCHEDSTATS is not set
778# CONFIG_DEBUG_SLAB is not set
779# CONFIG_DEBUG_KOBJECT is not set
780# CONFIG_DEBUG_BUGVERBOSE is not set
781# CONFIG_DEBUG_INFO is not set
782
783#
784# Security options
785#
786# CONFIG_KEYS is not set
787# CONFIG_SECURITY is not set
788
789#
790# Cryptographic options
791#
792CONFIG_CRYPTO=y
793CONFIG_CRYPTO_HMAC=y
794CONFIG_CRYPTO_NULL=m
795CONFIG_CRYPTO_MD4=m
796CONFIG_CRYPTO_MD5=y
797CONFIG_CRYPTO_SHA1=m
798CONFIG_CRYPTO_SHA256=m
799CONFIG_CRYPTO_SHA512=m
800# CONFIG_CRYPTO_WP512 is not set
801CONFIG_CRYPTO_DES=y
802CONFIG_CRYPTO_BLOWFISH=m
803CONFIG_CRYPTO_TWOFISH=m
804CONFIG_CRYPTO_SERPENT=m
805CONFIG_CRYPTO_AES=m
806CONFIG_CRYPTO_CAST5=m
807CONFIG_CRYPTO_CAST6=m
808CONFIG_CRYPTO_TEA=m
809CONFIG_CRYPTO_ARC4=m
810CONFIG_CRYPTO_KHAZAD=m
811CONFIG_CRYPTO_ANUBIS=m
812CONFIG_CRYPTO_DEFLATE=m
813CONFIG_CRYPTO_MICHAEL_MIC=m
814CONFIG_CRYPTO_CRC32C=m
815CONFIG_CRYPTO_TEST=m
816
817#
818# Library routines
819#
820CONFIG_CRC_CCITT=m
821CONFIG_CRC32=m
822CONFIG_LIBCRC32C=m
823CONFIG_ZLIB_INFLATE=y
824CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
new file mode 100644
index 000000000000..53dde43ddfcb
--- /dev/null
+++ b/arch/m68k/configs/hp300_defconfig
@@ -0,0 +1,824 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:23:40 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-hp300"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63# CONFIG_ATARI is not set
64# CONFIG_MAC is not set
65# CONFIG_APOLLO is not set
66# CONFIG_VME is not set
67CONFIG_HP300=y
68CONFIG_DIO=y
69# CONFIG_SUN3X is not set
70# CONFIG_Q40 is not set
71
72#
73# Processor type
74#
75CONFIG_M68020=y
76CONFIG_M68030=y
77CONFIG_M68040=y
78CONFIG_M68060=y
79CONFIG_MMU_MOTOROLA=y
80CONFIG_M68KFPU_EMU=y
81CONFIG_M68KFPU_EMU_EXTRAPREC=y
82# CONFIG_M68KFPU_EMU_ONLY is not set
83# CONFIG_ADVANCED is not set
84
85#
86# General setup
87#
88CONFIG_BINFMT_ELF=y
89CONFIG_BINFMT_AOUT=m
90CONFIG_BINFMT_MISC=m
91CONFIG_HEARTBEAT=y
92CONFIG_PROC_HARDWARE=y
93
94#
95# Device Drivers
96#
97
98#
99# Generic Driver Options
100#
101CONFIG_STANDALONE=y
102CONFIG_PREVENT_FIRMWARE_BUILD=y
103# CONFIG_DEBUG_DRIVER is not set
104
105#
106# Memory Technology Devices (MTD)
107#
108# CONFIG_MTD is not set
109
110#
111# Parallel port support
112#
113# CONFIG_PARPORT is not set
114
115#
116# Plug and Play support
117#
118
119#
120# Block devices
121#
122CONFIG_BLK_DEV_LOOP=y
123CONFIG_BLK_DEV_CRYPTOLOOP=m
124CONFIG_BLK_DEV_NBD=m
125CONFIG_BLK_DEV_RAM=y
126CONFIG_BLK_DEV_RAM_COUNT=16
127CONFIG_BLK_DEV_RAM_SIZE=4096
128CONFIG_BLK_DEV_INITRD=y
129CONFIG_INITRAMFS_SOURCE=""
130CONFIG_CDROM_PKTCDVD=m
131CONFIG_CDROM_PKTCDVD_BUFFERS=8
132# CONFIG_CDROM_PKTCDVD_WCACHE is not set
133
134#
135# IO Schedulers
136#
137CONFIG_IOSCHED_NOOP=y
138CONFIG_IOSCHED_AS=y
139CONFIG_IOSCHED_DEADLINE=y
140CONFIG_IOSCHED_CFQ=y
141
142#
143# ATA/ATAPI/MFM/RLL support
144#
145# CONFIG_IDE is not set
146
147#
148# SCSI device support
149#
150CONFIG_SCSI=y
151CONFIG_SCSI_PROC_FS=y
152
153#
154# SCSI support type (disk, tape, CD-ROM)
155#
156CONFIG_BLK_DEV_SD=y
157CONFIG_CHR_DEV_ST=m
158# CONFIG_CHR_DEV_OSST is not set
159CONFIG_BLK_DEV_SR=y
160CONFIG_BLK_DEV_SR_VENDOR=y
161CONFIG_CHR_DEV_SG=m
162
163#
164# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
165#
166# CONFIG_SCSI_MULTI_LUN is not set
167CONFIG_SCSI_CONSTANTS=y
168# CONFIG_SCSI_LOGGING is not set
169
170#
171# SCSI Transport Attributes
172#
173# CONFIG_SCSI_SPI_ATTRS is not set
174# CONFIG_SCSI_FC_ATTRS is not set
175
176#
177# SCSI low-level drivers
178#
179# CONFIG_SCSI_SATA is not set
180# CONFIG_SCSI_DEBUG is not set
181
182#
183# Multi-device support (RAID and LVM)
184#
185CONFIG_MD=y
186CONFIG_BLK_DEV_MD=m
187CONFIG_MD_LINEAR=m
188CONFIG_MD_RAID0=m
189CONFIG_MD_RAID1=m
190# CONFIG_MD_RAID10 is not set
191CONFIG_MD_RAID5=m
192CONFIG_MD_RAID6=m
193CONFIG_MD_MULTIPATH=m
194# CONFIG_MD_FAULTY is not set
195CONFIG_BLK_DEV_DM=m
196CONFIG_DM_CRYPT=m
197CONFIG_DM_SNAPSHOT=m
198CONFIG_DM_MIRROR=m
199CONFIG_DM_ZERO=m
200
201#
202# Fusion MPT device support
203#
204
205#
206# IEEE 1394 (FireWire) support
207#
208
209#
210# I2O device support
211#
212
213#
214# Networking support
215#
216CONFIG_NET=y
217
218#
219# Networking options
220#
221CONFIG_PACKET=y
222# CONFIG_PACKET_MMAP is not set
223CONFIG_NETLINK_DEV=y
224CONFIG_UNIX=y
225CONFIG_NET_KEY=y
226CONFIG_INET=y
227# CONFIG_IP_MULTICAST is not set
228# CONFIG_IP_ADVANCED_ROUTER is not set
229CONFIG_IP_PNP=y
230CONFIG_IP_PNP_DHCP=y
231CONFIG_IP_PNP_BOOTP=y
232CONFIG_IP_PNP_RARP=y
233CONFIG_NET_IPIP=m
234CONFIG_NET_IPGRE=m
235# CONFIG_ARPD is not set
236CONFIG_SYN_COOKIES=y
237CONFIG_INET_AH=m
238CONFIG_INET_ESP=m
239CONFIG_INET_IPCOMP=m
240CONFIG_INET_TUNNEL=m
241CONFIG_IP_TCPDIAG=m
242CONFIG_IP_TCPDIAG_IPV6=y
243
244#
245# IP: Virtual Server Configuration
246#
247# CONFIG_IP_VS is not set
248CONFIG_IPV6=m
249CONFIG_IPV6_PRIVACY=y
250CONFIG_INET6_AH=m
251CONFIG_INET6_ESP=m
252CONFIG_INET6_IPCOMP=m
253CONFIG_INET6_TUNNEL=m
254CONFIG_IPV6_TUNNEL=m
255CONFIG_NETFILTER=y
256# CONFIG_NETFILTER_DEBUG is not set
257
258#
259# IP: Netfilter Configuration
260#
261CONFIG_IP_NF_CONNTRACK=m
262# CONFIG_IP_NF_CT_ACCT is not set
263CONFIG_IP_NF_CONNTRACK_MARK=y
264# CONFIG_IP_NF_CT_PROTO_SCTP is not set
265CONFIG_IP_NF_FTP=m
266CONFIG_IP_NF_IRC=m
267CONFIG_IP_NF_TFTP=m
268CONFIG_IP_NF_AMANDA=m
269CONFIG_IP_NF_QUEUE=m
270CONFIG_IP_NF_IPTABLES=m
271CONFIG_IP_NF_MATCH_LIMIT=m
272CONFIG_IP_NF_MATCH_IPRANGE=m
273CONFIG_IP_NF_MATCH_MAC=m
274CONFIG_IP_NF_MATCH_PKTTYPE=m
275CONFIG_IP_NF_MATCH_MARK=m
276CONFIG_IP_NF_MATCH_MULTIPORT=m
277CONFIG_IP_NF_MATCH_TOS=m
278CONFIG_IP_NF_MATCH_RECENT=m
279CONFIG_IP_NF_MATCH_ECN=m
280CONFIG_IP_NF_MATCH_DSCP=m
281CONFIG_IP_NF_MATCH_AH_ESP=m
282CONFIG_IP_NF_MATCH_LENGTH=m
283CONFIG_IP_NF_MATCH_TTL=m
284CONFIG_IP_NF_MATCH_TCPMSS=m
285CONFIG_IP_NF_MATCH_HELPER=m
286CONFIG_IP_NF_MATCH_STATE=m
287CONFIG_IP_NF_MATCH_CONNTRACK=m
288CONFIG_IP_NF_MATCH_OWNER=m
289CONFIG_IP_NF_MATCH_ADDRTYPE=m
290CONFIG_IP_NF_MATCH_REALM=m
291# CONFIG_IP_NF_MATCH_SCTP is not set
292# CONFIG_IP_NF_MATCH_COMMENT is not set
293CONFIG_IP_NF_MATCH_CONNMARK=m
294CONFIG_IP_NF_MATCH_HASHLIMIT=m
295CONFIG_IP_NF_FILTER=m
296CONFIG_IP_NF_TARGET_REJECT=m
297CONFIG_IP_NF_TARGET_LOG=m
298CONFIG_IP_NF_TARGET_ULOG=m
299CONFIG_IP_NF_TARGET_TCPMSS=m
300CONFIG_IP_NF_NAT=m
301CONFIG_IP_NF_NAT_NEEDED=y
302CONFIG_IP_NF_TARGET_MASQUERADE=m
303CONFIG_IP_NF_TARGET_REDIRECT=m
304CONFIG_IP_NF_TARGET_NETMAP=m
305CONFIG_IP_NF_TARGET_SAME=m
306CONFIG_IP_NF_NAT_SNMP_BASIC=m
307CONFIG_IP_NF_NAT_IRC=m
308CONFIG_IP_NF_NAT_FTP=m
309CONFIG_IP_NF_NAT_TFTP=m
310CONFIG_IP_NF_NAT_AMANDA=m
311CONFIG_IP_NF_MANGLE=m
312CONFIG_IP_NF_TARGET_TOS=m
313CONFIG_IP_NF_TARGET_ECN=m
314CONFIG_IP_NF_TARGET_DSCP=m
315CONFIG_IP_NF_TARGET_MARK=m
316CONFIG_IP_NF_TARGET_CLASSIFY=m
317CONFIG_IP_NF_TARGET_CONNMARK=m
318# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
319CONFIG_IP_NF_RAW=m
320CONFIG_IP_NF_TARGET_NOTRACK=m
321CONFIG_IP_NF_ARPTABLES=m
322CONFIG_IP_NF_ARPFILTER=m
323CONFIG_IP_NF_ARP_MANGLE=m
324CONFIG_IP_NF_COMPAT_IPCHAINS=m
325CONFIG_IP_NF_COMPAT_IPFWADM=m
326
327#
328# IPv6: Netfilter Configuration
329#
330CONFIG_IP6_NF_QUEUE=m
331CONFIG_IP6_NF_IPTABLES=m
332CONFIG_IP6_NF_MATCH_LIMIT=m
333CONFIG_IP6_NF_MATCH_MAC=m
334CONFIG_IP6_NF_MATCH_RT=m
335CONFIG_IP6_NF_MATCH_OPTS=m
336CONFIG_IP6_NF_MATCH_FRAG=m
337CONFIG_IP6_NF_MATCH_HL=m
338CONFIG_IP6_NF_MATCH_MULTIPORT=m
339CONFIG_IP6_NF_MATCH_OWNER=m
340CONFIG_IP6_NF_MATCH_MARK=m
341CONFIG_IP6_NF_MATCH_IPV6HEADER=m
342CONFIG_IP6_NF_MATCH_AHESP=m
343CONFIG_IP6_NF_MATCH_LENGTH=m
344CONFIG_IP6_NF_MATCH_EUI64=m
345CONFIG_IP6_NF_FILTER=m
346CONFIG_IP6_NF_TARGET_LOG=m
347CONFIG_IP6_NF_MANGLE=m
348CONFIG_IP6_NF_TARGET_MARK=m
349CONFIG_IP6_NF_RAW=m
350CONFIG_XFRM=y
351CONFIG_XFRM_USER=m
352
353#
354# SCTP Configuration (EXPERIMENTAL)
355#
356CONFIG_IP_SCTP=m
357# CONFIG_SCTP_DBG_MSG is not set
358# CONFIG_SCTP_DBG_OBJCNT is not set
359# CONFIG_SCTP_HMAC_NONE is not set
360# CONFIG_SCTP_HMAC_SHA1 is not set
361CONFIG_SCTP_HMAC_MD5=y
362# CONFIG_ATM is not set
363# CONFIG_BRIDGE is not set
364# CONFIG_VLAN_8021Q is not set
365# CONFIG_DECNET is not set
366CONFIG_LLC=m
367# CONFIG_LLC2 is not set
368CONFIG_IPX=m
369# CONFIG_IPX_INTERN is not set
370CONFIG_ATALK=m
371# CONFIG_DEV_APPLETALK is not set
372# CONFIG_X25 is not set
373# CONFIG_LAPB is not set
374# CONFIG_NET_DIVERT is not set
375# CONFIG_ECONET is not set
376# CONFIG_WAN_ROUTER is not set
377
378#
379# QoS and/or fair queueing
380#
381# CONFIG_NET_SCHED is not set
382CONFIG_NET_CLS_ROUTE=y
383
384#
385# Network testing
386#
387# CONFIG_NET_PKTGEN is not set
388CONFIG_NETPOLL=y
389# CONFIG_NETPOLL_RX is not set
390# CONFIG_NETPOLL_TRAP is not set
391CONFIG_NET_POLL_CONTROLLER=y
392# CONFIG_HAMRADIO is not set
393# CONFIG_IRDA is not set
394# CONFIG_BT is not set
395CONFIG_NETDEVICES=y
396CONFIG_DUMMY=m
397# CONFIG_BONDING is not set
398CONFIG_EQUALIZER=m
399# CONFIG_TUN is not set
400# CONFIG_ETHERTAP is not set
401
402#
403# Ethernet (10 or 100Mbit)
404#
405CONFIG_NET_ETHERNET=y
406CONFIG_MII=m
407CONFIG_HPLANCE=y
408
409#
410# Ethernet (1000 Mbit)
411#
412
413#
414# Ethernet (10000 Mbit)
415#
416
417#
418# Token Ring devices
419#
420
421#
422# Wireless LAN (non-hamradio)
423#
424# CONFIG_NET_RADIO is not set
425
426#
427# Wan interfaces
428#
429# CONFIG_WAN is not set
430CONFIG_PPP=m
431# CONFIG_PPP_MULTILINK is not set
432CONFIG_PPP_FILTER=y
433CONFIG_PPP_ASYNC=m
434CONFIG_PPP_SYNC_TTY=m
435CONFIG_PPP_DEFLATE=m
436CONFIG_PPP_BSDCOMP=m
437CONFIG_PPPOE=m
438CONFIG_SLIP=m
439CONFIG_SLIP_COMPRESSED=y
440CONFIG_SLIP_SMART=y
441CONFIG_SLIP_MODE_SLIP6=y
442CONFIG_SHAPER=m
443CONFIG_NETCONSOLE=m
444
445#
446# ISDN subsystem
447#
448# CONFIG_ISDN is not set
449
450#
451# Telephony Support
452#
453# CONFIG_PHONE is not set
454
455#
456# Input device support
457#
458CONFIG_INPUT=y
459
460#
461# Userland interfaces
462#
463CONFIG_INPUT_MOUSEDEV=y
464CONFIG_INPUT_MOUSEDEV_PSAUX=y
465CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
466CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
467# CONFIG_INPUT_JOYDEV is not set
468# CONFIG_INPUT_TSDEV is not set
469# CONFIG_INPUT_EVDEV is not set
470# CONFIG_INPUT_EVBUG is not set
471
472#
473# Input I/O drivers
474#
475# CONFIG_GAMEPORT is not set
476CONFIG_SOUND_GAMEPORT=y
477CONFIG_SERIO=m
478CONFIG_SERIO_SERPORT=m
479# CONFIG_SERIO_CT82C710 is not set
480# CONFIG_SERIO_RAW is not set
481
482#
483# Input Device Drivers
484#
485CONFIG_INPUT_KEYBOARD=y
486# CONFIG_KEYBOARD_ATKBD is not set
487# CONFIG_KEYBOARD_SUNKBD is not set
488# CONFIG_KEYBOARD_LKKBD is not set
489# CONFIG_KEYBOARD_XTKBD is not set
490# CONFIG_KEYBOARD_NEWTON is not set
491CONFIG_INPUT_MOUSE=y
492CONFIG_MOUSE_PS2=m
493CONFIG_MOUSE_SERIAL=m
494# CONFIG_MOUSE_VSXXXAA is not set
495# CONFIG_INPUT_JOYSTICK is not set
496# CONFIG_INPUT_TOUCHSCREEN is not set
497# CONFIG_INPUT_MISC is not set
498
499#
500# Character devices
501#
502CONFIG_VT=y
503CONFIG_VT_CONSOLE=y
504CONFIG_HW_CONSOLE=y
505# CONFIG_SERIAL_NONSTANDARD is not set
506
507#
508# Serial drivers
509#
510# CONFIG_SERIAL_8250 is not set
511
512#
513# Non-8250 serial port support
514#
515CONFIG_UNIX98_PTYS=y
516CONFIG_LEGACY_PTYS=y
517CONFIG_LEGACY_PTY_COUNT=256
518
519#
520# IPMI
521#
522# CONFIG_IPMI_HANDLER is not set
523
524#
525# Watchdog Cards
526#
527# CONFIG_WATCHDOG is not set
528CONFIG_GEN_RTC=y
529CONFIG_GEN_RTC_X=y
530# CONFIG_DTLK is not set
531# CONFIG_R3964 is not set
532
533#
534# Ftape, the floppy tape device driver
535#
536# CONFIG_DRM is not set
537# CONFIG_RAW_DRIVER is not set
538
539#
540# I2C support
541#
542# CONFIG_I2C is not set
543
544#
545# Dallas's 1-wire bus
546#
547# CONFIG_W1 is not set
548
549#
550# Misc devices
551#
552
553#
554# Multimedia devices
555#
556# CONFIG_VIDEO_DEV is not set
557
558#
559# Digital Video Broadcasting Devices
560#
561# CONFIG_DVB is not set
562
563#
564# Graphics support
565#
566# CONFIG_FB is not set
567
568#
569# Console display driver support
570#
571CONFIG_DUMMY_CONSOLE=y
572
573#
574# Sound
575#
576# CONFIG_SOUND is not set
577
578#
579# USB support
580#
581# CONFIG_USB_ARCH_HAS_HCD is not set
582# CONFIG_USB_ARCH_HAS_OHCI is not set
583
584#
585# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
586#
587
588#
589# USB Gadget Support
590#
591# CONFIG_USB_GADGET is not set
592
593#
594# MMC/SD Card support
595#
596# CONFIG_MMC is not set
597
598#
599# Character devices
600#
601
602#
603# File systems
604#
605CONFIG_EXT2_FS=y
606# CONFIG_EXT2_FS_XATTR is not set
607CONFIG_EXT3_FS=y
608# CONFIG_EXT3_FS_XATTR is not set
609CONFIG_JBD=y
610# CONFIG_JBD_DEBUG is not set
611CONFIG_REISERFS_FS=m
612# CONFIG_REISERFS_CHECK is not set
613# CONFIG_REISERFS_PROC_INFO is not set
614# CONFIG_REISERFS_FS_XATTR is not set
615CONFIG_JFS_FS=m
616# CONFIG_JFS_POSIX_ACL is not set
617# CONFIG_JFS_DEBUG is not set
618# CONFIG_JFS_STATISTICS is not set
619CONFIG_FS_POSIX_ACL=y
620CONFIG_XFS_FS=m
621# CONFIG_XFS_RT is not set
622# CONFIG_XFS_QUOTA is not set
623# CONFIG_XFS_SECURITY is not set
624# CONFIG_XFS_POSIX_ACL is not set
625CONFIG_MINIX_FS=y
626# CONFIG_ROMFS_FS is not set
627CONFIG_QUOTA=y
628# CONFIG_QFMT_V1 is not set
629# CONFIG_QFMT_V2 is not set
630CONFIG_QUOTACTL=y
631CONFIG_DNOTIFY=y
632CONFIG_AUTOFS_FS=m
633CONFIG_AUTOFS4_FS=m
634
635#
636# CD-ROM/DVD Filesystems
637#
638CONFIG_ISO9660_FS=y
639CONFIG_JOLIET=y
640CONFIG_ZISOFS=y
641CONFIG_ZISOFS_FS=y
642CONFIG_UDF_FS=m
643CONFIG_UDF_NLS=y
644
645#
646# DOS/FAT/NT Filesystems
647#
648CONFIG_FAT_FS=y
649CONFIG_MSDOS_FS=y
650CONFIG_VFAT_FS=m
651CONFIG_FAT_DEFAULT_CODEPAGE=437
652CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
653# CONFIG_NTFS_FS is not set
654
655#
656# Pseudo filesystems
657#
658CONFIG_PROC_FS=y
659CONFIG_PROC_KCORE=y
660CONFIG_SYSFS=y
661# CONFIG_DEVFS_FS is not set
662# CONFIG_DEVPTS_FS_XATTR is not set
663CONFIG_TMPFS=y
664# CONFIG_TMPFS_XATTR is not set
665# CONFIG_HUGETLB_PAGE is not set
666CONFIG_RAMFS=y
667
668#
669# Miscellaneous filesystems
670#
671# CONFIG_ADFS_FS is not set
672CONFIG_AFFS_FS=m
673CONFIG_HFS_FS=m
674CONFIG_HFSPLUS_FS=m
675# CONFIG_BEFS_FS is not set
676# CONFIG_BFS_FS is not set
677# CONFIG_EFS_FS is not set
678CONFIG_CRAMFS=m
679# CONFIG_VXFS_FS is not set
680CONFIG_HPFS_FS=m
681# CONFIG_QNX4FS_FS is not set
682CONFIG_SYSV_FS=m
683CONFIG_UFS_FS=m
684# CONFIG_UFS_FS_WRITE is not set
685
686#
687# Network File Systems
688#
689CONFIG_NFS_FS=y
690CONFIG_NFS_V3=y
691CONFIG_NFS_V4=y
692# CONFIG_NFS_DIRECTIO is not set
693CONFIG_NFSD=m
694CONFIG_NFSD_V3=y
695CONFIG_NFSD_V4=y
696CONFIG_NFSD_TCP=y
697CONFIG_ROOT_NFS=y
698CONFIG_LOCKD=y
699CONFIG_LOCKD_V4=y
700CONFIG_EXPORTFS=m
701CONFIG_SUNRPC=y
702CONFIG_SUNRPC_GSS=y
703CONFIG_RPCSEC_GSS_KRB5=y
704# CONFIG_RPCSEC_GSS_SPKM3 is not set
705CONFIG_SMB_FS=m
706CONFIG_SMB_NLS_DEFAULT=y
707CONFIG_SMB_NLS_REMOTE="cp437"
708# CONFIG_CIFS is not set
709CONFIG_NCP_FS=m
710# CONFIG_NCPFS_PACKET_SIGNING is not set
711# CONFIG_NCPFS_IOCTL_LOCKING is not set
712# CONFIG_NCPFS_STRONG is not set
713CONFIG_NCPFS_NFS_NS=y
714CONFIG_NCPFS_OS2_NS=y
715# CONFIG_NCPFS_SMALLDOS is not set
716CONFIG_NCPFS_NLS=y
717# CONFIG_NCPFS_EXTRAS is not set
718CONFIG_CODA_FS=m
719# CONFIG_CODA_FS_OLD_API is not set
720# CONFIG_AFS_FS is not set
721
722#
723# Partition Types
724#
725# CONFIG_PARTITION_ADVANCED is not set
726CONFIG_MSDOS_PARTITION=y
727
728#
729# Native Language Support
730#
731CONFIG_NLS=y
732CONFIG_NLS_DEFAULT="iso8859-1"
733CONFIG_NLS_CODEPAGE_437=y
734CONFIG_NLS_CODEPAGE_737=m
735CONFIG_NLS_CODEPAGE_775=m
736CONFIG_NLS_CODEPAGE_850=m
737CONFIG_NLS_CODEPAGE_852=m
738CONFIG_NLS_CODEPAGE_855=m
739CONFIG_NLS_CODEPAGE_857=m
740CONFIG_NLS_CODEPAGE_860=m
741CONFIG_NLS_CODEPAGE_861=m
742CONFIG_NLS_CODEPAGE_862=m
743CONFIG_NLS_CODEPAGE_863=m
744CONFIG_NLS_CODEPAGE_864=m
745CONFIG_NLS_CODEPAGE_865=m
746CONFIG_NLS_CODEPAGE_866=m
747CONFIG_NLS_CODEPAGE_869=m
748CONFIG_NLS_CODEPAGE_936=m
749CONFIG_NLS_CODEPAGE_950=m
750CONFIG_NLS_CODEPAGE_932=m
751CONFIG_NLS_CODEPAGE_949=m
752CONFIG_NLS_CODEPAGE_874=m
753CONFIG_NLS_ISO8859_8=m
754CONFIG_NLS_CODEPAGE_1250=m
755CONFIG_NLS_CODEPAGE_1251=m
756CONFIG_NLS_ASCII=m
757CONFIG_NLS_ISO8859_1=y
758CONFIG_NLS_ISO8859_2=m
759CONFIG_NLS_ISO8859_3=m
760CONFIG_NLS_ISO8859_4=m
761CONFIG_NLS_ISO8859_5=m
762CONFIG_NLS_ISO8859_6=m
763CONFIG_NLS_ISO8859_7=m
764CONFIG_NLS_ISO8859_9=m
765CONFIG_NLS_ISO8859_13=m
766CONFIG_NLS_ISO8859_14=m
767CONFIG_NLS_ISO8859_15=m
768CONFIG_NLS_KOI8_R=m
769CONFIG_NLS_KOI8_U=m
770CONFIG_NLS_UTF8=m
771
772#
773# Kernel hacking
774#
775CONFIG_DEBUG_KERNEL=y
776CONFIG_MAGIC_SYSRQ=y
777# CONFIG_SCHEDSTATS is not set
778# CONFIG_DEBUG_SLAB is not set
779# CONFIG_DEBUG_KOBJECT is not set
780# CONFIG_DEBUG_BUGVERBOSE is not set
781# CONFIG_DEBUG_INFO is not set
782
783#
784# Security options
785#
786# CONFIG_KEYS is not set
787# CONFIG_SECURITY is not set
788
789#
790# Cryptographic options
791#
792CONFIG_CRYPTO=y
793CONFIG_CRYPTO_HMAC=y
794CONFIG_CRYPTO_NULL=m
795CONFIG_CRYPTO_MD4=m
796CONFIG_CRYPTO_MD5=y
797CONFIG_CRYPTO_SHA1=m
798CONFIG_CRYPTO_SHA256=m
799CONFIG_CRYPTO_SHA512=m
800# CONFIG_CRYPTO_WP512 is not set
801CONFIG_CRYPTO_DES=y
802CONFIG_CRYPTO_BLOWFISH=m
803CONFIG_CRYPTO_TWOFISH=m
804CONFIG_CRYPTO_SERPENT=m
805CONFIG_CRYPTO_AES=m
806CONFIG_CRYPTO_CAST5=m
807CONFIG_CRYPTO_CAST6=m
808CONFIG_CRYPTO_TEA=m
809CONFIG_CRYPTO_ARC4=m
810CONFIG_CRYPTO_KHAZAD=m
811CONFIG_CRYPTO_ANUBIS=m
812CONFIG_CRYPTO_DEFLATE=m
813CONFIG_CRYPTO_MICHAEL_MIC=m
814CONFIG_CRYPTO_CRC32C=m
815CONFIG_CRYPTO_TEST=m
816
817#
818# Library routines
819#
820CONFIG_CRC_CCITT=m
821CONFIG_CRC32=y
822CONFIG_LIBCRC32C=m
823CONFIG_ZLIB_INFLATE=y
824CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
new file mode 100644
index 000000000000..2452dac8db9d
--- /dev/null
+++ b/arch/m68k/configs/mac_defconfig
@@ -0,0 +1,903 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:23:44 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-mac"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63# CONFIG_ATARI is not set
64CONFIG_MAC=y
65CONFIG_NUBUS=y
66CONFIG_M68K_L2_CACHE=y
67# CONFIG_APOLLO is not set
68# CONFIG_VME is not set
69# CONFIG_HP300 is not set
70# CONFIG_SUN3X is not set
71# CONFIG_Q40 is not set
72
73#
74# Processor type
75#
76CONFIG_M68020=y
77CONFIG_M68030=y
78CONFIG_M68040=y
79# CONFIG_M68060 is not set
80CONFIG_MMU_MOTOROLA=y
81CONFIG_M68KFPU_EMU=y
82CONFIG_M68KFPU_EMU_EXTRAPREC=y
83# CONFIG_M68KFPU_EMU_ONLY is not set
84# CONFIG_ADVANCED is not set
85
86#
87# General setup
88#
89CONFIG_BINFMT_ELF=y
90CONFIG_BINFMT_AOUT=m
91CONFIG_BINFMT_MISC=m
92# CONFIG_HEARTBEAT is not set
93CONFIG_PROC_HARDWARE=y
94
95#
96# Device Drivers
97#
98
99#
100# Generic Driver Options
101#
102CONFIG_STANDALONE=y
103CONFIG_PREVENT_FIRMWARE_BUILD=y
104# CONFIG_DEBUG_DRIVER is not set
105
106#
107# Memory Technology Devices (MTD)
108#
109# CONFIG_MTD is not set
110
111#
112# Parallel port support
113#
114# CONFIG_PARPORT is not set
115
116#
117# Plug and Play support
118#
119
120#
121# Block devices
122#
123CONFIG_BLK_DEV_LOOP=y
124CONFIG_BLK_DEV_CRYPTOLOOP=m
125CONFIG_BLK_DEV_NBD=m
126CONFIG_BLK_DEV_RAM=y
127CONFIG_BLK_DEV_RAM_COUNT=16
128CONFIG_BLK_DEV_RAM_SIZE=4096
129CONFIG_BLK_DEV_INITRD=y
130CONFIG_INITRAMFS_SOURCE=""
131CONFIG_CDROM_PKTCDVD=m
132CONFIG_CDROM_PKTCDVD_BUFFERS=8
133# CONFIG_CDROM_PKTCDVD_WCACHE is not set
134
135#
136# IO Schedulers
137#
138CONFIG_IOSCHED_NOOP=y
139CONFIG_IOSCHED_AS=y
140CONFIG_IOSCHED_DEADLINE=y
141CONFIG_IOSCHED_CFQ=y
142
143#
144# ATA/ATAPI/MFM/RLL support
145#
146CONFIG_IDE=y
147CONFIG_BLK_DEV_IDE=y
148
149#
150# Please see Documentation/ide.txt for help/info on IDE drives
151#
152# CONFIG_BLK_DEV_IDE_SATA is not set
153CONFIG_BLK_DEV_IDEDISK=y
154# CONFIG_IDEDISK_MULTI_MODE is not set
155CONFIG_BLK_DEV_IDECD=y
156CONFIG_BLK_DEV_IDETAPE=m
157CONFIG_BLK_DEV_IDEFLOPPY=m
158# CONFIG_BLK_DEV_IDESCSI is not set
159# CONFIG_IDE_TASK_IOCTL is not set
160
161#
162# IDE chipset support/bugfixes
163#
164CONFIG_IDE_GENERIC=y
165# CONFIG_IDE_ARM is not set
166CONFIG_BLK_DEV_MAC_IDE=y
167# CONFIG_BLK_DEV_IDEDMA is not set
168# CONFIG_IDEDMA_AUTO is not set
169# CONFIG_BLK_DEV_HD is not set
170
171#
172# SCSI device support
173#
174CONFIG_SCSI=y
175CONFIG_SCSI_PROC_FS=y
176
177#
178# SCSI support type (disk, tape, CD-ROM)
179#
180CONFIG_BLK_DEV_SD=y
181CONFIG_CHR_DEV_ST=m
182CONFIG_CHR_DEV_OSST=m
183CONFIG_BLK_DEV_SR=y
184CONFIG_BLK_DEV_SR_VENDOR=y
185CONFIG_CHR_DEV_SG=m
186
187#
188# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
189#
190# CONFIG_SCSI_MULTI_LUN is not set
191CONFIG_SCSI_CONSTANTS=y
192# CONFIG_SCSI_LOGGING is not set
193
194#
195# SCSI Transport Attributes
196#
197# CONFIG_SCSI_SPI_ATTRS is not set
198# CONFIG_SCSI_FC_ATTRS is not set
199
200#
201# SCSI low-level drivers
202#
203# CONFIG_SCSI_SATA is not set
204# CONFIG_SCSI_DEBUG is not set
205CONFIG_MAC_SCSI=y
206CONFIG_SCSI_MAC_ESP=y
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
217CONFIG_MD_RAID5=m
218CONFIG_MD_RAID6=m
219CONFIG_MD_MULTIPATH=m
220# CONFIG_MD_FAULTY is not set
221CONFIG_BLK_DEV_DM=m
222CONFIG_DM_CRYPT=m
223CONFIG_DM_SNAPSHOT=m
224CONFIG_DM_MIRROR=m
225CONFIG_DM_ZERO=m
226
227#
228# Fusion MPT device support
229#
230
231#
232# IEEE 1394 (FireWire) support
233#
234
235#
236# I2O device support
237#
238
239#
240# Macintosh device drivers
241#
242CONFIG_ADB=y
243CONFIG_ADB_MACII=y
244CONFIG_ADB_MACIISI=y
245CONFIG_ADB_IOP=y
246CONFIG_ADB_PMU68K=y
247CONFIG_ADB_CUDA=y
248CONFIG_INPUT_ADBHID=y
249CONFIG_MAC_EMUMOUSEBTN=y
250
251#
252# Networking support
253#
254CONFIG_NET=y
255
256#
257# Networking options
258#
259CONFIG_PACKET=y
260# CONFIG_PACKET_MMAP is not set
261CONFIG_NETLINK_DEV=y
262CONFIG_UNIX=y
263CONFIG_NET_KEY=y
264CONFIG_INET=y
265# CONFIG_IP_MULTICAST is not set
266# CONFIG_IP_ADVANCED_ROUTER is not set
267# CONFIG_IP_PNP is not set
268CONFIG_NET_IPIP=m
269CONFIG_NET_IPGRE=m
270# CONFIG_ARPD is not set
271CONFIG_SYN_COOKIES=y
272CONFIG_INET_AH=m
273CONFIG_INET_ESP=m
274CONFIG_INET_IPCOMP=m
275CONFIG_INET_TUNNEL=m
276CONFIG_IP_TCPDIAG=m
277CONFIG_IP_TCPDIAG_IPV6=y
278
279#
280# IP: Virtual Server Configuration
281#
282# CONFIG_IP_VS is not set
283CONFIG_IPV6=m
284CONFIG_IPV6_PRIVACY=y
285CONFIG_INET6_AH=m
286CONFIG_INET6_ESP=m
287CONFIG_INET6_IPCOMP=m
288CONFIG_INET6_TUNNEL=m
289CONFIG_IPV6_TUNNEL=m
290CONFIG_NETFILTER=y
291# CONFIG_NETFILTER_DEBUG is not set
292
293#
294# IP: Netfilter Configuration
295#
296CONFIG_IP_NF_CONNTRACK=m
297# CONFIG_IP_NF_CT_ACCT is not set
298CONFIG_IP_NF_CONNTRACK_MARK=y
299# CONFIG_IP_NF_CT_PROTO_SCTP is not set
300CONFIG_IP_NF_FTP=m
301CONFIG_IP_NF_IRC=m
302CONFIG_IP_NF_TFTP=m
303CONFIG_IP_NF_AMANDA=m
304CONFIG_IP_NF_QUEUE=m
305CONFIG_IP_NF_IPTABLES=m
306CONFIG_IP_NF_MATCH_LIMIT=m
307CONFIG_IP_NF_MATCH_IPRANGE=m
308CONFIG_IP_NF_MATCH_MAC=m
309CONFIG_IP_NF_MATCH_PKTTYPE=m
310CONFIG_IP_NF_MATCH_MARK=m
311CONFIG_IP_NF_MATCH_MULTIPORT=m
312CONFIG_IP_NF_MATCH_TOS=m
313CONFIG_IP_NF_MATCH_RECENT=m
314CONFIG_IP_NF_MATCH_ECN=m
315CONFIG_IP_NF_MATCH_DSCP=m
316CONFIG_IP_NF_MATCH_AH_ESP=m
317CONFIG_IP_NF_MATCH_LENGTH=m
318CONFIG_IP_NF_MATCH_TTL=m
319CONFIG_IP_NF_MATCH_TCPMSS=m
320CONFIG_IP_NF_MATCH_HELPER=m
321CONFIG_IP_NF_MATCH_STATE=m
322CONFIG_IP_NF_MATCH_CONNTRACK=m
323CONFIG_IP_NF_MATCH_OWNER=m
324CONFIG_IP_NF_MATCH_ADDRTYPE=m
325CONFIG_IP_NF_MATCH_REALM=m
326# CONFIG_IP_NF_MATCH_SCTP is not set
327# CONFIG_IP_NF_MATCH_COMMENT is not set
328CONFIG_IP_NF_MATCH_CONNMARK=m
329CONFIG_IP_NF_MATCH_HASHLIMIT=m
330CONFIG_IP_NF_FILTER=m
331CONFIG_IP_NF_TARGET_REJECT=m
332CONFIG_IP_NF_TARGET_LOG=m
333CONFIG_IP_NF_TARGET_ULOG=m
334CONFIG_IP_NF_TARGET_TCPMSS=m
335CONFIG_IP_NF_NAT=m
336CONFIG_IP_NF_NAT_NEEDED=y
337CONFIG_IP_NF_TARGET_MASQUERADE=m
338CONFIG_IP_NF_TARGET_REDIRECT=m
339CONFIG_IP_NF_TARGET_NETMAP=m
340CONFIG_IP_NF_TARGET_SAME=m
341CONFIG_IP_NF_NAT_SNMP_BASIC=m
342CONFIG_IP_NF_NAT_IRC=m
343CONFIG_IP_NF_NAT_FTP=m
344CONFIG_IP_NF_NAT_TFTP=m
345CONFIG_IP_NF_NAT_AMANDA=m
346CONFIG_IP_NF_MANGLE=m
347CONFIG_IP_NF_TARGET_TOS=m
348CONFIG_IP_NF_TARGET_ECN=m
349CONFIG_IP_NF_TARGET_DSCP=m
350CONFIG_IP_NF_TARGET_MARK=m
351CONFIG_IP_NF_TARGET_CLASSIFY=m
352CONFIG_IP_NF_TARGET_CONNMARK=m
353# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
354CONFIG_IP_NF_RAW=m
355CONFIG_IP_NF_TARGET_NOTRACK=m
356CONFIG_IP_NF_ARPTABLES=m
357CONFIG_IP_NF_ARPFILTER=m
358CONFIG_IP_NF_ARP_MANGLE=m
359CONFIG_IP_NF_COMPAT_IPCHAINS=m
360CONFIG_IP_NF_COMPAT_IPFWADM=m
361
362#
363# IPv6: Netfilter Configuration
364#
365CONFIG_IP6_NF_QUEUE=m
366CONFIG_IP6_NF_IPTABLES=m
367CONFIG_IP6_NF_MATCH_LIMIT=m
368CONFIG_IP6_NF_MATCH_MAC=m
369CONFIG_IP6_NF_MATCH_RT=m
370CONFIG_IP6_NF_MATCH_OPTS=m
371CONFIG_IP6_NF_MATCH_FRAG=m
372CONFIG_IP6_NF_MATCH_HL=m
373CONFIG_IP6_NF_MATCH_MULTIPORT=m
374CONFIG_IP6_NF_MATCH_OWNER=m
375CONFIG_IP6_NF_MATCH_MARK=m
376CONFIG_IP6_NF_MATCH_IPV6HEADER=m
377CONFIG_IP6_NF_MATCH_AHESP=m
378CONFIG_IP6_NF_MATCH_LENGTH=m
379CONFIG_IP6_NF_MATCH_EUI64=m
380CONFIG_IP6_NF_FILTER=m
381CONFIG_IP6_NF_TARGET_LOG=m
382CONFIG_IP6_NF_MANGLE=m
383CONFIG_IP6_NF_TARGET_MARK=m
384CONFIG_IP6_NF_RAW=m
385CONFIG_XFRM=y
386CONFIG_XFRM_USER=m
387
388#
389# SCTP Configuration (EXPERIMENTAL)
390#
391CONFIG_IP_SCTP=m
392# CONFIG_SCTP_DBG_MSG is not set
393# CONFIG_SCTP_DBG_OBJCNT is not set
394# CONFIG_SCTP_HMAC_NONE is not set
395# CONFIG_SCTP_HMAC_SHA1 is not set
396CONFIG_SCTP_HMAC_MD5=y
397# CONFIG_ATM is not set
398# CONFIG_BRIDGE is not set
399# CONFIG_VLAN_8021Q is not set
400# CONFIG_DECNET is not set
401CONFIG_LLC=m
402# CONFIG_LLC2 is not set
403CONFIG_IPX=m
404# CONFIG_IPX_INTERN is not set
405CONFIG_ATALK=m
406CONFIG_DEV_APPLETALK=y
407CONFIG_IPDDP=m
408CONFIG_IPDDP_ENCAP=y
409CONFIG_IPDDP_DECAP=y
410# CONFIG_X25 is not set
411# CONFIG_LAPB is not set
412# CONFIG_NET_DIVERT is not set
413# CONFIG_ECONET is not set
414# CONFIG_WAN_ROUTER is not set
415
416#
417# QoS and/or fair queueing
418#
419# CONFIG_NET_SCHED is not set
420CONFIG_NET_CLS_ROUTE=y
421
422#
423# Network testing
424#
425# CONFIG_NET_PKTGEN is not set
426CONFIG_NETPOLL=y
427# CONFIG_NETPOLL_RX is not set
428# CONFIG_NETPOLL_TRAP is not set
429CONFIG_NET_POLL_CONTROLLER=y
430# CONFIG_HAMRADIO is not set
431# CONFIG_IRDA is not set
432# CONFIG_BT is not set
433CONFIG_NETDEVICES=y
434CONFIG_DUMMY=m
435# CONFIG_BONDING is not set
436CONFIG_EQUALIZER=m
437# CONFIG_TUN is not set
438# CONFIG_ETHERTAP is not set
439
440#
441# Ethernet (10 or 100Mbit)
442#
443CONFIG_NET_ETHERNET=y
444# CONFIG_MII is not set
445CONFIG_MAC8390=y
446CONFIG_MAC89x0=y
447CONFIG_MACSONIC=y
448CONFIG_MACMACE=y
449# CONFIG_NET_VENDOR_SMC is not set
450
451#
452# Ethernet (1000 Mbit)
453#
454
455#
456# Ethernet (10000 Mbit)
457#
458
459#
460# Token Ring devices
461#
462
463#
464# Wireless LAN (non-hamradio)
465#
466# CONFIG_NET_RADIO is not set
467
468#
469# Wan interfaces
470#
471# CONFIG_WAN is not set
472CONFIG_PPP=m
473# CONFIG_PPP_MULTILINK is not set
474CONFIG_PPP_FILTER=y
475# CONFIG_PPP_ASYNC is not set
476# CONFIG_PPP_SYNC_TTY is not set
477CONFIG_PPP_DEFLATE=m
478CONFIG_PPP_BSDCOMP=m
479CONFIG_PPPOE=m
480CONFIG_SLIP=m
481CONFIG_SLIP_COMPRESSED=y
482CONFIG_SLIP_SMART=y
483CONFIG_SLIP_MODE_SLIP6=y
484CONFIG_SHAPER=m
485CONFIG_NETCONSOLE=m
486
487#
488# ISDN subsystem
489#
490# CONFIG_ISDN is not set
491
492#
493# Telephony Support
494#
495# CONFIG_PHONE is not set
496
497#
498# Input device support
499#
500CONFIG_INPUT=y
501
502#
503# Userland interfaces
504#
505CONFIG_INPUT_MOUSEDEV=y
506CONFIG_INPUT_MOUSEDEV_PSAUX=y
507CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
508CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
509# CONFIG_INPUT_JOYDEV is not set
510# CONFIG_INPUT_TSDEV is not set
511# CONFIG_INPUT_EVDEV is not set
512# CONFIG_INPUT_EVBUG is not set
513
514#
515# Input I/O drivers
516#
517# CONFIG_GAMEPORT is not set
518CONFIG_SOUND_GAMEPORT=y
519CONFIG_SERIO=m
520CONFIG_SERIO_SERPORT=m
521# CONFIG_SERIO_CT82C710 is not set
522# CONFIG_SERIO_RAW is not set
523
524#
525# Input Device Drivers
526#
527CONFIG_INPUT_KEYBOARD=y
528# CONFIG_KEYBOARD_ATKBD is not set
529# CONFIG_KEYBOARD_SUNKBD is not set
530# CONFIG_KEYBOARD_LKKBD is not set
531# CONFIG_KEYBOARD_XTKBD is not set
532# CONFIG_KEYBOARD_NEWTON is not set
533CONFIG_INPUT_MOUSE=y
534CONFIG_MOUSE_PS2=m
535CONFIG_MOUSE_SERIAL=m
536# CONFIG_MOUSE_VSXXXAA is not set
537# CONFIG_INPUT_JOYSTICK is not set
538# CONFIG_INPUT_TOUCHSCREEN is not set
539# CONFIG_INPUT_MISC is not set
540
541#
542# Character devices
543#
544CONFIG_VT=y
545CONFIG_VT_CONSOLE=y
546CONFIG_HW_CONSOLE=y
547# CONFIG_SERIAL_NONSTANDARD is not set
548
549#
550# Serial drivers
551#
552# CONFIG_SERIAL_8250 is not set
553
554#
555# Non-8250 serial port support
556#
557CONFIG_UNIX98_PTYS=y
558CONFIG_LEGACY_PTYS=y
559CONFIG_LEGACY_PTY_COUNT=256
560
561#
562# IPMI
563#
564# CONFIG_IPMI_HANDLER is not set
565
566#
567# Watchdog Cards
568#
569# CONFIG_WATCHDOG is not set
570CONFIG_GEN_RTC=m
571CONFIG_GEN_RTC_X=y
572# CONFIG_DTLK is not set
573# CONFIG_R3964 is not set
574
575#
576# Ftape, the floppy tape device driver
577#
578# CONFIG_DRM is not set
579# CONFIG_RAW_DRIVER is not set
580
581#
582# I2C support
583#
584# CONFIG_I2C is not set
585
586#
587# Dallas's 1-wire bus
588#
589# CONFIG_W1 is not set
590
591#
592# Misc devices
593#
594
595#
596# Multimedia devices
597#
598# CONFIG_VIDEO_DEV is not set
599
600#
601# Digital Video Broadcasting Devices
602#
603# CONFIG_DVB is not set
604
605#
606# Graphics support
607#
608CONFIG_FB=y
609CONFIG_FB_MODE_HELPERS=y
610# CONFIG_FB_TILEBLITTING is not set
611CONFIG_FB_VALKYRIE=y
612CONFIG_FB_MAC=y
613# CONFIG_FB_VIRTUAL is not set
614
615#
616# Console display driver support
617#
618CONFIG_DUMMY_CONSOLE=y
619CONFIG_FRAMEBUFFER_CONSOLE=y
620# CONFIG_FONTS is not set
621CONFIG_FONT_8x8=y
622CONFIG_FONT_8x16=y
623CONFIG_FONT_6x11=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_MAC_CLUT224=y
633
634#
635# Sound
636#
637# CONFIG_SOUND is not set
638
639#
640# USB support
641#
642# CONFIG_USB_ARCH_HAS_HCD is not set
643# CONFIG_USB_ARCH_HAS_OHCI is not set
644
645#
646# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
647#
648
649#
650# USB Gadget Support
651#
652# CONFIG_USB_GADGET is not set
653
654#
655# MMC/SD Card support
656#
657# CONFIG_MMC is not set
658
659#
660# Character devices
661#
662CONFIG_MAC_SCC=y
663CONFIG_MAC_HID=y
664CONFIG_MAC_ADBKEYCODES=y
665CONFIG_SERIAL_CONSOLE=y
666
667#
668# File systems
669#
670CONFIG_EXT2_FS=y
671# CONFIG_EXT2_FS_XATTR is not set
672CONFIG_EXT3_FS=y
673# CONFIG_EXT3_FS_XATTR is not set
674CONFIG_JBD=y
675# CONFIG_JBD_DEBUG is not set
676CONFIG_REISERFS_FS=m
677# CONFIG_REISERFS_CHECK is not set
678# CONFIG_REISERFS_PROC_INFO is not set
679# CONFIG_REISERFS_FS_XATTR is not set
680CONFIG_JFS_FS=m
681# CONFIG_JFS_POSIX_ACL is not set
682# CONFIG_JFS_DEBUG is not set
683# CONFIG_JFS_STATISTICS is not set
684CONFIG_FS_POSIX_ACL=y
685CONFIG_XFS_FS=m
686# CONFIG_XFS_RT is not set
687# CONFIG_XFS_QUOTA is not set
688# CONFIG_XFS_SECURITY is not set
689# CONFIG_XFS_POSIX_ACL is not set
690CONFIG_MINIX_FS=y
691# CONFIG_ROMFS_FS is not set
692CONFIG_QUOTA=y
693# CONFIG_QFMT_V1 is not set
694# CONFIG_QFMT_V2 is not set
695CONFIG_QUOTACTL=y
696CONFIG_DNOTIFY=y
697CONFIG_AUTOFS_FS=m
698CONFIG_AUTOFS4_FS=m
699
700#
701# CD-ROM/DVD Filesystems
702#
703CONFIG_ISO9660_FS=y
704CONFIG_JOLIET=y
705CONFIG_ZISOFS=y
706CONFIG_ZISOFS_FS=y
707CONFIG_UDF_FS=m
708CONFIG_UDF_NLS=y
709
710#
711# DOS/FAT/NT Filesystems
712#
713CONFIG_FAT_FS=y
714CONFIG_MSDOS_FS=y
715CONFIG_VFAT_FS=m
716CONFIG_FAT_DEFAULT_CODEPAGE=437
717CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
718# CONFIG_NTFS_FS is not set
719
720#
721# Pseudo filesystems
722#
723CONFIG_PROC_FS=y
724CONFIG_PROC_KCORE=y
725CONFIG_SYSFS=y
726# CONFIG_DEVFS_FS is not set
727# CONFIG_DEVPTS_FS_XATTR is not set
728CONFIG_TMPFS=y
729# CONFIG_TMPFS_XATTR is not set
730# CONFIG_HUGETLB_PAGE is not set
731CONFIG_RAMFS=y
732
733#
734# Miscellaneous filesystems
735#
736# CONFIG_ADFS_FS is not set
737CONFIG_AFFS_FS=m
738CONFIG_HFS_FS=y
739CONFIG_HFSPLUS_FS=y
740# CONFIG_BEFS_FS is not set
741# CONFIG_BFS_FS is not set
742# CONFIG_EFS_FS is not set
743CONFIG_CRAMFS=m
744# CONFIG_VXFS_FS is not set
745CONFIG_HPFS_FS=m
746# CONFIG_QNX4FS_FS is not set
747CONFIG_SYSV_FS=m
748CONFIG_UFS_FS=m
749# CONFIG_UFS_FS_WRITE is not set
750
751#
752# Network File Systems
753#
754CONFIG_NFS_FS=m
755CONFIG_NFS_V3=y
756CONFIG_NFS_V4=y
757# CONFIG_NFS_DIRECTIO is not set
758CONFIG_NFSD=m
759CONFIG_NFSD_V3=y
760CONFIG_NFSD_V4=y
761CONFIG_NFSD_TCP=y
762CONFIG_LOCKD=m
763CONFIG_LOCKD_V4=y
764CONFIG_EXPORTFS=m
765CONFIG_SUNRPC=m
766CONFIG_SUNRPC_GSS=m
767CONFIG_RPCSEC_GSS_KRB5=m
768# CONFIG_RPCSEC_GSS_SPKM3 is not set
769CONFIG_SMB_FS=m
770CONFIG_SMB_NLS_DEFAULT=y
771CONFIG_SMB_NLS_REMOTE="cp437"
772# CONFIG_CIFS is not set
773CONFIG_NCP_FS=m
774# CONFIG_NCPFS_PACKET_SIGNING is not set
775# CONFIG_NCPFS_IOCTL_LOCKING is not set
776# CONFIG_NCPFS_STRONG is not set
777CONFIG_NCPFS_NFS_NS=y
778CONFIG_NCPFS_OS2_NS=y
779# CONFIG_NCPFS_SMALLDOS is not set
780CONFIG_NCPFS_NLS=y
781# CONFIG_NCPFS_EXTRAS is not set
782CONFIG_CODA_FS=m
783# CONFIG_CODA_FS_OLD_API is not set
784# CONFIG_AFS_FS is not set
785
786#
787# Partition Types
788#
789CONFIG_PARTITION_ADVANCED=y
790# CONFIG_ACORN_PARTITION is not set
791# CONFIG_OSF_PARTITION is not set
792CONFIG_AMIGA_PARTITION=y
793CONFIG_ATARI_PARTITION=y
794CONFIG_MAC_PARTITION=y
795CONFIG_MSDOS_PARTITION=y
796CONFIG_BSD_DISKLABEL=y
797CONFIG_MINIX_SUBPARTITION=y
798CONFIG_SOLARIS_X86_PARTITION=y
799CONFIG_UNIXWARE_DISKLABEL=y
800CONFIG_LDM_PARTITION=y
801CONFIG_LDM_DEBUG=y
802# CONFIG_SGI_PARTITION is not set
803# CONFIG_ULTRIX_PARTITION is not set
804CONFIG_SUN_PARTITION=y
805# CONFIG_EFI_PARTITION is not set
806
807#
808# Native Language Support
809#
810CONFIG_NLS=y
811CONFIG_NLS_DEFAULT="iso8859-1"
812CONFIG_NLS_CODEPAGE_437=y
813CONFIG_NLS_CODEPAGE_737=m
814CONFIG_NLS_CODEPAGE_775=m
815CONFIG_NLS_CODEPAGE_850=m
816CONFIG_NLS_CODEPAGE_852=m
817CONFIG_NLS_CODEPAGE_855=m
818CONFIG_NLS_CODEPAGE_857=m
819CONFIG_NLS_CODEPAGE_860=m
820CONFIG_NLS_CODEPAGE_861=m
821CONFIG_NLS_CODEPAGE_862=m
822CONFIG_NLS_CODEPAGE_863=m
823CONFIG_NLS_CODEPAGE_864=m
824CONFIG_NLS_CODEPAGE_865=m
825CONFIG_NLS_CODEPAGE_866=m
826CONFIG_NLS_CODEPAGE_869=m
827CONFIG_NLS_CODEPAGE_936=m
828CONFIG_NLS_CODEPAGE_950=m
829CONFIG_NLS_CODEPAGE_932=m
830CONFIG_NLS_CODEPAGE_949=m
831CONFIG_NLS_CODEPAGE_874=m
832CONFIG_NLS_ISO8859_8=m
833CONFIG_NLS_CODEPAGE_1250=m
834CONFIG_NLS_CODEPAGE_1251=m
835CONFIG_NLS_ASCII=m
836CONFIG_NLS_ISO8859_1=y
837CONFIG_NLS_ISO8859_2=m
838CONFIG_NLS_ISO8859_3=m
839CONFIG_NLS_ISO8859_4=m
840CONFIG_NLS_ISO8859_5=m
841CONFIG_NLS_ISO8859_6=m
842CONFIG_NLS_ISO8859_7=m
843CONFIG_NLS_ISO8859_9=m
844CONFIG_NLS_ISO8859_13=m
845CONFIG_NLS_ISO8859_14=m
846CONFIG_NLS_ISO8859_15=m
847CONFIG_NLS_KOI8_R=m
848CONFIG_NLS_KOI8_U=m
849CONFIG_NLS_UTF8=m
850
851#
852# Kernel hacking
853#
854CONFIG_DEBUG_KERNEL=y
855CONFIG_MAGIC_SYSRQ=y
856# CONFIG_SCHEDSTATS is not set
857# CONFIG_DEBUG_SLAB is not set
858# CONFIG_DEBUG_KOBJECT is not set
859# CONFIG_DEBUG_BUGVERBOSE is not set
860# CONFIG_DEBUG_INFO is not set
861
862#
863# Security options
864#
865# CONFIG_KEYS is not set
866# CONFIG_SECURITY is not set
867
868#
869# Cryptographic options
870#
871CONFIG_CRYPTO=y
872CONFIG_CRYPTO_HMAC=y
873CONFIG_CRYPTO_NULL=m
874CONFIG_CRYPTO_MD4=m
875CONFIG_CRYPTO_MD5=y
876CONFIG_CRYPTO_SHA1=m
877CONFIG_CRYPTO_SHA256=m
878CONFIG_CRYPTO_SHA512=m
879# CONFIG_CRYPTO_WP512 is not set
880CONFIG_CRYPTO_DES=m
881CONFIG_CRYPTO_BLOWFISH=m
882CONFIG_CRYPTO_TWOFISH=m
883CONFIG_CRYPTO_SERPENT=m
884CONFIG_CRYPTO_AES=m
885CONFIG_CRYPTO_CAST5=m
886CONFIG_CRYPTO_CAST6=m
887CONFIG_CRYPTO_TEA=m
888CONFIG_CRYPTO_ARC4=m
889CONFIG_CRYPTO_KHAZAD=m
890CONFIG_CRYPTO_ANUBIS=m
891CONFIG_CRYPTO_DEFLATE=m
892CONFIG_CRYPTO_MICHAEL_MIC=m
893CONFIG_CRYPTO_CRC32C=m
894CONFIG_CRYPTO_TEST=m
895
896#
897# Library routines
898#
899CONFIG_CRC_CCITT=m
900CONFIG_CRC32=y
901CONFIG_LIBCRC32C=m
902CONFIG_ZLIB_INFLATE=y
903CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
new file mode 100644
index 000000000000..ea38e87a6051
--- /dev/null
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -0,0 +1,843 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:23:49 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-mvme147"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63# CONFIG_ATARI is not set
64# CONFIG_MAC is not set
65# CONFIG_APOLLO is not set
66CONFIG_VME=y
67CONFIG_MVME147=y
68# CONFIG_MVME16x is not set
69# CONFIG_BVME6000 is not set
70# CONFIG_HP300 is not set
71# CONFIG_SUN3X is not set
72# CONFIG_Q40 is not set
73
74#
75# Processor type
76#
77# CONFIG_M68020 is not set
78CONFIG_M68030=y
79# CONFIG_M68040 is not set
80# CONFIG_M68060 is not set
81CONFIG_MMU_MOTOROLA=y
82# CONFIG_M68KFPU_EMU is not set
83# CONFIG_ADVANCED is not set
84
85#
86# General setup
87#
88CONFIG_BINFMT_ELF=y
89CONFIG_BINFMT_AOUT=m
90CONFIG_BINFMT_MISC=m
91CONFIG_PROC_HARDWARE=y
92
93#
94# Device Drivers
95#
96
97#
98# Generic Driver Options
99#
100CONFIG_STANDALONE=y
101CONFIG_PREVENT_FIRMWARE_BUILD=y
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#
112# CONFIG_PARPORT is not set
113
114#
115# Plug and Play support
116#
117
118#
119# Block devices
120#
121CONFIG_BLK_DEV_LOOP=y
122CONFIG_BLK_DEV_CRYPTOLOOP=m
123CONFIG_BLK_DEV_NBD=m
124CONFIG_BLK_DEV_RAM=y
125CONFIG_BLK_DEV_RAM_COUNT=16
126CONFIG_BLK_DEV_RAM_SIZE=4096
127CONFIG_BLK_DEV_INITRD=y
128CONFIG_INITRAMFS_SOURCE=""
129CONFIG_CDROM_PKTCDVD=m
130CONFIG_CDROM_PKTCDVD_BUFFERS=8
131# CONFIG_CDROM_PKTCDVD_WCACHE is not set
132
133#
134# IO Schedulers
135#
136CONFIG_IOSCHED_NOOP=y
137CONFIG_IOSCHED_AS=y
138CONFIG_IOSCHED_DEADLINE=y
139CONFIG_IOSCHED_CFQ=y
140
141#
142# ATA/ATAPI/MFM/RLL support
143#
144# CONFIG_IDE is not set
145
146#
147# SCSI device support
148#
149CONFIG_SCSI=y
150CONFIG_SCSI_PROC_FS=y
151
152#
153# SCSI support type (disk, tape, CD-ROM)
154#
155CONFIG_BLK_DEV_SD=y
156CONFIG_CHR_DEV_ST=m
157# CONFIG_CHR_DEV_OSST is not set
158CONFIG_BLK_DEV_SR=y
159CONFIG_BLK_DEV_SR_VENDOR=y
160CONFIG_CHR_DEV_SG=m
161
162#
163# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
164#
165# CONFIG_SCSI_MULTI_LUN is not set
166CONFIG_SCSI_CONSTANTS=y
167# CONFIG_SCSI_LOGGING is not set
168
169#
170# SCSI Transport Attributes
171#
172# CONFIG_SCSI_SPI_ATTRS is not set
173# CONFIG_SCSI_FC_ATTRS is not set
174
175#
176# SCSI low-level drivers
177#
178# CONFIG_SCSI_SATA is not set
179# CONFIG_SCSI_DEBUG is not set
180CONFIG_MVME147_SCSI=y
181
182#
183# Multi-device support (RAID and LVM)
184#
185CONFIG_MD=y
186CONFIG_BLK_DEV_MD=m
187CONFIG_MD_LINEAR=m
188CONFIG_MD_RAID0=m
189CONFIG_MD_RAID1=m
190# CONFIG_MD_RAID10 is not set
191CONFIG_MD_RAID5=m
192CONFIG_MD_RAID6=m
193CONFIG_MD_MULTIPATH=m
194# CONFIG_MD_FAULTY is not set
195CONFIG_BLK_DEV_DM=m
196CONFIG_DM_CRYPT=m
197CONFIG_DM_SNAPSHOT=m
198CONFIG_DM_MIRROR=m
199CONFIG_DM_ZERO=m
200
201#
202# Fusion MPT device support
203#
204
205#
206# IEEE 1394 (FireWire) support
207#
208
209#
210# I2O device support
211#
212
213#
214# Networking support
215#
216CONFIG_NET=y
217
218#
219# Networking options
220#
221CONFIG_PACKET=y
222# CONFIG_PACKET_MMAP is not set
223CONFIG_NETLINK_DEV=y
224CONFIG_UNIX=y
225CONFIG_NET_KEY=y
226CONFIG_INET=y
227# CONFIG_IP_MULTICAST is not set
228# CONFIG_IP_ADVANCED_ROUTER is not set
229CONFIG_IP_PNP=y
230CONFIG_IP_PNP_DHCP=y
231CONFIG_IP_PNP_BOOTP=y
232CONFIG_IP_PNP_RARP=y
233CONFIG_NET_IPIP=m
234CONFIG_NET_IPGRE=m
235# CONFIG_ARPD is not set
236CONFIG_SYN_COOKIES=y
237CONFIG_INET_AH=m
238CONFIG_INET_ESP=m
239CONFIG_INET_IPCOMP=m
240CONFIG_INET_TUNNEL=m
241CONFIG_IP_TCPDIAG=m
242CONFIG_IP_TCPDIAG_IPV6=y
243
244#
245# IP: Virtual Server Configuration
246#
247# CONFIG_IP_VS is not set
248CONFIG_IPV6=m
249CONFIG_IPV6_PRIVACY=y
250CONFIG_INET6_AH=m
251CONFIG_INET6_ESP=m
252CONFIG_INET6_IPCOMP=m
253CONFIG_INET6_TUNNEL=m
254CONFIG_IPV6_TUNNEL=m
255CONFIG_NETFILTER=y
256# CONFIG_NETFILTER_DEBUG is not set
257
258#
259# IP: Netfilter Configuration
260#
261CONFIG_IP_NF_CONNTRACK=m
262# CONFIG_IP_NF_CT_ACCT is not set
263CONFIG_IP_NF_CONNTRACK_MARK=y
264# CONFIG_IP_NF_CT_PROTO_SCTP is not set
265CONFIG_IP_NF_FTP=m
266CONFIG_IP_NF_IRC=m
267CONFIG_IP_NF_TFTP=m
268CONFIG_IP_NF_AMANDA=m
269CONFIG_IP_NF_QUEUE=m
270CONFIG_IP_NF_IPTABLES=m
271CONFIG_IP_NF_MATCH_LIMIT=m
272CONFIG_IP_NF_MATCH_IPRANGE=m
273CONFIG_IP_NF_MATCH_MAC=m
274CONFIG_IP_NF_MATCH_PKTTYPE=m
275CONFIG_IP_NF_MATCH_MARK=m
276CONFIG_IP_NF_MATCH_MULTIPORT=m
277CONFIG_IP_NF_MATCH_TOS=m
278CONFIG_IP_NF_MATCH_RECENT=m
279CONFIG_IP_NF_MATCH_ECN=m
280CONFIG_IP_NF_MATCH_DSCP=m
281CONFIG_IP_NF_MATCH_AH_ESP=m
282CONFIG_IP_NF_MATCH_LENGTH=m
283CONFIG_IP_NF_MATCH_TTL=m
284CONFIG_IP_NF_MATCH_TCPMSS=m
285CONFIG_IP_NF_MATCH_HELPER=m
286CONFIG_IP_NF_MATCH_STATE=m
287CONFIG_IP_NF_MATCH_CONNTRACK=m
288CONFIG_IP_NF_MATCH_OWNER=m
289CONFIG_IP_NF_MATCH_ADDRTYPE=m
290CONFIG_IP_NF_MATCH_REALM=m
291# CONFIG_IP_NF_MATCH_SCTP is not set
292# CONFIG_IP_NF_MATCH_COMMENT is not set
293CONFIG_IP_NF_MATCH_CONNMARK=m
294CONFIG_IP_NF_MATCH_HASHLIMIT=m
295CONFIG_IP_NF_FILTER=m
296CONFIG_IP_NF_TARGET_REJECT=m
297CONFIG_IP_NF_TARGET_LOG=m
298CONFIG_IP_NF_TARGET_ULOG=m
299CONFIG_IP_NF_TARGET_TCPMSS=m
300CONFIG_IP_NF_NAT=m
301CONFIG_IP_NF_NAT_NEEDED=y
302CONFIG_IP_NF_TARGET_MASQUERADE=m
303CONFIG_IP_NF_TARGET_REDIRECT=m
304CONFIG_IP_NF_TARGET_NETMAP=m
305CONFIG_IP_NF_TARGET_SAME=m
306CONFIG_IP_NF_NAT_SNMP_BASIC=m
307CONFIG_IP_NF_NAT_IRC=m
308CONFIG_IP_NF_NAT_FTP=m
309CONFIG_IP_NF_NAT_TFTP=m
310CONFIG_IP_NF_NAT_AMANDA=m
311CONFIG_IP_NF_MANGLE=m
312CONFIG_IP_NF_TARGET_TOS=m
313CONFIG_IP_NF_TARGET_ECN=m
314CONFIG_IP_NF_TARGET_DSCP=m
315CONFIG_IP_NF_TARGET_MARK=m
316CONFIG_IP_NF_TARGET_CLASSIFY=m
317CONFIG_IP_NF_TARGET_CONNMARK=m
318# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
319CONFIG_IP_NF_RAW=m
320CONFIG_IP_NF_TARGET_NOTRACK=m
321CONFIG_IP_NF_ARPTABLES=m
322CONFIG_IP_NF_ARPFILTER=m
323CONFIG_IP_NF_ARP_MANGLE=m
324CONFIG_IP_NF_COMPAT_IPCHAINS=m
325CONFIG_IP_NF_COMPAT_IPFWADM=m
326
327#
328# IPv6: Netfilter Configuration
329#
330CONFIG_IP6_NF_QUEUE=m
331CONFIG_IP6_NF_IPTABLES=m
332CONFIG_IP6_NF_MATCH_LIMIT=m
333CONFIG_IP6_NF_MATCH_MAC=m
334CONFIG_IP6_NF_MATCH_RT=m
335CONFIG_IP6_NF_MATCH_OPTS=m
336CONFIG_IP6_NF_MATCH_FRAG=m
337CONFIG_IP6_NF_MATCH_HL=m
338CONFIG_IP6_NF_MATCH_MULTIPORT=m
339CONFIG_IP6_NF_MATCH_OWNER=m
340CONFIG_IP6_NF_MATCH_MARK=m
341CONFIG_IP6_NF_MATCH_IPV6HEADER=m
342CONFIG_IP6_NF_MATCH_AHESP=m
343CONFIG_IP6_NF_MATCH_LENGTH=m
344CONFIG_IP6_NF_MATCH_EUI64=m
345CONFIG_IP6_NF_FILTER=m
346CONFIG_IP6_NF_TARGET_LOG=m
347CONFIG_IP6_NF_MANGLE=m
348CONFIG_IP6_NF_TARGET_MARK=m
349CONFIG_IP6_NF_RAW=m
350CONFIG_XFRM=y
351CONFIG_XFRM_USER=m
352
353#
354# SCTP Configuration (EXPERIMENTAL)
355#
356CONFIG_IP_SCTP=m
357# CONFIG_SCTP_DBG_MSG is not set
358# CONFIG_SCTP_DBG_OBJCNT is not set
359# CONFIG_SCTP_HMAC_NONE is not set
360# CONFIG_SCTP_HMAC_SHA1 is not set
361CONFIG_SCTP_HMAC_MD5=y
362# CONFIG_ATM is not set
363# CONFIG_BRIDGE is not set
364# CONFIG_VLAN_8021Q is not set
365# CONFIG_DECNET is not set
366CONFIG_LLC=m
367# CONFIG_LLC2 is not set
368CONFIG_IPX=m
369# CONFIG_IPX_INTERN is not set
370CONFIG_ATALK=m
371# CONFIG_DEV_APPLETALK is not set
372# CONFIG_X25 is not set
373# CONFIG_LAPB is not set
374# CONFIG_NET_DIVERT is not set
375# CONFIG_ECONET is not set
376# CONFIG_WAN_ROUTER is not set
377
378#
379# QoS and/or fair queueing
380#
381# CONFIG_NET_SCHED is not set
382CONFIG_NET_CLS_ROUTE=y
383
384#
385# Network testing
386#
387# CONFIG_NET_PKTGEN is not set
388CONFIG_NETPOLL=y
389# CONFIG_NETPOLL_RX is not set
390# CONFIG_NETPOLL_TRAP is not set
391CONFIG_NET_POLL_CONTROLLER=y
392# CONFIG_HAMRADIO is not set
393# CONFIG_IRDA is not set
394# CONFIG_BT is not set
395CONFIG_NETDEVICES=y
396CONFIG_DUMMY=m
397# CONFIG_BONDING is not set
398CONFIG_EQUALIZER=m
399# CONFIG_TUN is not set
400# CONFIG_ETHERTAP is not set
401
402#
403# Ethernet (10 or 100Mbit)
404#
405CONFIG_NET_ETHERNET=y
406CONFIG_MII=m
407CONFIG_MVME147_NET=y
408
409#
410# Ethernet (1000 Mbit)
411#
412
413#
414# Ethernet (10000 Mbit)
415#
416
417#
418# Token Ring devices
419#
420
421#
422# Wireless LAN (non-hamradio)
423#
424# CONFIG_NET_RADIO is not set
425
426#
427# Wan interfaces
428#
429# CONFIG_WAN is not set
430CONFIG_PPP=m
431# CONFIG_PPP_MULTILINK is not set
432CONFIG_PPP_FILTER=y
433CONFIG_PPP_ASYNC=m
434CONFIG_PPP_SYNC_TTY=m
435CONFIG_PPP_DEFLATE=m
436CONFIG_PPP_BSDCOMP=m
437CONFIG_PPPOE=m
438CONFIG_SLIP=m
439CONFIG_SLIP_COMPRESSED=y
440CONFIG_SLIP_SMART=y
441CONFIG_SLIP_MODE_SLIP6=y
442CONFIG_SHAPER=m
443CONFIG_NETCONSOLE=m
444
445#
446# ISDN subsystem
447#
448# CONFIG_ISDN is not set
449
450#
451# Telephony Support
452#
453# CONFIG_PHONE is not set
454
455#
456# Input device support
457#
458CONFIG_INPUT=y
459
460#
461# Userland interfaces
462#
463CONFIG_INPUT_MOUSEDEV=y
464CONFIG_INPUT_MOUSEDEV_PSAUX=y
465CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
466CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
467# CONFIG_INPUT_JOYDEV is not set
468# CONFIG_INPUT_TSDEV is not set
469# CONFIG_INPUT_EVDEV is not set
470# CONFIG_INPUT_EVBUG is not set
471
472#
473# Input I/O drivers
474#
475# CONFIG_GAMEPORT is not set
476CONFIG_SOUND_GAMEPORT=y
477CONFIG_SERIO=m
478CONFIG_SERIO_SERPORT=m
479# CONFIG_SERIO_CT82C710 is not set
480# CONFIG_SERIO_RAW is not set
481
482#
483# Input Device Drivers
484#
485CONFIG_INPUT_KEYBOARD=y
486# CONFIG_KEYBOARD_ATKBD is not set
487# CONFIG_KEYBOARD_SUNKBD is not set
488# CONFIG_KEYBOARD_LKKBD is not set
489# CONFIG_KEYBOARD_XTKBD is not set
490# CONFIG_KEYBOARD_NEWTON is not set
491CONFIG_INPUT_MOUSE=y
492CONFIG_MOUSE_PS2=m
493CONFIG_MOUSE_SERIAL=m
494# CONFIG_MOUSE_VSXXXAA is not set
495# CONFIG_INPUT_JOYSTICK is not set
496# CONFIG_INPUT_TOUCHSCREEN is not set
497# CONFIG_INPUT_MISC is not set
498
499#
500# Character devices
501#
502CONFIG_VT=y
503CONFIG_VT_CONSOLE=y
504CONFIG_HW_CONSOLE=y
505# CONFIG_SERIAL_NONSTANDARD is not set
506
507#
508# Serial drivers
509#
510# CONFIG_SERIAL_8250 is not set
511
512#
513# Non-8250 serial port support
514#
515CONFIG_UNIX98_PTYS=y
516CONFIG_LEGACY_PTYS=y
517CONFIG_LEGACY_PTY_COUNT=256
518
519#
520# IPMI
521#
522# CONFIG_IPMI_HANDLER is not set
523
524#
525# Watchdog Cards
526#
527# CONFIG_WATCHDOG is not set
528CONFIG_GEN_RTC=m
529CONFIG_GEN_RTC_X=y
530# CONFIG_DTLK is not set
531# CONFIG_R3964 is not set
532
533#
534# Ftape, the floppy tape device driver
535#
536# CONFIG_DRM is not set
537# CONFIG_RAW_DRIVER is not set
538
539#
540# I2C support
541#
542# CONFIG_I2C is not set
543
544#
545# Dallas's 1-wire bus
546#
547# CONFIG_W1 is not set
548
549#
550# Misc devices
551#
552
553#
554# Multimedia devices
555#
556# CONFIG_VIDEO_DEV is not set
557
558#
559# Digital Video Broadcasting Devices
560#
561# CONFIG_DVB is not set
562
563#
564# Graphics support
565#
566CONFIG_FB=y
567CONFIG_FB_MODE_HELPERS=y
568# CONFIG_FB_TILEBLITTING is not set
569# CONFIG_FB_VIRTUAL is not set
570
571#
572# Console display driver support
573#
574CONFIG_DUMMY_CONSOLE=y
575CONFIG_FRAMEBUFFER_CONSOLE=y
576# CONFIG_FONTS is not set
577CONFIG_FONT_8x8=y
578CONFIG_FONT_8x16=y
579
580#
581# Logo configuration
582#
583CONFIG_LOGO=y
584CONFIG_LOGO_LINUX_MONO=y
585CONFIG_LOGO_LINUX_VGA16=y
586CONFIG_LOGO_LINUX_CLUT224=y
587
588#
589# Sound
590#
591# CONFIG_SOUND is not set
592
593#
594# USB support
595#
596# CONFIG_USB_ARCH_HAS_HCD is not set
597# CONFIG_USB_ARCH_HAS_OHCI is not set
598
599#
600# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
601#
602
603#
604# USB Gadget Support
605#
606# CONFIG_USB_GADGET is not set
607
608#
609# MMC/SD Card support
610#
611# CONFIG_MMC is not set
612
613#
614# Character devices
615#
616CONFIG_MVME147_SCC=y
617CONFIG_SERIAL_CONSOLE=y
618
619#
620# File systems
621#
622CONFIG_EXT2_FS=y
623# CONFIG_EXT2_FS_XATTR is not set
624CONFIG_EXT3_FS=y
625# CONFIG_EXT3_FS_XATTR is not set
626CONFIG_JBD=y
627# CONFIG_JBD_DEBUG is not set
628CONFIG_REISERFS_FS=m
629# CONFIG_REISERFS_CHECK is not set
630# CONFIG_REISERFS_PROC_INFO is not set
631# CONFIG_REISERFS_FS_XATTR is not set
632CONFIG_JFS_FS=m
633# CONFIG_JFS_POSIX_ACL is not set
634# CONFIG_JFS_DEBUG is not set
635# CONFIG_JFS_STATISTICS is not set
636CONFIG_FS_POSIX_ACL=y
637CONFIG_XFS_FS=m
638# CONFIG_XFS_RT is not set
639# CONFIG_XFS_QUOTA is not set
640# CONFIG_XFS_SECURITY is not set
641# CONFIG_XFS_POSIX_ACL is not set
642CONFIG_MINIX_FS=y
643# CONFIG_ROMFS_FS is not set
644CONFIG_QUOTA=y
645# CONFIG_QFMT_V1 is not set
646# CONFIG_QFMT_V2 is not set
647CONFIG_QUOTACTL=y
648CONFIG_DNOTIFY=y
649CONFIG_AUTOFS_FS=m
650CONFIG_AUTOFS4_FS=m
651
652#
653# CD-ROM/DVD Filesystems
654#
655CONFIG_ISO9660_FS=y
656CONFIG_JOLIET=y
657CONFIG_ZISOFS=y
658CONFIG_ZISOFS_FS=y
659CONFIG_UDF_FS=m
660CONFIG_UDF_NLS=y
661
662#
663# DOS/FAT/NT Filesystems
664#
665CONFIG_FAT_FS=y
666CONFIG_MSDOS_FS=y
667CONFIG_VFAT_FS=m
668CONFIG_FAT_DEFAULT_CODEPAGE=437
669CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
670# CONFIG_NTFS_FS is not set
671
672#
673# Pseudo filesystems
674#
675CONFIG_PROC_FS=y
676CONFIG_PROC_KCORE=y
677CONFIG_SYSFS=y
678CONFIG_DEVFS_FS=y
679# CONFIG_DEVFS_MOUNT is not set
680# CONFIG_DEVFS_DEBUG is not set
681# CONFIG_DEVPTS_FS_XATTR is not set
682CONFIG_TMPFS=y
683# CONFIG_TMPFS_XATTR is not set
684# CONFIG_HUGETLB_PAGE is not set
685CONFIG_RAMFS=y
686
687#
688# Miscellaneous filesystems
689#
690# CONFIG_ADFS_FS is not set
691CONFIG_AFFS_FS=m
692CONFIG_HFS_FS=m
693CONFIG_HFSPLUS_FS=m
694# CONFIG_BEFS_FS is not set
695# CONFIG_BFS_FS is not set
696# CONFIG_EFS_FS is not set
697CONFIG_CRAMFS=m
698# CONFIG_VXFS_FS is not set
699CONFIG_HPFS_FS=m
700# CONFIG_QNX4FS_FS is not set
701CONFIG_SYSV_FS=m
702CONFIG_UFS_FS=m
703# CONFIG_UFS_FS_WRITE is not set
704
705#
706# Network File Systems
707#
708CONFIG_NFS_FS=y
709CONFIG_NFS_V3=y
710CONFIG_NFS_V4=y
711# CONFIG_NFS_DIRECTIO is not set
712CONFIG_NFSD=m
713CONFIG_NFSD_V3=y
714CONFIG_NFSD_V4=y
715CONFIG_NFSD_TCP=y
716CONFIG_ROOT_NFS=y
717CONFIG_LOCKD=y
718CONFIG_LOCKD_V4=y
719CONFIG_EXPORTFS=m
720CONFIG_SUNRPC=y
721CONFIG_SUNRPC_GSS=y
722CONFIG_RPCSEC_GSS_KRB5=y
723# CONFIG_RPCSEC_GSS_SPKM3 is not set
724CONFIG_SMB_FS=m
725CONFIG_SMB_NLS_DEFAULT=y
726CONFIG_SMB_NLS_REMOTE="cp437"
727# CONFIG_CIFS is not set
728CONFIG_NCP_FS=m
729# CONFIG_NCPFS_PACKET_SIGNING is not set
730# CONFIG_NCPFS_IOCTL_LOCKING is not set
731# CONFIG_NCPFS_STRONG is not set
732# CONFIG_NCPFS_NFS_NS is not set
733# CONFIG_NCPFS_OS2_NS is not set
734# CONFIG_NCPFS_SMALLDOS is not set
735CONFIG_NCPFS_NLS=y
736# CONFIG_NCPFS_EXTRAS is not set
737CONFIG_CODA_FS=m
738# CONFIG_CODA_FS_OLD_API is not set
739# CONFIG_AFS_FS is not set
740
741#
742# Partition Types
743#
744# CONFIG_PARTITION_ADVANCED is not set
745CONFIG_MSDOS_PARTITION=y
746
747#
748# Native Language Support
749#
750CONFIG_NLS=y
751CONFIG_NLS_DEFAULT="iso8859-1"
752CONFIG_NLS_CODEPAGE_437=y
753CONFIG_NLS_CODEPAGE_737=m
754CONFIG_NLS_CODEPAGE_775=m
755CONFIG_NLS_CODEPAGE_850=m
756CONFIG_NLS_CODEPAGE_852=m
757CONFIG_NLS_CODEPAGE_855=m
758CONFIG_NLS_CODEPAGE_857=m
759CONFIG_NLS_CODEPAGE_860=m
760CONFIG_NLS_CODEPAGE_861=m
761CONFIG_NLS_CODEPAGE_862=m
762CONFIG_NLS_CODEPAGE_863=m
763CONFIG_NLS_CODEPAGE_864=m
764CONFIG_NLS_CODEPAGE_865=m
765CONFIG_NLS_CODEPAGE_866=m
766CONFIG_NLS_CODEPAGE_869=m
767CONFIG_NLS_CODEPAGE_936=m
768CONFIG_NLS_CODEPAGE_950=m
769CONFIG_NLS_CODEPAGE_932=m
770CONFIG_NLS_CODEPAGE_949=m
771CONFIG_NLS_CODEPAGE_874=m
772CONFIG_NLS_ISO8859_8=m
773CONFIG_NLS_CODEPAGE_1250=m
774CONFIG_NLS_CODEPAGE_1251=m
775CONFIG_NLS_ASCII=m
776CONFIG_NLS_ISO8859_1=y
777CONFIG_NLS_ISO8859_2=m
778CONFIG_NLS_ISO8859_3=m
779CONFIG_NLS_ISO8859_4=m
780CONFIG_NLS_ISO8859_5=m
781CONFIG_NLS_ISO8859_6=m
782CONFIG_NLS_ISO8859_7=m
783CONFIG_NLS_ISO8859_9=m
784CONFIG_NLS_ISO8859_13=m
785CONFIG_NLS_ISO8859_14=m
786CONFIG_NLS_ISO8859_15=m
787CONFIG_NLS_KOI8_R=m
788CONFIG_NLS_KOI8_U=m
789CONFIG_NLS_UTF8=m
790
791#
792# Kernel hacking
793#
794CONFIG_DEBUG_KERNEL=y
795CONFIG_MAGIC_SYSRQ=y
796# CONFIG_SCHEDSTATS is not set
797# CONFIG_DEBUG_SLAB is not set
798# CONFIG_DEBUG_KOBJECT is not set
799# CONFIG_DEBUG_BUGVERBOSE is not set
800# CONFIG_DEBUG_INFO is not set
801
802#
803# Security options
804#
805# CONFIG_KEYS is not set
806# CONFIG_SECURITY is not set
807
808#
809# Cryptographic options
810#
811CONFIG_CRYPTO=y
812CONFIG_CRYPTO_HMAC=y
813CONFIG_CRYPTO_NULL=m
814CONFIG_CRYPTO_MD4=m
815CONFIG_CRYPTO_MD5=y
816CONFIG_CRYPTO_SHA1=m
817CONFIG_CRYPTO_SHA256=m
818CONFIG_CRYPTO_SHA512=m
819# CONFIG_CRYPTO_WP512 is not set
820CONFIG_CRYPTO_DES=y
821CONFIG_CRYPTO_BLOWFISH=m
822CONFIG_CRYPTO_TWOFISH=m
823CONFIG_CRYPTO_SERPENT=m
824CONFIG_CRYPTO_AES=m
825CONFIG_CRYPTO_CAST5=m
826CONFIG_CRYPTO_CAST6=m
827CONFIG_CRYPTO_TEA=m
828CONFIG_CRYPTO_ARC4=m
829CONFIG_CRYPTO_KHAZAD=m
830CONFIG_CRYPTO_ANUBIS=m
831CONFIG_CRYPTO_DEFLATE=m
832CONFIG_CRYPTO_MICHAEL_MIC=m
833CONFIG_CRYPTO_CRC32C=m
834CONFIG_CRYPTO_TEST=m
835
836#
837# Library routines
838#
839CONFIG_CRC_CCITT=m
840CONFIG_CRC32=y
841CONFIG_LIBCRC32C=m
842CONFIG_ZLIB_INFLATE=y
843CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
new file mode 100644
index 000000000000..f931a64939d6
--- /dev/null
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -0,0 +1,842 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:23:53 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-mvme16x"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63# CONFIG_ATARI is not set
64# CONFIG_MAC is not set
65# CONFIG_APOLLO is not set
66CONFIG_VME=y
67# CONFIG_MVME147 is not set
68CONFIG_MVME16x=y
69# CONFIG_BVME6000 is not set
70# CONFIG_HP300 is not set
71# CONFIG_SUN3X is not set
72# CONFIG_Q40 is not set
73
74#
75# Processor type
76#
77# CONFIG_M68020 is not set
78# CONFIG_M68030 is not set
79CONFIG_M68040=y
80CONFIG_M68060=y
81CONFIG_MMU_MOTOROLA=y
82# CONFIG_M68KFPU_EMU is not set
83# CONFIG_ADVANCED is not set
84
85#
86# General setup
87#
88CONFIG_BINFMT_ELF=y
89CONFIG_BINFMT_AOUT=m
90CONFIG_BINFMT_MISC=m
91CONFIG_PROC_HARDWARE=y
92
93#
94# Device Drivers
95#
96
97#
98# Generic Driver Options
99#
100CONFIG_STANDALONE=y
101CONFIG_PREVENT_FIRMWARE_BUILD=y
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#
112# CONFIG_PARPORT is not set
113
114#
115# Plug and Play support
116#
117
118#
119# Block devices
120#
121CONFIG_BLK_DEV_LOOP=y
122CONFIG_BLK_DEV_CRYPTOLOOP=m
123CONFIG_BLK_DEV_NBD=m
124CONFIG_BLK_DEV_RAM=y
125CONFIG_BLK_DEV_RAM_COUNT=16
126CONFIG_BLK_DEV_RAM_SIZE=4096
127CONFIG_BLK_DEV_INITRD=y
128CONFIG_INITRAMFS_SOURCE=""
129CONFIG_CDROM_PKTCDVD=m
130CONFIG_CDROM_PKTCDVD_BUFFERS=8
131# CONFIG_CDROM_PKTCDVD_WCACHE is not set
132
133#
134# IO Schedulers
135#
136CONFIG_IOSCHED_NOOP=y
137CONFIG_IOSCHED_AS=y
138CONFIG_IOSCHED_DEADLINE=y
139CONFIG_IOSCHED_CFQ=y
140
141#
142# ATA/ATAPI/MFM/RLL support
143#
144# CONFIG_IDE is not set
145
146#
147# SCSI device support
148#
149CONFIG_SCSI=y
150CONFIG_SCSI_PROC_FS=y
151
152#
153# SCSI support type (disk, tape, CD-ROM)
154#
155CONFIG_BLK_DEV_SD=y
156CONFIG_CHR_DEV_ST=m
157# CONFIG_CHR_DEV_OSST is not set
158CONFIG_BLK_DEV_SR=y
159CONFIG_BLK_DEV_SR_VENDOR=y
160CONFIG_CHR_DEV_SG=m
161
162#
163# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
164#
165# CONFIG_SCSI_MULTI_LUN is not set
166CONFIG_SCSI_CONSTANTS=y
167# CONFIG_SCSI_LOGGING is not set
168
169#
170# SCSI Transport Attributes
171#
172# CONFIG_SCSI_SPI_ATTRS is not set
173# CONFIG_SCSI_FC_ATTRS is not set
174
175#
176# SCSI low-level drivers
177#
178# CONFIG_SCSI_SATA is not set
179# CONFIG_SCSI_DEBUG is not set
180
181#
182# Multi-device support (RAID and LVM)
183#
184CONFIG_MD=y
185CONFIG_BLK_DEV_MD=m
186CONFIG_MD_LINEAR=m
187CONFIG_MD_RAID0=m
188CONFIG_MD_RAID1=m
189# CONFIG_MD_RAID10 is not set
190CONFIG_MD_RAID5=m
191CONFIG_MD_RAID6=m
192CONFIG_MD_MULTIPATH=m
193# CONFIG_MD_FAULTY is not set
194CONFIG_BLK_DEV_DM=m
195CONFIG_DM_CRYPT=m
196CONFIG_DM_SNAPSHOT=m
197CONFIG_DM_MIRROR=m
198CONFIG_DM_ZERO=m
199
200#
201# Fusion MPT device support
202#
203
204#
205# IEEE 1394 (FireWire) support
206#
207
208#
209# I2O device support
210#
211
212#
213# Networking support
214#
215CONFIG_NET=y
216
217#
218# Networking options
219#
220CONFIG_PACKET=y
221# CONFIG_PACKET_MMAP is not set
222CONFIG_NETLINK_DEV=y
223CONFIG_UNIX=y
224CONFIG_NET_KEY=y
225CONFIG_INET=y
226# CONFIG_IP_MULTICAST is not set
227# CONFIG_IP_ADVANCED_ROUTER is not set
228CONFIG_IP_PNP=y
229CONFIG_IP_PNP_DHCP=y
230CONFIG_IP_PNP_BOOTP=y
231CONFIG_IP_PNP_RARP=y
232CONFIG_NET_IPIP=m
233CONFIG_NET_IPGRE=m
234# CONFIG_ARPD is not set
235CONFIG_SYN_COOKIES=y
236CONFIG_INET_AH=m
237CONFIG_INET_ESP=m
238CONFIG_INET_IPCOMP=m
239CONFIG_INET_TUNNEL=m
240CONFIG_IP_TCPDIAG=m
241CONFIG_IP_TCPDIAG_IPV6=y
242
243#
244# IP: Virtual Server Configuration
245#
246# CONFIG_IP_VS is not set
247CONFIG_IPV6=m
248CONFIG_IPV6_PRIVACY=y
249CONFIG_INET6_AH=m
250CONFIG_INET6_ESP=m
251CONFIG_INET6_IPCOMP=m
252CONFIG_INET6_TUNNEL=m
253CONFIG_IPV6_TUNNEL=m
254CONFIG_NETFILTER=y
255# CONFIG_NETFILTER_DEBUG is not set
256
257#
258# IP: Netfilter Configuration
259#
260CONFIG_IP_NF_CONNTRACK=m
261# CONFIG_IP_NF_CT_ACCT is not set
262CONFIG_IP_NF_CONNTRACK_MARK=y
263# CONFIG_IP_NF_CT_PROTO_SCTP is not set
264CONFIG_IP_NF_FTP=m
265CONFIG_IP_NF_IRC=m
266CONFIG_IP_NF_TFTP=m
267CONFIG_IP_NF_AMANDA=m
268CONFIG_IP_NF_QUEUE=m
269CONFIG_IP_NF_IPTABLES=m
270CONFIG_IP_NF_MATCH_LIMIT=m
271CONFIG_IP_NF_MATCH_IPRANGE=m
272CONFIG_IP_NF_MATCH_MAC=m
273CONFIG_IP_NF_MATCH_PKTTYPE=m
274CONFIG_IP_NF_MATCH_MARK=m
275CONFIG_IP_NF_MATCH_MULTIPORT=m
276CONFIG_IP_NF_MATCH_TOS=m
277CONFIG_IP_NF_MATCH_RECENT=m
278CONFIG_IP_NF_MATCH_ECN=m
279CONFIG_IP_NF_MATCH_DSCP=m
280CONFIG_IP_NF_MATCH_AH_ESP=m
281CONFIG_IP_NF_MATCH_LENGTH=m
282CONFIG_IP_NF_MATCH_TTL=m
283CONFIG_IP_NF_MATCH_TCPMSS=m
284CONFIG_IP_NF_MATCH_HELPER=m
285CONFIG_IP_NF_MATCH_STATE=m
286CONFIG_IP_NF_MATCH_CONNTRACK=m
287CONFIG_IP_NF_MATCH_OWNER=m
288CONFIG_IP_NF_MATCH_ADDRTYPE=m
289CONFIG_IP_NF_MATCH_REALM=m
290# CONFIG_IP_NF_MATCH_SCTP is not set
291# CONFIG_IP_NF_MATCH_COMMENT is not set
292CONFIG_IP_NF_MATCH_CONNMARK=m
293CONFIG_IP_NF_MATCH_HASHLIMIT=m
294CONFIG_IP_NF_FILTER=m
295CONFIG_IP_NF_TARGET_REJECT=m
296CONFIG_IP_NF_TARGET_LOG=m
297CONFIG_IP_NF_TARGET_ULOG=m
298CONFIG_IP_NF_TARGET_TCPMSS=m
299CONFIG_IP_NF_NAT=m
300CONFIG_IP_NF_NAT_NEEDED=y
301CONFIG_IP_NF_TARGET_MASQUERADE=m
302CONFIG_IP_NF_TARGET_REDIRECT=m
303CONFIG_IP_NF_TARGET_NETMAP=m
304CONFIG_IP_NF_TARGET_SAME=m
305CONFIG_IP_NF_NAT_SNMP_BASIC=m
306CONFIG_IP_NF_NAT_IRC=m
307CONFIG_IP_NF_NAT_FTP=m
308CONFIG_IP_NF_NAT_TFTP=m
309CONFIG_IP_NF_NAT_AMANDA=m
310CONFIG_IP_NF_MANGLE=m
311CONFIG_IP_NF_TARGET_TOS=m
312CONFIG_IP_NF_TARGET_ECN=m
313CONFIG_IP_NF_TARGET_DSCP=m
314CONFIG_IP_NF_TARGET_MARK=m
315CONFIG_IP_NF_TARGET_CLASSIFY=m
316CONFIG_IP_NF_TARGET_CONNMARK=m
317# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
318CONFIG_IP_NF_RAW=m
319CONFIG_IP_NF_TARGET_NOTRACK=m
320CONFIG_IP_NF_ARPTABLES=m
321CONFIG_IP_NF_ARPFILTER=m
322CONFIG_IP_NF_ARP_MANGLE=m
323CONFIG_IP_NF_COMPAT_IPCHAINS=m
324CONFIG_IP_NF_COMPAT_IPFWADM=m
325
326#
327# IPv6: Netfilter Configuration
328#
329CONFIG_IP6_NF_QUEUE=m
330CONFIG_IP6_NF_IPTABLES=m
331CONFIG_IP6_NF_MATCH_LIMIT=m
332CONFIG_IP6_NF_MATCH_MAC=m
333CONFIG_IP6_NF_MATCH_RT=m
334CONFIG_IP6_NF_MATCH_OPTS=m
335CONFIG_IP6_NF_MATCH_FRAG=m
336CONFIG_IP6_NF_MATCH_HL=m
337CONFIG_IP6_NF_MATCH_MULTIPORT=m
338CONFIG_IP6_NF_MATCH_OWNER=m
339CONFIG_IP6_NF_MATCH_MARK=m
340CONFIG_IP6_NF_MATCH_IPV6HEADER=m
341CONFIG_IP6_NF_MATCH_AHESP=m
342CONFIG_IP6_NF_MATCH_LENGTH=m
343CONFIG_IP6_NF_MATCH_EUI64=m
344CONFIG_IP6_NF_FILTER=m
345CONFIG_IP6_NF_TARGET_LOG=m
346CONFIG_IP6_NF_MANGLE=m
347CONFIG_IP6_NF_TARGET_MARK=m
348CONFIG_IP6_NF_RAW=m
349CONFIG_XFRM=y
350CONFIG_XFRM_USER=m
351
352#
353# SCTP Configuration (EXPERIMENTAL)
354#
355CONFIG_IP_SCTP=m
356# CONFIG_SCTP_DBG_MSG is not set
357# CONFIG_SCTP_DBG_OBJCNT is not set
358# CONFIG_SCTP_HMAC_NONE is not set
359# CONFIG_SCTP_HMAC_SHA1 is not set
360CONFIG_SCTP_HMAC_MD5=y
361# CONFIG_ATM is not set
362# CONFIG_BRIDGE is not set
363# CONFIG_VLAN_8021Q is not set
364# CONFIG_DECNET is not set
365CONFIG_LLC=m
366# CONFIG_LLC2 is not set
367CONFIG_IPX=m
368# CONFIG_IPX_INTERN is not set
369CONFIG_ATALK=m
370# CONFIG_DEV_APPLETALK is not set
371# CONFIG_X25 is not set
372# CONFIG_LAPB is not set
373# CONFIG_NET_DIVERT is not set
374# CONFIG_ECONET is not set
375# CONFIG_WAN_ROUTER is not set
376
377#
378# QoS and/or fair queueing
379#
380# CONFIG_NET_SCHED is not set
381CONFIG_NET_CLS_ROUTE=y
382
383#
384# Network testing
385#
386# CONFIG_NET_PKTGEN is not set
387CONFIG_NETPOLL=y
388# CONFIG_NETPOLL_RX is not set
389# CONFIG_NETPOLL_TRAP is not set
390CONFIG_NET_POLL_CONTROLLER=y
391# CONFIG_HAMRADIO is not set
392# CONFIG_IRDA is not set
393# CONFIG_BT is not set
394CONFIG_NETDEVICES=y
395CONFIG_DUMMY=m
396# CONFIG_BONDING is not set
397CONFIG_EQUALIZER=m
398# CONFIG_TUN is not set
399# CONFIG_ETHERTAP is not set
400
401#
402# Ethernet (10 or 100Mbit)
403#
404CONFIG_NET_ETHERNET=y
405CONFIG_MII=m
406CONFIG_MVME16x_NET=y
407
408#
409# Ethernet (1000 Mbit)
410#
411
412#
413# Ethernet (10000 Mbit)
414#
415
416#
417# Token Ring devices
418#
419
420#
421# Wireless LAN (non-hamradio)
422#
423# CONFIG_NET_RADIO is not set
424
425#
426# Wan interfaces
427#
428# CONFIG_WAN is not set
429CONFIG_PPP=m
430# CONFIG_PPP_MULTILINK is not set
431CONFIG_PPP_FILTER=y
432CONFIG_PPP_ASYNC=m
433CONFIG_PPP_SYNC_TTY=m
434CONFIG_PPP_DEFLATE=m
435CONFIG_PPP_BSDCOMP=m
436CONFIG_PPPOE=m
437CONFIG_SLIP=m
438CONFIG_SLIP_COMPRESSED=y
439CONFIG_SLIP_SMART=y
440CONFIG_SLIP_MODE_SLIP6=y
441CONFIG_SHAPER=m
442CONFIG_NETCONSOLE=m
443
444#
445# ISDN subsystem
446#
447# CONFIG_ISDN is not set
448
449#
450# Telephony Support
451#
452# CONFIG_PHONE is not set
453
454#
455# Input device support
456#
457CONFIG_INPUT=y
458
459#
460# Userland interfaces
461#
462CONFIG_INPUT_MOUSEDEV=y
463CONFIG_INPUT_MOUSEDEV_PSAUX=y
464CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
465CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
466# CONFIG_INPUT_JOYDEV is not set
467# CONFIG_INPUT_TSDEV is not set
468# CONFIG_INPUT_EVDEV is not set
469# CONFIG_INPUT_EVBUG is not set
470
471#
472# Input I/O drivers
473#
474# CONFIG_GAMEPORT is not set
475CONFIG_SOUND_GAMEPORT=y
476CONFIG_SERIO=m
477CONFIG_SERIO_SERPORT=m
478# CONFIG_SERIO_CT82C710 is not set
479# CONFIG_SERIO_RAW is not set
480
481#
482# Input Device Drivers
483#
484CONFIG_INPUT_KEYBOARD=y
485# CONFIG_KEYBOARD_ATKBD is not set
486# CONFIG_KEYBOARD_SUNKBD is not set
487# CONFIG_KEYBOARD_LKKBD is not set
488# CONFIG_KEYBOARD_XTKBD is not set
489# CONFIG_KEYBOARD_NEWTON is not set
490CONFIG_INPUT_MOUSE=y
491CONFIG_MOUSE_PS2=m
492CONFIG_MOUSE_SERIAL=m
493# CONFIG_MOUSE_VSXXXAA is not set
494# CONFIG_INPUT_JOYSTICK is not set
495# CONFIG_INPUT_TOUCHSCREEN is not set
496# CONFIG_INPUT_MISC is not set
497
498#
499# Character devices
500#
501CONFIG_VT=y
502CONFIG_VT_CONSOLE=y
503CONFIG_HW_CONSOLE=y
504# CONFIG_SERIAL_NONSTANDARD is not set
505
506#
507# Serial drivers
508#
509# CONFIG_SERIAL_8250 is not set
510
511#
512# Non-8250 serial port support
513#
514CONFIG_UNIX98_PTYS=y
515CONFIG_LEGACY_PTYS=y
516CONFIG_LEGACY_PTY_COUNT=256
517
518#
519# IPMI
520#
521# CONFIG_IPMI_HANDLER is not set
522
523#
524# Watchdog Cards
525#
526# CONFIG_WATCHDOG is not set
527CONFIG_GEN_RTC=m
528CONFIG_GEN_RTC_X=y
529# CONFIG_DTLK is not set
530# CONFIG_R3964 is not set
531
532#
533# Ftape, the floppy tape device driver
534#
535# CONFIG_DRM is not set
536# CONFIG_RAW_DRIVER is not set
537
538#
539# I2C support
540#
541# CONFIG_I2C is not set
542
543#
544# Dallas's 1-wire bus
545#
546# CONFIG_W1 is not set
547
548#
549# Misc devices
550#
551
552#
553# Multimedia devices
554#
555# CONFIG_VIDEO_DEV is not set
556
557#
558# Digital Video Broadcasting Devices
559#
560# CONFIG_DVB is not set
561
562#
563# Graphics support
564#
565CONFIG_FB=y
566CONFIG_FB_MODE_HELPERS=y
567# CONFIG_FB_TILEBLITTING is not set
568# CONFIG_FB_VIRTUAL is not set
569
570#
571# Console display driver support
572#
573CONFIG_DUMMY_CONSOLE=y
574CONFIG_FRAMEBUFFER_CONSOLE=y
575# CONFIG_FONTS is not set
576CONFIG_FONT_8x8=y
577CONFIG_FONT_8x16=y
578
579#
580# Logo configuration
581#
582CONFIG_LOGO=y
583CONFIG_LOGO_LINUX_MONO=y
584CONFIG_LOGO_LINUX_VGA16=y
585CONFIG_LOGO_LINUX_CLUT224=y
586
587#
588# Sound
589#
590# CONFIG_SOUND is not set
591
592#
593# USB support
594#
595# CONFIG_USB_ARCH_HAS_HCD is not set
596# CONFIG_USB_ARCH_HAS_OHCI is not set
597
598#
599# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
600#
601
602#
603# USB Gadget Support
604#
605# CONFIG_USB_GADGET is not set
606
607#
608# MMC/SD Card support
609#
610# CONFIG_MMC is not set
611
612#
613# Character devices
614#
615CONFIG_MVME162_SCC=y
616CONFIG_SERIAL_CONSOLE=y
617
618#
619# File systems
620#
621CONFIG_EXT2_FS=y
622# CONFIG_EXT2_FS_XATTR is not set
623CONFIG_EXT3_FS=y
624# CONFIG_EXT3_FS_XATTR is not set
625CONFIG_JBD=y
626# CONFIG_JBD_DEBUG is not set
627CONFIG_REISERFS_FS=m
628# CONFIG_REISERFS_CHECK is not set
629# CONFIG_REISERFS_PROC_INFO is not set
630# CONFIG_REISERFS_FS_XATTR is not set
631CONFIG_JFS_FS=m
632# CONFIG_JFS_POSIX_ACL is not set
633# CONFIG_JFS_DEBUG is not set
634# CONFIG_JFS_STATISTICS is not set
635CONFIG_FS_POSIX_ACL=y
636CONFIG_XFS_FS=m
637# CONFIG_XFS_RT is not set
638# CONFIG_XFS_QUOTA is not set
639# CONFIG_XFS_SECURITY is not set
640# CONFIG_XFS_POSIX_ACL is not set
641CONFIG_MINIX_FS=y
642# CONFIG_ROMFS_FS is not set
643CONFIG_QUOTA=y
644# CONFIG_QFMT_V1 is not set
645# CONFIG_QFMT_V2 is not set
646CONFIG_QUOTACTL=y
647CONFIG_DNOTIFY=y
648CONFIG_AUTOFS_FS=m
649CONFIG_AUTOFS4_FS=m
650
651#
652# CD-ROM/DVD Filesystems
653#
654CONFIG_ISO9660_FS=y
655CONFIG_JOLIET=y
656CONFIG_ZISOFS=y
657CONFIG_ZISOFS_FS=y
658CONFIG_UDF_FS=m
659CONFIG_UDF_NLS=y
660
661#
662# DOS/FAT/NT Filesystems
663#
664CONFIG_FAT_FS=y
665CONFIG_MSDOS_FS=y
666CONFIG_VFAT_FS=m
667CONFIG_FAT_DEFAULT_CODEPAGE=437
668CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
669# CONFIG_NTFS_FS is not set
670
671#
672# Pseudo filesystems
673#
674CONFIG_PROC_FS=y
675CONFIG_PROC_KCORE=y
676CONFIG_SYSFS=y
677CONFIG_DEVFS_FS=y
678# CONFIG_DEVFS_MOUNT is not set
679# CONFIG_DEVFS_DEBUG is not set
680# CONFIG_DEVPTS_FS_XATTR is not set
681CONFIG_TMPFS=y
682# CONFIG_TMPFS_XATTR is not set
683# CONFIG_HUGETLB_PAGE is not set
684CONFIG_RAMFS=y
685
686#
687# Miscellaneous filesystems
688#
689# CONFIG_ADFS_FS is not set
690CONFIG_AFFS_FS=m
691CONFIG_HFS_FS=m
692CONFIG_HFSPLUS_FS=m
693# CONFIG_BEFS_FS is not set
694# CONFIG_BFS_FS is not set
695# CONFIG_EFS_FS is not set
696CONFIG_CRAMFS=m
697# CONFIG_VXFS_FS is not set
698CONFIG_HPFS_FS=m
699# CONFIG_QNX4FS_FS is not set
700CONFIG_SYSV_FS=m
701CONFIG_UFS_FS=m
702# CONFIG_UFS_FS_WRITE is not set
703
704#
705# Network File Systems
706#
707CONFIG_NFS_FS=y
708CONFIG_NFS_V3=y
709CONFIG_NFS_V4=y
710# CONFIG_NFS_DIRECTIO is not set
711CONFIG_NFSD=m
712CONFIG_NFSD_V3=y
713CONFIG_NFSD_V4=y
714CONFIG_NFSD_TCP=y
715CONFIG_ROOT_NFS=y
716CONFIG_LOCKD=y
717CONFIG_LOCKD_V4=y
718CONFIG_EXPORTFS=m
719CONFIG_SUNRPC=y
720CONFIG_SUNRPC_GSS=y
721CONFIG_RPCSEC_GSS_KRB5=y
722# CONFIG_RPCSEC_GSS_SPKM3 is not set
723CONFIG_SMB_FS=m
724CONFIG_SMB_NLS_DEFAULT=y
725CONFIG_SMB_NLS_REMOTE="cp437"
726# CONFIG_CIFS is not set
727CONFIG_NCP_FS=m
728# CONFIG_NCPFS_PACKET_SIGNING is not set
729# CONFIG_NCPFS_IOCTL_LOCKING is not set
730# CONFIG_NCPFS_STRONG is not set
731# CONFIG_NCPFS_NFS_NS is not set
732# CONFIG_NCPFS_OS2_NS is not set
733# CONFIG_NCPFS_SMALLDOS is not set
734CONFIG_NCPFS_NLS=y
735# CONFIG_NCPFS_EXTRAS is not set
736CONFIG_CODA_FS=m
737# CONFIG_CODA_FS_OLD_API is not set
738# CONFIG_AFS_FS is not set
739
740#
741# Partition Types
742#
743# CONFIG_PARTITION_ADVANCED is not set
744CONFIG_MSDOS_PARTITION=y
745
746#
747# Native Language Support
748#
749CONFIG_NLS=y
750CONFIG_NLS_DEFAULT="iso8859-1"
751CONFIG_NLS_CODEPAGE_437=y
752CONFIG_NLS_CODEPAGE_737=m
753CONFIG_NLS_CODEPAGE_775=m
754CONFIG_NLS_CODEPAGE_850=m
755CONFIG_NLS_CODEPAGE_852=m
756CONFIG_NLS_CODEPAGE_855=m
757CONFIG_NLS_CODEPAGE_857=m
758CONFIG_NLS_CODEPAGE_860=m
759CONFIG_NLS_CODEPAGE_861=m
760CONFIG_NLS_CODEPAGE_862=m
761CONFIG_NLS_CODEPAGE_863=m
762CONFIG_NLS_CODEPAGE_864=m
763CONFIG_NLS_CODEPAGE_865=m
764CONFIG_NLS_CODEPAGE_866=m
765CONFIG_NLS_CODEPAGE_869=m
766CONFIG_NLS_CODEPAGE_936=m
767CONFIG_NLS_CODEPAGE_950=m
768CONFIG_NLS_CODEPAGE_932=m
769CONFIG_NLS_CODEPAGE_949=m
770CONFIG_NLS_CODEPAGE_874=m
771CONFIG_NLS_ISO8859_8=m
772CONFIG_NLS_CODEPAGE_1250=m
773CONFIG_NLS_CODEPAGE_1251=m
774CONFIG_NLS_ASCII=m
775CONFIG_NLS_ISO8859_1=y
776CONFIG_NLS_ISO8859_2=m
777CONFIG_NLS_ISO8859_3=m
778CONFIG_NLS_ISO8859_4=m
779CONFIG_NLS_ISO8859_5=m
780CONFIG_NLS_ISO8859_6=m
781CONFIG_NLS_ISO8859_7=m
782CONFIG_NLS_ISO8859_9=m
783CONFIG_NLS_ISO8859_13=m
784CONFIG_NLS_ISO8859_14=m
785CONFIG_NLS_ISO8859_15=m
786CONFIG_NLS_KOI8_R=m
787CONFIG_NLS_KOI8_U=m
788CONFIG_NLS_UTF8=m
789
790#
791# Kernel hacking
792#
793CONFIG_DEBUG_KERNEL=y
794CONFIG_MAGIC_SYSRQ=y
795# CONFIG_SCHEDSTATS is not set
796# CONFIG_DEBUG_SLAB is not set
797# CONFIG_DEBUG_KOBJECT is not set
798# CONFIG_DEBUG_BUGVERBOSE is not set
799# CONFIG_DEBUG_INFO is not set
800
801#
802# Security options
803#
804# CONFIG_KEYS is not set
805# CONFIG_SECURITY is not set
806
807#
808# Cryptographic options
809#
810CONFIG_CRYPTO=y
811CONFIG_CRYPTO_HMAC=y
812CONFIG_CRYPTO_NULL=m
813CONFIG_CRYPTO_MD4=m
814CONFIG_CRYPTO_MD5=y
815CONFIG_CRYPTO_SHA1=m
816CONFIG_CRYPTO_SHA256=m
817CONFIG_CRYPTO_SHA512=m
818# CONFIG_CRYPTO_WP512 is not set
819CONFIG_CRYPTO_DES=y
820CONFIG_CRYPTO_BLOWFISH=m
821CONFIG_CRYPTO_TWOFISH=m
822CONFIG_CRYPTO_SERPENT=m
823CONFIG_CRYPTO_AES=m
824CONFIG_CRYPTO_CAST5=m
825CONFIG_CRYPTO_CAST6=m
826CONFIG_CRYPTO_TEA=m
827CONFIG_CRYPTO_ARC4=m
828CONFIG_CRYPTO_KHAZAD=m
829CONFIG_CRYPTO_ANUBIS=m
830CONFIG_CRYPTO_DEFLATE=m
831CONFIG_CRYPTO_MICHAEL_MIC=m
832CONFIG_CRYPTO_CRC32C=m
833CONFIG_CRYPTO_TEST=m
834
835#
836# Library routines
837#
838CONFIG_CRC_CCITT=m
839CONFIG_CRC32=y
840CONFIG_LIBCRC32C=m
841CONFIG_ZLIB_INFLATE=y
842CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
new file mode 100644
index 000000000000..713020cd6f2e
--- /dev/null
+++ b/arch/m68k/configs/q40_defconfig
@@ -0,0 +1,915 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:23:57 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-q40"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63# CONFIG_ATARI is not set
64# CONFIG_MAC is not set
65# CONFIG_APOLLO is not set
66# CONFIG_VME is not set
67# CONFIG_HP300 is not set
68# CONFIG_SUN3X is not set
69CONFIG_Q40=y
70
71#
72# Processor type
73#
74# CONFIG_M68020 is not set
75# CONFIG_M68030 is not set
76CONFIG_M68040=y
77CONFIG_M68060=y
78CONFIG_MMU_MOTOROLA=y
79CONFIG_M68KFPU_EMU=y
80CONFIG_M68KFPU_EMU_EXTRAPREC=y
81# CONFIG_M68KFPU_EMU_ONLY is not set
82# CONFIG_ADVANCED is not set
83
84#
85# General setup
86#
87CONFIG_BINFMT_ELF=y
88CONFIG_BINFMT_AOUT=m
89CONFIG_BINFMT_MISC=m
90# CONFIG_HEARTBEAT is not set
91CONFIG_PROC_HARDWARE=y
92CONFIG_ISA=y
93CONFIG_GENERIC_ISA_DMA=y
94
95#
96# Device Drivers
97#
98
99#
100# Generic Driver Options
101#
102CONFIG_STANDALONE=y
103CONFIG_PREVENT_FIRMWARE_BUILD=y
104# CONFIG_DEBUG_DRIVER is not set
105
106#
107# Memory Technology Devices (MTD)
108#
109# CONFIG_MTD is not set
110
111#
112# Parallel port support
113#
114# CONFIG_PARPORT is not set
115
116#
117# Plug and Play support
118#
119# CONFIG_PNP is not set
120
121#
122# Block devices
123#
124# CONFIG_BLK_DEV_FD is not set
125# CONFIG_BLK_DEV_XD is not set
126CONFIG_BLK_DEV_LOOP=y
127CONFIG_BLK_DEV_CRYPTOLOOP=m
128CONFIG_BLK_DEV_NBD=m
129CONFIG_BLK_DEV_RAM=y
130CONFIG_BLK_DEV_RAM_COUNT=16
131CONFIG_BLK_DEV_RAM_SIZE=4096
132CONFIG_BLK_DEV_INITRD=y
133CONFIG_INITRAMFS_SOURCE=""
134CONFIG_CDROM_PKTCDVD=m
135CONFIG_CDROM_PKTCDVD_BUFFERS=8
136# CONFIG_CDROM_PKTCDVD_WCACHE is not set
137
138#
139# IO Schedulers
140#
141CONFIG_IOSCHED_NOOP=y
142CONFIG_IOSCHED_AS=y
143CONFIG_IOSCHED_DEADLINE=y
144CONFIG_IOSCHED_CFQ=y
145
146#
147# ATA/ATAPI/MFM/RLL support
148#
149CONFIG_IDE=y
150CONFIG_BLK_DEV_IDE=y
151
152#
153# Please see Documentation/ide.txt for help/info on IDE drives
154#
155# CONFIG_BLK_DEV_IDE_SATA is not set
156CONFIG_BLK_DEV_IDEDISK=y
157# CONFIG_IDEDISK_MULTI_MODE is not set
158CONFIG_BLK_DEV_IDECD=y
159CONFIG_BLK_DEV_IDETAPE=m
160CONFIG_BLK_DEV_IDEFLOPPY=m
161# CONFIG_BLK_DEV_IDESCSI is not set
162# CONFIG_IDE_TASK_IOCTL is not set
163
164#
165# IDE chipset support/bugfixes
166#
167CONFIG_IDE_GENERIC=y
168# CONFIG_IDE_ARM is not set
169CONFIG_BLK_DEV_Q40IDE=y
170# CONFIG_IDE_CHIPSETS is not set
171# CONFIG_BLK_DEV_IDEDMA is not set
172# CONFIG_IDEDMA_AUTO is not set
173# CONFIG_BLK_DEV_HD is not set
174
175#
176# SCSI device support
177#
178CONFIG_SCSI=y
179CONFIG_SCSI_PROC_FS=y
180
181#
182# SCSI support type (disk, tape, CD-ROM)
183#
184CONFIG_BLK_DEV_SD=y
185CONFIG_CHR_DEV_ST=m
186# CONFIG_CHR_DEV_OSST is not set
187CONFIG_BLK_DEV_SR=y
188CONFIG_BLK_DEV_SR_VENDOR=y
189CONFIG_CHR_DEV_SG=m
190
191#
192# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
193#
194# CONFIG_SCSI_MULTI_LUN is not set
195CONFIG_SCSI_CONSTANTS=y
196# CONFIG_SCSI_LOGGING is not set
197
198#
199# SCSI Transport Attributes
200#
201# CONFIG_SCSI_SPI_ATTRS is not set
202# CONFIG_SCSI_FC_ATTRS is not set
203
204#
205# SCSI low-level drivers
206#
207# CONFIG_SCSI_7000FASST is not set
208# CONFIG_SCSI_AHA152X is not set
209# CONFIG_SCSI_AHA1542 is not set
210# CONFIG_SCSI_AIC7XXX_OLD is not set
211# CONFIG_SCSI_IN2000 is not set
212# CONFIG_SCSI_SATA is not set
213# CONFIG_SCSI_BUSLOGIC is not set
214# CONFIG_SCSI_DTC3280 is not set
215# CONFIG_SCSI_EATA is not set
216# CONFIG_SCSI_EATA_PIO is not set
217# CONFIG_SCSI_FUTURE_DOMAIN is not set
218# CONFIG_SCSI_GDTH is not set
219# CONFIG_SCSI_GENERIC_NCR5380 is not set
220# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
221# CONFIG_SCSI_NCR53C406A is not set
222# CONFIG_SCSI_PAS16 is not set
223# CONFIG_SCSI_PSI240I is not set
224# CONFIG_SCSI_QLOGIC_FAS is not set
225# CONFIG_SCSI_SYM53C416 is not set
226# CONFIG_SCSI_T128 is not set
227# CONFIG_SCSI_U14_34F is not set
228# CONFIG_SCSI_DEBUG is not set
229
230#
231# Old CD-ROM drivers (not SCSI, not IDE)
232#
233# CONFIG_CD_NO_IDESCSI is not set
234
235#
236# Multi-device support (RAID and LVM)
237#
238CONFIG_MD=y
239CONFIG_BLK_DEV_MD=m
240CONFIG_MD_LINEAR=m
241CONFIG_MD_RAID0=m
242CONFIG_MD_RAID1=m
243# CONFIG_MD_RAID10 is not set
244CONFIG_MD_RAID5=m
245CONFIG_MD_RAID6=m
246CONFIG_MD_MULTIPATH=m
247# CONFIG_MD_FAULTY is not set
248CONFIG_BLK_DEV_DM=m
249CONFIG_DM_CRYPT=m
250CONFIG_DM_SNAPSHOT=m
251CONFIG_DM_MIRROR=m
252CONFIG_DM_ZERO=m
253
254#
255# Fusion MPT device support
256#
257
258#
259# IEEE 1394 (FireWire) support
260#
261
262#
263# I2O device support
264#
265
266#
267# Networking support
268#
269CONFIG_NET=y
270
271#
272# Networking options
273#
274CONFIG_PACKET=y
275# CONFIG_PACKET_MMAP is not set
276CONFIG_NETLINK_DEV=y
277CONFIG_UNIX=y
278CONFIG_NET_KEY=y
279CONFIG_INET=y
280# CONFIG_IP_MULTICAST is not set
281# CONFIG_IP_ADVANCED_ROUTER is not set
282CONFIG_IP_PNP=y
283CONFIG_IP_PNP_DHCP=y
284CONFIG_IP_PNP_BOOTP=y
285CONFIG_IP_PNP_RARP=y
286CONFIG_NET_IPIP=m
287CONFIG_NET_IPGRE=m
288# CONFIG_ARPD is not set
289CONFIG_SYN_COOKIES=y
290CONFIG_INET_AH=m
291CONFIG_INET_ESP=m
292CONFIG_INET_IPCOMP=m
293CONFIG_INET_TUNNEL=m
294CONFIG_IP_TCPDIAG=m
295CONFIG_IP_TCPDIAG_IPV6=y
296
297#
298# IP: Virtual Server Configuration
299#
300# CONFIG_IP_VS is not set
301CONFIG_IPV6=m
302CONFIG_IPV6_PRIVACY=y
303CONFIG_INET6_AH=m
304CONFIG_INET6_ESP=m
305CONFIG_INET6_IPCOMP=m
306CONFIG_INET6_TUNNEL=m
307CONFIG_IPV6_TUNNEL=m
308CONFIG_NETFILTER=y
309# CONFIG_NETFILTER_DEBUG is not set
310
311#
312# IP: Netfilter Configuration
313#
314CONFIG_IP_NF_CONNTRACK=m
315# CONFIG_IP_NF_CT_ACCT is not set
316CONFIG_IP_NF_CONNTRACK_MARK=y
317# CONFIG_IP_NF_CT_PROTO_SCTP is not set
318CONFIG_IP_NF_FTP=m
319CONFIG_IP_NF_IRC=m
320CONFIG_IP_NF_TFTP=m
321CONFIG_IP_NF_AMANDA=m
322CONFIG_IP_NF_QUEUE=m
323CONFIG_IP_NF_IPTABLES=m
324CONFIG_IP_NF_MATCH_LIMIT=m
325CONFIG_IP_NF_MATCH_IPRANGE=m
326CONFIG_IP_NF_MATCH_MAC=m
327CONFIG_IP_NF_MATCH_PKTTYPE=m
328CONFIG_IP_NF_MATCH_MARK=m
329CONFIG_IP_NF_MATCH_MULTIPORT=m
330CONFIG_IP_NF_MATCH_TOS=m
331CONFIG_IP_NF_MATCH_RECENT=m
332CONFIG_IP_NF_MATCH_ECN=m
333CONFIG_IP_NF_MATCH_DSCP=m
334CONFIG_IP_NF_MATCH_AH_ESP=m
335CONFIG_IP_NF_MATCH_LENGTH=m
336CONFIG_IP_NF_MATCH_TTL=m
337CONFIG_IP_NF_MATCH_TCPMSS=m
338CONFIG_IP_NF_MATCH_HELPER=m
339CONFIG_IP_NF_MATCH_STATE=m
340CONFIG_IP_NF_MATCH_CONNTRACK=m
341CONFIG_IP_NF_MATCH_OWNER=m
342CONFIG_IP_NF_MATCH_ADDRTYPE=m
343CONFIG_IP_NF_MATCH_REALM=m
344# CONFIG_IP_NF_MATCH_SCTP is not set
345# CONFIG_IP_NF_MATCH_COMMENT is not set
346CONFIG_IP_NF_MATCH_CONNMARK=m
347CONFIG_IP_NF_MATCH_HASHLIMIT=m
348CONFIG_IP_NF_FILTER=m
349CONFIG_IP_NF_TARGET_REJECT=m
350CONFIG_IP_NF_TARGET_LOG=m
351CONFIG_IP_NF_TARGET_ULOG=m
352CONFIG_IP_NF_TARGET_TCPMSS=m
353CONFIG_IP_NF_NAT=m
354CONFIG_IP_NF_NAT_NEEDED=y
355CONFIG_IP_NF_TARGET_MASQUERADE=m
356CONFIG_IP_NF_TARGET_REDIRECT=m
357CONFIG_IP_NF_TARGET_NETMAP=m
358CONFIG_IP_NF_TARGET_SAME=m
359CONFIG_IP_NF_NAT_SNMP_BASIC=m
360CONFIG_IP_NF_NAT_IRC=m
361CONFIG_IP_NF_NAT_FTP=m
362CONFIG_IP_NF_NAT_TFTP=m
363CONFIG_IP_NF_NAT_AMANDA=m
364CONFIG_IP_NF_MANGLE=m
365CONFIG_IP_NF_TARGET_TOS=m
366CONFIG_IP_NF_TARGET_ECN=m
367CONFIG_IP_NF_TARGET_DSCP=m
368CONFIG_IP_NF_TARGET_MARK=m
369CONFIG_IP_NF_TARGET_CLASSIFY=m
370CONFIG_IP_NF_TARGET_CONNMARK=m
371# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
372CONFIG_IP_NF_RAW=m
373CONFIG_IP_NF_TARGET_NOTRACK=m
374CONFIG_IP_NF_ARPTABLES=m
375CONFIG_IP_NF_ARPFILTER=m
376CONFIG_IP_NF_ARP_MANGLE=m
377CONFIG_IP_NF_COMPAT_IPCHAINS=m
378CONFIG_IP_NF_COMPAT_IPFWADM=m
379
380#
381# IPv6: Netfilter Configuration
382#
383CONFIG_IP6_NF_QUEUE=m
384CONFIG_IP6_NF_IPTABLES=m
385CONFIG_IP6_NF_MATCH_LIMIT=m
386CONFIG_IP6_NF_MATCH_MAC=m
387CONFIG_IP6_NF_MATCH_RT=m
388CONFIG_IP6_NF_MATCH_OPTS=m
389CONFIG_IP6_NF_MATCH_FRAG=m
390CONFIG_IP6_NF_MATCH_HL=m
391CONFIG_IP6_NF_MATCH_MULTIPORT=m
392CONFIG_IP6_NF_MATCH_OWNER=m
393CONFIG_IP6_NF_MATCH_MARK=m
394CONFIG_IP6_NF_MATCH_IPV6HEADER=m
395CONFIG_IP6_NF_MATCH_AHESP=m
396CONFIG_IP6_NF_MATCH_LENGTH=m
397CONFIG_IP6_NF_MATCH_EUI64=m
398CONFIG_IP6_NF_FILTER=m
399CONFIG_IP6_NF_TARGET_LOG=m
400CONFIG_IP6_NF_MANGLE=m
401CONFIG_IP6_NF_TARGET_MARK=m
402CONFIG_IP6_NF_RAW=m
403CONFIG_XFRM=y
404# CONFIG_XFRM_USER is not set
405
406#
407# SCTP Configuration (EXPERIMENTAL)
408#
409CONFIG_IP_SCTP=m
410# CONFIG_SCTP_DBG_MSG is not set
411# CONFIG_SCTP_DBG_OBJCNT is not set
412# CONFIG_SCTP_HMAC_NONE is not set
413# CONFIG_SCTP_HMAC_SHA1 is not set
414CONFIG_SCTP_HMAC_MD5=y
415# CONFIG_ATM is not set
416# CONFIG_BRIDGE is not set
417# CONFIG_VLAN_8021Q is not set
418# CONFIG_DECNET is not set
419CONFIG_LLC=m
420# CONFIG_LLC2 is not set
421CONFIG_IPX=m
422# CONFIG_IPX_INTERN is not set
423CONFIG_ATALK=m
424# CONFIG_DEV_APPLETALK is not set
425# CONFIG_X25 is not set
426# CONFIG_LAPB is not set
427# CONFIG_NET_DIVERT is not set
428# CONFIG_ECONET is not set
429# CONFIG_WAN_ROUTER is not set
430
431#
432# QoS and/or fair queueing
433#
434# CONFIG_NET_SCHED is not set
435CONFIG_NET_CLS_ROUTE=y
436
437#
438# Network testing
439#
440# CONFIG_NET_PKTGEN is not set
441CONFIG_NETPOLL=y
442# CONFIG_NETPOLL_RX is not set
443# CONFIG_NETPOLL_TRAP is not set
444CONFIG_NET_POLL_CONTROLLER=y
445# CONFIG_HAMRADIO is not set
446# CONFIG_IRDA is not set
447# CONFIG_BT is not set
448CONFIG_NETDEVICES=y
449CONFIG_DUMMY=m
450# CONFIG_BONDING is not set
451CONFIG_EQUALIZER=m
452# CONFIG_TUN is not set
453# CONFIG_ETHERTAP is not set
454
455#
456# ARCnet devices
457#
458# CONFIG_ARCNET is not set
459
460#
461# Ethernet (10 or 100Mbit)
462#
463CONFIG_NET_ETHERNET=y
464CONFIG_MII=m
465# CONFIG_NET_VENDOR_3COM is not set
466# CONFIG_LANCE is not set
467# CONFIG_NET_VENDOR_SMC is not set
468# CONFIG_NET_VENDOR_RACAL is not set
469# CONFIG_AT1700 is not set
470# CONFIG_DEPCA is not set
471# CONFIG_HP100 is not set
472# CONFIG_NET_ISA is not set
473CONFIG_NE2000=m
474# CONFIG_NET_PCI is not set
475# CONFIG_NET_POCKET is not set
476
477#
478# Ethernet (1000 Mbit)
479#
480
481#
482# Ethernet (10000 Mbit)
483#
484
485#
486# Token Ring devices
487#
488# CONFIG_TR is not set
489
490#
491# Wireless LAN (non-hamradio)
492#
493# CONFIG_NET_RADIO is not set
494
495#
496# Wan interfaces
497#
498# CONFIG_WAN is not set
499CONFIG_PPP=m
500# CONFIG_PPP_MULTILINK is not set
501CONFIG_PPP_FILTER=y
502CONFIG_PPP_ASYNC=m
503CONFIG_PPP_SYNC_TTY=m
504CONFIG_PPP_DEFLATE=m
505CONFIG_PPP_BSDCOMP=m
506CONFIG_PPPOE=m
507CONFIG_SLIP=m
508CONFIG_SLIP_COMPRESSED=y
509CONFIG_SLIP_SMART=y
510CONFIG_SLIP_MODE_SLIP6=y
511CONFIG_SHAPER=m
512CONFIG_NETCONSOLE=m
513
514#
515# ISDN subsystem
516#
517# CONFIG_ISDN is not set
518
519#
520# Telephony Support
521#
522# CONFIG_PHONE is not set
523
524#
525# Input device support
526#
527CONFIG_INPUT=y
528
529#
530# Userland interfaces
531#
532CONFIG_INPUT_MOUSEDEV=y
533CONFIG_INPUT_MOUSEDEV_PSAUX=y
534CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
535CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
536# CONFIG_INPUT_JOYDEV is not set
537# CONFIG_INPUT_TSDEV is not set
538# CONFIG_INPUT_EVDEV is not set
539# CONFIG_INPUT_EVBUG is not set
540
541#
542# Input I/O drivers
543#
544# CONFIG_GAMEPORT is not set
545CONFIG_SOUND_GAMEPORT=y
546CONFIG_SERIO=m
547CONFIG_SERIO_SERPORT=m
548# CONFIG_SERIO_CT82C710 is not set
549CONFIG_SERIO_Q40KBD=m
550# CONFIG_SERIO_RAW is not set
551
552#
553# Input Device Drivers
554#
555CONFIG_INPUT_KEYBOARD=y
556# CONFIG_KEYBOARD_ATKBD is not set
557# CONFIG_KEYBOARD_SUNKBD is not set
558# CONFIG_KEYBOARD_LKKBD is not set
559# CONFIG_KEYBOARD_XTKBD is not set
560# CONFIG_KEYBOARD_NEWTON is not set
561CONFIG_INPUT_MOUSE=y
562CONFIG_MOUSE_PS2=m
563CONFIG_MOUSE_SERIAL=m
564# CONFIG_MOUSE_INPORT is not set
565# CONFIG_MOUSE_LOGIBM is not set
566# CONFIG_MOUSE_PC110PAD is not set
567# CONFIG_MOUSE_VSXXXAA is not set
568# CONFIG_INPUT_JOYSTICK is not set
569# CONFIG_INPUT_TOUCHSCREEN is not set
570# CONFIG_INPUT_MISC is not set
571
572#
573# Character devices
574#
575CONFIG_VT=y
576CONFIG_VT_CONSOLE=y
577CONFIG_HW_CONSOLE=y
578# CONFIG_SERIAL_NONSTANDARD is not set
579
580#
581# Serial drivers
582#
583# CONFIG_SERIAL_8250 is not set
584
585#
586# Non-8250 serial port support
587#
588CONFIG_UNIX98_PTYS=y
589CONFIG_LEGACY_PTYS=y
590CONFIG_LEGACY_PTY_COUNT=256
591
592#
593# IPMI
594#
595# CONFIG_IPMI_HANDLER is not set
596
597#
598# Watchdog Cards
599#
600# CONFIG_WATCHDOG is not set
601CONFIG_GEN_RTC=m
602CONFIG_GEN_RTC_X=y
603# CONFIG_DTLK is not set
604# CONFIG_R3964 is not set
605
606#
607# Ftape, the floppy tape device driver
608#
609# CONFIG_DRM is not set
610# CONFIG_RAW_DRIVER is not set
611
612#
613# I2C support
614#
615# CONFIG_I2C is not set
616
617#
618# Dallas's 1-wire bus
619#
620# CONFIG_W1 is not set
621
622#
623# Misc devices
624#
625
626#
627# Multimedia devices
628#
629# CONFIG_VIDEO_DEV is not set
630
631#
632# Digital Video Broadcasting Devices
633#
634# CONFIG_DVB is not set
635
636#
637# Graphics support
638#
639CONFIG_FB=y
640CONFIG_FB_MODE_HELPERS=y
641# CONFIG_FB_TILEBLITTING is not set
642CONFIG_FB_Q40=y
643# CONFIG_FB_VIRTUAL is not set
644
645#
646# Console display driver support
647#
648CONFIG_DUMMY_CONSOLE=y
649CONFIG_FRAMEBUFFER_CONSOLE=y
650# CONFIG_FONTS is not set
651CONFIG_FONT_8x8=y
652CONFIG_FONT_8x16=y
653
654#
655# Logo configuration
656#
657CONFIG_LOGO=y
658CONFIG_LOGO_LINUX_MONO=y
659CONFIG_LOGO_LINUX_VGA16=y
660CONFIG_LOGO_LINUX_CLUT224=y
661
662#
663# Sound
664#
665CONFIG_SOUND=y
666CONFIG_DMASOUND_Q40=y
667CONFIG_DMASOUND=y
668
669#
670# USB support
671#
672# CONFIG_USB_ARCH_HAS_HCD is not set
673# CONFIG_USB_ARCH_HAS_OHCI is not set
674
675#
676# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
677#
678
679#
680# USB Gadget Support
681#
682# CONFIG_USB_GADGET is not set
683
684#
685# MMC/SD Card support
686#
687# CONFIG_MMC is not set
688
689#
690# Character devices
691#
692
693#
694# File systems
695#
696CONFIG_EXT2_FS=y
697# CONFIG_EXT2_FS_XATTR is not set
698CONFIG_EXT3_FS=y
699# CONFIG_EXT3_FS_XATTR is not set
700CONFIG_JBD=y
701# CONFIG_JBD_DEBUG is not set
702CONFIG_REISERFS_FS=m
703# CONFIG_REISERFS_CHECK is not set
704# CONFIG_REISERFS_PROC_INFO is not set
705# CONFIG_REISERFS_FS_XATTR is not set
706CONFIG_JFS_FS=m
707# CONFIG_JFS_POSIX_ACL is not set
708# CONFIG_JFS_DEBUG is not set
709# CONFIG_JFS_STATISTICS is not set
710CONFIG_FS_POSIX_ACL=y
711CONFIG_XFS_FS=m
712# CONFIG_XFS_RT is not set
713# CONFIG_XFS_QUOTA is not set
714# CONFIG_XFS_SECURITY is not set
715# CONFIG_XFS_POSIX_ACL is not set
716CONFIG_MINIX_FS=y
717# CONFIG_ROMFS_FS is not set
718CONFIG_QUOTA=y
719# CONFIG_QFMT_V1 is not set
720# CONFIG_QFMT_V2 is not set
721CONFIG_QUOTACTL=y
722CONFIG_DNOTIFY=y
723CONFIG_AUTOFS_FS=m
724CONFIG_AUTOFS4_FS=m
725
726#
727# CD-ROM/DVD Filesystems
728#
729CONFIG_ISO9660_FS=y
730CONFIG_JOLIET=y
731CONFIG_ZISOFS=y
732CONFIG_ZISOFS_FS=y
733CONFIG_UDF_FS=m
734CONFIG_UDF_NLS=y
735
736#
737# DOS/FAT/NT Filesystems
738#
739CONFIG_FAT_FS=y
740CONFIG_MSDOS_FS=y
741CONFIG_VFAT_FS=m
742CONFIG_FAT_DEFAULT_CODEPAGE=437
743CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
744# CONFIG_NTFS_FS is not set
745
746#
747# Pseudo filesystems
748#
749CONFIG_PROC_FS=y
750CONFIG_PROC_KCORE=y
751CONFIG_SYSFS=y
752# CONFIG_DEVFS_FS is not set
753# CONFIG_DEVPTS_FS_XATTR is not set
754CONFIG_TMPFS=y
755# CONFIG_TMPFS_XATTR is not set
756# CONFIG_HUGETLB_PAGE is not set
757CONFIG_RAMFS=y
758
759#
760# Miscellaneous filesystems
761#
762# CONFIG_ADFS_FS is not set
763CONFIG_AFFS_FS=m
764CONFIG_HFS_FS=m
765CONFIG_HFSPLUS_FS=m
766# CONFIG_BEFS_FS is not set
767# CONFIG_BFS_FS is not set
768# CONFIG_EFS_FS is not set
769CONFIG_CRAMFS=m
770# CONFIG_VXFS_FS is not set
771CONFIG_HPFS_FS=m
772# CONFIG_QNX4FS_FS is not set
773CONFIG_SYSV_FS=m
774CONFIG_UFS_FS=m
775CONFIG_UFS_FS_WRITE=y
776
777#
778# Network File Systems
779#
780CONFIG_NFS_FS=y
781CONFIG_NFS_V3=y
782CONFIG_NFS_V4=y
783# CONFIG_NFS_DIRECTIO is not set
784CONFIG_NFSD=m
785CONFIG_NFSD_V3=y
786CONFIG_NFSD_V4=y
787CONFIG_NFSD_TCP=y
788CONFIG_ROOT_NFS=y
789CONFIG_LOCKD=y
790CONFIG_LOCKD_V4=y
791CONFIG_EXPORTFS=m
792CONFIG_SUNRPC=y
793CONFIG_SUNRPC_GSS=y
794CONFIG_RPCSEC_GSS_KRB5=y
795# CONFIG_RPCSEC_GSS_SPKM3 is not set
796CONFIG_SMB_FS=m
797CONFIG_SMB_NLS_DEFAULT=y
798CONFIG_SMB_NLS_REMOTE="cp437"
799# CONFIG_CIFS is not set
800CONFIG_NCP_FS=m
801# CONFIG_NCPFS_PACKET_SIGNING is not set
802# CONFIG_NCPFS_IOCTL_LOCKING is not set
803# CONFIG_NCPFS_STRONG is not set
804# CONFIG_NCPFS_NFS_NS is not set
805# CONFIG_NCPFS_OS2_NS is not set
806# CONFIG_NCPFS_SMALLDOS is not set
807CONFIG_NCPFS_NLS=y
808# CONFIG_NCPFS_EXTRAS is not set
809CONFIG_CODA_FS=m
810# CONFIG_CODA_FS_OLD_API is not set
811# CONFIG_AFS_FS is not set
812
813#
814# Partition Types
815#
816# CONFIG_PARTITION_ADVANCED is not set
817CONFIG_MSDOS_PARTITION=y
818
819#
820# Native Language Support
821#
822CONFIG_NLS=y
823CONFIG_NLS_DEFAULT="iso8859-1"
824CONFIG_NLS_CODEPAGE_437=y
825CONFIG_NLS_CODEPAGE_737=m
826CONFIG_NLS_CODEPAGE_775=m
827CONFIG_NLS_CODEPAGE_850=m
828CONFIG_NLS_CODEPAGE_852=m
829CONFIG_NLS_CODEPAGE_855=m
830CONFIG_NLS_CODEPAGE_857=m
831CONFIG_NLS_CODEPAGE_860=m
832CONFIG_NLS_CODEPAGE_861=m
833CONFIG_NLS_CODEPAGE_862=m
834CONFIG_NLS_CODEPAGE_863=m
835CONFIG_NLS_CODEPAGE_864=m
836CONFIG_NLS_CODEPAGE_865=m
837CONFIG_NLS_CODEPAGE_866=m
838CONFIG_NLS_CODEPAGE_869=m
839CONFIG_NLS_CODEPAGE_936=m
840CONFIG_NLS_CODEPAGE_950=m
841CONFIG_NLS_CODEPAGE_932=m
842CONFIG_NLS_CODEPAGE_949=m
843CONFIG_NLS_CODEPAGE_874=m
844CONFIG_NLS_ISO8859_8=m
845CONFIG_NLS_CODEPAGE_1250=m
846CONFIG_NLS_CODEPAGE_1251=m
847CONFIG_NLS_ASCII=m
848CONFIG_NLS_ISO8859_1=y
849CONFIG_NLS_ISO8859_2=m
850CONFIG_NLS_ISO8859_3=m
851CONFIG_NLS_ISO8859_4=m
852CONFIG_NLS_ISO8859_5=m
853CONFIG_NLS_ISO8859_6=m
854CONFIG_NLS_ISO8859_7=m
855CONFIG_NLS_ISO8859_9=m
856CONFIG_NLS_ISO8859_13=m
857CONFIG_NLS_ISO8859_14=m
858CONFIG_NLS_ISO8859_15=m
859CONFIG_NLS_KOI8_R=m
860CONFIG_NLS_KOI8_U=m
861CONFIG_NLS_UTF8=m
862
863#
864# Kernel hacking
865#
866CONFIG_DEBUG_KERNEL=y
867CONFIG_MAGIC_SYSRQ=y
868# CONFIG_SCHEDSTATS is not set
869# CONFIG_DEBUG_SLAB is not set
870# CONFIG_DEBUG_KOBJECT is not set
871# CONFIG_DEBUG_BUGVERBOSE is not set
872# CONFIG_DEBUG_INFO is not set
873
874#
875# Security options
876#
877# CONFIG_KEYS is not set
878# CONFIG_SECURITY is not set
879
880#
881# Cryptographic options
882#
883CONFIG_CRYPTO=y
884CONFIG_CRYPTO_HMAC=y
885CONFIG_CRYPTO_NULL=m
886CONFIG_CRYPTO_MD4=m
887CONFIG_CRYPTO_MD5=y
888CONFIG_CRYPTO_SHA1=m
889CONFIG_CRYPTO_SHA256=m
890CONFIG_CRYPTO_SHA512=m
891# CONFIG_CRYPTO_WP512 is not set
892CONFIG_CRYPTO_DES=y
893CONFIG_CRYPTO_BLOWFISH=m
894CONFIG_CRYPTO_TWOFISH=m
895CONFIG_CRYPTO_SERPENT=m
896CONFIG_CRYPTO_AES=m
897CONFIG_CRYPTO_CAST5=m
898CONFIG_CRYPTO_CAST6=m
899CONFIG_CRYPTO_TEA=m
900CONFIG_CRYPTO_ARC4=m
901CONFIG_CRYPTO_KHAZAD=m
902CONFIG_CRYPTO_ANUBIS=m
903CONFIG_CRYPTO_DEFLATE=m
904CONFIG_CRYPTO_MICHAEL_MIC=m
905CONFIG_CRYPTO_CRC32C=m
906CONFIG_CRYPTO_TEST=m
907
908#
909# Library routines
910#
911CONFIG_CRC_CCITT=m
912CONFIG_CRC32=y
913CONFIG_LIBCRC32C=m
914CONFIG_ZLIB_INFLATE=y
915CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
new file mode 100644
index 000000000000..33c4db63b72c
--- /dev/null
+++ b/arch/m68k/configs/sun3_defconfig
@@ -0,0 +1,831 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:24:01 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-sun3"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61CONFIG_SUN3=y
62
63#
64# Processor type
65#
66CONFIG_M68020=y
67CONFIG_MMU_SUN3=y
68CONFIG_M68KFPU_EMU=y
69CONFIG_M68KFPU_EMU_EXTRAPREC=y
70# CONFIG_M68KFPU_EMU_ONLY is not set
71# CONFIG_ADVANCED is not set
72
73#
74# General setup
75#
76CONFIG_BINFMT_ELF=y
77CONFIG_BINFMT_AOUT=m
78CONFIG_BINFMT_MISC=m
79CONFIG_PROC_HARDWARE=y
80
81#
82# Device Drivers
83#
84
85#
86# Generic Driver Options
87#
88CONFIG_STANDALONE=y
89CONFIG_PREVENT_FIRMWARE_BUILD=y
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#
100# CONFIG_PARPORT is not set
101
102#
103# Plug and Play support
104#
105
106#
107# Block devices
108#
109CONFIG_BLK_DEV_LOOP=y
110CONFIG_BLK_DEV_CRYPTOLOOP=m
111CONFIG_BLK_DEV_NBD=m
112CONFIG_BLK_DEV_RAM=y
113CONFIG_BLK_DEV_RAM_COUNT=16
114CONFIG_BLK_DEV_RAM_SIZE=4096
115CONFIG_BLK_DEV_INITRD=y
116CONFIG_INITRAMFS_SOURCE=""
117CONFIG_CDROM_PKTCDVD=m
118CONFIG_CDROM_PKTCDVD_BUFFERS=8
119# CONFIG_CDROM_PKTCDVD_WCACHE is not set
120
121#
122# IO Schedulers
123#
124CONFIG_IOSCHED_NOOP=y
125CONFIG_IOSCHED_AS=y
126CONFIG_IOSCHED_DEADLINE=y
127CONFIG_IOSCHED_CFQ=y
128
129#
130# ATA/ATAPI/MFM/RLL support
131#
132# CONFIG_IDE is not set
133
134#
135# SCSI device support
136#
137CONFIG_SCSI=y
138CONFIG_SCSI_PROC_FS=y
139
140#
141# SCSI support type (disk, tape, CD-ROM)
142#
143CONFIG_BLK_DEV_SD=y
144CONFIG_CHR_DEV_ST=m
145# CONFIG_CHR_DEV_OSST is not set
146CONFIG_BLK_DEV_SR=y
147CONFIG_BLK_DEV_SR_VENDOR=y
148CONFIG_CHR_DEV_SG=m
149
150#
151# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
152#
153# CONFIG_SCSI_MULTI_LUN is not set
154CONFIG_SCSI_CONSTANTS=y
155# CONFIG_SCSI_LOGGING is not set
156
157#
158# SCSI Transport Attributes
159#
160# CONFIG_SCSI_SPI_ATTRS is not set
161# CONFIG_SCSI_FC_ATTRS is not set
162
163#
164# SCSI low-level drivers
165#
166# CONFIG_SCSI_SATA is not set
167# CONFIG_SCSI_DEBUG is not set
168CONFIG_SUN3_SCSI=y
169
170#
171# Multi-device support (RAID and LVM)
172#
173CONFIG_MD=y
174CONFIG_BLK_DEV_MD=m
175CONFIG_MD_LINEAR=m
176CONFIG_MD_RAID0=m
177CONFIG_MD_RAID1=m
178# CONFIG_MD_RAID10 is not set
179CONFIG_MD_RAID5=m
180CONFIG_MD_RAID6=m
181CONFIG_MD_MULTIPATH=m
182# CONFIG_MD_FAULTY is not set
183CONFIG_BLK_DEV_DM=m
184CONFIG_DM_CRYPT=m
185CONFIG_DM_SNAPSHOT=m
186CONFIG_DM_MIRROR=m
187CONFIG_DM_ZERO=m
188
189#
190# Fusion MPT device support
191#
192
193#
194# IEEE 1394 (FireWire) support
195#
196
197#
198# I2O device support
199#
200
201#
202# Networking support
203#
204CONFIG_NET=y
205
206#
207# Networking options
208#
209CONFIG_PACKET=y
210# CONFIG_PACKET_MMAP is not set
211CONFIG_NETLINK_DEV=y
212CONFIG_UNIX=y
213CONFIG_NET_KEY=y
214CONFIG_INET=y
215# CONFIG_IP_MULTICAST is not set
216# CONFIG_IP_ADVANCED_ROUTER is not set
217CONFIG_IP_PNP=y
218CONFIG_IP_PNP_DHCP=y
219CONFIG_IP_PNP_BOOTP=y
220CONFIG_IP_PNP_RARP=y
221CONFIG_NET_IPIP=m
222CONFIG_NET_IPGRE=m
223# CONFIG_ARPD is not set
224CONFIG_SYN_COOKIES=y
225CONFIG_INET_AH=m
226CONFIG_INET_ESP=m
227CONFIG_INET_IPCOMP=m
228CONFIG_INET_TUNNEL=m
229CONFIG_IP_TCPDIAG=m
230CONFIG_IP_TCPDIAG_IPV6=y
231
232#
233# IP: Virtual Server Configuration
234#
235# CONFIG_IP_VS is not set
236CONFIG_IPV6=m
237CONFIG_IPV6_PRIVACY=y
238CONFIG_INET6_AH=m
239CONFIG_INET6_ESP=m
240CONFIG_INET6_IPCOMP=m
241CONFIG_INET6_TUNNEL=m
242CONFIG_IPV6_TUNNEL=m
243CONFIG_NETFILTER=y
244# CONFIG_NETFILTER_DEBUG is not set
245
246#
247# IP: Netfilter Configuration
248#
249CONFIG_IP_NF_CONNTRACK=m
250# CONFIG_IP_NF_CT_ACCT is not set
251CONFIG_IP_NF_CONNTRACK_MARK=y
252# CONFIG_IP_NF_CT_PROTO_SCTP is not set
253CONFIG_IP_NF_FTP=m
254CONFIG_IP_NF_IRC=m
255CONFIG_IP_NF_TFTP=m
256CONFIG_IP_NF_AMANDA=m
257CONFIG_IP_NF_QUEUE=m
258CONFIG_IP_NF_IPTABLES=m
259CONFIG_IP_NF_MATCH_LIMIT=m
260CONFIG_IP_NF_MATCH_IPRANGE=m
261CONFIG_IP_NF_MATCH_MAC=m
262CONFIG_IP_NF_MATCH_PKTTYPE=m
263CONFIG_IP_NF_MATCH_MARK=m
264CONFIG_IP_NF_MATCH_MULTIPORT=m
265CONFIG_IP_NF_MATCH_TOS=m
266CONFIG_IP_NF_MATCH_RECENT=m
267CONFIG_IP_NF_MATCH_ECN=m
268CONFIG_IP_NF_MATCH_DSCP=m
269CONFIG_IP_NF_MATCH_AH_ESP=m
270CONFIG_IP_NF_MATCH_LENGTH=m
271CONFIG_IP_NF_MATCH_TTL=m
272CONFIG_IP_NF_MATCH_TCPMSS=m
273CONFIG_IP_NF_MATCH_HELPER=m
274CONFIG_IP_NF_MATCH_STATE=m
275CONFIG_IP_NF_MATCH_CONNTRACK=m
276CONFIG_IP_NF_MATCH_OWNER=m
277CONFIG_IP_NF_MATCH_ADDRTYPE=m
278CONFIG_IP_NF_MATCH_REALM=m
279# CONFIG_IP_NF_MATCH_SCTP is not set
280# CONFIG_IP_NF_MATCH_COMMENT is not set
281CONFIG_IP_NF_MATCH_CONNMARK=m
282CONFIG_IP_NF_MATCH_HASHLIMIT=m
283CONFIG_IP_NF_FILTER=m
284CONFIG_IP_NF_TARGET_REJECT=m
285CONFIG_IP_NF_TARGET_LOG=m
286CONFIG_IP_NF_TARGET_ULOG=m
287CONFIG_IP_NF_TARGET_TCPMSS=m
288CONFIG_IP_NF_NAT=m
289CONFIG_IP_NF_NAT_NEEDED=y
290CONFIG_IP_NF_TARGET_MASQUERADE=m
291CONFIG_IP_NF_TARGET_REDIRECT=m
292CONFIG_IP_NF_TARGET_NETMAP=m
293CONFIG_IP_NF_TARGET_SAME=m
294CONFIG_IP_NF_NAT_SNMP_BASIC=m
295CONFIG_IP_NF_NAT_IRC=m
296CONFIG_IP_NF_NAT_FTP=m
297CONFIG_IP_NF_NAT_TFTP=m
298CONFIG_IP_NF_NAT_AMANDA=m
299CONFIG_IP_NF_MANGLE=m
300CONFIG_IP_NF_TARGET_TOS=m
301CONFIG_IP_NF_TARGET_ECN=m
302CONFIG_IP_NF_TARGET_DSCP=m
303CONFIG_IP_NF_TARGET_MARK=m
304CONFIG_IP_NF_TARGET_CLASSIFY=m
305CONFIG_IP_NF_TARGET_CONNMARK=m
306# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
307CONFIG_IP_NF_RAW=m
308CONFIG_IP_NF_TARGET_NOTRACK=m
309CONFIG_IP_NF_ARPTABLES=m
310CONFIG_IP_NF_ARPFILTER=m
311CONFIG_IP_NF_ARP_MANGLE=m
312CONFIG_IP_NF_COMPAT_IPCHAINS=m
313CONFIG_IP_NF_COMPAT_IPFWADM=m
314
315#
316# IPv6: Netfilter Configuration
317#
318CONFIG_IP6_NF_QUEUE=m
319CONFIG_IP6_NF_IPTABLES=m
320CONFIG_IP6_NF_MATCH_LIMIT=m
321CONFIG_IP6_NF_MATCH_MAC=m
322CONFIG_IP6_NF_MATCH_RT=m
323CONFIG_IP6_NF_MATCH_OPTS=m
324CONFIG_IP6_NF_MATCH_FRAG=m
325CONFIG_IP6_NF_MATCH_HL=m
326CONFIG_IP6_NF_MATCH_MULTIPORT=m
327CONFIG_IP6_NF_MATCH_OWNER=m
328CONFIG_IP6_NF_MATCH_MARK=m
329CONFIG_IP6_NF_MATCH_IPV6HEADER=m
330CONFIG_IP6_NF_MATCH_AHESP=m
331CONFIG_IP6_NF_MATCH_LENGTH=m
332CONFIG_IP6_NF_MATCH_EUI64=m
333CONFIG_IP6_NF_FILTER=m
334CONFIG_IP6_NF_TARGET_LOG=m
335CONFIG_IP6_NF_MANGLE=m
336CONFIG_IP6_NF_TARGET_MARK=m
337CONFIG_IP6_NF_RAW=m
338CONFIG_XFRM=y
339# CONFIG_XFRM_USER is not set
340
341#
342# SCTP Configuration (EXPERIMENTAL)
343#
344CONFIG_IP_SCTP=m
345# CONFIG_SCTP_DBG_MSG is not set
346# CONFIG_SCTP_DBG_OBJCNT is not set
347# CONFIG_SCTP_HMAC_NONE is not set
348# CONFIG_SCTP_HMAC_SHA1 is not set
349CONFIG_SCTP_HMAC_MD5=y
350# CONFIG_ATM is not set
351# CONFIG_BRIDGE is not set
352# CONFIG_VLAN_8021Q is not set
353# CONFIG_DECNET is not set
354CONFIG_LLC=m
355# CONFIG_LLC2 is not set
356CONFIG_IPX=m
357# CONFIG_IPX_INTERN is not set
358CONFIG_ATALK=m
359# CONFIG_DEV_APPLETALK 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
370CONFIG_NET_CLS_ROUTE=y
371
372#
373# Network testing
374#
375# CONFIG_NET_PKTGEN is not set
376CONFIG_NETPOLL=y
377# CONFIG_NETPOLL_RX is not set
378# CONFIG_NETPOLL_TRAP is not set
379CONFIG_NET_POLL_CONTROLLER=y
380# CONFIG_HAMRADIO is not set
381# CONFIG_IRDA is not set
382# CONFIG_BT is not set
383CONFIG_NETDEVICES=y
384CONFIG_DUMMY=m
385# CONFIG_BONDING is not set
386CONFIG_EQUALIZER=m
387# CONFIG_TUN is not set
388# CONFIG_ETHERTAP is not set
389
390#
391# Ethernet (10 or 100Mbit)
392#
393CONFIG_NET_ETHERNET=y
394CONFIG_MII=m
395CONFIG_SUN3LANCE=y
396CONFIG_SUN3_82586=y
397
398#
399# Ethernet (1000 Mbit)
400#
401
402#
403# Ethernet (10000 Mbit)
404#
405
406#
407# Token Ring devices
408#
409
410#
411# Wireless LAN (non-hamradio)
412#
413# CONFIG_NET_RADIO is not set
414
415#
416# Wan interfaces
417#
418# CONFIG_WAN is not set
419CONFIG_PPP=m
420# CONFIG_PPP_MULTILINK is not set
421CONFIG_PPP_FILTER=y
422CONFIG_PPP_ASYNC=m
423CONFIG_PPP_SYNC_TTY=m
424CONFIG_PPP_DEFLATE=m
425CONFIG_PPP_BSDCOMP=m
426CONFIG_PPPOE=m
427CONFIG_SLIP=m
428CONFIG_SLIP_COMPRESSED=y
429CONFIG_SLIP_SMART=y
430CONFIG_SLIP_MODE_SLIP6=y
431CONFIG_SHAPER=m
432CONFIG_NETCONSOLE=m
433
434#
435# ISDN subsystem
436#
437# CONFIG_ISDN is not set
438
439#
440# Telephony Support
441#
442# CONFIG_PHONE is not set
443
444#
445# Input device support
446#
447CONFIG_INPUT=y
448
449#
450# Userland interfaces
451#
452CONFIG_INPUT_MOUSEDEV=y
453CONFIG_INPUT_MOUSEDEV_PSAUX=y
454CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
455CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
456# CONFIG_INPUT_JOYDEV is not set
457# CONFIG_INPUT_TSDEV is not set
458# CONFIG_INPUT_EVDEV is not set
459# CONFIG_INPUT_EVBUG is not set
460
461#
462# Input I/O drivers
463#
464# CONFIG_GAMEPORT is not set
465CONFIG_SOUND_GAMEPORT=y
466CONFIG_SERIO=y
467CONFIG_SERIO_SERPORT=m
468# CONFIG_SERIO_CT82C710 is not set
469# CONFIG_SERIO_RAW is not set
470
471#
472# Input Device Drivers
473#
474CONFIG_INPUT_KEYBOARD=y
475# CONFIG_KEYBOARD_ATKBD is not set
476CONFIG_KEYBOARD_SUNKBD=y
477# CONFIG_KEYBOARD_LKKBD is not set
478# CONFIG_KEYBOARD_XTKBD is not set
479# CONFIG_KEYBOARD_NEWTON is not set
480CONFIG_INPUT_MOUSE=y
481CONFIG_MOUSE_PS2=m
482CONFIG_MOUSE_SERIAL=m
483# CONFIG_MOUSE_VSXXXAA is not set
484# CONFIG_INPUT_JOYSTICK is not set
485# CONFIG_INPUT_TOUCHSCREEN is not set
486# CONFIG_INPUT_MISC is not set
487
488#
489# Character devices
490#
491CONFIG_VT=y
492CONFIG_VT_CONSOLE=y
493CONFIG_HW_CONSOLE=y
494# CONFIG_SERIAL_NONSTANDARD is not set
495
496#
497# Serial drivers
498#
499# CONFIG_SERIAL_8250 is not set
500
501#
502# Non-8250 serial port support
503#
504CONFIG_UNIX98_PTYS=y
505CONFIG_LEGACY_PTYS=y
506CONFIG_LEGACY_PTY_COUNT=256
507
508#
509# IPMI
510#
511# CONFIG_IPMI_HANDLER is not set
512
513#
514# Watchdog Cards
515#
516# CONFIG_WATCHDOG is not set
517CONFIG_GEN_RTC=y
518CONFIG_GEN_RTC_X=y
519# CONFIG_DTLK is not set
520# CONFIG_R3964 is not set
521
522#
523# Ftape, the floppy tape device driver
524#
525# CONFIG_DRM is not set
526# CONFIG_RAW_DRIVER is not set
527
528#
529# I2C support
530#
531# CONFIG_I2C is not set
532
533#
534# Dallas's 1-wire bus
535#
536# CONFIG_W1 is not set
537
538#
539# Misc devices
540#
541
542#
543# Multimedia devices
544#
545# CONFIG_VIDEO_DEV is not set
546
547#
548# Digital Video Broadcasting Devices
549#
550# CONFIG_DVB is not set
551
552#
553# Graphics support
554#
555CONFIG_FB=y
556CONFIG_FB_MODE_HELPERS=y
557# CONFIG_FB_TILEBLITTING is not set
558# CONFIG_FB_VIRTUAL is not set
559
560#
561# Console display driver support
562#
563CONFIG_DUMMY_CONSOLE=y
564CONFIG_FRAMEBUFFER_CONSOLE=y
565# CONFIG_FONTS is not set
566CONFIG_FONT_8x8=y
567CONFIG_FONT_8x16=y
568
569#
570# Logo configuration
571#
572CONFIG_LOGO=y
573CONFIG_LOGO_LINUX_MONO=y
574CONFIG_LOGO_LINUX_VGA16=y
575CONFIG_LOGO_LINUX_CLUT224=y
576
577#
578# Sound
579#
580# CONFIG_SOUND is not set
581
582#
583# USB support
584#
585# CONFIG_USB_ARCH_HAS_HCD is not set
586# CONFIG_USB_ARCH_HAS_OHCI is not set
587
588#
589# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
590#
591
592#
593# USB Gadget Support
594#
595# CONFIG_USB_GADGET is not set
596
597#
598# MMC/SD Card support
599#
600# CONFIG_MMC is not set
601
602#
603# Character devices
604#
605
606#
607# File systems
608#
609CONFIG_EXT2_FS=y
610# CONFIG_EXT2_FS_XATTR is not set
611CONFIG_EXT3_FS=y
612# CONFIG_EXT3_FS_XATTR is not set
613CONFIG_JBD=y
614# CONFIG_JBD_DEBUG is not set
615CONFIG_REISERFS_FS=m
616# CONFIG_REISERFS_CHECK is not set
617# CONFIG_REISERFS_PROC_INFO is not set
618# CONFIG_REISERFS_FS_XATTR is not set
619CONFIG_JFS_FS=m
620# CONFIG_JFS_POSIX_ACL is not set
621# CONFIG_JFS_DEBUG is not set
622# CONFIG_JFS_STATISTICS is not set
623CONFIG_FS_POSIX_ACL=y
624CONFIG_XFS_FS=m
625# CONFIG_XFS_RT is not set
626# CONFIG_XFS_QUOTA is not set
627# CONFIG_XFS_SECURITY is not set
628# CONFIG_XFS_POSIX_ACL is not set
629CONFIG_MINIX_FS=y
630# CONFIG_ROMFS_FS is not set
631CONFIG_QUOTA=y
632# CONFIG_QFMT_V1 is not set
633# CONFIG_QFMT_V2 is not set
634CONFIG_QUOTACTL=y
635CONFIG_DNOTIFY=y
636CONFIG_AUTOFS_FS=m
637CONFIG_AUTOFS4_FS=m
638
639#
640# CD-ROM/DVD Filesystems
641#
642CONFIG_ISO9660_FS=y
643CONFIG_JOLIET=y
644CONFIG_ZISOFS=y
645CONFIG_ZISOFS_FS=y
646CONFIG_UDF_FS=m
647CONFIG_UDF_NLS=y
648
649#
650# DOS/FAT/NT Filesystems
651#
652CONFIG_FAT_FS=y
653CONFIG_MSDOS_FS=y
654CONFIG_VFAT_FS=m
655CONFIG_FAT_DEFAULT_CODEPAGE=437
656CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
657# CONFIG_NTFS_FS is not set
658
659#
660# Pseudo filesystems
661#
662CONFIG_PROC_FS=y
663CONFIG_PROC_KCORE=y
664CONFIG_SYSFS=y
665CONFIG_DEVFS_FS=y
666CONFIG_DEVFS_MOUNT=y
667# CONFIG_DEVFS_DEBUG is not set
668# CONFIG_DEVPTS_FS_XATTR is not set
669CONFIG_TMPFS=y
670# CONFIG_TMPFS_XATTR is not set
671# CONFIG_HUGETLB_PAGE is not set
672CONFIG_RAMFS=y
673
674#
675# Miscellaneous filesystems
676#
677# CONFIG_ADFS_FS is not set
678CONFIG_AFFS_FS=m
679CONFIG_HFS_FS=m
680CONFIG_HFSPLUS_FS=m
681# CONFIG_BEFS_FS is not set
682# CONFIG_BFS_FS is not set
683# CONFIG_EFS_FS is not set
684CONFIG_CRAMFS=m
685# CONFIG_VXFS_FS is not set
686CONFIG_HPFS_FS=m
687# CONFIG_QNX4FS_FS is not set
688CONFIG_SYSV_FS=m
689CONFIG_UFS_FS=m
690CONFIG_UFS_FS_WRITE=y
691
692#
693# Network File Systems
694#
695CONFIG_NFS_FS=y
696CONFIG_NFS_V3=y
697CONFIG_NFS_V4=y
698# CONFIG_NFS_DIRECTIO is not set
699CONFIG_NFSD=m
700CONFIG_NFSD_V3=y
701CONFIG_NFSD_V4=y
702CONFIG_NFSD_TCP=y
703CONFIG_ROOT_NFS=y
704CONFIG_LOCKD=y
705CONFIG_LOCKD_V4=y
706CONFIG_EXPORTFS=m
707CONFIG_SUNRPC=y
708CONFIG_SUNRPC_GSS=y
709CONFIG_RPCSEC_GSS_KRB5=y
710# CONFIG_RPCSEC_GSS_SPKM3 is not set
711CONFIG_SMB_FS=m
712CONFIG_SMB_NLS_DEFAULT=y
713CONFIG_SMB_NLS_REMOTE="cp437"
714# CONFIG_CIFS is not set
715CONFIG_NCP_FS=m
716# CONFIG_NCPFS_PACKET_SIGNING is not set
717# CONFIG_NCPFS_IOCTL_LOCKING is not set
718# CONFIG_NCPFS_STRONG is not set
719# CONFIG_NCPFS_NFS_NS is not set
720# CONFIG_NCPFS_OS2_NS is not set
721# CONFIG_NCPFS_SMALLDOS is not set
722CONFIG_NCPFS_NLS=y
723# CONFIG_NCPFS_EXTRAS is not set
724CONFIG_CODA_FS=m
725# CONFIG_CODA_FS_OLD_API is not set
726# CONFIG_AFS_FS is not set
727
728#
729# Partition Types
730#
731# CONFIG_PARTITION_ADVANCED is not set
732CONFIG_MSDOS_PARTITION=y
733CONFIG_SUN_PARTITION=y
734
735#
736# Native Language Support
737#
738CONFIG_NLS=y
739CONFIG_NLS_DEFAULT="iso8859-1"
740CONFIG_NLS_CODEPAGE_437=y
741CONFIG_NLS_CODEPAGE_737=m
742CONFIG_NLS_CODEPAGE_775=m
743CONFIG_NLS_CODEPAGE_850=m
744CONFIG_NLS_CODEPAGE_852=m
745CONFIG_NLS_CODEPAGE_855=m
746CONFIG_NLS_CODEPAGE_857=m
747CONFIG_NLS_CODEPAGE_860=m
748CONFIG_NLS_CODEPAGE_861=m
749CONFIG_NLS_CODEPAGE_862=m
750CONFIG_NLS_CODEPAGE_863=m
751CONFIG_NLS_CODEPAGE_864=m
752CONFIG_NLS_CODEPAGE_865=m
753CONFIG_NLS_CODEPAGE_866=m
754CONFIG_NLS_CODEPAGE_869=m
755CONFIG_NLS_CODEPAGE_936=m
756CONFIG_NLS_CODEPAGE_950=m
757CONFIG_NLS_CODEPAGE_932=m
758CONFIG_NLS_CODEPAGE_949=m
759CONFIG_NLS_CODEPAGE_874=m
760CONFIG_NLS_ISO8859_8=m
761CONFIG_NLS_CODEPAGE_1250=m
762CONFIG_NLS_CODEPAGE_1251=m
763CONFIG_NLS_ASCII=m
764CONFIG_NLS_ISO8859_1=y
765CONFIG_NLS_ISO8859_2=m
766CONFIG_NLS_ISO8859_3=m
767CONFIG_NLS_ISO8859_4=m
768CONFIG_NLS_ISO8859_5=m
769CONFIG_NLS_ISO8859_6=m
770CONFIG_NLS_ISO8859_7=m
771CONFIG_NLS_ISO8859_9=m
772CONFIG_NLS_ISO8859_13=m
773CONFIG_NLS_ISO8859_14=m
774CONFIG_NLS_ISO8859_15=m
775CONFIG_NLS_KOI8_R=m
776CONFIG_NLS_KOI8_U=m
777CONFIG_NLS_UTF8=m
778
779#
780# Kernel hacking
781#
782CONFIG_DEBUG_KERNEL=y
783CONFIG_MAGIC_SYSRQ=y
784# CONFIG_SCHEDSTATS is not set
785# CONFIG_DEBUG_SLAB is not set
786# CONFIG_DEBUG_KOBJECT is not set
787# CONFIG_DEBUG_BUGVERBOSE is not set
788# CONFIG_DEBUG_INFO is not set
789
790#
791# Security options
792#
793# CONFIG_KEYS is not set
794# CONFIG_SECURITY is not set
795
796#
797# Cryptographic options
798#
799CONFIG_CRYPTO=y
800CONFIG_CRYPTO_HMAC=y
801CONFIG_CRYPTO_NULL=m
802CONFIG_CRYPTO_MD4=m
803CONFIG_CRYPTO_MD5=y
804CONFIG_CRYPTO_SHA1=m
805CONFIG_CRYPTO_SHA256=m
806CONFIG_CRYPTO_SHA512=m
807# CONFIG_CRYPTO_WP512 is not set
808CONFIG_CRYPTO_DES=y
809CONFIG_CRYPTO_BLOWFISH=m
810CONFIG_CRYPTO_TWOFISH=m
811CONFIG_CRYPTO_SERPENT=m
812CONFIG_CRYPTO_AES=m
813CONFIG_CRYPTO_CAST5=m
814CONFIG_CRYPTO_CAST6=m
815CONFIG_CRYPTO_TEA=m
816CONFIG_CRYPTO_ARC4=m
817CONFIG_CRYPTO_KHAZAD=m
818CONFIG_CRYPTO_ANUBIS=m
819CONFIG_CRYPTO_DEFLATE=m
820CONFIG_CRYPTO_MICHAEL_MIC=m
821CONFIG_CRYPTO_CRC32C=m
822CONFIG_CRYPTO_TEST=m
823
824#
825# Library routines
826#
827CONFIG_CRC_CCITT=m
828CONFIG_CRC32=y
829CONFIG_LIBCRC32C=m
830CONFIG_ZLIB_INFLATE=y
831CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
new file mode 100644
index 000000000000..fe008c9b10c1
--- /dev/null
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -0,0 +1,841 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:24:05 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION="-sun3x"
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24CONFIG_POSIX_MQUEUE=y
25CONFIG_BSD_PROCESS_ACCT=y
26# CONFIG_BSD_PROCESS_ACCT_V3 is not set
27CONFIG_SYSCTL=y
28CONFIG_AUDIT=y
29CONFIG_LOG_BUF_SHIFT=16
30# CONFIG_HOTPLUG is not set
31CONFIG_KOBJECT_UEVENT=y
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35# CONFIG_KALLSYMS_ALL is not set
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
40CONFIG_SHMEM=y
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55# CONFIG_MODULE_SRCVERSION_ALL is not set
56CONFIG_KMOD=y
57
58#
59# Platform dependent setup
60#
61# CONFIG_SUN3 is not set
62# CONFIG_AMIGA is not set
63# CONFIG_ATARI is not set
64# CONFIG_MAC is not set
65# CONFIG_APOLLO is not set
66# CONFIG_VME is not set
67# CONFIG_HP300 is not set
68CONFIG_SUN3X=y
69# CONFIG_Q40 is not set
70
71#
72# Processor type
73#
74# CONFIG_M68020 is not set
75CONFIG_M68030=y
76# CONFIG_M68040 is not set
77# CONFIG_M68060 is not set
78CONFIG_MMU_MOTOROLA=y
79CONFIG_M68KFPU_EMU=y
80CONFIG_M68KFPU_EMU_EXTRAPREC=y
81# CONFIG_M68KFPU_EMU_ONLY is not set
82# CONFIG_ADVANCED is not set
83
84#
85# General setup
86#
87CONFIG_BINFMT_ELF=y
88CONFIG_BINFMT_AOUT=m
89CONFIG_BINFMT_MISC=m
90CONFIG_PROC_HARDWARE=y
91
92#
93# Device Drivers
94#
95
96#
97# Generic Driver Options
98#
99CONFIG_STANDALONE=y
100CONFIG_PREVENT_FIRMWARE_BUILD=y
101# CONFIG_DEBUG_DRIVER is not set
102
103#
104# Memory Technology Devices (MTD)
105#
106# CONFIG_MTD is not set
107
108#
109# Parallel port support
110#
111# CONFIG_PARPORT is not set
112
113#
114# Plug and Play support
115#
116
117#
118# Block devices
119#
120CONFIG_BLK_DEV_LOOP=y
121CONFIG_BLK_DEV_CRYPTOLOOP=m
122CONFIG_BLK_DEV_NBD=m
123CONFIG_BLK_DEV_RAM=y
124CONFIG_BLK_DEV_RAM_COUNT=16
125CONFIG_BLK_DEV_RAM_SIZE=4096
126CONFIG_BLK_DEV_INITRD=y
127CONFIG_INITRAMFS_SOURCE=""
128CONFIG_CDROM_PKTCDVD=m
129CONFIG_CDROM_PKTCDVD_BUFFERS=8
130# CONFIG_CDROM_PKTCDVD_WCACHE is not set
131
132#
133# IO Schedulers
134#
135CONFIG_IOSCHED_NOOP=y
136CONFIG_IOSCHED_AS=y
137CONFIG_IOSCHED_DEADLINE=y
138CONFIG_IOSCHED_CFQ=y
139
140#
141# ATA/ATAPI/MFM/RLL support
142#
143# CONFIG_IDE is not set
144
145#
146# SCSI device support
147#
148CONFIG_SCSI=y
149CONFIG_SCSI_PROC_FS=y
150
151#
152# SCSI support type (disk, tape, CD-ROM)
153#
154CONFIG_BLK_DEV_SD=y
155CONFIG_CHR_DEV_ST=m
156# CONFIG_CHR_DEV_OSST is not set
157CONFIG_BLK_DEV_SR=y
158CONFIG_BLK_DEV_SR_VENDOR=y
159CONFIG_CHR_DEV_SG=m
160
161#
162# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
163#
164# CONFIG_SCSI_MULTI_LUN is not set
165CONFIG_SCSI_CONSTANTS=y
166# CONFIG_SCSI_LOGGING is not set
167
168#
169# SCSI Transport Attributes
170#
171# CONFIG_SCSI_SPI_ATTRS is not set
172# CONFIG_SCSI_FC_ATTRS is not set
173
174#
175# SCSI low-level drivers
176#
177# CONFIG_SCSI_SATA is not set
178# CONFIG_SCSI_DEBUG is not set
179CONFIG_SUN3X_ESP=y
180
181#
182# Multi-device support (RAID and LVM)
183#
184CONFIG_MD=y
185CONFIG_BLK_DEV_MD=m
186CONFIG_MD_LINEAR=m
187CONFIG_MD_RAID0=m
188CONFIG_MD_RAID1=m
189# CONFIG_MD_RAID10 is not set
190CONFIG_MD_RAID5=m
191CONFIG_MD_RAID6=m
192CONFIG_MD_MULTIPATH=m
193# CONFIG_MD_FAULTY is not set
194CONFIG_BLK_DEV_DM=m
195CONFIG_DM_CRYPT=m
196CONFIG_DM_SNAPSHOT=m
197CONFIG_DM_MIRROR=m
198CONFIG_DM_ZERO=m
199
200#
201# Fusion MPT device support
202#
203
204#
205# IEEE 1394 (FireWire) support
206#
207
208#
209# I2O device support
210#
211
212#
213# Networking support
214#
215CONFIG_NET=y
216
217#
218# Networking options
219#
220CONFIG_PACKET=y
221# CONFIG_PACKET_MMAP is not set
222CONFIG_NETLINK_DEV=y
223CONFIG_UNIX=y
224CONFIG_NET_KEY=y
225CONFIG_INET=y
226# CONFIG_IP_MULTICAST is not set
227# CONFIG_IP_ADVANCED_ROUTER is not set
228CONFIG_IP_PNP=y
229CONFIG_IP_PNP_DHCP=y
230CONFIG_IP_PNP_BOOTP=y
231CONFIG_IP_PNP_RARP=y
232CONFIG_NET_IPIP=m
233CONFIG_NET_IPGRE=m
234# CONFIG_ARPD is not set
235CONFIG_SYN_COOKIES=y
236CONFIG_INET_AH=m
237CONFIG_INET_ESP=m
238CONFIG_INET_IPCOMP=m
239CONFIG_INET_TUNNEL=m
240CONFIG_IP_TCPDIAG=m
241CONFIG_IP_TCPDIAG_IPV6=y
242
243#
244# IP: Virtual Server Configuration
245#
246# CONFIG_IP_VS is not set
247CONFIG_IPV6=m
248CONFIG_IPV6_PRIVACY=y
249CONFIG_INET6_AH=m
250CONFIG_INET6_ESP=m
251CONFIG_INET6_IPCOMP=m
252CONFIG_INET6_TUNNEL=m
253CONFIG_IPV6_TUNNEL=m
254CONFIG_NETFILTER=y
255# CONFIG_NETFILTER_DEBUG is not set
256
257#
258# IP: Netfilter Configuration
259#
260CONFIG_IP_NF_CONNTRACK=m
261# CONFIG_IP_NF_CT_ACCT is not set
262CONFIG_IP_NF_CONNTRACK_MARK=y
263# CONFIG_IP_NF_CT_PROTO_SCTP is not set
264CONFIG_IP_NF_FTP=m
265CONFIG_IP_NF_IRC=m
266CONFIG_IP_NF_TFTP=m
267CONFIG_IP_NF_AMANDA=m
268CONFIG_IP_NF_QUEUE=m
269CONFIG_IP_NF_IPTABLES=m
270CONFIG_IP_NF_MATCH_LIMIT=m
271CONFIG_IP_NF_MATCH_IPRANGE=m
272CONFIG_IP_NF_MATCH_MAC=m
273CONFIG_IP_NF_MATCH_PKTTYPE=m
274CONFIG_IP_NF_MATCH_MARK=m
275CONFIG_IP_NF_MATCH_MULTIPORT=m
276CONFIG_IP_NF_MATCH_TOS=m
277CONFIG_IP_NF_MATCH_RECENT=m
278CONFIG_IP_NF_MATCH_ECN=m
279CONFIG_IP_NF_MATCH_DSCP=m
280CONFIG_IP_NF_MATCH_AH_ESP=m
281CONFIG_IP_NF_MATCH_LENGTH=m
282CONFIG_IP_NF_MATCH_TTL=m
283CONFIG_IP_NF_MATCH_TCPMSS=m
284CONFIG_IP_NF_MATCH_HELPER=m
285CONFIG_IP_NF_MATCH_STATE=m
286CONFIG_IP_NF_MATCH_CONNTRACK=m
287CONFIG_IP_NF_MATCH_OWNER=m
288CONFIG_IP_NF_MATCH_ADDRTYPE=m
289CONFIG_IP_NF_MATCH_REALM=m
290# CONFIG_IP_NF_MATCH_SCTP is not set
291# CONFIG_IP_NF_MATCH_COMMENT is not set
292CONFIG_IP_NF_MATCH_CONNMARK=m
293CONFIG_IP_NF_MATCH_HASHLIMIT=m
294CONFIG_IP_NF_FILTER=m
295CONFIG_IP_NF_TARGET_REJECT=m
296CONFIG_IP_NF_TARGET_LOG=m
297CONFIG_IP_NF_TARGET_ULOG=m
298CONFIG_IP_NF_TARGET_TCPMSS=m
299CONFIG_IP_NF_NAT=m
300CONFIG_IP_NF_NAT_NEEDED=y
301CONFIG_IP_NF_TARGET_MASQUERADE=m
302CONFIG_IP_NF_TARGET_REDIRECT=m
303CONFIG_IP_NF_TARGET_NETMAP=m
304CONFIG_IP_NF_TARGET_SAME=m
305CONFIG_IP_NF_NAT_SNMP_BASIC=m
306CONFIG_IP_NF_NAT_IRC=m
307CONFIG_IP_NF_NAT_FTP=m
308CONFIG_IP_NF_NAT_TFTP=m
309CONFIG_IP_NF_NAT_AMANDA=m
310CONFIG_IP_NF_MANGLE=m
311CONFIG_IP_NF_TARGET_TOS=m
312CONFIG_IP_NF_TARGET_ECN=m
313CONFIG_IP_NF_TARGET_DSCP=m
314CONFIG_IP_NF_TARGET_MARK=m
315CONFIG_IP_NF_TARGET_CLASSIFY=m
316CONFIG_IP_NF_TARGET_CONNMARK=m
317# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
318CONFIG_IP_NF_RAW=m
319CONFIG_IP_NF_TARGET_NOTRACK=m
320CONFIG_IP_NF_ARPTABLES=m
321CONFIG_IP_NF_ARPFILTER=m
322CONFIG_IP_NF_ARP_MANGLE=m
323CONFIG_IP_NF_COMPAT_IPCHAINS=m
324CONFIG_IP_NF_COMPAT_IPFWADM=m
325
326#
327# IPv6: Netfilter Configuration
328#
329CONFIG_IP6_NF_QUEUE=m
330CONFIG_IP6_NF_IPTABLES=m
331CONFIG_IP6_NF_MATCH_LIMIT=m
332CONFIG_IP6_NF_MATCH_MAC=m
333CONFIG_IP6_NF_MATCH_RT=m
334CONFIG_IP6_NF_MATCH_OPTS=m
335CONFIG_IP6_NF_MATCH_FRAG=m
336CONFIG_IP6_NF_MATCH_HL=m
337CONFIG_IP6_NF_MATCH_MULTIPORT=m
338CONFIG_IP6_NF_MATCH_OWNER=m
339CONFIG_IP6_NF_MATCH_MARK=m
340CONFIG_IP6_NF_MATCH_IPV6HEADER=m
341CONFIG_IP6_NF_MATCH_AHESP=m
342CONFIG_IP6_NF_MATCH_LENGTH=m
343CONFIG_IP6_NF_MATCH_EUI64=m
344CONFIG_IP6_NF_FILTER=m
345CONFIG_IP6_NF_TARGET_LOG=m
346CONFIG_IP6_NF_MANGLE=m
347CONFIG_IP6_NF_TARGET_MARK=m
348CONFIG_IP6_NF_RAW=m
349CONFIG_XFRM=y
350# CONFIG_XFRM_USER is not set
351
352#
353# SCTP Configuration (EXPERIMENTAL)
354#
355CONFIG_IP_SCTP=m
356# CONFIG_SCTP_DBG_MSG is not set
357# CONFIG_SCTP_DBG_OBJCNT is not set
358# CONFIG_SCTP_HMAC_NONE is not set
359# CONFIG_SCTP_HMAC_SHA1 is not set
360CONFIG_SCTP_HMAC_MD5=y
361# CONFIG_ATM is not set
362# CONFIG_BRIDGE is not set
363# CONFIG_VLAN_8021Q is not set
364# CONFIG_DECNET is not set
365CONFIG_LLC=m
366# CONFIG_LLC2 is not set
367CONFIG_IPX=m
368# CONFIG_IPX_INTERN is not set
369CONFIG_ATALK=m
370# CONFIG_DEV_APPLETALK is not set
371# CONFIG_X25 is not set
372# CONFIG_LAPB is not set
373# CONFIG_NET_DIVERT is not set
374# CONFIG_ECONET is not set
375# CONFIG_WAN_ROUTER is not set
376
377#
378# QoS and/or fair queueing
379#
380# CONFIG_NET_SCHED is not set
381CONFIG_NET_CLS_ROUTE=y
382
383#
384# Network testing
385#
386# CONFIG_NET_PKTGEN is not set
387CONFIG_NETPOLL=y
388# CONFIG_NETPOLL_RX is not set
389# CONFIG_NETPOLL_TRAP is not set
390CONFIG_NET_POLL_CONTROLLER=y
391# CONFIG_HAMRADIO is not set
392# CONFIG_IRDA is not set
393# CONFIG_BT is not set
394CONFIG_NETDEVICES=y
395CONFIG_DUMMY=m
396# CONFIG_BONDING is not set
397CONFIG_EQUALIZER=m
398# CONFIG_TUN is not set
399# CONFIG_ETHERTAP is not set
400
401#
402# Ethernet (10 or 100Mbit)
403#
404CONFIG_NET_ETHERNET=y
405CONFIG_MII=m
406CONFIG_SUN3LANCE=y
407
408#
409# Ethernet (1000 Mbit)
410#
411
412#
413# Ethernet (10000 Mbit)
414#
415
416#
417# Token Ring devices
418#
419
420#
421# Wireless LAN (non-hamradio)
422#
423# CONFIG_NET_RADIO is not set
424
425#
426# Wan interfaces
427#
428# CONFIG_WAN is not set
429CONFIG_PPP=m
430# CONFIG_PPP_MULTILINK is not set
431CONFIG_PPP_FILTER=y
432CONFIG_PPP_ASYNC=m
433CONFIG_PPP_SYNC_TTY=m
434CONFIG_PPP_DEFLATE=m
435CONFIG_PPP_BSDCOMP=m
436CONFIG_PPPOE=m
437CONFIG_SLIP=m
438CONFIG_SLIP_COMPRESSED=y
439CONFIG_SLIP_SMART=y
440CONFIG_SLIP_MODE_SLIP6=y
441CONFIG_SHAPER=m
442CONFIG_NETCONSOLE=m
443
444#
445# ISDN subsystem
446#
447# CONFIG_ISDN is not set
448
449#
450# Telephony Support
451#
452# CONFIG_PHONE is not set
453
454#
455# Input device support
456#
457CONFIG_INPUT=y
458
459#
460# Userland interfaces
461#
462CONFIG_INPUT_MOUSEDEV=y
463CONFIG_INPUT_MOUSEDEV_PSAUX=y
464CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
465CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
466# CONFIG_INPUT_JOYDEV is not set
467# CONFIG_INPUT_TSDEV is not set
468# CONFIG_INPUT_EVDEV is not set
469# CONFIG_INPUT_EVBUG is not set
470
471#
472# Input I/O drivers
473#
474# CONFIG_GAMEPORT is not set
475CONFIG_SOUND_GAMEPORT=y
476CONFIG_SERIO=y
477CONFIG_SERIO_SERPORT=m
478# CONFIG_SERIO_CT82C710 is not set
479# CONFIG_SERIO_RAW is not set
480
481#
482# Input Device Drivers
483#
484CONFIG_INPUT_KEYBOARD=y
485# CONFIG_KEYBOARD_ATKBD is not set
486CONFIG_KEYBOARD_SUNKBD=y
487# CONFIG_KEYBOARD_LKKBD is not set
488# CONFIG_KEYBOARD_XTKBD is not set
489# CONFIG_KEYBOARD_NEWTON is not set
490CONFIG_INPUT_MOUSE=y
491CONFIG_MOUSE_PS2=m
492CONFIG_MOUSE_SERIAL=m
493# CONFIG_MOUSE_VSXXXAA is not set
494# CONFIG_INPUT_JOYSTICK is not set
495# CONFIG_INPUT_TOUCHSCREEN is not set
496# CONFIG_INPUT_MISC is not set
497
498#
499# Character devices
500#
501CONFIG_VT=y
502CONFIG_VT_CONSOLE=y
503CONFIG_HW_CONSOLE=y
504# CONFIG_SERIAL_NONSTANDARD is not set
505
506#
507# Serial drivers
508#
509# CONFIG_SERIAL_8250 is not set
510
511#
512# Non-8250 serial port support
513#
514CONFIG_UNIX98_PTYS=y
515CONFIG_LEGACY_PTYS=y
516CONFIG_LEGACY_PTY_COUNT=256
517
518#
519# IPMI
520#
521# CONFIG_IPMI_HANDLER is not set
522
523#
524# Watchdog Cards
525#
526# CONFIG_WATCHDOG is not set
527CONFIG_GEN_RTC=y
528CONFIG_GEN_RTC_X=y
529# CONFIG_DTLK is not set
530# CONFIG_R3964 is not set
531
532#
533# Ftape, the floppy tape device driver
534#
535# CONFIG_DRM is not set
536# CONFIG_RAW_DRIVER is not set
537
538#
539# I2C support
540#
541# CONFIG_I2C is not set
542
543#
544# Dallas's 1-wire bus
545#
546# CONFIG_W1 is not set
547
548#
549# Misc devices
550#
551
552#
553# Multimedia devices
554#
555# CONFIG_VIDEO_DEV is not set
556
557#
558# Digital Video Broadcasting Devices
559#
560# CONFIG_DVB is not set
561
562#
563# Graphics support
564#
565CONFIG_FB=y
566CONFIG_FB_MODE_HELPERS=y
567# CONFIG_FB_TILEBLITTING is not set
568# CONFIG_FB_VIRTUAL is not set
569
570#
571# Console display driver support
572#
573CONFIG_DUMMY_CONSOLE=y
574CONFIG_FRAMEBUFFER_CONSOLE=y
575# CONFIG_FONTS is not set
576CONFIG_FONT_8x8=y
577CONFIG_FONT_8x16=y
578
579#
580# Logo configuration
581#
582CONFIG_LOGO=y
583CONFIG_LOGO_LINUX_MONO=y
584CONFIG_LOGO_LINUX_VGA16=y
585CONFIG_LOGO_LINUX_CLUT224=y
586
587#
588# Sound
589#
590# CONFIG_SOUND is not set
591
592#
593# USB support
594#
595# CONFIG_USB_ARCH_HAS_HCD is not set
596# CONFIG_USB_ARCH_HAS_OHCI is not set
597
598#
599# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
600#
601
602#
603# USB Gadget Support
604#
605# CONFIG_USB_GADGET is not set
606
607#
608# MMC/SD Card support
609#
610# CONFIG_MMC is not set
611
612#
613# Character devices
614#
615
616#
617# File systems
618#
619CONFIG_EXT2_FS=y
620# CONFIG_EXT2_FS_XATTR is not set
621CONFIG_EXT3_FS=y
622# CONFIG_EXT3_FS_XATTR is not set
623CONFIG_JBD=y
624# CONFIG_JBD_DEBUG is not set
625CONFIG_REISERFS_FS=m
626# CONFIG_REISERFS_CHECK is not set
627# CONFIG_REISERFS_PROC_INFO is not set
628# CONFIG_REISERFS_FS_XATTR is not set
629CONFIG_JFS_FS=m
630# CONFIG_JFS_POSIX_ACL is not set
631# CONFIG_JFS_DEBUG is not set
632# CONFIG_JFS_STATISTICS is not set
633CONFIG_FS_POSIX_ACL=y
634CONFIG_XFS_FS=m
635# CONFIG_XFS_RT is not set
636# CONFIG_XFS_QUOTA is not set
637# CONFIG_XFS_SECURITY is not set
638# CONFIG_XFS_POSIX_ACL is not set
639CONFIG_MINIX_FS=y
640# CONFIG_ROMFS_FS is not set
641CONFIG_QUOTA=y
642# CONFIG_QFMT_V1 is not set
643# CONFIG_QFMT_V2 is not set
644CONFIG_QUOTACTL=y
645CONFIG_DNOTIFY=y
646CONFIG_AUTOFS_FS=m
647CONFIG_AUTOFS4_FS=m
648
649#
650# CD-ROM/DVD Filesystems
651#
652CONFIG_ISO9660_FS=y
653CONFIG_JOLIET=y
654CONFIG_ZISOFS=y
655CONFIG_ZISOFS_FS=y
656CONFIG_UDF_FS=m
657CONFIG_UDF_NLS=y
658
659#
660# DOS/FAT/NT Filesystems
661#
662CONFIG_FAT_FS=y
663CONFIG_MSDOS_FS=y
664CONFIG_VFAT_FS=m
665CONFIG_FAT_DEFAULT_CODEPAGE=437
666CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
667# CONFIG_NTFS_FS is not set
668
669#
670# Pseudo filesystems
671#
672CONFIG_PROC_FS=y
673CONFIG_PROC_KCORE=y
674CONFIG_SYSFS=y
675CONFIG_DEVFS_FS=y
676CONFIG_DEVFS_MOUNT=y
677# CONFIG_DEVFS_DEBUG is not set
678# CONFIG_DEVPTS_FS_XATTR is not set
679CONFIG_TMPFS=y
680# CONFIG_TMPFS_XATTR is not set
681# CONFIG_HUGETLB_PAGE is not set
682CONFIG_RAMFS=y
683
684#
685# Miscellaneous filesystems
686#
687# CONFIG_ADFS_FS is not set
688CONFIG_AFFS_FS=m
689CONFIG_HFS_FS=m
690CONFIG_HFSPLUS_FS=m
691# CONFIG_BEFS_FS is not set
692# CONFIG_BFS_FS is not set
693# CONFIG_EFS_FS is not set
694CONFIG_CRAMFS=m
695# CONFIG_VXFS_FS is not set
696CONFIG_HPFS_FS=m
697# CONFIG_QNX4FS_FS is not set
698CONFIG_SYSV_FS=m
699CONFIG_UFS_FS=m
700CONFIG_UFS_FS_WRITE=y
701
702#
703# Network File Systems
704#
705CONFIG_NFS_FS=y
706CONFIG_NFS_V3=y
707CONFIG_NFS_V4=y
708# CONFIG_NFS_DIRECTIO is not set
709CONFIG_NFSD=m
710CONFIG_NFSD_V3=y
711CONFIG_NFSD_V4=y
712CONFIG_NFSD_TCP=y
713CONFIG_ROOT_NFS=y
714CONFIG_LOCKD=y
715CONFIG_LOCKD_V4=y
716CONFIG_EXPORTFS=m
717CONFIG_SUNRPC=y
718CONFIG_SUNRPC_GSS=y
719CONFIG_RPCSEC_GSS_KRB5=y
720# CONFIG_RPCSEC_GSS_SPKM3 is not set
721CONFIG_SMB_FS=m
722CONFIG_SMB_NLS_DEFAULT=y
723CONFIG_SMB_NLS_REMOTE="cp437"
724# CONFIG_CIFS is not set
725CONFIG_NCP_FS=m
726# CONFIG_NCPFS_PACKET_SIGNING is not set
727# CONFIG_NCPFS_IOCTL_LOCKING is not set
728# CONFIG_NCPFS_STRONG is not set
729# CONFIG_NCPFS_NFS_NS is not set
730# CONFIG_NCPFS_OS2_NS is not set
731# CONFIG_NCPFS_SMALLDOS is not set
732CONFIG_NCPFS_NLS=y
733# CONFIG_NCPFS_EXTRAS is not set
734CONFIG_CODA_FS=m
735# CONFIG_CODA_FS_OLD_API is not set
736# CONFIG_AFS_FS is not set
737
738#
739# Partition Types
740#
741# CONFIG_PARTITION_ADVANCED is not set
742CONFIG_MSDOS_PARTITION=y
743CONFIG_SUN_PARTITION=y
744
745#
746# Native Language Support
747#
748CONFIG_NLS=y
749CONFIG_NLS_DEFAULT="iso8859-1"
750CONFIG_NLS_CODEPAGE_437=y
751CONFIG_NLS_CODEPAGE_737=m
752CONFIG_NLS_CODEPAGE_775=m
753CONFIG_NLS_CODEPAGE_850=m
754CONFIG_NLS_CODEPAGE_852=m
755CONFIG_NLS_CODEPAGE_855=m
756CONFIG_NLS_CODEPAGE_857=m
757CONFIG_NLS_CODEPAGE_860=m
758CONFIG_NLS_CODEPAGE_861=m
759CONFIG_NLS_CODEPAGE_862=m
760CONFIG_NLS_CODEPAGE_863=m
761CONFIG_NLS_CODEPAGE_864=m
762CONFIG_NLS_CODEPAGE_865=m
763CONFIG_NLS_CODEPAGE_866=m
764CONFIG_NLS_CODEPAGE_869=m
765CONFIG_NLS_CODEPAGE_936=m
766CONFIG_NLS_CODEPAGE_950=m
767CONFIG_NLS_CODEPAGE_932=m
768CONFIG_NLS_CODEPAGE_949=m
769CONFIG_NLS_CODEPAGE_874=m
770CONFIG_NLS_ISO8859_8=m
771CONFIG_NLS_CODEPAGE_1250=m
772CONFIG_NLS_CODEPAGE_1251=m
773CONFIG_NLS_ASCII=m
774CONFIG_NLS_ISO8859_1=y
775CONFIG_NLS_ISO8859_2=m
776CONFIG_NLS_ISO8859_3=m
777CONFIG_NLS_ISO8859_4=m
778CONFIG_NLS_ISO8859_5=m
779CONFIG_NLS_ISO8859_6=m
780CONFIG_NLS_ISO8859_7=m
781CONFIG_NLS_ISO8859_9=m
782CONFIG_NLS_ISO8859_13=m
783CONFIG_NLS_ISO8859_14=m
784CONFIG_NLS_ISO8859_15=m
785CONFIG_NLS_KOI8_R=m
786CONFIG_NLS_KOI8_U=m
787CONFIG_NLS_UTF8=m
788
789#
790# Kernel hacking
791#
792CONFIG_DEBUG_KERNEL=y
793CONFIG_MAGIC_SYSRQ=y
794# CONFIG_SCHEDSTATS is not set
795# CONFIG_DEBUG_SLAB is not set
796# CONFIG_DEBUG_KOBJECT is not set
797# CONFIG_DEBUG_BUGVERBOSE is not set
798# CONFIG_DEBUG_INFO is not set
799
800#
801# Security options
802#
803# CONFIG_KEYS is not set
804# CONFIG_SECURITY is not set
805
806#
807# Cryptographic options
808#
809CONFIG_CRYPTO=y
810CONFIG_CRYPTO_HMAC=y
811CONFIG_CRYPTO_NULL=m
812CONFIG_CRYPTO_MD4=m
813CONFIG_CRYPTO_MD5=y
814CONFIG_CRYPTO_SHA1=m
815CONFIG_CRYPTO_SHA256=m
816CONFIG_CRYPTO_SHA512=m
817# CONFIG_CRYPTO_WP512 is not set
818CONFIG_CRYPTO_DES=y
819CONFIG_CRYPTO_BLOWFISH=m
820CONFIG_CRYPTO_TWOFISH=m
821CONFIG_CRYPTO_SERPENT=m
822CONFIG_CRYPTO_AES=m
823CONFIG_CRYPTO_CAST5=m
824CONFIG_CRYPTO_CAST6=m
825CONFIG_CRYPTO_TEA=m
826CONFIG_CRYPTO_ARC4=m
827CONFIG_CRYPTO_KHAZAD=m
828CONFIG_CRYPTO_ANUBIS=m
829CONFIG_CRYPTO_DEFLATE=m
830CONFIG_CRYPTO_MICHAEL_MIC=m
831CONFIG_CRYPTO_CRC32C=m
832CONFIG_CRYPTO_TEST=m
833
834#
835# Library routines
836#
837CONFIG_CRC_CCITT=m
838CONFIG_CRC32=y
839CONFIG_LIBCRC32C=m
840CONFIG_ZLIB_INFLATE=y
841CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig
new file mode 100644
index 000000000000..78f57d398340
--- /dev/null
+++ b/arch/m68k/defconfig
@@ -0,0 +1,629 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-m68k
4# Sun Dec 26 11:23:36 2004
5#
6CONFIG_M68K=y
7CONFIG_MMU=y
8CONFIG_UID16=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
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_POSIX_MQUEUE is not set
25# CONFIG_BSD_PROCESS_ACCT is not set
26CONFIG_SYSCTL=y
27# CONFIG_AUDIT is not set
28CONFIG_LOG_BUF_SHIFT=14
29# CONFIG_HOTPLUG is not set
30CONFIG_KOBJECT_UEVENT=y
31# CONFIG_IKCONFIG is not set
32# CONFIG_EMBEDDED is not set
33CONFIG_KALLSYMS=y
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#
48# CONFIG_MODULES is not set
49
50#
51# Platform dependent setup
52#
53# CONFIG_SUN3 is not set
54CONFIG_AMIGA=y
55# CONFIG_ATARI is not set
56# CONFIG_MAC is not set
57# CONFIG_APOLLO is not set
58# CONFIG_VME is not set
59# CONFIG_HP300 is not set
60# CONFIG_SUN3X is not set
61# CONFIG_Q40 is not set
62
63#
64# Processor type
65#
66CONFIG_M68020=y
67CONFIG_M68030=y
68CONFIG_M68040=y
69# CONFIG_M68060 is not set
70CONFIG_MMU_MOTOROLA=y
71# CONFIG_M68KFPU_EMU is not set
72# CONFIG_ADVANCED is not set
73
74#
75# General setup
76#
77CONFIG_BINFMT_ELF=y
78CONFIG_BINFMT_AOUT=y
79# CONFIG_BINFMT_MISC is not set
80CONFIG_ZORRO=y
81# CONFIG_AMIGA_PCMCIA is not set
82# CONFIG_HEARTBEAT is not set
83CONFIG_PROC_HARDWARE=y
84# CONFIG_ZORRO_NAMES is not set
85
86#
87# Device Drivers
88#
89
90#
91# Generic Driver Options
92#
93CONFIG_STANDALONE=y
94CONFIG_PREVENT_FIRMWARE_BUILD=y
95
96#
97# Memory Technology Devices (MTD)
98#
99# CONFIG_MTD is not set
100
101#
102# Parallel port support
103#
104# CONFIG_PARPORT is not set
105
106#
107# Plug and Play support
108#
109
110#
111# Block devices
112#
113CONFIG_AMIGA_FLOPPY=y
114# CONFIG_AMIGA_Z2RAM is not set
115# CONFIG_BLK_DEV_LOOP is not set
116# CONFIG_BLK_DEV_NBD is not set
117CONFIG_BLK_DEV_RAM=y
118CONFIG_BLK_DEV_RAM_COUNT=16
119CONFIG_BLK_DEV_RAM_SIZE=4096
120CONFIG_BLK_DEV_INITRD=y
121CONFIG_INITRAMFS_SOURCE=""
122CONFIG_CDROM_PKTCDVD=y
123CONFIG_CDROM_PKTCDVD_BUFFERS=8
124# CONFIG_CDROM_PKTCDVD_WCACHE is not set
125
126#
127# IO Schedulers
128#
129CONFIG_IOSCHED_NOOP=y
130CONFIG_IOSCHED_AS=y
131CONFIG_IOSCHED_DEADLINE=y
132CONFIG_IOSCHED_CFQ=y
133
134#
135# ATA/ATAPI/MFM/RLL support
136#
137# CONFIG_IDE is not set
138
139#
140# SCSI device support
141#
142CONFIG_SCSI=y
143CONFIG_SCSI_PROC_FS=y
144
145#
146# SCSI support type (disk, tape, CD-ROM)
147#
148CONFIG_BLK_DEV_SD=y
149CONFIG_CHR_DEV_ST=y
150# CONFIG_CHR_DEV_OSST is not set
151CONFIG_BLK_DEV_SR=y
152# CONFIG_BLK_DEV_SR_VENDOR is not set
153# CONFIG_CHR_DEV_SG is not set
154
155#
156# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
157#
158# CONFIG_SCSI_MULTI_LUN is not set
159CONFIG_SCSI_CONSTANTS=y
160# CONFIG_SCSI_LOGGING is not set
161
162#
163# SCSI Transport Attributes
164#
165# CONFIG_SCSI_SPI_ATTRS is not set
166# CONFIG_SCSI_FC_ATTRS is not set
167
168#
169# SCSI low-level drivers
170#
171# CONFIG_SCSI_SATA is not set
172# CONFIG_SCSI_DEBUG is not set
173CONFIG_A3000_SCSI=y
174CONFIG_A2091_SCSI=y
175CONFIG_GVP11_SCSI=y
176# CONFIG_CYBERSTORM_SCSI is not set
177# CONFIG_CYBERSTORMII_SCSI is not set
178# CONFIG_BLZ2060_SCSI is not set
179# CONFIG_BLZ1230_SCSI is not set
180# CONFIG_FASTLANE_SCSI is not set
181# CONFIG_OKTAGON_SCSI is not set
182
183#
184# Multi-device support (RAID and LVM)
185#
186# CONFIG_MD is not set
187
188#
189# Fusion MPT device support
190#
191
192#
193# IEEE 1394 (FireWire) support
194#
195
196#
197# I2O device support
198#
199
200#
201# Networking support
202#
203CONFIG_NET=y
204
205#
206# Networking options
207#
208CONFIG_PACKET=y
209# CONFIG_PACKET_MMAP is not set
210# CONFIG_NETLINK_DEV is not set
211CONFIG_UNIX=y
212# CONFIG_NET_KEY is not set
213CONFIG_INET=y
214# CONFIG_IP_MULTICAST is not set
215# CONFIG_IP_ADVANCED_ROUTER is not set
216# CONFIG_IP_PNP is not set
217# CONFIG_NET_IPIP is not set
218# CONFIG_NET_IPGRE is not set
219# CONFIG_ARPD is not set
220# CONFIG_SYN_COOKIES is not set
221# CONFIG_INET_AH is not set
222# CONFIG_INET_ESP is not set
223# CONFIG_INET_IPCOMP is not set
224# CONFIG_INET_TUNNEL is not set
225CONFIG_IP_TCPDIAG=y
226# CONFIG_IP_TCPDIAG_IPV6 is not set
227# CONFIG_IPV6 is not set
228# CONFIG_NETFILTER is not set
229
230#
231# SCTP Configuration (EXPERIMENTAL)
232#
233# CONFIG_IP_SCTP is not set
234# CONFIG_ATM is not set
235# CONFIG_BRIDGE is not set
236# CONFIG_VLAN_8021Q is not set
237# CONFIG_DECNET is not set
238# CONFIG_LLC2 is not set
239# CONFIG_IPX is not set
240# CONFIG_ATALK is not set
241# CONFIG_X25 is not set
242# CONFIG_LAPB is not set
243# CONFIG_NET_DIVERT is not set
244# CONFIG_ECONET is not set
245# CONFIG_WAN_ROUTER is not set
246
247#
248# QoS and/or fair queueing
249#
250# CONFIG_NET_SCHED is not set
251# CONFIG_NET_CLS_ROUTE is not set
252
253#
254# Network testing
255#
256# CONFIG_NET_PKTGEN is not set
257# CONFIG_NETPOLL is not set
258# CONFIG_NET_POLL_CONTROLLER is not set
259# CONFIG_HAMRADIO is not set
260# CONFIG_IRDA is not set
261# CONFIG_BT is not set
262CONFIG_NETDEVICES=y
263# CONFIG_DUMMY is not set
264# CONFIG_BONDING is not set
265# CONFIG_EQUALIZER is not set
266# CONFIG_TUN is not set
267
268#
269# Ethernet (10 or 100Mbit)
270#
271# CONFIG_NET_ETHERNET is not set
272
273#
274# Ethernet (1000 Mbit)
275#
276
277#
278# Ethernet (10000 Mbit)
279#
280
281#
282# Token Ring devices
283#
284
285#
286# Wireless LAN (non-hamradio)
287#
288# CONFIG_NET_RADIO is not set
289
290#
291# Wan interfaces
292#
293# CONFIG_WAN is not set
294# CONFIG_PPP is not set
295# CONFIG_SLIP is not set
296# CONFIG_SHAPER is not set
297# CONFIG_NETCONSOLE is not set
298
299#
300# ISDN subsystem
301#
302# CONFIG_ISDN is not set
303
304#
305# Telephony Support
306#
307# CONFIG_PHONE is not set
308
309#
310# Input device support
311#
312CONFIG_INPUT=y
313
314#
315# Userland interfaces
316#
317CONFIG_INPUT_MOUSEDEV=y
318CONFIG_INPUT_MOUSEDEV_PSAUX=y
319CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
320CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
321# CONFIG_INPUT_JOYDEV is not set
322# CONFIG_INPUT_TSDEV is not set
323# CONFIG_INPUT_EVDEV is not set
324# CONFIG_INPUT_EVBUG is not set
325
326#
327# Input I/O drivers
328#
329# CONFIG_GAMEPORT is not set
330CONFIG_SOUND_GAMEPORT=y
331CONFIG_SERIO=y
332CONFIG_SERIO_SERPORT=y
333# CONFIG_SERIO_CT82C710 is not set
334# CONFIG_SERIO_RAW is not set
335
336#
337# Input Device Drivers
338#
339CONFIG_INPUT_KEYBOARD=y
340CONFIG_KEYBOARD_ATKBD=y
341# CONFIG_KEYBOARD_SUNKBD is not set
342# CONFIG_KEYBOARD_LKKBD is not set
343# CONFIG_KEYBOARD_XTKBD is not set
344# CONFIG_KEYBOARD_NEWTON is not set
345# CONFIG_KEYBOARD_AMIGA is not set
346CONFIG_INPUT_MOUSE=y
347CONFIG_MOUSE_PS2=y
348# CONFIG_MOUSE_SERIAL is not set
349# CONFIG_MOUSE_AMIGA is not set
350# CONFIG_MOUSE_VSXXXAA is not set
351# CONFIG_INPUT_JOYSTICK is not set
352# CONFIG_INPUT_TOUCHSCREEN is not set
353# CONFIG_INPUT_MISC is not set
354
355#
356# Character devices
357#
358CONFIG_VT=y
359CONFIG_VT_CONSOLE=y
360CONFIG_HW_CONSOLE=y
361# CONFIG_SERIAL_NONSTANDARD is not set
362# CONFIG_A2232 is not set
363
364#
365# Serial drivers
366#
367# CONFIG_SERIAL_8250 is not set
368
369#
370# Non-8250 serial port support
371#
372CONFIG_UNIX98_PTYS=y
373CONFIG_LEGACY_PTYS=y
374CONFIG_LEGACY_PTY_COUNT=256
375
376#
377# IPMI
378#
379# CONFIG_IPMI_HANDLER is not set
380
381#
382# Watchdog Cards
383#
384# CONFIG_WATCHDOG is not set
385# CONFIG_GEN_RTC is not set
386# CONFIG_DTLK is not set
387# CONFIG_R3964 is not set
388
389#
390# Ftape, the floppy tape device driver
391#
392# CONFIG_DRM is not set
393# CONFIG_RAW_DRIVER is not set
394
395#
396# I2C support
397#
398# CONFIG_I2C is not set
399
400#
401# Dallas's 1-wire bus
402#
403# CONFIG_W1 is not set
404
405#
406# Misc devices
407#
408
409#
410# Multimedia devices
411#
412# CONFIG_VIDEO_DEV is not set
413
414#
415# Digital Video Broadcasting Devices
416#
417# CONFIG_DVB is not set
418
419#
420# Graphics support
421#
422CONFIG_FB=y
423CONFIG_FB_MODE_HELPERS=y
424# CONFIG_FB_TILEBLITTING is not set
425# CONFIG_FB_CIRRUS is not set
426CONFIG_FB_AMIGA=y
427CONFIG_FB_AMIGA_OCS=y
428CONFIG_FB_AMIGA_ECS=y
429CONFIG_FB_AMIGA_AGA=y
430# CONFIG_FB_FM2 is not set
431# CONFIG_FB_VIRTUAL is not set
432
433#
434# Console display driver support
435#
436CONFIG_DUMMY_CONSOLE=y
437# CONFIG_FRAMEBUFFER_CONSOLE is not set
438
439#
440# Logo configuration
441#
442# CONFIG_LOGO is not set
443
444#
445# Sound
446#
447# CONFIG_SOUND is not set
448
449#
450# USB support
451#
452# CONFIG_USB_ARCH_HAS_HCD is not set
453# CONFIG_USB_ARCH_HAS_OHCI is not set
454
455#
456# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
457#
458
459#
460# USB Gadget Support
461#
462# CONFIG_USB_GADGET is not set
463
464#
465# MMC/SD Card support
466#
467# CONFIG_MMC is not set
468
469#
470# Character devices
471#
472CONFIG_AMIGA_BUILTIN_SERIAL=y
473# CONFIG_MULTIFACE_III_TTY is not set
474# CONFIG_GVPIOEXT is not set
475# CONFIG_SERIAL_CONSOLE is not set
476
477#
478# File systems
479#
480CONFIG_EXT2_FS=y
481# CONFIG_EXT2_FS_XATTR is not set
482# CONFIG_EXT3_FS is not set
483# CONFIG_JBD is not set
484# CONFIG_REISERFS_FS is not set
485# CONFIG_JFS_FS is not set
486# CONFIG_XFS_FS is not set
487CONFIG_MINIX_FS=y
488# CONFIG_ROMFS_FS is not set
489# CONFIG_QUOTA is not set
490CONFIG_DNOTIFY=y
491# CONFIG_AUTOFS_FS is not set
492# CONFIG_AUTOFS4_FS is not set
493
494#
495# CD-ROM/DVD Filesystems
496#
497# CONFIG_ISO9660_FS is not set
498# CONFIG_UDF_FS is not set
499
500#
501# DOS/FAT/NT Filesystems
502#
503CONFIG_FAT_FS=y
504CONFIG_MSDOS_FS=y
505# CONFIG_VFAT_FS is not set
506CONFIG_FAT_DEFAULT_CODEPAGE=437
507# CONFIG_NTFS_FS is not set
508
509#
510# Pseudo filesystems
511#
512CONFIG_PROC_FS=y
513CONFIG_PROC_KCORE=y
514CONFIG_SYSFS=y
515# CONFIG_DEVFS_FS is not set
516# CONFIG_DEVPTS_FS_XATTR is not set
517# CONFIG_TMPFS is not set
518# CONFIG_HUGETLB_PAGE is not set
519CONFIG_RAMFS=y
520
521#
522# Miscellaneous filesystems
523#
524# CONFIG_ADFS_FS is not set
525# CONFIG_AFFS_FS is not set
526# CONFIG_HFS_FS is not set
527# CONFIG_HFSPLUS_FS is not set
528# CONFIG_BEFS_FS is not set
529# CONFIG_BFS_FS is not set
530# CONFIG_EFS_FS is not set
531# CONFIG_CRAMFS is not set
532# CONFIG_VXFS_FS is not set
533# CONFIG_HPFS_FS is not set
534# CONFIG_QNX4FS_FS is not set
535# CONFIG_SYSV_FS is not set
536# CONFIG_UFS_FS is not set
537
538#
539# Network File Systems
540#
541CONFIG_NFS_FS=y
542# CONFIG_NFS_V3 is not set
543# CONFIG_NFS_V4 is not set
544# CONFIG_NFS_DIRECTIO is not set
545# CONFIG_NFSD is not set
546CONFIG_LOCKD=y
547# CONFIG_EXPORTFS is not set
548CONFIG_SUNRPC=y
549# CONFIG_RPCSEC_GSS_KRB5 is not set
550# CONFIG_RPCSEC_GSS_SPKM3 is not set
551# CONFIG_SMB_FS is not set
552# CONFIG_CIFS is not set
553# CONFIG_NCP_FS is not set
554# CONFIG_CODA_FS is not set
555# CONFIG_AFS_FS is not set
556
557#
558# Partition Types
559#
560# CONFIG_PARTITION_ADVANCED is not set
561CONFIG_AMIGA_PARTITION=y
562CONFIG_MSDOS_PARTITION=y
563
564#
565# Native Language Support
566#
567CONFIG_NLS=y
568CONFIG_NLS_DEFAULT="iso8859-1"
569CONFIG_NLS_CODEPAGE_437=y
570# CONFIG_NLS_CODEPAGE_737 is not set
571# CONFIG_NLS_CODEPAGE_775 is not set
572# CONFIG_NLS_CODEPAGE_850 is not set
573# CONFIG_NLS_CODEPAGE_852 is not set
574# CONFIG_NLS_CODEPAGE_855 is not set
575# CONFIG_NLS_CODEPAGE_857 is not set
576# CONFIG_NLS_CODEPAGE_860 is not set
577# CONFIG_NLS_CODEPAGE_861 is not set
578# CONFIG_NLS_CODEPAGE_862 is not set
579# CONFIG_NLS_CODEPAGE_863 is not set
580# CONFIG_NLS_CODEPAGE_864 is not set
581# CONFIG_NLS_CODEPAGE_865 is not set
582# CONFIG_NLS_CODEPAGE_866 is not set
583# CONFIG_NLS_CODEPAGE_869 is not set
584# CONFIG_NLS_CODEPAGE_936 is not set
585# CONFIG_NLS_CODEPAGE_950 is not set
586# CONFIG_NLS_CODEPAGE_932 is not set
587# CONFIG_NLS_CODEPAGE_949 is not set
588# CONFIG_NLS_CODEPAGE_874 is not set
589# CONFIG_NLS_ISO8859_8 is not set
590# CONFIG_NLS_CODEPAGE_1250 is not set
591# CONFIG_NLS_CODEPAGE_1251 is not set
592# CONFIG_NLS_ASCII is not set
593# CONFIG_NLS_ISO8859_1 is not set
594# CONFIG_NLS_ISO8859_2 is not set
595# CONFIG_NLS_ISO8859_3 is not set
596# CONFIG_NLS_ISO8859_4 is not set
597# CONFIG_NLS_ISO8859_5 is not set
598# CONFIG_NLS_ISO8859_6 is not set
599# CONFIG_NLS_ISO8859_7 is not set
600# CONFIG_NLS_ISO8859_9 is not set
601# CONFIG_NLS_ISO8859_13 is not set
602# CONFIG_NLS_ISO8859_14 is not set
603# CONFIG_NLS_ISO8859_15 is not set
604# CONFIG_NLS_KOI8_R is not set
605# CONFIG_NLS_KOI8_U is not set
606# CONFIG_NLS_UTF8 is not set
607
608#
609# Kernel hacking
610#
611# CONFIG_DEBUG_KERNEL is not set
612
613#
614# Security options
615#
616# CONFIG_KEYS is not set
617# CONFIG_SECURITY is not set
618
619#
620# Cryptographic options
621#
622# CONFIG_CRYPTO is not set
623
624#
625# Library routines
626#
627# CONFIG_CRC_CCITT is not set
628CONFIG_CRC32=y
629# CONFIG_LIBCRC32C is not set
diff --git a/arch/m68k/fpsp040/Makefile b/arch/m68k/fpsp040/Makefile
new file mode 100644
index 000000000000..0214d2f6f8b0
--- /dev/null
+++ b/arch/m68k/fpsp040/Makefile
@@ -0,0 +1,16 @@
1#
2# Makefile for Linux arch/m68k/fpsp040 source directory
3#
4
5obj-y := bindec.o binstr.o decbin.o do_func.o gen_except.o get_op.o \
6 kernel_ex.o res_func.o round.o sacos.o sasin.o satan.o satanh.o \
7 scosh.o setox.o sgetem.o sint.o slog2.o slogn.o \
8 smovecr.o srem_mod.o scale.o \
9 ssin.o ssinh.o stan.o stanh.o sto_res.o stwotox.o tbldo.o util.o \
10 x_bsun.o x_fline.o x_operr.o x_ovfl.o x_snan.o x_store.o \
11 x_unfl.o x_unimp.o x_unsupp.o bugfix.o skeleton.o
12
13EXTRA_AFLAGS := -traditional
14EXTRA_LDFLAGS := -x
15
16$(OS_OBJS): fpsp.h
diff --git a/arch/m68k/fpsp040/README b/arch/m68k/fpsp040/README
new file mode 100644
index 000000000000..f5749446033e
--- /dev/null
+++ b/arch/m68k/fpsp040/README
@@ -0,0 +1,30 @@
1
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68040 Software Package
5
6M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
7All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
13PARTICULAR PURPOSE and any warranty against infringement with
14regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
15and any accompanying written materials.
16
17To the maximum extent permitted by applicable law,
18IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
19(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
20PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
21OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
22SOFTWARE. Motorola assumes no responsibility for the maintenance
23and support of the SOFTWARE.
24
25You are hereby granted a copyright license to use, modify, and
26distribute the SOFTWARE so long as this entire notice is retained
27without alteration in any modified and/or redistributed versions,
28and that such modified versions are clearly identified as such.
29No licenses are granted by implication, estoppel or otherwise
30under any patents or trademarks of Motorola, Inc.
diff --git a/arch/m68k/fpsp040/bindec.S b/arch/m68k/fpsp040/bindec.S
new file mode 100644
index 000000000000..3ba446a99a12
--- /dev/null
+++ b/arch/m68k/fpsp040/bindec.S
@@ -0,0 +1,920 @@
1|
2| bindec.sa 3.4 1/3/91
3|
4| bindec
5|
6| Description:
7| Converts an input in extended precision format
8| to bcd format.
9|
10| Input:
11| a0 points to the input extended precision value
12| value in memory; d0 contains the k-factor sign-extended
13| to 32-bits. The input may be either normalized,
14| unnormalized, or denormalized.
15|
16| Output: result in the FP_SCR1 space on the stack.
17|
18| Saves and Modifies: D2-D7,A2,FP2
19|
20| Algorithm:
21|
22| A1. Set RM and size ext; Set SIGMA = sign of input.
23| The k-factor is saved for use in d7. Clear the
24| BINDEC_FLG for separating normalized/denormalized
25| input. If input is unnormalized or denormalized,
26| normalize it.
27|
28| A2. Set X = abs(input).
29|
30| A3. Compute ILOG.
31| ILOG is the log base 10 of the input value. It is
32| approximated by adding e + 0.f when the original
33| value is viewed as 2^^e * 1.f in extended precision.
34| This value is stored in d6.
35|
36| A4. Clr INEX bit.
37| The operation in A3 above may have set INEX2.
38|
39| A5. Set ICTR = 0;
40| ICTR is a flag used in A13. It must be set before the
41| loop entry A6.
42|
43| A6. Calculate LEN.
44| LEN is the number of digits to be displayed. The
45| k-factor can dictate either the total number of digits,
46| if it is a positive number, or the number of digits
47| after the decimal point which are to be included as
48| significant. See the 68882 manual for examples.
49| If LEN is computed to be greater than 17, set OPERR in
50| USER_FPSR. LEN is stored in d4.
51|
52| A7. Calculate SCALE.
53| SCALE is equal to 10^ISCALE, where ISCALE is the number
54| of decimal places needed to insure LEN integer digits
55| in the output before conversion to bcd. LAMBDA is the
56| sign of ISCALE, used in A9. Fp1 contains
57| 10^^(abs(ISCALE)) using a rounding mode which is a
58| function of the original rounding mode and the signs
59| of ISCALE and X. A table is given in the code.
60|
61| A8. Clr INEX; Force RZ.
62| The operation in A3 above may have set INEX2.
63| RZ mode is forced for the scaling operation to insure
64| only one rounding error. The grs bits are collected in
65| the INEX flag for use in A10.
66|
67| A9. Scale X -> Y.
68| The mantissa is scaled to the desired number of
69| significant digits. The excess digits are collected
70| in INEX2.
71|
72| A10. Or in INEX.
73| If INEX is set, round error occurred. This is
74| compensated for by 'or-ing' in the INEX2 flag to
75| the lsb of Y.
76|
77| A11. Restore original FPCR; set size ext.
78| Perform FINT operation in the user's rounding mode.
79| Keep the size to extended.
80|
81| A12. Calculate YINT = FINT(Y) according to user's rounding
82| mode. The FPSP routine sintd0 is used. The output
83| is in fp0.
84|
85| A13. Check for LEN digits.
86| If the int operation results in more than LEN digits,
87| or less than LEN -1 digits, adjust ILOG and repeat from
88| A6. This test occurs only on the first pass. If the
89| result is exactly 10^LEN, decrement ILOG and divide
90| the mantissa by 10.
91|
92| A14. Convert the mantissa to bcd.
93| The binstr routine is used to convert the LEN digit
94| mantissa to bcd in memory. The input to binstr is
95| to be a fraction; i.e. (mantissa)/10^LEN and adjusted
96| such that the decimal point is to the left of bit 63.
97| The bcd digits are stored in the correct position in
98| the final string area in memory.
99|
100| A15. Convert the exponent to bcd.
101| As in A14 above, the exp is converted to bcd and the
102| digits are stored in the final string.
103| Test the length of the final exponent string. If the
104| length is 4, set operr.
105|
106| A16. Write sign bits to final string.
107|
108| Implementation Notes:
109|
110| The registers are used as follows:
111|
112| d0: scratch; LEN input to binstr
113| d1: scratch
114| d2: upper 32-bits of mantissa for binstr
115| d3: scratch;lower 32-bits of mantissa for binstr
116| d4: LEN
117| d5: LAMBDA/ICTR
118| d6: ILOG
119| d7: k-factor
120| a0: ptr for original operand/final result
121| a1: scratch pointer
122| a2: pointer to FP_X; abs(original value) in ext
123| fp0: scratch
124| fp1: scratch
125| fp2: scratch
126| F_SCR1:
127| F_SCR2:
128| L_SCR1:
129| L_SCR2:
130
131| Copyright (C) Motorola, Inc. 1990
132| All Rights Reserved
133|
134| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
135| The copyright notice above does not evidence any
136| actual or intended publication of such source code.
137
138|BINDEC idnt 2,1 | Motorola 040 Floating Point Software Package
139
140#include "fpsp.h"
141
142 |section 8
143
144| Constants in extended precision
145LOG2: .long 0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000
146LOG2UP1: .long 0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000
147
148| Constants in single precision
149FONE: .long 0x3F800000,0x00000000,0x00000000,0x00000000
150FTWO: .long 0x40000000,0x00000000,0x00000000,0x00000000
151FTEN: .long 0x41200000,0x00000000,0x00000000,0x00000000
152F4933: .long 0x459A2800,0x00000000,0x00000000,0x00000000
153
154RBDTBL: .byte 0,0,0,0
155 .byte 3,3,2,2
156 .byte 3,2,2,3
157 .byte 2,3,3,2
158
159 |xref binstr
160 |xref sintdo
161 |xref ptenrn,ptenrm,ptenrp
162
163 .global bindec
164 .global sc_mul
165bindec:
166 moveml %d2-%d7/%a2,-(%a7)
167 fmovemx %fp0-%fp2,-(%a7)
168
169| A1. Set RM and size ext. Set SIGMA = sign input;
170| The k-factor is saved for use in d7. Clear BINDEC_FLG for
171| separating normalized/denormalized input. If the input
172| is a denormalized number, set the BINDEC_FLG memory word
173| to signal denorm. If the input is unnormalized, normalize
174| the input and test for denormalized result.
175|
176 fmovel #rm_mode,%FPCR |set RM and ext
177 movel (%a0),L_SCR2(%a6) |save exponent for sign check
178 movel %d0,%d7 |move k-factor to d7
179 clrb BINDEC_FLG(%a6) |clr norm/denorm flag
180 movew STAG(%a6),%d0 |get stag
181 andiw #0xe000,%d0 |isolate stag bits
182 beq A2_str |if zero, input is norm
183|
184| Normalize the denorm
185|
186un_de_norm:
187 movew (%a0),%d0
188 andiw #0x7fff,%d0 |strip sign of normalized exp
189 movel 4(%a0),%d1
190 movel 8(%a0),%d2
191norm_loop:
192 subw #1,%d0
193 lsll #1,%d2
194 roxll #1,%d1
195 tstl %d1
196 bges norm_loop
197|
198| Test if the normalized input is denormalized
199|
200 tstw %d0
201 bgts pos_exp |if greater than zero, it is a norm
202 st BINDEC_FLG(%a6) |set flag for denorm
203pos_exp:
204 andiw #0x7fff,%d0 |strip sign of normalized exp
205 movew %d0,(%a0)
206 movel %d1,4(%a0)
207 movel %d2,8(%a0)
208
209| A2. Set X = abs(input).
210|
211A2_str:
212 movel (%a0),FP_SCR2(%a6) | move input to work space
213 movel 4(%a0),FP_SCR2+4(%a6) | move input to work space
214 movel 8(%a0),FP_SCR2+8(%a6) | move input to work space
215 andil #0x7fffffff,FP_SCR2(%a6) |create abs(X)
216
217| A3. Compute ILOG.
218| ILOG is the log base 10 of the input value. It is approx-
219| imated by adding e + 0.f when the original value is viewed
220| as 2^^e * 1.f in extended precision. This value is stored
221| in d6.
222|
223| Register usage:
224| Input/Output
225| d0: k-factor/exponent
226| d2: x/x
227| d3: x/x
228| d4: x/x
229| d5: x/x
230| d6: x/ILOG
231| d7: k-factor/Unchanged
232| a0: ptr for original operand/final result
233| a1: x/x
234| a2: x/x
235| fp0: x/float(ILOG)
236| fp1: x/x
237| fp2: x/x
238| F_SCR1:x/x
239| F_SCR2:Abs(X)/Abs(X) with $3fff exponent
240| L_SCR1:x/x
241| L_SCR2:first word of X packed/Unchanged
242
243 tstb BINDEC_FLG(%a6) |check for denorm
244 beqs A3_cont |if clr, continue with norm
245 movel #-4933,%d6 |force ILOG = -4933
246 bras A4_str
247A3_cont:
248 movew FP_SCR2(%a6),%d0 |move exp to d0
249 movew #0x3fff,FP_SCR2(%a6) |replace exponent with 0x3fff
250 fmovex FP_SCR2(%a6),%fp0 |now fp0 has 1.f
251 subw #0x3fff,%d0 |strip off bias
252 faddw %d0,%fp0 |add in exp
253 fsubs FONE,%fp0 |subtract off 1.0
254 fbge pos_res |if pos, branch
255 fmulx LOG2UP1,%fp0 |if neg, mul by LOG2UP1
256 fmovel %fp0,%d6 |put ILOG in d6 as a lword
257 bras A4_str |go move out ILOG
258pos_res:
259 fmulx LOG2,%fp0 |if pos, mul by LOG2
260 fmovel %fp0,%d6 |put ILOG in d6 as a lword
261
262
263| A4. Clr INEX bit.
264| The operation in A3 above may have set INEX2.
265
266A4_str:
267 fmovel #0,%FPSR |zero all of fpsr - nothing needed
268
269
270| A5. Set ICTR = 0;
271| ICTR is a flag used in A13. It must be set before the
272| loop entry A6. The lower word of d5 is used for ICTR.
273
274 clrw %d5 |clear ICTR
275
276
277| A6. Calculate LEN.
278| LEN is the number of digits to be displayed. The k-factor
279| can dictate either the total number of digits, if it is
280| a positive number, or the number of digits after the
281| original decimal point which are to be included as
282| significant. See the 68882 manual for examples.
283| If LEN is computed to be greater than 17, set OPERR in
284| USER_FPSR. LEN is stored in d4.
285|
286| Register usage:
287| Input/Output
288| d0: exponent/Unchanged
289| d2: x/x/scratch
290| d3: x/x
291| d4: exc picture/LEN
292| d5: ICTR/Unchanged
293| d6: ILOG/Unchanged
294| d7: k-factor/Unchanged
295| a0: ptr for original operand/final result
296| a1: x/x
297| a2: x/x
298| fp0: float(ILOG)/Unchanged
299| fp1: x/x
300| fp2: x/x
301| F_SCR1:x/x
302| F_SCR2:Abs(X) with $3fff exponent/Unchanged
303| L_SCR1:x/x
304| L_SCR2:first word of X packed/Unchanged
305
306A6_str:
307 tstl %d7 |branch on sign of k
308 bles k_neg |if k <= 0, LEN = ILOG + 1 - k
309 movel %d7,%d4 |if k > 0, LEN = k
310 bras len_ck |skip to LEN check
311k_neg:
312 movel %d6,%d4 |first load ILOG to d4
313 subl %d7,%d4 |subtract off k
314 addql #1,%d4 |add in the 1
315len_ck:
316 tstl %d4 |LEN check: branch on sign of LEN
317 bles LEN_ng |if neg, set LEN = 1
318 cmpl #17,%d4 |test if LEN > 17
319 bles A7_str |if not, forget it
320 movel #17,%d4 |set max LEN = 17
321 tstl %d7 |if negative, never set OPERR
322 bles A7_str |if positive, continue
323 orl #opaop_mask,USER_FPSR(%a6) |set OPERR & AIOP in USER_FPSR
324 bras A7_str |finished here
325LEN_ng:
326 moveql #1,%d4 |min LEN is 1
327
328
329| A7. Calculate SCALE.
330| SCALE is equal to 10^ISCALE, where ISCALE is the number
331| of decimal places needed to insure LEN integer digits
332| in the output before conversion to bcd. LAMBDA is the sign
333| of ISCALE, used in A9. Fp1 contains 10^^(abs(ISCALE)) using
334| the rounding mode as given in the following table (see
335| Coonen, p. 7.23 as ref.; however, the SCALE variable is
336| of opposite sign in bindec.sa from Coonen).
337|
338| Initial USE
339| FPCR[6:5] LAMBDA SIGN(X) FPCR[6:5]
340| ----------------------------------------------
341| RN 00 0 0 00/0 RN
342| RN 00 0 1 00/0 RN
343| RN 00 1 0 00/0 RN
344| RN 00 1 1 00/0 RN
345| RZ 01 0 0 11/3 RP
346| RZ 01 0 1 11/3 RP
347| RZ 01 1 0 10/2 RM
348| RZ 01 1 1 10/2 RM
349| RM 10 0 0 11/3 RP
350| RM 10 0 1 10/2 RM
351| RM 10 1 0 10/2 RM
352| RM 10 1 1 11/3 RP
353| RP 11 0 0 10/2 RM
354| RP 11 0 1 11/3 RP
355| RP 11 1 0 11/3 RP
356| RP 11 1 1 10/2 RM
357|
358| Register usage:
359| Input/Output
360| d0: exponent/scratch - final is 0
361| d2: x/0 or 24 for A9
362| d3: x/scratch - offset ptr into PTENRM array
363| d4: LEN/Unchanged
364| d5: 0/ICTR:LAMBDA
365| d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
366| d7: k-factor/Unchanged
367| a0: ptr for original operand/final result
368| a1: x/ptr to PTENRM array
369| a2: x/x
370| fp0: float(ILOG)/Unchanged
371| fp1: x/10^ISCALE
372| fp2: x/x
373| F_SCR1:x/x
374| F_SCR2:Abs(X) with $3fff exponent/Unchanged
375| L_SCR1:x/x
376| L_SCR2:first word of X packed/Unchanged
377
378A7_str:
379 tstl %d7 |test sign of k
380 bgts k_pos |if pos and > 0, skip this
381 cmpl %d6,%d7 |test k - ILOG
382 blts k_pos |if ILOG >= k, skip this
383 movel %d7,%d6 |if ((k<0) & (ILOG < k)) ILOG = k
384k_pos:
385 movel %d6,%d0 |calc ILOG + 1 - LEN in d0
386 addql #1,%d0 |add the 1
387 subl %d4,%d0 |sub off LEN
388 swap %d5 |use upper word of d5 for LAMBDA
389 clrw %d5 |set it zero initially
390 clrw %d2 |set up d2 for very small case
391 tstl %d0 |test sign of ISCALE
392 bges iscale |if pos, skip next inst
393 addqw #1,%d5 |if neg, set LAMBDA true
394 cmpl #0xffffecd4,%d0 |test iscale <= -4908
395 bgts no_inf |if false, skip rest
396 addil #24,%d0 |add in 24 to iscale
397 movel #24,%d2 |put 24 in d2 for A9
398no_inf:
399 negl %d0 |and take abs of ISCALE
400iscale:
401 fmoves FONE,%fp1 |init fp1 to 1
402 bfextu USER_FPCR(%a6){#26:#2},%d1 |get initial rmode bits
403 lslw #1,%d1 |put them in bits 2:1
404 addw %d5,%d1 |add in LAMBDA
405 lslw #1,%d1 |put them in bits 3:1
406 tstl L_SCR2(%a6) |test sign of original x
407 bges x_pos |if pos, don't set bit 0
408 addql #1,%d1 |if neg, set bit 0
409x_pos:
410 leal RBDTBL,%a2 |load rbdtbl base
411 moveb (%a2,%d1),%d3 |load d3 with new rmode
412 lsll #4,%d3 |put bits in proper position
413 fmovel %d3,%fpcr |load bits into fpu
414 lsrl #4,%d3 |put bits in proper position
415 tstb %d3 |decode new rmode for pten table
416 bnes not_rn |if zero, it is RN
417 leal PTENRN,%a1 |load a1 with RN table base
418 bras rmode |exit decode
419not_rn:
420 lsrb #1,%d3 |get lsb in carry
421 bccs not_rp |if carry clear, it is RM
422 leal PTENRP,%a1 |load a1 with RP table base
423 bras rmode |exit decode
424not_rp:
425 leal PTENRM,%a1 |load a1 with RM table base
426rmode:
427 clrl %d3 |clr table index
428e_loop:
429 lsrl #1,%d0 |shift next bit into carry
430 bccs e_next |if zero, skip the mul
431 fmulx (%a1,%d3),%fp1 |mul by 10**(d3_bit_no)
432e_next:
433 addl #12,%d3 |inc d3 to next pwrten table entry
434 tstl %d0 |test if ISCALE is zero
435 bnes e_loop |if not, loop
436
437
438| A8. Clr INEX; Force RZ.
439| The operation in A3 above may have set INEX2.
440| RZ mode is forced for the scaling operation to insure
441| only one rounding error. The grs bits are collected in
442| the INEX flag for use in A10.
443|
444| Register usage:
445| Input/Output
446
447 fmovel #0,%FPSR |clr INEX
448 fmovel #rz_mode,%FPCR |set RZ rounding mode
449
450
451| A9. Scale X -> Y.
452| The mantissa is scaled to the desired number of significant
453| digits. The excess digits are collected in INEX2. If mul,
454| Check d2 for excess 10 exponential value. If not zero,
455| the iscale value would have caused the pwrten calculation
456| to overflow. Only a negative iscale can cause this, so
457| multiply by 10^(d2), which is now only allowed to be 24,
458| with a multiply by 10^8 and 10^16, which is exact since
459| 10^24 is exact. If the input was denormalized, we must
460| create a busy stack frame with the mul command and the
461| two operands, and allow the fpu to complete the multiply.
462|
463| Register usage:
464| Input/Output
465| d0: FPCR with RZ mode/Unchanged
466| d2: 0 or 24/unchanged
467| d3: x/x
468| d4: LEN/Unchanged
469| d5: ICTR:LAMBDA
470| d6: ILOG/Unchanged
471| d7: k-factor/Unchanged
472| a0: ptr for original operand/final result
473| a1: ptr to PTENRM array/Unchanged
474| a2: x/x
475| fp0: float(ILOG)/X adjusted for SCALE (Y)
476| fp1: 10^ISCALE/Unchanged
477| fp2: x/x
478| F_SCR1:x/x
479| F_SCR2:Abs(X) with $3fff exponent/Unchanged
480| L_SCR1:x/x
481| L_SCR2:first word of X packed/Unchanged
482
483A9_str:
484 fmovex (%a0),%fp0 |load X from memory
485 fabsx %fp0 |use abs(X)
486 tstw %d5 |LAMBDA is in lower word of d5
487 bne sc_mul |if neg (LAMBDA = 1), scale by mul
488 fdivx %fp1,%fp0 |calculate X / SCALE -> Y to fp0
489 bras A10_st |branch to A10
490
491sc_mul:
492 tstb BINDEC_FLG(%a6) |check for denorm
493 beqs A9_norm |if norm, continue with mul
494 fmovemx %fp1-%fp1,-(%a7) |load ETEMP with 10^ISCALE
495 movel 8(%a0),-(%a7) |load FPTEMP with input arg
496 movel 4(%a0),-(%a7)
497 movel (%a0),-(%a7)
498 movel #18,%d3 |load count for busy stack
499A9_loop:
500 clrl -(%a7) |clear lword on stack
501 dbf %d3,A9_loop
502 moveb VER_TMP(%a6),(%a7) |write current version number
503 moveb #BUSY_SIZE-4,1(%a7) |write current busy size
504 moveb #0x10,0x44(%a7) |set fcefpte[15] bit
505 movew #0x0023,0x40(%a7) |load cmdreg1b with mul command
506 moveb #0xfe,0x8(%a7) |load all 1s to cu savepc
507 frestore (%a7)+ |restore frame to fpu for completion
508 fmulx 36(%a1),%fp0 |multiply fp0 by 10^8
509 fmulx 48(%a1),%fp0 |multiply fp0 by 10^16
510 bras A10_st
511A9_norm:
512 tstw %d2 |test for small exp case
513 beqs A9_con |if zero, continue as normal
514 fmulx 36(%a1),%fp0 |multiply fp0 by 10^8
515 fmulx 48(%a1),%fp0 |multiply fp0 by 10^16
516A9_con:
517 fmulx %fp1,%fp0 |calculate X * SCALE -> Y to fp0
518
519
520| A10. Or in INEX.
521| If INEX is set, round error occurred. This is compensated
522| for by 'or-ing' in the INEX2 flag to the lsb of Y.
523|
524| Register usage:
525| Input/Output
526| d0: FPCR with RZ mode/FPSR with INEX2 isolated
527| d2: x/x
528| d3: x/x
529| d4: LEN/Unchanged
530| d5: ICTR:LAMBDA
531| d6: ILOG/Unchanged
532| d7: k-factor/Unchanged
533| a0: ptr for original operand/final result
534| a1: ptr to PTENxx array/Unchanged
535| a2: x/ptr to FP_SCR2(a6)
536| fp0: Y/Y with lsb adjusted
537| fp1: 10^ISCALE/Unchanged
538| fp2: x/x
539
540A10_st:
541 fmovel %FPSR,%d0 |get FPSR
542 fmovex %fp0,FP_SCR2(%a6) |move Y to memory
543 leal FP_SCR2(%a6),%a2 |load a2 with ptr to FP_SCR2
544 btstl #9,%d0 |check if INEX2 set
545 beqs A11_st |if clear, skip rest
546 oril #1,8(%a2) |or in 1 to lsb of mantissa
547 fmovex FP_SCR2(%a6),%fp0 |write adjusted Y back to fpu
548
549
550| A11. Restore original FPCR; set size ext.
551| Perform FINT operation in the user's rounding mode. Keep
552| the size to extended. The sintdo entry point in the sint
553| routine expects the FPCR value to be in USER_FPCR for
554| mode and precision. The original FPCR is saved in L_SCR1.
555
556A11_st:
557 movel USER_FPCR(%a6),L_SCR1(%a6) |save it for later
558 andil #0x00000030,USER_FPCR(%a6) |set size to ext,
559| ;block exceptions
560
561
562| A12. Calculate YINT = FINT(Y) according to user's rounding mode.
563| The FPSP routine sintd0 is used. The output is in fp0.
564|
565| Register usage:
566| Input/Output
567| d0: FPSR with AINEX cleared/FPCR with size set to ext
568| d2: x/x/scratch
569| d3: x/x
570| d4: LEN/Unchanged
571| d5: ICTR:LAMBDA/Unchanged
572| d6: ILOG/Unchanged
573| d7: k-factor/Unchanged
574| a0: ptr for original operand/src ptr for sintdo
575| a1: ptr to PTENxx array/Unchanged
576| a2: ptr to FP_SCR2(a6)/Unchanged
577| a6: temp pointer to FP_SCR2(a6) - orig value saved and restored
578| fp0: Y/YINT
579| fp1: 10^ISCALE/Unchanged
580| fp2: x/x
581| F_SCR1:x/x
582| F_SCR2:Y adjusted for inex/Y with original exponent
583| L_SCR1:x/original USER_FPCR
584| L_SCR2:first word of X packed/Unchanged
585
586A12_st:
587 moveml %d0-%d1/%a0-%a1,-(%a7) |save regs used by sintd0
588 movel L_SCR1(%a6),-(%a7)
589 movel L_SCR2(%a6),-(%a7)
590 leal FP_SCR2(%a6),%a0 |a0 is ptr to F_SCR2(a6)
591 fmovex %fp0,(%a0) |move Y to memory at FP_SCR2(a6)
592 tstl L_SCR2(%a6) |test sign of original operand
593 bges do_fint |if pos, use Y
594 orl #0x80000000,(%a0) |if neg, use -Y
595do_fint:
596 movel USER_FPSR(%a6),-(%a7)
597 bsr sintdo |sint routine returns int in fp0
598 moveb (%a7),USER_FPSR(%a6)
599 addl #4,%a7
600 movel (%a7)+,L_SCR2(%a6)
601 movel (%a7)+,L_SCR1(%a6)
602 moveml (%a7)+,%d0-%d1/%a0-%a1 |restore regs used by sint
603 movel L_SCR2(%a6),FP_SCR2(%a6) |restore original exponent
604 movel L_SCR1(%a6),USER_FPCR(%a6) |restore user's FPCR
605
606
607| A13. Check for LEN digits.
608| If the int operation results in more than LEN digits,
609| or less than LEN -1 digits, adjust ILOG and repeat from
610| A6. This test occurs only on the first pass. If the
611| result is exactly 10^LEN, decrement ILOG and divide
612| the mantissa by 10. The calculation of 10^LEN cannot
613| be inexact, since all powers of ten upto 10^27 are exact
614| in extended precision, so the use of a previous power-of-ten
615| table will introduce no error.
616|
617|
618| Register usage:
619| Input/Output
620| d0: FPCR with size set to ext/scratch final = 0
621| d2: x/x
622| d3: x/scratch final = x
623| d4: LEN/LEN adjusted
624| d5: ICTR:LAMBDA/LAMBDA:ICTR
625| d6: ILOG/ILOG adjusted
626| d7: k-factor/Unchanged
627| a0: pointer into memory for packed bcd string formation
628| a1: ptr to PTENxx array/Unchanged
629| a2: ptr to FP_SCR2(a6)/Unchanged
630| fp0: int portion of Y/abs(YINT) adjusted
631| fp1: 10^ISCALE/Unchanged
632| fp2: x/10^LEN
633| F_SCR1:x/x
634| F_SCR2:Y with original exponent/Unchanged
635| L_SCR1:original USER_FPCR/Unchanged
636| L_SCR2:first word of X packed/Unchanged
637
638A13_st:
639 swap %d5 |put ICTR in lower word of d5
640 tstw %d5 |check if ICTR = 0
641 bne not_zr |if non-zero, go to second test
642|
643| Compute 10^(LEN-1)
644|
645 fmoves FONE,%fp2 |init fp2 to 1.0
646 movel %d4,%d0 |put LEN in d0
647 subql #1,%d0 |d0 = LEN -1
648 clrl %d3 |clr table index
649l_loop:
650 lsrl #1,%d0 |shift next bit into carry
651 bccs l_next |if zero, skip the mul
652 fmulx (%a1,%d3),%fp2 |mul by 10**(d3_bit_no)
653l_next:
654 addl #12,%d3 |inc d3 to next pwrten table entry
655 tstl %d0 |test if LEN is zero
656 bnes l_loop |if not, loop
657|
658| 10^LEN-1 is computed for this test and A14. If the input was
659| denormalized, check only the case in which YINT > 10^LEN.
660|
661 tstb BINDEC_FLG(%a6) |check if input was norm
662 beqs A13_con |if norm, continue with checking
663 fabsx %fp0 |take abs of YINT
664 bra test_2
665|
666| Compare abs(YINT) to 10^(LEN-1) and 10^LEN
667|
668A13_con:
669 fabsx %fp0 |take abs of YINT
670 fcmpx %fp2,%fp0 |compare abs(YINT) with 10^(LEN-1)
671 fbge test_2 |if greater, do next test
672 subql #1,%d6 |subtract 1 from ILOG
673 movew #1,%d5 |set ICTR
674 fmovel #rm_mode,%FPCR |set rmode to RM
675 fmuls FTEN,%fp2 |compute 10^LEN
676 bra A6_str |return to A6 and recompute YINT
677test_2:
678 fmuls FTEN,%fp2 |compute 10^LEN
679 fcmpx %fp2,%fp0 |compare abs(YINT) with 10^LEN
680 fblt A14_st |if less, all is ok, go to A14
681 fbgt fix_ex |if greater, fix and redo
682 fdivs FTEN,%fp0 |if equal, divide by 10
683 addql #1,%d6 | and inc ILOG
684 bras A14_st | and continue elsewhere
685fix_ex:
686 addql #1,%d6 |increment ILOG by 1
687 movew #1,%d5 |set ICTR
688 fmovel #rm_mode,%FPCR |set rmode to RM
689 bra A6_str |return to A6 and recompute YINT
690|
691| Since ICTR <> 0, we have already been through one adjustment,
692| and shouldn't have another; this is to check if abs(YINT) = 10^LEN
693| 10^LEN is again computed using whatever table is in a1 since the
694| value calculated cannot be inexact.
695|
696not_zr:
697 fmoves FONE,%fp2 |init fp2 to 1.0
698 movel %d4,%d0 |put LEN in d0
699 clrl %d3 |clr table index
700z_loop:
701 lsrl #1,%d0 |shift next bit into carry
702 bccs z_next |if zero, skip the mul
703 fmulx (%a1,%d3),%fp2 |mul by 10**(d3_bit_no)
704z_next:
705 addl #12,%d3 |inc d3 to next pwrten table entry
706 tstl %d0 |test if LEN is zero
707 bnes z_loop |if not, loop
708 fabsx %fp0 |get abs(YINT)
709 fcmpx %fp2,%fp0 |check if abs(YINT) = 10^LEN
710 fbne A14_st |if not, skip this
711 fdivs FTEN,%fp0 |divide abs(YINT) by 10
712 addql #1,%d6 |and inc ILOG by 1
713 addql #1,%d4 | and inc LEN
714 fmuls FTEN,%fp2 | if LEN++, the get 10^^LEN
715
716
717| A14. Convert the mantissa to bcd.
718| The binstr routine is used to convert the LEN digit
719| mantissa to bcd in memory. The input to binstr is
720| to be a fraction; i.e. (mantissa)/10^LEN and adjusted
721| such that the decimal point is to the left of bit 63.
722| The bcd digits are stored in the correct position in
723| the final string area in memory.
724|
725|
726| Register usage:
727| Input/Output
728| d0: x/LEN call to binstr - final is 0
729| d1: x/0
730| d2: x/ms 32-bits of mant of abs(YINT)
731| d3: x/ls 32-bits of mant of abs(YINT)
732| d4: LEN/Unchanged
733| d5: ICTR:LAMBDA/LAMBDA:ICTR
734| d6: ILOG
735| d7: k-factor/Unchanged
736| a0: pointer into memory for packed bcd string formation
737| /ptr to first mantissa byte in result string
738| a1: ptr to PTENxx array/Unchanged
739| a2: ptr to FP_SCR2(a6)/Unchanged
740| fp0: int portion of Y/abs(YINT) adjusted
741| fp1: 10^ISCALE/Unchanged
742| fp2: 10^LEN/Unchanged
743| F_SCR1:x/Work area for final result
744| F_SCR2:Y with original exponent/Unchanged
745| L_SCR1:original USER_FPCR/Unchanged
746| L_SCR2:first word of X packed/Unchanged
747
748A14_st:
749 fmovel #rz_mode,%FPCR |force rz for conversion
750 fdivx %fp2,%fp0 |divide abs(YINT) by 10^LEN
751 leal FP_SCR1(%a6),%a0
752 fmovex %fp0,(%a0) |move abs(YINT)/10^LEN to memory
753 movel 4(%a0),%d2 |move 2nd word of FP_RES to d2
754 movel 8(%a0),%d3 |move 3rd word of FP_RES to d3
755 clrl 4(%a0) |zero word 2 of FP_RES
756 clrl 8(%a0) |zero word 3 of FP_RES
757 movel (%a0),%d0 |move exponent to d0
758 swap %d0 |put exponent in lower word
759 beqs no_sft |if zero, don't shift
760 subil #0x3ffd,%d0 |sub bias less 2 to make fract
761 tstl %d0 |check if > 1
762 bgts no_sft |if so, don't shift
763 negl %d0 |make exp positive
764m_loop:
765 lsrl #1,%d2 |shift d2:d3 right, add 0s
766 roxrl #1,%d3 |the number of places
767 dbf %d0,m_loop |given in d0
768no_sft:
769 tstl %d2 |check for mantissa of zero
770 bnes no_zr |if not, go on
771 tstl %d3 |continue zero check
772 beqs zer_m |if zero, go directly to binstr
773no_zr:
774 clrl %d1 |put zero in d1 for addx
775 addil #0x00000080,%d3 |inc at bit 7
776 addxl %d1,%d2 |continue inc
777 andil #0xffffff80,%d3 |strip off lsb not used by 882
778zer_m:
779 movel %d4,%d0 |put LEN in d0 for binstr call
780 addql #3,%a0 |a0 points to M16 byte in result
781 bsr binstr |call binstr to convert mant
782
783
784| A15. Convert the exponent to bcd.
785| As in A14 above, the exp is converted to bcd and the
786| digits are stored in the final string.
787|
788| Digits are stored in L_SCR1(a6) on return from BINDEC as:
789|
790| 32 16 15 0
791| -----------------------------------------
792| | 0 | e3 | e2 | e1 | e4 | X | X | X |
793| -----------------------------------------
794|
795| And are moved into their proper places in FP_SCR1. If digit e4
796| is non-zero, OPERR is signaled. In all cases, all 4 digits are
797| written as specified in the 881/882 manual for packed decimal.
798|
799| Register usage:
800| Input/Output
801| d0: x/LEN call to binstr - final is 0
802| d1: x/scratch (0);shift count for final exponent packing
803| d2: x/ms 32-bits of exp fraction/scratch
804| d3: x/ls 32-bits of exp fraction
805| d4: LEN/Unchanged
806| d5: ICTR:LAMBDA/LAMBDA:ICTR
807| d6: ILOG
808| d7: k-factor/Unchanged
809| a0: ptr to result string/ptr to L_SCR1(a6)
810| a1: ptr to PTENxx array/Unchanged
811| a2: ptr to FP_SCR2(a6)/Unchanged
812| fp0: abs(YINT) adjusted/float(ILOG)
813| fp1: 10^ISCALE/Unchanged
814| fp2: 10^LEN/Unchanged
815| F_SCR1:Work area for final result/BCD result
816| F_SCR2:Y with original exponent/ILOG/10^4
817| L_SCR1:original USER_FPCR/Exponent digits on return from binstr
818| L_SCR2:first word of X packed/Unchanged
819
820A15_st:
821 tstb BINDEC_FLG(%a6) |check for denorm
822 beqs not_denorm
823 ftstx %fp0 |test for zero
824 fbeq den_zero |if zero, use k-factor or 4933
825 fmovel %d6,%fp0 |float ILOG
826 fabsx %fp0 |get abs of ILOG
827 bras convrt
828den_zero:
829 tstl %d7 |check sign of the k-factor
830 blts use_ilog |if negative, use ILOG
831 fmoves F4933,%fp0 |force exponent to 4933
832 bras convrt |do it
833use_ilog:
834 fmovel %d6,%fp0 |float ILOG
835 fabsx %fp0 |get abs of ILOG
836 bras convrt
837not_denorm:
838 ftstx %fp0 |test for zero
839 fbne not_zero |if zero, force exponent
840 fmoves FONE,%fp0 |force exponent to 1
841 bras convrt |do it
842not_zero:
843 fmovel %d6,%fp0 |float ILOG
844 fabsx %fp0 |get abs of ILOG
845convrt:
846 fdivx 24(%a1),%fp0 |compute ILOG/10^4
847 fmovex %fp0,FP_SCR2(%a6) |store fp0 in memory
848 movel 4(%a2),%d2 |move word 2 to d2
849 movel 8(%a2),%d3 |move word 3 to d3
850 movew (%a2),%d0 |move exp to d0
851 beqs x_loop_fin |if zero, skip the shift
852 subiw #0x3ffd,%d0 |subtract off bias
853 negw %d0 |make exp positive
854x_loop:
855 lsrl #1,%d2 |shift d2:d3 right
856 roxrl #1,%d3 |the number of places
857 dbf %d0,x_loop |given in d0
858x_loop_fin:
859 clrl %d1 |put zero in d1 for addx
860 addil #0x00000080,%d3 |inc at bit 6
861 addxl %d1,%d2 |continue inc
862 andil #0xffffff80,%d3 |strip off lsb not used by 882
863 movel #4,%d0 |put 4 in d0 for binstr call
864 leal L_SCR1(%a6),%a0 |a0 is ptr to L_SCR1 for exp digits
865 bsr binstr |call binstr to convert exp
866 movel L_SCR1(%a6),%d0 |load L_SCR1 lword to d0
867 movel #12,%d1 |use d1 for shift count
868 lsrl %d1,%d0 |shift d0 right by 12
869 bfins %d0,FP_SCR1(%a6){#4:#12} |put e3:e2:e1 in FP_SCR1
870 lsrl %d1,%d0 |shift d0 right by 12
871 bfins %d0,FP_SCR1(%a6){#16:#4} |put e4 in FP_SCR1
872 tstb %d0 |check if e4 is zero
873 beqs A16_st |if zero, skip rest
874 orl #opaop_mask,USER_FPSR(%a6) |set OPERR & AIOP in USER_FPSR
875
876
877| A16. Write sign bits to final string.
878| Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
879|
880| Register usage:
881| Input/Output
882| d0: x/scratch - final is x
883| d2: x/x
884| d3: x/x
885| d4: LEN/Unchanged
886| d5: ICTR:LAMBDA/LAMBDA:ICTR
887| d6: ILOG/ILOG adjusted
888| d7: k-factor/Unchanged
889| a0: ptr to L_SCR1(a6)/Unchanged
890| a1: ptr to PTENxx array/Unchanged
891| a2: ptr to FP_SCR2(a6)/Unchanged
892| fp0: float(ILOG)/Unchanged
893| fp1: 10^ISCALE/Unchanged
894| fp2: 10^LEN/Unchanged
895| F_SCR1:BCD result with correct signs
896| F_SCR2:ILOG/10^4
897| L_SCR1:Exponent digits on return from binstr
898| L_SCR2:first word of X packed/Unchanged
899
900A16_st:
901 clrl %d0 |clr d0 for collection of signs
902 andib #0x0f,FP_SCR1(%a6) |clear first nibble of FP_SCR1
903 tstl L_SCR2(%a6) |check sign of original mantissa
904 bges mant_p |if pos, don't set SM
905 moveql #2,%d0 |move 2 in to d0 for SM
906mant_p:
907 tstl %d6 |check sign of ILOG
908 bges wr_sgn |if pos, don't set SE
909 addql #1,%d0 |set bit 0 in d0 for SE
910wr_sgn:
911 bfins %d0,FP_SCR1(%a6){#0:#2} |insert SM and SE into FP_SCR1
912
913| Clean up and restore all registers used.
914
915 fmovel #0,%FPSR |clear possible inex2/ainex bits
916 fmovemx (%a7)+,%fp0-%fp2
917 moveml (%a7)+,%d2-%d7/%a2
918 rts
919
920 |end
diff --git a/arch/m68k/fpsp040/binstr.S b/arch/m68k/fpsp040/binstr.S
new file mode 100644
index 000000000000..d53555c0a2b6
--- /dev/null
+++ b/arch/m68k/fpsp040/binstr.S
@@ -0,0 +1,140 @@
1|
2| binstr.sa 3.3 12/19/90
3|
4|
5| Description: Converts a 64-bit binary integer to bcd.
6|
7| Input: 64-bit binary integer in d2:d3, desired length (LEN) in
8| d0, and a pointer to start in memory for bcd characters
9| in d0. (This pointer must point to byte 4 of the first
10| lword of the packed decimal memory string.)
11|
12| Output: LEN bcd digits representing the 64-bit integer.
13|
14| Algorithm:
15| The 64-bit binary is assumed to have a decimal point before
16| bit 63. The fraction is multiplied by 10 using a mul by 2
17| shift and a mul by 8 shift. The bits shifted out of the
18| msb form a decimal digit. This process is iterated until
19| LEN digits are formed.
20|
21| A1. Init d7 to 1. D7 is the byte digit counter, and if 1, the
22| digit formed will be assumed the least significant. This is
23| to force the first byte formed to have a 0 in the upper 4 bits.
24|
25| A2. Beginning of the loop:
26| Copy the fraction in d2:d3 to d4:d5.
27|
28| A3. Multiply the fraction in d2:d3 by 8 using bit-field
29| extracts and shifts. The three msbs from d2 will go into
30| d1.
31|
32| A4. Multiply the fraction in d4:d5 by 2 using shifts. The msb
33| will be collected by the carry.
34|
35| A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5
36| into d2:d3. D1 will contain the bcd digit formed.
37|
38| A6. Test d7. If zero, the digit formed is the ms digit. If non-
39| zero, it is the ls digit. Put the digit in its place in the
40| upper word of d0. If it is the ls digit, write the word
41| from d0 to memory.
42|
43| A7. Decrement d6 (LEN counter) and repeat the loop until zero.
44|
45| Implementation Notes:
46|
47| The registers are used as follows:
48|
49| d0: LEN counter
50| d1: temp used to form the digit
51| d2: upper 32-bits of fraction for mul by 8
52| d3: lower 32-bits of fraction for mul by 8
53| d4: upper 32-bits of fraction for mul by 2
54| d5: lower 32-bits of fraction for mul by 2
55| d6: temp for bit-field extracts
56| d7: byte digit formation word;digit count {0,1}
57| a0: pointer into memory for packed bcd string formation
58|
59
60| Copyright (C) Motorola, Inc. 1990
61| All Rights Reserved
62|
63| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
64| The copyright notice above does not evidence any
65| actual or intended publication of such source code.
66
67|BINSTR idnt 2,1 | Motorola 040 Floating Point Software Package
68
69 |section 8
70
71#include "fpsp.h"
72
73 .global binstr
74binstr:
75 moveml %d0-%d7,-(%a7)
76|
77| A1: Init d7
78|
79 moveql #1,%d7 |init d7 for second digit
80 subql #1,%d0 |for dbf d0 would have LEN+1 passes
81|
82| A2. Copy d2:d3 to d4:d5. Start loop.
83|
84loop:
85 movel %d2,%d4 |copy the fraction before muls
86 movel %d3,%d5 |to d4:d5
87|
88| A3. Multiply d2:d3 by 8; extract msbs into d1.
89|
90 bfextu %d2{#0:#3},%d1 |copy 3 msbs of d2 into d1
91 asll #3,%d2 |shift d2 left by 3 places
92 bfextu %d3{#0:#3},%d6 |copy 3 msbs of d3 into d6
93 asll #3,%d3 |shift d3 left by 3 places
94 orl %d6,%d2 |or in msbs from d3 into d2
95|
96| A4. Multiply d4:d5 by 2; add carry out to d1.
97|
98 asll #1,%d5 |mul d5 by 2
99 roxll #1,%d4 |mul d4 by 2
100 swap %d6 |put 0 in d6 lower word
101 addxw %d6,%d1 |add in extend from mul by 2
102|
103| A5. Add mul by 8 to mul by 2. D1 contains the digit formed.
104|
105 addl %d5,%d3 |add lower 32 bits
106 nop |ERRATA ; FIX #13 (Rev. 1.2 6/6/90)
107 addxl %d4,%d2 |add with extend upper 32 bits
108 nop |ERRATA ; FIX #13 (Rev. 1.2 6/6/90)
109 addxw %d6,%d1 |add in extend from add to d1
110 swap %d6 |with d6 = 0; put 0 in upper word
111|
112| A6. Test d7 and branch.
113|
114 tstw %d7 |if zero, store digit & to loop
115 beqs first_d |if non-zero, form byte & write
116sec_d:
117 swap %d7 |bring first digit to word d7b
118 aslw #4,%d7 |first digit in upper 4 bits d7b
119 addw %d1,%d7 |add in ls digit to d7b
120 moveb %d7,(%a0)+ |store d7b byte in memory
121 swap %d7 |put LEN counter in word d7a
122 clrw %d7 |set d7a to signal no digits done
123 dbf %d0,loop |do loop some more!
124 bras end_bstr |finished, so exit
125first_d:
126 swap %d7 |put digit word in d7b
127 movew %d1,%d7 |put new digit in d7b
128 swap %d7 |put LEN counter in word d7a
129 addqw #1,%d7 |set d7a to signal first digit done
130 dbf %d0,loop |do loop some more!
131 swap %d7 |put last digit in string
132 lslw #4,%d7 |move it to upper 4 bits
133 moveb %d7,(%a0)+ |store it in memory string
134|
135| Clean up and return with result in fp0.
136|
137end_bstr:
138 moveml (%a7)+,%d0-%d7
139 rts
140 |end
diff --git a/arch/m68k/fpsp040/bugfix.S b/arch/m68k/fpsp040/bugfix.S
new file mode 100644
index 000000000000..942c4f6f4fd1
--- /dev/null
+++ b/arch/m68k/fpsp040/bugfix.S
@@ -0,0 +1,496 @@
1|
2| bugfix.sa 3.2 1/31/91
3|
4|
5| This file contains workarounds for bugs in the 040
6| relating to the Floating-Point Software Package (FPSP)
7|
8| Fixes for bugs: 1238
9|
10| Bug: 1238
11|
12|
13| /* The following dirty_bit clear should be left in
14| * the handler permanently to improve throughput.
15| * The dirty_bits are located at bits [23:16] in
16| * longword $08 in the busy frame $4x60. Bit 16
17| * corresponds to FP0, bit 17 corresponds to FP1,
18| * and so on.
19| */
20| if (E3_exception_just_serviced) {
21| dirty_bit[cmdreg3b[9:7]] = 0;
22| }
23|
24| if (fsave_format_version != $40) {goto NOFIX}
25|
26| if !(E3_exception_just_serviced) {goto NOFIX}
27| if (cupc == 0000000) {goto NOFIX}
28| if ((cmdreg1b[15:13] != 000) &&
29| (cmdreg1b[15:10] != 010001)) {goto NOFIX}
30| if (((cmdreg1b[15:13] != 000) || ((cmdreg1b[12:10] != cmdreg2b[9:7]) &&
31| (cmdreg1b[12:10] != cmdreg3b[9:7])) ) &&
32| ((cmdreg1b[ 9: 7] != cmdreg2b[9:7]) &&
33| (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) ) {goto NOFIX}
34|
35| /* Note: for 6d43b or 8d43b, you may want to add the following code
36| * to get better coverage. (If you do not insert this code, the part
37| * won't lock up; it will simply get the wrong answer.)
38| * Do NOT insert this code for 10d43b or later parts.
39| *
40| * if (fpiarcu == integer stack return address) {
41| * cupc = 0000000;
42| * goto NOFIX;
43| * }
44| */
45|
46| if (cmdreg1b[15:13] != 000) {goto FIX_OPCLASS2}
47| FIX_OPCLASS0:
48| if (((cmdreg1b[12:10] == cmdreg2b[9:7]) ||
49| (cmdreg1b[ 9: 7] == cmdreg2b[9:7])) &&
50| (cmdreg1b[12:10] != cmdreg3b[9:7]) &&
51| (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) { /* xu conflict only */
52| /* We execute the following code if there is an
53| xu conflict and NOT an nu conflict */
54|
55| /* first save some values on the fsave frame */
56| stag_temp = STAG[fsave_frame];
57| cmdreg1b_temp = CMDREG1B[fsave_frame];
58| dtag_temp = DTAG[fsave_frame];
59| ete15_temp = ETE15[fsave_frame];
60|
61| CUPC[fsave_frame] = 0000000;
62| FRESTORE
63| FSAVE
64|
65| /* If the xu instruction is exceptional, we punt.
66| * Otherwise, we would have to include OVFL/UNFL handler
67| * code here to get the correct answer.
68| */
69| if (fsave_frame_format == $4060) {goto KILL_PROCESS}
70|
71| fsave_frame = /* build a long frame of all zeros */
72| fsave_frame_format = $4060; /* label it as long frame */
73|
74| /* load it with the temps we saved */
75| STAG[fsave_frame] = stag_temp;
76| CMDREG1B[fsave_frame] = cmdreg1b_temp;
77| DTAG[fsave_frame] = dtag_temp;
78| ETE15[fsave_frame] = ete15_temp;
79|
80| /* Make sure that the cmdreg3b dest reg is not going to
81| * be destroyed by a FMOVEM at the end of all this code.
82| * If it is, you should move the current value of the reg
83| * onto the stack so that the reg will loaded with that value.
84| */
85|
86| /* All done. Proceed with the code below */
87| }
88|
89| etemp = FP_reg_[cmdreg1b[12:10]];
90| ete15 = ~ete14;
91| cmdreg1b[15:10] = 010010;
92| clear(bug_flag_procIDxxxx);
93| FRESTORE and return;
94|
95|
96| FIX_OPCLASS2:
97| if ((cmdreg1b[9:7] == cmdreg2b[9:7]) &&
98| (cmdreg1b[9:7] != cmdreg3b[9:7])) { /* xu conflict only */
99| /* We execute the following code if there is an
100| xu conflict and NOT an nu conflict */
101|
102| /* first save some values on the fsave frame */
103| stag_temp = STAG[fsave_frame];
104| cmdreg1b_temp = CMDREG1B[fsave_frame];
105| dtag_temp = DTAG[fsave_frame];
106| ete15_temp = ETE15[fsave_frame];
107| etemp_temp = ETEMP[fsave_frame];
108|
109| CUPC[fsave_frame] = 0000000;
110| FRESTORE
111| FSAVE
112|
113|
114| /* If the xu instruction is exceptional, we punt.
115| * Otherwise, we would have to include OVFL/UNFL handler
116| * code here to get the correct answer.
117| */
118| if (fsave_frame_format == $4060) {goto KILL_PROCESS}
119|
120| fsave_frame = /* build a long frame of all zeros */
121| fsave_frame_format = $4060; /* label it as long frame */
122|
123| /* load it with the temps we saved */
124| STAG[fsave_frame] = stag_temp;
125| CMDREG1B[fsave_frame] = cmdreg1b_temp;
126| DTAG[fsave_frame] = dtag_temp;
127| ETE15[fsave_frame] = ete15_temp;
128| ETEMP[fsave_frame] = etemp_temp;
129|
130| /* Make sure that the cmdreg3b dest reg is not going to
131| * be destroyed by a FMOVEM at the end of all this code.
132| * If it is, you should move the current value of the reg
133| * onto the stack so that the reg will loaded with that value.
134| */
135|
136| /* All done. Proceed with the code below */
137| }
138|
139| if (etemp_exponent == min_sgl) etemp_exponent = min_dbl;
140| if (etemp_exponent == max_sgl) etemp_exponent = max_dbl;
141| cmdreg1b[15:10] = 010101;
142| clear(bug_flag_procIDxxxx);
143| FRESTORE and return;
144|
145|
146| NOFIX:
147| clear(bug_flag_procIDxxxx);
148| FRESTORE and return;
149|
150
151
152| Copyright (C) Motorola, Inc. 1990
153| All Rights Reserved
154|
155| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
156| The copyright notice above does not evidence any
157| actual or intended publication of such source code.
158
159|BUGFIX idnt 2,1 | Motorola 040 Floating Point Software Package
160
161 |section 8
162
163#include "fpsp.h"
164
165 |xref fpsp_fmt_error
166
167 .global b1238_fix
168b1238_fix:
169|
170| This code is entered only on completion of the handling of an
171| nu-generated ovfl, unfl, or inex exception. If the version
172| number of the fsave is not $40, this handler is not necessary.
173| Simply branch to fix_done and exit normally.
174|
175 cmpib #VER_40,4(%a7)
176 bne fix_done
177|
178| Test for cu_savepc equal to zero. If not, this is not a bug
179| #1238 case.
180|
181 moveb CU_SAVEPC(%a6),%d0
182 andib #0xFE,%d0
183 beq fix_done |if zero, this is not bug #1238
184
185|
186| Test the register conflict aspect. If opclass0, check for
187| cu src equal to xu dest or equal to nu dest. If so, go to
188| op0. Else, or if opclass2, check for cu dest equal to
189| xu dest or equal to nu dest. If so, go to tst_opcl. Else,
190| exit, it is not the bug case.
191|
192| Check for opclass 0. If not, go and check for opclass 2 and sgl.
193|
194 movew CMDREG1B(%a6),%d0
195 andiw #0xE000,%d0 |strip all but opclass
196 bne op2sgl |not opclass 0, check op2
197|
198| Check for cu and nu register conflict. If one exists, this takes
199| priority over a cu and xu conflict.
200|
201 bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src
202 bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest
203 cmpb %d0,%d1
204 beqs op0 |if equal, continue bugfix
205|
206| Check for cu dest equal to nu dest. If so, go and fix the
207| bug condition. Otherwise, exit.
208|
209 bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest
210 cmpb %d0,%d1 |cmp 1st dest with 3rd dest
211 beqs op0 |if equal, continue bugfix
212|
213| Check for cu and xu register conflict.
214|
215 bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest
216 cmpb %d0,%d1 |cmp 1st dest with 2nd dest
217 beqs op0_xu |if equal, continue bugfix
218 bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src
219 cmpb %d0,%d1 |cmp 1st src with 2nd dest
220 beq op0_xu
221 bne fix_done |if the reg checks fail, exit
222|
223| We have the opclass 0 situation.
224|
225op0:
226 bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no
227 movel #7,%d1
228 subl %d0,%d1
229 clrl %d0
230 bsetl %d1,%d0
231 fmovemx %d0,ETEMP(%a6) |load source to ETEMP
232
233 moveb #0x12,%d0
234 bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended
235|
236| Set ETEMP exponent bit 15 as the opposite of ete14
237|
238 btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14
239 beq setete15
240 bclr #etemp15_bit,STAG(%a6)
241 bra finish
242setete15:
243 bset #etemp15_bit,STAG(%a6)
244 bra finish
245
246|
247| We have the case in which a conflict exists between the cu src or
248| dest and the dest of the xu. We must clear the instruction in
249| the cu and restore the state, allowing the instruction in the
250| xu to complete. Remember, the instruction in the nu
251| was exceptional, and was completed by the appropriate handler.
252| If the result of the xu instruction is not exceptional, we can
253| restore the instruction from the cu to the frame and continue
254| processing the original exception. If the result is also
255| exceptional, we choose to kill the process.
256|
257| Items saved from the stack:
258|
259| $3c stag - L_SCR1
260| $40 cmdreg1b - L_SCR2
261| $44 dtag - L_SCR3
262|
263| The cu savepc is set to zero, and the frame is restored to the
264| fpu.
265|
266op0_xu:
267 movel STAG(%a6),L_SCR1(%a6)
268 movel CMDREG1B(%a6),L_SCR2(%a6)
269 movel DTAG(%a6),L_SCR3(%a6)
270 andil #0xe0000000,L_SCR3(%a6)
271 moveb #0,CU_SAVEPC(%a6)
272 movel (%a7)+,%d1 |save return address from bsr
273 frestore (%a7)+
274 fsave -(%a7)
275|
276| Check if the instruction which just completed was exceptional.
277|
278 cmpw #0x4060,(%a7)
279 beq op0_xb
280|
281| It is necessary to isolate the result of the instruction in the
282| xu if it is to fp0 - fp3 and write that value to the USER_FPn
283| locations on the stack. The correct destination register is in
284| cmdreg2b.
285|
286 bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no
287 cmpil #3,%d0
288 bgts op0_xi
289 beqs op0_fp3
290 cmpil #1,%d0
291 blts op0_fp0
292 beqs op0_fp1
293op0_fp2:
294 fmovemx %fp2-%fp2,USER_FP2(%a6)
295 bras op0_xi
296op0_fp1:
297 fmovemx %fp1-%fp1,USER_FP1(%a6)
298 bras op0_xi
299op0_fp0:
300 fmovemx %fp0-%fp0,USER_FP0(%a6)
301 bras op0_xi
302op0_fp3:
303 fmovemx %fp3-%fp3,USER_FP3(%a6)
304|
305| The frame returned is idle. We must build a busy frame to hold
306| the cu state information and setup etemp.
307|
308op0_xi:
309 movel #22,%d0 |clear 23 lwords
310 clrl (%a7)
311op0_loop:
312 clrl -(%a7)
313 dbf %d0,op0_loop
314 movel #0x40600000,-(%a7)
315 movel L_SCR1(%a6),STAG(%a6)
316 movel L_SCR2(%a6),CMDREG1B(%a6)
317 movel L_SCR3(%a6),DTAG(%a6)
318 moveb #0x6,CU_SAVEPC(%a6)
319 movel %d1,-(%a7) |return bsr return address
320 bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no
321 movel #7,%d1
322 subl %d0,%d1
323 clrl %d0
324 bsetl %d1,%d0
325 fmovemx %d0,ETEMP(%a6) |load source to ETEMP
326
327 moveb #0x12,%d0
328 bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended
329|
330| Set ETEMP exponent bit 15 as the opposite of ete14
331|
332 btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14
333 beq op0_sete15
334 bclr #etemp15_bit,STAG(%a6)
335 bra finish
336op0_sete15:
337 bset #etemp15_bit,STAG(%a6)
338 bra finish
339
340|
341| The frame returned is busy. It is not possible to reconstruct
342| the code sequence to allow completion. We will jump to
343| fpsp_fmt_error and allow the kernel to kill the process.
344|
345op0_xb:
346 jmp fpsp_fmt_error
347
348|
349| Check for opclass 2 and single size. If not both, exit.
350|
351op2sgl:
352 movew CMDREG1B(%a6),%d0
353 andiw #0xFC00,%d0 |strip all but opclass and size
354 cmpiw #0x4400,%d0 |test for opclass 2 and size=sgl
355 bne fix_done |if not, it is not bug 1238
356|
357| Check for cu dest equal to nu dest or equal to xu dest, with
358| a cu and nu conflict taking priority an nu conflict. If either,
359| go and fix the bug condition. Otherwise, exit.
360|
361 bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest
362 bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest
363 cmpb %d0,%d1 |cmp 1st dest with 3rd dest
364 beq op2_com |if equal, continue bugfix
365 bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest
366 cmpb %d0,%d1 |cmp 1st dest with 2nd dest
367 bne fix_done |if the reg checks fail, exit
368|
369| We have the case in which a conflict exists between the cu src or
370| dest and the dest of the xu. We must clear the instruction in
371| the cu and restore the state, allowing the instruction in the
372| xu to complete. Remember, the instruction in the nu
373| was exceptional, and was completed by the appropriate handler.
374| If the result of the xu instruction is not exceptional, we can
375| restore the instruction from the cu to the frame and continue
376| processing the original exception. If the result is also
377| exceptional, we choose to kill the process.
378|
379| Items saved from the stack:
380|
381| $3c stag - L_SCR1
382| $40 cmdreg1b - L_SCR2
383| $44 dtag - L_SCR3
384| etemp - FP_SCR2
385|
386| The cu savepc is set to zero, and the frame is restored to the
387| fpu.
388|
389op2_xu:
390 movel STAG(%a6),L_SCR1(%a6)
391 movel CMDREG1B(%a6),L_SCR2(%a6)
392 movel DTAG(%a6),L_SCR3(%a6)
393 andil #0xe0000000,L_SCR3(%a6)
394 moveb #0,CU_SAVEPC(%a6)
395 movel ETEMP(%a6),FP_SCR2(%a6)
396 movel ETEMP_HI(%a6),FP_SCR2+4(%a6)
397 movel ETEMP_LO(%a6),FP_SCR2+8(%a6)
398 movel (%a7)+,%d1 |save return address from bsr
399 frestore (%a7)+
400 fsave -(%a7)
401|
402| Check if the instruction which just completed was exceptional.
403|
404 cmpw #0x4060,(%a7)
405 beq op2_xb
406|
407| It is necessary to isolate the result of the instruction in the
408| xu if it is to fp0 - fp3 and write that value to the USER_FPn
409| locations on the stack. The correct destination register is in
410| cmdreg2b.
411|
412 bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no
413 cmpil #3,%d0
414 bgts op2_xi
415 beqs op2_fp3
416 cmpil #1,%d0
417 blts op2_fp0
418 beqs op2_fp1
419op2_fp2:
420 fmovemx %fp2-%fp2,USER_FP2(%a6)
421 bras op2_xi
422op2_fp1:
423 fmovemx %fp1-%fp1,USER_FP1(%a6)
424 bras op2_xi
425op2_fp0:
426 fmovemx %fp0-%fp0,USER_FP0(%a6)
427 bras op2_xi
428op2_fp3:
429 fmovemx %fp3-%fp3,USER_FP3(%a6)
430|
431| The frame returned is idle. We must build a busy frame to hold
432| the cu state information and fix up etemp.
433|
434op2_xi:
435 movel #22,%d0 |clear 23 lwords
436 clrl (%a7)
437op2_loop:
438 clrl -(%a7)
439 dbf %d0,op2_loop
440 movel #0x40600000,-(%a7)
441 movel L_SCR1(%a6),STAG(%a6)
442 movel L_SCR2(%a6),CMDREG1B(%a6)
443 movel L_SCR3(%a6),DTAG(%a6)
444 moveb #0x6,CU_SAVEPC(%a6)
445 movel FP_SCR2(%a6),ETEMP(%a6)
446 movel FP_SCR2+4(%a6),ETEMP_HI(%a6)
447 movel FP_SCR2+8(%a6),ETEMP_LO(%a6)
448 movel %d1,-(%a7)
449 bra op2_com
450
451|
452| We have the opclass 2 single source situation.
453|
454op2_com:
455 moveb #0x15,%d0
456 bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, double
457
458 cmpw #0x407F,ETEMP_EX(%a6) |single +max
459 bnes case2
460 movew #0x43FF,ETEMP_EX(%a6) |to double +max
461 bra finish
462case2:
463 cmpw #0xC07F,ETEMP_EX(%a6) |single -max
464 bnes case3
465 movew #0xC3FF,ETEMP_EX(%a6) |to double -max
466 bra finish
467case3:
468 cmpw #0x3F80,ETEMP_EX(%a6) |single +min
469 bnes case4
470 movew #0x3C00,ETEMP_EX(%a6) |to double +min
471 bra finish
472case4:
473 cmpw #0xBF80,ETEMP_EX(%a6) |single -min
474 bne fix_done
475 movew #0xBC00,ETEMP_EX(%a6) |to double -min
476 bra finish
477|
478| The frame returned is busy. It is not possible to reconstruct
479| the code sequence to allow completion. fpsp_fmt_error causes
480| an fline illegal instruction to be executed.
481|
482| You should replace the jump to fpsp_fmt_error with a jump
483| to the entry point used to kill a process.
484|
485op2_xb:
486 jmp fpsp_fmt_error
487
488|
489| Enter here if the case is not of the situations affected by
490| bug #1238, or if the fix is completed, and exit.
491|
492finish:
493fix_done:
494 rts
495
496 |end
diff --git a/arch/m68k/fpsp040/decbin.S b/arch/m68k/fpsp040/decbin.S
new file mode 100644
index 000000000000..2160609e328d
--- /dev/null
+++ b/arch/m68k/fpsp040/decbin.S
@@ -0,0 +1,506 @@
1|
2| decbin.sa 3.3 12/19/90
3|
4| Description: Converts normalized packed bcd value pointed to by
5| register A6 to extended-precision value in FP0.
6|
7| Input: Normalized packed bcd value in ETEMP(a6).
8|
9| Output: Exact floating-point representation of the packed bcd value.
10|
11| Saves and Modifies: D2-D5
12|
13| Speed: The program decbin takes ??? cycles to execute.
14|
15| Object Size:
16|
17| External Reference(s): None.
18|
19| Algorithm:
20| Expected is a normal bcd (i.e. non-exceptional; all inf, zero,
21| and NaN operands are dispatched without entering this routine)
22| value in 68881/882 format at location ETEMP(A6).
23|
24| A1. Convert the bcd exponent to binary by successive adds and muls.
25| Set the sign according to SE. Subtract 16 to compensate
26| for the mantissa which is to be interpreted as 17 integer
27| digits, rather than 1 integer and 16 fraction digits.
28| Note: this operation can never overflow.
29|
30| A2. Convert the bcd mantissa to binary by successive
31| adds and muls in FP0. Set the sign according to SM.
32| The mantissa digits will be converted with the decimal point
33| assumed following the least-significant digit.
34| Note: this operation can never overflow.
35|
36| A3. Count the number of leading/trailing zeros in the
37| bcd string. If SE is positive, count the leading zeros;
38| if negative, count the trailing zeros. Set the adjusted
39| exponent equal to the exponent from A1 and the zero count
40| added if SM = 1 and subtracted if SM = 0. Scale the
41| mantissa the equivalent of forcing in the bcd value:
42|
43| SM = 0 a non-zero digit in the integer position
44| SM = 1 a non-zero digit in Mant0, lsd of the fraction
45|
46| this will insure that any value, regardless of its
47| representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted
48| consistently.
49|
50| A4. Calculate the factor 10^exp in FP1 using a table of
51| 10^(2^n) values. To reduce the error in forming factors
52| greater than 10^27, a directed rounding scheme is used with
53| tables rounded to RN, RM, and RP, according to the table
54| in the comments of the pwrten section.
55|
56| A5. Form the final binary number by scaling the mantissa by
57| the exponent factor. This is done by multiplying the
58| mantissa in FP0 by the factor in FP1 if the adjusted
59| exponent sign is positive, and dividing FP0 by FP1 if
60| it is negative.
61|
62| Clean up and return. Check if the final mul or div resulted
63| in an inex2 exception. If so, set inex1 in the fpsr and
64| check if the inex1 exception is enabled. If so, set d7 upper
65| word to $0100. This will signal unimp.sa that an enabled inex1
66| exception occurred. Unimp will fix the stack.
67|
68
69| Copyright (C) Motorola, Inc. 1990
70| All Rights Reserved
71|
72| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
73| The copyright notice above does not evidence any
74| actual or intended publication of such source code.
75
76|DECBIN idnt 2,1 | Motorola 040 Floating Point Software Package
77
78 |section 8
79
80#include "fpsp.h"
81
82|
83| PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded
84| to nearest, minus, and plus, respectively. The tables include
85| 10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}. No rounding
86| is required until the power is greater than 27, however, all
87| tables include the first 5 for ease of indexing.
88|
89 |xref PTENRN
90 |xref PTENRM
91 |xref PTENRP
92
93RTABLE: .byte 0,0,0,0
94 .byte 2,3,2,3
95 .byte 2,3,3,2
96 .byte 3,2,2,3
97
98 .global decbin
99 .global calc_e
100 .global pwrten
101 .global calc_m
102 .global norm
103 .global ap_st_z
104 .global ap_st_n
105|
106 .set FNIBS,7
107 .set FSTRT,0
108|
109 .set ESTRT,4
110 .set EDIGITS,2 |
111|
112| Constants in single precision
113FZERO: .long 0x00000000
114FONE: .long 0x3F800000
115FTEN: .long 0x41200000
116
117 .set TEN,10
118
119|
120decbin:
121 | fmovel #0,FPCR ;clr real fpcr
122 moveml %d2-%d5,-(%a7)
123|
124| Calculate exponent:
125| 1. Copy bcd value in memory for use as a working copy.
126| 2. Calculate absolute value of exponent in d1 by mul and add.
127| 3. Correct for exponent sign.
128| 4. Subtract 16 to compensate for interpreting the mant as all integer digits.
129| (i.e., all digits assumed left of the decimal point.)
130|
131| Register usage:
132|
133| calc_e:
134| (*) d0: temp digit storage
135| (*) d1: accumulator for binary exponent
136| (*) d2: digit count
137| (*) d3: offset pointer
138| ( ) d4: first word of bcd
139| ( ) a0: pointer to working bcd value
140| ( ) a6: pointer to original bcd value
141| (*) FP_SCR1: working copy of original bcd value
142| (*) L_SCR1: copy of original exponent word
143|
144calc_e:
145 movel #EDIGITS,%d2 |# of nibbles (digits) in fraction part
146 moveql #ESTRT,%d3 |counter to pick up digits
147 leal FP_SCR1(%a6),%a0 |load tmp bcd storage address
148 movel ETEMP(%a6),(%a0) |save input bcd value
149 movel ETEMP_HI(%a6),4(%a0) |save words 2 and 3
150 movel ETEMP_LO(%a6),8(%a0) |and work with these
151 movel (%a0),%d4 |get first word of bcd
152 clrl %d1 |zero d1 for accumulator
153e_gd:
154 mulul #TEN,%d1 |mul partial product by one digit place
155 bfextu %d4{%d3:#4},%d0 |get the digit and zero extend into d0
156 addl %d0,%d1 |d1 = d1 + d0
157 addqb #4,%d3 |advance d3 to the next digit
158 dbf %d2,e_gd |if we have used all 3 digits, exit loop
159 btst #30,%d4 |get SE
160 beqs e_pos |don't negate if pos
161 negl %d1 |negate before subtracting
162e_pos:
163 subl #16,%d1 |sub to compensate for shift of mant
164 bges e_save |if still pos, do not neg
165 negl %d1 |now negative, make pos and set SE
166 orl #0x40000000,%d4 |set SE in d4,
167 orl #0x40000000,(%a0) |and in working bcd
168e_save:
169 movel %d1,L_SCR1(%a6) |save exp in memory
170|
171|
172| Calculate mantissa:
173| 1. Calculate absolute value of mantissa in fp0 by mul and add.
174| 2. Correct for mantissa sign.
175| (i.e., all digits assumed left of the decimal point.)
176|
177| Register usage:
178|
179| calc_m:
180| (*) d0: temp digit storage
181| (*) d1: lword counter
182| (*) d2: digit count
183| (*) d3: offset pointer
184| ( ) d4: words 2 and 3 of bcd
185| ( ) a0: pointer to working bcd value
186| ( ) a6: pointer to original bcd value
187| (*) fp0: mantissa accumulator
188| ( ) FP_SCR1: working copy of original bcd value
189| ( ) L_SCR1: copy of original exponent word
190|
191calc_m:
192 moveql #1,%d1 |word counter, init to 1
193 fmoves FZERO,%fp0 |accumulator
194|
195|
196| Since the packed number has a long word between the first & second parts,
197| get the integer digit then skip down & get the rest of the
198| mantissa. We will unroll the loop once.
199|
200 bfextu (%a0){#28:#4},%d0 |integer part is ls digit in long word
201 faddb %d0,%fp0 |add digit to sum in fp0
202|
203|
204| Get the rest of the mantissa.
205|
206loadlw:
207 movel (%a0,%d1.L*4),%d4 |load mantissa longword into d4
208 moveql #FSTRT,%d3 |counter to pick up digits
209 moveql #FNIBS,%d2 |reset number of digits per a0 ptr
210md2b:
211 fmuls FTEN,%fp0 |fp0 = fp0 * 10
212 bfextu %d4{%d3:#4},%d0 |get the digit and zero extend
213 faddb %d0,%fp0 |fp0 = fp0 + digit
214|
215|
216| If all the digits (8) in that long word have been converted (d2=0),
217| then inc d1 (=2) to point to the next long word and reset d3 to 0
218| to initialize the digit offset, and set d2 to 7 for the digit count;
219| else continue with this long word.
220|
221 addqb #4,%d3 |advance d3 to the next digit
222 dbf %d2,md2b |check for last digit in this lw
223nextlw:
224 addql #1,%d1 |inc lw pointer in mantissa
225 cmpl #2,%d1 |test for last lw
226 ble loadlw |if not, get last one
227
228|
229| Check the sign of the mant and make the value in fp0 the same sign.
230|
231m_sign:
232 btst #31,(%a0) |test sign of the mantissa
233 beq ap_st_z |if clear, go to append/strip zeros
234 fnegx %fp0 |if set, negate fp0
235
236|
237| Append/strip zeros:
238|
239| For adjusted exponents which have an absolute value greater than 27*,
240| this routine calculates the amount needed to normalize the mantissa
241| for the adjusted exponent. That number is subtracted from the exp
242| if the exp was positive, and added if it was negative. The purpose
243| of this is to reduce the value of the exponent and the possibility
244| of error in calculation of pwrten.
245|
246| 1. Branch on the sign of the adjusted exponent.
247| 2p.(positive exp)
248| 2. Check M16 and the digits in lwords 2 and 3 in descending order.
249| 3. Add one for each zero encountered until a non-zero digit.
250| 4. Subtract the count from the exp.
251| 5. Check if the exp has crossed zero in #3 above; make the exp abs
252| and set SE.
253| 6. Multiply the mantissa by 10**count.
254| 2n.(negative exp)
255| 2. Check the digits in lwords 3 and 2 in descending order.
256| 3. Add one for each zero encountered until a non-zero digit.
257| 4. Add the count to the exp.
258| 5. Check if the exp has crossed zero in #3 above; clear SE.
259| 6. Divide the mantissa by 10**count.
260|
261| *Why 27? If the adjusted exponent is within -28 < expA < 28, than
262| any adjustment due to append/strip zeros will drive the resultant
263| exponent towards zero. Since all pwrten constants with a power
264| of 27 or less are exact, there is no need to use this routine to
265| attempt to lessen the resultant exponent.
266|
267| Register usage:
268|
269| ap_st_z:
270| (*) d0: temp digit storage
271| (*) d1: zero count
272| (*) d2: digit count
273| (*) d3: offset pointer
274| ( ) d4: first word of bcd
275| (*) d5: lword counter
276| ( ) a0: pointer to working bcd value
277| ( ) FP_SCR1: working copy of original bcd value
278| ( ) L_SCR1: copy of original exponent word
279|
280|
281| First check the absolute value of the exponent to see if this
282| routine is necessary. If so, then check the sign of the exponent
283| and do append (+) or strip (-) zeros accordingly.
284| This section handles a positive adjusted exponent.
285|
286ap_st_z:
287 movel L_SCR1(%a6),%d1 |load expA for range test
288 cmpl #27,%d1 |test is with 27
289 ble pwrten |if abs(expA) <28, skip ap/st zeros
290 btst #30,(%a0) |check sign of exp
291 bne ap_st_n |if neg, go to neg side
292 clrl %d1 |zero count reg
293 movel (%a0),%d4 |load lword 1 to d4
294 bfextu %d4{#28:#4},%d0 |get M16 in d0
295 bnes ap_p_fx |if M16 is non-zero, go fix exp
296 addql #1,%d1 |inc zero count
297 moveql #1,%d5 |init lword counter
298 movel (%a0,%d5.L*4),%d4 |get lword 2 to d4
299 bnes ap_p_cl |if lw 2 is zero, skip it
300 addql #8,%d1 |and inc count by 8
301 addql #1,%d5 |inc lword counter
302 movel (%a0,%d5.L*4),%d4 |get lword 3 to d4
303ap_p_cl:
304 clrl %d3 |init offset reg
305 moveql #7,%d2 |init digit counter
306ap_p_gd:
307 bfextu %d4{%d3:#4},%d0 |get digit
308 bnes ap_p_fx |if non-zero, go to fix exp
309 addql #4,%d3 |point to next digit
310 addql #1,%d1 |inc digit counter
311 dbf %d2,ap_p_gd |get next digit
312ap_p_fx:
313 movel %d1,%d0 |copy counter to d2
314 movel L_SCR1(%a6),%d1 |get adjusted exp from memory
315 subl %d0,%d1 |subtract count from exp
316 bges ap_p_fm |if still pos, go to pwrten
317 negl %d1 |now its neg; get abs
318 movel (%a0),%d4 |load lword 1 to d4
319 orl #0x40000000,%d4 | and set SE in d4
320 orl #0x40000000,(%a0) | and in memory
321|
322| Calculate the mantissa multiplier to compensate for the striping of
323| zeros from the mantissa.
324|
325ap_p_fm:
326 movel #PTENRN,%a1 |get address of power-of-ten table
327 clrl %d3 |init table index
328 fmoves FONE,%fp1 |init fp1 to 1
329 moveql #3,%d2 |init d2 to count bits in counter
330ap_p_el:
331 asrl #1,%d0 |shift lsb into carry
332 bccs ap_p_en |if 1, mul fp1 by pwrten factor
333 fmulx (%a1,%d3),%fp1 |mul by 10**(d3_bit_no)
334ap_p_en:
335 addl #12,%d3 |inc d3 to next rtable entry
336 tstl %d0 |check if d0 is zero
337 bnes ap_p_el |if not, get next bit
338 fmulx %fp1,%fp0 |mul mantissa by 10**(no_bits_shifted)
339 bra pwrten |go calc pwrten
340|
341| This section handles a negative adjusted exponent.
342|
343ap_st_n:
344 clrl %d1 |clr counter
345 moveql #2,%d5 |set up d5 to point to lword 3
346 movel (%a0,%d5.L*4),%d4 |get lword 3
347 bnes ap_n_cl |if not zero, check digits
348 subl #1,%d5 |dec d5 to point to lword 2
349 addql #8,%d1 |inc counter by 8
350 movel (%a0,%d5.L*4),%d4 |get lword 2
351ap_n_cl:
352 movel #28,%d3 |point to last digit
353 moveql #7,%d2 |init digit counter
354ap_n_gd:
355 bfextu %d4{%d3:#4},%d0 |get digit
356 bnes ap_n_fx |if non-zero, go to exp fix
357 subql #4,%d3 |point to previous digit
358 addql #1,%d1 |inc digit counter
359 dbf %d2,ap_n_gd |get next digit
360ap_n_fx:
361 movel %d1,%d0 |copy counter to d0
362 movel L_SCR1(%a6),%d1 |get adjusted exp from memory
363 subl %d0,%d1 |subtract count from exp
364 bgts ap_n_fm |if still pos, go fix mantissa
365 negl %d1 |take abs of exp and clr SE
366 movel (%a0),%d4 |load lword 1 to d4
367 andl #0xbfffffff,%d4 | and clr SE in d4
368 andl #0xbfffffff,(%a0) | and in memory
369|
370| Calculate the mantissa multiplier to compensate for the appending of
371| zeros to the mantissa.
372|
373ap_n_fm:
374 movel #PTENRN,%a1 |get address of power-of-ten table
375 clrl %d3 |init table index
376 fmoves FONE,%fp1 |init fp1 to 1
377 moveql #3,%d2 |init d2 to count bits in counter
378ap_n_el:
379 asrl #1,%d0 |shift lsb into carry
380 bccs ap_n_en |if 1, mul fp1 by pwrten factor
381 fmulx (%a1,%d3),%fp1 |mul by 10**(d3_bit_no)
382ap_n_en:
383 addl #12,%d3 |inc d3 to next rtable entry
384 tstl %d0 |check if d0 is zero
385 bnes ap_n_el |if not, get next bit
386 fdivx %fp1,%fp0 |div mantissa by 10**(no_bits_shifted)
387|
388|
389| Calculate power-of-ten factor from adjusted and shifted exponent.
390|
391| Register usage:
392|
393| pwrten:
394| (*) d0: temp
395| ( ) d1: exponent
396| (*) d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp
397| (*) d3: FPCR work copy
398| ( ) d4: first word of bcd
399| (*) a1: RTABLE pointer
400| calc_p:
401| (*) d0: temp
402| ( ) d1: exponent
403| (*) d3: PWRTxx table index
404| ( ) a0: pointer to working copy of bcd
405| (*) a1: PWRTxx pointer
406| (*) fp1: power-of-ten accumulator
407|
408| Pwrten calculates the exponent factor in the selected rounding mode
409| according to the following table:
410|
411| Sign of Mant Sign of Exp Rounding Mode PWRTEN Rounding Mode
412|
413| ANY ANY RN RN
414|
415| + + RP RP
416| - + RP RM
417| + - RP RM
418| - - RP RP
419|
420| + + RM RM
421| - + RM RP
422| + - RM RP
423| - - RM RM
424|
425| + + RZ RM
426| - + RZ RM
427| + - RZ RP
428| - - RZ RP
429|
430|
431pwrten:
432 movel USER_FPCR(%a6),%d3 |get user's FPCR
433 bfextu %d3{#26:#2},%d2 |isolate rounding mode bits
434 movel (%a0),%d4 |reload 1st bcd word to d4
435 asll #2,%d2 |format d2 to be
436 bfextu %d4{#0:#2},%d0 | {FPCR[6],FPCR[5],SM,SE}
437 addl %d0,%d2 |in d2 as index into RTABLE
438 leal RTABLE,%a1 |load rtable base
439 moveb (%a1,%d2),%d0 |load new rounding bits from table
440 clrl %d3 |clear d3 to force no exc and extended
441 bfins %d0,%d3{#26:#2} |stuff new rounding bits in FPCR
442 fmovel %d3,%FPCR |write new FPCR
443 asrl #1,%d0 |write correct PTENxx table
444 bccs not_rp |to a1
445 leal PTENRP,%a1 |it is RP
446 bras calc_p |go to init section
447not_rp:
448 asrl #1,%d0 |keep checking
449 bccs not_rm
450 leal PTENRM,%a1 |it is RM
451 bras calc_p |go to init section
452not_rm:
453 leal PTENRN,%a1 |it is RN
454calc_p:
455 movel %d1,%d0 |copy exp to d0;use d0
456 bpls no_neg |if exp is negative,
457 negl %d0 |invert it
458 orl #0x40000000,(%a0) |and set SE bit
459no_neg:
460 clrl %d3 |table index
461 fmoves FONE,%fp1 |init fp1 to 1
462e_loop:
463 asrl #1,%d0 |shift next bit into carry
464 bccs e_next |if zero, skip the mul
465 fmulx (%a1,%d3),%fp1 |mul by 10**(d3_bit_no)
466e_next:
467 addl #12,%d3 |inc d3 to next rtable entry
468 tstl %d0 |check if d0 is zero
469 bnes e_loop |not zero, continue shifting
470|
471|
472| Check the sign of the adjusted exp and make the value in fp0 the
473| same sign. If the exp was pos then multiply fp1*fp0;
474| else divide fp0/fp1.
475|
476| Register Usage:
477| norm:
478| ( ) a0: pointer to working bcd value
479| (*) fp0: mantissa accumulator
480| ( ) fp1: scaling factor - 10**(abs(exp))
481|
482norm:
483 btst #30,(%a0) |test the sign of the exponent
484 beqs mul |if clear, go to multiply
485div:
486 fdivx %fp1,%fp0 |exp is negative, so divide mant by exp
487 bras end_dec
488mul:
489 fmulx %fp1,%fp0 |exp is positive, so multiply by exp
490|
491|
492| Clean up and return with result in fp0.
493|
494| If the final mul/div in decbin incurred an inex exception,
495| it will be inex2, but will be reported as inex1 by get_op.
496|
497end_dec:
498 fmovel %FPSR,%d0 |get status register
499 bclrl #inex2_bit+8,%d0 |test for inex2 and clear it
500 fmovel %d0,%FPSR |return status reg w/o inex2
501 beqs no_exc |skip this if no exc
502 orl #inx1a_mask,USER_FPSR(%a6) |set inex1/ainex
503no_exc:
504 moveml (%a7)+,%d2-%d5
505 rts
506 |end
diff --git a/arch/m68k/fpsp040/do_func.S b/arch/m68k/fpsp040/do_func.S
new file mode 100644
index 000000000000..81f6a9856dce
--- /dev/null
+++ b/arch/m68k/fpsp040/do_func.S
@@ -0,0 +1,559 @@
1|
2| do_func.sa 3.4 2/18/91
3|
4| Do_func performs the unimplemented operation. The operation
5| to be performed is determined from the lower 7 bits of the
6| extension word (except in the case of fmovecr and fsincos).
7| The opcode and tag bits form an index into a jump table in
8| tbldo.sa. Cases of zero, infinity and NaN are handled in
9| do_func by forcing the default result. Normalized and
10| denormalized (there are no unnormalized numbers at this
11| point) are passed onto the emulation code.
12|
13| CMDREG1B and STAG are extracted from the fsave frame
14| and combined to form the table index. The function called
15| will start with a0 pointing to the ETEMP operand. Dyadic
16| functions can find FPTEMP at -12(a0).
17|
18| Called functions return their result in fp0. Sincos returns
19| sin(x) in fp0 and cos(x) in fp1.
20|
21
22| Copyright (C) Motorola, Inc. 1990
23| All Rights Reserved
24|
25| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
26| The copyright notice above does not evidence any
27| actual or intended publication of such source code.
28
29DO_FUNC: |idnt 2,1 | Motorola 040 Floating Point Software Package
30
31 |section 8
32
33#include "fpsp.h"
34
35 |xref t_dz2
36 |xref t_operr
37 |xref t_inx2
38 |xref t_resdnrm
39 |xref dst_nan
40 |xref src_nan
41 |xref nrm_set
42 |xref sto_cos
43
44 |xref tblpre
45 |xref slognp1,slogn,slog10,slog2
46 |xref slognd,slog10d,slog2d
47 |xref smod,srem
48 |xref sscale
49 |xref smovcr
50
51PONE: .long 0x3fff0000,0x80000000,0x00000000 |+1
52MONE: .long 0xbfff0000,0x80000000,0x00000000 |-1
53PZERO: .long 0x00000000,0x00000000,0x00000000 |+0
54MZERO: .long 0x80000000,0x00000000,0x00000000 |-0
55PINF: .long 0x7fff0000,0x00000000,0x00000000 |+inf
56MINF: .long 0xffff0000,0x00000000,0x00000000 |-inf
57QNAN: .long 0x7fff0000,0xffffffff,0xffffffff |non-signaling nan
58PPIBY2: .long 0x3FFF0000,0xC90FDAA2,0x2168C235 |+PI/2
59MPIBY2: .long 0xbFFF0000,0xC90FDAA2,0x2168C235 |-PI/2
60
61 .global do_func
62do_func:
63 clrb CU_ONLY(%a6)
64|
65| Check for fmovecr. It does not follow the format of fp gen
66| unimplemented instructions. The test is on the upper 6 bits;
67| if they are $17, the inst is fmovecr. Call entry smovcr
68| directly.
69|
70 bfextu CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
71 cmpil #0x17,%d0 |if op class and size fields are $17,
72| ;it is FMOVECR; if not, continue
73 bnes not_fmovecr
74 jmp smovcr |fmovecr; jmp directly to emulation
75
76not_fmovecr:
77 movew CMDREG1B(%a6),%d0
78 andl #0x7F,%d0
79 cmpil #0x38,%d0 |if the extension is >= $38,
80 bge serror |it is illegal
81 bfextu STAG(%a6){#0:#3},%d1
82 lsll #3,%d0 |make room for STAG
83 addl %d1,%d0 |combine for final index into table
84 leal tblpre,%a1 |start of monster jump table
85 movel (%a1,%d0.w*4),%a1 |real target address
86 leal ETEMP(%a6),%a0 |a0 is pointer to src op
87 movel USER_FPCR(%a6),%d1
88 andl #0xFF,%d1 | discard all but rounding mode/prec
89 fmovel #0,%fpcr
90 jmp (%a1)
91|
92| ERROR
93|
94 .global serror
95serror:
96 st STORE_FLG(%a6)
97 rts
98|
99| These routines load forced values into fp0. They are called
100| by index into tbldo.
101|
102| Load a signed zero to fp0 and set inex2/ainex
103|
104 .global snzrinx
105snzrinx:
106 btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand
107 bnes ld_mzinx |if negative, branch
108 bsr ld_pzero |bsr so we can return and set inx
109 bra t_inx2 |now, set the inx for the next inst
110ld_mzinx:
111 bsr ld_mzero |if neg, load neg zero, return here
112 bra t_inx2 |now, set the inx for the next inst
113|
114| Load a signed zero to fp0; do not set inex2/ainex
115|
116 .global szero
117szero:
118 btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand
119 bne ld_mzero |if neg, load neg zero
120 bra ld_pzero |load positive zero
121|
122| Load a signed infinity to fp0; do not set inex2/ainex
123|
124 .global sinf
125sinf:
126 btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand
127 bne ld_minf |if negative branch
128 bra ld_pinf
129|
130| Load a signed one to fp0; do not set inex2/ainex
131|
132 .global sone
133sone:
134 btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
135 bne ld_mone
136 bra ld_pone
137|
138| Load a signed pi/2 to fp0; do not set inex2/ainex
139|
140 .global spi_2
141spi_2:
142 btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
143 bne ld_mpi2
144 bra ld_ppi2
145|
146| Load either a +0 or +inf for plus/minus operand
147|
148 .global szr_inf
149szr_inf:
150 btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
151 bne ld_pzero
152 bra ld_pinf
153|
154| Result is either an operr or +inf for plus/minus operand
155| [Used by slogn, slognp1, slog10, and slog2]
156|
157 .global sopr_inf
158sopr_inf:
159 btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
160 bne t_operr
161 bra ld_pinf
162|
163| FLOGNP1
164|
165 .global sslognp1
166sslognp1:
167 fmovemx (%a0),%fp0-%fp0
168 fcmpb #-1,%fp0
169 fbgt slognp1
170 fbeq t_dz2 |if = -1, divide by zero exception
171 fmovel #0,%FPSR |clr N flag
172 bra t_operr |take care of operands < -1
173|
174| FETOXM1
175|
176 .global setoxm1i
177setoxm1i:
178 btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
179 bne ld_mone
180 bra ld_pinf
181|
182| FLOGN
183|
184| Test for 1.0 as an input argument, returning +zero. Also check
185| the sign and return operr if negative.
186|
187 .global sslogn
188sslogn:
189 btstb #sign_bit,LOCAL_EX(%a0)
190 bne t_operr |take care of operands < 0
191 cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
192 bne slogn
193 cmpil #0x80000000,LOCAL_HI(%a0)
194 bne slogn
195 tstl LOCAL_LO(%a0)
196 bne slogn
197 fmovex PZERO,%fp0
198 rts
199
200 .global sslognd
201sslognd:
202 btstb #sign_bit,LOCAL_EX(%a0)
203 beq slognd
204 bra t_operr |take care of operands < 0
205
206|
207| FLOG10
208|
209 .global sslog10
210sslog10:
211 btstb #sign_bit,LOCAL_EX(%a0)
212 bne t_operr |take care of operands < 0
213 cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
214 bne slog10
215 cmpil #0x80000000,LOCAL_HI(%a0)
216 bne slog10
217 tstl LOCAL_LO(%a0)
218 bne slog10
219 fmovex PZERO,%fp0
220 rts
221
222 .global sslog10d
223sslog10d:
224 btstb #sign_bit,LOCAL_EX(%a0)
225 beq slog10d
226 bra t_operr |take care of operands < 0
227
228|
229| FLOG2
230|
231 .global sslog2
232sslog2:
233 btstb #sign_bit,LOCAL_EX(%a0)
234 bne t_operr |take care of operands < 0
235 cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
236 bne slog2
237 cmpil #0x80000000,LOCAL_HI(%a0)
238 bne slog2
239 tstl LOCAL_LO(%a0)
240 bne slog2
241 fmovex PZERO,%fp0
242 rts
243
244 .global sslog2d
245sslog2d:
246 btstb #sign_bit,LOCAL_EX(%a0)
247 beq slog2d
248 bra t_operr |take care of operands < 0
249
250|
251| FMOD
252|
253pmodt:
254| ;$21 fmod
255| ;dtag,stag
256 .long smod | 00,00 norm,norm = normal
257 .long smod_oper | 00,01 norm,zero = nan with operr
258 .long smod_fpn | 00,10 norm,inf = fpn
259 .long smod_snan | 00,11 norm,nan = nan
260 .long smod_zro | 01,00 zero,norm = +-zero
261 .long smod_oper | 01,01 zero,zero = nan with operr
262 .long smod_zro | 01,10 zero,inf = +-zero
263 .long smod_snan | 01,11 zero,nan = nan
264 .long smod_oper | 10,00 inf,norm = nan with operr
265 .long smod_oper | 10,01 inf,zero = nan with operr
266 .long smod_oper | 10,10 inf,inf = nan with operr
267 .long smod_snan | 10,11 inf,nan = nan
268 .long smod_dnan | 11,00 nan,norm = nan
269 .long smod_dnan | 11,01 nan,zero = nan
270 .long smod_dnan | 11,10 nan,inf = nan
271 .long smod_dnan | 11,11 nan,nan = nan
272
273 .global pmod
274pmod:
275 clrb FPSR_QBYTE(%a6) | clear quotient field
276 bfextu STAG(%a6){#0:#3},%d0 |stag = d0
277 bfextu DTAG(%a6){#0:#3},%d1 |dtag = d1
278
279|
280| Alias extended denorms to norms for the jump table.
281|
282 bclrl #2,%d0
283 bclrl #2,%d1
284
285 lslb #2,%d1
286 orb %d0,%d1 |d1{3:2} = dtag, d1{1:0} = stag
287| ;Tag values:
288| ;00 = norm or denorm
289| ;01 = zero
290| ;10 = inf
291| ;11 = nan
292 lea pmodt,%a1
293 movel (%a1,%d1.w*4),%a1
294 jmp (%a1)
295
296smod_snan:
297 bra src_nan
298smod_dnan:
299 bra dst_nan
300smod_oper:
301 bra t_operr
302smod_zro:
303 moveb ETEMP(%a6),%d1 |get sign of src op
304 moveb FPTEMP(%a6),%d0 |get sign of dst op
305 eorb %d0,%d1 |get exor of sign bits
306 btstl #7,%d1 |test for sign
307 beqs smod_zsn |if clr, do not set sign big
308 bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
309smod_zsn:
310 btstl #7,%d0 |test if + or -
311 beq ld_pzero |if pos then load +0
312 bra ld_mzero |else neg load -0
313
314smod_fpn:
315 moveb ETEMP(%a6),%d1 |get sign of src op
316 moveb FPTEMP(%a6),%d0 |get sign of dst op
317 eorb %d0,%d1 |get exor of sign bits
318 btstl #7,%d1 |test for sign
319 beqs smod_fsn |if clr, do not set sign big
320 bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
321smod_fsn:
322 tstb DTAG(%a6) |filter out denormal destination case
323 bpls smod_nrm |
324 leal FPTEMP(%a6),%a0 |a0<- addr(FPTEMP)
325 bra t_resdnrm |force UNFL(but exact) result
326smod_nrm:
327 fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
328 fmovex FPTEMP(%a6),%fp0 |return dest to fp0
329 rts
330
331|
332| FREM
333|
334premt:
335| ;$25 frem
336| ;dtag,stag
337 .long srem | 00,00 norm,norm = normal
338 .long srem_oper | 00,01 norm,zero = nan with operr
339 .long srem_fpn | 00,10 norm,inf = fpn
340 .long srem_snan | 00,11 norm,nan = nan
341 .long srem_zro | 01,00 zero,norm = +-zero
342 .long srem_oper | 01,01 zero,zero = nan with operr
343 .long srem_zro | 01,10 zero,inf = +-zero
344 .long srem_snan | 01,11 zero,nan = nan
345 .long srem_oper | 10,00 inf,norm = nan with operr
346 .long srem_oper | 10,01 inf,zero = nan with operr
347 .long srem_oper | 10,10 inf,inf = nan with operr
348 .long srem_snan | 10,11 inf,nan = nan
349 .long srem_dnan | 11,00 nan,norm = nan
350 .long srem_dnan | 11,01 nan,zero = nan
351 .long srem_dnan | 11,10 nan,inf = nan
352 .long srem_dnan | 11,11 nan,nan = nan
353
354 .global prem
355prem:
356 clrb FPSR_QBYTE(%a6) |clear quotient field
357 bfextu STAG(%a6){#0:#3},%d0 |stag = d0
358 bfextu DTAG(%a6){#0:#3},%d1 |dtag = d1
359|
360| Alias extended denorms to norms for the jump table.
361|
362 bclr #2,%d0
363 bclr #2,%d1
364
365 lslb #2,%d1
366 orb %d0,%d1 |d1{3:2} = dtag, d1{1:0} = stag
367| ;Tag values:
368| ;00 = norm or denorm
369| ;01 = zero
370| ;10 = inf
371| ;11 = nan
372 lea premt,%a1
373 movel (%a1,%d1.w*4),%a1
374 jmp (%a1)
375
376srem_snan:
377 bra src_nan
378srem_dnan:
379 bra dst_nan
380srem_oper:
381 bra t_operr
382srem_zro:
383 moveb ETEMP(%a6),%d1 |get sign of src op
384 moveb FPTEMP(%a6),%d0 |get sign of dst op
385 eorb %d0,%d1 |get exor of sign bits
386 btstl #7,%d1 |test for sign
387 beqs srem_zsn |if clr, do not set sign big
388 bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
389srem_zsn:
390 btstl #7,%d0 |test if + or -
391 beq ld_pzero |if pos then load +0
392 bra ld_mzero |else neg load -0
393
394srem_fpn:
395 moveb ETEMP(%a6),%d1 |get sign of src op
396 moveb FPTEMP(%a6),%d0 |get sign of dst op
397 eorb %d0,%d1 |get exor of sign bits
398 btstl #7,%d1 |test for sign
399 beqs srem_fsn |if clr, do not set sign big
400 bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
401srem_fsn:
402 tstb DTAG(%a6) |filter out denormal destination case
403 bpls srem_nrm |
404 leal FPTEMP(%a6),%a0 |a0<- addr(FPTEMP)
405 bra t_resdnrm |force UNFL(but exact) result
406srem_nrm:
407 fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
408 fmovex FPTEMP(%a6),%fp0 |return dest to fp0
409 rts
410|
411| FSCALE
412|
413pscalet:
414| ;$26 fscale
415| ;dtag,stag
416 .long sscale | 00,00 norm,norm = result
417 .long sscale | 00,01 norm,zero = fpn
418 .long scl_opr | 00,10 norm,inf = nan with operr
419 .long scl_snan | 00,11 norm,nan = nan
420 .long scl_zro | 01,00 zero,norm = +-zero
421 .long scl_zro | 01,01 zero,zero = +-zero
422 .long scl_opr | 01,10 zero,inf = nan with operr
423 .long scl_snan | 01,11 zero,nan = nan
424 .long scl_inf | 10,00 inf,norm = +-inf
425 .long scl_inf | 10,01 inf,zero = +-inf
426 .long scl_opr | 10,10 inf,inf = nan with operr
427 .long scl_snan | 10,11 inf,nan = nan
428 .long scl_dnan | 11,00 nan,norm = nan
429 .long scl_dnan | 11,01 nan,zero = nan
430 .long scl_dnan | 11,10 nan,inf = nan
431 .long scl_dnan | 11,11 nan,nan = nan
432
433 .global pscale
434pscale:
435 bfextu STAG(%a6){#0:#3},%d0 |stag in d0
436 bfextu DTAG(%a6){#0:#3},%d1 |dtag in d1
437 bclrl #2,%d0 |alias denorm into norm
438 bclrl #2,%d1 |alias denorm into norm
439 lslb #2,%d1
440 orb %d0,%d1 |d1{4:2} = dtag, d1{1:0} = stag
441| ;dtag values stag values:
442| ;000 = norm 00 = norm
443| ;001 = zero 01 = zero
444| ;010 = inf 10 = inf
445| ;011 = nan 11 = nan
446| ;100 = dnrm
447|
448|
449 leal pscalet,%a1 |load start of jump table
450 movel (%a1,%d1.w*4),%a1 |load a1 with label depending on tag
451 jmp (%a1) |go to the routine
452
453scl_opr:
454 bra t_operr
455
456scl_dnan:
457 bra dst_nan
458
459scl_zro:
460 btstb #sign_bit,FPTEMP_EX(%a6) |test if + or -
461 beq ld_pzero |if pos then load +0
462 bra ld_mzero |if neg then load -0
463scl_inf:
464 btstb #sign_bit,FPTEMP_EX(%a6) |test if + or -
465 beq ld_pinf |if pos then load +inf
466 bra ld_minf |else neg load -inf
467scl_snan:
468 bra src_nan
469|
470| FSINCOS
471|
472 .global ssincosz
473ssincosz:
474 btstb #sign_bit,ETEMP(%a6) |get sign
475 beqs sincosp
476 fmovex MZERO,%fp0
477 bras sincoscom
478sincosp:
479 fmovex PZERO,%fp0
480sincoscom:
481 fmovemx PONE,%fp1-%fp1 |do not allow FPSR to be affected
482 bra sto_cos |store cosine result
483
484 .global ssincosi
485ssincosi:
486 fmovex QNAN,%fp1 |load NAN
487 bsr sto_cos |store cosine result
488 fmovex QNAN,%fp0 |load NAN
489 bra t_operr
490
491 .global ssincosnan
492ssincosnan:
493 movel ETEMP_EX(%a6),FP_SCR1(%a6)
494 movel ETEMP_HI(%a6),FP_SCR1+4(%a6)
495 movel ETEMP_LO(%a6),FP_SCR1+8(%a6)
496 bsetb #signan_bit,FP_SCR1+4(%a6)
497 fmovemx FP_SCR1(%a6),%fp1-%fp1
498 bsr sto_cos
499 bra src_nan
500|
501| This code forces default values for the zero, inf, and nan cases
502| in the transcendentals code. The CC bits must be set in the
503| stacked FPSR to be correctly reported.
504|
505|**Returns +PI/2
506 .global ld_ppi2
507ld_ppi2:
508 fmovex PPIBY2,%fp0 |load +pi/2
509 bra t_inx2 |set inex2 exc
510
511|**Returns -PI/2
512 .global ld_mpi2
513ld_mpi2:
514 fmovex MPIBY2,%fp0 |load -pi/2
515 orl #neg_mask,USER_FPSR(%a6) |set N bit
516 bra t_inx2 |set inex2 exc
517
518|**Returns +inf
519 .global ld_pinf
520ld_pinf:
521 fmovex PINF,%fp0 |load +inf
522 orl #inf_mask,USER_FPSR(%a6) |set I bit
523 rts
524
525|**Returns -inf
526 .global ld_minf
527ld_minf:
528 fmovex MINF,%fp0 |load -inf
529 orl #neg_mask+inf_mask,USER_FPSR(%a6) |set N and I bits
530 rts
531
532|**Returns +1
533 .global ld_pone
534ld_pone:
535 fmovex PONE,%fp0 |load +1
536 rts
537
538|**Returns -1
539 .global ld_mone
540ld_mone:
541 fmovex MONE,%fp0 |load -1
542 orl #neg_mask,USER_FPSR(%a6) |set N bit
543 rts
544
545|**Returns +0
546 .global ld_pzero
547ld_pzero:
548 fmovex PZERO,%fp0 |load +0
549 orl #z_mask,USER_FPSR(%a6) |set Z bit
550 rts
551
552|**Returns -0
553 .global ld_mzero
554ld_mzero:
555 fmovex MZERO,%fp0 |load -0
556 orl #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z bits
557 rts
558
559 |end
diff --git a/arch/m68k/fpsp040/fpsp.h b/arch/m68k/fpsp040/fpsp.h
new file mode 100644
index 000000000000..984a4eb8010a
--- /dev/null
+++ b/arch/m68k/fpsp040/fpsp.h
@@ -0,0 +1,348 @@
1|
2| fpsp.h 3.3 3.3
3|
4
5| Copyright (C) Motorola, Inc. 1990
6| All Rights Reserved
7|
8| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
9| The copyright notice above does not evidence any
10| actual or intended publication of such source code.
11
12| fpsp.h --- stack frame offsets during FPSP exception handling
13|
14| These equates are used to access the exception frame, the fsave
15| frame and any local variables needed by the FPSP package.
16|
17| All FPSP handlers begin by executing:
18|
19| link a6,#-LOCAL_SIZE
20| fsave -(a7)
21| movem.l d0-d1/a0-a1,USER_DA(a6)
22| fmovem.x fp0-fp3,USER_FP0(a6)
23| fmove.l fpsr/fpcr/fpiar,USER_FPSR(a6)
24|
25| After initialization, the stack looks like this:
26|
27| A7 ---> +-------------------------------+
28| | |
29| | FPU fsave area |
30| | |
31| +-------------------------------+
32| | |
33| | FPSP Local Variables |
34| | including |
35| | saved registers |
36| | |
37| +-------------------------------+
38| A6 ---> | Saved A6 |
39| +-------------------------------+
40| | |
41| | Exception Frame |
42| | |
43| | |
44|
45| Positive offsets from A6 refer to the exception frame. Negative
46| offsets refer to the Local Variable area and the fsave area.
47| The fsave frame is also accessible from the top via A7.
48|
49| On exit, the handlers execute:
50|
51| movem.l USER_DA(a6),d0-d1/a0-a1
52| fmovem.x USER_FP0(a6),fp0-fp3
53| fmove.l USER_FPSR(a6),fpsr/fpcr/fpiar
54| frestore (a7)+
55| unlk a6
56|
57| and then either "bra fpsp_done" if the exception was completely
58| handled by the package, or "bra real_xxxx" which is an external
59| label to a routine that will process a real exception of the
60| type that was generated. Some handlers may omit the "frestore"
61| if the FPU state after the exception is idle.
62|
63| Sometimes the exception handler will transform the fsave area
64| because it needs to report an exception back to the user. This
65| can happen if the package is entered for an unimplemented float
66| instruction that generates (say) an underflow. Alternatively,
67| a second fsave frame can be pushed onto the stack and the
68| handler exit code will reload the new frame and discard the old.
69|
70| The registers d0, d1, a0, a1 and fp0-fp3 are always saved and
71| restored from the "local variable" area and can be used as
72| temporaries. If a routine needs to change any
73| of these registers, it should modify the saved copy and let
74| the handler exit code restore the value.
75|
76|----------------------------------------------------------------------
77|
78| Local Variables on the stack
79|
80 .set LOCAL_SIZE,192 | bytes needed for local variables
81 .set LV,-LOCAL_SIZE | convenient base value
82|
83 .set USER_DA,LV+0 | save space for D0-D1,A0-A1
84 .set USER_D0,LV+0 | saved user D0
85 .set USER_D1,LV+4 | saved user D1
86 .set USER_A0,LV+8 | saved user A0
87 .set USER_A1,LV+12 | saved user A1
88 .set USER_FP0,LV+16 | saved user FP0
89 .set USER_FP1,LV+28 | saved user FP1
90 .set USER_FP2,LV+40 | saved user FP2
91 .set USER_FP3,LV+52 | saved user FP3
92 .set USER_FPCR,LV+64 | saved user FPCR
93 .set FPCR_ENABLE,USER_FPCR+2 | FPCR exception enable
94 .set FPCR_MODE,USER_FPCR+3 | FPCR rounding mode control
95 .set USER_FPSR,LV+68 | saved user FPSR
96 .set FPSR_CC,USER_FPSR+0 | FPSR condition code
97 .set FPSR_QBYTE,USER_FPSR+1 | FPSR quotient
98 .set FPSR_EXCEPT,USER_FPSR+2 | FPSR exception
99 .set FPSR_AEXCEPT,USER_FPSR+3 | FPSR accrued exception
100 .set USER_FPIAR,LV+72 | saved user FPIAR
101 .set FP_SCR1,LV+76 | room for a temporary float value
102 .set FP_SCR2,LV+92 | room for a temporary float value
103 .set L_SCR1,LV+108 | room for a temporary long value
104 .set L_SCR2,LV+112 | room for a temporary long value
105 .set STORE_FLG,LV+116
106 .set BINDEC_FLG,LV+117 | used in bindec
107 .set DNRM_FLG,LV+118 | used in res_func
108 .set RES_FLG,LV+119 | used in res_func
109 .set DY_MO_FLG,LV+120 | dyadic/monadic flag
110 .set UFLG_TMP,LV+121 | temporary for uflag errata
111 .set CU_ONLY,LV+122 | cu-only flag
112 .set VER_TMP,LV+123 | temp holding for version number
113 .set L_SCR3,LV+124 | room for a temporary long value
114 .set FP_SCR3,LV+128 | room for a temporary float value
115 .set FP_SCR4,LV+144 | room for a temporary float value
116 .set FP_SCR5,LV+160 | room for a temporary float value
117 .set FP_SCR6,LV+176
118|
119|NEXT equ LV+192 ;need to increase LOCAL_SIZE
120|
121|--------------------------------------------------------------------------
122|
123| fsave offsets and bit definitions
124|
125| Offsets are defined from the end of an fsave because the last 10
126| words of a busy frame are the same as the unimplemented frame.
127|
128 .set CU_SAVEPC,LV-92 | micro-pc for CU (1 byte)
129 .set FPR_DIRTY_BITS,LV-91 | fpr dirty bits
130|
131 .set WBTEMP,LV-76 | write back temp (12 bytes)
132 .set WBTEMP_EX,WBTEMP | wbtemp sign and exponent (2 bytes)
133 .set WBTEMP_HI,WBTEMP+4 | wbtemp mantissa [63:32] (4 bytes)
134 .set WBTEMP_LO,WBTEMP+8 | wbtemp mantissa [31:00] (4 bytes)
135|
136 .set WBTEMP_SGN,WBTEMP+2 | used to store sign
137|
138 .set FPSR_SHADOW,LV-64 | fpsr shadow reg
139|
140 .set FPIARCU,LV-60 | Instr. addr. reg. for CU (4 bytes)
141|
142 .set CMDREG2B,LV-52 | cmd reg for machine 2
143 .set CMDREG3B,LV-48 | cmd reg for E3 exceptions (2 bytes)
144|
145 .set NMNEXC,LV-44 | NMNEXC (unsup,snan bits only)
146 .set nmn_unsup_bit,1 |
147 .set nmn_snan_bit,0 |
148|
149 .set NMCEXC,LV-43 | NMNEXC & NMCEXC
150 .set nmn_operr_bit,7
151 .set nmn_ovfl_bit,6
152 .set nmn_unfl_bit,5
153 .set nmc_unsup_bit,4
154 .set nmc_snan_bit,3
155 .set nmc_operr_bit,2
156 .set nmc_ovfl_bit,1
157 .set nmc_unfl_bit,0
158|
159 .set STAG,LV-40 | source tag (1 byte)
160 .set WBTEMP_GRS,LV-40 | alias wbtemp guard, round, sticky
161 .set guard_bit,1 | guard bit is bit number 1
162 .set round_bit,0 | round bit is bit number 0
163 .set stag_mask,0xE0 | upper 3 bits are source tag type
164 .set denorm_bit,7 | bit determines if denorm or unnorm
165 .set etemp15_bit,4 | etemp exponent bit #15
166 .set wbtemp66_bit,2 | wbtemp mantissa bit #66
167 .set wbtemp1_bit,1 | wbtemp mantissa bit #1
168 .set wbtemp0_bit,0 | wbtemp mantissa bit #0
169|
170 .set STICKY,LV-39 | holds sticky bit
171 .set sticky_bit,7
172|
173 .set CMDREG1B,LV-36 | cmd reg for E1 exceptions (2 bytes)
174 .set kfact_bit,12 | distinguishes static/dynamic k-factor
175| ;on packed move outs. NOTE: this
176| ;equate only works when CMDREG1B is in
177| ;a register.
178|
179 .set CMDWORD,LV-35 | command word in cmd1b
180 .set direction_bit,5 | bit 0 in opclass
181 .set size_bit2,12 | bit 2 in size field
182|
183 .set DTAG,LV-32 | dest tag (1 byte)
184 .set dtag_mask,0xE0 | upper 3 bits are dest type tag
185 .set fptemp15_bit,4 | fptemp exponent bit #15
186|
187 .set WB_BYTE,LV-31 | holds WBTE15 bit (1 byte)
188 .set wbtemp15_bit,4 | wbtemp exponent bit #15
189|
190 .set E_BYTE,LV-28 | holds E1 and E3 bits (1 byte)
191 .set E1,2 | which bit is E1 flag
192 .set E3,1 | which bit is E3 flag
193 .set SFLAG,0 | which bit is S flag
194|
195 .set T_BYTE,LV-27 | holds T and U bits (1 byte)
196 .set XFLAG,7 | which bit is X flag
197 .set UFLAG,5 | which bit is U flag
198 .set TFLAG,4 | which bit is T flag
199|
200 .set FPTEMP,LV-24 | fptemp (12 bytes)
201 .set FPTEMP_EX,FPTEMP | fptemp sign and exponent (2 bytes)
202 .set FPTEMP_HI,FPTEMP+4 | fptemp mantissa [63:32] (4 bytes)
203 .set FPTEMP_LO,FPTEMP+8 | fptemp mantissa [31:00] (4 bytes)
204|
205 .set FPTEMP_SGN,FPTEMP+2 | used to store sign
206|
207 .set ETEMP,LV-12 | etemp (12 bytes)
208 .set ETEMP_EX,ETEMP | etemp sign and exponent (2 bytes)
209 .set ETEMP_HI,ETEMP+4 | etemp mantissa [63:32] (4 bytes)
210 .set ETEMP_LO,ETEMP+8 | etemp mantissa [31:00] (4 bytes)
211|
212 .set ETEMP_SGN,ETEMP+2 | used to store sign
213|
214 .set EXC_SR,4 | exception frame status register
215 .set EXC_PC,6 | exception frame program counter
216 .set EXC_VEC,10 | exception frame vector (format+vector#)
217 .set EXC_EA,12 | exception frame effective address
218|
219|--------------------------------------------------------------------------
220|
221| FPSR/FPCR bits
222|
223 .set neg_bit,3 | negative result
224 .set z_bit,2 | zero result
225 .set inf_bit,1 | infinity result
226 .set nan_bit,0 | not-a-number result
227|
228 .set q_sn_bit,7 | sign bit of quotient byte
229|
230 .set bsun_bit,7 | branch on unordered
231 .set snan_bit,6 | signalling nan
232 .set operr_bit,5 | operand error
233 .set ovfl_bit,4 | overflow
234 .set unfl_bit,3 | underflow
235 .set dz_bit,2 | divide by zero
236 .set inex2_bit,1 | inexact result 2
237 .set inex1_bit,0 | inexact result 1
238|
239 .set aiop_bit,7 | accrued illegal operation
240 .set aovfl_bit,6 | accrued overflow
241 .set aunfl_bit,5 | accrued underflow
242 .set adz_bit,4 | accrued divide by zero
243 .set ainex_bit,3 | accrued inexact
244|
245| FPSR individual bit masks
246|
247 .set neg_mask,0x08000000
248 .set z_mask,0x04000000
249 .set inf_mask,0x02000000
250 .set nan_mask,0x01000000
251|
252 .set bsun_mask,0x00008000 |
253 .set snan_mask,0x00004000
254 .set operr_mask,0x00002000
255 .set ovfl_mask,0x00001000
256 .set unfl_mask,0x00000800
257 .set dz_mask,0x00000400
258 .set inex2_mask,0x00000200
259 .set inex1_mask,0x00000100
260|
261 .set aiop_mask,0x00000080 | accrued illegal operation
262 .set aovfl_mask,0x00000040 | accrued overflow
263 .set aunfl_mask,0x00000020 | accrued underflow
264 .set adz_mask,0x00000010 | accrued divide by zero
265 .set ainex_mask,0x00000008 | accrued inexact
266|
267| FPSR combinations used in the FPSP
268|
269 .set dzinf_mask,inf_mask+dz_mask+adz_mask
270 .set opnan_mask,nan_mask+operr_mask+aiop_mask
271 .set nzi_mask,0x01ffffff | clears N, Z, and I
272 .set unfinx_mask,unfl_mask+inex2_mask+aunfl_mask+ainex_mask
273 .set unf2inx_mask,unfl_mask+inex2_mask+ainex_mask
274 .set ovfinx_mask,ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
275 .set inx1a_mask,inex1_mask+ainex_mask
276 .set inx2a_mask,inex2_mask+ainex_mask
277 .set snaniop_mask,nan_mask+snan_mask+aiop_mask
278 .set naniop_mask,nan_mask+aiop_mask
279 .set neginf_mask,neg_mask+inf_mask
280 .set infaiop_mask,inf_mask+aiop_mask
281 .set negz_mask,neg_mask+z_mask
282 .set opaop_mask,operr_mask+aiop_mask
283 .set unfl_inx_mask,unfl_mask+aunfl_mask+ainex_mask
284 .set ovfl_inx_mask,ovfl_mask+aovfl_mask+ainex_mask
285|
286|--------------------------------------------------------------------------
287|
288| FPCR rounding modes
289|
290 .set x_mode,0x00 | round to extended
291 .set s_mode,0x40 | round to single
292 .set d_mode,0x80 | round to double
293|
294 .set rn_mode,0x00 | round nearest
295 .set rz_mode,0x10 | round to zero
296 .set rm_mode,0x20 | round to minus infinity
297 .set rp_mode,0x30 | round to plus infinity
298|
299|--------------------------------------------------------------------------
300|
301| Miscellaneous equates
302|
303 .set signan_bit,6 | signalling nan bit in mantissa
304 .set sign_bit,7
305|
306 .set rnd_stky_bit,29 | round/sticky bit of mantissa
307| this can only be used if in a data register
308 .set sx_mask,0x01800000 | set s and x bits in word $48
309|
310 .set LOCAL_EX,0
311 .set LOCAL_SGN,2
312 .set LOCAL_HI,4
313 .set LOCAL_LO,8
314 .set LOCAL_GRS,12 | valid ONLY for FP_SCR1, FP_SCR2
315|
316|
317 .set norm_tag,0x00 | tag bits in {7:5} position
318 .set zero_tag,0x20
319 .set inf_tag,0x40
320 .set nan_tag,0x60
321 .set dnrm_tag,0x80
322|
323| fsave sizes and formats
324|
325 .set VER_4,0x40 | fpsp compatible version numbers
326| are in the $40s {$40-$4f}
327 .set VER_40,0x40 | original version number
328 .set VER_41,0x41 | revision version number
329|
330 .set BUSY_SIZE,100 | size of busy frame
331 .set BUSY_FRAME,LV-BUSY_SIZE | start of busy frame
332|
333 .set UNIMP_40_SIZE,44 | size of orig unimp frame
334 .set UNIMP_41_SIZE,52 | size of rev unimp frame
335|
336 .set IDLE_SIZE,4 | size of idle frame
337 .set IDLE_FRAME,LV-IDLE_SIZE | start of idle frame
338|
339| exception vectors
340|
341 .set TRACE_VEC,0x2024 | trace trap
342 .set FLINE_VEC,0x002C | real F-line
343 .set UNIMP_VEC,0x202C | unimplemented
344 .set INEX_VEC,0x00C4
345|
346 .set dbl_thresh,0x3C01
347 .set sgl_thresh,0x3F81
348|
diff --git a/arch/m68k/fpsp040/gen_except.S b/arch/m68k/fpsp040/gen_except.S
new file mode 100644
index 000000000000..401d06f39f73
--- /dev/null
+++ b/arch/m68k/fpsp040/gen_except.S
@@ -0,0 +1,468 @@
1|
2| gen_except.sa 3.7 1/16/92
3|
4| gen_except --- FPSP routine to detect reportable exceptions
5|
6| This routine compares the exception enable byte of the
7| user_fpcr on the stack with the exception status byte
8| of the user_fpsr.
9|
10| Any routine which may report an exceptions must load
11| the stack frame in memory with the exceptional operand(s).
12|
13| Priority for exceptions is:
14|
15| Highest: bsun
16| snan
17| operr
18| ovfl
19| unfl
20| dz
21| inex2
22| Lowest: inex1
23|
24| Note: The IEEE standard specifies that inex2 is to be
25| reported if ovfl occurs and the ovfl enable bit is not
26| set but the inex2 enable bit is.
27|
28|
29| Copyright (C) Motorola, Inc. 1990
30| All Rights Reserved
31|
32| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
33| The copyright notice above does not evidence any
34| actual or intended publication of such source code.
35
36GEN_EXCEPT: |idnt 2,1 | Motorola 040 Floating Point Software Package
37
38 |section 8
39
40#include "fpsp.h"
41
42 |xref real_trace
43 |xref fpsp_done
44 |xref fpsp_fmt_error
45
46exc_tbl:
47 .long bsun_exc
48 .long commonE1
49 .long commonE1
50 .long ovfl_unfl
51 .long ovfl_unfl
52 .long commonE1
53 .long commonE3
54 .long commonE3
55 .long no_match
56
57 .global gen_except
58gen_except:
59 cmpib #IDLE_SIZE-4,1(%a7) |test for idle frame
60 beq do_check |go handle idle frame
61 cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame
62 beqs unimp_x |go handle unimp frame
63 cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame
64 beqs unimp_x |go handle unimp frame
65 cmpib #BUSY_SIZE-4,1(%a7) |if size <> $60, fmt error
66 bnel fpsp_fmt_error
67 leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 so fpsp.h
68| ;equates will work
69| Fix up the new busy frame with entries from the unimp frame
70|
71 movel ETEMP_EX(%a6),ETEMP_EX(%a1) |copy etemp from unimp
72 movel ETEMP_HI(%a6),ETEMP_HI(%a1) |frame to busy frame
73 movel ETEMP_LO(%a6),ETEMP_LO(%a1)
74 movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp
75 movel CMDREG1B(%a6),%d0 |fix cmd1b to make it
76 andl #0x03c30000,%d0 |work for cmd3b
77 bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2
78 lsll #5,%d1
79 swap %d1
80 orl %d1,%d0 |put it in the right place
81 bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5
82 lsll #2,%d1
83 swap %d1
84 orl %d1,%d0 |put them in the right place
85 movel %d0,CMDREG3B(%a1) |in the busy frame
86|
87| Or in the FPSR from the emulation with the USER_FPSR on the stack.
88|
89 fmovel %FPSR,%d0
90 orl %d0,USER_FPSR(%a6)
91 movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits
92 orl #sx_mask,E_BYTE(%a1)
93 bra do_clean
94
95|
96| Frame is an unimp frame possible resulting from an fmove <ea>,fp0
97| that caused an exception
98|
99| a1 is modified to point into the new frame allowing fpsp equates
100| to be valid.
101|
102unimp_x:
103 cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame
104 bnes test_rev
105 leal UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1
106 bras unimp_con
107test_rev:
108 cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame
109 bnel fpsp_fmt_error |if not $28 or $30
110 leal UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1
111
112unimp_con:
113|
114| Fix up the new unimp frame with entries from the old unimp frame
115|
116 movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp
117|
118| Or in the FPSR from the emulation with the USER_FPSR on the stack.
119|
120 fmovel %FPSR,%d0
121 orl %d0,USER_FPSR(%a6)
122 bra do_clean
123
124|
125| Frame is idle, so check for exceptions reported through
126| USER_FPSR and set the unimp frame accordingly.
127| A7 must be incremented to the point before the
128| idle fsave vector to the unimp vector.
129|
130
131do_check:
132 addl #4,%a7 |point A7 back to unimp frame
133|
134| Or in the FPSR from the emulation with the USER_FPSR on the stack.
135|
136 fmovel %FPSR,%d0
137 orl %d0,USER_FPSR(%a6)
138|
139| On a busy frame, we must clear the nmnexc bits.
140|
141 cmpib #BUSY_SIZE-4,1(%a7) |check frame type
142 bnes check_fr |if busy, clr nmnexc
143 clrw NMNEXC(%a6) |clr nmnexc & nmcexc
144 btstb #5,CMDREG1B(%a6) |test for fmove out
145 bnes frame_com
146 movel USER_FPSR(%a6),FPSR_SHADOW(%a6) |set exc bits
147 orl #sx_mask,E_BYTE(%a6)
148 bras frame_com
149check_fr:
150 cmpb #UNIMP_40_SIZE-4,1(%a7)
151 beqs frame_com
152 clrw NMNEXC(%a6)
153frame_com:
154 moveb FPCR_ENABLE(%a6),%d0 |get fpcr enable byte
155 andb FPSR_EXCEPT(%a6),%d0 |and in the fpsr exc byte
156 bfffo %d0{#24:#8},%d1 |test for first set bit
157 leal exc_tbl,%a0 |load jmp table address
158 subib #24,%d1 |normalize bit offset to 0-8
159 movel (%a0,%d1.w*4),%a0 |load routine address based
160| ;based on first enabled exc
161 jmp (%a0) |jump to routine
162|
163| Bsun is not possible in unimp or unsupp
164|
165bsun_exc:
166 bra do_clean
167|
168| The typical work to be done to the unimp frame to report an
169| exception is to set the E1/E3 byte and clr the U flag.
170| commonE1 does this for E1 exceptions, which are snan,
171| operr, and dz. commonE3 does this for E3 exceptions, which
172| are inex2 and inex1, and also clears the E1 exception bit
173| left over from the unimp exception.
174|
175commonE1:
176 bsetb #E1,E_BYTE(%a6) |set E1 flag
177 bra commonE |go clean and exit
178
179commonE3:
180 tstb UFLG_TMP(%a6) |test flag for unsup/unimp state
181 bnes unsE3
182uniE3:
183 bsetb #E3,E_BYTE(%a6) |set E3 flag
184 bclrb #E1,E_BYTE(%a6) |clr E1 from unimp
185 bra commonE
186
187unsE3:
188 tstb RES_FLG(%a6)
189 bnes unsE3_0
190unsE3_1:
191 bsetb #E3,E_BYTE(%a6) |set E3 flag
192unsE3_0:
193 bclrb #E1,E_BYTE(%a6) |clr E1 flag
194 movel CMDREG1B(%a6),%d0
195 andl #0x03c30000,%d0 |work for cmd3b
196 bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2
197 lsll #5,%d1
198 swap %d1
199 orl %d1,%d0 |put it in the right place
200 bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5
201 lsll #2,%d1
202 swap %d1
203 orl %d1,%d0 |put them in the right place
204 movel %d0,CMDREG3B(%a6) |in the busy frame
205
206commonE:
207 bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp
208 bra do_clean |go clean and exit
209|
210| No bits in the enable byte match existing exceptions. Check for
211| the case of the ovfl exc without the ovfl enabled, but with
212| inex2 enabled.
213|
214no_match:
215 btstb #inex2_bit,FPCR_ENABLE(%a6) |check for ovfl/inex2 case
216 beqs no_exc |if clear, exit
217 btstb #ovfl_bit,FPSR_EXCEPT(%a6) |now check ovfl
218 beqs no_exc |if clear, exit
219 bras ovfl_unfl |go to unfl_ovfl to determine if
220| ;it is an unsupp or unimp exc
221
222| No exceptions are to be reported. If the instruction was
223| unimplemented, no FPU restore is necessary. If it was
224| unsupported, we must perform the restore.
225no_exc:
226 tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
227 beqs uni_no_exc
228uns_no_exc:
229 tstb RES_FLG(%a6) |check if frestore is needed
230 bne do_clean |if clear, no frestore needed
231uni_no_exc:
232 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
233 fmovemx USER_FP0(%a6),%fp0-%fp3
234 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
235 unlk %a6
236 bra finish_up
237|
238| Unsupported Data Type Handler:
239| Ovfl:
240| An fmoveout that results in an overflow is reported this way.
241| Unfl:
242| An fmoveout that results in an underflow is reported this way.
243|
244| Unimplemented Instruction Handler:
245| Ovfl:
246| Only scosh, setox, ssinh, stwotox, and scale can set overflow in
247| this manner.
248| Unfl:
249| Stwotox, setox, and scale can set underflow in this manner.
250| Any of the other Library Routines such that f(x)=x in which
251| x is an extended denorm can report an underflow exception.
252| It is the responsibility of the exception-causing exception
253| to make sure that WBTEMP is correct.
254|
255| The exceptional operand is in FP_SCR1.
256|
257ovfl_unfl:
258 tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
259 beqs ofuf_con
260|
261| The caller was from an unsupported data type trap. Test if the
262| caller set CU_ONLY. If so, the exceptional operand is expected in
263| FPTEMP, rather than WBTEMP.
264|
265 tstb CU_ONLY(%a6) |test if inst is cu-only
266 beq unsE3
267| move.w #$fe,CU_SAVEPC(%a6)
268 clrb CU_SAVEPC(%a6)
269 bsetb #E1,E_BYTE(%a6) |set E1 exception flag
270 movew ETEMP_EX(%a6),FPTEMP_EX(%a6)
271 movel ETEMP_HI(%a6),FPTEMP_HI(%a6)
272 movel ETEMP_LO(%a6),FPTEMP_LO(%a6)
273 bsetb #fptemp15_bit,DTAG(%a6) |set fpte15
274 bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp
275 bra do_clean |go clean and exit
276
277ofuf_con:
278 moveb (%a7),VER_TMP(%a6) |save version number
279 cmpib #BUSY_SIZE-4,1(%a7) |check for busy frame
280 beqs busy_fr |if unimp, grow to busy
281 cmpib #VER_40,(%a7) |test for orig unimp frame
282 bnes try_41 |if not, test for rev frame
283 moveql #13,%d0 |need to zero 14 lwords
284 bras ofuf_fin
285try_41:
286 cmpib #VER_41,(%a7) |test for rev unimp frame
287 bnel fpsp_fmt_error |if neither, exit with error
288 moveql #11,%d0 |need to zero 12 lwords
289
290ofuf_fin:
291 clrl (%a7)
292loop1:
293 clrl -(%a7) |clear and dec a7
294 dbra %d0,loop1
295 moveb VER_TMP(%a6),(%a7)
296 moveb #BUSY_SIZE-4,1(%a7) |write busy fmt word.
297busy_fr:
298 movel FP_SCR1(%a6),WBTEMP_EX(%a6) |write
299 movel FP_SCR1+4(%a6),WBTEMP_HI(%a6) |exceptional op to
300 movel FP_SCR1+8(%a6),WBTEMP_LO(%a6) |wbtemp
301 bsetb #E3,E_BYTE(%a6) |set E3 flag
302 bclrb #E1,E_BYTE(%a6) |make sure E1 is clear
303 bclrb #UFLAG,T_BYTE(%a6) |clr U flag
304 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
305 orl #sx_mask,E_BYTE(%a6)
306 movel CMDREG1B(%a6),%d0 |fix cmd1b to make it
307 andl #0x03c30000,%d0 |work for cmd3b
308 bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2
309 lsll #5,%d1
310 swap %d1
311 orl %d1,%d0 |put it in the right place
312 bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5
313 lsll #2,%d1
314 swap %d1
315 orl %d1,%d0 |put them in the right place
316 movel %d0,CMDREG3B(%a6) |in the busy frame
317
318|
319| Check if the frame to be restored is busy or unimp.
320|** NOTE *** Bug fix for errata (0d43b #3)
321| If the frame is unimp, we must create a busy frame to
322| fix the bug with the nmnexc bits in cases in which they
323| are set by a previous instruction and not cleared by
324| the save. The frame will be unimp only if the final
325| instruction in an emulation routine caused the exception
326| by doing an fmove <ea>,fp0. The exception operand, in
327| internal format, is in fptemp.
328|
329do_clean:
330 cmpib #UNIMP_40_SIZE-4,1(%a7)
331 bnes do_con
332 moveql #13,%d0 |in orig, need to zero 14 lwords
333 bras do_build
334do_con:
335 cmpib #UNIMP_41_SIZE-4,1(%a7)
336 bnes do_restore |frame must be busy
337 moveql #11,%d0 |in rev, need to zero 12 lwords
338
339do_build:
340 moveb (%a7),VER_TMP(%a6)
341 clrl (%a7)
342loop2:
343 clrl -(%a7) |clear and dec a7
344 dbra %d0,loop2
345|
346| Use a1 as pointer into new frame. a6 is not correct if an unimp or
347| busy frame was created as the result of an exception on the final
348| instruction of an emulation routine.
349|
350| We need to set the nmcexc bits if the exception is E1. Otherwise,
351| the exc taken will be inex2.
352|
353 leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 for new frame
354 moveb VER_TMP(%a6),(%a7) |write busy fmt word
355 moveb #BUSY_SIZE-4,1(%a7)
356 movel FP_SCR1(%a6),WBTEMP_EX(%a1) |write
357 movel FP_SCR1+4(%a6),WBTEMP_HI(%a1) |exceptional op to
358 movel FP_SCR1+8(%a6),WBTEMP_LO(%a1) |wbtemp
359| btst.b #E1,E_BYTE(%a1)
360| beq.b do_restore
361 bfextu USER_FPSR(%a6){#17:#4},%d0 |get snan/operr/ovfl/unfl bits
362 bfins %d0,NMCEXC(%a1){#4:#4} |and insert them in nmcexc
363 movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits
364 orl #sx_mask,E_BYTE(%a1)
365
366do_restore:
367 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
368 fmovemx USER_FP0(%a6),%fp0-%fp3
369 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
370 frestore (%a7)+
371 tstb RES_FLG(%a6) |RES_FLG indicates a "continuation" frame
372 beq cont
373 bsr bug1384
374cont:
375 unlk %a6
376|
377| If trace mode enabled, then go to trace handler. This handler
378| cannot have any fp instructions. If there are fp inst's and an
379| exception has been restored into the machine then the exception
380| will occur upon execution of the fp inst. This is not desirable
381| in the kernel (supervisor mode). See MC68040 manual Section 9.3.8.
382|
383finish_up:
384 btstb #7,(%a7) |test T1 in SR
385 bnes g_trace
386 btstb #6,(%a7) |test T0 in SR
387 bnes g_trace
388 bral fpsp_done
389|
390| Change integer stack to look like trace stack
391| The address of the instruction that caused the
392| exception is already in the integer stack (is
393| the same as the saved friar)
394|
395| If the current frame is already a 6-word stack then all
396| that needs to be done is to change the vector# to TRACE.
397| If the frame is only a 4-word stack (meaning we got here
398| on an Unsupported data type exception), then we need to grow
399| the stack an extra 2 words and get the FPIAR from the FPU.
400|
401g_trace:
402 bftst EXC_VEC-4(%sp){#0:#4}
403 bne g_easy
404
405 subw #4,%sp | make room
406 movel 4(%sp),(%sp)
407 movel 8(%sp),4(%sp)
408 subw #BUSY_SIZE,%sp
409 fsave (%sp)
410 fmovel %fpiar,BUSY_SIZE+EXC_EA-4(%sp)
411 frestore (%sp)
412 addw #BUSY_SIZE,%sp
413
414g_easy:
415 movew #TRACE_VEC,EXC_VEC-4(%a7)
416 bral real_trace
417|
418| This is a work-around for hardware bug 1384.
419|
420bug1384:
421 link %a5,#0
422 fsave -(%sp)
423 cmpib #0x41,(%sp) | check for correct frame
424 beq frame_41
425 bgt nofix | if more advanced mask, do nada
426
427frame_40:
428 tstb 1(%sp) | check to see if idle
429 bne notidle
430idle40:
431 clrl (%sp) | get rid of old fsave frame
432 movel %d1,USER_D1(%a6) | save d1
433 movew #8,%d1 | place unimp frame instead
434loop40: clrl -(%sp)
435 dbra %d1,loop40
436 movel USER_D1(%a6),%d1 | restore d1
437 movel #0x40280000,-(%sp)
438 frestore (%sp)+
439 unlk %a5
440 rts
441
442frame_41:
443 tstb 1(%sp) | check to see if idle
444 bne notidle
445idle41:
446 clrl (%sp) | get rid of old fsave frame
447 movel %d1,USER_D1(%a6) | save d1
448 movew #10,%d1 | place unimp frame instead
449loop41: clrl -(%sp)
450 dbra %d1,loop41
451 movel USER_D1(%a6),%d1 | restore d1
452 movel #0x41300000,-(%sp)
453 frestore (%sp)+
454 unlk %a5
455 rts
456
457notidle:
458 bclrb #etemp15_bit,-40(%a5)
459 frestore (%sp)+
460 unlk %a5
461 rts
462
463nofix:
464 frestore (%sp)+
465 unlk %a5
466 rts
467
468 |end
diff --git a/arch/m68k/fpsp040/get_op.S b/arch/m68k/fpsp040/get_op.S
new file mode 100644
index 000000000000..c7c2f3727425
--- /dev/null
+++ b/arch/m68k/fpsp040/get_op.S
@@ -0,0 +1,676 @@
1|
2| get_op.sa 3.6 5/19/92
3|
4| get_op.sa 3.5 4/26/91
5|
6| Description: This routine is called by the unsupported format/data
7| type exception handler ('unsupp' - vector 55) and the unimplemented
8| instruction exception handler ('unimp' - vector 11). 'get_op'
9| determines the opclass (0, 2, or 3) and branches to the
10| opclass handler routine. See 68881/2 User's Manual table 4-11
11| for a description of the opclasses.
12|
13| For UNSUPPORTED data/format (exception vector 55) and for
14| UNIMPLEMENTED instructions (exception vector 11) the following
15| applies:
16|
17| - For unnormalized numbers (opclass 0, 2, or 3) the
18| number(s) is normalized and the operand type tag is updated.
19|
20| - For a packed number (opclass 2) the number is unpacked and the
21| operand type tag is updated.
22|
23| - For denormalized numbers (opclass 0 or 2) the number(s) is not
24| changed but passed to the next module. The next module for
25| unimp is do_func, the next module for unsupp is res_func.
26|
27| For UNSUPPORTED data/format (exception vector 55) only the
28| following applies:
29|
30| - If there is a move out with a packed number (opclass 3) the
31| number is packed and written to user memory. For the other
32| opclasses the number(s) are written back to the fsave stack
33| and the instruction is then restored back into the '040. The
34| '040 is then able to complete the instruction.
35|
36| For example:
37| fadd.x fpm,fpn where the fpm contains an unnormalized number.
38| The '040 takes an unsupported data trap and gets to this
39| routine. The number is normalized, put back on the stack and
40| then an frestore is done to restore the instruction back into
41| the '040. The '040 then re-executes the fadd.x fpm,fpn with
42| a normalized number in the source and the instruction is
43| successful.
44|
45| Next consider if in the process of normalizing the un-
46| normalized number it becomes a denormalized number. The
47| routine which converts the unnorm to a norm (called mk_norm)
48| detects this and tags the number as a denorm. The routine
49| res_func sees the denorm tag and converts the denorm to a
50| norm. The instruction is then restored back into the '040
51| which re_executes the instruction.
52|
53|
54| Copyright (C) Motorola, Inc. 1990
55| All Rights Reserved
56|
57| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
58| The copyright notice above does not evidence any
59| actual or intended publication of such source code.
60
61GET_OP: |idnt 2,1 | Motorola 040 Floating Point Software Package
62
63 |section 8
64
65#include "fpsp.h"
66
67 .global PIRN,PIRZRM,PIRP
68 .global SMALRN,SMALRZRM,SMALRP
69 .global BIGRN,BIGRZRM,BIGRP
70
71PIRN:
72 .long 0x40000000,0xc90fdaa2,0x2168c235 |pi
73PIRZRM:
74 .long 0x40000000,0xc90fdaa2,0x2168c234 |pi
75PIRP:
76 .long 0x40000000,0xc90fdaa2,0x2168c235 |pi
77
78|round to nearest
79SMALRN:
80 .long 0x3ffd0000,0x9a209a84,0xfbcff798 |log10(2)
81 .long 0x40000000,0xadf85458,0xa2bb4a9a |e
82 .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc |log2(e)
83 .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
84 .long 0x00000000,0x00000000,0x00000000 |0.0
85| round to zero;round to negative infinity
86SMALRZRM:
87 .long 0x3ffd0000,0x9a209a84,0xfbcff798 |log10(2)
88 .long 0x40000000,0xadf85458,0xa2bb4a9a |e
89 .long 0x3fff0000,0xb8aa3b29,0x5c17f0bb |log2(e)
90 .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
91 .long 0x00000000,0x00000000,0x00000000 |0.0
92| round to positive infinity
93SMALRP:
94 .long 0x3ffd0000,0x9a209a84,0xfbcff799 |log10(2)
95 .long 0x40000000,0xadf85458,0xa2bb4a9b |e
96 .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc |log2(e)
97 .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
98 .long 0x00000000,0x00000000,0x00000000 |0.0
99
100|round to nearest
101BIGRN:
102 .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2)
103 .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10)
104 .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
105
106 .global PTENRN
107PTENRN:
108 .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
109 .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
110 .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
111 .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
112 .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
113 .long 0x40690000,0x9DC5ADA8,0x2B70B59E |10 ^ 32
114 .long 0x40D30000,0xC2781F49,0xFFCFA6D5 |10 ^ 64
115 .long 0x41A80000,0x93BA47C9,0x80E98CE0 |10 ^ 128
116 .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E |10 ^ 256
117 .long 0x46A30000,0xE319A0AE,0xA60E91C7 |10 ^ 512
118 .long 0x4D480000,0xC9767586,0x81750C17 |10 ^ 1024
119 .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 |10 ^ 2048
120 .long 0x75250000,0xC4605202,0x8A20979B |10 ^ 4096
121|round to minus infinity
122BIGRZRM:
123 .long 0x3ffe0000,0xb17217f7,0xd1cf79ab |ln(2)
124 .long 0x40000000,0x935d8ddd,0xaaa8ac16 |ln(10)
125 .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
126
127 .global PTENRM
128PTENRM:
129 .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
130 .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
131 .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
132 .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
133 .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
134 .long 0x40690000,0x9DC5ADA8,0x2B70B59D |10 ^ 32
135 .long 0x40D30000,0xC2781F49,0xFFCFA6D5 |10 ^ 64
136 .long 0x41A80000,0x93BA47C9,0x80E98CDF |10 ^ 128
137 .long 0x43510000,0xAA7EEBFB,0x9DF9DE8D |10 ^ 256
138 .long 0x46A30000,0xE319A0AE,0xA60E91C6 |10 ^ 512
139 .long 0x4D480000,0xC9767586,0x81750C17 |10 ^ 1024
140 .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 |10 ^ 2048
141 .long 0x75250000,0xC4605202,0x8A20979A |10 ^ 4096
142|round to positive infinity
143BIGRP:
144 .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2)
145 .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10)
146 .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
147
148 .global PTENRP
149PTENRP:
150 .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
151 .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
152 .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
153 .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
154 .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
155 .long 0x40690000,0x9DC5ADA8,0x2B70B59E |10 ^ 32
156 .long 0x40D30000,0xC2781F49,0xFFCFA6D6 |10 ^ 64
157 .long 0x41A80000,0x93BA47C9,0x80E98CE0 |10 ^ 128
158 .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E |10 ^ 256
159 .long 0x46A30000,0xE319A0AE,0xA60E91C7 |10 ^ 512
160 .long 0x4D480000,0xC9767586,0x81750C18 |10 ^ 1024
161 .long 0x5A920000,0x9E8B3B5D,0xC53D5DE6 |10 ^ 2048
162 .long 0x75250000,0xC4605202,0x8A20979B |10 ^ 4096
163
164 |xref nrm_zero
165 |xref decbin
166 |xref round
167
168 .global get_op
169 .global uns_getop
170 .global uni_getop
171get_op:
172 clrb DY_MO_FLG(%a6)
173 tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
174 beq uni_getop
175
176uns_getop:
177 btstb #direction_bit,CMDREG1B(%a6)
178 bne opclass3 |branch if a fmove out (any kind)
179 btstb #6,CMDREG1B(%a6)
180 beqs uns_notpacked
181
182 bfextu CMDREG1B(%a6){#3:#3},%d0
183 cmpb #3,%d0
184 beq pack_source |check for a packed src op, branch if so
185uns_notpacked:
186 bsr chk_dy_mo |set the dyadic/monadic flag
187 tstb DY_MO_FLG(%a6)
188 beqs src_op_ck |if monadic, go check src op
189| ;else, check dst op (fall through)
190
191 btstb #7,DTAG(%a6)
192 beqs src_op_ck |if dst op is norm, check src op
193 bras dst_ex_dnrm |else, handle destination unnorm/dnrm
194
195uni_getop:
196 bfextu CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
197 cmpil #0x17,%d0 |if op class and size fields are $17,
198| ;it is FMOVECR; if not, continue
199|
200| If the instruction is fmovecr, exit get_op. It is handled
201| in do_func and smovecr.sa.
202|
203 bne not_fmovecr |handle fmovecr as an unimplemented inst
204 rts
205
206not_fmovecr:
207 btstb #E1,E_BYTE(%a6) |if set, there is a packed operand
208 bne pack_source |check for packed src op, branch if so
209
210| The following lines of are coded to optimize on normalized operands
211 moveb STAG(%a6),%d0
212 orb DTAG(%a6),%d0 |check if either of STAG/DTAG msb set
213 bmis dest_op_ck |if so, some op needs to be fixed
214 rts
215
216dest_op_ck:
217 btstb #7,DTAG(%a6) |check for unsupported data types in
218 beqs src_op_ck |the destination, if not, check src op
219 bsr chk_dy_mo |set dyadic/monadic flag
220 tstb DY_MO_FLG(%a6) |
221 beqs src_op_ck |if monadic, check src op
222|
223| At this point, destination has an extended denorm or unnorm.
224|
225dst_ex_dnrm:
226 movew FPTEMP_EX(%a6),%d0 |get destination exponent
227 andiw #0x7fff,%d0 |mask sign, check if exp = 0000
228 beqs src_op_ck |if denorm then check source op.
229| ;denorms are taken care of in res_func
230| ;(unsupp) or do_func (unimp)
231| ;else unnorm fall through
232 leal FPTEMP(%a6),%a0 |point a0 to dop - used in mk_norm
233 bsr mk_norm |go normalize - mk_norm returns:
234| ;L_SCR1{7:5} = operand tag
235| ; (000 = norm, 100 = denorm)
236| ;L_SCR1{4} = fpte15 or ete15
237| ; 0 = exp > $3fff
238| ; 1 = exp <= $3fff
239| ;and puts the normalized num back
240| ;on the fsave stack
241|
242 moveb L_SCR1(%a6),DTAG(%a6) |write the new tag & fpte15
243| ;to the fsave stack and fall
244| ;through to check source operand
245|
246src_op_ck:
247 btstb #7,STAG(%a6)
248 beq end_getop |check for unsupported data types on the
249| ;source operand
250 btstb #5,STAG(%a6)
251 bnes src_sd_dnrm |if bit 5 set, handle sgl/dbl denorms
252|
253| At this point only unnorms or extended denorms are possible.
254|
255src_ex_dnrm:
256 movew ETEMP_EX(%a6),%d0 |get source exponent
257 andiw #0x7fff,%d0 |mask sign, check if exp = 0000
258 beq end_getop |if denorm then exit, denorms are
259| ;handled in do_func
260 leal ETEMP(%a6),%a0 |point a0 to sop - used in mk_norm
261 bsr mk_norm |go normalize - mk_norm returns:
262| ;L_SCR1{7:5} = operand tag
263| ; (000 = norm, 100 = denorm)
264| ;L_SCR1{4} = fpte15 or ete15
265| ; 0 = exp > $3fff
266| ; 1 = exp <= $3fff
267| ;and puts the normalized num back
268| ;on the fsave stack
269|
270 moveb L_SCR1(%a6),STAG(%a6) |write the new tag & ete15
271 rts |end_getop
272
273|
274| At this point, only single or double denorms are possible.
275| If the inst is not fmove, normalize the source. If it is,
276| do nothing to the input.
277|
278src_sd_dnrm:
279 btstb #4,CMDREG1B(%a6) |differentiate between sgl/dbl denorm
280 bnes is_double
281is_single:
282 movew #0x3f81,%d1 |write bias for sgl denorm
283 bras common |goto the common code
284is_double:
285 movew #0x3c01,%d1 |write the bias for a dbl denorm
286common:
287 btstb #sign_bit,ETEMP_EX(%a6) |grab sign bit of mantissa
288 beqs pos
289 bset #15,%d1 |set sign bit because it is negative
290pos:
291 movew %d1,ETEMP_EX(%a6)
292| ;put exponent on stack
293
294 movew CMDREG1B(%a6),%d1
295 andw #0xe3ff,%d1 |clear out source specifier
296 orw #0x0800,%d1 |set source specifier to extended prec
297 movew %d1,CMDREG1B(%a6) |write back to the command word in stack
298| ;this is needed to fix unsupp data stack
299 leal ETEMP(%a6),%a0 |point a0 to sop
300
301 bsr mk_norm |convert sgl/dbl denorm to norm
302 moveb L_SCR1(%a6),STAG(%a6) |put tag into source tag reg - d0
303 rts |end_getop
304|
305| At this point, the source is definitely packed, whether
306| instruction is dyadic or monadic is still unknown
307|
308pack_source:
309 movel FPTEMP_LO(%a6),ETEMP(%a6) |write ms part of packed
310| ;number to etemp slot
311 bsr chk_dy_mo |set dyadic/monadic flag
312 bsr unpack
313
314 tstb DY_MO_FLG(%a6)
315 beqs end_getop |if monadic, exit
316| ;else, fix FPTEMP
317pack_dya:
318 bfextu CMDREG1B(%a6){#6:#3},%d0 |extract dest fp reg
319 movel #7,%d1
320 subl %d0,%d1
321 clrl %d0
322 bsetl %d1,%d0 |set up d0 as a dynamic register mask
323 fmovemx %d0,FPTEMP(%a6) |write to FPTEMP
324
325 btstb #7,DTAG(%a6) |check dest tag for unnorm or denorm
326 bne dst_ex_dnrm |else, handle the unnorm or ext denorm
327|
328| Dest is not denormalized. Check for norm, and set fpte15
329| accordingly.
330|
331 moveb DTAG(%a6),%d0
332 andib #0xf0,%d0 |strip to only dtag:fpte15
333 tstb %d0 |check for normalized value
334 bnes end_getop |if inf/nan/zero leave get_op
335 movew FPTEMP_EX(%a6),%d0
336 andiw #0x7fff,%d0
337 cmpiw #0x3fff,%d0 |check if fpte15 needs setting
338 bges end_getop |if >= $3fff, leave fpte15=0
339 orb #0x10,DTAG(%a6)
340 bras end_getop
341
342|
343| At this point, it is either an fmoveout packed, unnorm or denorm
344|
345opclass3:
346 clrb DY_MO_FLG(%a6) |set dyadic/monadic flag to monadic
347 bfextu CMDREG1B(%a6){#4:#2},%d0
348 cmpib #3,%d0
349 bne src_ex_dnrm |if not equal, must be unnorm or denorm
350| ;else it is a packed move out
351| ;exit
352end_getop:
353 rts
354
355|
356| Sets the DY_MO_FLG correctly. This is used only on if it is an
357| unsupported data type exception. Set if dyadic.
358|
359chk_dy_mo:
360 movew CMDREG1B(%a6),%d0
361 btstl #5,%d0 |testing extension command word
362 beqs set_mon |if bit 5 = 0 then monadic
363 btstl #4,%d0 |know that bit 5 = 1
364 beqs set_dya |if bit 4 = 0 then dyadic
365 andiw #0x007f,%d0 |get rid of all but extension bits {6:0}
366 cmpiw #0x0038,%d0 |if extension = $38 then fcmp (dyadic)
367 bnes set_mon
368set_dya:
369 st DY_MO_FLG(%a6) |set the inst flag type to dyadic
370 rts
371set_mon:
372 clrb DY_MO_FLG(%a6) |set the inst flag type to monadic
373 rts
374|
375| MK_NORM
376|
377| Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
378| exception if denorm.
379|
380| CASE opclass 0x0 unsupp
381| mk_norm till msb set
382| set tag = norm
383|
384| CASE opclass 0x0 unimp
385| mk_norm till msb set or exp = 0
386| if integer bit = 0
387| tag = denorm
388| else
389| tag = norm
390|
391| CASE opclass 011 unsupp
392| mk_norm till msb set or exp = 0
393| if integer bit = 0
394| tag = denorm
395| set unfl_nmcexe = 1
396| else
397| tag = norm
398|
399| if exp <= $3fff
400| set ete15 or fpte15 = 1
401| else set ete15 or fpte15 = 0
402
403| input:
404| a0 = points to operand to be normalized
405| output:
406| L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
407| L_SCR1{4} = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
408| the normalized operand is placed back on the fsave stack
409mk_norm:
410 clrl L_SCR1(%a6)
411 bclrb #sign_bit,LOCAL_EX(%a0)
412 sne LOCAL_SGN(%a0) |transform into internal extended format
413
414 cmpib #0x2c,1+EXC_VEC(%a6) |check if unimp
415 bnes uns_data |branch if unsupp
416 bsr uni_inst |call if unimp (opclass 0x0)
417 bras reload
418uns_data:
419 btstb #direction_bit,CMDREG1B(%a6) |check transfer direction
420 bnes bit_set |branch if set (opclass 011)
421 bsr uns_opx |call if opclass 0x0
422 bras reload
423bit_set:
424 bsr uns_op3 |opclass 011
425reload:
426 cmpw #0x3fff,LOCAL_EX(%a0) |if exp > $3fff
427 bgts end_mk | fpte15/ete15 already set to 0
428 bsetb #4,L_SCR1(%a6) |else set fpte15/ete15 to 1
429| ;calling routine actually sets the
430| ;value on the stack (along with the
431| ;tag), since this routine doesn't
432| ;know if it should set ete15 or fpte15
433| ;ie, it doesn't know if this is the
434| ;src op or dest op.
435end_mk:
436 bfclr LOCAL_SGN(%a0){#0:#8}
437 beqs end_mk_pos
438 bsetb #sign_bit,LOCAL_EX(%a0) |convert back to IEEE format
439end_mk_pos:
440 rts
441|
442| CASE opclass 011 unsupp
443|
444uns_op3:
445 bsr nrm_zero |normalize till msb = 1 or exp = zero
446 btstb #7,LOCAL_HI(%a0) |if msb = 1
447 bnes no_unfl |then branch
448set_unfl:
449 orw #dnrm_tag,L_SCR1(%a6) |set denorm tag
450 bsetb #unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit
451no_unfl:
452 rts
453|
454| CASE opclass 0x0 unsupp
455|
456uns_opx:
457 bsr nrm_zero |normalize the number
458 btstb #7,LOCAL_HI(%a0) |check if integer bit (j-bit) is set
459 beqs uns_den |if clear then now have a denorm
460uns_nrm:
461 orb #norm_tag,L_SCR1(%a6) |set tag to norm
462 rts
463uns_den:
464 orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm
465 rts
466|
467| CASE opclass 0x0 unimp
468|
469uni_inst:
470 bsr nrm_zero
471 btstb #7,LOCAL_HI(%a0) |check if integer bit (j-bit) is set
472 beqs uni_den |if clear then now have a denorm
473uni_nrm:
474 orb #norm_tag,L_SCR1(%a6) |set tag to norm
475 rts
476uni_den:
477 orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm
478 rts
479
480|
481| Decimal to binary conversion
482|
483| Special cases of inf and NaNs are completed outside of decbin.
484| If the input is an snan, the snan bit is not set.
485|
486| input:
487| ETEMP(a6) - points to packed decimal string in memory
488| output:
489| fp0 - contains packed string converted to extended precision
490| ETEMP - same as fp0
491unpack:
492 movew CMDREG1B(%a6),%d0 |examine command word, looking for fmove's
493 andw #0x3b,%d0
494 beq move_unpack |special handling for fmove: must set FPSR_CC
495
496 movew ETEMP(%a6),%d0 |get word with inf information
497 bfextu %d0{#20:#12},%d1 |get exponent into d1
498 cmpiw #0x0fff,%d1 |test for inf or NaN
499 bnes try_zero |if not equal, it is not special
500 bfextu %d0{#17:#3},%d1 |get SE and y bits into d1
501 cmpiw #7,%d1 |SE and y bits must be on for special
502 bnes try_zero |if not on, it is not special
503|input is of the special cases of inf and NaN
504 tstl ETEMP_HI(%a6) |check ms mantissa
505 bnes fix_nan |if non-zero, it is a NaN
506 tstl ETEMP_LO(%a6) |check ls mantissa
507 bnes fix_nan |if non-zero, it is a NaN
508 bra finish |special already on stack
509fix_nan:
510 btstb #signan_bit,ETEMP_HI(%a6) |test for snan
511 bne finish
512 orl #snaniop_mask,USER_FPSR(%a6) |always set snan if it is so
513 bra finish
514try_zero:
515 movew ETEMP_EX+2(%a6),%d0 |get word 4
516 andiw #0x000f,%d0 |clear all but last ni(y)bble
517 tstw %d0 |check for zero.
518 bne not_spec
519 tstl ETEMP_HI(%a6) |check words 3 and 2
520 bne not_spec
521 tstl ETEMP_LO(%a6) |check words 1 and 0
522 bne not_spec
523 tstl ETEMP(%a6) |test sign of the zero
524 bges pos_zero
525 movel #0x80000000,ETEMP(%a6) |write neg zero to etemp
526 clrl ETEMP_HI(%a6)
527 clrl ETEMP_LO(%a6)
528 bra finish
529pos_zero:
530 clrl ETEMP(%a6)
531 clrl ETEMP_HI(%a6)
532 clrl ETEMP_LO(%a6)
533 bra finish
534
535not_spec:
536 fmovemx %fp0-%fp1,-(%a7) |save fp0 - decbin returns in it
537 bsr decbin
538 fmovex %fp0,ETEMP(%a6) |put the unpacked sop in the fsave stack
539 fmovemx (%a7)+,%fp0-%fp1
540 fmovel #0,%FPSR |clr fpsr from decbin
541 bra finish
542
543|
544| Special handling for packed move in: Same results as all other
545| packed cases, but we must set the FPSR condition codes properly.
546|
547move_unpack:
548 movew ETEMP(%a6),%d0 |get word with inf information
549 bfextu %d0{#20:#12},%d1 |get exponent into d1
550 cmpiw #0x0fff,%d1 |test for inf or NaN
551 bnes mtry_zero |if not equal, it is not special
552 bfextu %d0{#17:#3},%d1 |get SE and y bits into d1
553 cmpiw #7,%d1 |SE and y bits must be on for special
554 bnes mtry_zero |if not on, it is not special
555|input is of the special cases of inf and NaN
556 tstl ETEMP_HI(%a6) |check ms mantissa
557 bnes mfix_nan |if non-zero, it is a NaN
558 tstl ETEMP_LO(%a6) |check ls mantissa
559 bnes mfix_nan |if non-zero, it is a NaN
560|input is inf
561 orl #inf_mask,USER_FPSR(%a6) |set I bit
562 tstl ETEMP(%a6) |check sign
563 bge finish
564 orl #neg_mask,USER_FPSR(%a6) |set N bit
565 bra finish |special already on stack
566mfix_nan:
567 orl #nan_mask,USER_FPSR(%a6) |set NaN bit
568 moveb #nan_tag,STAG(%a6) |set stag to NaN
569 btstb #signan_bit,ETEMP_HI(%a6) |test for snan
570 bnes mn_snan
571 orl #snaniop_mask,USER_FPSR(%a6) |set snan bit
572 btstb #snan_bit,FPCR_ENABLE(%a6) |test for snan enabled
573 bnes mn_snan
574 bsetb #signan_bit,ETEMP_HI(%a6) |force snans to qnans
575mn_snan:
576 tstl ETEMP(%a6) |check for sign
577 bge finish |if clr, go on
578 orl #neg_mask,USER_FPSR(%a6) |set N bit
579 bra finish
580
581mtry_zero:
582 movew ETEMP_EX+2(%a6),%d0 |get word 4
583 andiw #0x000f,%d0 |clear all but last ni(y)bble
584 tstw %d0 |check for zero.
585 bnes mnot_spec
586 tstl ETEMP_HI(%a6) |check words 3 and 2
587 bnes mnot_spec
588 tstl ETEMP_LO(%a6) |check words 1 and 0
589 bnes mnot_spec
590 tstl ETEMP(%a6) |test sign of the zero
591 bges mpos_zero
592 orl #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z
593 movel #0x80000000,ETEMP(%a6) |write neg zero to etemp
594 clrl ETEMP_HI(%a6)
595 clrl ETEMP_LO(%a6)
596 bras finish
597mpos_zero:
598 orl #z_mask,USER_FPSR(%a6) |set Z
599 clrl ETEMP(%a6)
600 clrl ETEMP_HI(%a6)
601 clrl ETEMP_LO(%a6)
602 bras finish
603
604mnot_spec:
605 fmovemx %fp0-%fp1,-(%a7) |save fp0 ,fp1 - decbin returns in fp0
606 bsr decbin
607 fmovex %fp0,ETEMP(%a6)
608| ;put the unpacked sop in the fsave stack
609 fmovemx (%a7)+,%fp0-%fp1
610
611finish:
612 movew CMDREG1B(%a6),%d0 |get the command word
613 andw #0xfbff,%d0 |change the source specifier field to
614| ;extended (was packed).
615 movew %d0,CMDREG1B(%a6) |write command word back to fsave stack
616| ;we need to do this so the 040 will
617| ;re-execute the inst. without taking
618| ;another packed trap.
619
620fix_stag:
621|Converted result is now in etemp on fsave stack, now set the source
622|tag (stag)
623| if (ete =$7fff) then INF or NAN
624| if (etemp = $x.0----0) then
625| stag = INF
626| else
627| stag = NAN
628| else
629| if (ete = $0000) then
630| stag = ZERO
631| else
632| stag = NORM
633|
634| Note also that the etemp_15 bit (just right of the stag) must
635| be set accordingly.
636|
637 movew ETEMP_EX(%a6),%d1
638 andiw #0x7fff,%d1 |strip sign
639 cmpw #0x7fff,%d1
640 bnes z_or_nrm
641 movel ETEMP_HI(%a6),%d1
642 bnes is_nan
643 movel ETEMP_LO(%a6),%d1
644 bnes is_nan
645is_inf:
646 moveb #0x40,STAG(%a6)
647 movel #0x40,%d0
648 rts
649is_nan:
650 moveb #0x60,STAG(%a6)
651 movel #0x60,%d0
652 rts
653z_or_nrm:
654 tstw %d1
655 bnes is_nrm
656is_zro:
657| For a zero, set etemp_15
658 moveb #0x30,STAG(%a6)
659 movel #0x20,%d0
660 rts
661is_nrm:
662| For a norm, check if the exp <= $3fff; if so, set etemp_15
663 cmpiw #0x3fff,%d1
664 bles set_bit15
665 moveb #0,STAG(%a6)
666 bras end_is_nrm
667set_bit15:
668 moveb #0x10,STAG(%a6)
669end_is_nrm:
670 movel #0,%d0
671end_fix:
672 rts
673
674end_get:
675 rts
676 |end
diff --git a/arch/m68k/fpsp040/kernel_ex.S b/arch/m68k/fpsp040/kernel_ex.S
new file mode 100644
index 000000000000..476b711967ce
--- /dev/null
+++ b/arch/m68k/fpsp040/kernel_ex.S
@@ -0,0 +1,494 @@
1|
2| kernel_ex.sa 3.3 12/19/90
3|
4| This file contains routines to force exception status in the
5| fpu for exceptional cases detected or reported within the
6| transcendental functions. Typically, the t_xx routine will
7| set the appropriate bits in the USER_FPSR word on the stack.
8| The bits are tested in gen_except.sa to determine if an exceptional
9| situation needs to be created on return from the FPSP.
10|
11
12| Copyright (C) Motorola, Inc. 1990
13| All Rights Reserved
14|
15| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
16| The copyright notice above does not evidence any
17| actual or intended publication of such source code.
18
19KERNEL_EX: |idnt 2,1 | Motorola 040 Floating Point Software Package
20
21 |section 8
22
23#include "fpsp.h"
24
25mns_inf: .long 0xffff0000,0x00000000,0x00000000
26pls_inf: .long 0x7fff0000,0x00000000,0x00000000
27nan: .long 0x7fff0000,0xffffffff,0xffffffff
28huge: .long 0x7ffe0000,0xffffffff,0xffffffff
29
30 |xref ovf_r_k
31 |xref unf_sub
32 |xref nrm_set
33
34 .global t_dz
35 .global t_dz2
36 .global t_operr
37 .global t_unfl
38 .global t_ovfl
39 .global t_ovfl2
40 .global t_inx2
41 .global t_frcinx
42 .global t_extdnrm
43 .global t_resdnrm
44 .global dst_nan
45 .global src_nan
46|
47| DZ exception
48|
49|
50| if dz trap disabled
51| store properly signed inf (use sign of etemp) into fp0
52| set FPSR exception status dz bit, condition code
53| inf bit, and accrued dz bit
54| return
55| frestore the frame into the machine (done by unimp_hd)
56|
57| else dz trap enabled
58| set exception status bit & accrued bits in FPSR
59| set flag to disable sto_res from corrupting fp register
60| return
61| frestore the frame into the machine (done by unimp_hd)
62|
63| t_dz2 is used by monadic functions such as flogn (from do_func).
64| t_dz is used by monadic functions such as satanh (from the
65| transcendental function).
66|
67t_dz2:
68 bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR
69 fmovel #0,%FPSR |clr status bits (Z set)
70 btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled
71 bnes dz_ena_end
72 bras m_inf |flogx always returns -inf
73t_dz:
74 fmovel #0,%FPSR |clr status bits (Z set)
75 btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled
76 bnes dz_ena
77|
78| dz disabled
79|
80 btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos
81 beqs p_inf |branch if pos sign
82
83m_inf:
84 fmovemx mns_inf,%fp0-%fp0 |load -inf
85 bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR
86 bras set_fpsr
87p_inf:
88 fmovemx pls_inf,%fp0-%fp0 |load +inf
89set_fpsr:
90 orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
91 rts
92|
93| dz enabled
94|
95dz_ena:
96 btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos
97 beqs dz_ena_end
98 bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR
99dz_ena_end:
100 orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
101 st STORE_FLG(%a6)
102 rts
103|
104| OPERR exception
105|
106| if (operr trap disabled)
107| set FPSR exception status operr bit, condition code
108| nan bit; Store default NAN into fp0
109| frestore the frame into the machine (done by unimp_hd)
110|
111| else (operr trap enabled)
112| set FPSR exception status operr bit, accrued operr bit
113| set flag to disable sto_res from corrupting fp register
114| frestore the frame into the machine (done by unimp_hd)
115|
116t_operr:
117 orl #opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP
118
119 btstb #operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled
120 bnes op_ena
121
122 fmovemx nan,%fp0-%fp0 |load default nan
123 rts
124op_ena:
125 st STORE_FLG(%a6) |do not corrupt destination
126 rts
127
128|
129| t_unfl --- UNFL exception
130|
131| This entry point is used by all routines requiring unfl, inex2,
132| aunfl, and ainex to be set on exit.
133|
134| On entry, a0 points to the exceptional operand. The final exceptional
135| operand is built in FP_SCR1 and only the sign from the original operand
136| is used.
137|
138t_unfl:
139 clrl FP_SCR1(%a6) |set exceptional operand to zero
140 clrl FP_SCR1+4(%a6)
141 clrl FP_SCR1+8(%a6)
142 tstb (%a0) |extract sign from caller's exop
143 bpls unfl_signok
144 bset #sign_bit,FP_SCR1(%a6)
145unfl_signok:
146 leal FP_SCR1(%a6),%a0
147 orl #unfinx_mask,USER_FPSR(%a6)
148| ;set UNFL, INEX2, AUNFL, AINEX
149unfl_con:
150 btstb #unfl_bit,FPCR_ENABLE(%a6)
151 beqs unfl_dis
152
153unfl_ena:
154 bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0
155 bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
156 bsetb #sticky_bit,STICKY(%a6) |set sticky bit
157
158 bclrb #E1,E_BYTE(%a6)
159
160unfl_dis:
161 bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision
162
163 bclrb #sign_bit,LOCAL_EX(%a0)
164 sne LOCAL_SGN(%a0) |convert to internal ext format
165
166 bsr unf_sub |returns IEEE result at a0
167| ;and sets FPSR_CC accordingly
168
169 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
170 beqs unfl_fin
171
172 bsetb #sign_bit,LOCAL_EX(%a0)
173 bsetb #sign_bit,FP_SCR1(%a6) |set sign bit of exc operand
174
175unfl_fin:
176 fmovemx (%a0),%fp0-%fp0 |store result in fp0
177 rts
178
179
180|
181| t_ovfl2 --- OVFL exception (without inex2 returned)
182|
183| This entry is used by scale to force catastrophic overflow. The
184| ovfl, aovfl, and ainex bits are set, but not the inex2 bit.
185|
186t_ovfl2:
187 orl #ovfl_inx_mask,USER_FPSR(%a6)
188 movel ETEMP(%a6),FP_SCR1(%a6)
189 movel ETEMP_HI(%a6),FP_SCR1+4(%a6)
190 movel ETEMP_LO(%a6),FP_SCR1+8(%a6)
191|
192| Check for single or double round precision. If single, check if
193| the lower 40 bits of ETEMP are zero; if not, set inex2. If double,
194| check if the lower 21 bits are zero; if not, set inex2.
195|
196 moveb FPCR_MODE(%a6),%d0
197 andib #0xc0,%d0
198 beq t_work |if extended, finish ovfl processing
199 cmpib #0x40,%d0 |test for single
200 bnes t_dbl
201t_sgl:
202 tstb ETEMP_LO(%a6)
203 bnes t_setinx2
204 movel ETEMP_HI(%a6),%d0
205 andil #0xff,%d0 |look at only lower 8 bits
206 bnes t_setinx2
207 bra t_work
208t_dbl:
209 movel ETEMP_LO(%a6),%d0
210 andil #0x7ff,%d0 |look at only lower 11 bits
211 beq t_work
212t_setinx2:
213 orl #inex2_mask,USER_FPSR(%a6)
214 bras t_work
215|
216| t_ovfl --- OVFL exception
217|
218|** Note: the exc operand is returned in ETEMP.
219|
220t_ovfl:
221 orl #ovfinx_mask,USER_FPSR(%a6)
222t_work:
223 btstb #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled
224 beqs ovf_dis
225
226ovf_ena:
227 clrl FP_SCR1(%a6) |set exceptional operand
228 clrl FP_SCR1+4(%a6)
229 clrl FP_SCR1+8(%a6)
230
231 bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0
232 bclrb #wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15
233 bsetb #sticky_bit,STICKY(%a6) |set sticky bit
234
235 bclrb #E1,E_BYTE(%a6)
236| ;fall through to disabled case
237
238| For disabled overflow call 'ovf_r_k'. This routine loads the
239| correct result based on the rounding precision, destination
240| format, rounding mode and sign.
241|
242ovf_dis:
243 bsr ovf_r_k |returns unsigned ETEMP_EX
244| ;and sets FPSR_CC accordingly.
245 bfclr ETEMP_SGN(%a6){#0:#8} |fix sign
246 beqs ovf_pos
247 bsetb #sign_bit,ETEMP_EX(%a6)
248 bsetb #sign_bit,FP_SCR1(%a6) |set exceptional operand sign
249ovf_pos:
250 fmovemx ETEMP(%a6),%fp0-%fp0 |move the result to fp0
251 rts
252
253
254|
255| INEX2 exception
256|
257| The inex2 and ainex bits are set.
258|
259t_inx2:
260 orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
261 rts
262
263|
264| Force Inex2
265|
266| This routine is called by the transcendental routines to force
267| the inex2 exception bits set in the FPSR. If the underflow bit
268| is set, but the underflow trap was not taken, the aunfl bit in
269| the FPSR must be set.
270|
271t_frcinx:
272 orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
273 btstb #unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set
274 beqs no_uacc1 |if clear, do not set aunfl
275 bsetb #aunfl_bit,FPSR_AEXCEPT(%a6)
276no_uacc1:
277 rts
278
279|
280| DST_NAN
281|
282| Determine if the destination nan is signalling or non-signalling,
283| and set the FPSR bits accordingly. See the MC68040 User's Manual
284| section 3.2.2.5 NOT-A-NUMBERS.
285|
286dst_nan:
287 btstb #sign_bit,FPTEMP_EX(%a6) |test sign of nan
288 beqs dst_pos |if clr, it was positive
289 bsetb #neg_bit,FPSR_CC(%a6) |set N bit
290dst_pos:
291 btstb #signan_bit,FPTEMP_HI(%a6) |check if signalling
292 beqs dst_snan |branch if signalling
293
294 fmovel %d1,%fpcr |restore user's rmode/prec
295 fmovex FPTEMP(%a6),%fp0 |return the non-signalling nan
296|
297| Check the source nan. If it is signalling, snan will be reported.
298|
299 moveb STAG(%a6),%d0
300 andib #0xe0,%d0
301 cmpib #0x60,%d0
302 bnes no_snan
303 btstb #signan_bit,ETEMP_HI(%a6) |check if signalling
304 bnes no_snan
305 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
306no_snan:
307 rts
308
309dst_snan:
310 btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
311 beqs dst_dis |branch if disabled
312
313 orb #nan_tag,DTAG(%a6) |set up dtag for nan
314 st STORE_FLG(%a6) |do not store a result
315 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
316 rts
317
318dst_dis:
319 bsetb #signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop
320 fmovel %d1,%fpcr |restore user's rmode/prec
321 fmovex FPTEMP(%a6),%fp0 |load non-sign. nan
322 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
323 rts
324
325|
326| SRC_NAN
327|
328| Determine if the source nan is signalling or non-signalling,
329| and set the FPSR bits accordingly. See the MC68040 User's Manual
330| section 3.2.2.5 NOT-A-NUMBERS.
331|
332src_nan:
333 btstb #sign_bit,ETEMP_EX(%a6) |test sign of nan
334 beqs src_pos |if clr, it was positive
335 bsetb #neg_bit,FPSR_CC(%a6) |set N bit
336src_pos:
337 btstb #signan_bit,ETEMP_HI(%a6) |check if signalling
338 beqs src_snan |branch if signalling
339 fmovel %d1,%fpcr |restore user's rmode/prec
340 fmovex ETEMP(%a6),%fp0 |return the non-signalling nan
341 rts
342
343src_snan:
344 btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
345 beqs src_dis |branch if disabled
346 bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
347 orb #norm_tag,DTAG(%a6) |set up dtag for norm
348 orb #nan_tag,STAG(%a6) |set up stag for nan
349 st STORE_FLG(%a6) |do not store a result
350 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
351 rts
352
353src_dis:
354 bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
355 fmovel %d1,%fpcr |restore user's rmode/prec
356 fmovex ETEMP(%a6),%fp0 |load non-sign. nan
357 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
358 rts
359
360|
361| For all functions that have a denormalized input and that f(x)=x,
362| this is the entry point
363|
364t_extdnrm:
365 orl #unfinx_mask,USER_FPSR(%a6)
366| ;set UNFL, INEX2, AUNFL, AINEX
367 bras xdnrm_con
368|
369| Entry point for scale with extended denorm. The function does
370| not set inex2, aunfl, or ainex.
371|
372t_resdnrm:
373 orl #unfl_mask,USER_FPSR(%a6)
374
375xdnrm_con:
376 btstb #unfl_bit,FPCR_ENABLE(%a6)
377 beqs xdnrm_dis
378
379|
380| If exceptions are enabled, the additional task of setting up WBTEMP
381| is needed so that when the underflow exception handler is entered,
382| the user perceives no difference between what the 040 provides vs.
383| what the FPSP provides.
384|
385xdnrm_ena:
386 movel %a0,-(%a7)
387
388 movel LOCAL_EX(%a0),FP_SCR1(%a6)
389 movel LOCAL_HI(%a0),FP_SCR1+4(%a6)
390 movel LOCAL_LO(%a0),FP_SCR1+8(%a6)
391
392 lea FP_SCR1(%a6),%a0
393
394 bclrb #sign_bit,LOCAL_EX(%a0)
395 sne LOCAL_SGN(%a0) |convert to internal ext format
396 tstw LOCAL_EX(%a0) |check if input is denorm
397 beqs xdnrm_dn |if so, skip nrm_set
398 bsr nrm_set |normalize the result (exponent
399| ;will be negative
400xdnrm_dn:
401 bclrb #sign_bit,LOCAL_EX(%a0) |take off false sign
402 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
403 beqs xdep
404 bsetb #sign_bit,LOCAL_EX(%a0)
405xdep:
406 bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0
407 bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
408 bclrb #sticky_bit,STICKY(%a6) |clear sticky bit
409 bclrb #E1,E_BYTE(%a6)
410 movel (%a7)+,%a0
411xdnrm_dis:
412 bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision
413 bnes not_ext |if not round extended, store
414| ;IEEE defaults
415is_ext:
416 btstb #sign_bit,LOCAL_EX(%a0)
417 beqs xdnrm_store
418
419 bsetb #neg_bit,FPSR_CC(%a6) |set N bit in FPSR_CC
420
421 bras xdnrm_store
422
423not_ext:
424 bclrb #sign_bit,LOCAL_EX(%a0)
425 sne LOCAL_SGN(%a0) |convert to internal ext format
426 bsr unf_sub |returns IEEE result pointed by
427| ;a0; sets FPSR_CC accordingly
428 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
429 beqs xdnrm_store
430 bsetb #sign_bit,LOCAL_EX(%a0)
431xdnrm_store:
432 fmovemx (%a0),%fp0-%fp0 |store result in fp0
433 rts
434
435|
436| This subroutine is used for dyadic operations that use an extended
437| denorm within the kernel. The approach used is to capture the frame,
438| fix/restore.
439|
440 .global t_avoid_unsupp
441t_avoid_unsupp:
442 link %a2,#-LOCAL_SIZE |so that a2 fpsp.h negative
443| ;offsets may be used
444 fsave -(%a7)
445 tstb 1(%a7) |check if idle, exit if so
446 beq idle_end
447 btstb #E1,E_BYTE(%a2) |check for an E1 exception if
448| ;enabled, there is an unsupp
449 beq end_avun |else, exit
450 btstb #7,DTAG(%a2) |check for denorm destination
451 beqs src_den |else, must be a source denorm
452|
453| handle destination denorm
454|
455 lea FPTEMP(%a2),%a0
456 btstb #sign_bit,LOCAL_EX(%a0)
457 sne LOCAL_SGN(%a0) |convert to internal ext format
458 bclrb #7,DTAG(%a2) |set DTAG to norm
459 bsr nrm_set |normalize result, exponent
460| ;will become negative
461 bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign
462 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
463 beqs ck_src_den |check if source is also denorm
464 bsetb #sign_bit,LOCAL_EX(%a0)
465ck_src_den:
466 btstb #7,STAG(%a2)
467 beqs end_avun
468src_den:
469 lea ETEMP(%a2),%a0
470 btstb #sign_bit,LOCAL_EX(%a0)
471 sne LOCAL_SGN(%a0) |convert to internal ext format
472 bclrb #7,STAG(%a2) |set STAG to norm
473 bsr nrm_set |normalize result, exponent
474| ;will become negative
475 bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign
476 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
477 beqs den_com
478 bsetb #sign_bit,LOCAL_EX(%a0)
479den_com:
480 moveb #0xfe,CU_SAVEPC(%a2) |set continue frame
481 clrw NMNEXC(%a2) |clear NMNEXC
482 bclrb #E1,E_BYTE(%a2)
483| fmove.l %FPSR,FPSR_SHADOW(%a2)
484| bset.b #SFLAG,E_BYTE(%a2)
485| bset.b #XFLAG,T_BYTE(%a2)
486end_avun:
487 frestore (%a7)+
488 unlk %a2
489 rts
490idle_end:
491 addl #4,%a7
492 unlk %a2
493 rts
494 |end
diff --git a/arch/m68k/fpsp040/res_func.S b/arch/m68k/fpsp040/res_func.S
new file mode 100644
index 000000000000..8f6b95217865
--- /dev/null
+++ b/arch/m68k/fpsp040/res_func.S
@@ -0,0 +1,2040 @@
1|
2| res_func.sa 3.9 7/29/91
3|
4| Normalizes denormalized numbers if necessary and updates the
5| stack frame. The function is then restored back into the
6| machine and the 040 completes the operation. This routine
7| is only used by the unsupported data type/format handler.
8| (Exception vector 55).
9|
10| For packed move out (fmove.p fpm,<ea>) the operation is
11| completed here; data is packed and moved to user memory.
12| The stack is restored to the 040 only in the case of a
13| reportable exception in the conversion.
14|
15|
16| Copyright (C) Motorola, Inc. 1990
17| All Rights Reserved
18|
19| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
20| The copyright notice above does not evidence any
21| actual or intended publication of such source code.
22
23RES_FUNC: |idnt 2,1 | Motorola 040 Floating Point Software Package
24
25 |section 8
26
27#include "fpsp.h"
28
29sp_bnds: .short 0x3f81,0x407e
30 .short 0x3f6a,0x0000
31dp_bnds: .short 0x3c01,0x43fe
32 .short 0x3bcd,0x0000
33
34 |xref mem_write
35 |xref bindec
36 |xref get_fline
37 |xref round
38 |xref denorm
39 |xref dest_ext
40 |xref dest_dbl
41 |xref dest_sgl
42 |xref unf_sub
43 |xref nrm_set
44 |xref dnrm_lp
45 |xref ovf_res
46 |xref reg_dest
47 |xref t_ovfl
48 |xref t_unfl
49
50 .global res_func
51 .global p_move
52
53res_func:
54 clrb DNRM_FLG(%a6)
55 clrb RES_FLG(%a6)
56 clrb CU_ONLY(%a6)
57 tstb DY_MO_FLG(%a6)
58 beqs monadic
59dyadic:
60 btstb #7,DTAG(%a6) |if dop = norm=000, zero=001,
61| ;inf=010 or nan=011
62 beqs monadic |then branch
63| ;else denorm
64| HANDLE DESTINATION DENORM HERE
65| ;set dtag to norm
66| ;write the tag & fpte15 to the fstack
67 leal FPTEMP(%a6),%a0
68
69 bclrb #sign_bit,LOCAL_EX(%a0)
70 sne LOCAL_SGN(%a0)
71
72 bsr nrm_set |normalize number (exp will go negative)
73 bclrb #sign_bit,LOCAL_EX(%a0) |get rid of false sign
74 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
75 beqs dpos
76 bsetb #sign_bit,LOCAL_EX(%a0)
77dpos:
78 bfclr DTAG(%a6){#0:#4} |set tag to normalized, FPTE15 = 0
79 bsetb #4,DTAG(%a6) |set FPTE15
80 orb #0x0f,DNRM_FLG(%a6)
81monadic:
82 leal ETEMP(%a6),%a0
83 btstb #direction_bit,CMDREG1B(%a6) |check direction
84 bne opclass3 |it is a mv out
85|
86| At this point, only opclass 0 and 2 possible
87|
88 btstb #7,STAG(%a6) |if sop = norm=000, zero=001,
89| ;inf=010 or nan=011
90 bne mon_dnrm |else denorm
91 tstb DY_MO_FLG(%a6) |all cases of dyadic instructions would
92 bne normal |require normalization of denorm
93
94| At this point:
95| monadic instructions: fabs = $18 fneg = $1a ftst = $3a
96| fmove = $00 fsmove = $40 fdmove = $44
97| fsqrt = $05* fssqrt = $41 fdsqrt = $45
98| (*fsqrt reencoded to $05)
99|
100 movew CMDREG1B(%a6),%d0 |get command register
101 andil #0x7f,%d0 |strip to only command word
102|
103| At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and
104| fdsqrt are possible.
105| For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize)
106| For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize)
107|
108 btstl #0,%d0
109 bne normal |weed out fsqrt instructions
110|
111| cu_norm handles fmove in instructions with normalized inputs.
112| The routine round is used to correctly round the input for the
113| destination precision and mode.
114|
115cu_norm:
116 st CU_ONLY(%a6) |set cu-only inst flag
117 movew CMDREG1B(%a6),%d0
118 andib #0x3b,%d0 |isolate bits to select inst
119 tstb %d0
120 beql cu_nmove |if zero, it is an fmove
121 cmpib #0x18,%d0
122 beql cu_nabs |if $18, it is fabs
123 cmpib #0x1a,%d0
124 beql cu_nneg |if $1a, it is fneg
125|
126| Inst is ftst. Check the source operand and set the cc's accordingly.
127| No write is done, so simply rts.
128|
129cu_ntst:
130 movew LOCAL_EX(%a0),%d0
131 bclrl #15,%d0
132 sne LOCAL_SGN(%a0)
133 beqs cu_ntpo
134 orl #neg_mask,USER_FPSR(%a6) |set N
135cu_ntpo:
136 cmpiw #0x7fff,%d0 |test for inf/nan
137 bnes cu_ntcz
138 tstl LOCAL_HI(%a0)
139 bnes cu_ntn
140 tstl LOCAL_LO(%a0)
141 bnes cu_ntn
142 orl #inf_mask,USER_FPSR(%a6)
143 rts
144cu_ntn:
145 orl #nan_mask,USER_FPSR(%a6)
146 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for
147| ;snan handler
148
149 rts
150cu_ntcz:
151 tstl LOCAL_HI(%a0)
152 bnel cu_ntsx
153 tstl LOCAL_LO(%a0)
154 bnel cu_ntsx
155 orl #z_mask,USER_FPSR(%a6)
156cu_ntsx:
157 rts
158|
159| Inst is fabs. Execute the absolute value function on the input.
160| Branch to the fmove code. If the operand is NaN, do nothing.
161|
162cu_nabs:
163 moveb STAG(%a6),%d0
164 btstl #5,%d0 |test for NaN or zero
165 bne wr_etemp |if either, simply write it
166 bclrb #7,LOCAL_EX(%a0) |do abs
167 bras cu_nmove |fmove code will finish
168|
169| Inst is fneg. Execute the negate value function on the input.
170| Fall though to the fmove code. If the operand is NaN, do nothing.
171|
172cu_nneg:
173 moveb STAG(%a6),%d0
174 btstl #5,%d0 |test for NaN or zero
175 bne wr_etemp |if either, simply write it
176 bchgb #7,LOCAL_EX(%a0) |do neg
177|
178| Inst is fmove. This code also handles all result writes.
179| If bit 2 is set, round is forced to double. If it is clear,
180| and bit 6 is set, round is forced to single. If both are clear,
181| the round precision is found in the fpcr. If the rounding precision
182| is double or single, round the result before the write.
183|
184cu_nmove:
185 moveb STAG(%a6),%d0
186 andib #0xe0,%d0 |isolate stag bits
187 bne wr_etemp |if not norm, simply write it
188 btstb #2,CMDREG1B+1(%a6) |check for rd
189 bne cu_nmrd
190 btstb #6,CMDREG1B+1(%a6) |check for rs
191 bne cu_nmrs
192|
193| The move or operation is not with forced precision. Test for
194| nan or inf as the input; if so, simply write it to FPn. Use the
195| FPCR_MODE byte to get rounding on norms and zeros.
196|
197cu_nmnr:
198 bfextu FPCR_MODE(%a6){#0:#2},%d0
199 tstb %d0 |check for extended
200 beq cu_wrexn |if so, just write result
201 cmpib #1,%d0 |check for single
202 beq cu_nmrs |fall through to double
203|
204| The move is fdmove or round precision is double.
205|
206cu_nmrd:
207 movel #2,%d0 |set up the size for denorm
208 movew LOCAL_EX(%a0),%d1 |compare exponent to double threshold
209 andw #0x7fff,%d1
210 cmpw #0x3c01,%d1
211 bls cu_nunfl
212 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode
213 orl #0x00020000,%d1 |or in rprec (double)
214 clrl %d0 |clear g,r,s for round
215 bclrb #sign_bit,LOCAL_EX(%a0) |convert to internal format
216 sne LOCAL_SGN(%a0)
217 bsrl round
218 bfclr LOCAL_SGN(%a0){#0:#8}
219 beqs cu_nmrdc
220 bsetb #sign_bit,LOCAL_EX(%a0)
221cu_nmrdc:
222 movew LOCAL_EX(%a0),%d1 |check for overflow
223 andw #0x7fff,%d1
224 cmpw #0x43ff,%d1
225 bge cu_novfl |take care of overflow case
226 bra cu_wrexn
227|
228| The move is fsmove or round precision is single.
229|
230cu_nmrs:
231 movel #1,%d0
232 movew LOCAL_EX(%a0),%d1
233 andw #0x7fff,%d1
234 cmpw #0x3f81,%d1
235 bls cu_nunfl
236 bfextu FPCR_MODE(%a6){#2:#2},%d1
237 orl #0x00010000,%d1
238 clrl %d0
239 bclrb #sign_bit,LOCAL_EX(%a0)
240 sne LOCAL_SGN(%a0)
241 bsrl round
242 bfclr LOCAL_SGN(%a0){#0:#8}
243 beqs cu_nmrsc
244 bsetb #sign_bit,LOCAL_EX(%a0)
245cu_nmrsc:
246 movew LOCAL_EX(%a0),%d1
247 andw #0x7FFF,%d1
248 cmpw #0x407f,%d1
249 blt cu_wrexn
250|
251| The operand is above precision boundaries. Use t_ovfl to
252| generate the correct value.
253|
254cu_novfl:
255 bsr t_ovfl
256 bra cu_wrexn
257|
258| The operand is below precision boundaries. Use denorm to
259| generate the correct value.
260|
261cu_nunfl:
262 bclrb #sign_bit,LOCAL_EX(%a0)
263 sne LOCAL_SGN(%a0)
264 bsr denorm
265 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
266 beqs cu_nucont
267 bsetb #sign_bit,LOCAL_EX(%a0)
268cu_nucont:
269 bfextu FPCR_MODE(%a6){#2:#2},%d1
270 btstb #2,CMDREG1B+1(%a6) |check for rd
271 bne inst_d
272 btstb #6,CMDREG1B+1(%a6) |check for rs
273 bne inst_s
274 swap %d1
275 moveb FPCR_MODE(%a6),%d1
276 lsrb #6,%d1
277 swap %d1
278 bra inst_sd
279inst_d:
280 orl #0x00020000,%d1
281 bra inst_sd
282inst_s:
283 orl #0x00010000,%d1
284inst_sd:
285 bclrb #sign_bit,LOCAL_EX(%a0)
286 sne LOCAL_SGN(%a0)
287 bsrl round
288 bfclr LOCAL_SGN(%a0){#0:#8}
289 beqs cu_nuflp
290 bsetb #sign_bit,LOCAL_EX(%a0)
291cu_nuflp:
292 btstb #inex2_bit,FPSR_EXCEPT(%a6)
293 beqs cu_nuninx
294 orl #aunfl_mask,USER_FPSR(%a6) |if the round was inex, set AUNFL
295cu_nuninx:
296 tstl LOCAL_HI(%a0) |test for zero
297 bnes cu_nunzro
298 tstl LOCAL_LO(%a0)
299 bnes cu_nunzro
300|
301| The mantissa is zero from the denorm loop. Check sign and rmode
302| to see if rounding should have occurred which would leave the lsb.
303|
304 movel USER_FPCR(%a6),%d0
305 andil #0x30,%d0 |isolate rmode
306 cmpil #0x20,%d0
307 blts cu_nzro
308 bnes cu_nrp
309cu_nrm:
310 tstw LOCAL_EX(%a0) |if positive, set lsb
311 bges cu_nzro
312 btstb #7,FPCR_MODE(%a6) |check for double
313 beqs cu_nincs
314 bras cu_nincd
315cu_nrp:
316 tstw LOCAL_EX(%a0) |if positive, set lsb
317 blts cu_nzro
318 btstb #7,FPCR_MODE(%a6) |check for double
319 beqs cu_nincs
320cu_nincd:
321 orl #0x800,LOCAL_LO(%a0) |inc for double
322 bra cu_nunzro
323cu_nincs:
324 orl #0x100,LOCAL_HI(%a0) |inc for single
325 bra cu_nunzro
326cu_nzro:
327 orl #z_mask,USER_FPSR(%a6)
328 moveb STAG(%a6),%d0
329 andib #0xe0,%d0
330 cmpib #0x40,%d0 |check if input was tagged zero
331 beqs cu_numv
332cu_nunzro:
333 orl #unfl_mask,USER_FPSR(%a6) |set unfl
334cu_numv:
335 movel (%a0),ETEMP(%a6)
336 movel 4(%a0),ETEMP_HI(%a6)
337 movel 8(%a0),ETEMP_LO(%a6)
338|
339| Write the result to memory, setting the fpsr cc bits. NaN and Inf
340| bypass cu_wrexn.
341|
342cu_wrexn:
343 tstw LOCAL_EX(%a0) |test for zero
344 beqs cu_wrzero
345 cmpw #0x8000,LOCAL_EX(%a0) |test for zero
346 bnes cu_wreon
347cu_wrzero:
348 orl #z_mask,USER_FPSR(%a6) |set Z bit
349cu_wreon:
350 tstw LOCAL_EX(%a0)
351 bpl wr_etemp
352 orl #neg_mask,USER_FPSR(%a6)
353 bra wr_etemp
354
355|
356| HANDLE SOURCE DENORM HERE
357|
358| ;clear denorm stag to norm
359| ;write the new tag & ete15 to the fstack
360mon_dnrm:
361|
362| At this point, check for the cases in which normalizing the
363| denorm produces incorrect results.
364|
365 tstb DY_MO_FLG(%a6) |all cases of dyadic instructions would
366 bnes nrm_src |require normalization of denorm
367
368| At this point:
369| monadic instructions: fabs = $18 fneg = $1a ftst = $3a
370| fmove = $00 fsmove = $40 fdmove = $44
371| fsqrt = $05* fssqrt = $41 fdsqrt = $45
372| (*fsqrt reencoded to $05)
373|
374 movew CMDREG1B(%a6),%d0 |get command register
375 andil #0x7f,%d0 |strip to only command word
376|
377| At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and
378| fdsqrt are possible.
379| For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize)
380| For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize)
381|
382 btstl #0,%d0
383 bnes nrm_src |weed out fsqrt instructions
384 st CU_ONLY(%a6) |set cu-only inst flag
385 bra cu_dnrm |fmove, fabs, fneg, ftst
386| ;cases go to cu_dnrm
387nrm_src:
388 bclrb #sign_bit,LOCAL_EX(%a0)
389 sne LOCAL_SGN(%a0)
390 bsr nrm_set |normalize number (exponent will go
391| ; negative)
392 bclrb #sign_bit,LOCAL_EX(%a0) |get rid of false sign
393
394 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
395 beqs spos
396 bsetb #sign_bit,LOCAL_EX(%a0)
397spos:
398 bfclr STAG(%a6){#0:#4} |set tag to normalized, FPTE15 = 0
399 bsetb #4,STAG(%a6) |set ETE15
400 orb #0xf0,DNRM_FLG(%a6)
401normal:
402 tstb DNRM_FLG(%a6) |check if any of the ops were denorms
403 bne ck_wrap |if so, check if it is a potential
404| ;wrap-around case
405fix_stk:
406 moveb #0xfe,CU_SAVEPC(%a6)
407 bclrb #E1,E_BYTE(%a6)
408
409 clrw NMNEXC(%a6)
410
411 st RES_FLG(%a6) |indicate that a restore is needed
412 rts
413
414|
415| cu_dnrm handles all cu-only instructions (fmove, fabs, fneg, and
416| ftst) completely in software without an frestore to the 040.
417|
418cu_dnrm:
419 st CU_ONLY(%a6)
420 movew CMDREG1B(%a6),%d0
421 andib #0x3b,%d0 |isolate bits to select inst
422 tstb %d0
423 beql cu_dmove |if zero, it is an fmove
424 cmpib #0x18,%d0
425 beql cu_dabs |if $18, it is fabs
426 cmpib #0x1a,%d0
427 beql cu_dneg |if $1a, it is fneg
428|
429| Inst is ftst. Check the source operand and set the cc's accordingly.
430| No write is done, so simply rts.
431|
432cu_dtst:
433 movew LOCAL_EX(%a0),%d0
434 bclrl #15,%d0
435 sne LOCAL_SGN(%a0)
436 beqs cu_dtpo
437 orl #neg_mask,USER_FPSR(%a6) |set N
438cu_dtpo:
439 cmpiw #0x7fff,%d0 |test for inf/nan
440 bnes cu_dtcz
441 tstl LOCAL_HI(%a0)
442 bnes cu_dtn
443 tstl LOCAL_LO(%a0)
444 bnes cu_dtn
445 orl #inf_mask,USER_FPSR(%a6)
446 rts
447cu_dtn:
448 orl #nan_mask,USER_FPSR(%a6)
449 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for
450| ;snan handler
451 rts
452cu_dtcz:
453 tstl LOCAL_HI(%a0)
454 bnel cu_dtsx
455 tstl LOCAL_LO(%a0)
456 bnel cu_dtsx
457 orl #z_mask,USER_FPSR(%a6)
458cu_dtsx:
459 rts
460|
461| Inst is fabs. Execute the absolute value function on the input.
462| Branch to the fmove code.
463|
464cu_dabs:
465 bclrb #7,LOCAL_EX(%a0) |do abs
466 bras cu_dmove |fmove code will finish
467|
468| Inst is fneg. Execute the negate value function on the input.
469| Fall though to the fmove code.
470|
471cu_dneg:
472 bchgb #7,LOCAL_EX(%a0) |do neg
473|
474| Inst is fmove. This code also handles all result writes.
475| If bit 2 is set, round is forced to double. If it is clear,
476| and bit 6 is set, round is forced to single. If both are clear,
477| the round precision is found in the fpcr. If the rounding precision
478| is double or single, the result is zero, and the mode is checked
479| to determine if the lsb of the result should be set.
480|
481cu_dmove:
482 btstb #2,CMDREG1B+1(%a6) |check for rd
483 bne cu_dmrd
484 btstb #6,CMDREG1B+1(%a6) |check for rs
485 bne cu_dmrs
486|
487| The move or operation is not with forced precision. Use the
488| FPCR_MODE byte to get rounding.
489|
490cu_dmnr:
491 bfextu FPCR_MODE(%a6){#0:#2},%d0
492 tstb %d0 |check for extended
493 beq cu_wrexd |if so, just write result
494 cmpib #1,%d0 |check for single
495 beq cu_dmrs |fall through to double
496|
497| The move is fdmove or round precision is double. Result is zero.
498| Check rmode for rp or rm and set lsb accordingly.
499|
500cu_dmrd:
501 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode
502 tstw LOCAL_EX(%a0) |check sign
503 blts cu_dmdn
504 cmpib #3,%d1 |check for rp
505 bne cu_dpd |load double pos zero
506 bra cu_dpdr |load double pos zero w/lsb
507cu_dmdn:
508 cmpib #2,%d1 |check for rm
509 bne cu_dnd |load double neg zero
510 bra cu_dndr |load double neg zero w/lsb
511|
512| The move is fsmove or round precision is single. Result is zero.
513| Check for rp or rm and set lsb accordingly.
514|
515cu_dmrs:
516 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode
517 tstw LOCAL_EX(%a0) |check sign
518 blts cu_dmsn
519 cmpib #3,%d1 |check for rp
520 bne cu_spd |load single pos zero
521 bra cu_spdr |load single pos zero w/lsb
522cu_dmsn:
523 cmpib #2,%d1 |check for rm
524 bne cu_snd |load single neg zero
525 bra cu_sndr |load single neg zero w/lsb
526|
527| The precision is extended, so the result in etemp is correct.
528| Simply set unfl (not inex2 or aunfl) and write the result to
529| the correct fp register.
530cu_wrexd:
531 orl #unfl_mask,USER_FPSR(%a6)
532 tstw LOCAL_EX(%a0)
533 beq wr_etemp
534 orl #neg_mask,USER_FPSR(%a6)
535 bra wr_etemp
536|
537| These routines write +/- zero in double format. The routines
538| cu_dpdr and cu_dndr set the double lsb.
539|
540cu_dpd:
541 movel #0x3c010000,LOCAL_EX(%a0) |force pos double zero
542 clrl LOCAL_HI(%a0)
543 clrl LOCAL_LO(%a0)
544 orl #z_mask,USER_FPSR(%a6)
545 orl #unfinx_mask,USER_FPSR(%a6)
546 bra wr_etemp
547cu_dpdr:
548 movel #0x3c010000,LOCAL_EX(%a0) |force pos double zero
549 clrl LOCAL_HI(%a0)
550 movel #0x800,LOCAL_LO(%a0) |with lsb set
551 orl #unfinx_mask,USER_FPSR(%a6)
552 bra wr_etemp
553cu_dnd:
554 movel #0xbc010000,LOCAL_EX(%a0) |force pos double zero
555 clrl LOCAL_HI(%a0)
556 clrl LOCAL_LO(%a0)
557 orl #z_mask,USER_FPSR(%a6)
558 orl #neg_mask,USER_FPSR(%a6)
559 orl #unfinx_mask,USER_FPSR(%a6)
560 bra wr_etemp
561cu_dndr:
562 movel #0xbc010000,LOCAL_EX(%a0) |force pos double zero
563 clrl LOCAL_HI(%a0)
564 movel #0x800,LOCAL_LO(%a0) |with lsb set
565 orl #neg_mask,USER_FPSR(%a6)
566 orl #unfinx_mask,USER_FPSR(%a6)
567 bra wr_etemp
568|
569| These routines write +/- zero in single format. The routines
570| cu_dpdr and cu_dndr set the single lsb.
571|
572cu_spd:
573 movel #0x3f810000,LOCAL_EX(%a0) |force pos single zero
574 clrl LOCAL_HI(%a0)
575 clrl LOCAL_LO(%a0)
576 orl #z_mask,USER_FPSR(%a6)
577 orl #unfinx_mask,USER_FPSR(%a6)
578 bra wr_etemp
579cu_spdr:
580 movel #0x3f810000,LOCAL_EX(%a0) |force pos single zero
581 movel #0x100,LOCAL_HI(%a0) |with lsb set
582 clrl LOCAL_LO(%a0)
583 orl #unfinx_mask,USER_FPSR(%a6)
584 bra wr_etemp
585cu_snd:
586 movel #0xbf810000,LOCAL_EX(%a0) |force pos single zero
587 clrl LOCAL_HI(%a0)
588 clrl LOCAL_LO(%a0)
589 orl #z_mask,USER_FPSR(%a6)
590 orl #neg_mask,USER_FPSR(%a6)
591 orl #unfinx_mask,USER_FPSR(%a6)
592 bra wr_etemp
593cu_sndr:
594 movel #0xbf810000,LOCAL_EX(%a0) |force pos single zero
595 movel #0x100,LOCAL_HI(%a0) |with lsb set
596 clrl LOCAL_LO(%a0)
597 orl #neg_mask,USER_FPSR(%a6)
598 orl #unfinx_mask,USER_FPSR(%a6)
599 bra wr_etemp
600
601|
602| This code checks for 16-bit overflow conditions on dyadic
603| operations which are not restorable into the floating-point
604| unit and must be completed in software. Basically, this
605| condition exists with a very large norm and a denorm. One
606| of the operands must be denormalized to enter this code.
607|
608| Flags used:
609| DY_MO_FLG contains 0 for monadic op, $ff for dyadic
610| DNRM_FLG contains $00 for neither op denormalized
611| $0f for the destination op denormalized
612| $f0 for the source op denormalized
613| $ff for both ops denormalized
614|
615| The wrap-around condition occurs for add, sub, div, and cmp
616| when
617|
618| abs(dest_exp - src_exp) >= $8000
619|
620| and for mul when
621|
622| (dest_exp + src_exp) < $0
623|
624| we must process the operation here if this case is true.
625|
626| The rts following the frcfpn routine is the exit from res_func
627| for this condition. The restore flag (RES_FLG) is left clear.
628| No frestore is done unless an exception is to be reported.
629|
630| For fadd:
631| if(sign_of(dest) != sign_of(src))
632| replace exponent of src with $3fff (keep sign)
633| use fpu to perform dest+new_src (user's rmode and X)
634| clr sticky
635| else
636| set sticky
637| call round with user's precision and mode
638| move result to fpn and wbtemp
639|
640| For fsub:
641| if(sign_of(dest) == sign_of(src))
642| replace exponent of src with $3fff (keep sign)
643| use fpu to perform dest+new_src (user's rmode and X)
644| clr sticky
645| else
646| set sticky
647| call round with user's precision and mode
648| move result to fpn and wbtemp
649|
650| For fdiv/fsgldiv:
651| if(both operands are denorm)
652| restore_to_fpu;
653| if(dest is norm)
654| force_ovf;
655| else(dest is denorm)
656| force_unf:
657|
658| For fcmp:
659| if(dest is norm)
660| N = sign_of(dest);
661| else(dest is denorm)
662| N = sign_of(src);
663|
664| For fmul:
665| if(both operands are denorm)
666| force_unf;
667| if((dest_exp + src_exp) < 0)
668| force_unf:
669| else
670| restore_to_fpu;
671|
672| local equates:
673 .set addcode,0x22
674 .set subcode,0x28
675 .set mulcode,0x23
676 .set divcode,0x20
677 .set cmpcode,0x38
678ck_wrap:
679 | tstb DY_MO_FLG(%a6) ;check for fsqrt
680 beq fix_stk |if zero, it is fsqrt
681 movew CMDREG1B(%a6),%d0
682 andiw #0x3b,%d0 |strip to command bits
683 cmpiw #addcode,%d0
684 beq wrap_add
685 cmpiw #subcode,%d0
686 beq wrap_sub
687 cmpiw #mulcode,%d0
688 beq wrap_mul
689 cmpiw #cmpcode,%d0
690 beq wrap_cmp
691|
692| Inst is fdiv.
693|
694wrap_div:
695 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
696 beq fix_stk |restore to fpu
697|
698| One of the ops is denormalized. Test for wrap condition
699| and force the result.
700|
701 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
702 bnes div_srcd
703div_destd:
704 bsrl ckinf_ns
705 bne fix_stk
706 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
707 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
708 subl %d1,%d0 |subtract dest from src
709 cmpl #0x7fff,%d0
710 blt fix_stk |if less, not wrap case
711 clrb WBTEMP_SGN(%a6)
712 movew ETEMP_EX(%a6),%d0 |find the sign of the result
713 movew FPTEMP_EX(%a6),%d1
714 eorw %d1,%d0
715 andiw #0x8000,%d0
716 beq force_unf
717 st WBTEMP_SGN(%a6)
718 bra force_unf
719
720ckinf_ns:
721 moveb STAG(%a6),%d0 |check source tag for inf or nan
722 bra ck_in_com
723ckinf_nd:
724 moveb DTAG(%a6),%d0 |check destination tag for inf or nan
725ck_in_com:
726 andib #0x60,%d0 |isolate tag bits
727 cmpb #0x40,%d0 |is it inf?
728 beq nan_or_inf |not wrap case
729 cmpb #0x60,%d0 |is it nan?
730 beq nan_or_inf |yes, not wrap case?
731 cmpb #0x20,%d0 |is it a zero?
732 beq nan_or_inf |yes
733 clrl %d0
734 rts |then ; it is either a zero of norm,
735| ;check wrap case
736nan_or_inf:
737 moveql #-1,%d0
738 rts
739
740
741
742div_srcd:
743 bsrl ckinf_nd
744 bne fix_stk
745 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
746 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
747 subl %d1,%d0 |subtract src from dest
748 cmpl #0x8000,%d0
749 blt fix_stk |if less, not wrap case
750 clrb WBTEMP_SGN(%a6)
751 movew ETEMP_EX(%a6),%d0 |find the sign of the result
752 movew FPTEMP_EX(%a6),%d1
753 eorw %d1,%d0
754 andiw #0x8000,%d0
755 beqs force_ovf
756 st WBTEMP_SGN(%a6)
757|
758| This code handles the case of the instruction resulting in
759| an overflow condition.
760|
761force_ovf:
762 bclrb #E1,E_BYTE(%a6)
763 orl #ovfl_inx_mask,USER_FPSR(%a6)
764 clrw NMNEXC(%a6)
765 leal WBTEMP(%a6),%a0 |point a0 to memory location
766 movew CMDREG1B(%a6),%d0
767 btstl #6,%d0 |test for forced precision
768 beqs frcovf_fpcr
769 btstl #2,%d0 |check for double
770 bnes frcovf_dbl
771 movel #0x1,%d0 |inst is forced single
772 bras frcovf_rnd
773frcovf_dbl:
774 movel #0x2,%d0 |inst is forced double
775 bras frcovf_rnd
776frcovf_fpcr:
777 bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec
778frcovf_rnd:
779
780| The 881/882 does not set inex2 for the following case, so the
781| line is commented out to be compatible with 881/882
782| tst.b %d0
783| beq.b frcovf_x
784| or.l #inex2_mask,USER_FPSR(%a6) ;if prec is s or d, set inex2
785
786|frcovf_x:
787 bsrl ovf_res |get correct result based on
788| ;round precision/mode. This
789| ;sets FPSR_CC correctly
790| ;returns in external format
791 bfclr WBTEMP_SGN(%a6){#0:#8}
792 beq frcfpn
793 bsetb #sign_bit,WBTEMP_EX(%a6)
794 bra frcfpn
795|
796| Inst is fadd.
797|
798wrap_add:
799 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
800 beq fix_stk |restore to fpu
801|
802| One of the ops is denormalized. Test for wrap condition
803| and complete the instruction.
804|
805 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
806 bnes add_srcd
807add_destd:
808 bsrl ckinf_ns
809 bne fix_stk
810 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
811 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
812 subl %d1,%d0 |subtract dest from src
813 cmpl #0x8000,%d0
814 blt fix_stk |if less, not wrap case
815 bra add_wrap
816add_srcd:
817 bsrl ckinf_nd
818 bne fix_stk
819 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
820 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
821 subl %d1,%d0 |subtract src from dest
822 cmpl #0x8000,%d0
823 blt fix_stk |if less, not wrap case
824|
825| Check the signs of the operands. If they are unlike, the fpu
826| can be used to add the norm and 1.0 with the sign of the
827| denorm and it will correctly generate the result in extended
828| precision. We can then call round with no sticky and the result
829| will be correct for the user's rounding mode and precision. If
830| the signs are the same, we call round with the sticky bit set
831| and the result will be correct for the user's rounding mode and
832| precision.
833|
834add_wrap:
835 movew ETEMP_EX(%a6),%d0
836 movew FPTEMP_EX(%a6),%d1
837 eorw %d1,%d0
838 andiw #0x8000,%d0
839 beq add_same
840|
841| The signs are unlike.
842|
843 cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm?
844 bnes add_u_srcd
845 movew FPTEMP_EX(%a6),%d0
846 andiw #0x8000,%d0
847 orw #0x3fff,%d0 |force the exponent to +/- 1
848 movew %d0,FPTEMP_EX(%a6) |in the denorm
849 movel USER_FPCR(%a6),%d0
850 andil #0x30,%d0
851 fmovel %d0,%fpcr |set up users rmode and X
852 fmovex ETEMP(%a6),%fp0
853 faddx FPTEMP(%a6),%fp0
854 leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame
855 fmovel %fpsr,%d1
856 orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd
857 fmovex %fp0,WBTEMP(%a6) |write result to memory
858 lsrl #4,%d0 |put rmode in lower 2 bits
859 movel USER_FPCR(%a6),%d1
860 andil #0xc0,%d1
861 lsrl #6,%d1 |put precision in upper word
862 swap %d1
863 orl %d0,%d1 |set up for round call
864 clrl %d0 |force sticky to zero
865 bclrb #sign_bit,WBTEMP_EX(%a6)
866 sne WBTEMP_SGN(%a6)
867 bsrl round |round result to users rmode & prec
868 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
869 beq frcfpnr
870 bsetb #sign_bit,WBTEMP_EX(%a6)
871 bra frcfpnr
872add_u_srcd:
873 movew ETEMP_EX(%a6),%d0
874 andiw #0x8000,%d0
875 orw #0x3fff,%d0 |force the exponent to +/- 1
876 movew %d0,ETEMP_EX(%a6) |in the denorm
877 movel USER_FPCR(%a6),%d0
878 andil #0x30,%d0
879 fmovel %d0,%fpcr |set up users rmode and X
880 fmovex ETEMP(%a6),%fp0
881 faddx FPTEMP(%a6),%fp0
882 fmovel %fpsr,%d1
883 orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd
884 leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame
885 fmovex %fp0,WBTEMP(%a6) |write result to memory
886 lsrl #4,%d0 |put rmode in lower 2 bits
887 movel USER_FPCR(%a6),%d1
888 andil #0xc0,%d1
889 lsrl #6,%d1 |put precision in upper word
890 swap %d1
891 orl %d0,%d1 |set up for round call
892 clrl %d0 |force sticky to zero
893 bclrb #sign_bit,WBTEMP_EX(%a6)
894 sne WBTEMP_SGN(%a6) |use internal format for round
895 bsrl round |round result to users rmode & prec
896 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
897 beq frcfpnr
898 bsetb #sign_bit,WBTEMP_EX(%a6)
899 bra frcfpnr
900|
901| Signs are alike:
902|
903add_same:
904 cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm?
905 bnes add_s_srcd
906add_s_destd:
907 leal ETEMP(%a6),%a0
908 movel USER_FPCR(%a6),%d0
909 andil #0x30,%d0
910 lsrl #4,%d0 |put rmode in lower 2 bits
911 movel USER_FPCR(%a6),%d1
912 andil #0xc0,%d1
913 lsrl #6,%d1 |put precision in upper word
914 swap %d1
915 orl %d0,%d1 |set up for round call
916 movel #0x20000000,%d0 |set sticky for round
917 bclrb #sign_bit,ETEMP_EX(%a6)
918 sne ETEMP_SGN(%a6)
919 bsrl round |round result to users rmode & prec
920 bfclr ETEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
921 beqs add_s_dclr
922 bsetb #sign_bit,ETEMP_EX(%a6)
923add_s_dclr:
924 leal WBTEMP(%a6),%a0
925 movel ETEMP(%a6),(%a0) |write result to wbtemp
926 movel ETEMP_HI(%a6),4(%a0)
927 movel ETEMP_LO(%a6),8(%a0)
928 tstw ETEMP_EX(%a6)
929 bgt add_ckovf
930 orl #neg_mask,USER_FPSR(%a6)
931 bra add_ckovf
932add_s_srcd:
933 leal FPTEMP(%a6),%a0
934 movel USER_FPCR(%a6),%d0
935 andil #0x30,%d0
936 lsrl #4,%d0 |put rmode in lower 2 bits
937 movel USER_FPCR(%a6),%d1
938 andil #0xc0,%d1
939 lsrl #6,%d1 |put precision in upper word
940 swap %d1
941 orl %d0,%d1 |set up for round call
942 movel #0x20000000,%d0 |set sticky for round
943 bclrb #sign_bit,FPTEMP_EX(%a6)
944 sne FPTEMP_SGN(%a6)
945 bsrl round |round result to users rmode & prec
946 bfclr FPTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
947 beqs add_s_sclr
948 bsetb #sign_bit,FPTEMP_EX(%a6)
949add_s_sclr:
950 leal WBTEMP(%a6),%a0
951 movel FPTEMP(%a6),(%a0) |write result to wbtemp
952 movel FPTEMP_HI(%a6),4(%a0)
953 movel FPTEMP_LO(%a6),8(%a0)
954 tstw FPTEMP_EX(%a6)
955 bgt add_ckovf
956 orl #neg_mask,USER_FPSR(%a6)
957add_ckovf:
958 movew WBTEMP_EX(%a6),%d0
959 andiw #0x7fff,%d0
960 cmpiw #0x7fff,%d0
961 bne frcfpnr
962|
963| The result has overflowed to $7fff exponent. Set I, ovfl,
964| and aovfl, and clr the mantissa (incorrectly set by the
965| round routine.)
966|
967 orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6)
968 clrl 4(%a0)
969 bra frcfpnr
970|
971| Inst is fsub.
972|
973wrap_sub:
974 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
975 beq fix_stk |restore to fpu
976|
977| One of the ops is denormalized. Test for wrap condition
978| and complete the instruction.
979|
980 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
981 bnes sub_srcd
982sub_destd:
983 bsrl ckinf_ns
984 bne fix_stk
985 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
986 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
987 subl %d1,%d0 |subtract src from dest
988 cmpl #0x8000,%d0
989 blt fix_stk |if less, not wrap case
990 bra sub_wrap
991sub_srcd:
992 bsrl ckinf_nd
993 bne fix_stk
994 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
995 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
996 subl %d1,%d0 |subtract dest from src
997 cmpl #0x8000,%d0
998 blt fix_stk |if less, not wrap case
999|
1000| Check the signs of the operands. If they are alike, the fpu
1001| can be used to subtract from the norm 1.0 with the sign of the
1002| denorm and it will correctly generate the result in extended
1003| precision. We can then call round with no sticky and the result
1004| will be correct for the user's rounding mode and precision. If
1005| the signs are unlike, we call round with the sticky bit set
1006| and the result will be correct for the user's rounding mode and
1007| precision.
1008|
1009sub_wrap:
1010 movew ETEMP_EX(%a6),%d0
1011 movew FPTEMP_EX(%a6),%d1
1012 eorw %d1,%d0
1013 andiw #0x8000,%d0
1014 bne sub_diff
1015|
1016| The signs are alike.
1017|
1018 cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm?
1019 bnes sub_u_srcd
1020 movew FPTEMP_EX(%a6),%d0
1021 andiw #0x8000,%d0
1022 orw #0x3fff,%d0 |force the exponent to +/- 1
1023 movew %d0,FPTEMP_EX(%a6) |in the denorm
1024 movel USER_FPCR(%a6),%d0
1025 andil #0x30,%d0
1026 fmovel %d0,%fpcr |set up users rmode and X
1027 fmovex FPTEMP(%a6),%fp0
1028 fsubx ETEMP(%a6),%fp0
1029 fmovel %fpsr,%d1
1030 orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd
1031 leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame
1032 fmovex %fp0,WBTEMP(%a6) |write result to memory
1033 lsrl #4,%d0 |put rmode in lower 2 bits
1034 movel USER_FPCR(%a6),%d1
1035 andil #0xc0,%d1
1036 lsrl #6,%d1 |put precision in upper word
1037 swap %d1
1038 orl %d0,%d1 |set up for round call
1039 clrl %d0 |force sticky to zero
1040 bclrb #sign_bit,WBTEMP_EX(%a6)
1041 sne WBTEMP_SGN(%a6)
1042 bsrl round |round result to users rmode & prec
1043 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
1044 beq frcfpnr
1045 bsetb #sign_bit,WBTEMP_EX(%a6)
1046 bra frcfpnr
1047sub_u_srcd:
1048 movew ETEMP_EX(%a6),%d0
1049 andiw #0x8000,%d0
1050 orw #0x3fff,%d0 |force the exponent to +/- 1
1051 movew %d0,ETEMP_EX(%a6) |in the denorm
1052 movel USER_FPCR(%a6),%d0
1053 andil #0x30,%d0
1054 fmovel %d0,%fpcr |set up users rmode and X
1055 fmovex FPTEMP(%a6),%fp0
1056 fsubx ETEMP(%a6),%fp0
1057 fmovel %fpsr,%d1
1058 orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd
1059 leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame
1060 fmovex %fp0,WBTEMP(%a6) |write result to memory
1061 lsrl #4,%d0 |put rmode in lower 2 bits
1062 movel USER_FPCR(%a6),%d1
1063 andil #0xc0,%d1
1064 lsrl #6,%d1 |put precision in upper word
1065 swap %d1
1066 orl %d0,%d1 |set up for round call
1067 clrl %d0 |force sticky to zero
1068 bclrb #sign_bit,WBTEMP_EX(%a6)
1069 sne WBTEMP_SGN(%a6)
1070 bsrl round |round result to users rmode & prec
1071 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
1072 beq frcfpnr
1073 bsetb #sign_bit,WBTEMP_EX(%a6)
1074 bra frcfpnr
1075|
1076| Signs are unlike:
1077|
1078sub_diff:
1079 cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm?
1080 bnes sub_s_srcd
1081sub_s_destd:
1082 leal ETEMP(%a6),%a0
1083 movel USER_FPCR(%a6),%d0
1084 andil #0x30,%d0
1085 lsrl #4,%d0 |put rmode in lower 2 bits
1086 movel USER_FPCR(%a6),%d1
1087 andil #0xc0,%d1
1088 lsrl #6,%d1 |put precision in upper word
1089 swap %d1
1090 orl %d0,%d1 |set up for round call
1091 movel #0x20000000,%d0 |set sticky for round
1092|
1093| Since the dest is the denorm, the sign is the opposite of the
1094| norm sign.
1095|
1096 eoriw #0x8000,ETEMP_EX(%a6) |flip sign on result
1097 tstw ETEMP_EX(%a6)
1098 bgts sub_s_dwr
1099 orl #neg_mask,USER_FPSR(%a6)
1100sub_s_dwr:
1101 bclrb #sign_bit,ETEMP_EX(%a6)
1102 sne ETEMP_SGN(%a6)
1103 bsrl round |round result to users rmode & prec
1104 bfclr ETEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
1105 beqs sub_s_dclr
1106 bsetb #sign_bit,ETEMP_EX(%a6)
1107sub_s_dclr:
1108 leal WBTEMP(%a6),%a0
1109 movel ETEMP(%a6),(%a0) |write result to wbtemp
1110 movel ETEMP_HI(%a6),4(%a0)
1111 movel ETEMP_LO(%a6),8(%a0)
1112 bra sub_ckovf
1113sub_s_srcd:
1114 leal FPTEMP(%a6),%a0
1115 movel USER_FPCR(%a6),%d0
1116 andil #0x30,%d0
1117 lsrl #4,%d0 |put rmode in lower 2 bits
1118 movel USER_FPCR(%a6),%d1
1119 andil #0xc0,%d1
1120 lsrl #6,%d1 |put precision in upper word
1121 swap %d1
1122 orl %d0,%d1 |set up for round call
1123 movel #0x20000000,%d0 |set sticky for round
1124 bclrb #sign_bit,FPTEMP_EX(%a6)
1125 sne FPTEMP_SGN(%a6)
1126 bsrl round |round result to users rmode & prec
1127 bfclr FPTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
1128 beqs sub_s_sclr
1129 bsetb #sign_bit,FPTEMP_EX(%a6)
1130sub_s_sclr:
1131 leal WBTEMP(%a6),%a0
1132 movel FPTEMP(%a6),(%a0) |write result to wbtemp
1133 movel FPTEMP_HI(%a6),4(%a0)
1134 movel FPTEMP_LO(%a6),8(%a0)
1135 tstw FPTEMP_EX(%a6)
1136 bgt sub_ckovf
1137 orl #neg_mask,USER_FPSR(%a6)
1138sub_ckovf:
1139 movew WBTEMP_EX(%a6),%d0
1140 andiw #0x7fff,%d0
1141 cmpiw #0x7fff,%d0
1142 bne frcfpnr
1143|
1144| The result has overflowed to $7fff exponent. Set I, ovfl,
1145| and aovfl, and clr the mantissa (incorrectly set by the
1146| round routine.)
1147|
1148 orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6)
1149 clrl 4(%a0)
1150 bra frcfpnr
1151|
1152| Inst is fcmp.
1153|
1154wrap_cmp:
1155 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
1156 beq fix_stk |restore to fpu
1157|
1158| One of the ops is denormalized. Test for wrap condition
1159| and complete the instruction.
1160|
1161 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
1162 bnes cmp_srcd
1163cmp_destd:
1164 bsrl ckinf_ns
1165 bne fix_stk
1166 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
1167 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
1168 subl %d1,%d0 |subtract dest from src
1169 cmpl #0x8000,%d0
1170 blt fix_stk |if less, not wrap case
1171 tstw ETEMP_EX(%a6) |set N to ~sign_of(src)
1172 bge cmp_setn
1173 rts
1174cmp_srcd:
1175 bsrl ckinf_nd
1176 bne fix_stk
1177 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
1178 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
1179 subl %d1,%d0 |subtract src from dest
1180 cmpl #0x8000,%d0
1181 blt fix_stk |if less, not wrap case
1182 tstw FPTEMP_EX(%a6) |set N to sign_of(dest)
1183 blt cmp_setn
1184 rts
1185cmp_setn:
1186 orl #neg_mask,USER_FPSR(%a6)
1187 rts
1188
1189|
1190| Inst is fmul.
1191|
1192wrap_mul:
1193 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
1194 beq force_unf |force an underflow (really!)
1195|
1196| One of the ops is denormalized. Test for wrap condition
1197| and complete the instruction.
1198|
1199 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
1200 bnes mul_srcd
1201mul_destd:
1202 bsrl ckinf_ns
1203 bne fix_stk
1204 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
1205 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
1206 addl %d1,%d0 |subtract dest from src
1207 bgt fix_stk
1208 bra force_unf
1209mul_srcd:
1210 bsrl ckinf_nd
1211 bne fix_stk
1212 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
1213 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
1214 addl %d1,%d0 |subtract src from dest
1215 bgt fix_stk
1216
1217|
1218| This code handles the case of the instruction resulting in
1219| an underflow condition.
1220|
1221force_unf:
1222 bclrb #E1,E_BYTE(%a6)
1223 orl #unfinx_mask,USER_FPSR(%a6)
1224 clrw NMNEXC(%a6)
1225 clrb WBTEMP_SGN(%a6)
1226 movew ETEMP_EX(%a6),%d0 |find the sign of the result
1227 movew FPTEMP_EX(%a6),%d1
1228 eorw %d1,%d0
1229 andiw #0x8000,%d0
1230 beqs frcunfcont
1231 st WBTEMP_SGN(%a6)
1232frcunfcont:
1233 lea WBTEMP(%a6),%a0 |point a0 to memory location
1234 movew CMDREG1B(%a6),%d0
1235 btstl #6,%d0 |test for forced precision
1236 beqs frcunf_fpcr
1237 btstl #2,%d0 |check for double
1238 bnes frcunf_dbl
1239 movel #0x1,%d0 |inst is forced single
1240 bras frcunf_rnd
1241frcunf_dbl:
1242 movel #0x2,%d0 |inst is forced double
1243 bras frcunf_rnd
1244frcunf_fpcr:
1245 bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec
1246frcunf_rnd:
1247 bsrl unf_sub |get correct result based on
1248| ;round precision/mode. This
1249| ;sets FPSR_CC correctly
1250 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
1251 beqs frcfpn
1252 bsetb #sign_bit,WBTEMP_EX(%a6)
1253 bra frcfpn
1254
1255|
1256| Write the result to the user's fpn. All results must be HUGE to be
1257| written; otherwise the results would have overflowed or underflowed.
1258| If the rounding precision is single or double, the ovf_res routine
1259| is needed to correctly supply the max value.
1260|
1261frcfpnr:
1262 movew CMDREG1B(%a6),%d0
1263 btstl #6,%d0 |test for forced precision
1264 beqs frcfpn_fpcr
1265 btstl #2,%d0 |check for double
1266 bnes frcfpn_dbl
1267 movel #0x1,%d0 |inst is forced single
1268 bras frcfpn_rnd
1269frcfpn_dbl:
1270 movel #0x2,%d0 |inst is forced double
1271 bras frcfpn_rnd
1272frcfpn_fpcr:
1273 bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec
1274 tstb %d0
1275 beqs frcfpn |if extended, write what you got
1276frcfpn_rnd:
1277 bclrb #sign_bit,WBTEMP_EX(%a6)
1278 sne WBTEMP_SGN(%a6)
1279 bsrl ovf_res |get correct result based on
1280| ;round precision/mode. This
1281| ;sets FPSR_CC correctly
1282 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
1283 beqs frcfpn_clr
1284 bsetb #sign_bit,WBTEMP_EX(%a6)
1285frcfpn_clr:
1286 orl #ovfinx_mask,USER_FPSR(%a6)
1287|
1288| Perform the write.
1289|
1290frcfpn:
1291 bfextu CMDREG1B(%a6){#6:#3},%d0 |extract fp destination register
1292 cmpib #3,%d0
1293 bles frc0123 |check if dest is fp0-fp3
1294 movel #7,%d1
1295 subl %d0,%d1
1296 clrl %d0
1297 bsetl %d1,%d0
1298 fmovemx WBTEMP(%a6),%d0
1299 rts
1300frc0123:
1301 cmpib #0,%d0
1302 beqs frc0_dst
1303 cmpib #1,%d0
1304 beqs frc1_dst
1305 cmpib #2,%d0
1306 beqs frc2_dst
1307frc3_dst:
1308 movel WBTEMP_EX(%a6),USER_FP3(%a6)
1309 movel WBTEMP_HI(%a6),USER_FP3+4(%a6)
1310 movel WBTEMP_LO(%a6),USER_FP3+8(%a6)
1311 rts
1312frc2_dst:
1313 movel WBTEMP_EX(%a6),USER_FP2(%a6)
1314 movel WBTEMP_HI(%a6),USER_FP2+4(%a6)
1315 movel WBTEMP_LO(%a6),USER_FP2+8(%a6)
1316 rts
1317frc1_dst:
1318 movel WBTEMP_EX(%a6),USER_FP1(%a6)
1319 movel WBTEMP_HI(%a6),USER_FP1+4(%a6)
1320 movel WBTEMP_LO(%a6),USER_FP1+8(%a6)
1321 rts
1322frc0_dst:
1323 movel WBTEMP_EX(%a6),USER_FP0(%a6)
1324 movel WBTEMP_HI(%a6),USER_FP0+4(%a6)
1325 movel WBTEMP_LO(%a6),USER_FP0+8(%a6)
1326 rts
1327
1328|
1329| Write etemp to fpn.
1330| A check is made on enabled and signalled snan exceptions,
1331| and the destination is not overwritten if this condition exists.
1332| This code is designed to make fmoveins of unsupported data types
1333| faster.
1334|
1335wr_etemp:
1336 btstb #snan_bit,FPSR_EXCEPT(%a6) |if snan is set, and
1337 beqs fmoveinc |enabled, force restore
1338 btstb #snan_bit,FPCR_ENABLE(%a6) |and don't overwrite
1339 beqs fmoveinc |the dest
1340 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for
1341| ;snan handler
1342 tstb ETEMP(%a6) |check for negative
1343 blts snan_neg
1344 rts
1345snan_neg:
1346 orl #neg_bit,USER_FPSR(%a6) |snan is negative; set N
1347 rts
1348fmoveinc:
1349 clrw NMNEXC(%a6)
1350 bclrb #E1,E_BYTE(%a6)
1351 moveb STAG(%a6),%d0 |check if stag is inf
1352 andib #0xe0,%d0
1353 cmpib #0x40,%d0
1354 bnes fminc_cnan
1355 orl #inf_mask,USER_FPSR(%a6) |if inf, nothing yet has set I
1356 tstw LOCAL_EX(%a0) |check sign
1357 bges fminc_con
1358 orl #neg_mask,USER_FPSR(%a6)
1359 bra fminc_con
1360fminc_cnan:
1361 cmpib #0x60,%d0 |check if stag is NaN
1362 bnes fminc_czero
1363 orl #nan_mask,USER_FPSR(%a6) |if nan, nothing yet has set NaN
1364 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for
1365| ;snan handler
1366 tstw LOCAL_EX(%a0) |check sign
1367 bges fminc_con
1368 orl #neg_mask,USER_FPSR(%a6)
1369 bra fminc_con
1370fminc_czero:
1371 cmpib #0x20,%d0 |check if zero
1372 bnes fminc_con
1373 orl #z_mask,USER_FPSR(%a6) |if zero, set Z
1374 tstw LOCAL_EX(%a0) |check sign
1375 bges fminc_con
1376 orl #neg_mask,USER_FPSR(%a6)
1377fminc_con:
1378 bfextu CMDREG1B(%a6){#6:#3},%d0 |extract fp destination register
1379 cmpib #3,%d0
1380 bles fp0123 |check if dest is fp0-fp3
1381 movel #7,%d1
1382 subl %d0,%d1
1383 clrl %d0
1384 bsetl %d1,%d0
1385 fmovemx ETEMP(%a6),%d0
1386 rts
1387
1388fp0123:
1389 cmpib #0,%d0
1390 beqs fp0_dst
1391 cmpib #1,%d0
1392 beqs fp1_dst
1393 cmpib #2,%d0
1394 beqs fp2_dst
1395fp3_dst:
1396 movel ETEMP_EX(%a6),USER_FP3(%a6)
1397 movel ETEMP_HI(%a6),USER_FP3+4(%a6)
1398 movel ETEMP_LO(%a6),USER_FP3+8(%a6)
1399 rts
1400fp2_dst:
1401 movel ETEMP_EX(%a6),USER_FP2(%a6)
1402 movel ETEMP_HI(%a6),USER_FP2+4(%a6)
1403 movel ETEMP_LO(%a6),USER_FP2+8(%a6)
1404 rts
1405fp1_dst:
1406 movel ETEMP_EX(%a6),USER_FP1(%a6)
1407 movel ETEMP_HI(%a6),USER_FP1+4(%a6)
1408 movel ETEMP_LO(%a6),USER_FP1+8(%a6)
1409 rts
1410fp0_dst:
1411 movel ETEMP_EX(%a6),USER_FP0(%a6)
1412 movel ETEMP_HI(%a6),USER_FP0+4(%a6)
1413 movel ETEMP_LO(%a6),USER_FP0+8(%a6)
1414 rts
1415
1416opclass3:
1417 st CU_ONLY(%a6)
1418 movew CMDREG1B(%a6),%d0 |check if packed moveout
1419 andiw #0x0c00,%d0 |isolate last 2 bits of size field
1420 cmpiw #0x0c00,%d0 |if size is 011 or 111, it is packed
1421 beq pack_out |else it is norm or denorm
1422 bra mv_out
1423
1424
1425|
1426| MOVE OUT
1427|
1428
1429mv_tbl:
1430 .long li
1431 .long sgp
1432 .long xp
1433 .long mvout_end |should never be taken
1434 .long wi
1435 .long dp
1436 .long bi
1437 .long mvout_end |should never be taken
1438mv_out:
1439 bfextu CMDREG1B(%a6){#3:#3},%d1 |put source specifier in d1
1440 leal mv_tbl,%a0
1441 movel %a0@(%d1:l:4),%a0
1442 jmp (%a0)
1443
1444|
1445| This exit is for move-out to memory. The aunfl bit is
1446| set if the result is inex and unfl is signalled.
1447|
1448mvout_end:
1449 btstb #inex2_bit,FPSR_EXCEPT(%a6)
1450 beqs no_aufl
1451 btstb #unfl_bit,FPSR_EXCEPT(%a6)
1452 beqs no_aufl
1453 bsetb #aunfl_bit,FPSR_AEXCEPT(%a6)
1454no_aufl:
1455 clrw NMNEXC(%a6)
1456 bclrb #E1,E_BYTE(%a6)
1457 fmovel #0,%FPSR |clear any cc bits from res_func
1458|
1459| Return ETEMP to extended format from internal extended format so
1460| that gen_except will have a correctly signed value for ovfl/unfl
1461| handlers.
1462|
1463 bfclr ETEMP_SGN(%a6){#0:#8}
1464 beqs mvout_con
1465 bsetb #sign_bit,ETEMP_EX(%a6)
1466mvout_con:
1467 rts
1468|
1469| This exit is for move-out to int register. The aunfl bit is
1470| not set in any case for this move.
1471|
1472mvouti_end:
1473 clrw NMNEXC(%a6)
1474 bclrb #E1,E_BYTE(%a6)
1475 fmovel #0,%FPSR |clear any cc bits from res_func
1476|
1477| Return ETEMP to extended format from internal extended format so
1478| that gen_except will have a correctly signed value for ovfl/unfl
1479| handlers.
1480|
1481 bfclr ETEMP_SGN(%a6){#0:#8}
1482 beqs mvouti_con
1483 bsetb #sign_bit,ETEMP_EX(%a6)
1484mvouti_con:
1485 rts
1486|
1487| li is used to handle a long integer source specifier
1488|
1489
1490li:
1491 moveql #4,%d0 |set byte count
1492
1493 btstb #7,STAG(%a6) |check for extended denorm
1494 bne int_dnrm |if so, branch
1495
1496 fmovemx ETEMP(%a6),%fp0-%fp0
1497 fcmpd #0x41dfffffffc00000,%fp0
1498| 41dfffffffc00000 in dbl prec = 401d0000fffffffe00000000 in ext prec
1499 fbge lo_plrg
1500 fcmpd #0xc1e0000000000000,%fp0
1501| c1e0000000000000 in dbl prec = c01e00008000000000000000 in ext prec
1502 fble lo_nlrg
1503|
1504| at this point, the answer is between the largest pos and neg values
1505|
1506 movel USER_FPCR(%a6),%d1 |use user's rounding mode
1507 andil #0x30,%d1
1508 fmovel %d1,%fpcr
1509 fmovel %fp0,L_SCR1(%a6) |let the 040 perform conversion
1510 fmovel %fpsr,%d1
1511 orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set
1512 bra int_wrt
1513
1514
1515lo_plrg:
1516 movel #0x7fffffff,L_SCR1(%a6) |answer is largest positive int
1517 fbeq int_wrt |exact answer
1518 fcmpd #0x41dfffffffe00000,%fp0
1519| 41dfffffffe00000 in dbl prec = 401d0000ffffffff00000000 in ext prec
1520 fbge int_operr |set operr
1521 bra int_inx |set inexact
1522
1523lo_nlrg:
1524 movel #0x80000000,L_SCR1(%a6)
1525 fbeq int_wrt |exact answer
1526 fcmpd #0xc1e0000000100000,%fp0
1527| c1e0000000100000 in dbl prec = c01e00008000000080000000 in ext prec
1528 fblt int_operr |set operr
1529 bra int_inx |set inexact
1530
1531|
1532| wi is used to handle a word integer source specifier
1533|
1534
1535wi:
1536 moveql #2,%d0 |set byte count
1537
1538 btstb #7,STAG(%a6) |check for extended denorm
1539 bne int_dnrm |branch if so
1540
1541 fmovemx ETEMP(%a6),%fp0-%fp0
1542 fcmps #0x46fffe00,%fp0
1543| 46fffe00 in sgl prec = 400d0000fffe000000000000 in ext prec
1544 fbge wo_plrg
1545 fcmps #0xc7000000,%fp0
1546| c7000000 in sgl prec = c00e00008000000000000000 in ext prec
1547 fble wo_nlrg
1548
1549|
1550| at this point, the answer is between the largest pos and neg values
1551|
1552 movel USER_FPCR(%a6),%d1 |use user's rounding mode
1553 andil #0x30,%d1
1554 fmovel %d1,%fpcr
1555 fmovew %fp0,L_SCR1(%a6) |let the 040 perform conversion
1556 fmovel %fpsr,%d1
1557 orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set
1558 bra int_wrt
1559
1560wo_plrg:
1561 movew #0x7fff,L_SCR1(%a6) |answer is largest positive int
1562 fbeq int_wrt |exact answer
1563 fcmps #0x46ffff00,%fp0
1564| 46ffff00 in sgl prec = 400d0000ffff000000000000 in ext prec
1565 fbge int_operr |set operr
1566 bra int_inx |set inexact
1567
1568wo_nlrg:
1569 movew #0x8000,L_SCR1(%a6)
1570 fbeq int_wrt |exact answer
1571 fcmps #0xc7000080,%fp0
1572| c7000080 in sgl prec = c00e00008000800000000000 in ext prec
1573 fblt int_operr |set operr
1574 bra int_inx |set inexact
1575
1576|
1577| bi is used to handle a byte integer source specifier
1578|
1579
1580bi:
1581 moveql #1,%d0 |set byte count
1582
1583 btstb #7,STAG(%a6) |check for extended denorm
1584 bne int_dnrm |branch if so
1585
1586 fmovemx ETEMP(%a6),%fp0-%fp0
1587 fcmps #0x42fe0000,%fp0
1588| 42fe0000 in sgl prec = 40050000fe00000000000000 in ext prec
1589 fbge by_plrg
1590 fcmps #0xc3000000,%fp0
1591| c3000000 in sgl prec = c00600008000000000000000 in ext prec
1592 fble by_nlrg
1593
1594|
1595| at this point, the answer is between the largest pos and neg values
1596|
1597 movel USER_FPCR(%a6),%d1 |use user's rounding mode
1598 andil #0x30,%d1
1599 fmovel %d1,%fpcr
1600 fmoveb %fp0,L_SCR1(%a6) |let the 040 perform conversion
1601 fmovel %fpsr,%d1
1602 orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set
1603 bra int_wrt
1604
1605by_plrg:
1606 moveb #0x7f,L_SCR1(%a6) |answer is largest positive int
1607 fbeq int_wrt |exact answer
1608 fcmps #0x42ff0000,%fp0
1609| 42ff0000 in sgl prec = 40050000ff00000000000000 in ext prec
1610 fbge int_operr |set operr
1611 bra int_inx |set inexact
1612
1613by_nlrg:
1614 moveb #0x80,L_SCR1(%a6)
1615 fbeq int_wrt |exact answer
1616 fcmps #0xc3008000,%fp0
1617| c3008000 in sgl prec = c00600008080000000000000 in ext prec
1618 fblt int_operr |set operr
1619 bra int_inx |set inexact
1620
1621|
1622| Common integer routines
1623|
1624| int_drnrm---account for possible nonzero result for round up with positive
1625| operand and round down for negative answer. In the first case (result = 1)
1626| byte-width (store in d0) of result must be honored. In the second case,
1627| -1 in L_SCR1(a6) will cover all contingencies (FMOVE.B/W/L out).
1628
1629int_dnrm:
1630 movel #0,L_SCR1(%a6) | initialize result to 0
1631 bfextu FPCR_MODE(%a6){#2:#2},%d1 | d1 is the rounding mode
1632 cmpb #2,%d1
1633 bmis int_inx | if RN or RZ, done
1634 bnes int_rp | if RP, continue below
1635 tstw ETEMP(%a6) | RM: store -1 in L_SCR1 if src is negative
1636 bpls int_inx | otherwise result is 0
1637 movel #-1,L_SCR1(%a6)
1638 bras int_inx
1639int_rp:
1640 tstw ETEMP(%a6) | RP: store +1 of proper width in L_SCR1 if
1641| ; source is greater than 0
1642 bmis int_inx | otherwise, result is 0
1643 lea L_SCR1(%a6),%a1 | a1 is address of L_SCR1
1644 addal %d0,%a1 | offset by destination width -1
1645 subal #1,%a1
1646 bsetb #0,(%a1) | set low bit at a1 address
1647int_inx:
1648 oril #inx2a_mask,USER_FPSR(%a6)
1649 bras int_wrt
1650int_operr:
1651 fmovemx %fp0-%fp0,FPTEMP(%a6) |FPTEMP must contain the extended
1652| ;precision source that needs to be
1653| ;converted to integer this is required
1654| ;if the operr exception is enabled.
1655| ;set operr/aiop (no inex2 on int ovfl)
1656
1657 oril #opaop_mask,USER_FPSR(%a6)
1658| ;fall through to perform int_wrt
1659int_wrt:
1660 movel EXC_EA(%a6),%a1 |load destination address
1661 tstl %a1 |check to see if it is a dest register
1662 beqs wrt_dn |write data register
1663 lea L_SCR1(%a6),%a0 |point to supervisor source address
1664 bsrl mem_write
1665 bra mvouti_end
1666
1667wrt_dn:
1668 movel %d0,-(%sp) |d0 currently contains the size to write
1669 bsrl get_fline |get_fline returns Dn in d0
1670 andiw #0x7,%d0 |isolate register
1671 movel (%sp)+,%d1 |get size
1672 cmpil #4,%d1 |most frequent case
1673 beqs sz_long
1674 cmpil #2,%d1
1675 bnes sz_con
1676 orl #8,%d0 |add 'word' size to register#
1677 bras sz_con
1678sz_long:
1679 orl #0x10,%d0 |add 'long' size to register#
1680sz_con:
1681 movel %d0,%d1 |reg_dest expects size:reg in d1
1682 bsrl reg_dest |load proper data register
1683 bra mvouti_end
1684xp:
1685 lea ETEMP(%a6),%a0
1686 bclrb #sign_bit,LOCAL_EX(%a0)
1687 sne LOCAL_SGN(%a0)
1688 btstb #7,STAG(%a6) |check for extended denorm
1689 bne xdnrm
1690 clrl %d0
1691 bras do_fp |do normal case
1692sgp:
1693 lea ETEMP(%a6),%a0
1694 bclrb #sign_bit,LOCAL_EX(%a0)
1695 sne LOCAL_SGN(%a0)
1696 btstb #7,STAG(%a6) |check for extended denorm
1697 bne sp_catas |branch if so
1698 movew LOCAL_EX(%a0),%d0
1699 lea sp_bnds,%a1
1700 cmpw (%a1),%d0
1701 blt sp_under
1702 cmpw 2(%a1),%d0
1703 bgt sp_over
1704 movel #1,%d0 |set destination format to single
1705 bras do_fp |do normal case
1706dp:
1707 lea ETEMP(%a6),%a0
1708 bclrb #sign_bit,LOCAL_EX(%a0)
1709 sne LOCAL_SGN(%a0)
1710
1711 btstb #7,STAG(%a6) |check for extended denorm
1712 bne dp_catas |branch if so
1713
1714 movew LOCAL_EX(%a0),%d0
1715 lea dp_bnds,%a1
1716
1717 cmpw (%a1),%d0
1718 blt dp_under
1719 cmpw 2(%a1),%d0
1720 bgt dp_over
1721
1722 movel #2,%d0 |set destination format to double
1723| ;fall through to do_fp
1724|
1725do_fp:
1726 bfextu FPCR_MODE(%a6){#2:#2},%d1 |rnd mode in d1
1727 swap %d0 |rnd prec in upper word
1728 addl %d0,%d1 |d1 has PREC/MODE info
1729
1730 clrl %d0 |clear g,r,s
1731
1732 bsrl round |round
1733
1734 movel %a0,%a1
1735 movel EXC_EA(%a6),%a0
1736
1737 bfextu CMDREG1B(%a6){#3:#3},%d1 |extract destination format
1738| ;at this point only the dest
1739| ;formats sgl, dbl, ext are
1740| ;possible
1741 cmpb #2,%d1
1742 bgts ddbl |double=5, extended=2, single=1
1743 bnes dsgl
1744| ;fall through to dext
1745dext:
1746 bsrl dest_ext
1747 bra mvout_end
1748dsgl:
1749 bsrl dest_sgl
1750 bra mvout_end
1751ddbl:
1752 bsrl dest_dbl
1753 bra mvout_end
1754
1755|
1756| Handle possible denorm or catastrophic underflow cases here
1757|
1758xdnrm:
1759 bsr set_xop |initialize WBTEMP
1760 bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
1761
1762 movel %a0,%a1
1763 movel EXC_EA(%a6),%a0 |a0 has the destination pointer
1764 bsrl dest_ext |store to memory
1765 bsetb #unfl_bit,FPSR_EXCEPT(%a6)
1766 bra mvout_end
1767
1768sp_under:
1769 bsetb #etemp15_bit,STAG(%a6)
1770
1771 cmpw 4(%a1),%d0
1772 blts sp_catas |catastrophic underflow case
1773
1774 movel #1,%d0 |load in round precision
1775 movel #sgl_thresh,%d1 |load in single denorm threshold
1776 bsrl dpspdnrm |expects d1 to have the proper
1777| ;denorm threshold
1778 bsrl dest_sgl |stores value to destination
1779 bsetb #unfl_bit,FPSR_EXCEPT(%a6)
1780 bra mvout_end |exit
1781
1782dp_under:
1783 bsetb #etemp15_bit,STAG(%a6)
1784
1785 cmpw 4(%a1),%d0
1786 blts dp_catas |catastrophic underflow case
1787
1788 movel #dbl_thresh,%d1 |load in double precision threshold
1789 movel #2,%d0
1790 bsrl dpspdnrm |expects d1 to have proper
1791| ;denorm threshold
1792| ;expects d0 to have round precision
1793 bsrl dest_dbl |store value to destination
1794 bsetb #unfl_bit,FPSR_EXCEPT(%a6)
1795 bra mvout_end |exit
1796
1797|
1798| Handle catastrophic underflow cases here
1799|
1800sp_catas:
1801| Temp fix for z bit set in unf_sub
1802 movel USER_FPSR(%a6),-(%a7)
1803
1804 movel #1,%d0 |set round precision to sgl
1805
1806 bsrl unf_sub |a0 points to result
1807
1808 movel (%a7)+,USER_FPSR(%a6)
1809
1810 movel #1,%d0
1811 subw %d0,LOCAL_EX(%a0) |account for difference between
1812| ;denorm/norm bias
1813
1814 movel %a0,%a1 |a1 has the operand input
1815 movel EXC_EA(%a6),%a0 |a0 has the destination pointer
1816
1817 bsrl dest_sgl |store the result
1818 oril #unfinx_mask,USER_FPSR(%a6)
1819 bra mvout_end
1820
1821dp_catas:
1822| Temp fix for z bit set in unf_sub
1823 movel USER_FPSR(%a6),-(%a7)
1824
1825 movel #2,%d0 |set round precision to dbl
1826 bsrl unf_sub |a0 points to result
1827
1828 movel (%a7)+,USER_FPSR(%a6)
1829
1830 movel #1,%d0
1831 subw %d0,LOCAL_EX(%a0) |account for difference between
1832| ;denorm/norm bias
1833
1834 movel %a0,%a1 |a1 has the operand input
1835 movel EXC_EA(%a6),%a0 |a0 has the destination pointer
1836
1837 bsrl dest_dbl |store the result
1838 oril #unfinx_mask,USER_FPSR(%a6)
1839 bra mvout_end
1840
1841|
1842| Handle catastrophic overflow cases here
1843|
1844sp_over:
1845| Temp fix for z bit set in unf_sub
1846 movel USER_FPSR(%a6),-(%a7)
1847
1848 movel #1,%d0
1849 leal FP_SCR1(%a6),%a0 |use FP_SCR1 for creating result
1850 movel ETEMP_EX(%a6),(%a0)
1851 movel ETEMP_HI(%a6),4(%a0)
1852 movel ETEMP_LO(%a6),8(%a0)
1853 bsrl ovf_res
1854
1855 movel (%a7)+,USER_FPSR(%a6)
1856
1857 movel %a0,%a1
1858 movel EXC_EA(%a6),%a0
1859 bsrl dest_sgl
1860 orl #ovfinx_mask,USER_FPSR(%a6)
1861 bra mvout_end
1862
1863dp_over:
1864| Temp fix for z bit set in ovf_res
1865 movel USER_FPSR(%a6),-(%a7)
1866
1867 movel #2,%d0
1868 leal FP_SCR1(%a6),%a0 |use FP_SCR1 for creating result
1869 movel ETEMP_EX(%a6),(%a0)
1870 movel ETEMP_HI(%a6),4(%a0)
1871 movel ETEMP_LO(%a6),8(%a0)
1872 bsrl ovf_res
1873
1874 movel (%a7)+,USER_FPSR(%a6)
1875
1876 movel %a0,%a1
1877 movel EXC_EA(%a6),%a0
1878 bsrl dest_dbl
1879 orl #ovfinx_mask,USER_FPSR(%a6)
1880 bra mvout_end
1881
1882|
1883| DPSPDNRM
1884|
1885| This subroutine takes an extended normalized number and denormalizes
1886| it to the given round precision. This subroutine also decrements
1887| the input operand's exponent by 1 to account for the fact that
1888| dest_sgl or dest_dbl expects a normalized number's bias.
1889|
1890| Input: a0 points to a normalized number in internal extended format
1891| d0 is the round precision (=1 for sgl; =2 for dbl)
1892| d1 is the single precision or double precision
1893| denorm threshold
1894|
1895| Output: (In the format for dest_sgl or dest_dbl)
1896| a0 points to the destination
1897| a1 points to the operand
1898|
1899| Exceptions: Reports inexact 2 exception by setting USER_FPSR bits
1900|
1901dpspdnrm:
1902 movel %d0,-(%a7) |save round precision
1903 clrl %d0 |clear initial g,r,s
1904 bsrl dnrm_lp |careful with d0, it's needed by round
1905
1906 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rounding mode
1907 swap %d1
1908 movew 2(%a7),%d1 |set rounding precision
1909 swap %d1 |at this point d1 has PREC/MODE info
1910 bsrl round |round result, sets the inex bit in
1911| ;USER_FPSR if needed
1912
1913 movew #1,%d0
1914 subw %d0,LOCAL_EX(%a0) |account for difference in denorm
1915| ;vs norm bias
1916
1917 movel %a0,%a1 |a1 has the operand input
1918 movel EXC_EA(%a6),%a0 |a0 has the destination pointer
1919 addw #4,%a7 |pop stack
1920 rts
1921|
1922| SET_XOP initialized WBTEMP with the value pointed to by a0
1923| input: a0 points to input operand in the internal extended format
1924|
1925set_xop:
1926 movel LOCAL_EX(%a0),WBTEMP_EX(%a6)
1927 movel LOCAL_HI(%a0),WBTEMP_HI(%a6)
1928 movel LOCAL_LO(%a0),WBTEMP_LO(%a6)
1929 bfclr WBTEMP_SGN(%a6){#0:#8}
1930 beqs sxop
1931 bsetb #sign_bit,WBTEMP_EX(%a6)
1932sxop:
1933 bfclr STAG(%a6){#5:#4} |clear wbtm66,wbtm1,wbtm0,sbit
1934 rts
1935|
1936| P_MOVE
1937|
1938p_movet:
1939 .long p_move
1940 .long p_movez
1941 .long p_movei
1942 .long p_moven
1943 .long p_move
1944p_regd:
1945 .long p_dyd0
1946 .long p_dyd1
1947 .long p_dyd2
1948 .long p_dyd3
1949 .long p_dyd4
1950 .long p_dyd5
1951 .long p_dyd6
1952 .long p_dyd7
1953
1954pack_out:
1955 leal p_movet,%a0 |load jmp table address
1956 movew STAG(%a6),%d0 |get source tag
1957 bfextu %d0{#16:#3},%d0 |isolate source bits
1958 movel (%a0,%d0.w*4),%a0 |load a0 with routine label for tag
1959 jmp (%a0) |go to the routine
1960
1961p_write:
1962 movel #0x0c,%d0 |get byte count
1963 movel EXC_EA(%a6),%a1 |get the destination address
1964 bsr mem_write |write the user's destination
1965 moveb #0,CU_SAVEPC(%a6) |set the cu save pc to all 0's
1966
1967|
1968| Also note that the dtag must be set to norm here - this is because
1969| the 040 uses the dtag to execute the correct microcode.
1970|
1971 bfclr DTAG(%a6){#0:#3} |set dtag to norm
1972
1973 rts
1974
1975| Notes on handling of special case (zero, inf, and nan) inputs:
1976| 1. Operr is not signalled if the k-factor is greater than 18.
1977| 2. Per the manual, status bits are not set.
1978|
1979
1980p_move:
1981 movew CMDREG1B(%a6),%d0
1982 btstl #kfact_bit,%d0 |test for dynamic k-factor
1983 beqs statick |if clear, k-factor is static
1984dynamick:
1985 bfextu %d0{#25:#3},%d0 |isolate register for dynamic k-factor
1986 lea p_regd,%a0
1987 movel %a0@(%d0:l:4),%a0
1988 jmp (%a0)
1989statick:
1990 andiw #0x007f,%d0 |get k-factor
1991 bfexts %d0{#25:#7},%d0 |sign extend d0 for bindec
1992 leal ETEMP(%a6),%a0 |a0 will point to the packed decimal
1993 bsrl bindec |perform the convert; data at a6
1994 leal FP_SCR1(%a6),%a0 |load a0 with result address
1995 bral p_write
1996p_movez:
1997 leal ETEMP(%a6),%a0 |a0 will point to the packed decimal
1998 clrw 2(%a0) |clear lower word of exp
1999 clrl 4(%a0) |load second lword of ZERO
2000 clrl 8(%a0) |load third lword of ZERO
2001 bra p_write |go write results
2002p_movei:
2003 fmovel #0,%FPSR |clear aiop
2004 leal ETEMP(%a6),%a0 |a0 will point to the packed decimal
2005 clrw 2(%a0) |clear lower word of exp
2006 bra p_write |go write the result
2007p_moven:
2008 leal ETEMP(%a6),%a0 |a0 will point to the packed decimal
2009 clrw 2(%a0) |clear lower word of exp
2010 bra p_write |go write the result
2011
2012|
2013| Routines to read the dynamic k-factor from Dn.
2014|
2015p_dyd0:
2016 movel USER_D0(%a6),%d0
2017 bras statick
2018p_dyd1:
2019 movel USER_D1(%a6),%d0
2020 bras statick
2021p_dyd2:
2022 movel %d2,%d0
2023 bras statick
2024p_dyd3:
2025 movel %d3,%d0
2026 bras statick
2027p_dyd4:
2028 movel %d4,%d0
2029 bras statick
2030p_dyd5:
2031 movel %d5,%d0
2032 bras statick
2033p_dyd6:
2034 movel %d6,%d0
2035 bra statick
2036p_dyd7:
2037 movel %d7,%d0
2038 bra statick
2039
2040 |end
diff --git a/arch/m68k/fpsp040/round.S b/arch/m68k/fpsp040/round.S
new file mode 100644
index 000000000000..00f98068783f
--- /dev/null
+++ b/arch/m68k/fpsp040/round.S
@@ -0,0 +1,649 @@
1|
2| round.sa 3.4 7/29/91
3|
4| handle rounding and normalization tasks
5|
6|
7|
8| Copyright (C) Motorola, Inc. 1990
9| All Rights Reserved
10|
11| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
12| The copyright notice above does not evidence any
13| actual or intended publication of such source code.
14
15|ROUND idnt 2,1 | Motorola 040 Floating Point Software Package
16
17 |section 8
18
19#include "fpsp.h"
20
21|
22| round --- round result according to precision/mode
23|
24| a0 points to the input operand in the internal extended format
25| d1(high word) contains rounding precision:
26| ext = $0000xxxx
27| sgl = $0001xxxx
28| dbl = $0002xxxx
29| d1(low word) contains rounding mode:
30| RN = $xxxx0000
31| RZ = $xxxx0001
32| RM = $xxxx0010
33| RP = $xxxx0011
34| d0{31:29} contains the g,r,s bits (extended)
35|
36| On return the value pointed to by a0 is correctly rounded,
37| a0 is preserved and the g-r-s bits in d0 are cleared.
38| The result is not typed - the tag field is invalid. The
39| result is still in the internal extended format.
40|
41| The INEX bit of USER_FPSR will be set if the rounded result was
42| inexact (i.e. if any of the g-r-s bits were set).
43|
44
45 .global round
46round:
47| If g=r=s=0 then result is exact and round is done, else set
48| the inex flag in status reg and continue.
49|
50 bsrs ext_grs |this subroutine looks at the
51| :rounding precision and sets
52| ;the appropriate g-r-s bits.
53 tstl %d0 |if grs are zero, go force
54 bne rnd_cont |lower bits to zero for size
55
56 swap %d1 |set up d1.w for round prec.
57 bra truncate
58
59rnd_cont:
60|
61| Use rounding mode as an index into a jump table for these modes.
62|
63 orl #inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
64 lea mode_tab,%a1
65 movel (%a1,%d1.w*4),%a1
66 jmp (%a1)
67|
68| Jump table indexed by rounding mode in d1.w. All following assumes
69| grs != 0.
70|
71mode_tab:
72 .long rnd_near
73 .long rnd_zero
74 .long rnd_mnus
75 .long rnd_plus
76|
77| ROUND PLUS INFINITY
78|
79| If sign of fp number = 0 (positive), then add 1 to l.
80|
81rnd_plus:
82 swap %d1 |set up d1 for round prec.
83 tstb LOCAL_SGN(%a0) |check for sign
84 bmi truncate |if positive then truncate
85 movel #0xffffffff,%d0 |force g,r,s to be all f's
86 lea add_to_l,%a1
87 movel (%a1,%d1.w*4),%a1
88 jmp (%a1)
89|
90| ROUND MINUS INFINITY
91|
92| If sign of fp number = 1 (negative), then add 1 to l.
93|
94rnd_mnus:
95 swap %d1 |set up d1 for round prec.
96 tstb LOCAL_SGN(%a0) |check for sign
97 bpl truncate |if negative then truncate
98 movel #0xffffffff,%d0 |force g,r,s to be all f's
99 lea add_to_l,%a1
100 movel (%a1,%d1.w*4),%a1
101 jmp (%a1)
102|
103| ROUND ZERO
104|
105| Always truncate.
106rnd_zero:
107 swap %d1 |set up d1 for round prec.
108 bra truncate
109|
110|
111| ROUND NEAREST
112|
113| If (g=1), then add 1 to l and if (r=s=0), then clear l
114| Note that this will round to even in case of a tie.
115|
116rnd_near:
117 swap %d1 |set up d1 for round prec.
118 asll #1,%d0 |shift g-bit to c-bit
119 bcc truncate |if (g=1) then
120 lea add_to_l,%a1
121 movel (%a1,%d1.w*4),%a1
122 jmp (%a1)
123
124|
125| ext_grs --- extract guard, round and sticky bits
126|
127| Input: d1 = PREC:ROUND
128| Output: d0{31:29}= guard, round, sticky
129|
130| The ext_grs extract the guard/round/sticky bits according to the
131| selected rounding precision. It is called by the round subroutine
132| only. All registers except d0 are kept intact. d0 becomes an
133| updated guard,round,sticky in d0{31:29}
134|
135| Notes: the ext_grs uses the round PREC, and therefore has to swap d1
136| prior to usage, and needs to restore d1 to original.
137|
138ext_grs:
139 swap %d1 |have d1.w point to round precision
140 cmpiw #0,%d1
141 bnes sgl_or_dbl
142 bras end_ext_grs
143
144sgl_or_dbl:
145 moveml %d2/%d3,-(%a7) |make some temp registers
146 cmpiw #1,%d1
147 bnes grs_dbl
148grs_sgl:
149 bfextu LOCAL_HI(%a0){#24:#2},%d3 |sgl prec. g-r are 2 bits right
150 movel #30,%d2 |of the sgl prec. limits
151 lsll %d2,%d3 |shift g-r bits to MSB of d3
152 movel LOCAL_HI(%a0),%d2 |get word 2 for s-bit test
153 andil #0x0000003f,%d2 |s bit is the or of all other
154 bnes st_stky |bits to the right of g-r
155 tstl LOCAL_LO(%a0) |test lower mantissa
156 bnes st_stky |if any are set, set sticky
157 tstl %d0 |test original g,r,s
158 bnes st_stky |if any are set, set sticky
159 bras end_sd |if words 3 and 4 are clr, exit
160grs_dbl:
161 bfextu LOCAL_LO(%a0){#21:#2},%d3 |dbl-prec. g-r are 2 bits right
162 movel #30,%d2 |of the dbl prec. limits
163 lsll %d2,%d3 |shift g-r bits to the MSB of d3
164 movel LOCAL_LO(%a0),%d2 |get lower mantissa for s-bit test
165 andil #0x000001ff,%d2 |s bit is the or-ing of all
166 bnes st_stky |other bits to the right of g-r
167 tstl %d0 |test word original g,r,s
168 bnes st_stky |if any are set, set sticky
169 bras end_sd |if clear, exit
170st_stky:
171 bset #rnd_stky_bit,%d3
172end_sd:
173 movel %d3,%d0 |return grs to d0
174 moveml (%a7)+,%d2/%d3 |restore scratch registers
175end_ext_grs:
176 swap %d1 |restore d1 to original
177 rts
178
179|******************* Local Equates
180 .set ad_1_sgl,0x00000100 | constant to add 1 to l-bit in sgl prec
181 .set ad_1_dbl,0x00000800 | constant to add 1 to l-bit in dbl prec
182
183
184|Jump table for adding 1 to the l-bit indexed by rnd prec
185
186add_to_l:
187 .long add_ext
188 .long add_sgl
189 .long add_dbl
190 .long add_dbl
191|
192| ADD SINGLE
193|
194add_sgl:
195 addl #ad_1_sgl,LOCAL_HI(%a0)
196 bccs scc_clr |no mantissa overflow
197 roxrw LOCAL_HI(%a0) |shift v-bit back in
198 roxrw LOCAL_HI+2(%a0) |shift v-bit back in
199 addw #0x1,LOCAL_EX(%a0) |and incr exponent
200scc_clr:
201 tstl %d0 |test for rs = 0
202 bnes sgl_done
203 andiw #0xfe00,LOCAL_HI+2(%a0) |clear the l-bit
204sgl_done:
205 andil #0xffffff00,LOCAL_HI(%a0) |truncate bits beyond sgl limit
206 clrl LOCAL_LO(%a0) |clear d2
207 rts
208
209|
210| ADD EXTENDED
211|
212add_ext:
213 addql #1,LOCAL_LO(%a0) |add 1 to l-bit
214 bccs xcc_clr |test for carry out
215 addql #1,LOCAL_HI(%a0) |propagate carry
216 bccs xcc_clr
217 roxrw LOCAL_HI(%a0) |mant is 0 so restore v-bit
218 roxrw LOCAL_HI+2(%a0) |mant is 0 so restore v-bit
219 roxrw LOCAL_LO(%a0)
220 roxrw LOCAL_LO+2(%a0)
221 addw #0x1,LOCAL_EX(%a0) |and inc exp
222xcc_clr:
223 tstl %d0 |test rs = 0
224 bnes add_ext_done
225 andib #0xfe,LOCAL_LO+3(%a0) |clear the l bit
226add_ext_done:
227 rts
228|
229| ADD DOUBLE
230|
231add_dbl:
232 addl #ad_1_dbl,LOCAL_LO(%a0)
233 bccs dcc_clr
234 addql #1,LOCAL_HI(%a0) |propagate carry
235 bccs dcc_clr
236 roxrw LOCAL_HI(%a0) |mant is 0 so restore v-bit
237 roxrw LOCAL_HI+2(%a0) |mant is 0 so restore v-bit
238 roxrw LOCAL_LO(%a0)
239 roxrw LOCAL_LO+2(%a0)
240 addw #0x1,LOCAL_EX(%a0) |incr exponent
241dcc_clr:
242 tstl %d0 |test for rs = 0
243 bnes dbl_done
244 andiw #0xf000,LOCAL_LO+2(%a0) |clear the l-bit
245
246dbl_done:
247 andil #0xfffff800,LOCAL_LO(%a0) |truncate bits beyond dbl limit
248 rts
249
250error:
251 rts
252|
253| Truncate all other bits
254|
255trunct:
256 .long end_rnd
257 .long sgl_done
258 .long dbl_done
259 .long dbl_done
260
261truncate:
262 lea trunct,%a1
263 movel (%a1,%d1.w*4),%a1
264 jmp (%a1)
265
266end_rnd:
267 rts
268
269|
270| NORMALIZE
271|
272| These routines (nrm_zero & nrm_set) normalize the unnorm. This
273| is done by shifting the mantissa left while decrementing the
274| exponent.
275|
276| NRM_SET shifts and decrements until there is a 1 set in the integer
277| bit of the mantissa (msb in d1).
278|
279| NRM_ZERO shifts and decrements until there is a 1 set in the integer
280| bit of the mantissa (msb in d1) unless this would mean the exponent
281| would go less than 0. In that case the number becomes a denorm - the
282| exponent (d0) is set to 0 and the mantissa (d1 & d2) is not
283| normalized.
284|
285| Note that both routines have been optimized (for the worst case) and
286| therefore do not have the easy to follow decrement/shift loop.
287|
288| NRM_ZERO
289|
290| Distance to first 1 bit in mantissa = X
291| Distance to 0 from exponent = Y
292| If X < Y
293| Then
294| nrm_set
295| Else
296| shift mantissa by Y
297| set exponent = 0
298|
299|input:
300| FP_SCR1 = exponent, ms mantissa part, ls mantissa part
301|output:
302| L_SCR1{4} = fpte15 or ete15 bit
303|
304 .global nrm_zero
305nrm_zero:
306 movew LOCAL_EX(%a0),%d0
307 cmpw #64,%d0 |see if exp > 64
308 bmis d0_less
309 bsr nrm_set |exp > 64 so exp won't exceed 0
310 rts
311d0_less:
312 moveml %d2/%d3/%d5/%d6,-(%a7)
313 movel LOCAL_HI(%a0),%d1
314 movel LOCAL_LO(%a0),%d2
315
316 bfffo %d1{#0:#32},%d3 |get the distance to the first 1
317| ;in ms mant
318 beqs ms_clr |branch if no bits were set
319 cmpw %d3,%d0 |of X>Y
320 bmis greater |then exp will go past 0 (neg) if
321| ;it is just shifted
322 bsr nrm_set |else exp won't go past 0
323 moveml (%a7)+,%d2/%d3/%d5/%d6
324 rts
325greater:
326 movel %d2,%d6 |save ls mant in d6
327 lsll %d0,%d2 |shift ls mant by count
328 lsll %d0,%d1 |shift ms mant by count
329 movel #32,%d5
330 subl %d0,%d5 |make op a denorm by shifting bits
331 lsrl %d5,%d6 |by the number in the exp, then
332| ;set exp = 0.
333 orl %d6,%d1 |shift the ls mant bits into the ms mant
334 movel #0,%d0 |same as if decremented exp to 0
335| ;while shifting
336 movew %d0,LOCAL_EX(%a0)
337 movel %d1,LOCAL_HI(%a0)
338 movel %d2,LOCAL_LO(%a0)
339 moveml (%a7)+,%d2/%d3/%d5/%d6
340 rts
341ms_clr:
342 bfffo %d2{#0:#32},%d3 |check if any bits set in ls mant
343 beqs all_clr |branch if none set
344 addw #32,%d3
345 cmpw %d3,%d0 |if X>Y
346 bmis greater |then branch
347 bsr nrm_set |else exp won't go past 0
348 moveml (%a7)+,%d2/%d3/%d5/%d6
349 rts
350all_clr:
351 movew #0,LOCAL_EX(%a0) |no mantissa bits set. Set exp = 0.
352 moveml (%a7)+,%d2/%d3/%d5/%d6
353 rts
354|
355| NRM_SET
356|
357 .global nrm_set
358nrm_set:
359 movel %d7,-(%a7)
360 bfffo LOCAL_HI(%a0){#0:#32},%d7 |find first 1 in ms mant to d7)
361 beqs lower |branch if ms mant is all 0's
362
363 movel %d6,-(%a7)
364
365 subw %d7,LOCAL_EX(%a0) |sub exponent by count
366 movel LOCAL_HI(%a0),%d0 |d0 has ms mant
367 movel LOCAL_LO(%a0),%d1 |d1 has ls mant
368
369 lsll %d7,%d0 |shift first 1 to j bit position
370 movel %d1,%d6 |copy ls mant into d6
371 lsll %d7,%d6 |shift ls mant by count
372 movel %d6,LOCAL_LO(%a0) |store ls mant into memory
373 moveql #32,%d6
374 subl %d7,%d6 |continue shift
375 lsrl %d6,%d1 |shift off all bits but those that will
376| ;be shifted into ms mant
377 orl %d1,%d0 |shift the ls mant bits into the ms mant
378 movel %d0,LOCAL_HI(%a0) |store ms mant into memory
379 moveml (%a7)+,%d7/%d6 |restore registers
380 rts
381
382|
383| We get here if ms mant was = 0, and we assume ls mant has bits
384| set (otherwise this would have been tagged a zero not a denorm).
385|
386lower:
387 movew LOCAL_EX(%a0),%d0 |d0 has exponent
388 movel LOCAL_LO(%a0),%d1 |d1 has ls mant
389 subw #32,%d0 |account for ms mant being all zeros
390 bfffo %d1{#0:#32},%d7 |find first 1 in ls mant to d7)
391 subw %d7,%d0 |subtract shift count from exp
392 lsll %d7,%d1 |shift first 1 to integer bit in ms mant
393 movew %d0,LOCAL_EX(%a0) |store ms mant
394 movel %d1,LOCAL_HI(%a0) |store exp
395 clrl LOCAL_LO(%a0) |clear ls mant
396 movel (%a7)+,%d7
397 rts
398|
399| denorm --- denormalize an intermediate result
400|
401| Used by underflow.
402|
403| Input:
404| a0 points to the operand to be denormalized
405| (in the internal extended format)
406|
407| d0: rounding precision
408| Output:
409| a0 points to the denormalized result
410| (in the internal extended format)
411|
412| d0 is guard,round,sticky
413|
414| d0 comes into this routine with the rounding precision. It
415| is then loaded with the denormalized exponent threshold for the
416| rounding precision.
417|
418
419 .global denorm
420denorm:
421 btstb #6,LOCAL_EX(%a0) |check for exponents between $7fff-$4000
422 beqs no_sgn_ext
423 bsetb #7,LOCAL_EX(%a0) |sign extend if it is so
424no_sgn_ext:
425
426 cmpib #0,%d0 |if 0 then extended precision
427 bnes not_ext |else branch
428
429 clrl %d1 |load d1 with ext threshold
430 clrl %d0 |clear the sticky flag
431 bsr dnrm_lp |denormalize the number
432 tstb %d1 |check for inex
433 beq no_inex |if clr, no inex
434 bras dnrm_inex |if set, set inex
435
436not_ext:
437 cmpil #1,%d0 |if 1 then single precision
438 beqs load_sgl |else must be 2, double prec
439
440load_dbl:
441 movew #dbl_thresh,%d1 |put copy of threshold in d1
442 movel %d1,%d0 |copy d1 into d0
443 subw LOCAL_EX(%a0),%d0 |diff = threshold - exp
444 cmpw #67,%d0 |if diff > 67 (mant + grs bits)
445 bpls chk_stky |then branch (all bits would be
446| ; shifted off in denorm routine)
447 clrl %d0 |else clear the sticky flag
448 bsr dnrm_lp |denormalize the number
449 tstb %d1 |check flag
450 beqs no_inex |if clr, no inex
451 bras dnrm_inex |if set, set inex
452
453load_sgl:
454 movew #sgl_thresh,%d1 |put copy of threshold in d1
455 movel %d1,%d0 |copy d1 into d0
456 subw LOCAL_EX(%a0),%d0 |diff = threshold - exp
457 cmpw #67,%d0 |if diff > 67 (mant + grs bits)
458 bpls chk_stky |then branch (all bits would be
459| ; shifted off in denorm routine)
460 clrl %d0 |else clear the sticky flag
461 bsr dnrm_lp |denormalize the number
462 tstb %d1 |check flag
463 beqs no_inex |if clr, no inex
464 bras dnrm_inex |if set, set inex
465
466chk_stky:
467 tstl LOCAL_HI(%a0) |check for any bits set
468 bnes set_stky
469 tstl LOCAL_LO(%a0) |check for any bits set
470 bnes set_stky
471 bras clr_mant
472set_stky:
473 orl #inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
474 movel #0x20000000,%d0 |set sticky bit in return value
475clr_mant:
476 movew %d1,LOCAL_EX(%a0) |load exp with threshold
477 movel #0,LOCAL_HI(%a0) |set d1 = 0 (ms mantissa)
478 movel #0,LOCAL_LO(%a0) |set d2 = 0 (ms mantissa)
479 rts
480dnrm_inex:
481 orl #inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
482no_inex:
483 rts
484
485|
486| dnrm_lp --- normalize exponent/mantissa to specified threshold
487|
488| Input:
489| a0 points to the operand to be denormalized
490| d0{31:29} initial guard,round,sticky
491| d1{15:0} denormalization threshold
492| Output:
493| a0 points to the denormalized operand
494| d0{31:29} final guard,round,sticky
495| d1.b inexact flag: all ones means inexact result
496|
497| The LOCAL_LO and LOCAL_GRS parts of the value are copied to FP_SCR2
498| so that bfext can be used to extract the new low part of the mantissa.
499| Dnrm_lp can be called with a0 pointing to ETEMP or WBTEMP and there
500| is no LOCAL_GRS scratch word following it on the fsave frame.
501|
502 .global dnrm_lp
503dnrm_lp:
504 movel %d2,-(%sp) |save d2 for temp use
505 btstb #E3,E_BYTE(%a6) |test for type E3 exception
506 beqs not_E3 |not type E3 exception
507 bfextu WBTEMP_GRS(%a6){#6:#3},%d2 |extract guard,round, sticky bit
508 movel #29,%d0
509 lsll %d0,%d2 |shift g,r,s to their positions
510 movel %d2,%d0
511not_E3:
512 movel (%sp)+,%d2 |restore d2
513 movel LOCAL_LO(%a0),FP_SCR2+LOCAL_LO(%a6)
514 movel %d0,FP_SCR2+LOCAL_GRS(%a6)
515 movel %d1,%d0 |copy the denorm threshold
516 subw LOCAL_EX(%a0),%d1 |d1 = threshold - uns exponent
517 bles no_lp |d1 <= 0
518 cmpw #32,%d1
519 blts case_1 |0 = d1 < 32
520 cmpw #64,%d1
521 blts case_2 |32 <= d1 < 64
522 bra case_3 |d1 >= 64
523|
524| No normalization necessary
525|
526no_lp:
527 clrb %d1 |set no inex2 reported
528 movel FP_SCR2+LOCAL_GRS(%a6),%d0 |restore original g,r,s
529 rts
530|
531| case (0<d1<32)
532|
533case_1:
534 movel %d2,-(%sp)
535 movew %d0,LOCAL_EX(%a0) |exponent = denorm threshold
536 movel #32,%d0
537 subw %d1,%d0 |d0 = 32 - d1
538 bfextu LOCAL_EX(%a0){%d0:#32},%d2
539 bfextu %d2{%d1:%d0},%d2 |d2 = new LOCAL_HI
540 bfextu LOCAL_HI(%a0){%d0:#32},%d1 |d1 = new LOCAL_LO
541 bfextu FP_SCR2+LOCAL_LO(%a6){%d0:#32},%d0 |d0 = new G,R,S
542 movel %d2,LOCAL_HI(%a0) |store new LOCAL_HI
543 movel %d1,LOCAL_LO(%a0) |store new LOCAL_LO
544 clrb %d1
545 bftst %d0{#2:#30}
546 beqs c1nstky
547 bsetl #rnd_stky_bit,%d0
548 st %d1
549c1nstky:
550 movel FP_SCR2+LOCAL_GRS(%a6),%d2 |restore original g,r,s
551 andil #0xe0000000,%d2 |clear all but G,R,S
552 tstl %d2 |test if original G,R,S are clear
553 beqs grs_clear
554 orl #0x20000000,%d0 |set sticky bit in d0
555grs_clear:
556 andil #0xe0000000,%d0 |clear all but G,R,S
557 movel (%sp)+,%d2
558 rts
559|
560| case (32<=d1<64)
561|
562case_2:
563 movel %d2,-(%sp)
564 movew %d0,LOCAL_EX(%a0) |unsigned exponent = threshold
565 subw #32,%d1 |d1 now between 0 and 32
566 movel #32,%d0
567 subw %d1,%d0 |d0 = 32 - d1
568 bfextu LOCAL_EX(%a0){%d0:#32},%d2
569 bfextu %d2{%d1:%d0},%d2 |d2 = new LOCAL_LO
570 bfextu LOCAL_HI(%a0){%d0:#32},%d1 |d1 = new G,R,S
571 bftst %d1{#2:#30}
572 bnes c2_sstky |bra if sticky bit to be set
573 bftst FP_SCR2+LOCAL_LO(%a6){%d0:#32}
574 bnes c2_sstky |bra if sticky bit to be set
575 movel %d1,%d0
576 clrb %d1
577 bras end_c2
578c2_sstky:
579 movel %d1,%d0
580 bsetl #rnd_stky_bit,%d0
581 st %d1
582end_c2:
583 clrl LOCAL_HI(%a0) |store LOCAL_HI = 0
584 movel %d2,LOCAL_LO(%a0) |store LOCAL_LO
585 movel FP_SCR2+LOCAL_GRS(%a6),%d2 |restore original g,r,s
586 andil #0xe0000000,%d2 |clear all but G,R,S
587 tstl %d2 |test if original G,R,S are clear
588 beqs clear_grs
589 orl #0x20000000,%d0 |set sticky bit in d0
590clear_grs:
591 andil #0xe0000000,%d0 |get rid of all but G,R,S
592 movel (%sp)+,%d2
593 rts
594|
595| d1 >= 64 Force the exponent to be the denorm threshold with the
596| correct sign.
597|
598case_3:
599 movew %d0,LOCAL_EX(%a0)
600 tstw LOCAL_SGN(%a0)
601 bges c3con
602c3neg:
603 orl #0x80000000,LOCAL_EX(%a0)
604c3con:
605 cmpw #64,%d1
606 beqs sixty_four
607 cmpw #65,%d1
608 beqs sixty_five
609|
610| Shift value is out of range. Set d1 for inex2 flag and
611| return a zero with the given threshold.
612|
613 clrl LOCAL_HI(%a0)
614 clrl LOCAL_LO(%a0)
615 movel #0x20000000,%d0
616 st %d1
617 rts
618
619sixty_four:
620 movel LOCAL_HI(%a0),%d0
621 bfextu %d0{#2:#30},%d1
622 andil #0xc0000000,%d0
623 bras c3com
624
625sixty_five:
626 movel LOCAL_HI(%a0),%d0
627 bfextu %d0{#1:#31},%d1
628 andil #0x80000000,%d0
629 lsrl #1,%d0 |shift high bit into R bit
630
631c3com:
632 tstl %d1
633 bnes c3ssticky
634 tstl LOCAL_LO(%a0)
635 bnes c3ssticky
636 tstb FP_SCR2+LOCAL_GRS(%a6)
637 bnes c3ssticky
638 clrb %d1
639 bras c3end
640
641c3ssticky:
642 bsetl #rnd_stky_bit,%d0
643 st %d1
644c3end:
645 clrl LOCAL_HI(%a0)
646 clrl LOCAL_LO(%a0)
647 rts
648
649 |end
diff --git a/arch/m68k/fpsp040/sacos.S b/arch/m68k/fpsp040/sacos.S
new file mode 100644
index 000000000000..83b00ab1c48f
--- /dev/null
+++ b/arch/m68k/fpsp040/sacos.S
@@ -0,0 +1,115 @@
1|
2| sacos.sa 3.3 12/19/90
3|
4| Description: The entry point sAcos computes the inverse cosine of
5| an input argument; sAcosd does the same except for denormalized
6| input.
7|
8| Input: Double-extended number X in location pointed to
9| by address register a0.
10|
11| Output: The value arccos(X) returned in floating-point register Fp0.
12|
13| Accuracy and Monotonicity: The returned result is within 3 ulps in
14| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
15| result is subsequently rounded to double precision. The
16| result is provably monotonic in double precision.
17|
18| Speed: The program sCOS takes approximately 310 cycles.
19|
20| Algorithm:
21|
22| ACOS
23| 1. If |X| >= 1, go to 3.
24|
25| 2. (|X| < 1) Calculate acos(X) by
26| z := (1-X) / (1+X)
27| acos(X) = 2 * atan( sqrt(z) ).
28| Exit.
29|
30| 3. If |X| > 1, go to 5.
31|
32| 4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit.
33|
34| 5. (|X| > 1) Generate an invalid operation by 0 * infinity.
35| Exit.
36|
37
38| Copyright (C) Motorola, Inc. 1990
39| All Rights Reserved
40|
41| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
42| The copyright notice above does not evidence any
43| actual or intended publication of such source code.
44
45|SACOS idnt 2,1 | Motorola 040 Floating Point Software Package
46
47 |section 8
48
49PI: .long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
50PIBY2: .long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
51
52 |xref t_operr
53 |xref t_frcinx
54 |xref satan
55
56 .global sacosd
57sacosd:
58|--ACOS(X) = PI/2 FOR DENORMALIZED X
59 fmovel %d1,%fpcr | ...load user's rounding mode/precision
60 fmovex PIBY2,%fp0
61 bra t_frcinx
62
63 .global sacos
64sacos:
65 fmovex (%a0),%fp0 | ...LOAD INPUT
66
67 movel (%a0),%d0 | ...pack exponent with upper 16 fraction
68 movew 4(%a0),%d0
69 andil #0x7FFFFFFF,%d0
70 cmpil #0x3FFF8000,%d0
71 bges ACOSBIG
72
73|--THIS IS THE USUAL CASE, |X| < 1
74|--ACOS(X) = 2 * ATAN( SQRT( (1-X)/(1+X) ) )
75
76 fmoves #0x3F800000,%fp1
77 faddx %fp0,%fp1 | ...1+X
78 fnegx %fp0 | ... -X
79 fadds #0x3F800000,%fp0 | ...1-X
80 fdivx %fp1,%fp0 | ...(1-X)/(1+X)
81 fsqrtx %fp0 | ...SQRT((1-X)/(1+X))
82 fmovemx %fp0-%fp0,(%a0) | ...overwrite input
83 movel %d1,-(%sp) |save original users fpcr
84 clrl %d1
85 bsr satan | ...ATAN(SQRT([1-X]/[1+X]))
86 fmovel (%sp)+,%fpcr |restore users exceptions
87 faddx %fp0,%fp0 | ...2 * ATAN( STUFF )
88 bra t_frcinx
89
90ACOSBIG:
91 fabsx %fp0
92 fcmps #0x3F800000,%fp0
93 fbgt t_operr |cause an operr exception
94
95|--|X| = 1, ACOS(X) = 0 OR PI
96 movel (%a0),%d0 | ...pack exponent with upper 16 fraction
97 movew 4(%a0),%d0
98 cmpl #0,%d0 |D0 has original exponent+fraction
99 bgts ACOSP1
100
101|--X = -1
102|Returns PI and inexact exception
103 fmovex PI,%fp0
104 fmovel %d1,%FPCR
105 fadds #0x00800000,%fp0 |cause an inexact exception to be put
106| ;into the 040 - will not trap until next
107| ;fp inst.
108 bra t_frcinx
109
110ACOSP1:
111 fmovel %d1,%FPCR
112 fmoves #0x00000000,%fp0
113 rts |Facos ; of +1 is exact
114
115 |end
diff --git a/arch/m68k/fpsp040/sasin.S b/arch/m68k/fpsp040/sasin.S
new file mode 100644
index 000000000000..5647a6043903
--- /dev/null
+++ b/arch/m68k/fpsp040/sasin.S
@@ -0,0 +1,104 @@
1|
2| sasin.sa 3.3 12/19/90
3|
4| Description: The entry point sAsin computes the inverse sine of
5| an input argument; sAsind does the same except for denormalized
6| input.
7|
8| Input: Double-extended number X in location pointed to
9| by address register a0.
10|
11| Output: The value arcsin(X) returned in floating-point register Fp0.
12|
13| Accuracy and Monotonicity: The returned result is within 3 ulps in
14| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
15| result is subsequently rounded to double precision. The
16| result is provably monotonic in double precision.
17|
18| Speed: The program sASIN takes approximately 310 cycles.
19|
20| Algorithm:
21|
22| ASIN
23| 1. If |X| >= 1, go to 3.
24|
25| 2. (|X| < 1) Calculate asin(X) by
26| z := sqrt( [1-X][1+X] )
27| asin(X) = atan( x / z ).
28| Exit.
29|
30| 3. If |X| > 1, go to 5.
31|
32| 4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.
33|
34| 5. (|X| > 1) Generate an invalid operation by 0 * infinity.
35| Exit.
36|
37
38| Copyright (C) Motorola, Inc. 1990
39| All Rights Reserved
40|
41| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
42| The copyright notice above does not evidence any
43| actual or intended publication of such source code.
44
45|SASIN idnt 2,1 | Motorola 040 Floating Point Software Package
46
47 |section 8
48
49PIBY2: .long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
50
51 |xref t_operr
52 |xref t_frcinx
53 |xref t_extdnrm
54 |xref satan
55
56 .global sasind
57sasind:
58|--ASIN(X) = X FOR DENORMALIZED X
59
60 bra t_extdnrm
61
62 .global sasin
63sasin:
64 fmovex (%a0),%fp0 | ...LOAD INPUT
65
66 movel (%a0),%d0
67 movew 4(%a0),%d0
68 andil #0x7FFFFFFF,%d0
69 cmpil #0x3FFF8000,%d0
70 bges asinbig
71
72|--THIS IS THE USUAL CASE, |X| < 1
73|--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
74
75 fmoves #0x3F800000,%fp1
76 fsubx %fp0,%fp1 | ...1-X
77 fmovemx %fp2-%fp2,-(%a7)
78 fmoves #0x3F800000,%fp2
79 faddx %fp0,%fp2 | ...1+X
80 fmulx %fp2,%fp1 | ...(1+X)(1-X)
81 fmovemx (%a7)+,%fp2-%fp2
82 fsqrtx %fp1 | ...SQRT([1-X][1+X])
83 fdivx %fp1,%fp0 | ...X/SQRT([1-X][1+X])
84 fmovemx %fp0-%fp0,(%a0)
85 bsr satan
86 bra t_frcinx
87
88asinbig:
89 fabsx %fp0 | ...|X|
90 fcmps #0x3F800000,%fp0
91 fbgt t_operr |cause an operr exception
92
93|--|X| = 1, ASIN(X) = +- PI/2.
94
95 fmovex PIBY2,%fp0
96 movel (%a0),%d0
97 andil #0x80000000,%d0 | ...SIGN BIT OF X
98 oril #0x3F800000,%d0 | ...+-1 IN SGL FORMAT
99 movel %d0,-(%sp) | ...push SIGN(X) IN SGL-FMT
100 fmovel %d1,%FPCR
101 fmuls (%sp)+,%fp0
102 bra t_frcinx
103
104 |end
diff --git a/arch/m68k/fpsp040/satan.S b/arch/m68k/fpsp040/satan.S
new file mode 100644
index 000000000000..20dae222d51e
--- /dev/null
+++ b/arch/m68k/fpsp040/satan.S
@@ -0,0 +1,478 @@
1|
2| satan.sa 3.3 12/19/90
3|
4| The entry point satan computes the arctangent of an
5| input value. satand does the same except the input value is a
6| denormalized number.
7|
8| Input: Double-extended value in memory location pointed to by address
9| register a0.
10|
11| Output: Arctan(X) returned in floating-point register Fp0.
12|
13| Accuracy and Monotonicity: The returned result is within 2 ulps in
14| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
15| result is subsequently rounded to double precision. The
16| result is provably monotonic in double precision.
17|
18| Speed: The program satan takes approximately 160 cycles for input
19| argument X such that 1/16 < |X| < 16. For the other arguments,
20| the program will run no worse than 10% slower.
21|
22| Algorithm:
23| Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5.
24|
25| Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x. Note that k = -4, -3,..., or 3.
26| Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5 significant bits
27| of X with a bit-1 attached at the 6-th bit position. Define u
28| to be u = (X-F) / (1 + X*F).
29|
30| Step 3. Approximate arctan(u) by a polynomial poly.
31|
32| Step 4. Return arctan(F) + poly, arctan(F) is fetched from a table of values
33| calculated beforehand. Exit.
34|
35| Step 5. If |X| >= 16, go to Step 7.
36|
37| Step 6. Approximate arctan(X) by an odd polynomial in X. Exit.
38|
39| Step 7. Define X' = -1/X. Approximate arctan(X') by an odd polynomial in X'.
40| Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit.
41|
42
43| Copyright (C) Motorola, Inc. 1990
44| All Rights Reserved
45|
46| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
47| The copyright notice above does not evidence any
48| actual or intended publication of such source code.
49
50|satan idnt 2,1 | Motorola 040 Floating Point Software Package
51
52 |section 8
53
54#include "fpsp.h"
55
56BOUNDS1: .long 0x3FFB8000,0x4002FFFF
57
58ONE: .long 0x3F800000
59
60 .long 0x00000000
61
62ATANA3: .long 0xBFF6687E,0x314987D8
63ATANA2: .long 0x4002AC69,0x34A26DB3
64
65ATANA1: .long 0xBFC2476F,0x4E1DA28E
66ATANB6: .long 0x3FB34444,0x7F876989
67
68ATANB5: .long 0xBFB744EE,0x7FAF45DB
69ATANB4: .long 0x3FBC71C6,0x46940220
70
71ATANB3: .long 0xBFC24924,0x921872F9
72ATANB2: .long 0x3FC99999,0x99998FA9
73
74ATANB1: .long 0xBFD55555,0x55555555
75ATANC5: .long 0xBFB70BF3,0x98539E6A
76
77ATANC4: .long 0x3FBC7187,0x962D1D7D
78ATANC3: .long 0xBFC24924,0x827107B8
79
80ATANC2: .long 0x3FC99999,0x9996263E
81ATANC1: .long 0xBFD55555,0x55555536
82
83PPIBY2: .long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
84NPIBY2: .long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
85PTINY: .long 0x00010000,0x80000000,0x00000000,0x00000000
86NTINY: .long 0x80010000,0x80000000,0x00000000,0x00000000
87
88ATANTBL:
89 .long 0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
90 .long 0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
91 .long 0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
92 .long 0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
93 .long 0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
94 .long 0x3FFB0000,0xAB98E943,0x62765619,0x00000000
95 .long 0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
96 .long 0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
97 .long 0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
98 .long 0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
99 .long 0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
100 .long 0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
101 .long 0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
102 .long 0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
103 .long 0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
104 .long 0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
105 .long 0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
106 .long 0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
107 .long 0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
108 .long 0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
109 .long 0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
110 .long 0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
111 .long 0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
112 .long 0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
113 .long 0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
114 .long 0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
115 .long 0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
116 .long 0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
117 .long 0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
118 .long 0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
119 .long 0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
120 .long 0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
121 .long 0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
122 .long 0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
123 .long 0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
124 .long 0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
125 .long 0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
126 .long 0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
127 .long 0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
128 .long 0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
129 .long 0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
130 .long 0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
131 .long 0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
132 .long 0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
133 .long 0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
134 .long 0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
135 .long 0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
136 .long 0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
137 .long 0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
138 .long 0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
139 .long 0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
140 .long 0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
141 .long 0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
142 .long 0x3FFE0000,0x97731420,0x365E538C,0x00000000
143 .long 0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
144 .long 0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
145 .long 0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
146 .long 0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
147 .long 0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
148 .long 0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
149 .long 0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
150 .long 0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
151 .long 0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
152 .long 0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
153 .long 0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
154 .long 0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
155 .long 0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
156 .long 0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
157 .long 0x3FFE0000,0xE8771129,0xC4353259,0x00000000
158 .long 0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
159 .long 0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
160 .long 0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
161 .long 0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
162 .long 0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
163 .long 0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
164 .long 0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
165 .long 0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
166 .long 0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
167 .long 0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
168 .long 0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
169 .long 0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
170 .long 0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
171 .long 0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
172 .long 0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
173 .long 0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
174 .long 0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
175 .long 0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
176 .long 0x3FFF0000,0x9F100575,0x006CC571,0x00000000
177 .long 0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
178 .long 0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
179 .long 0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
180 .long 0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
181 .long 0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
182 .long 0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
183 .long 0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
184 .long 0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
185 .long 0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
186 .long 0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
187 .long 0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
188 .long 0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
189 .long 0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
190 .long 0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
191 .long 0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
192 .long 0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
193 .long 0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
194 .long 0x3FFF0000,0xB525529D,0x562246BD,0x00000000
195 .long 0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
196 .long 0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
197 .long 0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
198 .long 0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
199 .long 0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
200 .long 0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
201 .long 0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
202 .long 0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
203 .long 0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
204 .long 0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
205 .long 0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
206 .long 0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
207 .long 0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
208 .long 0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
209 .long 0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
210 .long 0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
211 .long 0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
212 .long 0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
213 .long 0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
214 .long 0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
215 .long 0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
216 .long 0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
217
218 .set X,FP_SCR1
219 .set XDCARE,X+2
220 .set XFRAC,X+4
221 .set XFRACLO,X+8
222
223 .set ATANF,FP_SCR2
224 .set ATANFHI,ATANF+4
225 .set ATANFLO,ATANF+8
226
227
228 | xref t_frcinx
229 |xref t_extdnrm
230
231 .global satand
232satand:
233|--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
234
235 bra t_extdnrm
236
237 .global satan
238satan:
239|--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
240
241 fmovex (%a0),%fp0 | ...LOAD INPUT
242
243 movel (%a0),%d0
244 movew 4(%a0),%d0
245 fmovex %fp0,X(%a6)
246 andil #0x7FFFFFFF,%d0
247
248 cmpil #0x3FFB8000,%d0 | ...|X| >= 1/16?
249 bges ATANOK1
250 bra ATANSM
251
252ATANOK1:
253 cmpil #0x4002FFFF,%d0 | ...|X| < 16 ?
254 bles ATANMAIN
255 bra ATANBIG
256
257
258|--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
259|--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
260|--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
261|--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
262|--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
263|--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
264|--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
265|--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
266|--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
267|--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
268|--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
269|--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
270|--WILL INVOLVE A VERY LONG POLYNOMIAL.
271
272|--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
273|--WE CHOSE F TO BE +-2^K * 1.BBBB1
274|--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
275|--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
276|--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
277|-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
278
279ATANMAIN:
280
281 movew #0x0000,XDCARE(%a6) | ...CLEAN UP X JUST IN CASE
282 andil #0xF8000000,XFRAC(%a6) | ...FIRST 5 BITS
283 oril #0x04000000,XFRAC(%a6) | ...SET 6-TH BIT TO 1
284 movel #0x00000000,XFRACLO(%a6) | ...LOCATION OF X IS NOW F
285
286 fmovex %fp0,%fp1 | ...FP1 IS X
287 fmulx X(%a6),%fp1 | ...FP1 IS X*F, NOTE THAT X*F > 0
288 fsubx X(%a6),%fp0 | ...FP0 IS X-F
289 fadds #0x3F800000,%fp1 | ...FP1 IS 1 + X*F
290 fdivx %fp1,%fp0 | ...FP0 IS U = (X-F)/(1+X*F)
291
292|--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
293|--CREATE ATAN(F) AND STORE IT IN ATANF, AND
294|--SAVE REGISTERS FP2.
295
296 movel %d2,-(%a7) | ...SAVE d2 TEMPORARILY
297 movel %d0,%d2 | ...THE EXPO AND 16 BITS OF X
298 andil #0x00007800,%d0 | ...4 VARYING BITS OF F'S FRACTION
299 andil #0x7FFF0000,%d2 | ...EXPONENT OF F
300 subil #0x3FFB0000,%d2 | ...K+4
301 asrl #1,%d2
302 addl %d2,%d0 | ...THE 7 BITS IDENTIFYING F
303 asrl #7,%d0 | ...INDEX INTO TBL OF ATAN(|F|)
304 lea ATANTBL,%a1
305 addal %d0,%a1 | ...ADDRESS OF ATAN(|F|)
306 movel (%a1)+,ATANF(%a6)
307 movel (%a1)+,ATANFHI(%a6)
308 movel (%a1)+,ATANFLO(%a6) | ...ATANF IS NOW ATAN(|F|)
309 movel X(%a6),%d0 | ...LOAD SIGN AND EXPO. AGAIN
310 andil #0x80000000,%d0 | ...SIGN(F)
311 orl %d0,ATANF(%a6) | ...ATANF IS NOW SIGN(F)*ATAN(|F|)
312 movel (%a7)+,%d2 | ...RESTORE d2
313
314|--THAT'S ALL I HAVE TO DO FOR NOW,
315|--BUT ALAS, THE DIVIDE IS STILL CRANKING!
316
317|--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
318|--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
319|--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
320|--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
321|--WHAT WE HAVE HERE IS MERELY A1 = A3, A2 = A1/A3, A3 = A2/A3.
322|--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
323|--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
324
325
326 fmovex %fp0,%fp1
327 fmulx %fp1,%fp1
328 fmoved ATANA3,%fp2
329 faddx %fp1,%fp2 | ...A3+V
330 fmulx %fp1,%fp2 | ...V*(A3+V)
331 fmulx %fp0,%fp1 | ...U*V
332 faddd ATANA2,%fp2 | ...A2+V*(A3+V)
333 fmuld ATANA1,%fp1 | ...A1*U*V
334 fmulx %fp2,%fp1 | ...A1*U*V*(A2+V*(A3+V))
335
336 faddx %fp1,%fp0 | ...ATAN(U), FP1 RELEASED
337 fmovel %d1,%FPCR |restore users exceptions
338 faddx ATANF(%a6),%fp0 | ...ATAN(X)
339 bra t_frcinx
340
341ATANBORS:
342|--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
343|--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
344 cmpil #0x3FFF8000,%d0
345 bgt ATANBIG | ...I.E. |X| >= 16
346
347ATANSM:
348|--|X| <= 1/16
349|--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
350|--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
351|--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
352|--WHERE Y = X*X, AND Z = Y*Y.
353
354 cmpil #0x3FD78000,%d0
355 blt ATANTINY
356|--COMPUTE POLYNOMIAL
357 fmulx %fp0,%fp0 | ...FP0 IS Y = X*X
358
359
360 movew #0x0000,XDCARE(%a6)
361
362 fmovex %fp0,%fp1
363 fmulx %fp1,%fp1 | ...FP1 IS Z = Y*Y
364
365 fmoved ATANB6,%fp2
366 fmoved ATANB5,%fp3
367
368 fmulx %fp1,%fp2 | ...Z*B6
369 fmulx %fp1,%fp3 | ...Z*B5
370
371 faddd ATANB4,%fp2 | ...B4+Z*B6
372 faddd ATANB3,%fp3 | ...B3+Z*B5
373
374 fmulx %fp1,%fp2 | ...Z*(B4+Z*B6)
375 fmulx %fp3,%fp1 | ...Z*(B3+Z*B5)
376
377 faddd ATANB2,%fp2 | ...B2+Z*(B4+Z*B6)
378 faddd ATANB1,%fp1 | ...B1+Z*(B3+Z*B5)
379
380 fmulx %fp0,%fp2 | ...Y*(B2+Z*(B4+Z*B6))
381 fmulx X(%a6),%fp0 | ...X*Y
382
383 faddx %fp2,%fp1 | ...[B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
384
385
386 fmulx %fp1,%fp0 | ...X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
387
388 fmovel %d1,%FPCR |restore users exceptions
389 faddx X(%a6),%fp0
390
391 bra t_frcinx
392
393ATANTINY:
394|--|X| < 2^(-40), ATAN(X) = X
395 movew #0x0000,XDCARE(%a6)
396
397 fmovel %d1,%FPCR |restore users exceptions
398 fmovex X(%a6),%fp0 |last inst - possible exception set
399
400 bra t_frcinx
401
402ATANBIG:
403|--IF |X| > 2^(100), RETURN SIGN(X)*(PI/2 - TINY). OTHERWISE,
404|--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
405 cmpil #0x40638000,%d0
406 bgt ATANHUGE
407
408|--APPROXIMATE ATAN(-1/X) BY
409|--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
410|--THIS CAN BE RE-WRITTEN AS
411|--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
412
413 fmoves #0xBF800000,%fp1 | ...LOAD -1
414 fdivx %fp0,%fp1 | ...FP1 IS -1/X
415
416
417|--DIVIDE IS STILL CRANKING
418
419 fmovex %fp1,%fp0 | ...FP0 IS X'
420 fmulx %fp0,%fp0 | ...FP0 IS Y = X'*X'
421 fmovex %fp1,X(%a6) | ...X IS REALLY X'
422
423 fmovex %fp0,%fp1
424 fmulx %fp1,%fp1 | ...FP1 IS Z = Y*Y
425
426 fmoved ATANC5,%fp3
427 fmoved ATANC4,%fp2
428
429 fmulx %fp1,%fp3 | ...Z*C5
430 fmulx %fp1,%fp2 | ...Z*B4
431
432 faddd ATANC3,%fp3 | ...C3+Z*C5
433 faddd ATANC2,%fp2 | ...C2+Z*C4
434
435 fmulx %fp3,%fp1 | ...Z*(C3+Z*C5), FP3 RELEASED
436 fmulx %fp0,%fp2 | ...Y*(C2+Z*C4)
437
438 faddd ATANC1,%fp1 | ...C1+Z*(C3+Z*C5)
439 fmulx X(%a6),%fp0 | ...X'*Y
440
441 faddx %fp2,%fp1 | ...[Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
442
443
444 fmulx %fp1,%fp0 | ...X'*Y*([B1+Z*(B3+Z*B5)]
445| ... +[Y*(B2+Z*(B4+Z*B6))])
446 faddx X(%a6),%fp0
447
448 fmovel %d1,%FPCR |restore users exceptions
449
450 btstb #7,(%a0)
451 beqs pos_big
452
453neg_big:
454 faddx NPIBY2,%fp0
455 bra t_frcinx
456
457pos_big:
458 faddx PPIBY2,%fp0
459 bra t_frcinx
460
461ATANHUGE:
462|--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
463 btstb #7,(%a0)
464 beqs pos_huge
465
466neg_huge:
467 fmovex NPIBY2,%fp0
468 fmovel %d1,%fpcr
469 fsubx NTINY,%fp0
470 bra t_frcinx
471
472pos_huge:
473 fmovex PPIBY2,%fp0
474 fmovel %d1,%fpcr
475 fsubx PTINY,%fp0
476 bra t_frcinx
477
478 |end
diff --git a/arch/m68k/fpsp040/satanh.S b/arch/m68k/fpsp040/satanh.S
new file mode 100644
index 000000000000..20f07810bcda
--- /dev/null
+++ b/arch/m68k/fpsp040/satanh.S
@@ -0,0 +1,104 @@
1|
2| satanh.sa 3.3 12/19/90
3|
4| The entry point satanh computes the inverse
5| hyperbolic tangent of
6| an input argument; satanhd does the same except for denormalized
7| input.
8|
9| Input: Double-extended number X in location pointed to
10| by address register a0.
11|
12| Output: The value arctanh(X) returned in floating-point register Fp0.
13|
14| Accuracy and Monotonicity: The returned result is within 3 ulps in
15| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
16| result is subsequently rounded to double precision. The
17| result is provably monotonic in double precision.
18|
19| Speed: The program satanh takes approximately 270 cycles.
20|
21| Algorithm:
22|
23| ATANH
24| 1. If |X| >= 1, go to 3.
25|
26| 2. (|X| < 1) Calculate atanh(X) by
27| sgn := sign(X)
28| y := |X|
29| z := 2y/(1-y)
30| atanh(X) := sgn * (1/2) * logp1(z)
31| Exit.
32|
33| 3. If |X| > 1, go to 5.
34|
35| 4. (|X| = 1) Generate infinity with an appropriate sign and
36| divide-by-zero by
37| sgn := sign(X)
38| atan(X) := sgn / (+0).
39| Exit.
40|
41| 5. (|X| > 1) Generate an invalid operation by 0 * infinity.
42| Exit.
43|
44
45| Copyright (C) Motorola, Inc. 1990
46| All Rights Reserved
47|
48| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
49| The copyright notice above does not evidence any
50| actual or intended publication of such source code.
51
52|satanh idnt 2,1 | Motorola 040 Floating Point Software Package
53
54 |section 8
55
56 |xref t_dz
57 |xref t_operr
58 |xref t_frcinx
59 |xref t_extdnrm
60 |xref slognp1
61
62 .global satanhd
63satanhd:
64|--ATANH(X) = X FOR DENORMALIZED X
65
66 bra t_extdnrm
67
68 .global satanh
69satanh:
70 movel (%a0),%d0
71 movew 4(%a0),%d0
72 andil #0x7FFFFFFF,%d0
73 cmpil #0x3FFF8000,%d0
74 bges ATANHBIG
75
76|--THIS IS THE USUAL CASE, |X| < 1
77|--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
78
79 fabsx (%a0),%fp0 | ...Y = |X|
80 fmovex %fp0,%fp1
81 fnegx %fp1 | ...-Y
82 faddx %fp0,%fp0 | ...2Y
83 fadds #0x3F800000,%fp1 | ...1-Y
84 fdivx %fp1,%fp0 | ...2Y/(1-Y)
85 movel (%a0),%d0
86 andil #0x80000000,%d0
87 oril #0x3F000000,%d0 | ...SIGN(X)*HALF
88 movel %d0,-(%sp)
89
90 fmovemx %fp0-%fp0,(%a0) | ...overwrite input
91 movel %d1,-(%sp)
92 clrl %d1
93 bsr slognp1 | ...LOG1P(Z)
94 fmovel (%sp)+,%fpcr
95 fmuls (%sp)+,%fp0
96 bra t_frcinx
97
98ATANHBIG:
99 fabsx (%a0),%fp0 | ...|X|
100 fcmps #0x3F800000,%fp0
101 fbgt t_operr
102 bra t_dz
103
104 |end
diff --git a/arch/m68k/fpsp040/scale.S b/arch/m68k/fpsp040/scale.S
new file mode 100644
index 000000000000..5c9b805265f2
--- /dev/null
+++ b/arch/m68k/fpsp040/scale.S
@@ -0,0 +1,371 @@
1|
2| scale.sa 3.3 7/30/91
3|
4| The entry point sSCALE computes the destination operand
5| scaled by the source operand. If the absolute value of
6| the source operand is (>= 2^14) an overflow or underflow
7| is returned.
8|
9| The entry point sscale is called from do_func to emulate
10| the fscale unimplemented instruction.
11|
12| Input: Double-extended destination operand in FPTEMP,
13| double-extended source operand in ETEMP.
14|
15| Output: The function returns scale(X,Y) to fp0.
16|
17| Modifies: fp0.
18|
19| Algorithm:
20|
21| Copyright (C) Motorola, Inc. 1990
22| All Rights Reserved
23|
24| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
25| The copyright notice above does not evidence any
26| actual or intended publication of such source code.
27
28|SCALE idnt 2,1 | Motorola 040 Floating Point Software Package
29
30 |section 8
31
32#include "fpsp.h"
33
34 |xref t_ovfl2
35 |xref t_unfl
36 |xref round
37 |xref t_resdnrm
38
39SRC_BNDS: .short 0x3fff,0x400c
40
41|
42| This entry point is used by the unimplemented instruction exception
43| handler.
44|
45|
46|
47| FSCALE
48|
49 .global sscale
50sscale:
51 fmovel #0,%fpcr |clr user enabled exc
52 clrl %d1
53 movew FPTEMP(%a6),%d1 |get dest exponent
54 smi L_SCR1(%a6) |use L_SCR1 to hold sign
55 andil #0x7fff,%d1 |strip sign
56 movew ETEMP(%a6),%d0 |check src bounds
57 andiw #0x7fff,%d0 |clr sign bit
58 cmp2w SRC_BNDS,%d0
59 bccs src_in
60 cmpiw #0x400c,%d0 |test for too large
61 bge src_out
62|
63| The source input is below 1, so we check for denormalized numbers
64| and set unfl.
65|
66src_small:
67 moveb DTAG(%a6),%d0
68 andib #0xe0,%d0
69 tstb %d0
70 beqs no_denorm
71 st STORE_FLG(%a6) |dest already contains result
72 orl #unfl_mask,USER_FPSR(%a6) |set UNFL
73den_done:
74 leal FPTEMP(%a6),%a0
75 bra t_resdnrm
76no_denorm:
77 fmovel USER_FPCR(%a6),%FPCR
78 fmovex FPTEMP(%a6),%fp0 |simply return dest
79 rts
80
81
82|
83| Source is within 2^14 range. To perform the int operation,
84| move it to d0.
85|
86src_in:
87 fmovex ETEMP(%a6),%fp0 |move in src for int
88 fmovel #rz_mode,%fpcr |force rz for src conversion
89 fmovel %fp0,%d0 |int src to d0
90 fmovel #0,%FPSR |clr status from above
91 tstw ETEMP(%a6) |check src sign
92 blt src_neg
93|
94| Source is positive. Add the src to the dest exponent.
95| The result can be denormalized, if src = 0, or overflow,
96| if the result of the add sets a bit in the upper word.
97|
98src_pos:
99 tstw %d1 |check for denorm
100 beq dst_dnrm
101 addl %d0,%d1 |add src to dest exp
102 beqs denorm |if zero, result is denorm
103 cmpil #0x7fff,%d1 |test for overflow
104 bges ovfl
105 tstb L_SCR1(%a6)
106 beqs spos_pos
107 orw #0x8000,%d1
108spos_pos:
109 movew %d1,FPTEMP(%a6) |result in FPTEMP
110 fmovel USER_FPCR(%a6),%FPCR
111 fmovex FPTEMP(%a6),%fp0 |write result to fp0
112 rts
113ovfl:
114 tstb L_SCR1(%a6)
115 beqs sovl_pos
116 orw #0x8000,%d1
117sovl_pos:
118 movew FPTEMP(%a6),ETEMP(%a6) |result in ETEMP
119 movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
120 movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
121 bra t_ovfl2
122
123denorm:
124 tstb L_SCR1(%a6)
125 beqs den_pos
126 orw #0x8000,%d1
127den_pos:
128 tstl FPTEMP_HI(%a6) |check j bit
129 blts nden_exit |if set, not denorm
130 movew %d1,ETEMP(%a6) |input expected in ETEMP
131 movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
132 movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
133 orl #unfl_bit,USER_FPSR(%a6) |set unfl
134 leal ETEMP(%a6),%a0
135 bra t_resdnrm
136nden_exit:
137 movew %d1,FPTEMP(%a6) |result in FPTEMP
138 fmovel USER_FPCR(%a6),%FPCR
139 fmovex FPTEMP(%a6),%fp0 |write result to fp0
140 rts
141
142|
143| Source is negative. Add the src to the dest exponent.
144| (The result exponent will be reduced). The result can be
145| denormalized.
146|
147src_neg:
148 addl %d0,%d1 |add src to dest
149 beqs denorm |if zero, result is denorm
150 blts fix_dnrm |if negative, result is
151| ;needing denormalization
152 tstb L_SCR1(%a6)
153 beqs sneg_pos
154 orw #0x8000,%d1
155sneg_pos:
156 movew %d1,FPTEMP(%a6) |result in FPTEMP
157 fmovel USER_FPCR(%a6),%FPCR
158 fmovex FPTEMP(%a6),%fp0 |write result to fp0
159 rts
160
161
162|
163| The result exponent is below denorm value. Test for catastrophic
164| underflow and force zero if true. If not, try to shift the
165| mantissa right until a zero exponent exists.
166|
167fix_dnrm:
168 cmpiw #0xffc0,%d1 |lower bound for normalization
169 blt fix_unfl |if lower, catastrophic unfl
170 movew %d1,%d0 |use d0 for exp
171 movel %d2,-(%a7) |free d2 for norm
172 movel FPTEMP_HI(%a6),%d1
173 movel FPTEMP_LO(%a6),%d2
174 clrl L_SCR2(%a6)
175fix_loop:
176 addw #1,%d0 |drive d0 to 0
177 lsrl #1,%d1 |while shifting the
178 roxrl #1,%d2 |mantissa to the right
179 bccs no_carry
180 st L_SCR2(%a6) |use L_SCR2 to capture inex
181no_carry:
182 tstw %d0 |it is finished when
183 blts fix_loop |d0 is zero or the mantissa
184 tstb L_SCR2(%a6)
185 beqs tst_zero
186 orl #unfl_inx_mask,USER_FPSR(%a6)
187| ;set unfl, aunfl, ainex
188|
189| Test for zero. If zero, simply use fmove to return +/- zero
190| to the fpu.
191|
192tst_zero:
193 clrw FPTEMP_EX(%a6)
194 tstb L_SCR1(%a6) |test for sign
195 beqs tst_con
196 orw #0x8000,FPTEMP_EX(%a6) |set sign bit
197tst_con:
198 movel %d1,FPTEMP_HI(%a6)
199 movel %d2,FPTEMP_LO(%a6)
200 movel (%a7)+,%d2
201 tstl %d1
202 bnes not_zero
203 tstl FPTEMP_LO(%a6)
204 bnes not_zero
205|
206| Result is zero. Check for rounding mode to set lsb. If the
207| mode is rp, and the zero is positive, return smallest denorm.
208| If the mode is rm, and the zero is negative, return smallest
209| negative denorm.
210|
211 btstb #5,FPCR_MODE(%a6) |test if rm or rp
212 beqs no_dir
213 btstb #4,FPCR_MODE(%a6) |check which one
214 beqs zer_rm
215zer_rp:
216 tstb L_SCR1(%a6) |check sign
217 bnes no_dir |if set, neg op, no inc
218 movel #1,FPTEMP_LO(%a6) |set lsb
219 bras sm_dnrm
220zer_rm:
221 tstb L_SCR1(%a6) |check sign
222 beqs no_dir |if clr, neg op, no inc
223 movel #1,FPTEMP_LO(%a6) |set lsb
224 orl #neg_mask,USER_FPSR(%a6) |set N
225 bras sm_dnrm
226no_dir:
227 fmovel USER_FPCR(%a6),%FPCR
228 fmovex FPTEMP(%a6),%fp0 |use fmove to set cc's
229 rts
230
231|
232| The rounding mode changed the zero to a smallest denorm. Call
233| t_resdnrm with exceptional operand in ETEMP.
234|
235sm_dnrm:
236 movel FPTEMP_EX(%a6),ETEMP_EX(%a6)
237 movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
238 movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
239 leal ETEMP(%a6),%a0
240 bra t_resdnrm
241
242|
243| Result is still denormalized.
244|
245not_zero:
246 orl #unfl_mask,USER_FPSR(%a6) |set unfl
247 tstb L_SCR1(%a6) |check for sign
248 beqs fix_exit
249 orl #neg_mask,USER_FPSR(%a6) |set N
250fix_exit:
251 bras sm_dnrm
252
253
254|
255| The result has underflowed to zero. Return zero and set
256| unfl, aunfl, and ainex.
257|
258fix_unfl:
259 orl #unfl_inx_mask,USER_FPSR(%a6)
260 btstb #5,FPCR_MODE(%a6) |test if rm or rp
261 beqs no_dir2
262 btstb #4,FPCR_MODE(%a6) |check which one
263 beqs zer_rm2
264zer_rp2:
265 tstb L_SCR1(%a6) |check sign
266 bnes no_dir2 |if set, neg op, no inc
267 clrl FPTEMP_EX(%a6)
268 clrl FPTEMP_HI(%a6)
269 movel #1,FPTEMP_LO(%a6) |set lsb
270 bras sm_dnrm |return smallest denorm
271zer_rm2:
272 tstb L_SCR1(%a6) |check sign
273 beqs no_dir2 |if clr, neg op, no inc
274 movew #0x8000,FPTEMP_EX(%a6)
275 clrl FPTEMP_HI(%a6)
276 movel #1,FPTEMP_LO(%a6) |set lsb
277 orl #neg_mask,USER_FPSR(%a6) |set N
278 bra sm_dnrm |return smallest denorm
279
280no_dir2:
281 tstb L_SCR1(%a6)
282 bges pos_zero
283neg_zero:
284 clrl FP_SCR1(%a6) |clear the exceptional operand
285 clrl FP_SCR1+4(%a6) |for gen_except.
286 clrl FP_SCR1+8(%a6)
287 fmoves #0x80000000,%fp0
288 rts
289pos_zero:
290 clrl FP_SCR1(%a6) |clear the exceptional operand
291 clrl FP_SCR1+4(%a6) |for gen_except.
292 clrl FP_SCR1+8(%a6)
293 fmoves #0x00000000,%fp0
294 rts
295
296|
297| The destination is a denormalized number. It must be handled
298| by first shifting the bits in the mantissa until it is normalized,
299| then adding the remainder of the source to the exponent.
300|
301dst_dnrm:
302 moveml %d2/%d3,-(%a7)
303 movew FPTEMP_EX(%a6),%d1
304 movel FPTEMP_HI(%a6),%d2
305 movel FPTEMP_LO(%a6),%d3
306dst_loop:
307 tstl %d2 |test for normalized result
308 blts dst_norm |exit loop if so
309 tstl %d0 |otherwise, test shift count
310 beqs dst_fin |if zero, shifting is done
311 subil #1,%d0 |dec src
312 lsll #1,%d3
313 roxll #1,%d2
314 bras dst_loop
315|
316| Destination became normalized. Simply add the remaining
317| portion of the src to the exponent.
318|
319dst_norm:
320 addw %d0,%d1 |dst is normalized; add src
321 tstb L_SCR1(%a6)
322 beqs dnrm_pos
323 orl #0x8000,%d1
324dnrm_pos:
325 movemw %d1,FPTEMP_EX(%a6)
326 moveml %d2,FPTEMP_HI(%a6)
327 moveml %d3,FPTEMP_LO(%a6)
328 fmovel USER_FPCR(%a6),%FPCR
329 fmovex FPTEMP(%a6),%fp0
330 moveml (%a7)+,%d2/%d3
331 rts
332
333|
334| Destination remained denormalized. Call t_excdnrm with
335| exceptional operand in ETEMP.
336|
337dst_fin:
338 tstb L_SCR1(%a6) |check for sign
339 beqs dst_exit
340 orl #neg_mask,USER_FPSR(%a6) |set N
341 orl #0x8000,%d1
342dst_exit:
343 movemw %d1,ETEMP_EX(%a6)
344 moveml %d2,ETEMP_HI(%a6)
345 moveml %d3,ETEMP_LO(%a6)
346 orl #unfl_mask,USER_FPSR(%a6) |set unfl
347 moveml (%a7)+,%d2/%d3
348 leal ETEMP(%a6),%a0
349 bra t_resdnrm
350
351|
352| Source is outside of 2^14 range. Test the sign and branch
353| to the appropriate exception handler.
354|
355src_out:
356 tstb L_SCR1(%a6)
357 beqs scro_pos
358 orl #0x8000,%d1
359scro_pos:
360 movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
361 movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
362 tstw ETEMP(%a6)
363 blts res_neg
364res_pos:
365 movew %d1,ETEMP(%a6) |result in ETEMP
366 bra t_ovfl2
367res_neg:
368 movew %d1,ETEMP(%a6) |result in ETEMP
369 leal ETEMP(%a6),%a0
370 bra t_unfl
371 |end
diff --git a/arch/m68k/fpsp040/scosh.S b/arch/m68k/fpsp040/scosh.S
new file mode 100644
index 000000000000..e81edbb87642
--- /dev/null
+++ b/arch/m68k/fpsp040/scosh.S
@@ -0,0 +1,132 @@
1|
2| scosh.sa 3.1 12/10/90
3|
4| The entry point sCosh computes the hyperbolic cosine of
5| an input argument; sCoshd does the same except for denormalized
6| input.
7|
8| Input: Double-extended number X in location pointed to
9| by address register a0.
10|
11| Output: The value cosh(X) returned in floating-point register Fp0.
12|
13| Accuracy and Monotonicity: The returned result is within 3 ulps in
14| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
15| result is subsequently rounded to double precision. The
16| result is provably monotonic in double precision.
17|
18| Speed: The program sCOSH takes approximately 250 cycles.
19|
20| Algorithm:
21|
22| COSH
23| 1. If |X| > 16380 log2, go to 3.
24|
25| 2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae
26| y = |X|, z = exp(Y), and
27| cosh(X) = (1/2)*( z + 1/z ).
28| Exit.
29|
30| 3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5.
31|
32| 4. (16380 log2 < |X| <= 16480 log2)
33| cosh(X) = sign(X) * exp(|X|)/2.
34| However, invoking exp(|X|) may cause premature overflow.
35| Thus, we calculate sinh(X) as follows:
36| Y := |X|
37| Fact := 2**(16380)
38| Y' := Y - 16381 log2
39| cosh(X) := Fact * exp(Y').
40| Exit.
41|
42| 5. (|X| > 16480 log2) sinh(X) must overflow. Return
43| Huge*Huge to generate overflow and an infinity with
44| the appropriate sign. Huge is the largest finite number in
45| extended format. Exit.
46|
47|
48
49| Copyright (C) Motorola, Inc. 1990
50| All Rights Reserved
51|
52| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
53| The copyright notice above does not evidence any
54| actual or intended publication of such source code.
55
56|SCOSH idnt 2,1 | Motorola 040 Floating Point Software Package
57
58 |section 8
59
60 |xref t_ovfl
61 |xref t_frcinx
62 |xref setox
63
64T1: .long 0x40C62D38,0xD3D64634 | ... 16381 LOG2 LEAD
65T2: .long 0x3D6F90AE,0xB1E75CC7 | ... 16381 LOG2 TRAIL
66
67TWO16380: .long 0x7FFB0000,0x80000000,0x00000000,0x00000000
68
69 .global scoshd
70scoshd:
71|--COSH(X) = 1 FOR DENORMALIZED X
72
73 fmoves #0x3F800000,%fp0
74
75 fmovel %d1,%FPCR
76 fadds #0x00800000,%fp0
77 bra t_frcinx
78
79 .global scosh
80scosh:
81 fmovex (%a0),%fp0 | ...LOAD INPUT
82
83 movel (%a0),%d0
84 movew 4(%a0),%d0
85 andil #0x7FFFFFFF,%d0
86 cmpil #0x400CB167,%d0
87 bgts COSHBIG
88
89|--THIS IS THE USUAL CASE, |X| < 16380 LOG2
90|--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
91
92 fabsx %fp0 | ...|X|
93
94 movel %d1,-(%sp)
95 clrl %d1
96 fmovemx %fp0-%fp0,(%a0) |pass parameter to setox
97 bsr setox | ...FP0 IS EXP(|X|)
98 fmuls #0x3F000000,%fp0 | ...(1/2)EXP(|X|)
99 movel (%sp)+,%d1
100
101 fmoves #0x3E800000,%fp1 | ...(1/4)
102 fdivx %fp0,%fp1 | ...1/(2 EXP(|X|))
103
104 fmovel %d1,%FPCR
105 faddx %fp1,%fp0
106
107 bra t_frcinx
108
109COSHBIG:
110 cmpil #0x400CB2B3,%d0
111 bgts COSHHUGE
112
113 fabsx %fp0
114 fsubd T1(%pc),%fp0 | ...(|X|-16381LOG2_LEAD)
115 fsubd T2(%pc),%fp0 | ...|X| - 16381 LOG2, ACCURATE
116
117 movel %d1,-(%sp)
118 clrl %d1
119 fmovemx %fp0-%fp0,(%a0)
120 bsr setox
121 fmovel (%sp)+,%fpcr
122
123 fmulx TWO16380(%pc),%fp0
124 bra t_frcinx
125
126COSHHUGE:
127 fmovel #0,%fpsr |clr N bit if set by source
128 bclrb #7,(%a0) |always return positive value
129 fmovemx (%a0),%fp0-%fp0
130 bra t_ovfl
131
132 |end
diff --git a/arch/m68k/fpsp040/setox.S b/arch/m68k/fpsp040/setox.S
new file mode 100644
index 000000000000..0aa75f9bf7d1
--- /dev/null
+++ b/arch/m68k/fpsp040/setox.S
@@ -0,0 +1,865 @@
1|
2| setox.sa 3.1 12/10/90
3|
4| The entry point setox computes the exponential of a value.
5| setoxd does the same except the input value is a denormalized
6| number. setoxm1 computes exp(X)-1, and setoxm1d computes
7| exp(X)-1 for denormalized X.
8|
9| INPUT
10| -----
11| Double-extended value in memory location pointed to by address
12| register a0.
13|
14| OUTPUT
15| ------
16| exp(X) or exp(X)-1 returned in floating-point register fp0.
17|
18| ACCURACY and MONOTONICITY
19| -------------------------
20| The returned result is within 0.85 ulps in 64 significant bit, i.e.
21| within 0.5001 ulp to 53 bits if the result is subsequently rounded
22| to double precision. The result is provably monotonic in double
23| precision.
24|
25| SPEED
26| -----
27| Two timings are measured, both in the copy-back mode. The
28| first one is measured when the function is invoked the first time
29| (so the instructions and data are not in cache), and the
30| second one is measured when the function is reinvoked at the same
31| input argument.
32|
33| The program setox takes approximately 210/190 cycles for input
34| argument X whose magnitude is less than 16380 log2, which
35| is the usual situation. For the less common arguments,
36| depending on their values, the program may run faster or slower --
37| but no worse than 10% slower even in the extreme cases.
38|
39| The program setoxm1 takes approximately ???/??? cycles for input
40| argument X, 0.25 <= |X| < 70log2. For |X| < 0.25, it takes
41| approximately ???/??? cycles. For the less common arguments,
42| depending on their values, the program may run faster or slower --
43| but no worse than 10% slower even in the extreme cases.
44|
45| ALGORITHM and IMPLEMENTATION NOTES
46| ----------------------------------
47|
48| setoxd
49| ------
50| Step 1. Set ans := 1.0
51|
52| Step 2. Return ans := ans + sign(X)*2^(-126). Exit.
53| Notes: This will always generate one exception -- inexact.
54|
55|
56| setox
57| -----
58|
59| Step 1. Filter out extreme cases of input argument.
60| 1.1 If |X| >= 2^(-65), go to Step 1.3.
61| 1.2 Go to Step 7.
62| 1.3 If |X| < 16380 log(2), go to Step 2.
63| 1.4 Go to Step 8.
64| Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.
65| To avoid the use of floating-point comparisons, a
66| compact representation of |X| is used. This format is a
67| 32-bit integer, the upper (more significant) 16 bits are
68| the sign and biased exponent field of |X|; the lower 16
69| bits are the 16 most significant fraction (including the
70| explicit bit) bits of |X|. Consequently, the comparisons
71| in Steps 1.1 and 1.3 can be performed by integer comparison.
72| Note also that the constant 16380 log(2) used in Step 1.3
73| is also in the compact form. Thus taking the branch
74| to Step 2 guarantees |X| < 16380 log(2). There is no harm
75| to have a small number of cases where |X| is less than,
76| but close to, 16380 log(2) and the branch to Step 9 is
77| taken.
78|
79| Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ).
80| 2.1 Set AdjFlag := 0 (indicates the branch 1.3 -> 2 was taken)
81| 2.2 N := round-to-nearest-integer( X * 64/log2 ).
82| 2.3 Calculate J = N mod 64; so J = 0,1,2,..., or 63.
83| 2.4 Calculate M = (N - J)/64; so N = 64M + J.
84| 2.5 Calculate the address of the stored value of 2^(J/64).
85| 2.6 Create the value Scale = 2^M.
86| Notes: The calculation in 2.2 is really performed by
87|
88| Z := X * constant
89| N := round-to-nearest-integer(Z)
90|
91| where
92|
93| constant := single-precision( 64/log 2 ).
94|
95| Using a single-precision constant avoids memory access.
96| Another effect of using a single-precision "constant" is
97| that the calculated value Z is
98|
99| Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24).
100|
101| This error has to be considered later in Steps 3 and 4.
102|
103| Step 3. Calculate X - N*log2/64.
104| 3.1 R := X + N*L1, where L1 := single-precision(-log2/64).
105| 3.2 R := R + N*L2, L2 := extended-precision(-log2/64 - L1).
106| Notes: a) The way L1 and L2 are chosen ensures L1+L2 approximate
107| the value -log2/64 to 88 bits of accuracy.
108| b) N*L1 is exact because N is no longer than 22 bits and
109| L1 is no longer than 24 bits.
110| c) The calculation X+N*L1 is also exact due to cancellation.
111| Thus, R is practically X+N(L1+L2) to full 64 bits.
112| d) It is important to estimate how large can |R| be after
113| Step 3.2.
114|
115| N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24)
116| X*64/log2 (1+eps) = N + f, |f| <= 0.5
117| X*64/log2 - N = f - eps*X 64/log2
118| X - N*log2/64 = f*log2/64 - eps*X
119|
120|
121| Now |X| <= 16446 log2, thus
122|
123| |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64
124| <= 0.57 log2/64.
125| This bound will be used in Step 4.
126|
127| Step 4. Approximate exp(R)-1 by a polynomial
128| p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
129| Notes: a) In order to reduce memory access, the coefficients are
130| made as "short" as possible: A1 (which is 1/2), A4 and A5
131| are single precision; A2 and A3 are double precision.
132| b) Even with the restrictions above,
133| |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062.
134| Note that 0.0062 is slightly bigger than 0.57 log2/64.
135| c) To fully utilize the pipeline, p is separated into
136| two independent pieces of roughly equal complexities
137| p = [ R + R*S*(A2 + S*A4) ] +
138| [ S*(A1 + S*(A3 + S*A5)) ]
139| where S = R*R.
140|
141| Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by
142| ans := T + ( T*p + t)
143| where T and t are the stored values for 2^(J/64).
144| Notes: 2^(J/64) is stored as T and t where T+t approximates
145| 2^(J/64) to roughly 85 bits; T is in extended precision
146| and t is in single precision. Note also that T is rounded
147| to 62 bits so that the last two bits of T are zero. The
148| reason for such a special form is that T-1, T-2, and T-8
149| will all be exact --- a property that will give much
150| more accurate computation of the function EXPM1.
151|
152| Step 6. Reconstruction of exp(X)
153| exp(X) = 2^M * 2^(J/64) * exp(R).
154| 6.1 If AdjFlag = 0, go to 6.3
155| 6.2 ans := ans * AdjScale
156| 6.3 Restore the user FPCR
157| 6.4 Return ans := ans * Scale. Exit.
158| Notes: If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R,
159| |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will
160| neither overflow nor underflow. If AdjFlag = 1, that
161| means that
162| X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380.
163| Hence, exp(X) may overflow or underflow or neither.
164| When that is the case, AdjScale = 2^(M1) where M1 is
165| approximately M. Thus 6.2 will never cause over/underflow.
166| Possible exception in 6.4 is overflow or underflow.
167| The inexact exception is not generated in 6.4. Although
168| one can argue that the inexact flag should always be
169| raised, to simulate that exception cost to much than the
170| flag is worth in practical uses.
171|
172| Step 7. Return 1 + X.
173| 7.1 ans := X
174| 7.2 Restore user FPCR.
175| 7.3 Return ans := 1 + ans. Exit
176| Notes: For non-zero X, the inexact exception will always be
177| raised by 7.3. That is the only exception raised by 7.3.
178| Note also that we use the FMOVEM instruction to move X
179| in Step 7.1 to avoid unnecessary trapping. (Although
180| the FMOVEM may not seem relevant since X is normalized,
181| the precaution will be useful in the library version of
182| this code where the separate entry for denormalized inputs
183| will be done away with.)
184|
185| Step 8. Handle exp(X) where |X| >= 16380log2.
186| 8.1 If |X| > 16480 log2, go to Step 9.
187| (mimic 2.2 - 2.6)
188| 8.2 N := round-to-integer( X * 64/log2 )
189| 8.3 Calculate J = N mod 64, J = 0,1,...,63
190| 8.4 K := (N-J)/64, M1 := truncate(K/2), M = K-M1, AdjFlag := 1.
191| 8.5 Calculate the address of the stored value 2^(J/64).
192| 8.6 Create the values Scale = 2^M, AdjScale = 2^M1.
193| 8.7 Go to Step 3.
194| Notes: Refer to notes for 2.2 - 2.6.
195|
196| Step 9. Handle exp(X), |X| > 16480 log2.
197| 9.1 If X < 0, go to 9.3
198| 9.2 ans := Huge, go to 9.4
199| 9.3 ans := Tiny.
200| 9.4 Restore user FPCR.
201| 9.5 Return ans := ans * ans. Exit.
202| Notes: Exp(X) will surely overflow or underflow, depending on
203| X's sign. "Huge" and "Tiny" are respectively large/tiny
204| extended-precision numbers whose square over/underflow
205| with an inexact result. Thus, 9.5 always raises the
206| inexact together with either overflow or underflow.
207|
208|
209| setoxm1d
210| --------
211|
212| Step 1. Set ans := 0
213|
214| Step 2. Return ans := X + ans. Exit.
215| Notes: This will return X with the appropriate rounding
216| precision prescribed by the user FPCR.
217|
218| setoxm1
219| -------
220|
221| Step 1. Check |X|
222| 1.1 If |X| >= 1/4, go to Step 1.3.
223| 1.2 Go to Step 7.
224| 1.3 If |X| < 70 log(2), go to Step 2.
225| 1.4 Go to Step 10.
226| Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.
227| However, it is conceivable |X| can be small very often
228| because EXPM1 is intended to evaluate exp(X)-1 accurately
229| when |X| is small. For further details on the comparisons,
230| see the notes on Step 1 of setox.
231|
232| Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ).
233| 2.1 N := round-to-nearest-integer( X * 64/log2 ).
234| 2.2 Calculate J = N mod 64; so J = 0,1,2,..., or 63.
235| 2.3 Calculate M = (N - J)/64; so N = 64M + J.
236| 2.4 Calculate the address of the stored value of 2^(J/64).
237| 2.5 Create the values Sc = 2^M and OnebySc := -2^(-M).
238| Notes: See the notes on Step 2 of setox.
239|
240| Step 3. Calculate X - N*log2/64.
241| 3.1 R := X + N*L1, where L1 := single-precision(-log2/64).
242| 3.2 R := R + N*L2, L2 := extended-precision(-log2/64 - L1).
243| Notes: Applying the analysis of Step 3 of setox in this case
244| shows that |R| <= 0.0055 (note that |X| <= 70 log2 in
245| this case).
246|
247| Step 4. Approximate exp(R)-1 by a polynomial
248| p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6)))))
249| Notes: a) In order to reduce memory access, the coefficients are
250| made as "short" as possible: A1 (which is 1/2), A5 and A6
251| are single precision; A2, A3 and A4 are double precision.
252| b) Even with the restriction above,
253| |p - (exp(R)-1)| < |R| * 2^(-72.7)
254| for all |R| <= 0.0055.
255| c) To fully utilize the pipeline, p is separated into
256| two independent pieces of roughly equal complexity
257| p = [ R*S*(A2 + S*(A4 + S*A6)) ] +
258| [ R + S*(A1 + S*(A3 + S*A5)) ]
259| where S = R*R.
260|
261| Step 5. Compute 2^(J/64)*p by
262| p := T*p
263| where T and t are the stored values for 2^(J/64).
264| Notes: 2^(J/64) is stored as T and t where T+t approximates
265| 2^(J/64) to roughly 85 bits; T is in extended precision
266| and t is in single precision. Note also that T is rounded
267| to 62 bits so that the last two bits of T are zero. The
268| reason for such a special form is that T-1, T-2, and T-8
269| will all be exact --- a property that will be exploited
270| in Step 6 below. The total relative error in p is no
271| bigger than 2^(-67.7) compared to the final result.
272|
273| Step 6. Reconstruction of exp(X)-1
274| exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ).
275| 6.1 If M <= 63, go to Step 6.3.
276| 6.2 ans := T + (p + (t + OnebySc)). Go to 6.6
277| 6.3 If M >= -3, go to 6.5.
278| 6.4 ans := (T + (p + t)) + OnebySc. Go to 6.6
279| 6.5 ans := (T + OnebySc) + (p + t).
280| 6.6 Restore user FPCR.
281| 6.7 Return ans := Sc * ans. Exit.
282| Notes: The various arrangements of the expressions give accurate
283| evaluations.
284|
285| Step 7. exp(X)-1 for |X| < 1/4.
286| 7.1 If |X| >= 2^(-65), go to Step 9.
287| 7.2 Go to Step 8.
288|
289| Step 8. Calculate exp(X)-1, |X| < 2^(-65).
290| 8.1 If |X| < 2^(-16312), goto 8.3
291| 8.2 Restore FPCR; return ans := X - 2^(-16382). Exit.
292| 8.3 X := X * 2^(140).
293| 8.4 Restore FPCR; ans := ans - 2^(-16382).
294| Return ans := ans*2^(140). Exit
295| Notes: The idea is to return "X - tiny" under the user
296| precision and rounding modes. To avoid unnecessary
297| inefficiency, we stay away from denormalized numbers the
298| best we can. For |X| >= 2^(-16312), the straightforward
299| 8.2 generates the inexact exception as the case warrants.
300|
301| Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial
302| p = X + X*X*(B1 + X*(B2 + ... + X*B12))
303| Notes: a) In order to reduce memory access, the coefficients are
304| made as "short" as possible: B1 (which is 1/2), B9 to B12
305| are single precision; B3 to B8 are double precision; and
306| B2 is double extended.
307| b) Even with the restriction above,
308| |p - (exp(X)-1)| < |X| 2^(-70.6)
309| for all |X| <= 0.251.
310| Note that 0.251 is slightly bigger than 1/4.
311| c) To fully preserve accuracy, the polynomial is computed
312| as X + ( S*B1 + Q ) where S = X*X and
313| Q = X*S*(B2 + X*(B3 + ... + X*B12))
314| d) To fully utilize the pipeline, Q is separated into
315| two independent pieces of roughly equal complexity
316| Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] +
317| [ S*S*(B3 + S*(B5 + ... + S*B11)) ]
318|
319| Step 10. Calculate exp(X)-1 for |X| >= 70 log 2.
320| 10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all practical
321| purposes. Therefore, go to Step 1 of setox.
322| 10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical purposes.
323| ans := -1
324| Restore user FPCR
325| Return ans := ans + 2^(-126). Exit.
326| Notes: 10.2 will always create an inexact and return -1 + tiny
327| in the user rounding precision and mode.
328|
329|
330
331| Copyright (C) Motorola, Inc. 1990
332| All Rights Reserved
333|
334| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
335| The copyright notice above does not evidence any
336| actual or intended publication of such source code.
337
338|setox idnt 2,1 | Motorola 040 Floating Point Software Package
339
340 |section 8
341
342#include "fpsp.h"
343
344L2: .long 0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
345
346EXPA3: .long 0x3FA55555,0x55554431
347EXPA2: .long 0x3FC55555,0x55554018
348
349HUGE: .long 0x7FFE0000,0xFFFFFFFF,0xFFFFFFFF,0x00000000
350TINY: .long 0x00010000,0xFFFFFFFF,0xFFFFFFFF,0x00000000
351
352EM1A4: .long 0x3F811111,0x11174385
353EM1A3: .long 0x3FA55555,0x55554F5A
354
355EM1A2: .long 0x3FC55555,0x55555555,0x00000000,0x00000000
356
357EM1B8: .long 0x3EC71DE3,0xA5774682
358EM1B7: .long 0x3EFA01A0,0x19D7CB68
359
360EM1B6: .long 0x3F2A01A0,0x1A019DF3
361EM1B5: .long 0x3F56C16C,0x16C170E2
362
363EM1B4: .long 0x3F811111,0x11111111
364EM1B3: .long 0x3FA55555,0x55555555
365
366EM1B2: .long 0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
367 .long 0x00000000
368
369TWO140: .long 0x48B00000,0x00000000
370TWON140: .long 0x37300000,0x00000000
371
372EXPTBL:
373 .long 0x3FFF0000,0x80000000,0x00000000,0x00000000
374 .long 0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
375 .long 0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
376 .long 0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
377 .long 0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
378 .long 0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
379 .long 0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
380 .long 0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
381 .long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
382 .long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
383 .long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
384 .long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
385 .long 0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
386 .long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
387 .long 0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
388 .long 0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
389 .long 0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
390 .long 0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
391 .long 0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
392 .long 0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
393 .long 0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
394 .long 0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
395 .long 0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
396 .long 0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
397 .long 0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
398 .long 0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
399 .long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
400 .long 0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
401 .long 0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
402 .long 0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
403 .long 0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
404 .long 0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
405 .long 0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
406 .long 0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
407 .long 0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
408 .long 0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
409 .long 0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
410 .long 0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
411 .long 0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
412 .long 0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
413 .long 0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
414 .long 0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
415 .long 0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
416 .long 0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
417 .long 0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
418 .long 0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
419 .long 0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
420 .long 0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
421 .long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
422 .long 0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
423 .long 0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
424 .long 0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
425 .long 0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
426 .long 0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
427 .long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
428 .long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
429 .long 0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
430 .long 0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
431 .long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
432 .long 0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
433 .long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
434 .long 0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
435 .long 0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
436 .long 0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
437
438 .set ADJFLAG,L_SCR2
439 .set SCALE,FP_SCR1
440 .set ADJSCALE,FP_SCR2
441 .set SC,FP_SCR3
442 .set ONEBYSC,FP_SCR4
443
444 | xref t_frcinx
445 |xref t_extdnrm
446 |xref t_unfl
447 |xref t_ovfl
448
449 .global setoxd
450setoxd:
451|--entry point for EXP(X), X is denormalized
452 movel (%a0),%d0
453 andil #0x80000000,%d0
454 oril #0x00800000,%d0 | ...sign(X)*2^(-126)
455 movel %d0,-(%sp)
456 fmoves #0x3F800000,%fp0
457 fmovel %d1,%fpcr
458 fadds (%sp)+,%fp0
459 bra t_frcinx
460
461 .global setox
462setox:
463|--entry point for EXP(X), here X is finite, non-zero, and not NaN's
464
465|--Step 1.
466 movel (%a0),%d0 | ...load part of input X
467 andil #0x7FFF0000,%d0 | ...biased expo. of X
468 cmpil #0x3FBE0000,%d0 | ...2^(-65)
469 bges EXPC1 | ...normal case
470 bra EXPSM
471
472EXPC1:
473|--The case |X| >= 2^(-65)
474 movew 4(%a0),%d0 | ...expo. and partial sig. of |X|
475 cmpil #0x400CB167,%d0 | ...16380 log2 trunc. 16 bits
476 blts EXPMAIN | ...normal case
477 bra EXPBIG
478
479EXPMAIN:
480|--Step 2.
481|--This is the normal branch: 2^(-65) <= |X| < 16380 log2.
482 fmovex (%a0),%fp0 | ...load input from (a0)
483
484 fmovex %fp0,%fp1
485 fmuls #0x42B8AA3B,%fp0 | ...64/log2 * X
486 fmovemx %fp2-%fp2/%fp3,-(%a7) | ...save fp2
487 movel #0,ADJFLAG(%a6)
488 fmovel %fp0,%d0 | ...N = int( X * 64/log2 )
489 lea EXPTBL,%a1
490 fmovel %d0,%fp0 | ...convert to floating-format
491
492 movel %d0,L_SCR1(%a6) | ...save N temporarily
493 andil #0x3F,%d0 | ...D0 is J = N mod 64
494 lsll #4,%d0
495 addal %d0,%a1 | ...address of 2^(J/64)
496 movel L_SCR1(%a6),%d0
497 asrl #6,%d0 | ...D0 is M
498 addiw #0x3FFF,%d0 | ...biased expo. of 2^(M)
499 movew L2,L_SCR1(%a6) | ...prefetch L2, no need in CB
500
501EXPCONT1:
502|--Step 3.
503|--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
504|--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
505 fmovex %fp0,%fp2
506 fmuls #0xBC317218,%fp0 | ...N * L1, L1 = lead(-log2/64)
507 fmulx L2,%fp2 | ...N * L2, L1+L2 = -log2/64
508 faddx %fp1,%fp0 | ...X + N*L1
509 faddx %fp2,%fp0 | ...fp0 is R, reduced arg.
510| MOVE.W #$3FA5,EXPA3 ...load EXPA3 in cache
511
512|--Step 4.
513|--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
514|-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
515|--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
516|--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
517
518 fmovex %fp0,%fp1
519 fmulx %fp1,%fp1 | ...fp1 IS S = R*R
520
521 fmoves #0x3AB60B70,%fp2 | ...fp2 IS A5
522| MOVE.W #0,2(%a1) ...load 2^(J/64) in cache
523
524 fmulx %fp1,%fp2 | ...fp2 IS S*A5
525 fmovex %fp1,%fp3
526 fmuls #0x3C088895,%fp3 | ...fp3 IS S*A4
527
528 faddd EXPA3,%fp2 | ...fp2 IS A3+S*A5
529 faddd EXPA2,%fp3 | ...fp3 IS A2+S*A4
530
531 fmulx %fp1,%fp2 | ...fp2 IS S*(A3+S*A5)
532 movew %d0,SCALE(%a6) | ...SCALE is 2^(M) in extended
533 clrw SCALE+2(%a6)
534 movel #0x80000000,SCALE+4(%a6)
535 clrl SCALE+8(%a6)
536
537 fmulx %fp1,%fp3 | ...fp3 IS S*(A2+S*A4)
538
539 fadds #0x3F000000,%fp2 | ...fp2 IS A1+S*(A3+S*A5)
540 fmulx %fp0,%fp3 | ...fp3 IS R*S*(A2+S*A4)
541
542 fmulx %fp1,%fp2 | ...fp2 IS S*(A1+S*(A3+S*A5))
543 faddx %fp3,%fp0 | ...fp0 IS R+R*S*(A2+S*A4),
544| ...fp3 released
545
546 fmovex (%a1)+,%fp1 | ...fp1 is lead. pt. of 2^(J/64)
547 faddx %fp2,%fp0 | ...fp0 is EXP(R) - 1
548| ...fp2 released
549
550|--Step 5
551|--final reconstruction process
552|--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
553
554 fmulx %fp1,%fp0 | ...2^(J/64)*(Exp(R)-1)
555 fmovemx (%a7)+,%fp2-%fp2/%fp3 | ...fp2 restored
556 fadds (%a1),%fp0 | ...accurate 2^(J/64)
557
558 faddx %fp1,%fp0 | ...2^(J/64) + 2^(J/64)*...
559 movel ADJFLAG(%a6),%d0
560
561|--Step 6
562 tstl %d0
563 beqs NORMAL
564ADJUST:
565 fmulx ADJSCALE(%a6),%fp0
566NORMAL:
567 fmovel %d1,%FPCR | ...restore user FPCR
568 fmulx SCALE(%a6),%fp0 | ...multiply 2^(M)
569 bra t_frcinx
570
571EXPSM:
572|--Step 7
573 fmovemx (%a0),%fp0-%fp0 | ...in case X is denormalized
574 fmovel %d1,%FPCR
575 fadds #0x3F800000,%fp0 | ...1+X in user mode
576 bra t_frcinx
577
578EXPBIG:
579|--Step 8
580 cmpil #0x400CB27C,%d0 | ...16480 log2
581 bgts EXP2BIG
582|--Steps 8.2 -- 8.6
583 fmovex (%a0),%fp0 | ...load input from (a0)
584
585 fmovex %fp0,%fp1
586 fmuls #0x42B8AA3B,%fp0 | ...64/log2 * X
587 fmovemx %fp2-%fp2/%fp3,-(%a7) | ...save fp2
588 movel #1,ADJFLAG(%a6)
589 fmovel %fp0,%d0 | ...N = int( X * 64/log2 )
590 lea EXPTBL,%a1
591 fmovel %d0,%fp0 | ...convert to floating-format
592 movel %d0,L_SCR1(%a6) | ...save N temporarily
593 andil #0x3F,%d0 | ...D0 is J = N mod 64
594 lsll #4,%d0
595 addal %d0,%a1 | ...address of 2^(J/64)
596 movel L_SCR1(%a6),%d0
597 asrl #6,%d0 | ...D0 is K
598 movel %d0,L_SCR1(%a6) | ...save K temporarily
599 asrl #1,%d0 | ...D0 is M1
600 subl %d0,L_SCR1(%a6) | ...a1 is M
601 addiw #0x3FFF,%d0 | ...biased expo. of 2^(M1)
602 movew %d0,ADJSCALE(%a6) | ...ADJSCALE := 2^(M1)
603 clrw ADJSCALE+2(%a6)
604 movel #0x80000000,ADJSCALE+4(%a6)
605 clrl ADJSCALE+8(%a6)
606 movel L_SCR1(%a6),%d0 | ...D0 is M
607 addiw #0x3FFF,%d0 | ...biased expo. of 2^(M)
608 bra EXPCONT1 | ...go back to Step 3
609
610EXP2BIG:
611|--Step 9
612 fmovel %d1,%FPCR
613 movel (%a0),%d0
614 bclrb #sign_bit,(%a0) | ...setox always returns positive
615 cmpil #0,%d0
616 blt t_unfl
617 bra t_ovfl
618
619 .global setoxm1d
620setoxm1d:
621|--entry point for EXPM1(X), here X is denormalized
622|--Step 0.
623 bra t_extdnrm
624
625
626 .global setoxm1
627setoxm1:
628|--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
629
630|--Step 1.
631|--Step 1.1
632 movel (%a0),%d0 | ...load part of input X
633 andil #0x7FFF0000,%d0 | ...biased expo. of X
634 cmpil #0x3FFD0000,%d0 | ...1/4
635 bges EM1CON1 | ...|X| >= 1/4
636 bra EM1SM
637
638EM1CON1:
639|--Step 1.3
640|--The case |X| >= 1/4
641 movew 4(%a0),%d0 | ...expo. and partial sig. of |X|
642 cmpil #0x4004C215,%d0 | ...70log2 rounded up to 16 bits
643 bles EM1MAIN | ...1/4 <= |X| <= 70log2
644 bra EM1BIG
645
646EM1MAIN:
647|--Step 2.
648|--This is the case: 1/4 <= |X| <= 70 log2.
649 fmovex (%a0),%fp0 | ...load input from (a0)
650
651 fmovex %fp0,%fp1
652 fmuls #0x42B8AA3B,%fp0 | ...64/log2 * X
653 fmovemx %fp2-%fp2/%fp3,-(%a7) | ...save fp2
654| MOVE.W #$3F81,EM1A4 ...prefetch in CB mode
655 fmovel %fp0,%d0 | ...N = int( X * 64/log2 )
656 lea EXPTBL,%a1
657 fmovel %d0,%fp0 | ...convert to floating-format
658
659 movel %d0,L_SCR1(%a6) | ...save N temporarily
660 andil #0x3F,%d0 | ...D0 is J = N mod 64
661 lsll #4,%d0
662 addal %d0,%a1 | ...address of 2^(J/64)
663 movel L_SCR1(%a6),%d0
664 asrl #6,%d0 | ...D0 is M
665 movel %d0,L_SCR1(%a6) | ...save a copy of M
666| MOVE.W #$3FDC,L2 ...prefetch L2 in CB mode
667
668|--Step 3.
669|--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
670|--a0 points to 2^(J/64), D0 and a1 both contain M
671 fmovex %fp0,%fp2
672 fmuls #0xBC317218,%fp0 | ...N * L1, L1 = lead(-log2/64)
673 fmulx L2,%fp2 | ...N * L2, L1+L2 = -log2/64
674 faddx %fp1,%fp0 | ...X + N*L1
675 faddx %fp2,%fp0 | ...fp0 is R, reduced arg.
676| MOVE.W #$3FC5,EM1A2 ...load EM1A2 in cache
677 addiw #0x3FFF,%d0 | ...D0 is biased expo. of 2^M
678
679|--Step 4.
680|--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
681|-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
682|--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
683|--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
684
685 fmovex %fp0,%fp1
686 fmulx %fp1,%fp1 | ...fp1 IS S = R*R
687
688 fmoves #0x3950097B,%fp2 | ...fp2 IS a6
689| MOVE.W #0,2(%a1) ...load 2^(J/64) in cache
690
691 fmulx %fp1,%fp2 | ...fp2 IS S*A6
692 fmovex %fp1,%fp3
693 fmuls #0x3AB60B6A,%fp3 | ...fp3 IS S*A5
694
695 faddd EM1A4,%fp2 | ...fp2 IS A4+S*A6
696 faddd EM1A3,%fp3 | ...fp3 IS A3+S*A5
697 movew %d0,SC(%a6) | ...SC is 2^(M) in extended
698 clrw SC+2(%a6)
699 movel #0x80000000,SC+4(%a6)
700 clrl SC+8(%a6)
701
702 fmulx %fp1,%fp2 | ...fp2 IS S*(A4+S*A6)
703 movel L_SCR1(%a6),%d0 | ...D0 is M
704 negw %d0 | ...D0 is -M
705 fmulx %fp1,%fp3 | ...fp3 IS S*(A3+S*A5)
706 addiw #0x3FFF,%d0 | ...biased expo. of 2^(-M)
707 faddd EM1A2,%fp2 | ...fp2 IS A2+S*(A4+S*A6)
708 fadds #0x3F000000,%fp3 | ...fp3 IS A1+S*(A3+S*A5)
709
710 fmulx %fp1,%fp2 | ...fp2 IS S*(A2+S*(A4+S*A6))
711 oriw #0x8000,%d0 | ...signed/expo. of -2^(-M)
712 movew %d0,ONEBYSC(%a6) | ...OnebySc is -2^(-M)
713 clrw ONEBYSC+2(%a6)
714 movel #0x80000000,ONEBYSC+4(%a6)
715 clrl ONEBYSC+8(%a6)
716 fmulx %fp3,%fp1 | ...fp1 IS S*(A1+S*(A3+S*A5))
717| ...fp3 released
718
719 fmulx %fp0,%fp2 | ...fp2 IS R*S*(A2+S*(A4+S*A6))
720 faddx %fp1,%fp0 | ...fp0 IS R+S*(A1+S*(A3+S*A5))
721| ...fp1 released
722
723 faddx %fp2,%fp0 | ...fp0 IS EXP(R)-1
724| ...fp2 released
725 fmovemx (%a7)+,%fp2-%fp2/%fp3 | ...fp2 restored
726
727|--Step 5
728|--Compute 2^(J/64)*p
729
730 fmulx (%a1),%fp0 | ...2^(J/64)*(Exp(R)-1)
731
732|--Step 6
733|--Step 6.1
734 movel L_SCR1(%a6),%d0 | ...retrieve M
735 cmpil #63,%d0
736 bles MLE63
737|--Step 6.2 M >= 64
738 fmoves 12(%a1),%fp1 | ...fp1 is t
739 faddx ONEBYSC(%a6),%fp1 | ...fp1 is t+OnebySc
740 faddx %fp1,%fp0 | ...p+(t+OnebySc), fp1 released
741 faddx (%a1),%fp0 | ...T+(p+(t+OnebySc))
742 bras EM1SCALE
743MLE63:
744|--Step 6.3 M <= 63
745 cmpil #-3,%d0
746 bges MGEN3
747MLTN3:
748|--Step 6.4 M <= -4
749 fadds 12(%a1),%fp0 | ...p+t
750 faddx (%a1),%fp0 | ...T+(p+t)
751 faddx ONEBYSC(%a6),%fp0 | ...OnebySc + (T+(p+t))
752 bras EM1SCALE
753MGEN3:
754|--Step 6.5 -3 <= M <= 63
755 fmovex (%a1)+,%fp1 | ...fp1 is T
756 fadds (%a1),%fp0 | ...fp0 is p+t
757 faddx ONEBYSC(%a6),%fp1 | ...fp1 is T+OnebySc
758 faddx %fp1,%fp0 | ...(T+OnebySc)+(p+t)
759
760EM1SCALE:
761|--Step 6.6
762 fmovel %d1,%FPCR
763 fmulx SC(%a6),%fp0
764
765 bra t_frcinx
766
767EM1SM:
768|--Step 7 |X| < 1/4.
769 cmpil #0x3FBE0000,%d0 | ...2^(-65)
770 bges EM1POLY
771
772EM1TINY:
773|--Step 8 |X| < 2^(-65)
774 cmpil #0x00330000,%d0 | ...2^(-16312)
775 blts EM12TINY
776|--Step 8.2
777 movel #0x80010000,SC(%a6) | ...SC is -2^(-16382)
778 movel #0x80000000,SC+4(%a6)
779 clrl SC+8(%a6)
780 fmovex (%a0),%fp0
781 fmovel %d1,%FPCR
782 faddx SC(%a6),%fp0
783
784 bra t_frcinx
785
786EM12TINY:
787|--Step 8.3
788 fmovex (%a0),%fp0
789 fmuld TWO140,%fp0
790 movel #0x80010000,SC(%a6)
791 movel #0x80000000,SC+4(%a6)
792 clrl SC+8(%a6)
793 faddx SC(%a6),%fp0
794 fmovel %d1,%FPCR
795 fmuld TWON140,%fp0
796
797 bra t_frcinx
798
799EM1POLY:
800|--Step 9 exp(X)-1 by a simple polynomial
801 fmovex (%a0),%fp0 | ...fp0 is X
802 fmulx %fp0,%fp0 | ...fp0 is S := X*X
803 fmovemx %fp2-%fp2/%fp3,-(%a7) | ...save fp2
804 fmoves #0x2F30CAA8,%fp1 | ...fp1 is B12
805 fmulx %fp0,%fp1 | ...fp1 is S*B12
806 fmoves #0x310F8290,%fp2 | ...fp2 is B11
807 fadds #0x32D73220,%fp1 | ...fp1 is B10+S*B12
808
809 fmulx %fp0,%fp2 | ...fp2 is S*B11
810 fmulx %fp0,%fp1 | ...fp1 is S*(B10 + ...
811
812 fadds #0x3493F281,%fp2 | ...fp2 is B9+S*...
813 faddd EM1B8,%fp1 | ...fp1 is B8+S*...
814
815 fmulx %fp0,%fp2 | ...fp2 is S*(B9+...
816 fmulx %fp0,%fp1 | ...fp1 is S*(B8+...
817
818 faddd EM1B7,%fp2 | ...fp2 is B7+S*...
819 faddd EM1B6,%fp1 | ...fp1 is B6+S*...
820
821 fmulx %fp0,%fp2 | ...fp2 is S*(B7+...
822 fmulx %fp0,%fp1 | ...fp1 is S*(B6+...
823
824 faddd EM1B5,%fp2 | ...fp2 is B5+S*...
825 faddd EM1B4,%fp1 | ...fp1 is B4+S*...
826
827 fmulx %fp0,%fp2 | ...fp2 is S*(B5+...
828 fmulx %fp0,%fp1 | ...fp1 is S*(B4+...
829
830 faddd EM1B3,%fp2 | ...fp2 is B3+S*...
831 faddx EM1B2,%fp1 | ...fp1 is B2+S*...
832
833 fmulx %fp0,%fp2 | ...fp2 is S*(B3+...
834 fmulx %fp0,%fp1 | ...fp1 is S*(B2+...
835
836 fmulx %fp0,%fp2 | ...fp2 is S*S*(B3+...)
837 fmulx (%a0),%fp1 | ...fp1 is X*S*(B2...
838
839 fmuls #0x3F000000,%fp0 | ...fp0 is S*B1
840 faddx %fp2,%fp1 | ...fp1 is Q
841| ...fp2 released
842
843 fmovemx (%a7)+,%fp2-%fp2/%fp3 | ...fp2 restored
844
845 faddx %fp1,%fp0 | ...fp0 is S*B1+Q
846| ...fp1 released
847
848 fmovel %d1,%FPCR
849 faddx (%a0),%fp0
850
851 bra t_frcinx
852
853EM1BIG:
854|--Step 10 |X| > 70 log2
855 movel (%a0),%d0
856 cmpil #0,%d0
857 bgt EXPC1
858|--Step 10.2
859 fmoves #0xBF800000,%fp0 | ...fp0 is -1
860 fmovel %d1,%FPCR
861 fadds #0x00800000,%fp0 | ...-1 + 2^(-126)
862
863 bra t_frcinx
864
865 |end
diff --git a/arch/m68k/fpsp040/sgetem.S b/arch/m68k/fpsp040/sgetem.S
new file mode 100644
index 000000000000..0fcbd045ba75
--- /dev/null
+++ b/arch/m68k/fpsp040/sgetem.S
@@ -0,0 +1,141 @@
1|
2| sgetem.sa 3.1 12/10/90
3|
4| The entry point sGETEXP returns the exponent portion
5| of the input argument. The exponent bias is removed
6| and the exponent value is returned as an extended
7| precision number in fp0. sGETEXPD handles denormalized
8| numbers.
9|
10| The entry point sGETMAN extracts the mantissa of the
11| input argument. The mantissa is converted to an
12| extended precision number and returned in fp0. The
13| range of the result is [1.0 - 2.0).
14|
15|
16| Input: Double-extended number X in the ETEMP space in
17| the floating-point save stack.
18|
19| Output: The functions return exp(X) or man(X) in fp0.
20|
21| Modified: fp0.
22|
23|
24| Copyright (C) Motorola, Inc. 1990
25| All Rights Reserved
26|
27| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
28| The copyright notice above does not evidence any
29| actual or intended publication of such source code.
30
31|SGETEM idnt 2,1 | Motorola 040 Floating Point Software Package
32
33 |section 8
34
35#include "fpsp.h"
36
37 |xref nrm_set
38
39|
40| This entry point is used by the unimplemented instruction exception
41| handler. It points a0 to the input operand.
42|
43|
44|
45| SGETEXP
46|
47
48 .global sgetexp
49sgetexp:
50 movew LOCAL_EX(%a0),%d0 |get the exponent
51 bclrl #15,%d0 |clear the sign bit
52 subw #0x3fff,%d0 |subtract off the bias
53 fmovew %d0,%fp0 |move the exp to fp0
54 rts
55
56 .global sgetexpd
57sgetexpd:
58 bclrb #sign_bit,LOCAL_EX(%a0)
59 bsr nrm_set |normalize (exp will go negative)
60 movew LOCAL_EX(%a0),%d0 |load resulting exponent into d0
61 subw #0x3fff,%d0 |subtract off the bias
62 fmovew %d0,%fp0 |move the exp to fp0
63 rts
64|
65|
66| This entry point is used by the unimplemented instruction exception
67| handler. It points a0 to the input operand.
68|
69|
70|
71| SGETMAN
72|
73|
74| For normalized numbers, leave the mantissa alone, simply load
75| with an exponent of +/- $3fff.
76|
77 .global sgetman
78sgetman:
79 movel USER_FPCR(%a6),%d0
80 andil #0xffffff00,%d0 |clear rounding precision and mode
81 fmovel %d0,%fpcr |this fpcr setting is used by the 882
82 movew LOCAL_EX(%a0),%d0 |get the exp (really just want sign bit)
83 orw #0x7fff,%d0 |clear old exp
84 bclrl #14,%d0 |make it the new exp +-3fff
85 movew %d0,LOCAL_EX(%a0) |move the sign & exp back to fsave stack
86 fmovex (%a0),%fp0 |put new value back in fp0
87 rts
88
89|
90| For denormalized numbers, shift the mantissa until the j-bit = 1,
91| then load the exponent with +/1 $3fff.
92|
93 .global sgetmand
94sgetmand:
95 movel LOCAL_HI(%a0),%d0 |load ms mant in d0
96 movel LOCAL_LO(%a0),%d1 |load ls mant in d1
97 bsr shft |shift mantissa bits till msbit is set
98 movel %d0,LOCAL_HI(%a0) |put ms mant back on stack
99 movel %d1,LOCAL_LO(%a0) |put ls mant back on stack
100 bras sgetman
101
102|
103| SHFT
104|
105| Shifts the mantissa bits until msbit is set.
106| input:
107| ms mantissa part in d0
108| ls mantissa part in d1
109| output:
110| shifted bits in d0 and d1
111shft:
112 tstl %d0 |if any bits set in ms mant
113 bnes upper |then branch
114| ;else no bits set in ms mant
115 tstl %d1 |test if any bits set in ls mant
116 bnes cont |if set then continue
117 bras shft_end |else return
118cont:
119 movel %d3,-(%a7) |save d3
120 exg %d0,%d1 |shift ls mant to ms mant
121 bfffo %d0{#0:#32},%d3 |find first 1 in ls mant to d0
122 lsll %d3,%d0 |shift first 1 to integer bit in ms mant
123 movel (%a7)+,%d3 |restore d3
124 bras shft_end
125upper:
126
127 moveml %d3/%d5/%d6,-(%a7) |save registers
128 bfffo %d0{#0:#32},%d3 |find first 1 in ls mant to d0
129 lsll %d3,%d0 |shift ms mant until j-bit is set
130 movel %d1,%d6 |save ls mant in d6
131 lsll %d3,%d1 |shift ls mant by count
132 movel #32,%d5
133 subl %d3,%d5 |sub 32 from shift for ls mant
134 lsrl %d5,%d6 |shift off all bits but those that will
135| ;be shifted into ms mant
136 orl %d6,%d0 |shift the ls mant bits into the ms mant
137 moveml (%a7)+,%d3/%d5/%d6 |restore registers
138shft_end:
139 rts
140
141 |end
diff --git a/arch/m68k/fpsp040/sint.S b/arch/m68k/fpsp040/sint.S
new file mode 100644
index 000000000000..0f9bd28e55a0
--- /dev/null
+++ b/arch/m68k/fpsp040/sint.S
@@ -0,0 +1,247 @@
1|
2| sint.sa 3.1 12/10/90
3|
4| The entry point sINT computes the rounded integer
5| equivalent of the input argument, sINTRZ computes
6| the integer rounded to zero of the input argument.
7|
8| Entry points sint and sintrz are called from do_func
9| to emulate the fint and fintrz unimplemented instructions,
10| respectively. Entry point sintdo is used by bindec.
11|
12| Input: (Entry points sint and sintrz) Double-extended
13| number X in the ETEMP space in the floating-point
14| save stack.
15| (Entry point sintdo) Double-extended number X in
16| location pointed to by the address register a0.
17| (Entry point sintd) Double-extended denormalized
18| number X in the ETEMP space in the floating-point
19| save stack.
20|
21| Output: The function returns int(X) or intrz(X) in fp0.
22|
23| Modifies: fp0.
24|
25| Algorithm: (sint and sintrz)
26|
27| 1. If exp(X) >= 63, return X.
28| If exp(X) < 0, return +/- 0 or +/- 1, according to
29| the rounding mode.
30|
31| 2. (X is in range) set rsc = 63 - exp(X). Unnormalize the
32| result to the exponent $403e.
33|
34| 3. Round the result in the mode given in USER_FPCR. For
35| sintrz, force round-to-zero mode.
36|
37| 4. Normalize the rounded result; store in fp0.
38|
39| For the denormalized cases, force the correct result
40| for the given sign and rounding mode.
41|
42| Sign(X)
43| RMODE + -
44| ----- --------
45| RN +0 -0
46| RZ +0 -0
47| RM +0 -1
48| RP +1 -0
49|
50|
51| Copyright (C) Motorola, Inc. 1990
52| All Rights Reserved
53|
54| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
55| The copyright notice above does not evidence any
56| actual or intended publication of such source code.
57
58|SINT idnt 2,1 | Motorola 040 Floating Point Software Package
59
60 |section 8
61
62#include "fpsp.h"
63
64 |xref dnrm_lp
65 |xref nrm_set
66 |xref round
67 |xref t_inx2
68 |xref ld_pone
69 |xref ld_mone
70 |xref ld_pzero
71 |xref ld_mzero
72 |xref snzrinx
73
74|
75| FINT
76|
77 .global sint
78sint:
79 bfextu FPCR_MODE(%a6){#2:#2},%d1 |use user's mode for rounding
80| ;implicitly has extend precision
81| ;in upper word.
82 movel %d1,L_SCR1(%a6) |save mode bits
83 bras sintexc
84
85|
86| FINT with extended denorm inputs.
87|
88 .global sintd
89sintd:
90 btstb #5,FPCR_MODE(%a6)
91 beq snzrinx |if round nearest or round zero, +/- 0
92 btstb #4,FPCR_MODE(%a6)
93 beqs rnd_mns
94rnd_pls:
95 btstb #sign_bit,LOCAL_EX(%a0)
96 bnes sintmz
97 bsr ld_pone |if round plus inf and pos, answer is +1
98 bra t_inx2
99rnd_mns:
100 btstb #sign_bit,LOCAL_EX(%a0)
101 beqs sintpz
102 bsr ld_mone |if round mns inf and neg, answer is -1
103 bra t_inx2
104sintpz:
105 bsr ld_pzero
106 bra t_inx2
107sintmz:
108 bsr ld_mzero
109 bra t_inx2
110
111|
112| FINTRZ
113|
114 .global sintrz
115sintrz:
116 movel #1,L_SCR1(%a6) |use rz mode for rounding
117| ;implicitly has extend precision
118| ;in upper word.
119 bras sintexc
120|
121| SINTDO
122|
123| Input: a0 points to an IEEE extended format operand
124| Output: fp0 has the result
125|
126| Exceptions:
127|
128| If the subroutine results in an inexact operation, the inx2 and
129| ainx bits in the USER_FPSR are set.
130|
131|
132 .global sintdo
133sintdo:
134 bfextu FPCR_MODE(%a6){#2:#2},%d1 |use user's mode for rounding
135| ;implicitly has ext precision
136| ;in upper word.
137 movel %d1,L_SCR1(%a6) |save mode bits
138|
139| Real work of sint is in sintexc
140|
141sintexc:
142 bclrb #sign_bit,LOCAL_EX(%a0) |convert to internal extended
143| ;format
144 sne LOCAL_SGN(%a0)
145 cmpw #0x403e,LOCAL_EX(%a0) |check if (unbiased) exp > 63
146 bgts out_rnge |branch if exp < 63
147 cmpw #0x3ffd,LOCAL_EX(%a0) |check if (unbiased) exp < 0
148 bgt in_rnge |if 63 >= exp > 0, do calc
149|
150| Input is less than zero. Restore sign, and check for directed
151| rounding modes. L_SCR1 contains the rmode in the lower byte.
152|
153un_rnge:
154 btstb #1,L_SCR1+3(%a6) |check for rn and rz
155 beqs un_rnrz
156 tstb LOCAL_SGN(%a0) |check for sign
157 bnes un_rmrp_neg
158|
159| Sign is +. If rp, load +1.0, if rm, load +0.0
160|
161 cmpib #3,L_SCR1+3(%a6) |check for rp
162 beqs un_ldpone |if rp, load +1.0
163 bsr ld_pzero |if rm, load +0.0
164 bra t_inx2
165un_ldpone:
166 bsr ld_pone
167 bra t_inx2
168|
169| Sign is -. If rm, load -1.0, if rp, load -0.0
170|
171un_rmrp_neg:
172 cmpib #2,L_SCR1+3(%a6) |check for rm
173 beqs un_ldmone |if rm, load -1.0
174 bsr ld_mzero |if rp, load -0.0
175 bra t_inx2
176un_ldmone:
177 bsr ld_mone
178 bra t_inx2
179|
180| Rmode is rn or rz; return signed zero
181|
182un_rnrz:
183 tstb LOCAL_SGN(%a0) |check for sign
184 bnes un_rnrz_neg
185 bsr ld_pzero
186 bra t_inx2
187un_rnrz_neg:
188 bsr ld_mzero
189 bra t_inx2
190
191|
192| Input is greater than 2^63. All bits are significant. Return
193| the input.
194|
195out_rnge:
196 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
197 beqs intps
198 bsetb #sign_bit,LOCAL_EX(%a0)
199intps:
200 fmovel %fpcr,-(%sp)
201 fmovel #0,%fpcr
202 fmovex LOCAL_EX(%a0),%fp0 |if exp > 63
203| ;then return X to the user
204| ;there are no fraction bits
205 fmovel (%sp)+,%fpcr
206 rts
207
208in_rnge:
209| ;shift off fraction bits
210 clrl %d0 |clear d0 - initial g,r,s for
211| ;dnrm_lp
212 movel #0x403e,%d1 |set threshold for dnrm_lp
213| ;assumes a0 points to operand
214 bsr dnrm_lp
215| ;returns unnormalized number
216| ;pointed by a0
217| ;output d0 supplies g,r,s
218| ;used by round
219 movel L_SCR1(%a6),%d1 |use selected rounding mode
220|
221|
222 bsr round |round the unnorm based on users
223| ;input a0 ptr to ext X
224| ; d0 g,r,s bits
225| ; d1 PREC/MODE info
226| ;output a0 ptr to rounded result
227| ;inexact flag set in USER_FPSR
228| ;if initial grs set
229|
230| normalize the rounded result and store value in fp0
231|
232 bsr nrm_set |normalize the unnorm
233| ;Input: a0 points to operand to
234| ;be normalized
235| ;Output: a0 points to normalized
236| ;result
237 bfclr LOCAL_SGN(%a0){#0:#8}
238 beqs nrmrndp
239 bsetb #sign_bit,LOCAL_EX(%a0) |return to IEEE extended format
240nrmrndp:
241 fmovel %fpcr,-(%sp)
242 fmovel #0,%fpcr
243 fmovex LOCAL_EX(%a0),%fp0 |move result to fp0
244 fmovel (%sp)+,%fpcr
245 rts
246
247 |end
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S
new file mode 100644
index 000000000000..dbc1255a5e99
--- /dev/null
+++ b/arch/m68k/fpsp040/skeleton.S
@@ -0,0 +1,516 @@
1|
2| skeleton.sa 3.2 4/26/91
3|
4| This file contains code that is system dependent and will
5| need to be modified to install the FPSP.
6|
7| Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
8| Put any target system specific handling that must be done immediately
9| before the jump instruction. If there no handling necessary, then
10| the 'fpsp_xxxx' handler entry point should be placed in the exception
11| table so that the 'jmp' can be eliminated. If the FPSP determines that the
12| exception is one that must be reported then there will be a
13| return from the package by a 'jmp real_xxxx'. At that point
14| the machine state will be identical to the state before
15| the FPSP was entered. In particular, whatever condition
16| that caused the exception will still be pending when the FPSP
17| package returns. Thus, there will be system specific code
18| to handle the exception.
19|
20| If the exception was completely handled by the package, then
21| the return will be via a 'jmp fpsp_done'. Unless there is
22| OS specific work to be done (such as handling a context switch or
23| interrupt) the user program can be resumed via 'rte'.
24|
25| In the following skeleton code, some typical 'real_xxxx' handling
26| code is shown. This code may need to be moved to an appropriate
27| place in the target system, or rewritten.
28|
29
30| Copyright (C) Motorola, Inc. 1990
31| All Rights Reserved
32|
33| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
34| The copyright notice above does not evidence any
35| actual or intended publication of such source code.
36
37|
38| Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
39|
40
41#include <linux/linkage.h>
42#include <asm/entry.h>
43#include <asm/offsets.h>
44
45|SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package
46
47 |section 15
48|
49| The following counters are used for standalone testing
50|
51
52 |section 8
53
54#include "fpsp.h"
55
56 |xref b1238_fix
57
58|
59| Divide by Zero exception
60|
61| All dz exceptions are 'real', hence no fpsp_dz entry point.
62|
63 .global dz
64 .global real_dz
65dz:
66real_dz:
67 link %a6,#-LOCAL_SIZE
68 fsave -(%sp)
69 bclrb #E1,E_BYTE(%a6)
70 frestore (%sp)+
71 unlk %a6
72
73 SAVE_ALL_INT
74 GET_CURRENT(%d0)
75 movel %sp,%sp@- | stack frame pointer argument
76 bsrl trap_c
77 addql #4,%sp
78 bral ret_from_exception
79
80|
81| Inexact exception
82|
83| All inexact exceptions are real, but the 'real' handler
84| will probably want to clear the pending exception.
85| The provided code will clear the E3 exception (if pending),
86| otherwise clear the E1 exception. The frestore is not really
87| necessary for E1 exceptions.
88|
89| Code following the 'inex' label is to handle bug #1232. In this
90| bug, if an E1 snan, ovfl, or unfl occurred, and the process was
91| swapped out before taking the exception, the exception taken on
92| return was inex, rather than the correct exception. The snan, ovfl,
93| and unfl exception to be taken must not have been enabled. The
94| fix is to check for E1, and the existence of one of snan, ovfl,
95| or unfl bits set in the fpsr. If any of these are set, branch
96| to the appropriate handler for the exception in the fpsr. Note
97| that this fix is only for d43b parts, and is skipped if the
98| version number is not $40.
99|
100|
101 .global real_inex
102 .global inex
103inex:
104 link %a6,#-LOCAL_SIZE
105 fsave -(%sp)
106 cmpib #VER_40,(%sp) |test version number
107 bnes not_fmt40
108 fmovel %fpsr,-(%sp)
109 btstb #E1,E_BYTE(%a6) |test for E1 set
110 beqs not_b1232
111 btstb #snan_bit,2(%sp) |test for snan
112 beq inex_ckofl
113 addl #4,%sp
114 frestore (%sp)+
115 unlk %a6
116 bra snan
117inex_ckofl:
118 btstb #ovfl_bit,2(%sp) |test for ovfl
119 beq inex_ckufl
120 addl #4,%sp
121 frestore (%sp)+
122 unlk %a6
123 bra ovfl
124inex_ckufl:
125 btstb #unfl_bit,2(%sp) |test for unfl
126 beq not_b1232
127 addl #4,%sp
128 frestore (%sp)+
129 unlk %a6
130 bra unfl
131
132|
133| We do not have the bug 1232 case. Clean up the stack and call
134| real_inex.
135|
136not_b1232:
137 addl #4,%sp
138 frestore (%sp)+
139 unlk %a6
140
141real_inex:
142
143 link %a6,#-LOCAL_SIZE
144 fsave -(%sp)
145not_fmt40:
146 bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
147 beqs inex_cke1
148|
149| Clear dirty bit on dest resister in the frame before branching
150| to b1238_fix.
151|
152 moveml %d0/%d1,USER_DA(%a6)
153 bfextu CMDREG1B(%a6){#6:#3},%d0 |get dest reg no
154 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
155 bsrl b1238_fix |test for bug1238 case
156 moveml USER_DA(%a6),%d0/%d1
157 bras inex_done
158inex_cke1:
159 bclrb #E1,E_BYTE(%a6)
160inex_done:
161 frestore (%sp)+
162 unlk %a6
163
164 SAVE_ALL_INT
165 GET_CURRENT(%d0)
166 movel %sp,%sp@- | stack frame pointer argument
167 bsrl trap_c
168 addql #4,%sp
169 bral ret_from_exception
170
171|
172| Overflow exception
173|
174 |xref fpsp_ovfl
175 .global real_ovfl
176 .global ovfl
177ovfl:
178 jmp fpsp_ovfl
179real_ovfl:
180
181 link %a6,#-LOCAL_SIZE
182 fsave -(%sp)
183 bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
184 bnes ovfl_done
185 bclrb #E1,E_BYTE(%a6)
186ovfl_done:
187 frestore (%sp)+
188 unlk %a6
189
190 SAVE_ALL_INT
191 GET_CURRENT(%d0)
192 movel %sp,%sp@- | stack frame pointer argument
193 bsrl trap_c
194 addql #4,%sp
195 bral ret_from_exception
196
197|
198| Underflow exception
199|
200 |xref fpsp_unfl
201 .global real_unfl
202 .global unfl
203unfl:
204 jmp fpsp_unfl
205real_unfl:
206
207 link %a6,#-LOCAL_SIZE
208 fsave -(%sp)
209 bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
210 bnes unfl_done
211 bclrb #E1,E_BYTE(%a6)
212unfl_done:
213 frestore (%sp)+
214 unlk %a6
215
216 SAVE_ALL_INT
217 GET_CURRENT(%d0)
218 movel %sp,%sp@- | stack frame pointer argument
219 bsrl trap_c
220 addql #4,%sp
221 bral ret_from_exception
222
223|
224| Signalling NAN exception
225|
226 |xref fpsp_snan
227 .global real_snan
228 .global snan
229snan:
230 jmp fpsp_snan
231real_snan:
232 link %a6,#-LOCAL_SIZE
233 fsave -(%sp)
234 bclrb #E1,E_BYTE(%a6) |snan is always an E1 exception
235 frestore (%sp)+
236 unlk %a6
237
238 SAVE_ALL_INT
239 GET_CURRENT(%d0)
240 movel %sp,%sp@- | stack frame pointer argument
241 bsrl trap_c
242 addql #4,%sp
243 bral ret_from_exception
244
245|
246| Operand Error exception
247|
248 |xref fpsp_operr
249 .global real_operr
250 .global operr
251operr:
252 jmp fpsp_operr
253real_operr:
254 link %a6,#-LOCAL_SIZE
255 fsave -(%sp)
256 bclrb #E1,E_BYTE(%a6) |operr is always an E1 exception
257 frestore (%sp)+
258 unlk %a6
259
260 SAVE_ALL_INT
261 GET_CURRENT(%d0)
262 movel %sp,%sp@- | stack frame pointer argument
263 bsrl trap_c
264 addql #4,%sp
265 bral ret_from_exception
266
267
268|
269| BSUN exception
270|
271| This sample handler simply clears the nan bit in the FPSR.
272|
273 |xref fpsp_bsun
274 .global real_bsun
275 .global bsun
276bsun:
277 jmp fpsp_bsun
278real_bsun:
279 link %a6,#-LOCAL_SIZE
280 fsave -(%sp)
281 bclrb #E1,E_BYTE(%a6) |bsun is always an E1 exception
282 fmovel %FPSR,-(%sp)
283 bclrb #nan_bit,(%sp)
284 fmovel (%sp)+,%FPSR
285 frestore (%sp)+
286 unlk %a6
287
288 SAVE_ALL_INT
289 GET_CURRENT(%d0)
290 movel %sp,%sp@- | stack frame pointer argument
291 bsrl trap_c
292 addql #4,%sp
293 bral ret_from_exception
294
295|
296| F-line exception
297|
298| A 'real' F-line exception is one that the FPSP isn't supposed to
299| handle. E.g. an instruction with a co-processor ID that is not 1.
300|
301|
302 |xref fpsp_fline
303 .global real_fline
304 .global fline
305fline:
306 jmp fpsp_fline
307real_fline:
308
309 SAVE_ALL_INT
310 GET_CURRENT(%d0)
311 movel %sp,%sp@- | stack frame pointer argument
312 bsrl trap_c
313 addql #4,%sp
314 bral ret_from_exception
315
316|
317| Unsupported data type exception
318|
319 |xref fpsp_unsupp
320 .global real_unsupp
321 .global unsupp
322unsupp:
323 jmp fpsp_unsupp
324real_unsupp:
325 link %a6,#-LOCAL_SIZE
326 fsave -(%sp)
327 bclrb #E1,E_BYTE(%a6) |unsupp is always an E1 exception
328 frestore (%sp)+
329 unlk %a6
330
331 SAVE_ALL_INT
332 GET_CURRENT(%d0)
333 movel %sp,%sp@- | stack frame pointer argument
334 bsrl trap_c
335 addql #4,%sp
336 bral ret_from_exception
337
338|
339| Trace exception
340|
341 .global real_trace
342real_trace:
343 |
344 bral trap
345
346|
347| fpsp_fmt_error --- exit point for frame format error
348|
349| The fpu stack frame does not match the frames existing
350| or planned at the time of this writing. The fpsp is
351| unable to handle frame sizes not in the following
352| version:size pairs:
353|
354| {4060, 4160} - busy frame
355| {4028, 4130} - unimp frame
356| {4000, 4100} - idle frame
357|
358| This entry point simply holds an f-line illegal value.
359| Replace this with a call to your kernel panic code or
360| code to handle future revisions of the fpu.
361|
362 .global fpsp_fmt_error
363fpsp_fmt_error:
364
365 .long 0xf27f0000 |f-line illegal
366
367|
368| fpsp_done --- FPSP exit point
369|
370| The exception has been handled by the package and we are ready
371| to return to user mode, but there may be OS specific code
372| to execute before we do. If there is, do it now.
373|
374|
375
376 .global fpsp_done
377fpsp_done:
378 btst #0x5,%sp@ | supervisor bit set in saved SR?
379 beq .Lnotkern
380 rte
381.Lnotkern:
382 SAVE_ALL_INT
383 GET_CURRENT(%d0)
384 tstb %curptr@(TASK_NEEDRESCHED)
385 jne ret_from_exception | deliver signals,
386 | reschedule etc..
387 RESTORE_ALL
388
389|
390| mem_write --- write to user or supervisor address space
391|
392| Writes to memory while in supervisor mode. copyout accomplishes
393| this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function.
394| If you don't have copyout, use the local copy of the function below.
395|
396| a0 - supervisor source address
397| a1 - user destination address
398| d0 - number of bytes to write (maximum count is 12)
399|
400| The supervisor source address is guaranteed to point into the supervisor
401| stack. The result is that a UNIX
402| process is allowed to sleep as a consequence of a page fault during
403| copyout. The probability of a page fault is exceedingly small because
404| the 68040 always reads the destination address and thus the page
405| faults should have already been handled.
406|
407| If the EXC_SR shows that the exception was from supervisor space,
408| then just do a dumb (and slow) memory move. In a UNIX environment
409| there shouldn't be any supervisor mode floating point exceptions.
410|
411 .global mem_write
412mem_write:
413 btstb #5,EXC_SR(%a6) |check for supervisor state
414 beqs user_write
415super_write:
416 moveb (%a0)+,(%a1)+
417 subql #1,%d0
418 bnes super_write
419 rts
420user_write:
421 movel %d1,-(%sp) |preserve d1 just in case
422 movel %d0,-(%sp)
423 movel %a1,-(%sp)
424 movel %a0,-(%sp)
425 jsr copyout
426 addw #12,%sp
427 movel (%sp)+,%d1
428 rts
429|
430| mem_read --- read from user or supervisor address space
431|
432| Reads from memory while in supervisor mode. copyin accomplishes
433| this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function.
434| If you don't have copyin, use the local copy of the function below.
435|
436| The FPSP calls mem_read to read the original F-line instruction in order
437| to extract the data register number when the 'Dn' addressing mode is
438| used.
439|
440|Input:
441| a0 - user source address
442| a1 - supervisor destination address
443| d0 - number of bytes to read (maximum count is 12)
444|
445| Like mem_write, mem_read always reads with a supervisor
446| destination address on the supervisor stack. Also like mem_write,
447| the EXC_SR is checked and a simple memory copy is done if reading
448| from supervisor space is indicated.
449|
450 .global mem_read
451mem_read:
452 btstb #5,EXC_SR(%a6) |check for supervisor state
453 beqs user_read
454super_read:
455 moveb (%a0)+,(%a1)+
456 subql #1,%d0
457 bnes super_read
458 rts
459user_read:
460 movel %d1,-(%sp) |preserve d1 just in case
461 movel %d0,-(%sp)
462 movel %a1,-(%sp)
463 movel %a0,-(%sp)
464 jsr copyin
465 addw #12,%sp
466 movel (%sp)+,%d1
467 rts
468
469|
470| Use these routines if your kernel doesn't have copyout/copyin equivalents.
471| Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
472| and copyin overwrites SFC.
473|
474copyout:
475 movel 4(%sp),%a0 | source
476 movel 8(%sp),%a1 | destination
477 movel 12(%sp),%d0 | count
478 subl #1,%d0 | dec count by 1 for dbra
479 movel #1,%d1
480
481| DFC is already set
482| movec %d1,%DFC | set dfc for user data space
483moreout:
484 moveb (%a0)+,%d1 | fetch supervisor byte
485out_ea:
486 movesb %d1,(%a1)+ | write user byte
487 dbf %d0,moreout
488 rts
489
490copyin:
491 movel 4(%sp),%a0 | source
492 movel 8(%sp),%a1 | destination
493 movel 12(%sp),%d0 | count
494 subl #1,%d0 | dec count by 1 for dbra
495 movel #1,%d1
496| SFC is already set
497| movec %d1,%SFC | set sfc for user space
498morein:
499in_ea:
500 movesb (%a0)+,%d1 | fetch user byte
501 moveb %d1,(%a1)+ | write supervisor byte
502 dbf %d0,morein
503 rts
504
505 .section .fixup,#alloc,#execinstr
506 .even
5071:
508 jbra fpsp040_die
509
510 .section __ex_table,#alloc
511 .align 4
512
513 .long in_ea,1b
514 .long out_ea,1b
515
516 |end
diff --git a/arch/m68k/fpsp040/slog2.S b/arch/m68k/fpsp040/slog2.S
new file mode 100644
index 000000000000..517fa4563246
--- /dev/null
+++ b/arch/m68k/fpsp040/slog2.S
@@ -0,0 +1,188 @@
1|
2| slog2.sa 3.1 12/10/90
3|
4| The entry point slog10 computes the base-10
5| logarithm of an input argument X.
6| slog10d does the same except the input value is a
7| denormalized number.
8| sLog2 and sLog2d are the base-2 analogues.
9|
10| INPUT: Double-extended value in memory location pointed to
11| by address register a0.
12|
13| OUTPUT: log_10(X) or log_2(X) returned in floating-point
14| register fp0.
15|
16| ACCURACY and MONOTONICITY: The returned result is within 1.7
17| ulps in 64 significant bit, i.e. within 0.5003 ulp
18| to 53 bits if the result is subsequently rounded
19| to double precision. The result is provably monotonic
20| in double precision.
21|
22| SPEED: Two timings are measured, both in the copy-back mode.
23| The first one is measured when the function is invoked
24| the first time (so the instructions and data are not
25| in cache), and the second one is measured when the
26| function is reinvoked at the same input argument.
27|
28| ALGORITHM and IMPLEMENTATION NOTES:
29|
30| slog10d:
31|
32| Step 0. If X < 0, create a NaN and raise the invalid operation
33| flag. Otherwise, save FPCR in D1; set FpCR to default.
34| Notes: Default means round-to-nearest mode, no floating-point
35| traps, and precision control = double extended.
36|
37| Step 1. Call slognd to obtain Y = log(X), the natural log of X.
38| Notes: Even if X is denormalized, log(X) is always normalized.
39|
40| Step 2. Compute log_10(X) = log(X) * (1/log(10)).
41| 2.1 Restore the user FPCR
42| 2.2 Return ans := Y * INV_L10.
43|
44|
45| slog10:
46|
47| Step 0. If X < 0, create a NaN and raise the invalid operation
48| flag. Otherwise, save FPCR in D1; set FpCR to default.
49| Notes: Default means round-to-nearest mode, no floating-point
50| traps, and precision control = double extended.
51|
52| Step 1. Call sLogN to obtain Y = log(X), the natural log of X.
53|
54| Step 2. Compute log_10(X) = log(X) * (1/log(10)).
55| 2.1 Restore the user FPCR
56| 2.2 Return ans := Y * INV_L10.
57|
58|
59| sLog2d:
60|
61| Step 0. If X < 0, create a NaN and raise the invalid operation
62| flag. Otherwise, save FPCR in D1; set FpCR to default.
63| Notes: Default means round-to-nearest mode, no floating-point
64| traps, and precision control = double extended.
65|
66| Step 1. Call slognd to obtain Y = log(X), the natural log of X.
67| Notes: Even if X is denormalized, log(X) is always normalized.
68|
69| Step 2. Compute log_10(X) = log(X) * (1/log(2)).
70| 2.1 Restore the user FPCR
71| 2.2 Return ans := Y * INV_L2.
72|
73|
74| sLog2:
75|
76| Step 0. If X < 0, create a NaN and raise the invalid operation
77| flag. Otherwise, save FPCR in D1; set FpCR to default.
78| Notes: Default means round-to-nearest mode, no floating-point
79| traps, and precision control = double extended.
80|
81| Step 1. If X is not an integer power of two, i.e., X != 2^k,
82| go to Step 3.
83|
84| Step 2. Return k.
85| 2.1 Get integer k, X = 2^k.
86| 2.2 Restore the user FPCR.
87| 2.3 Return ans := convert-to-double-extended(k).
88|
89| Step 3. Call sLogN to obtain Y = log(X), the natural log of X.
90|
91| Step 4. Compute log_2(X) = log(X) * (1/log(2)).
92| 4.1 Restore the user FPCR
93| 4.2 Return ans := Y * INV_L2.
94|
95
96| Copyright (C) Motorola, Inc. 1990
97| All Rights Reserved
98|
99| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
100| The copyright notice above does not evidence any
101| actual or intended publication of such source code.
102
103|SLOG2 idnt 2,1 | Motorola 040 Floating Point Software Package
104
105 |section 8
106
107 |xref t_frcinx
108 |xref t_operr
109 |xref slogn
110 |xref slognd
111
112INV_L10: .long 0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
113
114INV_L2: .long 0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
115
116 .global slog10d
117slog10d:
118|--entry point for Log10(X), X is denormalized
119 movel (%a0),%d0
120 blt invalid
121 movel %d1,-(%sp)
122 clrl %d1
123 bsr slognd | ...log(X), X denorm.
124 fmovel (%sp)+,%fpcr
125 fmulx INV_L10,%fp0
126 bra t_frcinx
127
128 .global slog10
129slog10:
130|--entry point for Log10(X), X is normalized
131
132 movel (%a0),%d0
133 blt invalid
134 movel %d1,-(%sp)
135 clrl %d1
136 bsr slogn | ...log(X), X normal.
137 fmovel (%sp)+,%fpcr
138 fmulx INV_L10,%fp0
139 bra t_frcinx
140
141
142 .global slog2d
143slog2d:
144|--entry point for Log2(X), X is denormalized
145
146 movel (%a0),%d0
147 blt invalid
148 movel %d1,-(%sp)
149 clrl %d1
150 bsr slognd | ...log(X), X denorm.
151 fmovel (%sp)+,%fpcr
152 fmulx INV_L2,%fp0
153 bra t_frcinx
154
155 .global slog2
156slog2:
157|--entry point for Log2(X), X is normalized
158 movel (%a0),%d0
159 blt invalid
160
161 movel 8(%a0),%d0
162 bnes continue | ...X is not 2^k
163
164 movel 4(%a0),%d0
165 andl #0x7FFFFFFF,%d0
166 tstl %d0
167 bnes continue
168
169|--X = 2^k.
170 movew (%a0),%d0
171 andl #0x00007FFF,%d0
172 subl #0x3FFF,%d0
173 fmovel %d1,%fpcr
174 fmovel %d0,%fp0
175 bra t_frcinx
176
177continue:
178 movel %d1,-(%sp)
179 clrl %d1
180 bsr slogn | ...log(X), X normal.
181 fmovel (%sp)+,%fpcr
182 fmulx INV_L2,%fp0
183 bra t_frcinx
184
185invalid:
186 bra t_operr
187
188 |end
diff --git a/arch/m68k/fpsp040/slogn.S b/arch/m68k/fpsp040/slogn.S
new file mode 100644
index 000000000000..2aaa0725c035
--- /dev/null
+++ b/arch/m68k/fpsp040/slogn.S
@@ -0,0 +1,592 @@
1|
2| slogn.sa 3.1 12/10/90
3|
4| slogn computes the natural logarithm of an
5| input value. slognd does the same except the input value is a
6| denormalized number. slognp1 computes log(1+X), and slognp1d
7| computes log(1+X) for denormalized X.
8|
9| Input: Double-extended value in memory location pointed to by address
10| register a0.
11|
12| Output: log(X) or log(1+X) returned in floating-point register Fp0.
13|
14| Accuracy and Monotonicity: The returned result is within 2 ulps in
15| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
16| result is subsequently rounded to double precision. The
17| result is provably monotonic in double precision.
18|
19| Speed: The program slogn takes approximately 190 cycles for input
20| argument X such that |X-1| >= 1/16, which is the usual
21| situation. For those arguments, slognp1 takes approximately
22| 210 cycles. For the less common arguments, the program will
23| run no worse than 10% slower.
24|
25| Algorithm:
26| LOGN:
27| Step 1. If |X-1| < 1/16, approximate log(X) by an odd polynomial in
28| u, where u = 2(X-1)/(X+1). Otherwise, move on to Step 2.
29|
30| Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first seven
31| significant bits of Y plus 2**(-7), i.e. F = 1.xxxxxx1 in base
32| 2 where the six "x" match those of Y. Note that |Y-F| <= 2**(-7).
33|
34| Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a polynomial in u,
35| log(1+u) = poly.
36|
37| Step 4. Reconstruct log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u)
38| by k*log(2) + (log(F) + poly). The values of log(F) are calculated
39| beforehand and stored in the program.
40|
41| lognp1:
42| Step 1: If |X| < 1/16, approximate log(1+X) by an odd polynomial in
43| u where u = 2X/(2+X). Otherwise, move on to Step 2.
44|
45| Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done in Step 2
46| of the algorithm for LOGN and compute log(1+X) as
47| k*log(2) + log(F) + poly where poly approximates log(1+u),
48| u = (Y-F)/F.
49|
50| Implementation Notes:
51| Note 1. There are 64 different possible values for F, thus 64 log(F)'s
52| need to be tabulated. Moreover, the values of 1/F are also
53| tabulated so that the division in (Y-F)/F can be performed by a
54| multiplication.
55|
56| Note 2. In Step 2 of lognp1, in order to preserved accuracy, the value
57| Y-F has to be calculated carefully when 1/2 <= X < 3/2.
58|
59| Note 3. To fully exploit the pipeline, polynomials are usually separated
60| into two parts evaluated independently before being added up.
61|
62
63| Copyright (C) Motorola, Inc. 1990
64| All Rights Reserved
65|
66| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
67| The copyright notice above does not evidence any
68| actual or intended publication of such source code.
69
70|slogn idnt 2,1 | Motorola 040 Floating Point Software Package
71
72 |section 8
73
74#include "fpsp.h"
75
76BOUNDS1: .long 0x3FFEF07D,0x3FFF8841
77BOUNDS2: .long 0x3FFE8000,0x3FFFC000
78
79LOGOF2: .long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
80
81one: .long 0x3F800000
82zero: .long 0x00000000
83infty: .long 0x7F800000
84negone: .long 0xBF800000
85
86LOGA6: .long 0x3FC2499A,0xB5E4040B
87LOGA5: .long 0xBFC555B5,0x848CB7DB
88
89LOGA4: .long 0x3FC99999,0x987D8730
90LOGA3: .long 0xBFCFFFFF,0xFF6F7E97
91
92LOGA2: .long 0x3FD55555,0x555555a4
93LOGA1: .long 0xBFE00000,0x00000008
94
95LOGB5: .long 0x3F175496,0xADD7DAD6
96LOGB4: .long 0x3F3C71C2,0xFE80C7E0
97
98LOGB3: .long 0x3F624924,0x928BCCFF
99LOGB2: .long 0x3F899999,0x999995EC
100
101LOGB1: .long 0x3FB55555,0x55555555
102TWO: .long 0x40000000,0x00000000
103
104LTHOLD: .long 0x3f990000,0x80000000,0x00000000,0x00000000
105
106LOGTBL:
107 .long 0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
108 .long 0x3FF70000,0xFF015358,0x833C47E2,0x00000000
109 .long 0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
110 .long 0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
111 .long 0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
112 .long 0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
113 .long 0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
114 .long 0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
115 .long 0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
116 .long 0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
117 .long 0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
118 .long 0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
119 .long 0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
120 .long 0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
121 .long 0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
122 .long 0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
123 .long 0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
124 .long 0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
125 .long 0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
126 .long 0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
127 .long 0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
128 .long 0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
129 .long 0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
130 .long 0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
131 .long 0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
132 .long 0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
133 .long 0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
134 .long 0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
135 .long 0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
136 .long 0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
137 .long 0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
138 .long 0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
139 .long 0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
140 .long 0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
141 .long 0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
142 .long 0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
143 .long 0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
144 .long 0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
145 .long 0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
146 .long 0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
147 .long 0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
148 .long 0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
149 .long 0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
150 .long 0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
151 .long 0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
152 .long 0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
153 .long 0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
154 .long 0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
155 .long 0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
156 .long 0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
157 .long 0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
158 .long 0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
159 .long 0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
160 .long 0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
161 .long 0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
162 .long 0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
163 .long 0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
164 .long 0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
165 .long 0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
166 .long 0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
167 .long 0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
168 .long 0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
169 .long 0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
170 .long 0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
171 .long 0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
172 .long 0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
173 .long 0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
174 .long 0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
175 .long 0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
176 .long 0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
177 .long 0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
178 .long 0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
179 .long 0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
180 .long 0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
181 .long 0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
182 .long 0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
183 .long 0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
184 .long 0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
185 .long 0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
186 .long 0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
187 .long 0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
188 .long 0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
189 .long 0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
190 .long 0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
191 .long 0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
192 .long 0x3FFE0000,0x825EFCED,0x49369330,0x00000000
193 .long 0x3FFE0000,0x9868C809,0x868C8098,0x00000000
194 .long 0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
195 .long 0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
196 .long 0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
197 .long 0x3FFE0000,0x95A02568,0x095A0257,0x00000000
198 .long 0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
199 .long 0x3FFE0000,0x94458094,0x45809446,0x00000000
200 .long 0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
201 .long 0x3FFE0000,0x92F11384,0x0497889C,0x00000000
202 .long 0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
203 .long 0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
204 .long 0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
205 .long 0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
206 .long 0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
207 .long 0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
208 .long 0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
209 .long 0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
210 .long 0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
211 .long 0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
212 .long 0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
213 .long 0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
214 .long 0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
215 .long 0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
216 .long 0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
217 .long 0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
218 .long 0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
219 .long 0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
220 .long 0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
221 .long 0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
222 .long 0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
223 .long 0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
224 .long 0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
225 .long 0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
226 .long 0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
227 .long 0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
228 .long 0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
229 .long 0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
230 .long 0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
231 .long 0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
232 .long 0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
233 .long 0x3FFE0000,0x80808080,0x80808081,0x00000000
234 .long 0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
235
236 .set ADJK,L_SCR1
237
238 .set X,FP_SCR1
239 .set XDCARE,X+2
240 .set XFRAC,X+4
241
242 .set F,FP_SCR2
243 .set FFRAC,F+4
244
245 .set KLOG2,FP_SCR3
246
247 .set SAVEU,FP_SCR4
248
249 | xref t_frcinx
250 |xref t_extdnrm
251 |xref t_operr
252 |xref t_dz
253
254 .global slognd
255slognd:
256|--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
257
258 movel #-100,ADJK(%a6) | ...INPUT = 2^(ADJK) * FP0
259
260|----normalize the input value by left shifting k bits (k to be determined
261|----below), adjusting exponent and storing -k to ADJK
262|----the value TWOTO100 is no longer needed.
263|----Note that this code assumes the denormalized input is NON-ZERO.
264
265 moveml %d2-%d7,-(%a7) | ...save some registers
266 movel #0x00000000,%d3 | ...D3 is exponent of smallest norm. #
267 movel 4(%a0),%d4
268 movel 8(%a0),%d5 | ...(D4,D5) is (Hi_X,Lo_X)
269 clrl %d2 | ...D2 used for holding K
270
271 tstl %d4
272 bnes HiX_not0
273
274HiX_0:
275 movel %d5,%d4
276 clrl %d5
277 movel #32,%d2
278 clrl %d6
279 bfffo %d4{#0:#32},%d6
280 lsll %d6,%d4
281 addl %d6,%d2 | ...(D3,D4,D5) is normalized
282
283 movel %d3,X(%a6)
284 movel %d4,XFRAC(%a6)
285 movel %d5,XFRAC+4(%a6)
286 negl %d2
287 movel %d2,ADJK(%a6)
288 fmovex X(%a6),%fp0
289 moveml (%a7)+,%d2-%d7 | ...restore registers
290 lea X(%a6),%a0
291 bras LOGBGN | ...begin regular log(X)
292
293
294HiX_not0:
295 clrl %d6
296 bfffo %d4{#0:#32},%d6 | ...find first 1
297 movel %d6,%d2 | ...get k
298 lsll %d6,%d4
299 movel %d5,%d7 | ...a copy of D5
300 lsll %d6,%d5
301 negl %d6
302 addil #32,%d6
303 lsrl %d6,%d7
304 orl %d7,%d4 | ...(D3,D4,D5) normalized
305
306 movel %d3,X(%a6)
307 movel %d4,XFRAC(%a6)
308 movel %d5,XFRAC+4(%a6)
309 negl %d2
310 movel %d2,ADJK(%a6)
311 fmovex X(%a6),%fp0
312 moveml (%a7)+,%d2-%d7 | ...restore registers
313 lea X(%a6),%a0
314 bras LOGBGN | ...begin regular log(X)
315
316
317 .global slogn
318slogn:
319|--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
320
321 fmovex (%a0),%fp0 | ...LOAD INPUT
322 movel #0x00000000,ADJK(%a6)
323
324LOGBGN:
325|--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
326|--A FINITE, NON-ZERO, NORMALIZED NUMBER.
327
328 movel (%a0),%d0
329 movew 4(%a0),%d0
330
331 movel (%a0),X(%a6)
332 movel 4(%a0),X+4(%a6)
333 movel 8(%a0),X+8(%a6)
334
335 cmpil #0,%d0 | ...CHECK IF X IS NEGATIVE
336 blt LOGNEG | ...LOG OF NEGATIVE ARGUMENT IS INVALID
337 cmp2l BOUNDS1,%d0 | ...X IS POSITIVE, CHECK IF X IS NEAR 1
338 bcc LOGNEAR1 | ...BOUNDS IS ROUGHLY [15/16, 17/16]
339
340LOGMAIN:
341|--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
342
343|--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
344|--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
345|--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
346|-- = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
347|--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
348|--LOG(1+U) CAN BE VERY EFFICIENT.
349|--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
350|--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
351
352|--GET K, Y, F, AND ADDRESS OF 1/F.
353 asrl #8,%d0
354 asrl #8,%d0 | ...SHIFTED 16 BITS, BIASED EXPO. OF X
355 subil #0x3FFF,%d0 | ...THIS IS K
356 addl ADJK(%a6),%d0 | ...ADJUST K, ORIGINAL INPUT MAY BE DENORM.
357 lea LOGTBL,%a0 | ...BASE ADDRESS OF 1/F AND LOG(F)
358 fmovel %d0,%fp1 | ...CONVERT K TO FLOATING-POINT FORMAT
359
360|--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
361 movel #0x3FFF0000,X(%a6) | ...X IS NOW Y, I.E. 2^(-K)*X
362 movel XFRAC(%a6),FFRAC(%a6)
363 andil #0xFE000000,FFRAC(%a6) | ...FIRST 7 BITS OF Y
364 oril #0x01000000,FFRAC(%a6) | ...GET F: ATTACH A 1 AT THE EIGHTH BIT
365 movel FFRAC(%a6),%d0 | ...READY TO GET ADDRESS OF 1/F
366 andil #0x7E000000,%d0
367 asrl #8,%d0
368 asrl #8,%d0
369 asrl #4,%d0 | ...SHIFTED 20, D0 IS THE DISPLACEMENT
370 addal %d0,%a0 | ...A0 IS THE ADDRESS FOR 1/F
371
372 fmovex X(%a6),%fp0
373 movel #0x3fff0000,F(%a6)
374 clrl F+8(%a6)
375 fsubx F(%a6),%fp0 | ...Y-F
376 fmovemx %fp2-%fp2/%fp3,-(%sp) | ...SAVE FP2 WHILE FP0 IS NOT READY
377|--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
378|--REGISTERS SAVED: FPCR, FP1, FP2
379
380LP1CONT1:
381|--AN RE-ENTRY POINT FOR LOGNP1
382 fmulx (%a0),%fp0 | ...FP0 IS U = (Y-F)/F
383 fmulx LOGOF2,%fp1 | ...GET K*LOG2 WHILE FP0 IS NOT READY
384 fmovex %fp0,%fp2
385 fmulx %fp2,%fp2 | ...FP2 IS V=U*U
386 fmovex %fp1,KLOG2(%a6) | ...PUT K*LOG2 IN MEMORY, FREE FP1
387
388|--LOG(1+U) IS APPROXIMATED BY
389|--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
390|--[U + V*(A1+V*(A3+V*A5))] + [U*V*(A2+V*(A4+V*A6))]
391
392 fmovex %fp2,%fp3
393 fmovex %fp2,%fp1
394
395 fmuld LOGA6,%fp1 | ...V*A6
396 fmuld LOGA5,%fp2 | ...V*A5
397
398 faddd LOGA4,%fp1 | ...A4+V*A6
399 faddd LOGA3,%fp2 | ...A3+V*A5
400
401 fmulx %fp3,%fp1 | ...V*(A4+V*A6)
402 fmulx %fp3,%fp2 | ...V*(A3+V*A5)
403
404 faddd LOGA2,%fp1 | ...A2+V*(A4+V*A6)
405 faddd LOGA1,%fp2 | ...A1+V*(A3+V*A5)
406
407 fmulx %fp3,%fp1 | ...V*(A2+V*(A4+V*A6))
408 addal #16,%a0 | ...ADDRESS OF LOG(F)
409 fmulx %fp3,%fp2 | ...V*(A1+V*(A3+V*A5)), FP3 RELEASED
410
411 fmulx %fp0,%fp1 | ...U*V*(A2+V*(A4+V*A6))
412 faddx %fp2,%fp0 | ...U+V*(A1+V*(A3+V*A5)), FP2 RELEASED
413
414 faddx (%a0),%fp1 | ...LOG(F)+U*V*(A2+V*(A4+V*A6))
415 fmovemx (%sp)+,%fp2-%fp2/%fp3 | ...RESTORE FP2
416 faddx %fp1,%fp0 | ...FP0 IS LOG(F) + LOG(1+U)
417
418 fmovel %d1,%fpcr
419 faddx KLOG2(%a6),%fp0 | ...FINAL ADD
420 bra t_frcinx
421
422
423LOGNEAR1:
424|--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
425 fmovex %fp0,%fp1
426 fsubs one,%fp1 | ...FP1 IS X-1
427 fadds one,%fp0 | ...FP0 IS X+1
428 faddx %fp1,%fp1 | ...FP1 IS 2(X-1)
429|--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
430|--IN U, U = 2(X-1)/(X+1) = FP1/FP0
431
432LP1CONT2:
433|--THIS IS AN RE-ENTRY POINT FOR LOGNP1
434 fdivx %fp0,%fp1 | ...FP1 IS U
435 fmovemx %fp2-%fp2/%fp3,-(%sp) | ...SAVE FP2
436|--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
437|--LET V=U*U, W=V*V, CALCULATE
438|--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
439|--U + U*V*( [B1 + W*(B3 + W*B5)] + [V*(B2 + W*B4)] )
440 fmovex %fp1,%fp0
441 fmulx %fp0,%fp0 | ...FP0 IS V
442 fmovex %fp1,SAVEU(%a6) | ...STORE U IN MEMORY, FREE FP1
443 fmovex %fp0,%fp1
444 fmulx %fp1,%fp1 | ...FP1 IS W
445
446 fmoved LOGB5,%fp3
447 fmoved LOGB4,%fp2
448
449 fmulx %fp1,%fp3 | ...W*B5
450 fmulx %fp1,%fp2 | ...W*B4
451
452 faddd LOGB3,%fp3 | ...B3+W*B5
453 faddd LOGB2,%fp2 | ...B2+W*B4
454
455 fmulx %fp3,%fp1 | ...W*(B3+W*B5), FP3 RELEASED
456
457 fmulx %fp0,%fp2 | ...V*(B2+W*B4)
458
459 faddd LOGB1,%fp1 | ...B1+W*(B3+W*B5)
460 fmulx SAVEU(%a6),%fp0 | ...FP0 IS U*V
461
462 faddx %fp2,%fp1 | ...B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
463 fmovemx (%sp)+,%fp2-%fp2/%fp3 | ...FP2 RESTORED
464
465 fmulx %fp1,%fp0 | ...U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
466
467 fmovel %d1,%fpcr
468 faddx SAVEU(%a6),%fp0
469 bra t_frcinx
470 rts
471
472LOGNEG:
473|--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
474 bra t_operr
475
476 .global slognp1d
477slognp1d:
478|--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
479| Simply return the denorm
480
481 bra t_extdnrm
482
483 .global slognp1
484slognp1:
485|--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
486
487 fmovex (%a0),%fp0 | ...LOAD INPUT
488 fabsx %fp0 |test magnitude
489 fcmpx LTHOLD,%fp0 |compare with min threshold
490 fbgt LP1REAL |if greater, continue
491 fmovel #0,%fpsr |clr N flag from compare
492 fmovel %d1,%fpcr
493 fmovex (%a0),%fp0 |return signed argument
494 bra t_frcinx
495
496LP1REAL:
497 fmovex (%a0),%fp0 | ...LOAD INPUT
498 movel #0x00000000,ADJK(%a6)
499 fmovex %fp0,%fp1 | ...FP1 IS INPUT Z
500 fadds one,%fp0 | ...X := ROUND(1+Z)
501 fmovex %fp0,X(%a6)
502 movew XFRAC(%a6),XDCARE(%a6)
503 movel X(%a6),%d0
504 cmpil #0,%d0
505 ble LP1NEG0 | ...LOG OF ZERO OR -VE
506 cmp2l BOUNDS2,%d0
507 bcs LOGMAIN | ...BOUNDS2 IS [1/2,3/2]
508|--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
509|--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
510|--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
511
512LP1NEAR1:
513|--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
514 cmp2l BOUNDS1,%d0
515 bcss LP1CARE
516
517LP1ONE16:
518|--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
519|--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
520 faddx %fp1,%fp1 | ...FP1 IS 2Z
521 fadds one,%fp0 | ...FP0 IS 1+X
522|--U = FP1/FP0
523 bra LP1CONT2
524
525LP1CARE:
526|--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
527|--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
528|--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
529|--THERE ARE ONLY TWO CASES.
530|--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
531|--CASE 2: 1+Z > 1, THEN K = 0 AND Y-F = (1-F) + Z
532|--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
533|--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
534
535 movel XFRAC(%a6),FFRAC(%a6)
536 andil #0xFE000000,FFRAC(%a6)
537 oril #0x01000000,FFRAC(%a6) | ...F OBTAINED
538 cmpil #0x3FFF8000,%d0 | ...SEE IF 1+Z > 1
539 bges KISZERO
540
541KISNEG1:
542 fmoves TWO,%fp0
543 movel #0x3fff0000,F(%a6)
544 clrl F+8(%a6)
545 fsubx F(%a6),%fp0 | ...2-F
546 movel FFRAC(%a6),%d0
547 andil #0x7E000000,%d0
548 asrl #8,%d0
549 asrl #8,%d0
550 asrl #4,%d0 | ...D0 CONTAINS DISPLACEMENT FOR 1/F
551 faddx %fp1,%fp1 | ...GET 2Z
552 fmovemx %fp2-%fp2/%fp3,-(%sp) | ...SAVE FP2
553 faddx %fp1,%fp0 | ...FP0 IS Y-F = (2-F)+2Z
554 lea LOGTBL,%a0 | ...A0 IS ADDRESS OF 1/F
555 addal %d0,%a0
556 fmoves negone,%fp1 | ...FP1 IS K = -1
557 bra LP1CONT1
558
559KISZERO:
560 fmoves one,%fp0
561 movel #0x3fff0000,F(%a6)
562 clrl F+8(%a6)
563 fsubx F(%a6),%fp0 | ...1-F
564 movel FFRAC(%a6),%d0
565 andil #0x7E000000,%d0
566 asrl #8,%d0
567 asrl #8,%d0
568 asrl #4,%d0
569 faddx %fp1,%fp0 | ...FP0 IS Y-F
570 fmovemx %fp2-%fp2/%fp3,-(%sp) | ...FP2 SAVED
571 lea LOGTBL,%a0
572 addal %d0,%a0 | ...A0 IS ADDRESS OF 1/F
573 fmoves zero,%fp1 | ...FP1 IS K = 0
574 bra LP1CONT1
575
576LP1NEG0:
577|--FPCR SAVED. D0 IS X IN COMPACT FORM.
578 cmpil #0,%d0
579 blts LP1NEG
580LP1ZERO:
581 fmoves negone,%fp0
582
583 fmovel %d1,%fpcr
584 bra t_dz
585
586LP1NEG:
587 fmoves zero,%fp0
588
589 fmovel %d1,%fpcr
590 bra t_operr
591
592 |end
diff --git a/arch/m68k/fpsp040/smovecr.S b/arch/m68k/fpsp040/smovecr.S
new file mode 100644
index 000000000000..a0127fa55e9c
--- /dev/null
+++ b/arch/m68k/fpsp040/smovecr.S
@@ -0,0 +1,162 @@
1|
2| smovecr.sa 3.1 12/10/90
3|
4| The entry point sMOVECR returns the constant at the
5| offset given in the instruction field.
6|
7| Input: An offset in the instruction word.
8|
9| Output: The constant rounded to the user's rounding
10| mode unchecked for overflow.
11|
12| Modified: fp0.
13|
14|
15| Copyright (C) Motorola, Inc. 1990
16| All Rights Reserved
17|
18| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
19| The copyright notice above does not evidence any
20| actual or intended publication of such source code.
21
22|SMOVECR idnt 2,1 | Motorola 040 Floating Point Software Package
23
24 |section 8
25
26#include "fpsp.h"
27
28 |xref nrm_set
29 |xref round
30 |xref PIRN
31 |xref PIRZRM
32 |xref PIRP
33 |xref SMALRN
34 |xref SMALRZRM
35 |xref SMALRP
36 |xref BIGRN
37 |xref BIGRZRM
38 |xref BIGRP
39
40FZERO: .long 00000000
41|
42| FMOVECR
43|
44 .global smovcr
45smovcr:
46 bfextu CMDREG1B(%a6){#9:#7},%d0 |get offset
47 bfextu USER_FPCR(%a6){#26:#2},%d1 |get rmode
48|
49| check range of offset
50|
51 tstb %d0 |if zero, offset is to pi
52 beqs PI_TBL |it is pi
53 cmpib #0x0a,%d0 |check range $01 - $0a
54 bles Z_VAL |if in this range, return zero
55 cmpib #0x0e,%d0 |check range $0b - $0e
56 bles SM_TBL |valid constants in this range
57 cmpib #0x2f,%d0 |check range $10 - $2f
58 bles Z_VAL |if in this range, return zero
59 cmpib #0x3f,%d0 |check range $30 - $3f
60 ble BG_TBL |valid constants in this range
61Z_VAL:
62 fmoves FZERO,%fp0
63 rts
64PI_TBL:
65 tstb %d1 |offset is zero, check for rmode
66 beqs PI_RN |if zero, rn mode
67 cmpib #0x3,%d1 |check for rp
68 beqs PI_RP |if 3, rp mode
69PI_RZRM:
70 leal PIRZRM,%a0 |rmode is rz or rm, load PIRZRM in a0
71 bra set_finx
72PI_RN:
73 leal PIRN,%a0 |rmode is rn, load PIRN in a0
74 bra set_finx
75PI_RP:
76 leal PIRP,%a0 |rmode is rp, load PIRP in a0
77 bra set_finx
78SM_TBL:
79 subil #0xb,%d0 |make offset in 0 - 4 range
80 tstb %d1 |check for rmode
81 beqs SM_RN |if zero, rn mode
82 cmpib #0x3,%d1 |check for rp
83 beqs SM_RP |if 3, rp mode
84SM_RZRM:
85 leal SMALRZRM,%a0 |rmode is rz or rm, load SMRZRM in a0
86 cmpib #0x2,%d0 |check if result is inex
87 ble set_finx |if 0 - 2, it is inexact
88 bra no_finx |if 3, it is exact
89SM_RN:
90 leal SMALRN,%a0 |rmode is rn, load SMRN in a0
91 cmpib #0x2,%d0 |check if result is inex
92 ble set_finx |if 0 - 2, it is inexact
93 bra no_finx |if 3, it is exact
94SM_RP:
95 leal SMALRP,%a0 |rmode is rp, load SMRP in a0
96 cmpib #0x2,%d0 |check if result is inex
97 ble set_finx |if 0 - 2, it is inexact
98 bra no_finx |if 3, it is exact
99BG_TBL:
100 subil #0x30,%d0 |make offset in 0 - f range
101 tstb %d1 |check for rmode
102 beqs BG_RN |if zero, rn mode
103 cmpib #0x3,%d1 |check for rp
104 beqs BG_RP |if 3, rp mode
105BG_RZRM:
106 leal BIGRZRM,%a0 |rmode is rz or rm, load BGRZRM in a0
107 cmpib #0x1,%d0 |check if result is inex
108 ble set_finx |if 0 - 1, it is inexact
109 cmpib #0x7,%d0 |second check
110 ble no_finx |if 0 - 7, it is exact
111 bra set_finx |if 8 - f, it is inexact
112BG_RN:
113 leal BIGRN,%a0 |rmode is rn, load BGRN in a0
114 cmpib #0x1,%d0 |check if result is inex
115 ble set_finx |if 0 - 1, it is inexact
116 cmpib #0x7,%d0 |second check
117 ble no_finx |if 0 - 7, it is exact
118 bra set_finx |if 8 - f, it is inexact
119BG_RP:
120 leal BIGRP,%a0 |rmode is rp, load SMRP in a0
121 cmpib #0x1,%d0 |check if result is inex
122 ble set_finx |if 0 - 1, it is inexact
123 cmpib #0x7,%d0 |second check
124 ble no_finx |if 0 - 7, it is exact
125| bra set_finx ;if 8 - f, it is inexact
126set_finx:
127 orl #inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
128no_finx:
129 mulul #12,%d0 |use offset to point into tables
130 movel %d1,L_SCR1(%a6) |load mode for round call
131 bfextu USER_FPCR(%a6){#24:#2},%d1 |get precision
132 tstl %d1 |check if extended precision
133|
134| Precision is extended
135|
136 bnes not_ext |if extended, do not call round
137 fmovemx (%a0,%d0),%fp0-%fp0 |return result in fp0
138 rts
139|
140| Precision is single or double
141|
142not_ext:
143 swap %d1 |rnd prec in upper word of d1
144 addl L_SCR1(%a6),%d1 |merge rmode in low word of d1
145 movel (%a0,%d0),FP_SCR1(%a6) |load first word to temp storage
146 movel 4(%a0,%d0),FP_SCR1+4(%a6) |load second word
147 movel 8(%a0,%d0),FP_SCR1+8(%a6) |load third word
148 clrl %d0 |clear g,r,s
149 lea FP_SCR1(%a6),%a0
150 btstb #sign_bit,LOCAL_EX(%a0)
151 sne LOCAL_SGN(%a0) |convert to internal ext. format
152
153 bsr round |go round the mantissa
154
155 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
156 beqs fin_fcr
157 bsetb #sign_bit,LOCAL_EX(%a0)
158fin_fcr:
159 fmovemx (%a0),%fp0-%fp0
160 rts
161
162 |end
diff --git a/arch/m68k/fpsp040/srem_mod.S b/arch/m68k/fpsp040/srem_mod.S
new file mode 100644
index 000000000000..8c8d7f50cc68
--- /dev/null
+++ b/arch/m68k/fpsp040/srem_mod.S
@@ -0,0 +1,422 @@
1|
2| srem_mod.sa 3.1 12/10/90
3|
4| The entry point sMOD computes the floating point MOD of the
5| input values X and Y. The entry point sREM computes the floating
6| point (IEEE) REM of the input values X and Y.
7|
8| INPUT
9| -----
10| Double-extended value Y is pointed to by address in register
11| A0. Double-extended value X is located in -12(A0). The values
12| of X and Y are both nonzero and finite; although either or both
13| of them can be denormalized. The special cases of zeros, NaNs,
14| and infinities are handled elsewhere.
15|
16| OUTPUT
17| ------
18| FREM(X,Y) or FMOD(X,Y), depending on entry point.
19|
20| ALGORITHM
21| ---------
22|
23| Step 1. Save and strip signs of X and Y: signX := sign(X),
24| signY := sign(Y), X := |X|, Y := |Y|,
25| signQ := signX EOR signY. Record whether MOD or REM
26| is requested.
27|
28| Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0.
29| If (L < 0) then
30| R := X, go to Step 4.
31| else
32| R := 2^(-L)X, j := L.
33| endif
34|
35| Step 3. Perform MOD(X,Y)
36| 3.1 If R = Y, go to Step 9.
37| 3.2 If R > Y, then { R := R - Y, Q := Q + 1}
38| 3.3 If j = 0, go to Step 4.
39| 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to
40| Step 3.1.
41|
42| Step 4. At this point, R = X - QY = MOD(X,Y). Set
43| Last_Subtract := false (used in Step 7 below). If
44| MOD is requested, go to Step 6.
45|
46| Step 5. R = MOD(X,Y), but REM(X,Y) is requested.
47| 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to
48| Step 6.
49| 5.2 If R > Y/2, then { set Last_Subtract := true,
50| Q := Q + 1, Y := signY*Y }. Go to Step 6.
51| 5.3 This is the tricky case of R = Y/2. If Q is odd,
52| then { Q := Q + 1, signX := -signX }.
53|
54| Step 6. R := signX*R.
55|
56| Step 7. If Last_Subtract = true, R := R - Y.
57|
58| Step 8. Return signQ, last 7 bits of Q, and R as required.
59|
60| Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus,
61| X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),
62| R := 0. Return signQ, last 7 bits of Q, and R.
63|
64|
65
66| Copyright (C) Motorola, Inc. 1990
67| All Rights Reserved
68|
69| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
70| The copyright notice above does not evidence any
71| actual or intended publication of such source code.
72
73SREM_MOD: |idnt 2,1 | Motorola 040 Floating Point Software Package
74
75 |section 8
76
77#include "fpsp.h"
78
79 .set Mod_Flag,L_SCR3
80 .set SignY,FP_SCR3+4
81 .set SignX,FP_SCR3+8
82 .set SignQ,FP_SCR3+12
83 .set Sc_Flag,FP_SCR4
84
85 .set Y,FP_SCR1
86 .set Y_Hi,Y+4
87 .set Y_Lo,Y+8
88
89 .set R,FP_SCR2
90 .set R_Hi,R+4
91 .set R_Lo,R+8
92
93
94Scale: .long 0x00010000,0x80000000,0x00000000,0x00000000
95
96 |xref t_avoid_unsupp
97
98 .global smod
99smod:
100
101 movel #0,Mod_Flag(%a6)
102 bras Mod_Rem
103
104 .global srem
105srem:
106
107 movel #1,Mod_Flag(%a6)
108
109Mod_Rem:
110|..Save sign of X and Y
111 moveml %d2-%d7,-(%a7) | ...save data registers
112 movew (%a0),%d3
113 movew %d3,SignY(%a6)
114 andil #0x00007FFF,%d3 | ...Y := |Y|
115
116|
117 movel 4(%a0),%d4
118 movel 8(%a0),%d5 | ...(D3,D4,D5) is |Y|
119
120 tstl %d3
121 bnes Y_Normal
122
123 movel #0x00003FFE,%d3 | ...$3FFD + 1
124 tstl %d4
125 bnes HiY_not0
126
127HiY_0:
128 movel %d5,%d4
129 clrl %d5
130 subil #32,%d3
131 clrl %d6
132 bfffo %d4{#0:#32},%d6
133 lsll %d6,%d4
134 subl %d6,%d3 | ...(D3,D4,D5) is normalized
135| ...with bias $7FFD
136 bras Chk_X
137
138HiY_not0:
139 clrl %d6
140 bfffo %d4{#0:#32},%d6
141 subl %d6,%d3
142 lsll %d6,%d4
143 movel %d5,%d7 | ...a copy of D5
144 lsll %d6,%d5
145 negl %d6
146 addil #32,%d6
147 lsrl %d6,%d7
148 orl %d7,%d4 | ...(D3,D4,D5) normalized
149| ...with bias $7FFD
150 bras Chk_X
151
152Y_Normal:
153 addil #0x00003FFE,%d3 | ...(D3,D4,D5) normalized
154| ...with bias $7FFD
155
156Chk_X:
157 movew -12(%a0),%d0
158 movew %d0,SignX(%a6)
159 movew SignY(%a6),%d1
160 eorl %d0,%d1
161 andil #0x00008000,%d1
162 movew %d1,SignQ(%a6) | ...sign(Q) obtained
163 andil #0x00007FFF,%d0
164 movel -8(%a0),%d1
165 movel -4(%a0),%d2 | ...(D0,D1,D2) is |X|
166 tstl %d0
167 bnes X_Normal
168 movel #0x00003FFE,%d0
169 tstl %d1
170 bnes HiX_not0
171
172HiX_0:
173 movel %d2,%d1
174 clrl %d2
175 subil #32,%d0
176 clrl %d6
177 bfffo %d1{#0:#32},%d6
178 lsll %d6,%d1
179 subl %d6,%d0 | ...(D0,D1,D2) is normalized
180| ...with bias $7FFD
181 bras Init
182
183HiX_not0:
184 clrl %d6
185 bfffo %d1{#0:#32},%d6
186 subl %d6,%d0
187 lsll %d6,%d1
188 movel %d2,%d7 | ...a copy of D2
189 lsll %d6,%d2
190 negl %d6
191 addil #32,%d6
192 lsrl %d6,%d7
193 orl %d7,%d1 | ...(D0,D1,D2) normalized
194| ...with bias $7FFD
195 bras Init
196
197X_Normal:
198 addil #0x00003FFE,%d0 | ...(D0,D1,D2) normalized
199| ...with bias $7FFD
200
201Init:
202|
203 movel %d3,L_SCR1(%a6) | ...save biased expo(Y)
204 movel %d0,L_SCR2(%a6) |save d0
205 subl %d3,%d0 | ...L := expo(X)-expo(Y)
206| Move.L D0,L ...D0 is j
207 clrl %d6 | ...D6 := carry <- 0
208 clrl %d3 | ...D3 is Q
209 moveal #0,%a1 | ...A1 is k; j+k=L, Q=0
210
211|..(Carry,D1,D2) is R
212 tstl %d0
213 bges Mod_Loop
214
215|..expo(X) < expo(Y). Thus X = mod(X,Y)
216|
217 movel L_SCR2(%a6),%d0 |restore d0
218 bra Get_Mod
219
220|..At this point R = 2^(-L)X; Q = 0; k = 0; and k+j = L
221
222
223Mod_Loop:
224 tstl %d6 | ...test carry bit
225 bgts R_GT_Y
226
227|..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
228 cmpl %d4,%d1 | ...compare hi(R) and hi(Y)
229 bnes R_NE_Y
230 cmpl %d5,%d2 | ...compare lo(R) and lo(Y)
231 bnes R_NE_Y
232
233|..At this point, R = Y
234 bra Rem_is_0
235
236R_NE_Y:
237|..use the borrow of the previous compare
238 bcss R_LT_Y | ...borrow is set iff R < Y
239
240R_GT_Y:
241|..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
242|..and Y < (D1,D2) < 2Y. Either way, perform R - Y
243 subl %d5,%d2 | ...lo(R) - lo(Y)
244 subxl %d4,%d1 | ...hi(R) - hi(Y)
245 clrl %d6 | ...clear carry
246 addql #1,%d3 | ...Q := Q + 1
247
248R_LT_Y:
249|..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
250 tstl %d0 | ...see if j = 0.
251 beqs PostLoop
252
253 addl %d3,%d3 | ...Q := 2Q
254 addl %d2,%d2 | ...lo(R) = 2lo(R)
255 roxll #1,%d1 | ...hi(R) = 2hi(R) + carry
256 scs %d6 | ...set Carry if 2(R) overflows
257 addql #1,%a1 | ...k := k+1
258 subql #1,%d0 | ...j := j - 1
259|..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
260
261 bras Mod_Loop
262
263PostLoop:
264|..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
265
266|..normalize R.
267 movel L_SCR1(%a6),%d0 | ...new biased expo of R
268 tstl %d1
269 bnes HiR_not0
270
271HiR_0:
272 movel %d2,%d1
273 clrl %d2
274 subil #32,%d0
275 clrl %d6
276 bfffo %d1{#0:#32},%d6
277 lsll %d6,%d1
278 subl %d6,%d0 | ...(D0,D1,D2) is normalized
279| ...with bias $7FFD
280 bras Get_Mod
281
282HiR_not0:
283 clrl %d6
284 bfffo %d1{#0:#32},%d6
285 bmis Get_Mod | ...already normalized
286 subl %d6,%d0
287 lsll %d6,%d1
288 movel %d2,%d7 | ...a copy of D2
289 lsll %d6,%d2
290 negl %d6
291 addil #32,%d6
292 lsrl %d6,%d7
293 orl %d7,%d1 | ...(D0,D1,D2) normalized
294
295|
296Get_Mod:
297 cmpil #0x000041FE,%d0
298 bges No_Scale
299Do_Scale:
300 movew %d0,R(%a6)
301 clrw R+2(%a6)
302 movel %d1,R_Hi(%a6)
303 movel %d2,R_Lo(%a6)
304 movel L_SCR1(%a6),%d6
305 movew %d6,Y(%a6)
306 clrw Y+2(%a6)
307 movel %d4,Y_Hi(%a6)
308 movel %d5,Y_Lo(%a6)
309 fmovex R(%a6),%fp0 | ...no exception
310 movel #1,Sc_Flag(%a6)
311 bras ModOrRem
312No_Scale:
313 movel %d1,R_Hi(%a6)
314 movel %d2,R_Lo(%a6)
315 subil #0x3FFE,%d0
316 movew %d0,R(%a6)
317 clrw R+2(%a6)
318 movel L_SCR1(%a6),%d6
319 subil #0x3FFE,%d6
320 movel %d6,L_SCR1(%a6)
321 fmovex R(%a6),%fp0
322 movew %d6,Y(%a6)
323 movel %d4,Y_Hi(%a6)
324 movel %d5,Y_Lo(%a6)
325 movel #0,Sc_Flag(%a6)
326
327|
328
329
330ModOrRem:
331 movel Mod_Flag(%a6),%d6
332 beqs Fix_Sign
333
334 movel L_SCR1(%a6),%d6 | ...new biased expo(Y)
335 subql #1,%d6 | ...biased expo(Y/2)
336 cmpl %d6,%d0
337 blts Fix_Sign
338 bgts Last_Sub
339
340 cmpl %d4,%d1
341 bnes Not_EQ
342 cmpl %d5,%d2
343 bnes Not_EQ
344 bra Tie_Case
345
346Not_EQ:
347 bcss Fix_Sign
348
349Last_Sub:
350|
351 fsubx Y(%a6),%fp0 | ...no exceptions
352 addql #1,%d3 | ...Q := Q + 1
353
354|
355
356Fix_Sign:
357|..Get sign of X
358 movew SignX(%a6),%d6
359 bges Get_Q
360 fnegx %fp0
361
362|..Get Q
363|
364Get_Q:
365 clrl %d6
366 movew SignQ(%a6),%d6 | ...D6 is sign(Q)
367 movel #8,%d7
368 lsrl %d7,%d6
369 andil #0x0000007F,%d3 | ...7 bits of Q
370 orl %d6,%d3 | ...sign and bits of Q
371 swap %d3
372 fmovel %fpsr,%d6
373 andil #0xFF00FFFF,%d6
374 orl %d3,%d6
375 fmovel %d6,%fpsr | ...put Q in fpsr
376
377|
378Restore:
379 moveml (%a7)+,%d2-%d7
380 fmovel USER_FPCR(%a6),%fpcr
381 movel Sc_Flag(%a6),%d0
382 beqs Finish
383 fmulx Scale(%pc),%fp0 | ...may cause underflow
384 bra t_avoid_unsupp |check for denorm as a
385| ;result of the scaling
386
387Finish:
388 fmovex %fp0,%fp0 |capture exceptions & round
389 rts
390
391Rem_is_0:
392|..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
393 addql #1,%d3
394 cmpil #8,%d0 | ...D0 is j
395 bges Q_Big
396
397 lsll %d0,%d3
398 bras Set_R_0
399
400Q_Big:
401 clrl %d3
402
403Set_R_0:
404 fmoves #0x00000000,%fp0
405 movel #0,Sc_Flag(%a6)
406 bra Fix_Sign
407
408Tie_Case:
409|..Check parity of Q
410 movel %d3,%d6
411 andil #0x00000001,%d6
412 tstl %d6
413 beq Fix_Sign | ...Q is even
414
415|..Q is odd, Q := Q + 1, signX := -signX
416 addql #1,%d3
417 movew SignX(%a6),%d6
418 eoril #0x00008000,%d6
419 movew %d6,SignX(%a6)
420 bra Fix_Sign
421
422 |end
diff --git a/arch/m68k/fpsp040/ssin.S b/arch/m68k/fpsp040/ssin.S
new file mode 100644
index 000000000000..043c91cdd657
--- /dev/null
+++ b/arch/m68k/fpsp040/ssin.S
@@ -0,0 +1,746 @@
1|
2| ssin.sa 3.3 7/29/91
3|
4| The entry point sSIN computes the sine of an input argument
5| sCOS computes the cosine, and sSINCOS computes both. The
6| corresponding entry points with a "d" computes the same
7| corresponding function values for denormalized inputs.
8|
9| Input: Double-extended number X in location pointed to
10| by address register a0.
11|
12| Output: The function value sin(X) or cos(X) returned in Fp0 if SIN or
13| COS is requested. Otherwise, for SINCOS, sin(X) is returned
14| in Fp0, and cos(X) is returned in Fp1.
15|
16| Modifies: Fp0 for SIN or COS; both Fp0 and Fp1 for SINCOS.
17|
18| Accuracy and Monotonicity: The returned result is within 1 ulp in
19| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
20| result is subsequently rounded to double precision. The
21| result is provably monotonic in double precision.
22|
23| Speed: The programs sSIN and sCOS take approximately 150 cycles for
24| input argument X such that |X| < 15Pi, which is the usual
25| situation. The speed for sSINCOS is approximately 190 cycles.
26|
27| Algorithm:
28|
29| SIN and COS:
30| 1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1.
31|
32| 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7.
33|
34| 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let
35| k = N mod 4, so in particular, k = 0,1,2,or 3. Overwrite
36| k by k := k + AdjN.
37|
38| 4. If k is even, go to 6.
39|
40| 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. Return sgn*cos(r)
41| where cos(r) is approximated by an even polynomial in r,
42| 1 + r*r*(B1+s*(B2+ ... + s*B8)), s = r*r.
43| Exit.
44|
45| 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r)
46| where sin(r) is approximated by an odd polynomial in r
47| r + r*s*(A1+s*(A2+ ... + s*A7)), s = r*r.
48| Exit.
49|
50| 7. If |X| > 1, go to 9.
51|
52| 8. (|X|<2**(-40)) If SIN is invoked, return X; otherwise return 1.
53|
54| 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back to 3.
55|
56| SINCOS:
57| 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.
58|
59| 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let
60| k = N mod 4, so in particular, k = 0,1,2,or 3.
61|
62| 3. If k is even, go to 5.
63|
64| 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), i.e.
65| j1 exclusive or with the l.s.b. of k.
66| sgn1 := (-1)**j1, sgn2 := (-1)**j2.
67| SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where
68| sin(r) and cos(r) are computed as odd and even polynomials
69| in r, respectively. Exit
70|
71| 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1.
72| SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where
73| sin(r) and cos(r) are computed as odd and even polynomials
74| in r, respectively. Exit
75|
76| 6. If |X| > 1, go to 8.
77|
78| 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit.
79|
80| 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back to 2.
81|
82
83| Copyright (C) Motorola, Inc. 1990
84| All Rights Reserved
85|
86| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
87| The copyright notice above does not evidence any
88| actual or intended publication of such source code.
89
90|SSIN idnt 2,1 | Motorola 040 Floating Point Software Package
91
92 |section 8
93
94#include "fpsp.h"
95
96BOUNDS1: .long 0x3FD78000,0x4004BC7E
97TWOBYPI: .long 0x3FE45F30,0x6DC9C883
98
99SINA7: .long 0xBD6AAA77,0xCCC994F5
100SINA6: .long 0x3DE61209,0x7AAE8DA1
101
102SINA5: .long 0xBE5AE645,0x2A118AE4
103SINA4: .long 0x3EC71DE3,0xA5341531
104
105SINA3: .long 0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
106
107SINA2: .long 0x3FF80000,0x88888888,0x888859AF,0x00000000
108
109SINA1: .long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
110
111COSB8: .long 0x3D2AC4D0,0xD6011EE3
112COSB7: .long 0xBDA9396F,0x9F45AC19
113
114COSB6: .long 0x3E21EED9,0x0612C972
115COSB5: .long 0xBE927E4F,0xB79D9FCF
116
117COSB4: .long 0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
118
119COSB3: .long 0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
120
121COSB2: .long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
122COSB1: .long 0xBF000000
123
124INVTWOPI: .long 0x3FFC0000,0xA2F9836E,0x4E44152A
125
126TWOPI1: .long 0x40010000,0xC90FDAA2,0x00000000,0x00000000
127TWOPI2: .long 0x3FDF0000,0x85A308D4,0x00000000,0x00000000
128
129 |xref PITBL
130
131 .set INARG,FP_SCR4
132
133 .set X,FP_SCR5
134 .set XDCARE,X+2
135 .set XFRAC,X+4
136
137 .set RPRIME,FP_SCR1
138 .set SPRIME,FP_SCR2
139
140 .set POSNEG1,L_SCR1
141 .set TWOTO63,L_SCR1
142
143 .set ENDFLAG,L_SCR2
144 .set N,L_SCR2
145
146 .set ADJN,L_SCR3
147
148 | xref t_frcinx
149 |xref t_extdnrm
150 |xref sto_cos
151
152 .global ssind
153ssind:
154|--SIN(X) = X FOR DENORMALIZED X
155 bra t_extdnrm
156
157 .global scosd
158scosd:
159|--COS(X) = 1 FOR DENORMALIZED X
160
161 fmoves #0x3F800000,%fp0
162|
163| 9D25B Fix: Sometimes the previous fmove.s sets fpsr bits
164|
165 fmovel #0,%fpsr
166|
167 bra t_frcinx
168
169 .global ssin
170ssin:
171|--SET ADJN TO 0
172 movel #0,ADJN(%a6)
173 bras SINBGN
174
175 .global scos
176scos:
177|--SET ADJN TO 1
178 movel #1,ADJN(%a6)
179
180SINBGN:
181|--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
182
183 fmovex (%a0),%fp0 | ...LOAD INPUT
184
185 movel (%a0),%d0
186 movew 4(%a0),%d0
187 fmovex %fp0,X(%a6)
188 andil #0x7FFFFFFF,%d0 | ...COMPACTIFY X
189
190 cmpil #0x3FD78000,%d0 | ...|X| >= 2**(-40)?
191 bges SOK1
192 bra SINSM
193
194SOK1:
195 cmpil #0x4004BC7E,%d0 | ...|X| < 15 PI?
196 blts SINMAIN
197 bra REDUCEX
198
199SINMAIN:
200|--THIS IS THE USUAL CASE, |X| <= 15 PI.
201|--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
202 fmovex %fp0,%fp1
203 fmuld TWOBYPI,%fp1 | ...X*2/PI
204
205|--HIDE THE NEXT THREE INSTRUCTIONS
206 lea PITBL+0x200,%a1 | ...TABLE OF N*PI/2, N = -32,...,32
207
208
209|--FP1 IS NOW READY
210 fmovel %fp1,N(%a6) | ...CONVERT TO INTEGER
211
212 movel N(%a6),%d0
213 asll #4,%d0
214 addal %d0,%a1 | ...A1 IS THE ADDRESS OF N*PIBY2
215| ...WHICH IS IN TWO PIECES Y1 & Y2
216
217 fsubx (%a1)+,%fp0 | ...X-Y1
218|--HIDE THE NEXT ONE
219 fsubs (%a1),%fp0 | ...FP0 IS R = (X-Y1)-Y2
220
221SINCONT:
222|--continuation from REDUCEX
223
224|--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
225 movel N(%a6),%d0
226 addl ADJN(%a6),%d0 | ...SEE IF D0 IS ODD OR EVEN
227 rorl #1,%d0 | ...D0 WAS ODD IFF D0 IS NEGATIVE
228 cmpil #0,%d0
229 blt COSPOLY
230
231SINPOLY:
232|--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
233|--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
234|--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
235|--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
236|--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
237|--WHERE T=S*S.
238|--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
239|--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
240 fmovex %fp0,X(%a6) | ...X IS R
241 fmulx %fp0,%fp0 | ...FP0 IS S
242|---HIDE THE NEXT TWO WHILE WAITING FOR FP0
243 fmoved SINA7,%fp3
244 fmoved SINA6,%fp2
245|--FP0 IS NOW READY
246 fmovex %fp0,%fp1
247 fmulx %fp1,%fp1 | ...FP1 IS T
248|--HIDE THE NEXT TWO WHILE WAITING FOR FP1
249
250 rorl #1,%d0
251 andil #0x80000000,%d0
252| ...LEAST SIG. BIT OF D0 IN SIGN POSITION
253 eorl %d0,X(%a6) | ...X IS NOW R'= SGN*R
254
255 fmulx %fp1,%fp3 | ...TA7
256 fmulx %fp1,%fp2 | ...TA6
257
258 faddd SINA5,%fp3 | ...A5+TA7
259 faddd SINA4,%fp2 | ...A4+TA6
260
261 fmulx %fp1,%fp3 | ...T(A5+TA7)
262 fmulx %fp1,%fp2 | ...T(A4+TA6)
263
264 faddd SINA3,%fp3 | ...A3+T(A5+TA7)
265 faddx SINA2,%fp2 | ...A2+T(A4+TA6)
266
267 fmulx %fp3,%fp1 | ...T(A3+T(A5+TA7))
268
269 fmulx %fp0,%fp2 | ...S(A2+T(A4+TA6))
270 faddx SINA1,%fp1 | ...A1+T(A3+T(A5+TA7))
271 fmulx X(%a6),%fp0 | ...R'*S
272
273 faddx %fp2,%fp1 | ...[A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
274|--FP3 RELEASED, RESTORE NOW AND TAKE SOME ADVANTAGE OF HIDING
275|--FP2 RELEASED, RESTORE NOW AND TAKE FULL ADVANTAGE OF HIDING
276
277
278 fmulx %fp1,%fp0 | ...SIN(R')-R'
279|--FP1 RELEASED.
280
281 fmovel %d1,%FPCR |restore users exceptions
282 faddx X(%a6),%fp0 |last inst - possible exception set
283 bra t_frcinx
284
285
286COSPOLY:
287|--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
288|--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY
289|--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
290|--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
291|--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
292|--WHERE T=S*S.
293|--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
294|--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
295|--AND IS THEREFORE STORED AS SINGLE PRECISION.
296
297 fmulx %fp0,%fp0 | ...FP0 IS S
298|---HIDE THE NEXT TWO WHILE WAITING FOR FP0
299 fmoved COSB8,%fp2
300 fmoved COSB7,%fp3
301|--FP0 IS NOW READY
302 fmovex %fp0,%fp1
303 fmulx %fp1,%fp1 | ...FP1 IS T
304|--HIDE THE NEXT TWO WHILE WAITING FOR FP1
305 fmovex %fp0,X(%a6) | ...X IS S
306 rorl #1,%d0
307 andil #0x80000000,%d0
308| ...LEAST SIG. BIT OF D0 IN SIGN POSITION
309
310 fmulx %fp1,%fp2 | ...TB8
311|--HIDE THE NEXT TWO WHILE WAITING FOR THE XU
312 eorl %d0,X(%a6) | ...X IS NOW S'= SGN*S
313 andil #0x80000000,%d0
314
315 fmulx %fp1,%fp3 | ...TB7
316|--HIDE THE NEXT TWO WHILE WAITING FOR THE XU
317 oril #0x3F800000,%d0 | ...D0 IS SGN IN SINGLE
318 movel %d0,POSNEG1(%a6)
319
320 faddd COSB6,%fp2 | ...B6+TB8
321 faddd COSB5,%fp3 | ...B5+TB7
322
323 fmulx %fp1,%fp2 | ...T(B6+TB8)
324 fmulx %fp1,%fp3 | ...T(B5+TB7)
325
326 faddd COSB4,%fp2 | ...B4+T(B6+TB8)
327 faddx COSB3,%fp3 | ...B3+T(B5+TB7)
328
329 fmulx %fp1,%fp2 | ...T(B4+T(B6+TB8))
330 fmulx %fp3,%fp1 | ...T(B3+T(B5+TB7))
331
332 faddx COSB2,%fp2 | ...B2+T(B4+T(B6+TB8))
333 fadds COSB1,%fp1 | ...B1+T(B3+T(B5+TB7))
334
335 fmulx %fp2,%fp0 | ...S(B2+T(B4+T(B6+TB8)))
336|--FP3 RELEASED, RESTORE NOW AND TAKE SOME ADVANTAGE OF HIDING
337|--FP2 RELEASED.
338
339
340 faddx %fp1,%fp0
341|--FP1 RELEASED
342
343 fmulx X(%a6),%fp0
344
345 fmovel %d1,%FPCR |restore users exceptions
346 fadds POSNEG1(%a6),%fp0 |last inst - possible exception set
347 bra t_frcinx
348
349
350SINBORS:
351|--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
352|--IF |X| < 2**(-40), RETURN X OR 1.
353 cmpil #0x3FFF8000,%d0
354 bgts REDUCEX
355
356
357SINSM:
358 movel ADJN(%a6),%d0
359 cmpil #0,%d0
360 bgts COSTINY
361
362SINTINY:
363 movew #0x0000,XDCARE(%a6) | ...JUST IN CASE
364 fmovel %d1,%FPCR |restore users exceptions
365 fmovex X(%a6),%fp0 |last inst - possible exception set
366 bra t_frcinx
367
368
369COSTINY:
370 fmoves #0x3F800000,%fp0
371
372 fmovel %d1,%FPCR |restore users exceptions
373 fsubs #0x00800000,%fp0 |last inst - possible exception set
374 bra t_frcinx
375
376
377REDUCEX:
378|--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
379|--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
380|--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
381
382 fmovemx %fp2-%fp5,-(%a7) | ...save FP2 through FP5
383 movel %d2,-(%a7)
384 fmoves #0x00000000,%fp1
385|--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
386|--there is a danger of unwanted overflow in first LOOP iteration. In this
387|--case, reduce argument by one remainder step to make subsequent reduction
388|--safe.
389 cmpil #0x7ffeffff,%d0 |is argument dangerously large?
390 bnes LOOP
391 movel #0x7ffe0000,FP_SCR2(%a6) |yes
392| ;create 2**16383*PI/2
393 movel #0xc90fdaa2,FP_SCR2+4(%a6)
394 clrl FP_SCR2+8(%a6)
395 ftstx %fp0 |test sign of argument
396 movel #0x7fdc0000,FP_SCR3(%a6) |create low half of 2**16383*
397| ;PI/2 at FP_SCR3
398 movel #0x85a308d3,FP_SCR3+4(%a6)
399 clrl FP_SCR3+8(%a6)
400 fblt red_neg
401 orw #0x8000,FP_SCR2(%a6) |positive arg
402 orw #0x8000,FP_SCR3(%a6)
403red_neg:
404 faddx FP_SCR2(%a6),%fp0 |high part of reduction is exact
405 fmovex %fp0,%fp1 |save high result in fp1
406 faddx FP_SCR3(%a6),%fp0 |low part of reduction
407 fsubx %fp0,%fp1 |determine low component of result
408 faddx FP_SCR3(%a6),%fp1 |fp0/fp1 are reduced argument.
409
410|--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
411|--integer quotient will be stored in N
412|--Intermediate remainder is 66-bit long; (R,r) in (FP0,FP1)
413
414LOOP:
415 fmovex %fp0,INARG(%a6) | ...+-2**K * F, 1 <= F < 2
416 movew INARG(%a6),%d0
417 movel %d0,%a1 | ...save a copy of D0
418 andil #0x00007FFF,%d0
419 subil #0x00003FFF,%d0 | ...D0 IS K
420 cmpil #28,%d0
421 bles LASTLOOP
422CONTLOOP:
423 subil #27,%d0 | ...D0 IS L := K-27
424 movel #0,ENDFLAG(%a6)
425 bras WORK
426LASTLOOP:
427 clrl %d0 | ...D0 IS L := 0
428 movel #1,ENDFLAG(%a6)
429
430WORK:
431|--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
432|--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
433
434|--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
435|--2**L * (PIby2_1), 2**L * (PIby2_2)
436
437 movel #0x00003FFE,%d2 | ...BIASED EXPO OF 2/PI
438 subl %d0,%d2 | ...BIASED EXPO OF 2**(-L)*(2/PI)
439
440 movel #0xA2F9836E,FP_SCR1+4(%a6)
441 movel #0x4E44152A,FP_SCR1+8(%a6)
442 movew %d2,FP_SCR1(%a6) | ...FP_SCR1 is 2**(-L)*(2/PI)
443
444 fmovex %fp0,%fp2
445 fmulx FP_SCR1(%a6),%fp2
446|--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
447|--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
448|--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
449|--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
450|--US THE DESIRED VALUE IN FLOATING POINT.
451
452|--HIDE SIX CYCLES OF INSTRUCTION
453 movel %a1,%d2
454 swap %d2
455 andil #0x80000000,%d2
456 oril #0x5F000000,%d2 | ...D2 IS SIGN(INARG)*2**63 IN SGL
457 movel %d2,TWOTO63(%a6)
458
459 movel %d0,%d2
460 addil #0x00003FFF,%d2 | ...BIASED EXPO OF 2**L * (PI/2)
461
462|--FP2 IS READY
463 fadds TWOTO63(%a6),%fp2 | ...THE FRACTIONAL PART OF FP1 IS ROUNDED
464
465|--HIDE 4 CYCLES OF INSTRUCTION; creating 2**(L)*Piby2_1 and 2**(L)*Piby2_2
466 movew %d2,FP_SCR2(%a6)
467 clrw FP_SCR2+2(%a6)
468 movel #0xC90FDAA2,FP_SCR2+4(%a6)
469 clrl FP_SCR2+8(%a6) | ...FP_SCR2 is 2**(L) * Piby2_1
470
471|--FP2 IS READY
472 fsubs TWOTO63(%a6),%fp2 | ...FP2 is N
473
474 addil #0x00003FDD,%d0
475 movew %d0,FP_SCR3(%a6)
476 clrw FP_SCR3+2(%a6)
477 movel #0x85A308D3,FP_SCR3+4(%a6)
478 clrl FP_SCR3+8(%a6) | ...FP_SCR3 is 2**(L) * Piby2_2
479
480 movel ENDFLAG(%a6),%d0
481
482|--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
483|--P2 = 2**(L) * Piby2_2
484 fmovex %fp2,%fp4
485 fmulx FP_SCR2(%a6),%fp4 | ...W = N*P1
486 fmovex %fp2,%fp5
487 fmulx FP_SCR3(%a6),%fp5 | ...w = N*P2
488 fmovex %fp4,%fp3
489|--we want P+p = W+w but |p| <= half ulp of P
490|--Then, we need to compute A := R-P and a := r-p
491 faddx %fp5,%fp3 | ...FP3 is P
492 fsubx %fp3,%fp4 | ...W-P
493
494 fsubx %fp3,%fp0 | ...FP0 is A := R - P
495 faddx %fp5,%fp4 | ...FP4 is p = (W-P)+w
496
497 fmovex %fp0,%fp3 | ...FP3 A
498 fsubx %fp4,%fp1 | ...FP1 is a := r - p
499
500|--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
501|--|r| <= half ulp of R.
502 faddx %fp1,%fp0 | ...FP0 is R := A+a
503|--No need to calculate r if this is the last loop
504 cmpil #0,%d0
505 bgt RESTORE
506
507|--Need to calculate r
508 fsubx %fp0,%fp3 | ...A-R
509 faddx %fp3,%fp1 | ...FP1 is r := (A-R)+a
510 bra LOOP
511
512RESTORE:
513 fmovel %fp2,N(%a6)
514 movel (%a7)+,%d2
515 fmovemx (%a7)+,%fp2-%fp5
516
517
518 movel ADJN(%a6),%d0
519 cmpil #4,%d0
520
521 blt SINCONT
522 bras SCCONT
523
524 .global ssincosd
525ssincosd:
526|--SIN AND COS OF X FOR DENORMALIZED X
527
528 fmoves #0x3F800000,%fp1
529 bsr sto_cos |store cosine result
530 bra t_extdnrm
531
532 .global ssincos
533ssincos:
534|--SET ADJN TO 4
535 movel #4,ADJN(%a6)
536
537 fmovex (%a0),%fp0 | ...LOAD INPUT
538
539 movel (%a0),%d0
540 movew 4(%a0),%d0
541 fmovex %fp0,X(%a6)
542 andil #0x7FFFFFFF,%d0 | ...COMPACTIFY X
543
544 cmpil #0x3FD78000,%d0 | ...|X| >= 2**(-40)?
545 bges SCOK1
546 bra SCSM
547
548SCOK1:
549 cmpil #0x4004BC7E,%d0 | ...|X| < 15 PI?
550 blts SCMAIN
551 bra REDUCEX
552
553
554SCMAIN:
555|--THIS IS THE USUAL CASE, |X| <= 15 PI.
556|--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
557 fmovex %fp0,%fp1
558 fmuld TWOBYPI,%fp1 | ...X*2/PI
559
560|--HIDE THE NEXT THREE INSTRUCTIONS
561 lea PITBL+0x200,%a1 | ...TABLE OF N*PI/2, N = -32,...,32
562
563
564|--FP1 IS NOW READY
565 fmovel %fp1,N(%a6) | ...CONVERT TO INTEGER
566
567 movel N(%a6),%d0
568 asll #4,%d0
569 addal %d0,%a1 | ...ADDRESS OF N*PIBY2, IN Y1, Y2
570
571 fsubx (%a1)+,%fp0 | ...X-Y1
572 fsubs (%a1),%fp0 | ...FP0 IS R = (X-Y1)-Y2
573
574SCCONT:
575|--continuation point from REDUCEX
576
577|--HIDE THE NEXT TWO
578 movel N(%a6),%d0
579 rorl #1,%d0
580
581 cmpil #0,%d0 | ...D0 < 0 IFF N IS ODD
582 bge NEVEN
583
584NODD:
585|--REGISTERS SAVED SO FAR: D0, A0, FP2.
586
587 fmovex %fp0,RPRIME(%a6)
588 fmulx %fp0,%fp0 | ...FP0 IS S = R*R
589 fmoved SINA7,%fp1 | ...A7
590 fmoved COSB8,%fp2 | ...B8
591 fmulx %fp0,%fp1 | ...SA7
592 movel %d2,-(%a7)
593 movel %d0,%d2
594 fmulx %fp0,%fp2 | ...SB8
595 rorl #1,%d2
596 andil #0x80000000,%d2
597
598 faddd SINA6,%fp1 | ...A6+SA7
599 eorl %d0,%d2
600 andil #0x80000000,%d2
601 faddd COSB7,%fp2 | ...B7+SB8
602
603 fmulx %fp0,%fp1 | ...S(A6+SA7)
604 eorl %d2,RPRIME(%a6)
605 movel (%a7)+,%d2
606 fmulx %fp0,%fp2 | ...S(B7+SB8)
607 rorl #1,%d0
608 andil #0x80000000,%d0
609
610 faddd SINA5,%fp1 | ...A5+S(A6+SA7)
611 movel #0x3F800000,POSNEG1(%a6)
612 eorl %d0,POSNEG1(%a6)
613 faddd COSB6,%fp2 | ...B6+S(B7+SB8)
614
615 fmulx %fp0,%fp1 | ...S(A5+S(A6+SA7))
616 fmulx %fp0,%fp2 | ...S(B6+S(B7+SB8))
617 fmovex %fp0,SPRIME(%a6)
618
619 faddd SINA4,%fp1 | ...A4+S(A5+S(A6+SA7))
620 eorl %d0,SPRIME(%a6)
621 faddd COSB5,%fp2 | ...B5+S(B6+S(B7+SB8))
622
623 fmulx %fp0,%fp1 | ...S(A4+...)
624 fmulx %fp0,%fp2 | ...S(B5+...)
625
626 faddd SINA3,%fp1 | ...A3+S(A4+...)
627 faddd COSB4,%fp2 | ...B4+S(B5+...)
628
629 fmulx %fp0,%fp1 | ...S(A3+...)
630 fmulx %fp0,%fp2 | ...S(B4+...)
631
632 faddx SINA2,%fp1 | ...A2+S(A3+...)
633 faddx COSB3,%fp2 | ...B3+S(B4+...)
634
635 fmulx %fp0,%fp1 | ...S(A2+...)
636 fmulx %fp0,%fp2 | ...S(B3+...)
637
638 faddx SINA1,%fp1 | ...A1+S(A2+...)
639 faddx COSB2,%fp2 | ...B2+S(B3+...)
640
641 fmulx %fp0,%fp1 | ...S(A1+...)
642 fmulx %fp2,%fp0 | ...S(B2+...)
643
644
645
646 fmulx RPRIME(%a6),%fp1 | ...R'S(A1+...)
647 fadds COSB1,%fp0 | ...B1+S(B2...)
648 fmulx SPRIME(%a6),%fp0 | ...S'(B1+S(B2+...))
649
650 movel %d1,-(%sp) |restore users mode & precision
651 andil #0xff,%d1 |mask off all exceptions
652 fmovel %d1,%FPCR
653 faddx RPRIME(%a6),%fp1 | ...COS(X)
654 bsr sto_cos |store cosine result
655 fmovel (%sp)+,%FPCR |restore users exceptions
656 fadds POSNEG1(%a6),%fp0 | ...SIN(X)
657
658 bra t_frcinx
659
660
661NEVEN:
662|--REGISTERS SAVED SO FAR: FP2.
663
664 fmovex %fp0,RPRIME(%a6)
665 fmulx %fp0,%fp0 | ...FP0 IS S = R*R
666 fmoved COSB8,%fp1 | ...B8
667 fmoved SINA7,%fp2 | ...A7
668 fmulx %fp0,%fp1 | ...SB8
669 fmovex %fp0,SPRIME(%a6)
670 fmulx %fp0,%fp2 | ...SA7
671 rorl #1,%d0
672 andil #0x80000000,%d0
673 faddd COSB7,%fp1 | ...B7+SB8
674 faddd SINA6,%fp2 | ...A6+SA7
675 eorl %d0,RPRIME(%a6)
676 eorl %d0,SPRIME(%a6)
677 fmulx %fp0,%fp1 | ...S(B7+SB8)
678 oril #0x3F800000,%d0
679 movel %d0,POSNEG1(%a6)
680 fmulx %fp0,%fp2 | ...S(A6+SA7)
681
682 faddd COSB6,%fp1 | ...B6+S(B7+SB8)
683 faddd SINA5,%fp2 | ...A5+S(A6+SA7)
684
685 fmulx %fp0,%fp1 | ...S(B6+S(B7+SB8))
686 fmulx %fp0,%fp2 | ...S(A5+S(A6+SA7))
687
688 faddd COSB5,%fp1 | ...B5+S(B6+S(B7+SB8))
689 faddd SINA4,%fp2 | ...A4+S(A5+S(A6+SA7))
690
691 fmulx %fp0,%fp1 | ...S(B5+...)
692 fmulx %fp0,%fp2 | ...S(A4+...)
693
694 faddd COSB4,%fp1 | ...B4+S(B5+...)
695 faddd SINA3,%fp2 | ...A3+S(A4+...)
696
697 fmulx %fp0,%fp1 | ...S(B4+...)
698 fmulx %fp0,%fp2 | ...S(A3+...)
699
700 faddx COSB3,%fp1 | ...B3+S(B4+...)
701 faddx SINA2,%fp2 | ...A2+S(A3+...)
702
703 fmulx %fp0,%fp1 | ...S(B3+...)
704 fmulx %fp0,%fp2 | ...S(A2+...)
705
706 faddx COSB2,%fp1 | ...B2+S(B3+...)
707 faddx SINA1,%fp2 | ...A1+S(A2+...)
708
709 fmulx %fp0,%fp1 | ...S(B2+...)
710 fmulx %fp2,%fp0 | ...s(a1+...)
711
712
713
714 fadds COSB1,%fp1 | ...B1+S(B2...)
715 fmulx RPRIME(%a6),%fp0 | ...R'S(A1+...)
716 fmulx SPRIME(%a6),%fp1 | ...S'(B1+S(B2+...))
717
718 movel %d1,-(%sp) |save users mode & precision
719 andil #0xff,%d1 |mask off all exceptions
720 fmovel %d1,%FPCR
721 fadds POSNEG1(%a6),%fp1 | ...COS(X)
722 bsr sto_cos |store cosine result
723 fmovel (%sp)+,%FPCR |restore users exceptions
724 faddx RPRIME(%a6),%fp0 | ...SIN(X)
725
726 bra t_frcinx
727
728SCBORS:
729 cmpil #0x3FFF8000,%d0
730 bgt REDUCEX
731
732
733SCSM:
734 movew #0x0000,XDCARE(%a6)
735 fmoves #0x3F800000,%fp1
736
737 movel %d1,-(%sp) |save users mode & precision
738 andil #0xff,%d1 |mask off all exceptions
739 fmovel %d1,%FPCR
740 fsubs #0x00800000,%fp1
741 bsr sto_cos |store cosine result
742 fmovel (%sp)+,%FPCR |restore users exceptions
743 fmovex X(%a6),%fp0
744 bra t_frcinx
745
746 |end
diff --git a/arch/m68k/fpsp040/ssinh.S b/arch/m68k/fpsp040/ssinh.S
new file mode 100644
index 000000000000..c8b3308bb143
--- /dev/null
+++ b/arch/m68k/fpsp040/ssinh.S
@@ -0,0 +1,135 @@
1|
2| ssinh.sa 3.1 12/10/90
3|
4| The entry point sSinh computes the hyperbolic sine of
5| an input argument; sSinhd does the same except for denormalized
6| input.
7|
8| Input: Double-extended number X in location pointed to
9| by address register a0.
10|
11| Output: The value sinh(X) returned in floating-point register Fp0.
12|
13| Accuracy and Monotonicity: The returned result is within 3 ulps in
14| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
15| result is subsequently rounded to double precision. The
16| result is provably monotonic in double precision.
17|
18| Speed: The program sSINH takes approximately 280 cycles.
19|
20| Algorithm:
21|
22| SINH
23| 1. If |X| > 16380 log2, go to 3.
24|
25| 2. (|X| <= 16380 log2) Sinh(X) is obtained by the formulae
26| y = |X|, sgn = sign(X), and z = expm1(Y),
27| sinh(X) = sgn*(1/2)*( z + z/(1+z) ).
28| Exit.
29|
30| 3. If |X| > 16480 log2, go to 5.
31|
32| 4. (16380 log2 < |X| <= 16480 log2)
33| sinh(X) = sign(X) * exp(|X|)/2.
34| However, invoking exp(|X|) may cause premature overflow.
35| Thus, we calculate sinh(X) as follows:
36| Y := |X|
37| sgn := sign(X)
38| sgnFact := sgn * 2**(16380)
39| Y' := Y - 16381 log2
40| sinh(X) := sgnFact * exp(Y').
41| Exit.
42|
43| 5. (|X| > 16480 log2) sinh(X) must overflow. Return
44| sign(X)*Huge*Huge to generate overflow and an infinity with
45| the appropriate sign. Huge is the largest finite number in
46| extended format. Exit.
47|
48
49| Copyright (C) Motorola, Inc. 1990
50| All Rights Reserved
51|
52| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
53| The copyright notice above does not evidence any
54| actual or intended publication of such source code.
55
56|SSINH idnt 2,1 | Motorola 040 Floating Point Software Package
57
58 |section 8
59
60T1: .long 0x40C62D38,0xD3D64634 | ... 16381 LOG2 LEAD
61T2: .long 0x3D6F90AE,0xB1E75CC7 | ... 16381 LOG2 TRAIL
62
63 |xref t_frcinx
64 |xref t_ovfl
65 |xref t_extdnrm
66 |xref setox
67 |xref setoxm1
68
69 .global ssinhd
70ssinhd:
71|--SINH(X) = X FOR DENORMALIZED X
72
73 bra t_extdnrm
74
75 .global ssinh
76ssinh:
77 fmovex (%a0),%fp0 | ...LOAD INPUT
78
79 movel (%a0),%d0
80 movew 4(%a0),%d0
81 movel %d0,%a1 | save a copy of original (compacted) operand
82 andl #0x7FFFFFFF,%d0
83 cmpl #0x400CB167,%d0
84 bgts SINHBIG
85
86|--THIS IS THE USUAL CASE, |X| < 16380 LOG2
87|--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
88
89 fabsx %fp0 | ...Y = |X|
90
91 moveml %a1/%d1,-(%sp)
92 fmovemx %fp0-%fp0,(%a0)
93 clrl %d1
94 bsr setoxm1 | ...FP0 IS Z = EXPM1(Y)
95 fmovel #0,%fpcr
96 moveml (%sp)+,%a1/%d1
97
98 fmovex %fp0,%fp1
99 fadds #0x3F800000,%fp1 | ...1+Z
100 fmovex %fp0,-(%sp)
101 fdivx %fp1,%fp0 | ...Z/(1+Z)
102 movel %a1,%d0
103 andl #0x80000000,%d0
104 orl #0x3F000000,%d0
105 faddx (%sp)+,%fp0
106 movel %d0,-(%sp)
107
108 fmovel %d1,%fpcr
109 fmuls (%sp)+,%fp0 |last fp inst - possible exceptions set
110
111 bra t_frcinx
112
113SINHBIG:
114 cmpl #0x400CB2B3,%d0
115 bgt t_ovfl
116 fabsx %fp0
117 fsubd T1(%pc),%fp0 | ...(|X|-16381LOG2_LEAD)
118 movel #0,-(%sp)
119 movel #0x80000000,-(%sp)
120 movel %a1,%d0
121 andl #0x80000000,%d0
122 orl #0x7FFB0000,%d0
123 movel %d0,-(%sp) | ...EXTENDED FMT
124 fsubd T2(%pc),%fp0 | ...|X| - 16381 LOG2, ACCURATE
125
126 movel %d1,-(%sp)
127 clrl %d1
128 fmovemx %fp0-%fp0,(%a0)
129 bsr setox
130 fmovel (%sp)+,%fpcr
131
132 fmulx (%sp)+,%fp0 |possible exception
133 bra t_frcinx
134
135 |end
diff --git a/arch/m68k/fpsp040/stan.S b/arch/m68k/fpsp040/stan.S
new file mode 100644
index 000000000000..b5c2a196e617
--- /dev/null
+++ b/arch/m68k/fpsp040/stan.S
@@ -0,0 +1,455 @@
1|
2| stan.sa 3.3 7/29/91
3|
4| The entry point stan computes the tangent of
5| an input argument;
6| stand does the same except for denormalized input.
7|
8| Input: Double-extended number X in location pointed to
9| by address register a0.
10|
11| Output: The value tan(X) returned in floating-point register Fp0.
12|
13| Accuracy and Monotonicity: The returned result is within 3 ulp in
14| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
15| result is subsequently rounded to double precision. The
16| result is provably monotonic in double precision.
17|
18| Speed: The program sTAN takes approximately 170 cycles for
19| input argument X such that |X| < 15Pi, which is the usual
20| situation.
21|
22| Algorithm:
23|
24| 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.
25|
26| 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let
27| k = N mod 2, so in particular, k = 0 or 1.
28|
29| 3. If k is odd, go to 5.
30|
31| 4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a
32| rational function U/V where
33| U = r + r*s*(P1 + s*(P2 + s*P3)), and
34| V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r.
35| Exit.
36|
37| 4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by a
38| rational function U/V where
39| U = r + r*s*(P1 + s*(P2 + s*P3)), and
40| V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r,
41| -Cot(r) = -V/U. Exit.
42|
43| 6. If |X| > 1, go to 8.
44|
45| 7. (|X|<2**(-40)) Tan(X) = X. Exit.
46|
47| 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back to 2.
48|
49
50| Copyright (C) Motorola, Inc. 1990
51| All Rights Reserved
52|
53| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
54| The copyright notice above does not evidence any
55| actual or intended publication of such source code.
56
57|STAN idnt 2,1 | Motorola 040 Floating Point Software Package
58
59 |section 8
60
61#include "fpsp.h"
62
63BOUNDS1: .long 0x3FD78000,0x4004BC7E
64TWOBYPI: .long 0x3FE45F30,0x6DC9C883
65
66TANQ4: .long 0x3EA0B759,0xF50F8688
67TANP3: .long 0xBEF2BAA5,0xA8924F04
68
69TANQ3: .long 0xBF346F59,0xB39BA65F,0x00000000,0x00000000
70
71TANP2: .long 0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
72
73TANQ2: .long 0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
74
75TANP1: .long 0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
76
77TANQ1: .long 0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
78
79INVTWOPI: .long 0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
80
81TWOPI1: .long 0x40010000,0xC90FDAA2,0x00000000,0x00000000
82TWOPI2: .long 0x3FDF0000,0x85A308D4,0x00000000,0x00000000
83
84|--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
85|--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
86|--MOST 69 BITS LONG.
87 .global PITBL
88PITBL:
89 .long 0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
90 .long 0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
91 .long 0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
92 .long 0xC0040000,0xB6365E22,0xEE46F000,0x21480000
93 .long 0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
94 .long 0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
95 .long 0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
96 .long 0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
97 .long 0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
98 .long 0xC0040000,0x90836524,0x88034B96,0x20B00000
99 .long 0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
100 .long 0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
101 .long 0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
102 .long 0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
103 .long 0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
104 .long 0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
105 .long 0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
106 .long 0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
107 .long 0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
108 .long 0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
109 .long 0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
110 .long 0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
111 .long 0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
112 .long 0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
113 .long 0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
114 .long 0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
115 .long 0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
116 .long 0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
117 .long 0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
118 .long 0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
119 .long 0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
120 .long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
121 .long 0x00000000,0x00000000,0x00000000,0x00000000
122 .long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
123 .long 0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
124 .long 0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
125 .long 0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
126 .long 0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
127 .long 0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
128 .long 0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
129 .long 0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
130 .long 0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
131 .long 0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
132 .long 0x40030000,0x8A3AE64F,0x76F80584,0x21080000
133 .long 0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
134 .long 0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
135 .long 0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
136 .long 0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
137 .long 0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
138 .long 0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
139 .long 0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
140 .long 0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
141 .long 0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
142 .long 0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
143 .long 0x40040000,0x8A3AE64F,0x76F80584,0x21880000
144 .long 0x40040000,0x90836524,0x88034B96,0xA0B00000
145 .long 0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
146 .long 0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
147 .long 0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
148 .long 0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
149 .long 0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
150 .long 0x40040000,0xB6365E22,0xEE46F000,0xA1480000
151 .long 0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
152 .long 0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
153 .long 0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
154
155 .set INARG,FP_SCR4
156
157 .set TWOTO63,L_SCR1
158 .set ENDFLAG,L_SCR2
159 .set N,L_SCR3
160
161 | xref t_frcinx
162 |xref t_extdnrm
163
164 .global stand
165stand:
166|--TAN(X) = X FOR DENORMALIZED X
167
168 bra t_extdnrm
169
170 .global stan
171stan:
172 fmovex (%a0),%fp0 | ...LOAD INPUT
173
174 movel (%a0),%d0
175 movew 4(%a0),%d0
176 andil #0x7FFFFFFF,%d0
177
178 cmpil #0x3FD78000,%d0 | ...|X| >= 2**(-40)?
179 bges TANOK1
180 bra TANSM
181TANOK1:
182 cmpil #0x4004BC7E,%d0 | ...|X| < 15 PI?
183 blts TANMAIN
184 bra REDUCEX
185
186
187TANMAIN:
188|--THIS IS THE USUAL CASE, |X| <= 15 PI.
189|--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
190 fmovex %fp0,%fp1
191 fmuld TWOBYPI,%fp1 | ...X*2/PI
192
193|--HIDE THE NEXT TWO INSTRUCTIONS
194 leal PITBL+0x200,%a1 | ...TABLE OF N*PI/2, N = -32,...,32
195
196|--FP1 IS NOW READY
197 fmovel %fp1,%d0 | ...CONVERT TO INTEGER
198
199 asll #4,%d0
200 addal %d0,%a1 | ...ADDRESS N*PIBY2 IN Y1, Y2
201
202 fsubx (%a1)+,%fp0 | ...X-Y1
203|--HIDE THE NEXT ONE
204
205 fsubs (%a1),%fp0 | ...FP0 IS R = (X-Y1)-Y2
206
207 rorl #5,%d0
208 andil #0x80000000,%d0 | ...D0 WAS ODD IFF D0 < 0
209
210TANCONT:
211
212 cmpil #0,%d0
213 blt NODD
214
215 fmovex %fp0,%fp1
216 fmulx %fp1,%fp1 | ...S = R*R
217
218 fmoved TANQ4,%fp3
219 fmoved TANP3,%fp2
220
221 fmulx %fp1,%fp3 | ...SQ4
222 fmulx %fp1,%fp2 | ...SP3
223
224 faddd TANQ3,%fp3 | ...Q3+SQ4
225 faddx TANP2,%fp2 | ...P2+SP3
226
227 fmulx %fp1,%fp3 | ...S(Q3+SQ4)
228 fmulx %fp1,%fp2 | ...S(P2+SP3)
229
230 faddx TANQ2,%fp3 | ...Q2+S(Q3+SQ4)
231 faddx TANP1,%fp2 | ...P1+S(P2+SP3)
232
233 fmulx %fp1,%fp3 | ...S(Q2+S(Q3+SQ4))
234 fmulx %fp1,%fp2 | ...S(P1+S(P2+SP3))
235
236 faddx TANQ1,%fp3 | ...Q1+S(Q2+S(Q3+SQ4))
237 fmulx %fp0,%fp2 | ...RS(P1+S(P2+SP3))
238
239 fmulx %fp3,%fp1 | ...S(Q1+S(Q2+S(Q3+SQ4)))
240
241
242 faddx %fp2,%fp0 | ...R+RS(P1+S(P2+SP3))
243
244
245 fadds #0x3F800000,%fp1 | ...1+S(Q1+...)
246
247 fmovel %d1,%fpcr |restore users exceptions
248 fdivx %fp1,%fp0 |last inst - possible exception set
249
250 bra t_frcinx
251
252NODD:
253 fmovex %fp0,%fp1
254 fmulx %fp0,%fp0 | ...S = R*R
255
256 fmoved TANQ4,%fp3
257 fmoved TANP3,%fp2
258
259 fmulx %fp0,%fp3 | ...SQ4
260 fmulx %fp0,%fp2 | ...SP3
261
262 faddd TANQ3,%fp3 | ...Q3+SQ4
263 faddx TANP2,%fp2 | ...P2+SP3
264
265 fmulx %fp0,%fp3 | ...S(Q3+SQ4)
266 fmulx %fp0,%fp2 | ...S(P2+SP3)
267
268 faddx TANQ2,%fp3 | ...Q2+S(Q3+SQ4)
269 faddx TANP1,%fp2 | ...P1+S(P2+SP3)
270
271 fmulx %fp0,%fp3 | ...S(Q2+S(Q3+SQ4))
272 fmulx %fp0,%fp2 | ...S(P1+S(P2+SP3))
273
274 faddx TANQ1,%fp3 | ...Q1+S(Q2+S(Q3+SQ4))
275 fmulx %fp1,%fp2 | ...RS(P1+S(P2+SP3))
276
277 fmulx %fp3,%fp0 | ...S(Q1+S(Q2+S(Q3+SQ4)))
278
279
280 faddx %fp2,%fp1 | ...R+RS(P1+S(P2+SP3))
281 fadds #0x3F800000,%fp0 | ...1+S(Q1+...)
282
283
284 fmovex %fp1,-(%sp)
285 eoril #0x80000000,(%sp)
286
287 fmovel %d1,%fpcr |restore users exceptions
288 fdivx (%sp)+,%fp0 |last inst - possible exception set
289
290 bra t_frcinx
291
292TANBORS:
293|--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
294|--IF |X| < 2**(-40), RETURN X OR 1.
295 cmpil #0x3FFF8000,%d0
296 bgts REDUCEX
297
298TANSM:
299
300 fmovex %fp0,-(%sp)
301 fmovel %d1,%fpcr |restore users exceptions
302 fmovex (%sp)+,%fp0 |last inst - possible exception set
303
304 bra t_frcinx
305
306
307REDUCEX:
308|--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
309|--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
310|--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
311
312 fmovemx %fp2-%fp5,-(%a7) | ...save FP2 through FP5
313 movel %d2,-(%a7)
314 fmoves #0x00000000,%fp1
315
316|--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
317|--there is a danger of unwanted overflow in first LOOP iteration. In this
318|--case, reduce argument by one remainder step to make subsequent reduction
319|--safe.
320 cmpil #0x7ffeffff,%d0 |is argument dangerously large?
321 bnes LOOP
322 movel #0x7ffe0000,FP_SCR2(%a6) |yes
323| ;create 2**16383*PI/2
324 movel #0xc90fdaa2,FP_SCR2+4(%a6)
325 clrl FP_SCR2+8(%a6)
326 ftstx %fp0 |test sign of argument
327 movel #0x7fdc0000,FP_SCR3(%a6) |create low half of 2**16383*
328| ;PI/2 at FP_SCR3
329 movel #0x85a308d3,FP_SCR3+4(%a6)
330 clrl FP_SCR3+8(%a6)
331 fblt red_neg
332 orw #0x8000,FP_SCR2(%a6) |positive arg
333 orw #0x8000,FP_SCR3(%a6)
334red_neg:
335 faddx FP_SCR2(%a6),%fp0 |high part of reduction is exact
336 fmovex %fp0,%fp1 |save high result in fp1
337 faddx FP_SCR3(%a6),%fp0 |low part of reduction
338 fsubx %fp0,%fp1 |determine low component of result
339 faddx FP_SCR3(%a6),%fp1 |fp0/fp1 are reduced argument.
340
341|--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
342|--integer quotient will be stored in N
343|--Intermediate remainder is 66-bit long; (R,r) in (FP0,FP1)
344
345LOOP:
346 fmovex %fp0,INARG(%a6) | ...+-2**K * F, 1 <= F < 2
347 movew INARG(%a6),%d0
348 movel %d0,%a1 | ...save a copy of D0
349 andil #0x00007FFF,%d0
350 subil #0x00003FFF,%d0 | ...D0 IS K
351 cmpil #28,%d0
352 bles LASTLOOP
353CONTLOOP:
354 subil #27,%d0 | ...D0 IS L := K-27
355 movel #0,ENDFLAG(%a6)
356 bras WORK
357LASTLOOP:
358 clrl %d0 | ...D0 IS L := 0
359 movel #1,ENDFLAG(%a6)
360
361WORK:
362|--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
363|--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
364
365|--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
366|--2**L * (PIby2_1), 2**L * (PIby2_2)
367
368 movel #0x00003FFE,%d2 | ...BIASED EXPO OF 2/PI
369 subl %d0,%d2 | ...BIASED EXPO OF 2**(-L)*(2/PI)
370
371 movel #0xA2F9836E,FP_SCR1+4(%a6)
372 movel #0x4E44152A,FP_SCR1+8(%a6)
373 movew %d2,FP_SCR1(%a6) | ...FP_SCR1 is 2**(-L)*(2/PI)
374
375 fmovex %fp0,%fp2
376 fmulx FP_SCR1(%a6),%fp2
377|--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
378|--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
379|--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
380|--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
381|--US THE DESIRED VALUE IN FLOATING POINT.
382
383|--HIDE SIX CYCLES OF INSTRUCTION
384 movel %a1,%d2
385 swap %d2
386 andil #0x80000000,%d2
387 oril #0x5F000000,%d2 | ...D2 IS SIGN(INARG)*2**63 IN SGL
388 movel %d2,TWOTO63(%a6)
389
390 movel %d0,%d2
391 addil #0x00003FFF,%d2 | ...BIASED EXPO OF 2**L * (PI/2)
392
393|--FP2 IS READY
394 fadds TWOTO63(%a6),%fp2 | ...THE FRACTIONAL PART OF FP1 IS ROUNDED
395
396|--HIDE 4 CYCLES OF INSTRUCTION; creating 2**(L)*Piby2_1 and 2**(L)*Piby2_2
397 movew %d2,FP_SCR2(%a6)
398 clrw FP_SCR2+2(%a6)
399 movel #0xC90FDAA2,FP_SCR2+4(%a6)
400 clrl FP_SCR2+8(%a6) | ...FP_SCR2 is 2**(L) * Piby2_1
401
402|--FP2 IS READY
403 fsubs TWOTO63(%a6),%fp2 | ...FP2 is N
404
405 addil #0x00003FDD,%d0
406 movew %d0,FP_SCR3(%a6)
407 clrw FP_SCR3+2(%a6)
408 movel #0x85A308D3,FP_SCR3+4(%a6)
409 clrl FP_SCR3+8(%a6) | ...FP_SCR3 is 2**(L) * Piby2_2
410
411 movel ENDFLAG(%a6),%d0
412
413|--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
414|--P2 = 2**(L) * Piby2_2
415 fmovex %fp2,%fp4
416 fmulx FP_SCR2(%a6),%fp4 | ...W = N*P1
417 fmovex %fp2,%fp5
418 fmulx FP_SCR3(%a6),%fp5 | ...w = N*P2
419 fmovex %fp4,%fp3
420|--we want P+p = W+w but |p| <= half ulp of P
421|--Then, we need to compute A := R-P and a := r-p
422 faddx %fp5,%fp3 | ...FP3 is P
423 fsubx %fp3,%fp4 | ...W-P
424
425 fsubx %fp3,%fp0 | ...FP0 is A := R - P
426 faddx %fp5,%fp4 | ...FP4 is p = (W-P)+w
427
428 fmovex %fp0,%fp3 | ...FP3 A
429 fsubx %fp4,%fp1 | ...FP1 is a := r - p
430
431|--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
432|--|r| <= half ulp of R.
433 faddx %fp1,%fp0 | ...FP0 is R := A+a
434|--No need to calculate r if this is the last loop
435 cmpil #0,%d0
436 bgt RESTORE
437
438|--Need to calculate r
439 fsubx %fp0,%fp3 | ...A-R
440 faddx %fp3,%fp1 | ...FP1 is r := (A-R)+a
441 bra LOOP
442
443RESTORE:
444 fmovel %fp2,N(%a6)
445 movel (%a7)+,%d2
446 fmovemx (%a7)+,%fp2-%fp5
447
448
449 movel N(%a6),%d0
450 rorl #1,%d0
451
452
453 bra TANCONT
454
455 |end
diff --git a/arch/m68k/fpsp040/stanh.S b/arch/m68k/fpsp040/stanh.S
new file mode 100644
index 000000000000..33b009802243
--- /dev/null
+++ b/arch/m68k/fpsp040/stanh.S
@@ -0,0 +1,185 @@
1|
2| stanh.sa 3.1 12/10/90
3|
4| The entry point sTanh computes the hyperbolic tangent of
5| an input argument; sTanhd does the same except for denormalized
6| input.
7|
8| Input: Double-extended number X in location pointed to
9| by address register a0.
10|
11| Output: The value tanh(X) returned in floating-point register Fp0.
12|
13| Accuracy and Monotonicity: The returned result is within 3 ulps in
14| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
15| result is subsequently rounded to double precision. The
16| result is provably monotonic in double precision.
17|
18| Speed: The program stanh takes approximately 270 cycles.
19|
20| Algorithm:
21|
22| TANH
23| 1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3.
24|
25| 2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by
26| sgn := sign(X), y := 2|X|, z := expm1(Y), and
27| tanh(X) = sgn*( z/(2+z) ).
28| Exit.
29|
30| 3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1,
31| go to 7.
32|
33| 4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6.
34|
35| 5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by
36| sgn := sign(X), y := 2|X|, z := exp(Y),
37| tanh(X) = sgn - [ sgn*2/(1+z) ].
38| Exit.
39|
40| 6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we
41| calculate Tanh(X) by
42| sgn := sign(X), Tiny := 2**(-126),
43| tanh(X) := sgn - sgn*Tiny.
44| Exit.
45|
46| 7. (|X| < 2**(-40)). Tanh(X) = X. Exit.
47|
48
49| Copyright (C) Motorola, Inc. 1990
50| All Rights Reserved
51|
52| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
53| The copyright notice above does not evidence any
54| actual or intended publication of such source code.
55
56|STANH idnt 2,1 | Motorola 040 Floating Point Software Package
57
58 |section 8
59
60#include "fpsp.h"
61
62 .set X,FP_SCR5
63 .set XDCARE,X+2
64 .set XFRAC,X+4
65
66 .set SGN,L_SCR3
67
68 .set V,FP_SCR6
69
70BOUNDS1: .long 0x3FD78000,0x3FFFDDCE | ... 2^(-40), (5/2)LOG2
71
72 |xref t_frcinx
73 |xref t_extdnrm
74 |xref setox
75 |xref setoxm1
76
77 .global stanhd
78stanhd:
79|--TANH(X) = X FOR DENORMALIZED X
80
81 bra t_extdnrm
82
83 .global stanh
84stanh:
85 fmovex (%a0),%fp0 | ...LOAD INPUT
86
87 fmovex %fp0,X(%a6)
88 movel (%a0),%d0
89 movew 4(%a0),%d0
90 movel %d0,X(%a6)
91 andl #0x7FFFFFFF,%d0
92 cmp2l BOUNDS1(%pc),%d0 | ...2**(-40) < |X| < (5/2)LOG2 ?
93 bcss TANHBORS
94
95|--THIS IS THE USUAL CASE
96|--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
97
98 movel X(%a6),%d0
99 movel %d0,SGN(%a6)
100 andl #0x7FFF0000,%d0
101 addl #0x00010000,%d0 | ...EXPONENT OF 2|X|
102 movel %d0,X(%a6)
103 andl #0x80000000,SGN(%a6)
104 fmovex X(%a6),%fp0 | ...FP0 IS Y = 2|X|
105
106 movel %d1,-(%a7)
107 clrl %d1
108 fmovemx %fp0-%fp0,(%a0)
109 bsr setoxm1 | ...FP0 IS Z = EXPM1(Y)
110 movel (%a7)+,%d1
111
112 fmovex %fp0,%fp1
113 fadds #0x40000000,%fp1 | ...Z+2
114 movel SGN(%a6),%d0
115 fmovex %fp1,V(%a6)
116 eorl %d0,V(%a6)
117
118 fmovel %d1,%FPCR |restore users exceptions
119 fdivx V(%a6),%fp0
120 bra t_frcinx
121
122TANHBORS:
123 cmpl #0x3FFF8000,%d0
124 blt TANHSM
125
126 cmpl #0x40048AA1,%d0
127 bgt TANHHUGE
128
129|-- (5/2) LOG2 < |X| < 50 LOG2,
130|--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
131|--TANH(X) = SGN - SGN*2/[EXP(Y)+1].
132
133 movel X(%a6),%d0
134 movel %d0,SGN(%a6)
135 andl #0x7FFF0000,%d0
136 addl #0x00010000,%d0 | ...EXPO OF 2|X|
137 movel %d0,X(%a6) | ...Y = 2|X|
138 andl #0x80000000,SGN(%a6)
139 movel SGN(%a6),%d0
140 fmovex X(%a6),%fp0 | ...Y = 2|X|
141
142 movel %d1,-(%a7)
143 clrl %d1
144 fmovemx %fp0-%fp0,(%a0)
145 bsr setox | ...FP0 IS EXP(Y)
146 movel (%a7)+,%d1
147 movel SGN(%a6),%d0
148 fadds #0x3F800000,%fp0 | ...EXP(Y)+1
149
150 eorl #0xC0000000,%d0 | ...-SIGN(X)*2
151 fmoves %d0,%fp1 | ...-SIGN(X)*2 IN SGL FMT
152 fdivx %fp0,%fp1 | ...-SIGN(X)2 / [EXP(Y)+1 ]
153
154 movel SGN(%a6),%d0
155 orl #0x3F800000,%d0 | ...SGN
156 fmoves %d0,%fp0 | ...SGN IN SGL FMT
157
158 fmovel %d1,%FPCR |restore users exceptions
159 faddx %fp1,%fp0
160
161 bra t_frcinx
162
163TANHSM:
164 movew #0x0000,XDCARE(%a6)
165
166 fmovel %d1,%FPCR |restore users exceptions
167 fmovex X(%a6),%fp0 |last inst - possible exception set
168
169 bra t_frcinx
170
171TANHHUGE:
172|---RETURN SGN(X) - SGN(X)EPS
173 movel X(%a6),%d0
174 andl #0x80000000,%d0
175 orl #0x3F800000,%d0
176 fmoves %d0,%fp0
177 andl #0x80000000,%d0
178 eorl #0x80800000,%d0 | ...-SIGN(X)*EPS
179
180 fmovel %d1,%FPCR |restore users exceptions
181 fadds %d0,%fp0
182
183 bra t_frcinx
184
185 |end
diff --git a/arch/m68k/fpsp040/sto_res.S b/arch/m68k/fpsp040/sto_res.S
new file mode 100644
index 000000000000..0cdca3b060ad
--- /dev/null
+++ b/arch/m68k/fpsp040/sto_res.S
@@ -0,0 +1,98 @@
1|
2| sto_res.sa 3.1 12/10/90
3|
4| Takes the result and puts it in where the user expects it.
5| Library functions return result in fp0. If fp0 is not the
6| users destination register then fp0 is moved to the
7| correct floating-point destination register. fp0 and fp1
8| are then restored to the original contents.
9|
10| Input: result in fp0,fp1
11|
12| d2 & a0 should be kept unmodified
13|
14| Output: moves the result to the true destination reg or mem
15|
16| Modifies: destination floating point register
17|
18
19| Copyright (C) Motorola, Inc. 1990
20| All Rights Reserved
21|
22| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
23| The copyright notice above does not evidence any
24| actual or intended publication of such source code.
25
26STO_RES: |idnt 2,1 | Motorola 040 Floating Point Software Package
27
28
29 |section 8
30
31#include "fpsp.h"
32
33 .global sto_cos
34sto_cos:
35 bfextu CMDREG1B(%a6){#13:#3},%d0 |extract cos destination
36 cmpib #3,%d0 |check for fp0/fp1 cases
37 bles c_fp0123
38 fmovemx %fp1-%fp1,-(%a7)
39 moveql #7,%d1
40 subl %d0,%d1 |d1 = 7- (dest. reg. no.)
41 clrl %d0
42 bsetl %d1,%d0 |d0 is dynamic register mask
43 fmovemx (%a7)+,%d0
44 rts
45c_fp0123:
46 cmpib #0,%d0
47 beqs c_is_fp0
48 cmpib #1,%d0
49 beqs c_is_fp1
50 cmpib #2,%d0
51 beqs c_is_fp2
52c_is_fp3:
53 fmovemx %fp1-%fp1,USER_FP3(%a6)
54 rts
55c_is_fp2:
56 fmovemx %fp1-%fp1,USER_FP2(%a6)
57 rts
58c_is_fp1:
59 fmovemx %fp1-%fp1,USER_FP1(%a6)
60 rts
61c_is_fp0:
62 fmovemx %fp1-%fp1,USER_FP0(%a6)
63 rts
64
65
66 .global sto_res
67sto_res:
68 bfextu CMDREG1B(%a6){#6:#3},%d0 |extract destination register
69 cmpib #3,%d0 |check for fp0/fp1 cases
70 bles fp0123
71 fmovemx %fp0-%fp0,-(%a7)
72 moveql #7,%d1
73 subl %d0,%d1 |d1 = 7- (dest. reg. no.)
74 clrl %d0
75 bsetl %d1,%d0 |d0 is dynamic register mask
76 fmovemx (%a7)+,%d0
77 rts
78fp0123:
79 cmpib #0,%d0
80 beqs is_fp0
81 cmpib #1,%d0
82 beqs is_fp1
83 cmpib #2,%d0
84 beqs is_fp2
85is_fp3:
86 fmovemx %fp0-%fp0,USER_FP3(%a6)
87 rts
88is_fp2:
89 fmovemx %fp0-%fp0,USER_FP2(%a6)
90 rts
91is_fp1:
92 fmovemx %fp0-%fp0,USER_FP1(%a6)
93 rts
94is_fp0:
95 fmovemx %fp0-%fp0,USER_FP0(%a6)
96 rts
97
98 |end
diff --git a/arch/m68k/fpsp040/stwotox.S b/arch/m68k/fpsp040/stwotox.S
new file mode 100644
index 000000000000..4e3c1407d3df
--- /dev/null
+++ b/arch/m68k/fpsp040/stwotox.S
@@ -0,0 +1,427 @@
1|
2| stwotox.sa 3.1 12/10/90
3|
4| stwotox --- 2**X
5| stwotoxd --- 2**X for denormalized X
6| stentox --- 10**X
7| stentoxd --- 10**X for denormalized X
8|
9| Input: Double-extended number X in location pointed to
10| by address register a0.
11|
12| Output: The function values are returned in Fp0.
13|
14| Accuracy and Monotonicity: The returned result is within 2 ulps in
15| 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
16| result is subsequently rounded to double precision. The
17| result is provably monotonic in double precision.
18|
19| Speed: The program stwotox takes approximately 190 cycles and the
20| program stentox takes approximately 200 cycles.
21|
22| Algorithm:
23|
24| twotox
25| 1. If |X| > 16480, go to ExpBig.
26|
27| 2. If |X| < 2**(-70), go to ExpSm.
28|
29| 3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore
30| decompose N as
31| N = 64(M + M') + j, j = 0,1,2,...,63.
32|
33| 4. Overwrite r := r * log2. Then
34| 2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).
35| Go to expr to compute that expression.
36|
37| tentox
38| 1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig.
39|
40| 2. If |X| < 2**(-70), go to ExpSm.
41|
42| 3. Set y := X*log_2(10)*64 (base 2 log of 10). Set
43| N := round-to-int(y). Decompose N as
44| N = 64(M + M') + j, j = 0,1,2,...,63.
45|
46| 4. Define r as
47| r := ((X - N*L1)-N*L2) * L10
48| where L1, L2 are the leading and trailing parts of log_10(2)/64
49| and L10 is the natural log of 10. Then
50| 10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).
51| Go to expr to compute that expression.
52|
53| expr
54| 1. Fetch 2**(j/64) from table as Fact1 and Fact2.
55|
56| 2. Overwrite Fact1 and Fact2 by
57| Fact1 := 2**(M) * Fact1
58| Fact2 := 2**(M) * Fact2
59| Thus Fact1 + Fact2 = 2**(M) * 2**(j/64).
60|
61| 3. Calculate P where 1 + P approximates exp(r):
62| P = r + r*r*(A1+r*(A2+...+r*A5)).
63|
64| 4. Let AdjFact := 2**(M'). Return
65| AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ).
66| Exit.
67|
68| ExpBig
69| 1. Generate overflow by Huge * Huge if X > 0; otherwise, generate
70| underflow by Tiny * Tiny.
71|
72| ExpSm
73| 1. Return 1 + X.
74|
75
76| Copyright (C) Motorola, Inc. 1990
77| All Rights Reserved
78|
79| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
80| The copyright notice above does not evidence any
81| actual or intended publication of such source code.
82
83|STWOTOX idnt 2,1 | Motorola 040 Floating Point Software Package
84
85 |section 8
86
87#include "fpsp.h"
88
89BOUNDS1: .long 0x3FB98000,0x400D80C0 | ... 2^(-70),16480
90BOUNDS2: .long 0x3FB98000,0x400B9B07 | ... 2^(-70),16480 LOG2/LOG10
91
92L2TEN64: .long 0x406A934F,0x0979A371 | ... 64LOG10/LOG2
93L10TWO1: .long 0x3F734413,0x509F8000 | ... LOG2/64LOG10
94
95L10TWO2: .long 0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
96
97LOG10: .long 0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
98
99LOG2: .long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
100
101EXPA5: .long 0x3F56C16D,0x6F7BD0B2
102EXPA4: .long 0x3F811112,0x302C712C
103EXPA3: .long 0x3FA55555,0x55554CC1
104EXPA2: .long 0x3FC55555,0x55554A54
105EXPA1: .long 0x3FE00000,0x00000000,0x00000000,0x00000000
106
107HUGE: .long 0x7FFE0000,0xFFFFFFFF,0xFFFFFFFF,0x00000000
108TINY: .long 0x00010000,0xFFFFFFFF,0xFFFFFFFF,0x00000000
109
110EXPTBL:
111 .long 0x3FFF0000,0x80000000,0x00000000,0x3F738000
112 .long 0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
113 .long 0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
114 .long 0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
115 .long 0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
116 .long 0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
117 .long 0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
118 .long 0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
119 .long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
120 .long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
121 .long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
122 .long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
123 .long 0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
124 .long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
125 .long 0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
126 .long 0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
127 .long 0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
128 .long 0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
129 .long 0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
130 .long 0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
131 .long 0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
132 .long 0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
133 .long 0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
134 .long 0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
135 .long 0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
136 .long 0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
137 .long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
138 .long 0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
139 .long 0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
140 .long 0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
141 .long 0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
142 .long 0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
143 .long 0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
144 .long 0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
145 .long 0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
146 .long 0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
147 .long 0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
148 .long 0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
149 .long 0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
150 .long 0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
151 .long 0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
152 .long 0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
153 .long 0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
154 .long 0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
155 .long 0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
156 .long 0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
157 .long 0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
158 .long 0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
159 .long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
160 .long 0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
161 .long 0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
162 .long 0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
163 .long 0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
164 .long 0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
165 .long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
166 .long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
167 .long 0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
168 .long 0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
169 .long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
170 .long 0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
171 .long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
172 .long 0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
173 .long 0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
174 .long 0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
175
176 .set N,L_SCR1
177
178 .set X,FP_SCR1
179 .set XDCARE,X+2
180 .set XFRAC,X+4
181
182 .set ADJFACT,FP_SCR2
183
184 .set FACT1,FP_SCR3
185 .set FACT1HI,FACT1+4
186 .set FACT1LOW,FACT1+8
187
188 .set FACT2,FP_SCR4
189 .set FACT2HI,FACT2+4
190 .set FACT2LOW,FACT2+8
191
192 | xref t_unfl
193 |xref t_ovfl
194 |xref t_frcinx
195
196 .global stwotoxd
197stwotoxd:
198|--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
199
200 fmovel %d1,%fpcr | ...set user's rounding mode/precision
201 fmoves #0x3F800000,%fp0 | ...RETURN 1 + X
202 movel (%a0),%d0
203 orl #0x00800001,%d0
204 fadds %d0,%fp0
205 bra t_frcinx
206
207 .global stwotox
208stwotox:
209|--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
210 fmovemx (%a0),%fp0-%fp0 | ...LOAD INPUT, do not set cc's
211
212 movel (%a0),%d0
213 movew 4(%a0),%d0
214 fmovex %fp0,X(%a6)
215 andil #0x7FFFFFFF,%d0
216
217 cmpil #0x3FB98000,%d0 | ...|X| >= 2**(-70)?
218 bges TWOOK1
219 bra EXPBORS
220
221TWOOK1:
222 cmpil #0x400D80C0,%d0 | ...|X| > 16480?
223 bles TWOMAIN
224 bra EXPBORS
225
226
227TWOMAIN:
228|--USUAL CASE, 2^(-70) <= |X| <= 16480
229
230 fmovex %fp0,%fp1
231 fmuls #0x42800000,%fp1 | ...64 * X
232
233 fmovel %fp1,N(%a6) | ...N = ROUND-TO-INT(64 X)
234 movel %d2,-(%sp)
235 lea EXPTBL,%a1 | ...LOAD ADDRESS OF TABLE OF 2^(J/64)
236 fmovel N(%a6),%fp1 | ...N --> FLOATING FMT
237 movel N(%a6),%d0
238 movel %d0,%d2
239 andil #0x3F,%d0 | ...D0 IS J
240 asll #4,%d0 | ...DISPLACEMENT FOR 2^(J/64)
241 addal %d0,%a1 | ...ADDRESS FOR 2^(J/64)
242 asrl #6,%d2 | ...d2 IS L, N = 64L + J
243 movel %d2,%d0
244 asrl #1,%d0 | ...D0 IS M
245 subl %d0,%d2 | ...d2 IS M', N = 64(M+M') + J
246 addil #0x3FFF,%d2
247 movew %d2,ADJFACT(%a6) | ...ADJFACT IS 2^(M')
248 movel (%sp)+,%d2
249|--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
250|--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
251|--ADJFACT = 2^(M').
252|--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
253
254 fmuls #0x3C800000,%fp1 | ...(1/64)*N
255 movel (%a1)+,FACT1(%a6)
256 movel (%a1)+,FACT1HI(%a6)
257 movel (%a1)+,FACT1LOW(%a6)
258 movew (%a1)+,FACT2(%a6)
259 clrw FACT2+2(%a6)
260
261 fsubx %fp1,%fp0 | ...X - (1/64)*INT(64 X)
262
263 movew (%a1)+,FACT2HI(%a6)
264 clrw FACT2HI+2(%a6)
265 clrl FACT2LOW(%a6)
266 addw %d0,FACT1(%a6)
267
268 fmulx LOG2,%fp0 | ...FP0 IS R
269 addw %d0,FACT2(%a6)
270
271 bra expr
272
273EXPBORS:
274|--FPCR, D0 SAVED
275 cmpil #0x3FFF8000,%d0
276 bgts EXPBIG
277
278EXPSM:
279|--|X| IS SMALL, RETURN 1 + X
280
281 fmovel %d1,%FPCR |restore users exceptions
282 fadds #0x3F800000,%fp0 | ...RETURN 1 + X
283
284 bra t_frcinx
285
286EXPBIG:
287|--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
288|--REGISTERS SAVE SO FAR ARE FPCR AND D0
289 movel X(%a6),%d0
290 cmpil #0,%d0
291 blts EXPNEG
292
293 bclrb #7,(%a0) |t_ovfl expects positive value
294 bra t_ovfl
295
296EXPNEG:
297 bclrb #7,(%a0) |t_unfl expects positive value
298 bra t_unfl
299
300 .global stentoxd
301stentoxd:
302|--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
303
304 fmovel %d1,%fpcr | ...set user's rounding mode/precision
305 fmoves #0x3F800000,%fp0 | ...RETURN 1 + X
306 movel (%a0),%d0
307 orl #0x00800001,%d0
308 fadds %d0,%fp0
309 bra t_frcinx
310
311 .global stentox
312stentox:
313|--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
314 fmovemx (%a0),%fp0-%fp0 | ...LOAD INPUT, do not set cc's
315
316 movel (%a0),%d0
317 movew 4(%a0),%d0
318 fmovex %fp0,X(%a6)
319 andil #0x7FFFFFFF,%d0
320
321 cmpil #0x3FB98000,%d0 | ...|X| >= 2**(-70)?
322 bges TENOK1
323 bra EXPBORS
324
325TENOK1:
326 cmpil #0x400B9B07,%d0 | ...|X| <= 16480*log2/log10 ?
327 bles TENMAIN
328 bra EXPBORS
329
330TENMAIN:
331|--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
332
333 fmovex %fp0,%fp1
334 fmuld L2TEN64,%fp1 | ...X*64*LOG10/LOG2
335
336 fmovel %fp1,N(%a6) | ...N=INT(X*64*LOG10/LOG2)
337 movel %d2,-(%sp)
338 lea EXPTBL,%a1 | ...LOAD ADDRESS OF TABLE OF 2^(J/64)
339 fmovel N(%a6),%fp1 | ...N --> FLOATING FMT
340 movel N(%a6),%d0
341 movel %d0,%d2
342 andil #0x3F,%d0 | ...D0 IS J
343 asll #4,%d0 | ...DISPLACEMENT FOR 2^(J/64)
344 addal %d0,%a1 | ...ADDRESS FOR 2^(J/64)
345 asrl #6,%d2 | ...d2 IS L, N = 64L + J
346 movel %d2,%d0
347 asrl #1,%d0 | ...D0 IS M
348 subl %d0,%d2 | ...d2 IS M', N = 64(M+M') + J
349 addil #0x3FFF,%d2
350 movew %d2,ADJFACT(%a6) | ...ADJFACT IS 2^(M')
351 movel (%sp)+,%d2
352
353|--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
354|--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
355|--ADJFACT = 2^(M').
356|--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
357
358 fmovex %fp1,%fp2
359
360 fmuld L10TWO1,%fp1 | ...N*(LOG2/64LOG10)_LEAD
361 movel (%a1)+,FACT1(%a6)
362
363 fmulx L10TWO2,%fp2 | ...N*(LOG2/64LOG10)_TRAIL
364
365 movel (%a1)+,FACT1HI(%a6)
366 movel (%a1)+,FACT1LOW(%a6)
367 fsubx %fp1,%fp0 | ...X - N L_LEAD
368 movew (%a1)+,FACT2(%a6)
369
370 fsubx %fp2,%fp0 | ...X - N L_TRAIL
371
372 clrw FACT2+2(%a6)
373 movew (%a1)+,FACT2HI(%a6)
374 clrw FACT2HI+2(%a6)
375 clrl FACT2LOW(%a6)
376
377 fmulx LOG10,%fp0 | ...FP0 IS R
378
379 addw %d0,FACT1(%a6)
380 addw %d0,FACT2(%a6)
381
382expr:
383|--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
384|--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
385|--FP0 IS R. THE FOLLOWING CODE COMPUTES
386|-- 2**(M'+M) * 2**(J/64) * EXP(R)
387
388 fmovex %fp0,%fp1
389 fmulx %fp1,%fp1 | ...FP1 IS S = R*R
390
391 fmoved EXPA5,%fp2 | ...FP2 IS A5
392 fmoved EXPA4,%fp3 | ...FP3 IS A4
393
394 fmulx %fp1,%fp2 | ...FP2 IS S*A5
395 fmulx %fp1,%fp3 | ...FP3 IS S*A4
396
397 faddd EXPA3,%fp2 | ...FP2 IS A3+S*A5
398 faddd EXPA2,%fp3 | ...FP3 IS A2+S*A4
399
400 fmulx %fp1,%fp2 | ...FP2 IS S*(A3+S*A5)
401 fmulx %fp1,%fp3 | ...FP3 IS S*(A2+S*A4)
402
403 faddd EXPA1,%fp2 | ...FP2 IS A1+S*(A3+S*A5)
404 fmulx %fp0,%fp3 | ...FP3 IS R*S*(A2+S*A4)
405
406 fmulx %fp1,%fp2 | ...FP2 IS S*(A1+S*(A3+S*A5))
407 faddx %fp3,%fp0 | ...FP0 IS R+R*S*(A2+S*A4)
408
409 faddx %fp2,%fp0 | ...FP0 IS EXP(R) - 1
410
411
412|--FINAL RECONSTRUCTION PROCESS
413|--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1) - (1 OR 0)
414
415 fmulx FACT1(%a6),%fp0
416 faddx FACT2(%a6),%fp0
417 faddx FACT1(%a6),%fp0
418
419 fmovel %d1,%FPCR |restore users exceptions
420 clrw ADJFACT+2(%a6)
421 movel #0x80000000,ADJFACT+4(%a6)
422 clrl ADJFACT+8(%a6)
423 fmulx ADJFACT(%a6),%fp0 | ...FINAL ADJUSTMENT
424
425 bra t_frcinx
426
427 |end
diff --git a/arch/m68k/fpsp040/tbldo.S b/arch/m68k/fpsp040/tbldo.S
new file mode 100644
index 000000000000..fe60cf4d20d7
--- /dev/null
+++ b/arch/m68k/fpsp040/tbldo.S
@@ -0,0 +1,554 @@
1|
2| tbldo.sa 3.1 12/10/90
3|
4| Modified:
5| 8/16/90 chinds The table was constructed to use only one level
6| of indirection in do_func for monadic
7| functions. Dyadic functions require two
8| levels, and the tables are still contained
9| in do_func. The table is arranged for
10| index with a 10-bit index, with the first
11| 7 bits the opcode, and the remaining 3
12| the stag. For dyadic functions, all
13| valid addresses are to the generic entry
14| point.
15|
16
17| Copyright (C) Motorola, Inc. 1990
18| All Rights Reserved
19|
20| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
21| The copyright notice above does not evidence any
22| actual or intended publication of such source code.
23
24|TBLDO idnt 2,1 | Motorola 040 Floating Point Software Package
25
26 |section 8
27
28 |xref ld_pinf,ld_pone,ld_ppi2
29 |xref t_dz2,t_operr
30 |xref serror,sone,szero,sinf,snzrinx
31 |xref sopr_inf,spi_2,src_nan,szr_inf
32
33 |xref smovcr
34 |xref pmod,prem,pscale
35 |xref satanh,satanhd
36 |xref sacos,sacosd,sasin,sasind,satan,satand
37 |xref setox,setoxd,setoxm1,setoxm1d,setoxm1i
38 |xref sgetexp,sgetexpd,sgetman,sgetmand
39 |xref sint,sintd,sintrz
40 |xref ssincos,ssincosd,ssincosi,ssincosnan,ssincosz
41 |xref scos,scosd,ssin,ssind,stan,stand
42 |xref scosh,scoshd,ssinh,ssinhd,stanh,stanhd
43 |xref sslog10,sslog2,sslogn,sslognp1
44 |xref sslog10d,sslog2d,sslognd,slognp1d
45 |xref stentox,stentoxd,stwotox,stwotoxd
46
47| instruction ;opcode-stag Notes
48 .global tblpre
49tblpre:
50 .long smovcr |$00-0 fmovecr all
51 .long smovcr |$00-1 fmovecr all
52 .long smovcr |$00-2 fmovecr all
53 .long smovcr |$00-3 fmovecr all
54 .long smovcr |$00-4 fmovecr all
55 .long smovcr |$00-5 fmovecr all
56 .long smovcr |$00-6 fmovecr all
57 .long smovcr |$00-7 fmovecr all
58
59 .long sint |$01-0 fint norm
60 .long szero |$01-1 fint zero
61 .long sinf |$01-2 fint inf
62 .long src_nan |$01-3 fint nan
63 .long sintd |$01-4 fint denorm inx
64 .long serror |$01-5 fint ERROR
65 .long serror |$01-6 fint ERROR
66 .long serror |$01-7 fint ERROR
67
68 .long ssinh |$02-0 fsinh norm
69 .long szero |$02-1 fsinh zero
70 .long sinf |$02-2 fsinh inf
71 .long src_nan |$02-3 fsinh nan
72 .long ssinhd |$02-4 fsinh denorm
73 .long serror |$02-5 fsinh ERROR
74 .long serror |$02-6 fsinh ERROR
75 .long serror |$02-7 fsinh ERROR
76
77 .long sintrz |$03-0 fintrz norm
78 .long szero |$03-1 fintrz zero
79 .long sinf |$03-2 fintrz inf
80 .long src_nan |$03-3 fintrz nan
81 .long snzrinx |$03-4 fintrz denorm inx
82 .long serror |$03-5 fintrz ERROR
83 .long serror |$03-6 fintrz ERROR
84 .long serror |$03-7 fintrz ERROR
85
86 .long serror |$04-0 ERROR - illegal extension
87 .long serror |$04-1 ERROR - illegal extension
88 .long serror |$04-2 ERROR - illegal extension
89 .long serror |$04-3 ERROR - illegal extension
90 .long serror |$04-4 ERROR - illegal extension
91 .long serror |$04-5 ERROR - illegal extension
92 .long serror |$04-6 ERROR - illegal extension
93 .long serror |$04-7 ERROR - illegal extension
94
95 .long serror |$05-0 ERROR - illegal extension
96 .long serror |$05-1 ERROR - illegal extension
97 .long serror |$05-2 ERROR - illegal extension
98 .long serror |$05-3 ERROR - illegal extension
99 .long serror |$05-4 ERROR - illegal extension
100 .long serror |$05-5 ERROR - illegal extension
101 .long serror |$05-6 ERROR - illegal extension
102 .long serror |$05-7 ERROR - illegal extension
103
104 .long sslognp1 |$06-0 flognp1 norm
105 .long szero |$06-1 flognp1 zero
106 .long sopr_inf |$06-2 flognp1 inf
107 .long src_nan |$06-3 flognp1 nan
108 .long slognp1d |$06-4 flognp1 denorm
109 .long serror |$06-5 flognp1 ERROR
110 .long serror |$06-6 flognp1 ERROR
111 .long serror |$06-7 flognp1 ERROR
112
113 .long serror |$07-0 ERROR - illegal extension
114 .long serror |$07-1 ERROR - illegal extension
115 .long serror |$07-2 ERROR - illegal extension
116 .long serror |$07-3 ERROR - illegal extension
117 .long serror |$07-4 ERROR - illegal extension
118 .long serror |$07-5 ERROR - illegal extension
119 .long serror |$07-6 ERROR - illegal extension
120 .long serror |$07-7 ERROR - illegal extension
121
122 .long setoxm1 |$08-0 fetoxm1 norm
123 .long szero |$08-1 fetoxm1 zero
124 .long setoxm1i |$08-2 fetoxm1 inf
125 .long src_nan |$08-3 fetoxm1 nan
126 .long setoxm1d |$08-4 fetoxm1 denorm
127 .long serror |$08-5 fetoxm1 ERROR
128 .long serror |$08-6 fetoxm1 ERROR
129 .long serror |$08-7 fetoxm1 ERROR
130
131 .long stanh |$09-0 ftanh norm
132 .long szero |$09-1 ftanh zero
133 .long sone |$09-2 ftanh inf
134 .long src_nan |$09-3 ftanh nan
135 .long stanhd |$09-4 ftanh denorm
136 .long serror |$09-5 ftanh ERROR
137 .long serror |$09-6 ftanh ERROR
138 .long serror |$09-7 ftanh ERROR
139
140 .long satan |$0a-0 fatan norm
141 .long szero |$0a-1 fatan zero
142 .long spi_2 |$0a-2 fatan inf
143 .long src_nan |$0a-3 fatan nan
144 .long satand |$0a-4 fatan denorm
145 .long serror |$0a-5 fatan ERROR
146 .long serror |$0a-6 fatan ERROR
147 .long serror |$0a-7 fatan ERROR
148
149 .long serror |$0b-0 ERROR - illegal extension
150 .long serror |$0b-1 ERROR - illegal extension
151 .long serror |$0b-2 ERROR - illegal extension
152 .long serror |$0b-3 ERROR - illegal extension
153 .long serror |$0b-4 ERROR - illegal extension
154 .long serror |$0b-5 ERROR - illegal extension
155 .long serror |$0b-6 ERROR - illegal extension
156 .long serror |$0b-7 ERROR - illegal extension
157
158 .long sasin |$0c-0 fasin norm
159 .long szero |$0c-1 fasin zero
160 .long t_operr |$0c-2 fasin inf
161 .long src_nan |$0c-3 fasin nan
162 .long sasind |$0c-4 fasin denorm
163 .long serror |$0c-5 fasin ERROR
164 .long serror |$0c-6 fasin ERROR
165 .long serror |$0c-7 fasin ERROR
166
167 .long satanh |$0d-0 fatanh norm
168 .long szero |$0d-1 fatanh zero
169 .long t_operr |$0d-2 fatanh inf
170 .long src_nan |$0d-3 fatanh nan
171 .long satanhd |$0d-4 fatanh denorm
172 .long serror |$0d-5 fatanh ERROR
173 .long serror |$0d-6 fatanh ERROR
174 .long serror |$0d-7 fatanh ERROR
175
176 .long ssin |$0e-0 fsin norm
177 .long szero |$0e-1 fsin zero
178 .long t_operr |$0e-2 fsin inf
179 .long src_nan |$0e-3 fsin nan
180 .long ssind |$0e-4 fsin denorm
181 .long serror |$0e-5 fsin ERROR
182 .long serror |$0e-6 fsin ERROR
183 .long serror |$0e-7 fsin ERROR
184
185 .long stan |$0f-0 ftan norm
186 .long szero |$0f-1 ftan zero
187 .long t_operr |$0f-2 ftan inf
188 .long src_nan |$0f-3 ftan nan
189 .long stand |$0f-4 ftan denorm
190 .long serror |$0f-5 ftan ERROR
191 .long serror |$0f-6 ftan ERROR
192 .long serror |$0f-7 ftan ERROR
193
194 .long setox |$10-0 fetox norm
195 .long ld_pone |$10-1 fetox zero
196 .long szr_inf |$10-2 fetox inf
197 .long src_nan |$10-3 fetox nan
198 .long setoxd |$10-4 fetox denorm
199 .long serror |$10-5 fetox ERROR
200 .long serror |$10-6 fetox ERROR
201 .long serror |$10-7 fetox ERROR
202
203 .long stwotox |$11-0 ftwotox norm
204 .long ld_pone |$11-1 ftwotox zero
205 .long szr_inf |$11-2 ftwotox inf
206 .long src_nan |$11-3 ftwotox nan
207 .long stwotoxd |$11-4 ftwotox denorm
208 .long serror |$11-5 ftwotox ERROR
209 .long serror |$11-6 ftwotox ERROR
210 .long serror |$11-7 ftwotox ERROR
211
212 .long stentox |$12-0 ftentox norm
213 .long ld_pone |$12-1 ftentox zero
214 .long szr_inf |$12-2 ftentox inf
215 .long src_nan |$12-3 ftentox nan
216 .long stentoxd |$12-4 ftentox denorm
217 .long serror |$12-5 ftentox ERROR
218 .long serror |$12-6 ftentox ERROR
219 .long serror |$12-7 ftentox ERROR
220
221 .long serror |$13-0 ERROR - illegal extension
222 .long serror |$13-1 ERROR - illegal extension
223 .long serror |$13-2 ERROR - illegal extension
224 .long serror |$13-3 ERROR - illegal extension
225 .long serror |$13-4 ERROR - illegal extension
226 .long serror |$13-5 ERROR - illegal extension
227 .long serror |$13-6 ERROR - illegal extension
228 .long serror |$13-7 ERROR - illegal extension
229
230 .long sslogn |$14-0 flogn norm
231 .long t_dz2 |$14-1 flogn zero
232 .long sopr_inf |$14-2 flogn inf
233 .long src_nan |$14-3 flogn nan
234 .long sslognd |$14-4 flogn denorm
235 .long serror |$14-5 flogn ERROR
236 .long serror |$14-6 flogn ERROR
237 .long serror |$14-7 flogn ERROR
238
239 .long sslog10 |$15-0 flog10 norm
240 .long t_dz2 |$15-1 flog10 zero
241 .long sopr_inf |$15-2 flog10 inf
242 .long src_nan |$15-3 flog10 nan
243 .long sslog10d |$15-4 flog10 denorm
244 .long serror |$15-5 flog10 ERROR
245 .long serror |$15-6 flog10 ERROR
246 .long serror |$15-7 flog10 ERROR
247
248 .long sslog2 |$16-0 flog2 norm
249 .long t_dz2 |$16-1 flog2 zero
250 .long sopr_inf |$16-2 flog2 inf
251 .long src_nan |$16-3 flog2 nan
252 .long sslog2d |$16-4 flog2 denorm
253 .long serror |$16-5 flog2 ERROR
254 .long serror |$16-6 flog2 ERROR
255 .long serror |$16-7 flog2 ERROR
256
257 .long serror |$17-0 ERROR - illegal extension
258 .long serror |$17-1 ERROR - illegal extension
259 .long serror |$17-2 ERROR - illegal extension
260 .long serror |$17-3 ERROR - illegal extension
261 .long serror |$17-4 ERROR - illegal extension
262 .long serror |$17-5 ERROR - illegal extension
263 .long serror |$17-6 ERROR - illegal extension
264 .long serror |$17-7 ERROR - illegal extension
265
266 .long serror |$18-0 ERROR - illegal extension
267 .long serror |$18-1 ERROR - illegal extension
268 .long serror |$18-2 ERROR - illegal extension
269 .long serror |$18-3 ERROR - illegal extension
270 .long serror |$18-4 ERROR - illegal extension
271 .long serror |$18-5 ERROR - illegal extension
272 .long serror |$18-6 ERROR - illegal extension
273 .long serror |$18-7 ERROR - illegal extension
274
275 .long scosh |$19-0 fcosh norm
276 .long ld_pone |$19-1 fcosh zero
277 .long ld_pinf |$19-2 fcosh inf
278 .long src_nan |$19-3 fcosh nan
279 .long scoshd |$19-4 fcosh denorm
280 .long serror |$19-5 fcosh ERROR
281 .long serror |$19-6 fcosh ERROR
282 .long serror |$19-7 fcosh ERROR
283
284 .long serror |$1a-0 ERROR - illegal extension
285 .long serror |$1a-1 ERROR - illegal extension
286 .long serror |$1a-2 ERROR - illegal extension
287 .long serror |$1a-3 ERROR - illegal extension
288 .long serror |$1a-4 ERROR - illegal extension
289 .long serror |$1a-5 ERROR - illegal extension
290 .long serror |$1a-6 ERROR - illegal extension
291 .long serror |$1a-7 ERROR - illegal extension
292
293 .long serror |$1b-0 ERROR - illegal extension
294 .long serror |$1b-1 ERROR - illegal extension
295 .long serror |$1b-2 ERROR - illegal extension
296 .long serror |$1b-3 ERROR - illegal extension
297 .long serror |$1b-4 ERROR - illegal extension
298 .long serror |$1b-5 ERROR - illegal extension
299 .long serror |$1b-6 ERROR - illegal extension
300 .long serror |$1b-7 ERROR - illegal extension
301
302 .long sacos |$1c-0 facos norm
303 .long ld_ppi2 |$1c-1 facos zero
304 .long t_operr |$1c-2 facos inf
305 .long src_nan |$1c-3 facos nan
306 .long sacosd |$1c-4 facos denorm
307 .long serror |$1c-5 facos ERROR
308 .long serror |$1c-6 facos ERROR
309 .long serror |$1c-7 facos ERROR
310
311 .long scos |$1d-0 fcos norm
312 .long ld_pone |$1d-1 fcos zero
313 .long t_operr |$1d-2 fcos inf
314 .long src_nan |$1d-3 fcos nan
315 .long scosd |$1d-4 fcos denorm
316 .long serror |$1d-5 fcos ERROR
317 .long serror |$1d-6 fcos ERROR
318 .long serror |$1d-7 fcos ERROR
319
320 .long sgetexp |$1e-0 fgetexp norm
321 .long szero |$1e-1 fgetexp zero
322 .long t_operr |$1e-2 fgetexp inf
323 .long src_nan |$1e-3 fgetexp nan
324 .long sgetexpd |$1e-4 fgetexp denorm
325 .long serror |$1e-5 fgetexp ERROR
326 .long serror |$1e-6 fgetexp ERROR
327 .long serror |$1e-7 fgetexp ERROR
328
329 .long sgetman |$1f-0 fgetman norm
330 .long szero |$1f-1 fgetman zero
331 .long t_operr |$1f-2 fgetman inf
332 .long src_nan |$1f-3 fgetman nan
333 .long sgetmand |$1f-4 fgetman denorm
334 .long serror |$1f-5 fgetman ERROR
335 .long serror |$1f-6 fgetman ERROR
336 .long serror |$1f-7 fgetman ERROR
337
338 .long serror |$20-0 ERROR - illegal extension
339 .long serror |$20-1 ERROR - illegal extension
340 .long serror |$20-2 ERROR - illegal extension
341 .long serror |$20-3 ERROR - illegal extension
342 .long serror |$20-4 ERROR - illegal extension
343 .long serror |$20-5 ERROR - illegal extension
344 .long serror |$20-6 ERROR - illegal extension
345 .long serror |$20-7 ERROR - illegal extension
346
347 .long pmod |$21-0 fmod all
348 .long pmod |$21-1 fmod all
349 .long pmod |$21-2 fmod all
350 .long pmod |$21-3 fmod all
351 .long pmod |$21-4 fmod all
352 .long serror |$21-5 fmod ERROR
353 .long serror |$21-6 fmod ERROR
354 .long serror |$21-7 fmod ERROR
355
356 .long serror |$22-0 ERROR - illegal extension
357 .long serror |$22-1 ERROR - illegal extension
358 .long serror |$22-2 ERROR - illegal extension
359 .long serror |$22-3 ERROR - illegal extension
360 .long serror |$22-4 ERROR - illegal extension
361 .long serror |$22-5 ERROR - illegal extension
362 .long serror |$22-6 ERROR - illegal extension
363 .long serror |$22-7 ERROR - illegal extension
364
365 .long serror |$23-0 ERROR - illegal extension
366 .long serror |$23-1 ERROR - illegal extension
367 .long serror |$23-2 ERROR - illegal extension
368 .long serror |$23-3 ERROR - illegal extension
369 .long serror |$23-4 ERROR - illegal extension
370 .long serror |$23-5 ERROR - illegal extension
371 .long serror |$23-6 ERROR - illegal extension
372 .long serror |$23-7 ERROR - illegal extension
373
374 .long serror |$24-0 ERROR - illegal extension
375 .long serror |$24-1 ERROR - illegal extension
376 .long serror |$24-2 ERROR - illegal extension
377 .long serror |$24-3 ERROR - illegal extension
378 .long serror |$24-4 ERROR - illegal extension
379 .long serror |$24-5 ERROR - illegal extension
380 .long serror |$24-6 ERROR - illegal extension
381 .long serror |$24-7 ERROR - illegal extension
382
383 .long prem |$25-0 frem all
384 .long prem |$25-1 frem all
385 .long prem |$25-2 frem all
386 .long prem |$25-3 frem all
387 .long prem |$25-4 frem all
388 .long serror |$25-5 frem ERROR
389 .long serror |$25-6 frem ERROR
390 .long serror |$25-7 frem ERROR
391
392 .long pscale |$26-0 fscale all
393 .long pscale |$26-1 fscale all
394 .long pscale |$26-2 fscale all
395 .long pscale |$26-3 fscale all
396 .long pscale |$26-4 fscale all
397 .long serror |$26-5 fscale ERROR
398 .long serror |$26-6 fscale ERROR
399 .long serror |$26-7 fscale ERROR
400
401 .long serror |$27-0 ERROR - illegal extension
402 .long serror |$27-1 ERROR - illegal extension
403 .long serror |$27-2 ERROR - illegal extension
404 .long serror |$27-3 ERROR - illegal extension
405 .long serror |$27-4 ERROR - illegal extension
406 .long serror |$27-5 ERROR - illegal extension
407 .long serror |$27-6 ERROR - illegal extension
408 .long serror |$27-7 ERROR - illegal extension
409
410 .long serror |$28-0 ERROR - illegal extension
411 .long serror |$28-1 ERROR - illegal extension
412 .long serror |$28-2 ERROR - illegal extension
413 .long serror |$28-3 ERROR - illegal extension
414 .long serror |$28-4 ERROR - illegal extension
415 .long serror |$28-5 ERROR - illegal extension
416 .long serror |$28-6 ERROR - illegal extension
417 .long serror |$28-7 ERROR - illegal extension
418
419 .long serror |$29-0 ERROR - illegal extension
420 .long serror |$29-1 ERROR - illegal extension
421 .long serror |$29-2 ERROR - illegal extension
422 .long serror |$29-3 ERROR - illegal extension
423 .long serror |$29-4 ERROR - illegal extension
424 .long serror |$29-5 ERROR - illegal extension
425 .long serror |$29-6 ERROR - illegal extension
426 .long serror |$29-7 ERROR - illegal extension
427
428 .long serror |$2a-0 ERROR - illegal extension
429 .long serror |$2a-1 ERROR - illegal extension
430 .long serror |$2a-2 ERROR - illegal extension
431 .long serror |$2a-3 ERROR - illegal extension
432 .long serror |$2a-4 ERROR - illegal extension
433 .long serror |$2a-5 ERROR - illegal extension
434 .long serror |$2a-6 ERROR - illegal extension
435 .long serror |$2a-7 ERROR - illegal extension
436
437 .long serror |$2b-0 ERROR - illegal extension
438 .long serror |$2b-1 ERROR - illegal extension
439 .long serror |$2b-2 ERROR - illegal extension
440 .long serror |$2b-3 ERROR - illegal extension
441 .long serror |$2b-4 ERROR - illegal extension
442 .long serror |$2b-5 ERROR - illegal extension
443 .long serror |$2b-6 ERROR - illegal extension
444 .long serror |$2b-7 ERROR - illegal extension
445
446 .long serror |$2c-0 ERROR - illegal extension
447 .long serror |$2c-1 ERROR - illegal extension
448 .long serror |$2c-2 ERROR - illegal extension
449 .long serror |$2c-3 ERROR - illegal extension
450 .long serror |$2c-4 ERROR - illegal extension
451 .long serror |$2c-5 ERROR - illegal extension
452 .long serror |$2c-6 ERROR - illegal extension
453 .long serror |$2c-7 ERROR - illegal extension
454
455 .long serror |$2d-0 ERROR - illegal extension
456 .long serror |$2d-1 ERROR - illegal extension
457 .long serror |$2d-2 ERROR - illegal extension
458 .long serror |$2d-3 ERROR - illegal extension
459 .long serror |$2d-4 ERROR - illegal extension
460 .long serror |$2d-5 ERROR - illegal extension
461 .long serror |$2d-6 ERROR - illegal extension
462 .long serror |$2d-7 ERROR - illegal extension
463
464 .long serror |$2e-0 ERROR - illegal extension
465 .long serror |$2e-1 ERROR - illegal extension
466 .long serror |$2e-2 ERROR - illegal extension
467 .long serror |$2e-3 ERROR - illegal extension
468 .long serror |$2e-4 ERROR - illegal extension
469 .long serror |$2e-5 ERROR - illegal extension
470 .long serror |$2e-6 ERROR - illegal extension
471 .long serror |$2e-7 ERROR - illegal extension
472
473 .long serror |$2f-0 ERROR - illegal extension
474 .long serror |$2f-1 ERROR - illegal extension
475 .long serror |$2f-2 ERROR - illegal extension
476 .long serror |$2f-3 ERROR - illegal extension
477 .long serror |$2f-4 ERROR - illegal extension
478 .long serror |$2f-5 ERROR - illegal extension
479 .long serror |$2f-6 ERROR - illegal extension
480 .long serror |$2f-7 ERROR - illegal extension
481
482 .long ssincos |$30-0 fsincos norm
483 .long ssincosz |$30-1 fsincos zero
484 .long ssincosi |$30-2 fsincos inf
485 .long ssincosnan |$30-3 fsincos nan
486 .long ssincosd |$30-4 fsincos denorm
487 .long serror |$30-5 fsincos ERROR
488 .long serror |$30-6 fsincos ERROR
489 .long serror |$30-7 fsincos ERROR
490
491 .long ssincos |$31-0 fsincos norm
492 .long ssincosz |$31-1 fsincos zero
493 .long ssincosi |$31-2 fsincos inf
494 .long ssincosnan |$31-3 fsincos nan
495 .long ssincosd |$31-4 fsincos denorm
496 .long serror |$31-5 fsincos ERROR
497 .long serror |$31-6 fsincos ERROR
498 .long serror |$31-7 fsincos ERROR
499
500 .long ssincos |$32-0 fsincos norm
501 .long ssincosz |$32-1 fsincos zero
502 .long ssincosi |$32-2 fsincos inf
503 .long ssincosnan |$32-3 fsincos nan
504 .long ssincosd |$32-4 fsincos denorm
505 .long serror |$32-5 fsincos ERROR
506 .long serror |$32-6 fsincos ERROR
507 .long serror |$32-7 fsincos ERROR
508
509 .long ssincos |$33-0 fsincos norm
510 .long ssincosz |$33-1 fsincos zero
511 .long ssincosi |$33-2 fsincos inf
512 .long ssincosnan |$33-3 fsincos nan
513 .long ssincosd |$33-4 fsincos denorm
514 .long serror |$33-5 fsincos ERROR
515 .long serror |$33-6 fsincos ERROR
516 .long serror |$33-7 fsincos ERROR
517
518 .long ssincos |$34-0 fsincos norm
519 .long ssincosz |$34-1 fsincos zero
520 .long ssincosi |$34-2 fsincos inf
521 .long ssincosnan |$34-3 fsincos nan
522 .long ssincosd |$34-4 fsincos denorm
523 .long serror |$34-5 fsincos ERROR
524 .long serror |$34-6 fsincos ERROR
525 .long serror |$34-7 fsincos ERROR
526
527 .long ssincos |$35-0 fsincos norm
528 .long ssincosz |$35-1 fsincos zero
529 .long ssincosi |$35-2 fsincos inf
530 .long ssincosnan |$35-3 fsincos nan
531 .long ssincosd |$35-4 fsincos denorm
532 .long serror |$35-5 fsincos ERROR
533 .long serror |$35-6 fsincos ERROR
534 .long serror |$35-7 fsincos ERROR
535
536 .long ssincos |$36-0 fsincos norm
537 .long ssincosz |$36-1 fsincos zero
538 .long ssincosi |$36-2 fsincos inf
539 .long ssincosnan |$36-3 fsincos nan
540 .long ssincosd |$36-4 fsincos denorm
541 .long serror |$36-5 fsincos ERROR
542 .long serror |$36-6 fsincos ERROR
543 .long serror |$36-7 fsincos ERROR
544
545 .long ssincos |$37-0 fsincos norm
546 .long ssincosz |$37-1 fsincos zero
547 .long ssincosi |$37-2 fsincos inf
548 .long ssincosnan |$37-3 fsincos nan
549 .long ssincosd |$37-4 fsincos denorm
550 .long serror |$37-5 fsincos ERROR
551 .long serror |$37-6 fsincos ERROR
552 .long serror |$37-7 fsincos ERROR
553
554 |end
diff --git a/arch/m68k/fpsp040/util.S b/arch/m68k/fpsp040/util.S
new file mode 100644
index 000000000000..452f3d65857b
--- /dev/null
+++ b/arch/m68k/fpsp040/util.S
@@ -0,0 +1,748 @@
1|
2| util.sa 3.7 7/29/91
3|
4| This file contains routines used by other programs.
5|
6| ovf_res: used by overflow to force the correct
7| result. ovf_r_k, ovf_r_x2, ovf_r_x3 are
8| derivatives of this routine.
9| get_fline: get user's opcode word
10| g_dfmtou: returns the destination format.
11| g_opcls: returns the opclass of the float instruction.
12| g_rndpr: returns the rounding precision.
13| reg_dest: write byte, word, or long data to Dn
14|
15|
16| Copyright (C) Motorola, Inc. 1990
17| All Rights Reserved
18|
19| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
20| The copyright notice above does not evidence any
21| actual or intended publication of such source code.
22
23|UTIL idnt 2,1 | Motorola 040 Floating Point Software Package
24
25 |section 8
26
27#include "fpsp.h"
28
29 |xref mem_read
30
31 .global g_dfmtou
32 .global g_opcls
33 .global g_rndpr
34 .global get_fline
35 .global reg_dest
36
37|
38| Final result table for ovf_res. Note that the negative counterparts
39| are unnecessary as ovf_res always returns the sign separately from
40| the exponent.
41| ;+inf
42EXT_PINF: .long 0x7fff0000,0x00000000,0x00000000,0x00000000
43| ;largest +ext
44EXT_PLRG: .long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000
45| ;largest magnitude +sgl in ext
46SGL_PLRG: .long 0x407e0000,0xffffff00,0x00000000,0x00000000
47| ;largest magnitude +dbl in ext
48DBL_PLRG: .long 0x43fe0000,0xffffffff,0xfffff800,0x00000000
49| ;largest -ext
50
51tblovfl:
52 .long EXT_RN
53 .long EXT_RZ
54 .long EXT_RM
55 .long EXT_RP
56 .long SGL_RN
57 .long SGL_RZ
58 .long SGL_RM
59 .long SGL_RP
60 .long DBL_RN
61 .long DBL_RZ
62 .long DBL_RM
63 .long DBL_RP
64 .long error
65 .long error
66 .long error
67 .long error
68
69
70|
71| ovf_r_k --- overflow result calculation
72|
73| This entry point is used by kernel_ex.
74|
75| This forces the destination precision to be extended
76|
77| Input: operand in ETEMP
78| Output: a result is in ETEMP (internal extended format)
79|
80 .global ovf_r_k
81ovf_r_k:
82 lea ETEMP(%a6),%a0 |a0 points to source operand
83 bclrb #sign_bit,ETEMP_EX(%a6)
84 sne ETEMP_SGN(%a6) |convert to internal IEEE format
85
86|
87| ovf_r_x2 --- overflow result calculation
88|
89| This entry point used by x_ovfl. (opclass 0 and 2)
90|
91| Input a0 points to an operand in the internal extended format
92| Output a0 points to the result in the internal extended format
93|
94| This sets the round precision according to the user's FPCR unless the
95| instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul,
96| fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg.
97| If the instruction is fsgldiv of fsglmul, the rounding precision must be
98| extended. If the instruction is not fsgldiv or fsglmul but a force-
99| precision instruction, the rounding precision is then set to the force
100| precision.
101
102 .global ovf_r_x2
103ovf_r_x2:
104 btstb #E3,E_BYTE(%a6) |check for nu exception
105 beql ovf_e1_exc |it is cu exception
106ovf_e3_exc:
107 movew CMDREG3B(%a6),%d0 |get the command word
108 andiw #0x00000060,%d0 |clear all bits except 6 and 5
109 cmpil #0x00000040,%d0
110 beql ovff_sgl |force precision is single
111 cmpil #0x00000060,%d0
112 beql ovff_dbl |force precision is double
113 movew CMDREG3B(%a6),%d0 |get the command word again
114 andil #0x7f,%d0 |clear all except operation
115 cmpil #0x33,%d0
116 beql ovf_fsgl |fsglmul or fsgldiv
117 cmpil #0x30,%d0
118 beql ovf_fsgl
119 bra ovf_fpcr |instruction is none of the above
120| ;use FPCR
121ovf_e1_exc:
122 movew CMDREG1B(%a6),%d0 |get command word
123 andil #0x00000044,%d0 |clear all bits except 6 and 2
124 cmpil #0x00000040,%d0
125 beql ovff_sgl |the instruction is force single
126 cmpil #0x00000044,%d0
127 beql ovff_dbl |the instruction is force double
128 movew CMDREG1B(%a6),%d0 |again get the command word
129 andil #0x0000007f,%d0 |clear all except the op code
130 cmpil #0x00000027,%d0
131 beql ovf_fsgl |fsglmul
132 cmpil #0x00000024,%d0
133 beql ovf_fsgl |fsgldiv
134 bra ovf_fpcr |none of the above, use FPCR
135|
136|
137| Inst is either fsgldiv or fsglmul. Force extended precision.
138|
139ovf_fsgl:
140 clrl %d0
141 bra ovf_res
142
143ovff_sgl:
144 movel #0x00000001,%d0 |set single
145 bra ovf_res
146ovff_dbl:
147 movel #0x00000002,%d0 |set double
148 bra ovf_res
149|
150| The precision is in the fpcr.
151|
152ovf_fpcr:
153 bfextu FPCR_MODE(%a6){#0:#2},%d0 |set round precision
154 bra ovf_res
155
156|
157|
158| ovf_r_x3 --- overflow result calculation
159|
160| This entry point used by x_ovfl. (opclass 3 only)
161|
162| Input a0 points to an operand in the internal extended format
163| Output a0 points to the result in the internal extended format
164|
165| This sets the round precision according to the destination size.
166|
167 .global ovf_r_x3
168ovf_r_x3:
169 bsr g_dfmtou |get dest fmt in d0{1:0}
170| ;for fmovout, the destination format
171| ;is the rounding precision
172
173|
174| ovf_res --- overflow result calculation
175|
176| Input:
177| a0 points to operand in internal extended format
178| Output:
179| a0 points to result in internal extended format
180|
181 .global ovf_res
182ovf_res:
183 lsll #2,%d0 |move round precision to d0{3:2}
184 bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode
185 orl %d1,%d0 |index is fmt:mode in d0{3:0}
186 leal tblovfl,%a1 |load a1 with table address
187 movel %a1@(%d0:l:4),%a1 |use d0 as index to the table
188 jmp (%a1) |go to the correct routine
189|
190|case DEST_FMT = EXT
191|
192EXT_RN:
193 leal EXT_PINF,%a1 |answer is +/- infinity
194 bsetb #inf_bit,FPSR_CC(%a6)
195 bra set_sign |now go set the sign
196EXT_RZ:
197 leal EXT_PLRG,%a1 |answer is +/- large number
198 bra set_sign |now go set the sign
199EXT_RM:
200 tstb LOCAL_SGN(%a0) |if negative overflow
201 beqs e_rm_pos
202e_rm_neg:
203 leal EXT_PINF,%a1 |answer is negative infinity
204 orl #neginf_mask,USER_FPSR(%a6)
205 bra end_ovfr
206e_rm_pos:
207 leal EXT_PLRG,%a1 |answer is large positive number
208 bra end_ovfr
209EXT_RP:
210 tstb LOCAL_SGN(%a0) |if negative overflow
211 beqs e_rp_pos
212e_rp_neg:
213 leal EXT_PLRG,%a1 |answer is large negative number
214 bsetb #neg_bit,FPSR_CC(%a6)
215 bra end_ovfr
216e_rp_pos:
217 leal EXT_PINF,%a1 |answer is positive infinity
218 bsetb #inf_bit,FPSR_CC(%a6)
219 bra end_ovfr
220|
221|case DEST_FMT = DBL
222|
223DBL_RN:
224 leal EXT_PINF,%a1 |answer is +/- infinity
225 bsetb #inf_bit,FPSR_CC(%a6)
226 bra set_sign
227DBL_RZ:
228 leal DBL_PLRG,%a1 |answer is +/- large number
229 bra set_sign |now go set the sign
230DBL_RM:
231 tstb LOCAL_SGN(%a0) |if negative overflow
232 beqs d_rm_pos
233d_rm_neg:
234 leal EXT_PINF,%a1 |answer is negative infinity
235 orl #neginf_mask,USER_FPSR(%a6)
236 bra end_ovfr |inf is same for all precisions (ext,dbl,sgl)
237d_rm_pos:
238 leal DBL_PLRG,%a1 |answer is large positive number
239 bra end_ovfr
240DBL_RP:
241 tstb LOCAL_SGN(%a0) |if negative overflow
242 beqs d_rp_pos
243d_rp_neg:
244 leal DBL_PLRG,%a1 |answer is large negative number
245 bsetb #neg_bit,FPSR_CC(%a6)
246 bra end_ovfr
247d_rp_pos:
248 leal EXT_PINF,%a1 |answer is positive infinity
249 bsetb #inf_bit,FPSR_CC(%a6)
250 bra end_ovfr
251|
252|case DEST_FMT = SGL
253|
254SGL_RN:
255 leal EXT_PINF,%a1 |answer is +/- infinity
256 bsetb #inf_bit,FPSR_CC(%a6)
257 bras set_sign
258SGL_RZ:
259 leal SGL_PLRG,%a1 |answer is +/- large number
260 bras set_sign
261SGL_RM:
262 tstb LOCAL_SGN(%a0) |if negative overflow
263 beqs s_rm_pos
264s_rm_neg:
265 leal EXT_PINF,%a1 |answer is negative infinity
266 orl #neginf_mask,USER_FPSR(%a6)
267 bras end_ovfr
268s_rm_pos:
269 leal SGL_PLRG,%a1 |answer is large positive number
270 bras end_ovfr
271SGL_RP:
272 tstb LOCAL_SGN(%a0) |if negative overflow
273 beqs s_rp_pos
274s_rp_neg:
275 leal SGL_PLRG,%a1 |answer is large negative number
276 bsetb #neg_bit,FPSR_CC(%a6)
277 bras end_ovfr
278s_rp_pos:
279 leal EXT_PINF,%a1 |answer is positive infinity
280 bsetb #inf_bit,FPSR_CC(%a6)
281 bras end_ovfr
282
283set_sign:
284 tstb LOCAL_SGN(%a0) |if negative overflow
285 beqs end_ovfr
286neg_sign:
287 bsetb #neg_bit,FPSR_CC(%a6)
288
289end_ovfr:
290 movew LOCAL_EX(%a1),LOCAL_EX(%a0) |do not overwrite sign
291 movel LOCAL_HI(%a1),LOCAL_HI(%a0)
292 movel LOCAL_LO(%a1),LOCAL_LO(%a0)
293 rts
294
295
296|
297| ERROR
298|
299error:
300 rts
301|
302| get_fline --- get f-line opcode of interrupted instruction
303|
304| Returns opcode in the low word of d0.
305|
306get_fline:
307 movel USER_FPIAR(%a6),%a0 |opcode address
308 movel #0,-(%a7) |reserve a word on the stack
309 leal 2(%a7),%a1 |point to low word of temporary
310 movel #2,%d0 |count
311 bsrl mem_read
312 movel (%a7)+,%d0
313 rts
314|
315| g_rndpr --- put rounding precision in d0{1:0}
316|
317| valid return codes are:
318| 00 - extended
319| 01 - single
320| 10 - double
321|
322| begin
323| get rounding precision (cmdreg3b{6:5})
324| begin
325| case opclass = 011 (move out)
326| get destination format - this is the also the rounding precision
327|
328| case opclass = 0x0
329| if E3
330| *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL
331| *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL
332| case RndPr(from cmdreg3b{6:5} = 00 | 01
333| use precision from FPCR{7:6}
334| case 00 then RND_PREC = EXT
335| case 01 then RND_PREC = SGL
336| case 10 then RND_PREC = DBL
337| else E1
338| use precision in FPCR{7:6}
339| case 00 then RND_PREC = EXT
340| case 01 then RND_PREC = SGL
341| case 10 then RND_PREC = DBL
342| end
343|
344g_rndpr:
345 bsr g_opcls |get opclass in d0{2:0}
346 cmpw #0x0003,%d0 |check for opclass 011
347 bnes op_0x0
348
349|
350| For move out instructions (opclass 011) the destination format
351| is the same as the rounding precision. Pass results from g_dfmtou.
352|
353 bsr g_dfmtou
354 rts
355op_0x0:
356 btstb #E3,E_BYTE(%a6)
357 beql unf_e1_exc |branch to e1 underflow
358unf_e3_exc:
359 movel CMDREG3B(%a6),%d0 |rounding precision in d0{10:9}
360 bfextu %d0{#9:#2},%d0 |move the rounding prec bits to d0{1:0}
361 cmpil #0x2,%d0
362 beql unff_sgl |force precision is single
363 cmpil #0x3,%d0 |force precision is double
364 beql unff_dbl
365 movew CMDREG3B(%a6),%d0 |get the command word again
366 andil #0x7f,%d0 |clear all except operation
367 cmpil #0x33,%d0
368 beql unf_fsgl |fsglmul or fsgldiv
369 cmpil #0x30,%d0
370 beql unf_fsgl |fsgldiv or fsglmul
371 bra unf_fpcr
372unf_e1_exc:
373 movel CMDREG1B(%a6),%d0 |get 32 bits off the stack, 1st 16 bits
374| ;are the command word
375 andil #0x00440000,%d0 |clear all bits except bits 6 and 2
376 cmpil #0x00400000,%d0
377 beql unff_sgl |force single
378 cmpil #0x00440000,%d0 |force double
379 beql unff_dbl
380 movel CMDREG1B(%a6),%d0 |get the command word again
381 andil #0x007f0000,%d0 |clear all bits except the operation
382 cmpil #0x00270000,%d0
383 beql unf_fsgl |fsglmul
384 cmpil #0x00240000,%d0
385 beql unf_fsgl |fsgldiv
386 bra unf_fpcr
387
388|
389| Convert to return format. The values from cmdreg3b and the return
390| values are:
391| cmdreg3b return precision
392| -------- ------ ---------
393| 00,01 0 ext
394| 10 1 sgl
395| 11 2 dbl
396| Force single
397|
398unff_sgl:
399 movel #1,%d0 |return 1
400 rts
401|
402| Force double
403|
404unff_dbl:
405 movel #2,%d0 |return 2
406 rts
407|
408| Force extended
409|
410unf_fsgl:
411 movel #0,%d0
412 rts
413|
414| Get rounding precision set in FPCR{7:6}.
415|
416unf_fpcr:
417 movel USER_FPCR(%a6),%d0 |rounding precision bits in d0{7:6}
418 bfextu %d0{#24:#2},%d0 |move the rounding prec bits to d0{1:0}
419 rts
420|
421| g_opcls --- put opclass in d0{2:0}
422|
423g_opcls:
424 btstb #E3,E_BYTE(%a6)
425 beqs opc_1b |if set, go to cmdreg1b
426opc_3b:
427 clrl %d0 |if E3, only opclass 0x0 is possible
428 rts
429opc_1b:
430 movel CMDREG1B(%a6),%d0
431 bfextu %d0{#0:#3},%d0 |shift opclass bits d0{31:29} to d0{2:0}
432 rts
433|
434| g_dfmtou --- put destination format in d0{1:0}
435|
436| If E1, the format is from cmdreg1b{12:10}
437| If E3, the format is extended.
438|
439| Dest. Fmt.
440| extended 010 -> 00
441| single 001 -> 01
442| double 101 -> 10
443|
444g_dfmtou:
445 btstb #E3,E_BYTE(%a6)
446 beqs op011
447 clrl %d0 |if E1, size is always ext
448 rts
449op011:
450 movel CMDREG1B(%a6),%d0
451 bfextu %d0{#3:#3},%d0 |dest fmt from cmdreg1b{12:10}
452 cmpb #1,%d0 |check for single
453 bnes not_sgl
454 movel #1,%d0
455 rts
456not_sgl:
457 cmpb #5,%d0 |check for double
458 bnes not_dbl
459 movel #2,%d0
460 rts
461not_dbl:
462 clrl %d0 |must be extended
463 rts
464
465|
466|
467| Final result table for unf_sub. Note that the negative counterparts
468| are unnecessary as unf_sub always returns the sign separately from
469| the exponent.
470| ;+zero
471EXT_PZRO: .long 0x00000000,0x00000000,0x00000000,0x00000000
472| ;+zero
473SGL_PZRO: .long 0x3f810000,0x00000000,0x00000000,0x00000000
474| ;+zero
475DBL_PZRO: .long 0x3c010000,0x00000000,0x00000000,0x00000000
476| ;smallest +ext denorm
477EXT_PSML: .long 0x00000000,0x00000000,0x00000001,0x00000000
478| ;smallest +sgl denorm
479SGL_PSML: .long 0x3f810000,0x00000100,0x00000000,0x00000000
480| ;smallest +dbl denorm
481DBL_PSML: .long 0x3c010000,0x00000000,0x00000800,0x00000000
482|
483| UNF_SUB --- underflow result calculation
484|
485| Input:
486| d0 contains round precision
487| a0 points to input operand in the internal extended format
488|
489| Output:
490| a0 points to correct internal extended precision result.
491|
492
493tblunf:
494 .long uEXT_RN
495 .long uEXT_RZ
496 .long uEXT_RM
497 .long uEXT_RP
498 .long uSGL_RN
499 .long uSGL_RZ
500 .long uSGL_RM
501 .long uSGL_RP
502 .long uDBL_RN
503 .long uDBL_RZ
504 .long uDBL_RM
505 .long uDBL_RP
506 .long uDBL_RN
507 .long uDBL_RZ
508 .long uDBL_RM
509 .long uDBL_RP
510
511 .global unf_sub
512unf_sub:
513 lsll #2,%d0 |move round precision to d0{3:2}
514 bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode
515 orl %d1,%d0 |index is fmt:mode in d0{3:0}
516 leal tblunf,%a1 |load a1 with table address
517 movel %a1@(%d0:l:4),%a1 |use d0 as index to the table
518 jmp (%a1) |go to the correct routine
519|
520|case DEST_FMT = EXT
521|
522uEXT_RN:
523 leal EXT_PZRO,%a1 |answer is +/- zero
524 bsetb #z_bit,FPSR_CC(%a6)
525 bra uset_sign |now go set the sign
526uEXT_RZ:
527 leal EXT_PZRO,%a1 |answer is +/- zero
528 bsetb #z_bit,FPSR_CC(%a6)
529 bra uset_sign |now go set the sign
530uEXT_RM:
531 tstb LOCAL_SGN(%a0) |if negative underflow
532 beqs ue_rm_pos
533ue_rm_neg:
534 leal EXT_PSML,%a1 |answer is negative smallest denorm
535 bsetb #neg_bit,FPSR_CC(%a6)
536 bra end_unfr
537ue_rm_pos:
538 leal EXT_PZRO,%a1 |answer is positive zero
539 bsetb #z_bit,FPSR_CC(%a6)
540 bra end_unfr
541uEXT_RP:
542 tstb LOCAL_SGN(%a0) |if negative underflow
543 beqs ue_rp_pos
544ue_rp_neg:
545 leal EXT_PZRO,%a1 |answer is negative zero
546 oril #negz_mask,USER_FPSR(%a6)
547 bra end_unfr
548ue_rp_pos:
549 leal EXT_PSML,%a1 |answer is positive smallest denorm
550 bra end_unfr
551|
552|case DEST_FMT = DBL
553|
554uDBL_RN:
555 leal DBL_PZRO,%a1 |answer is +/- zero
556 bsetb #z_bit,FPSR_CC(%a6)
557 bra uset_sign
558uDBL_RZ:
559 leal DBL_PZRO,%a1 |answer is +/- zero
560 bsetb #z_bit,FPSR_CC(%a6)
561 bra uset_sign |now go set the sign
562uDBL_RM:
563 tstb LOCAL_SGN(%a0) |if negative overflow
564 beqs ud_rm_pos
565ud_rm_neg:
566 leal DBL_PSML,%a1 |answer is smallest denormalized negative
567 bsetb #neg_bit,FPSR_CC(%a6)
568 bra end_unfr
569ud_rm_pos:
570 leal DBL_PZRO,%a1 |answer is positive zero
571 bsetb #z_bit,FPSR_CC(%a6)
572 bra end_unfr
573uDBL_RP:
574 tstb LOCAL_SGN(%a0) |if negative overflow
575 beqs ud_rp_pos
576ud_rp_neg:
577 leal DBL_PZRO,%a1 |answer is negative zero
578 oril #negz_mask,USER_FPSR(%a6)
579 bra end_unfr
580ud_rp_pos:
581 leal DBL_PSML,%a1 |answer is smallest denormalized negative
582 bra end_unfr
583|
584|case DEST_FMT = SGL
585|
586uSGL_RN:
587 leal SGL_PZRO,%a1 |answer is +/- zero
588 bsetb #z_bit,FPSR_CC(%a6)
589 bras uset_sign
590uSGL_RZ:
591 leal SGL_PZRO,%a1 |answer is +/- zero
592 bsetb #z_bit,FPSR_CC(%a6)
593 bras uset_sign
594uSGL_RM:
595 tstb LOCAL_SGN(%a0) |if negative overflow
596 beqs us_rm_pos
597us_rm_neg:
598 leal SGL_PSML,%a1 |answer is smallest denormalized negative
599 bsetb #neg_bit,FPSR_CC(%a6)
600 bras end_unfr
601us_rm_pos:
602 leal SGL_PZRO,%a1 |answer is positive zero
603 bsetb #z_bit,FPSR_CC(%a6)
604 bras end_unfr
605uSGL_RP:
606 tstb LOCAL_SGN(%a0) |if negative overflow
607 beqs us_rp_pos
608us_rp_neg:
609 leal SGL_PZRO,%a1 |answer is negative zero
610 oril #negz_mask,USER_FPSR(%a6)
611 bras end_unfr
612us_rp_pos:
613 leal SGL_PSML,%a1 |answer is smallest denormalized positive
614 bras end_unfr
615
616uset_sign:
617 tstb LOCAL_SGN(%a0) |if negative overflow
618 beqs end_unfr
619uneg_sign:
620 bsetb #neg_bit,FPSR_CC(%a6)
621
622end_unfr:
623 movew LOCAL_EX(%a1),LOCAL_EX(%a0) |be careful not to overwrite sign
624 movel LOCAL_HI(%a1),LOCAL_HI(%a0)
625 movel LOCAL_LO(%a1),LOCAL_LO(%a0)
626 rts
627|
628| reg_dest --- write byte, word, or long data to Dn
629|
630|
631| Input:
632| L_SCR1: Data
633| d1: data size and dest register number formatted as:
634|
635| 32 5 4 3 2 1 0
636| -----------------------------------------------
637| | 0 | Size | Dest Reg # |
638| -----------------------------------------------
639|
640| Size is:
641| 0 - Byte
642| 1 - Word
643| 2 - Long/Single
644|
645pregdst:
646 .long byte_d0
647 .long byte_d1
648 .long byte_d2
649 .long byte_d3
650 .long byte_d4
651 .long byte_d5
652 .long byte_d6
653 .long byte_d7
654 .long word_d0
655 .long word_d1
656 .long word_d2
657 .long word_d3
658 .long word_d4
659 .long word_d5
660 .long word_d6
661 .long word_d7
662 .long long_d0
663 .long long_d1
664 .long long_d2
665 .long long_d3
666 .long long_d4
667 .long long_d5
668 .long long_d6
669 .long long_d7
670
671reg_dest:
672 leal pregdst,%a0
673 movel %a0@(%d1:l:4),%a0
674 jmp (%a0)
675
676byte_d0:
677 moveb L_SCR1(%a6),USER_D0+3(%a6)
678 rts
679byte_d1:
680 moveb L_SCR1(%a6),USER_D1+3(%a6)
681 rts
682byte_d2:
683 moveb L_SCR1(%a6),%d2
684 rts
685byte_d3:
686 moveb L_SCR1(%a6),%d3
687 rts
688byte_d4:
689 moveb L_SCR1(%a6),%d4
690 rts
691byte_d5:
692 moveb L_SCR1(%a6),%d5
693 rts
694byte_d6:
695 moveb L_SCR1(%a6),%d6
696 rts
697byte_d7:
698 moveb L_SCR1(%a6),%d7
699 rts
700word_d0:
701 movew L_SCR1(%a6),USER_D0+2(%a6)
702 rts
703word_d1:
704 movew L_SCR1(%a6),USER_D1+2(%a6)
705 rts
706word_d2:
707 movew L_SCR1(%a6),%d2
708 rts
709word_d3:
710 movew L_SCR1(%a6),%d3
711 rts
712word_d4:
713 movew L_SCR1(%a6),%d4
714 rts
715word_d5:
716 movew L_SCR1(%a6),%d5
717 rts
718word_d6:
719 movew L_SCR1(%a6),%d6
720 rts
721word_d7:
722 movew L_SCR1(%a6),%d7
723 rts
724long_d0:
725 movel L_SCR1(%a6),USER_D0(%a6)
726 rts
727long_d1:
728 movel L_SCR1(%a6),USER_D1(%a6)
729 rts
730long_d2:
731 movel L_SCR1(%a6),%d2
732 rts
733long_d3:
734 movel L_SCR1(%a6),%d3
735 rts
736long_d4:
737 movel L_SCR1(%a6),%d4
738 rts
739long_d5:
740 movel L_SCR1(%a6),%d5
741 rts
742long_d6:
743 movel L_SCR1(%a6),%d6
744 rts
745long_d7:
746 movel L_SCR1(%a6),%d7
747 rts
748 |end
diff --git a/arch/m68k/fpsp040/x_bsun.S b/arch/m68k/fpsp040/x_bsun.S
new file mode 100644
index 000000000000..039247b09c8b
--- /dev/null
+++ b/arch/m68k/fpsp040/x_bsun.S
@@ -0,0 +1,47 @@
1|
2| x_bsun.sa 3.3 7/1/91
3|
4| fpsp_bsun --- FPSP handler for branch/set on unordered exception
5|
6| Copy the PC to FPIAR to maintain 881/882 compatibility
7|
8| The real_bsun handler will need to perform further corrective
9| measures as outlined in the 040 User's Manual on pages
10| 9-41f, section 9.8.3.
11|
12
13| Copyright (C) Motorola, Inc. 1990
14| All Rights Reserved
15|
16| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
17| The copyright notice above does not evidence any
18| actual or intended publication of such source code.
19
20X_BSUN: |idnt 2,1 | Motorola 040 Floating Point Software Package
21
22 |section 8
23
24#include "fpsp.h"
25
26 |xref real_bsun
27
28 .global fpsp_bsun
29fpsp_bsun:
30|
31 link %a6,#-LOCAL_SIZE
32 fsave -(%a7)
33 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
34 fmovemx %fp0-%fp3,USER_FP0(%a6)
35 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
36
37|
38 movel EXC_PC(%a6),USER_FPIAR(%a6)
39|
40 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
41 fmovemx USER_FP0(%a6),%fp0-%fp3
42 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
43 frestore (%a7)+
44 unlk %a6
45 bral real_bsun
46|
47 |end
diff --git a/arch/m68k/fpsp040/x_fline.S b/arch/m68k/fpsp040/x_fline.S
new file mode 100644
index 000000000000..3917710b0fde
--- /dev/null
+++ b/arch/m68k/fpsp040/x_fline.S
@@ -0,0 +1,104 @@
1|
2| x_fline.sa 3.3 1/10/91
3|
4| fpsp_fline --- FPSP handler for fline exception
5|
6| First determine if the exception is one of the unimplemented
7| floating point instructions. If so, let fpsp_unimp handle it.
8| Next, determine if the instruction is an fmovecr with a non-zero
9| <ea> field. If so, handle here and return. Otherwise, it
10| must be a real F-line exception.
11|
12
13| Copyright (C) Motorola, Inc. 1990
14| All Rights Reserved
15|
16| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
17| The copyright notice above does not evidence any
18| actual or intended publication of such source code.
19
20X_FLINE: |idnt 2,1 | Motorola 040 Floating Point Software Package
21
22 |section 8
23
24#include "fpsp.h"
25
26 |xref real_fline
27 |xref fpsp_unimp
28 |xref uni_2
29 |xref mem_read
30 |xref fpsp_fmt_error
31
32 .global fpsp_fline
33fpsp_fline:
34|
35| check for unimplemented vector first. Use EXC_VEC-4 because
36| the equate is valid only after a 'link a6' has pushed one more
37| long onto the stack.
38|
39 cmpw #UNIMP_VEC,EXC_VEC-4(%a7)
40 beql fpsp_unimp
41
42|
43| fmovecr with non-zero <ea> handling here
44|
45 subl #4,%a7 |4 accounts for 2-word difference
46| ;between six word frame (unimp) and
47| ;four word frame
48 link %a6,#-LOCAL_SIZE
49 fsave -(%a7)
50 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
51 moveal EXC_PC+4(%a6),%a0 |get address of fline instruction
52 leal L_SCR1(%a6),%a1 |use L_SCR1 as scratch
53 movel #4,%d0
54 addl #4,%a6 |to offset the sub.l #4,a7 above so that
55| ;a6 can point correctly to the stack frame
56| ;before branching to mem_read
57 bsrl mem_read
58 subl #4,%a6
59 movel L_SCR1(%a6),%d0 |d0 contains the fline and command word
60 bfextu %d0{#4:#3},%d1 |extract coprocessor id
61 cmpib #1,%d1 |check if cpid=1
62 bne not_mvcr |exit if not
63 bfextu %d0{#16:#6},%d1
64 cmpib #0x17,%d1 |check if it is an FMOVECR encoding
65 bne not_mvcr
66| ;if an FMOVECR instruction, fix stack
67| ;and go to FPSP_UNIMP
68fix_stack:
69 cmpib #VER_40,(%a7) |test for orig unimp frame
70 bnes ck_rev
71 subl #UNIMP_40_SIZE-4,%a7 |emulate an orig fsave
72 moveb #VER_40,(%a7)
73 moveb #UNIMP_40_SIZE-4,1(%a7)
74 clrw 2(%a7)
75 bras fix_con
76ck_rev:
77 cmpib #VER_41,(%a7) |test for rev unimp frame
78 bnel fpsp_fmt_error |if not $40 or $41, exit with error
79 subl #UNIMP_41_SIZE-4,%a7 |emulate a rev fsave
80 moveb #VER_41,(%a7)
81 moveb #UNIMP_41_SIZE-4,1(%a7)
82 clrw 2(%a7)
83fix_con:
84 movew EXC_SR+4(%a6),EXC_SR(%a6) |move stacked sr to new position
85 movel EXC_PC+4(%a6),EXC_PC(%a6) |move stacked pc to new position
86 fmovel EXC_PC(%a6),%FPIAR |point FPIAR to fline inst
87 movel #4,%d1
88 addl %d1,EXC_PC(%a6) |increment stacked pc value to next inst
89 movew #0x202c,EXC_VEC(%a6) |reformat vector to unimp
90 clrl EXC_EA(%a6) |clear the EXC_EA field
91 movew %d0,CMDREG1B(%a6) |move the lower word into CMDREG1B
92 clrl E_BYTE(%a6)
93 bsetb #UFLAG,T_BYTE(%a6)
94 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 |restore data registers
95 bral uni_2
96
97not_mvcr:
98 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 |restore data registers
99 frestore (%a7)+
100 unlk %a6
101 addl #4,%a7
102 bral real_fline
103
104 |end
diff --git a/arch/m68k/fpsp040/x_operr.S b/arch/m68k/fpsp040/x_operr.S
new file mode 100644
index 000000000000..b0f54bcb49a7
--- /dev/null
+++ b/arch/m68k/fpsp040/x_operr.S
@@ -0,0 +1,356 @@
1|
2| x_operr.sa 3.5 7/1/91
3|
4| fpsp_operr --- FPSP handler for operand error exception
5|
6| See 68040 User's Manual pp. 9-44f
7|
8| Note 1: For trap disabled 040 does the following:
9| If the dest is a fp reg, then an extended precision non_signaling
10| NAN is stored in the dest reg. If the dest format is b, w, or l and
11| the source op is a NAN, then garbage is stored as the result (actually
12| the upper 32 bits of the mantissa are sent to the integer unit). If
13| the dest format is integer (b, w, l) and the operr is caused by
14| integer overflow, or the source op is inf, then the result stored is
15| garbage.
16| There are three cases in which operr is incorrectly signaled on the
17| 040. This occurs for move_out of format b, w, or l for the largest
18| negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
19|
20| On opclass = 011 fmove.(b,w,l) that causes a conversion
21| overflow -> OPERR, the exponent in wbte (and fpte) is:
22| byte 56 - (62 - exp)
23| word 48 - (62 - exp)
24| long 32 - (62 - exp)
25|
26| where exp = (true exp) - 1
27|
28| So, wbtemp and fptemp will contain the following on erroneously
29| signalled operr:
30| fpts = 1
31| fpte = $4000 (15 bit externally)
32| byte fptm = $ffffffff ffffff80
33| word fptm = $ffffffff ffff8000
34| long fptm = $ffffffff 80000000
35|
36| Note 2: For trap enabled 040 does the following:
37| If the inst is move_out, then same as Note 1.
38| If the inst is not move_out, the dest is not modified.
39| The exceptional operand is not defined for integer overflow
40| during a move_out.
41|
42
43| Copyright (C) Motorola, Inc. 1990
44| All Rights Reserved
45|
46| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
47| The copyright notice above does not evidence any
48| actual or intended publication of such source code.
49
50X_OPERR: |idnt 2,1 | Motorola 040 Floating Point Software Package
51
52 |section 8
53
54#include "fpsp.h"
55
56 |xref mem_write
57 |xref real_operr
58 |xref real_inex
59 |xref get_fline
60 |xref fpsp_done
61 |xref reg_dest
62
63 .global fpsp_operr
64fpsp_operr:
65|
66 link %a6,#-LOCAL_SIZE
67 fsave -(%a7)
68 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
69 fmovemx %fp0-%fp3,USER_FP0(%a6)
70 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
71
72|
73| Check if this is an opclass 3 instruction.
74| If so, fall through, else branch to operr_end
75|
76 btstb #TFLAG,T_BYTE(%a6)
77 beqs operr_end
78
79|
80| If the destination size is B,W,or L, the operr must be
81| handled here.
82|
83 movel CMDREG1B(%a6),%d0
84 bfextu %d0{#3:#3},%d0 |0=long, 4=word, 6=byte
85 cmpib #0,%d0 |determine size; check long
86 beq operr_long
87 cmpib #4,%d0 |check word
88 beq operr_word
89 cmpib #6,%d0 |check byte
90 beq operr_byte
91
92|
93| The size is not B,W,or L, so the operr is handled by the
94| kernel handler. Set the operr bits and clean up, leaving
95| only the integer exception frame on the stack, and the
96| fpu in the original exceptional state.
97|
98operr_end:
99 bsetb #operr_bit,FPSR_EXCEPT(%a6)
100 bsetb #aiop_bit,FPSR_AEXCEPT(%a6)
101
102 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
103 fmovemx USER_FP0(%a6),%fp0-%fp3
104 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
105 frestore (%a7)+
106 unlk %a6
107 bral real_operr
108
109operr_long:
110 moveql #4,%d1 |write size to d1
111 moveb STAG(%a6),%d0 |test stag for nan
112 andib #0xe0,%d0 |clr all but tag
113 cmpib #0x60,%d0 |check for nan
114 beq operr_nan
115 cmpil #0x80000000,FPTEMP_LO(%a6) |test if ls lword is special
116 bnes chklerr |if not equal, check for incorrect operr
117 bsr check_upper |check if exp and ms mant are special
118 tstl %d0
119 bnes chklerr |if d0 is true, check for incorrect operr
120 movel #0x80000000,%d0 |store special case result
121 bsr operr_store
122 bra not_enabled |clean and exit
123|
124| CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
125|
126chklerr:
127 movew FPTEMP_EX(%a6),%d0
128 andw #0x7FFF,%d0 |ignore sign bit
129 cmpw #0x3FFE,%d0 |this is the only possible exponent value
130 bnes chklerr2
131fixlong:
132 movel FPTEMP_LO(%a6),%d0
133 bsr operr_store
134 bra not_enabled
135chklerr2:
136 movew FPTEMP_EX(%a6),%d0
137 andw #0x7FFF,%d0 |ignore sign bit
138 cmpw #0x4000,%d0
139 bcc store_max |exponent out of range
140
141 movel FPTEMP_LO(%a6),%d0
142 andl #0x7FFF0000,%d0 |look for all 1's on bits 30-16
143 cmpl #0x7FFF0000,%d0
144 beqs fixlong
145
146 tstl FPTEMP_LO(%a6)
147 bpls chklepos
148 cmpl #0xFFFFFFFF,FPTEMP_HI(%a6)
149 beqs fixlong
150 bra store_max
151chklepos:
152 tstl FPTEMP_HI(%a6)
153 beqs fixlong
154 bra store_max
155
156operr_word:
157 moveql #2,%d1 |write size to d1
158 moveb STAG(%a6),%d0 |test stag for nan
159 andib #0xe0,%d0 |clr all but tag
160 cmpib #0x60,%d0 |check for nan
161 beq operr_nan
162 cmpil #0xffff8000,FPTEMP_LO(%a6) |test if ls lword is special
163 bnes chkwerr |if not equal, check for incorrect operr
164 bsr check_upper |check if exp and ms mant are special
165 tstl %d0
166 bnes chkwerr |if d0 is true, check for incorrect operr
167 movel #0x80000000,%d0 |store special case result
168 bsr operr_store
169 bra not_enabled |clean and exit
170|
171| CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
172|
173chkwerr:
174 movew FPTEMP_EX(%a6),%d0
175 andw #0x7FFF,%d0 |ignore sign bit
176 cmpw #0x3FFE,%d0 |this is the only possible exponent value
177 bnes store_max
178 movel FPTEMP_LO(%a6),%d0
179 swap %d0
180 bsr operr_store
181 bra not_enabled
182
183operr_byte:
184 moveql #1,%d1 |write size to d1
185 moveb STAG(%a6),%d0 |test stag for nan
186 andib #0xe0,%d0 |clr all but tag
187 cmpib #0x60,%d0 |check for nan
188 beqs operr_nan
189 cmpil #0xffffff80,FPTEMP_LO(%a6) |test if ls lword is special
190 bnes chkberr |if not equal, check for incorrect operr
191 bsr check_upper |check if exp and ms mant are special
192 tstl %d0
193 bnes chkberr |if d0 is true, check for incorrect operr
194 movel #0x80000000,%d0 |store special case result
195 bsr operr_store
196 bra not_enabled |clean and exit
197|
198| CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
199|
200chkberr:
201 movew FPTEMP_EX(%a6),%d0
202 andw #0x7FFF,%d0 |ignore sign bit
203 cmpw #0x3FFE,%d0 |this is the only possible exponent value
204 bnes store_max
205 movel FPTEMP_LO(%a6),%d0
206 asll #8,%d0
207 swap %d0
208 bsr operr_store
209 bra not_enabled
210
211|
212| This operr condition is not of the special case. Set operr
213| and aiop and write the portion of the nan to memory for the
214| given size.
215|
216operr_nan:
217 orl #opaop_mask,USER_FPSR(%a6) |set operr & aiop
218
219 movel ETEMP_HI(%a6),%d0 |output will be from upper 32 bits
220 bsr operr_store
221 bra end_operr
222|
223| Store_max loads the max pos or negative for the size, sets
224| the operr and aiop bits, and clears inex and ainex, incorrectly
225| set by the 040.
226|
227store_max:
228 orl #opaop_mask,USER_FPSR(%a6) |set operr & aiop
229 bclrb #inex2_bit,FPSR_EXCEPT(%a6)
230 bclrb #ainex_bit,FPSR_AEXCEPT(%a6)
231 fmovel #0,%FPSR
232
233 tstw FPTEMP_EX(%a6) |check sign
234 blts load_neg
235 movel #0x7fffffff,%d0
236 bsr operr_store
237 bra end_operr
238load_neg:
239 movel #0x80000000,%d0
240 bsr operr_store
241 bra end_operr
242
243|
244| This routine stores the data in d0, for the given size in d1,
245| to memory or data register as required. A read of the fline
246| is required to determine the destination.
247|
248operr_store:
249 movel %d0,L_SCR1(%a6) |move write data to L_SCR1
250 movel %d1,-(%a7) |save register size
251 bsrl get_fline |fline returned in d0
252 movel (%a7)+,%d1
253 bftst %d0{#26:#3} |if mode is zero, dest is Dn
254 bnes dest_mem
255|
256| Destination is Dn. Get register number from d0. Data is on
257| the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
258|
259 andil #7,%d0 |isolate register number
260 cmpil #4,%d1
261 beqs op_long |the most frequent case
262 cmpil #2,%d1
263 bnes op_con
264 orl #8,%d0
265 bras op_con
266op_long:
267 orl #0x10,%d0
268op_con:
269 movel %d0,%d1 |format size:reg for reg_dest
270 bral reg_dest |call to reg_dest returns to caller
271| ;of operr_store
272|
273| Destination is memory. Get <ea> from integer exception frame
274| and call mem_write.
275|
276dest_mem:
277 leal L_SCR1(%a6),%a0 |put ptr to write data in a0
278 movel EXC_EA(%a6),%a1 |put user destination address in a1
279 movel %d1,%d0 |put size in d0
280 bsrl mem_write
281 rts
282|
283| Check the exponent for $c000 and the upper 32 bits of the
284| mantissa for $ffffffff. If both are true, return d0 clr
285| and store the lower n bits of the least lword of FPTEMP
286| to d0 for write out. If not, it is a real operr, and set d0.
287|
288check_upper:
289 cmpil #0xffffffff,FPTEMP_HI(%a6) |check if first byte is all 1's
290 bnes true_operr |if not all 1's then was true operr
291 cmpiw #0xc000,FPTEMP_EX(%a6) |check if incorrectly signalled
292 beqs not_true_operr |branch if not true operr
293 cmpiw #0xbfff,FPTEMP_EX(%a6) |check if incorrectly signalled
294 beqs not_true_operr |branch if not true operr
295true_operr:
296 movel #1,%d0 |signal real operr
297 rts
298not_true_operr:
299 clrl %d0 |signal no real operr
300 rts
301
302|
303| End_operr tests for operr enabled. If not, it cleans up the stack
304| and does an rte. If enabled, it cleans up the stack and branches
305| to the kernel operr handler with only the integer exception
306| frame on the stack and the fpu in the original exceptional state
307| with correct data written to the destination.
308|
309end_operr:
310 btstb #operr_bit,FPCR_ENABLE(%a6)
311 beqs not_enabled
312enabled:
313 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
314 fmovemx USER_FP0(%a6),%fp0-%fp3
315 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
316 frestore (%a7)+
317 unlk %a6
318 bral real_operr
319
320not_enabled:
321|
322| It is possible to have either inex2 or inex1 exceptions with the
323| operr. If the inex enable bit is set in the FPCR, and either
324| inex2 or inex1 occurred, we must clean up and branch to the
325| real inex handler.
326|
327ck_inex:
328 moveb FPCR_ENABLE(%a6),%d0
329 andb FPSR_EXCEPT(%a6),%d0
330 andib #0x3,%d0
331 beq operr_exit
332|
333| Inexact enabled and reported, and we must take an inexact exception.
334|
335take_inex:
336 moveb #INEX_VEC,EXC_VEC+1(%a6)
337 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
338 orl #sx_mask,E_BYTE(%a6)
339 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
340 fmovemx USER_FP0(%a6),%fp0-%fp3
341 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
342 frestore (%a7)+
343 unlk %a6
344 bral real_inex
345|
346| Since operr is only an E1 exception, there is no need to frestore
347| any state back to the fpu.
348|
349operr_exit:
350 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
351 fmovemx USER_FP0(%a6),%fp0-%fp3
352 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
353 unlk %a6
354 bral fpsp_done
355
356 |end
diff --git a/arch/m68k/fpsp040/x_ovfl.S b/arch/m68k/fpsp040/x_ovfl.S
new file mode 100644
index 000000000000..22cb8b42c7b6
--- /dev/null
+++ b/arch/m68k/fpsp040/x_ovfl.S
@@ -0,0 +1,186 @@
1|
2| x_ovfl.sa 3.5 7/1/91
3|
4| fpsp_ovfl --- FPSP handler for overflow exception
5|
6| Overflow occurs when a floating-point intermediate result is
7| too large to be represented in a floating-point data register,
8| or when storing to memory, the contents of a floating-point
9| data register are too large to be represented in the
10| destination format.
11|
12| Trap disabled results
13|
14| If the instruction is move_out, then garbage is stored in the
15| destination. If the instruction is not move_out, then the
16| destination is not affected. For 68881 compatibility, the
17| following values should be stored at the destination, based
18| on the current rounding mode:
19|
20| RN Infinity with the sign of the intermediate result.
21| RZ Largest magnitude number, with the sign of the
22| intermediate result.
23| RM For pos overflow, the largest pos number. For neg overflow,
24| -infinity
25| RP For pos overflow, +infinity. For neg overflow, the largest
26| neg number
27|
28| Trap enabled results
29| All trap disabled code applies. In addition the exceptional
30| operand needs to be made available to the users exception handler
31| with a bias of $6000 subtracted from the exponent.
32|
33|
34
35| Copyright (C) Motorola, Inc. 1990
36| All Rights Reserved
37|
38| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
39| The copyright notice above does not evidence any
40| actual or intended publication of such source code.
41
42X_OVFL: |idnt 2,1 | Motorola 040 Floating Point Software Package
43
44 |section 8
45
46#include "fpsp.h"
47
48 |xref ovf_r_x2
49 |xref ovf_r_x3
50 |xref store
51 |xref real_ovfl
52 |xref real_inex
53 |xref fpsp_done
54 |xref g_opcls
55 |xref b1238_fix
56
57 .global fpsp_ovfl
58fpsp_ovfl:
59 link %a6,#-LOCAL_SIZE
60 fsave -(%a7)
61 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
62 fmovemx %fp0-%fp3,USER_FP0(%a6)
63 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
64
65|
66| The 040 doesn't set the AINEX bit in the FPSR, the following
67| line temporarily rectifies this error.
68|
69 bsetb #ainex_bit,FPSR_AEXCEPT(%a6)
70|
71 bsrl ovf_adj |denormalize, round & store interm op
72|
73| if overflow traps not enabled check for inexact exception
74|
75 btstb #ovfl_bit,FPCR_ENABLE(%a6)
76 beqs ck_inex
77|
78 btstb #E3,E_BYTE(%a6)
79 beqs no_e3_1
80 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
81 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
82 bsrl b1238_fix
83 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
84 orl #sx_mask,E_BYTE(%a6)
85no_e3_1:
86 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
87 fmovemx USER_FP0(%a6),%fp0-%fp3
88 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
89 frestore (%a7)+
90 unlk %a6
91 bral real_ovfl
92|
93| It is possible to have either inex2 or inex1 exceptions with the
94| ovfl. If the inex enable bit is set in the FPCR, and either
95| inex2 or inex1 occurred, we must clean up and branch to the
96| real inex handler.
97|
98ck_inex:
99| move.b FPCR_ENABLE(%a6),%d0
100| and.b FPSR_EXCEPT(%a6),%d0
101| andi.b #$3,%d0
102 btstb #inex2_bit,FPCR_ENABLE(%a6)
103 beqs ovfl_exit
104|
105| Inexact enabled and reported, and we must take an inexact exception.
106|
107take_inex:
108 btstb #E3,E_BYTE(%a6)
109 beqs no_e3_2
110 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
111 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
112 bsrl b1238_fix
113 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
114 orl #sx_mask,E_BYTE(%a6)
115no_e3_2:
116 moveb #INEX_VEC,EXC_VEC+1(%a6)
117 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
118 fmovemx USER_FP0(%a6),%fp0-%fp3
119 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
120 frestore (%a7)+
121 unlk %a6
122 bral real_inex
123
124ovfl_exit:
125 bclrb #E3,E_BYTE(%a6) |test and clear E3 bit
126 beqs e1_set
127|
128| Clear dirty bit on dest resister in the frame before branching
129| to b1238_fix.
130|
131 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
132 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
133 bsrl b1238_fix |test for bug1238 case
134
135 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
136 orl #sx_mask,E_BYTE(%a6)
137 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
138 fmovemx USER_FP0(%a6),%fp0-%fp3
139 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
140 frestore (%a7)+
141 unlk %a6
142 bral fpsp_done
143e1_set:
144 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
145 fmovemx USER_FP0(%a6),%fp0-%fp3
146 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
147 unlk %a6
148 bral fpsp_done
149
150|
151| ovf_adj
152|
153ovf_adj:
154|
155| Have a0 point to the correct operand.
156|
157 btstb #E3,E_BYTE(%a6) |test E3 bit
158 beqs ovf_e1
159
160 lea WBTEMP(%a6),%a0
161 bras ovf_com
162ovf_e1:
163 lea ETEMP(%a6),%a0
164
165ovf_com:
166 bclrb #sign_bit,LOCAL_EX(%a0)
167 sne LOCAL_SGN(%a0)
168
169 bsrl g_opcls |returns opclass in d0
170 cmpiw #3,%d0 |check for opclass3
171 bnes not_opc011
172
173|
174| FPSR_CC is saved and restored because ovf_r_x3 affects it. The
175| CCs are defined to be 'not affected' for the opclass3 instruction.
176|
177 moveb FPSR_CC(%a6),L_SCR1(%a6)
178 bsrl ovf_r_x3 |returns a0 pointing to result
179 moveb L_SCR1(%a6),FPSR_CC(%a6)
180 bral store |stores to memory or register
181
182not_opc011:
183 bsrl ovf_r_x2 |returns a0 pointing to result
184 bral store |stores to memory or register
185
186 |end
diff --git a/arch/m68k/fpsp040/x_snan.S b/arch/m68k/fpsp040/x_snan.S
new file mode 100644
index 000000000000..039af573312e
--- /dev/null
+++ b/arch/m68k/fpsp040/x_snan.S
@@ -0,0 +1,277 @@
1|
2| x_snan.sa 3.3 7/1/91
3|
4| fpsp_snan --- FPSP handler for signalling NAN exception
5|
6| SNAN for float -> integer conversions (integer conversion of
7| an SNAN) is a non-maskable run-time exception.
8|
9| For trap disabled the 040 does the following:
10| If the dest data format is s, d, or x, then the SNAN bit in the NAN
11| is set to one and the resulting non-signaling NAN (truncated if
12| necessary) is transferred to the dest. If the dest format is b, w,
13| or l, then garbage is written to the dest (actually the upper 32 bits
14| of the mantissa are sent to the integer unit).
15|
16| For trap enabled the 040 does the following:
17| If the inst is move_out, then the results are the same as for trap
18| disabled with the exception posted. If the instruction is not move_
19| out, the dest. is not modified, and the exception is posted.
20|
21
22| Copyright (C) Motorola, Inc. 1990
23| All Rights Reserved
24|
25| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
26| The copyright notice above does not evidence any
27| actual or intended publication of such source code.
28
29X_SNAN: |idnt 2,1 | Motorola 040 Floating Point Software Package
30
31 |section 8
32
33#include "fpsp.h"
34
35 |xref get_fline
36 |xref mem_write
37 |xref real_snan
38 |xref real_inex
39 |xref fpsp_done
40 |xref reg_dest
41
42 .global fpsp_snan
43fpsp_snan:
44 link %a6,#-LOCAL_SIZE
45 fsave -(%a7)
46 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
47 fmovemx %fp0-%fp3,USER_FP0(%a6)
48 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
49
50|
51| Check if trap enabled
52|
53 btstb #snan_bit,FPCR_ENABLE(%a6)
54 bnes ena |If enabled, then branch
55
56 bsrl move_out |else SNAN disabled
57|
58| It is possible to have an inex1 exception with the
59| snan. If the inex enable bit is set in the FPCR, and either
60| inex2 or inex1 occurred, we must clean up and branch to the
61| real inex handler.
62|
63ck_inex:
64 moveb FPCR_ENABLE(%a6),%d0
65 andb FPSR_EXCEPT(%a6),%d0
66 andib #0x3,%d0
67 beq end_snan
68|
69| Inexact enabled and reported, and we must take an inexact exception.
70|
71take_inex:
72 moveb #INEX_VEC,EXC_VEC+1(%a6)
73 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
74 fmovemx USER_FP0(%a6),%fp0-%fp3
75 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
76 frestore (%a7)+
77 unlk %a6
78 bral real_inex
79|
80| SNAN is enabled. Check if inst is move_out.
81| Make any corrections to the 040 output as necessary.
82|
83ena:
84 btstb #5,CMDREG1B(%a6) |if set, inst is move out
85 beq not_out
86
87 bsrl move_out
88
89report_snan:
90 moveb (%a7),VER_TMP(%a6)
91 cmpib #VER_40,(%a7) |test for orig unimp frame
92 bnes ck_rev
93 moveql #13,%d0 |need to zero 14 lwords
94 bras rep_con
95ck_rev:
96 moveql #11,%d0 |need to zero 12 lwords
97rep_con:
98 clrl (%a7)
99loop1:
100 clrl -(%a7) |clear and dec a7
101 dbra %d0,loop1
102 moveb VER_TMP(%a6),(%a7) |format a busy frame
103 moveb #BUSY_SIZE-4,1(%a7)
104 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
105 orl #sx_mask,E_BYTE(%a6)
106 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
107 fmovemx USER_FP0(%a6),%fp0-%fp3
108 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
109 frestore (%a7)+
110 unlk %a6
111 bral real_snan
112|
113| Exit snan handler by expanding the unimp frame into a busy frame
114|
115end_snan:
116 bclrb #E1,E_BYTE(%a6)
117
118 moveb (%a7),VER_TMP(%a6)
119 cmpib #VER_40,(%a7) |test for orig unimp frame
120 bnes ck_rev2
121 moveql #13,%d0 |need to zero 14 lwords
122 bras rep_con2
123ck_rev2:
124 moveql #11,%d0 |need to zero 12 lwords
125rep_con2:
126 clrl (%a7)
127loop2:
128 clrl -(%a7) |clear and dec a7
129 dbra %d0,loop2
130 moveb VER_TMP(%a6),(%a7) |format a busy frame
131 moveb #BUSY_SIZE-4,1(%a7) |write busy size
132 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
133 orl #sx_mask,E_BYTE(%a6)
134 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
135 fmovemx USER_FP0(%a6),%fp0-%fp3
136 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
137 frestore (%a7)+
138 unlk %a6
139 bral fpsp_done
140
141|
142| Move_out
143|
144move_out:
145 movel EXC_EA(%a6),%a0 |get <ea> from exc frame
146
147 bfextu CMDREG1B(%a6){#3:#3},%d0 |move rx field to d0{2:0}
148 cmpil #0,%d0 |check for long
149 beqs sto_long |branch if move_out long
150
151 cmpil #4,%d0 |check for word
152 beqs sto_word |branch if move_out word
153
154 cmpil #6,%d0 |check for byte
155 beqs sto_byte |branch if move_out byte
156
157|
158| Not byte, word or long
159|
160 rts
161|
162| Get the 32 most significant bits of etemp mantissa
163|
164sto_long:
165 movel ETEMP_HI(%a6),%d1
166 movel #4,%d0 |load byte count
167|
168| Set signalling nan bit
169|
170 bsetl #30,%d1
171|
172| Store to the users destination address
173|
174 tstl %a0 |check if <ea> is 0
175 beqs wrt_dn |destination is a data register
176
177 movel %d1,-(%a7) |move the snan onto the stack
178 movel %a0,%a1 |load dest addr into a1
179 movel %a7,%a0 |load src addr of snan into a0
180 bsrl mem_write |write snan to user memory
181 movel (%a7)+,%d1 |clear off stack
182 rts
183|
184| Get the 16 most significant bits of etemp mantissa
185|
186sto_word:
187 movel ETEMP_HI(%a6),%d1
188 movel #2,%d0 |load byte count
189|
190| Set signalling nan bit
191|
192 bsetl #30,%d1
193|
194| Store to the users destination address
195|
196 tstl %a0 |check if <ea> is 0
197 beqs wrt_dn |destination is a data register
198
199 movel %d1,-(%a7) |move the snan onto the stack
200 movel %a0,%a1 |load dest addr into a1
201 movel %a7,%a0 |point to low word
202 bsrl mem_write |write snan to user memory
203 movel (%a7)+,%d1 |clear off stack
204 rts
205|
206| Get the 8 most significant bits of etemp mantissa
207|
208sto_byte:
209 movel ETEMP_HI(%a6),%d1
210 movel #1,%d0 |load byte count
211|
212| Set signalling nan bit
213|
214 bsetl #30,%d1
215|
216| Store to the users destination address
217|
218 tstl %a0 |check if <ea> is 0
219 beqs wrt_dn |destination is a data register
220 movel %d1,-(%a7) |move the snan onto the stack
221 movel %a0,%a1 |load dest addr into a1
222 movel %a7,%a0 |point to source byte
223 bsrl mem_write |write snan to user memory
224 movel (%a7)+,%d1 |clear off stack
225 rts
226
227|
228| wrt_dn --- write to a data register
229|
230| We get here with D1 containing the data to write and D0 the
231| number of bytes to write: 1=byte,2=word,4=long.
232|
233wrt_dn:
234 movel %d1,L_SCR1(%a6) |data
235 movel %d0,-(%a7) |size
236 bsrl get_fline |returns fline word in d0
237 movel %d0,%d1
238 andil #0x7,%d1 |d1 now holds register number
239 movel (%sp)+,%d0 |get original size
240 cmpil #4,%d0
241 beqs wrt_long
242 cmpil #2,%d0
243 bnes wrt_byte
244wrt_word:
245 orl #0x8,%d1
246 bral reg_dest
247wrt_long:
248 orl #0x10,%d1
249 bral reg_dest
250wrt_byte:
251 bral reg_dest
252|
253| Check if it is a src nan or dst nan
254|
255not_out:
256 movel DTAG(%a6),%d0
257 bfextu %d0{#0:#3},%d0 |isolate dtag in lsbs
258
259 cmpib #3,%d0 |check for nan in destination
260 bnes issrc |destination nan has priority
261dst_nan:
262 btstb #6,FPTEMP_HI(%a6) |check if dest nan is an snan
263 bnes issrc |no, so check source for snan
264 movew FPTEMP_EX(%a6),%d0
265 bras cont
266issrc:
267 movew ETEMP_EX(%a6),%d0
268cont:
269 btstl #15,%d0 |test for sign of snan
270 beqs clr_neg
271 bsetb #neg_bit,FPSR_CC(%a6)
272 bra report_snan
273clr_neg:
274 bclrb #neg_bit,FPSR_CC(%a6)
275 bra report_snan
276
277 |end
diff --git a/arch/m68k/fpsp040/x_store.S b/arch/m68k/fpsp040/x_store.S
new file mode 100644
index 000000000000..4282fa67d449
--- /dev/null
+++ b/arch/m68k/fpsp040/x_store.S
@@ -0,0 +1,256 @@
1|
2| x_store.sa 3.2 1/24/91
3|
4| store --- store operand to memory or register
5|
6| Used by underflow and overflow handlers.
7|
8| a6 = points to fp value to be stored.
9|
10
11| Copyright (C) Motorola, Inc. 1990
12| All Rights Reserved
13|
14| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
15| The copyright notice above does not evidence any
16| actual or intended publication of such source code.
17
18X_STORE: |idnt 2,1 | Motorola 040 Floating Point Software Package
19
20 |section 8
21
22fpreg_mask:
23 .byte 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
24
25#include "fpsp.h"
26
27 |xref mem_write
28 |xref get_fline
29 |xref g_opcls
30 |xref g_dfmtou
31 |xref reg_dest
32
33 .global dest_ext
34 .global dest_dbl
35 .global dest_sgl
36
37 .global store
38store:
39 btstb #E3,E_BYTE(%a6)
40 beqs E1_sto
41E3_sto:
42 movel CMDREG3B(%a6),%d0
43 bfextu %d0{#6:#3},%d0 |isolate dest. reg from cmdreg3b
44sto_fp:
45 lea fpreg_mask,%a1
46 moveb (%a1,%d0.w),%d0 |convert reg# to dynamic register mask
47 tstb LOCAL_SGN(%a0)
48 beqs is_pos
49 bsetb #sign_bit,LOCAL_EX(%a0)
50is_pos:
51 fmovemx (%a0),%d0 |move to correct register
52|
53| if fp0-fp3 is being modified, we must put a copy
54| in the USER_FPn variable on the stack because all exception
55| handlers restore fp0-fp3 from there.
56|
57 cmpb #0x80,%d0
58 bnes not_fp0
59 fmovemx %fp0-%fp0,USER_FP0(%a6)
60 rts
61not_fp0:
62 cmpb #0x40,%d0
63 bnes not_fp1
64 fmovemx %fp1-%fp1,USER_FP1(%a6)
65 rts
66not_fp1:
67 cmpb #0x20,%d0
68 bnes not_fp2
69 fmovemx %fp2-%fp2,USER_FP2(%a6)
70 rts
71not_fp2:
72 cmpb #0x10,%d0
73 bnes not_fp3
74 fmovemx %fp3-%fp3,USER_FP3(%a6)
75 rts
76not_fp3:
77 rts
78
79E1_sto:
80 bsrl g_opcls |returns opclass in d0
81 cmpib #3,%d0
82 beq opc011 |branch if opclass 3
83 movel CMDREG1B(%a6),%d0
84 bfextu %d0{#6:#3},%d0 |extract destination register
85 bras sto_fp
86
87opc011:
88 bsrl g_dfmtou |returns dest format in d0
89| ;ext=00, sgl=01, dbl=10
90 movel %a0,%a1 |save source addr in a1
91 movel EXC_EA(%a6),%a0 |get the address
92 cmpil #0,%d0 |if dest format is extended
93 beq dest_ext |then branch
94 cmpil #1,%d0 |if dest format is single
95 beq dest_sgl |then branch
96|
97| fall through to dest_dbl
98|
99
100|
101| dest_dbl --- write double precision value to user space
102|
103|Input
104| a0 -> destination address
105| a1 -> source in extended precision
106|Output
107| a0 -> destroyed
108| a1 -> destroyed
109| d0 -> 0
110|
111|Changes extended precision to double precision.
112| Note: no attempt is made to round the extended value to double.
113| dbl_sign = ext_sign
114| dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
115| get rid of ext integer bit
116| dbl_mant = ext_mant{62:12}
117|
118| --------------- --------------- ---------------
119| extended -> |s| exp | |1| ms mant | | ls mant |
120| --------------- --------------- ---------------
121| 95 64 63 62 32 31 11 0
122| | |
123| | |
124| | |
125| v v
126| --------------- ---------------
127| double -> |s|exp| mant | | mant |
128| --------------- ---------------
129| 63 51 32 31 0
130|
131dest_dbl:
132 clrl %d0 |clear d0
133 movew LOCAL_EX(%a1),%d0 |get exponent
134 subw #0x3fff,%d0 |subtract extended precision bias
135 cmpw #0x4000,%d0 |check if inf
136 beqs inf |if so, special case
137 addw #0x3ff,%d0 |add double precision bias
138 swap %d0 |d0 now in upper word
139 lsll #4,%d0 |d0 now in proper place for dbl prec exp
140 tstb LOCAL_SGN(%a1)
141 beqs get_mant |if positive, go process mantissa
142 bsetl #31,%d0 |if negative, put in sign information
143| ; before continuing
144 bras get_mant |go process mantissa
145inf:
146 movel #0x7ff00000,%d0 |load dbl inf exponent
147 clrl LOCAL_HI(%a1) |clear msb
148 tstb LOCAL_SGN(%a1)
149 beqs dbl_inf |if positive, go ahead and write it
150 bsetl #31,%d0 |if negative put in sign information
151dbl_inf:
152 movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack
153 bras dbl_wrt
154get_mant:
155 movel LOCAL_HI(%a1),%d1 |get ms mantissa
156 bfextu %d1{#1:#20},%d1 |get upper 20 bits of ms
157 orl %d1,%d0 |put these bits in ms word of double
158 movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack
159 movel LOCAL_HI(%a1),%d1 |get ms mantissa
160 movel #21,%d0 |load shift count
161 lsll %d0,%d1 |put lower 11 bits in upper bits
162 movel %d1,LOCAL_HI(%a1) |build lower lword in memory
163 movel LOCAL_LO(%a1),%d1 |get ls mantissa
164 bfextu %d1{#0:#21},%d0 |get ls 21 bits of double
165 orl %d0,LOCAL_HI(%a1) |put them in double result
166dbl_wrt:
167 movel #0x8,%d0 |byte count for double precision number
168 exg %a0,%a1 |a0=supervisor source, a1=user dest
169 bsrl mem_write |move the number to the user's memory
170 rts
171|
172| dest_sgl --- write single precision value to user space
173|
174|Input
175| a0 -> destination address
176| a1 -> source in extended precision
177|
178|Output
179| a0 -> destroyed
180| a1 -> destroyed
181| d0 -> 0
182|
183|Changes extended precision to single precision.
184| sgl_sign = ext_sign
185| sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
186| get rid of ext integer bit
187| sgl_mant = ext_mant{62:12}
188|
189| --------------- --------------- ---------------
190| extended -> |s| exp | |1| ms mant | | ls mant |
191| --------------- --------------- ---------------
192| 95 64 63 62 40 32 31 12 0
193| | |
194| | |
195| | |
196| v v
197| ---------------
198| single -> |s|exp| mant |
199| ---------------
200| 31 22 0
201|
202dest_sgl:
203 clrl %d0
204 movew LOCAL_EX(%a1),%d0 |get exponent
205 subw #0x3fff,%d0 |subtract extended precision bias
206 cmpw #0x4000,%d0 |check if inf
207 beqs sinf |if so, special case
208 addw #0x7f,%d0 |add single precision bias
209 swap %d0 |put exp in upper word of d0
210 lsll #7,%d0 |shift it into single exp bits
211 tstb LOCAL_SGN(%a1)
212 beqs get_sman |if positive, continue
213 bsetl #31,%d0 |if negative, put in sign first
214 bras get_sman |get mantissa
215sinf:
216 movel #0x7f800000,%d0 |load single inf exp to d0
217 tstb LOCAL_SGN(%a1)
218 beqs sgl_wrt |if positive, continue
219 bsetl #31,%d0 |if negative, put in sign info
220 bras sgl_wrt
221
222get_sman:
223 movel LOCAL_HI(%a1),%d1 |get ms mantissa
224 bfextu %d1{#1:#23},%d1 |get upper 23 bits of ms
225 orl %d1,%d0 |put these bits in ms word of single
226
227sgl_wrt:
228 movel %d0,L_SCR1(%a6) |put the new exp back on the stack
229 movel #0x4,%d0 |byte count for single precision number
230 tstl %a0 |users destination address
231 beqs sgl_Dn |destination is a data register
232 exg %a0,%a1 |a0=supervisor source, a1=user dest
233 leal L_SCR1(%a6),%a0 |point a0 to data
234 bsrl mem_write |move the number to the user's memory
235 rts
236sgl_Dn:
237 bsrl get_fline |returns fline word in d0
238 andw #0x7,%d0 |isolate register number
239 movel %d0,%d1 |d1 has size:reg formatted for reg_dest
240 orl #0x10,%d1 |reg_dest wants size added to reg#
241 bral reg_dest |size is X, rts in reg_dest will
242| ;return to caller of dest_sgl
243
244dest_ext:
245 tstb LOCAL_SGN(%a1) |put back sign into exponent word
246 beqs dstx_cont
247 bsetb #sign_bit,LOCAL_EX(%a1)
248dstx_cont:
249 clrb LOCAL_SGN(%a1) |clear out the sign byte
250
251 movel #0x0c,%d0 |byte count for extended number
252 exg %a0,%a1 |a0=supervisor source, a1=user dest
253 bsrl mem_write |move the number to the user's memory
254 rts
255
256 |end
diff --git a/arch/m68k/fpsp040/x_unfl.S b/arch/m68k/fpsp040/x_unfl.S
new file mode 100644
index 000000000000..077fcc230fcc
--- /dev/null
+++ b/arch/m68k/fpsp040/x_unfl.S
@@ -0,0 +1,269 @@
1|
2| x_unfl.sa 3.4 7/1/91
3|
4| fpsp_unfl --- FPSP handler for underflow exception
5|
6| Trap disabled results
7| For 881/2 compatibility, sw must denormalize the intermediate
8| result, then store the result. Denormalization is accomplished
9| by taking the intermediate result (which is always normalized) and
10| shifting the mantissa right while incrementing the exponent until
11| it is equal to the denormalized exponent for the destination
12| format. After denormalization, the result is rounded to the
13| destination format.
14|
15| Trap enabled results
16| All trap disabled code applies. In addition the exceptional
17| operand needs to made available to the user with a bias of $6000
18| added to the exponent.
19|
20
21| Copyright (C) Motorola, Inc. 1990
22| All Rights Reserved
23|
24| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
25| The copyright notice above does not evidence any
26| actual or intended publication of such source code.
27
28X_UNFL: |idnt 2,1 | Motorola 040 Floating Point Software Package
29
30 |section 8
31
32#include "fpsp.h"
33
34 |xref denorm
35 |xref round
36 |xref store
37 |xref g_rndpr
38 |xref g_opcls
39 |xref g_dfmtou
40 |xref real_unfl
41 |xref real_inex
42 |xref fpsp_done
43 |xref b1238_fix
44
45 .global fpsp_unfl
46fpsp_unfl:
47 link %a6,#-LOCAL_SIZE
48 fsave -(%a7)
49 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
50 fmovemx %fp0-%fp3,USER_FP0(%a6)
51 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
52
53|
54 bsrl unf_res |denormalize, round & store interm op
55|
56| If underflow exceptions are not enabled, check for inexact
57| exception
58|
59 btstb #unfl_bit,FPCR_ENABLE(%a6)
60 beqs ck_inex
61
62 btstb #E3,E_BYTE(%a6)
63 beqs no_e3_1
64|
65| Clear dirty bit on dest resister in the frame before branching
66| to b1238_fix.
67|
68 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
69 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
70 bsrl b1238_fix |test for bug1238 case
71 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
72 orl #sx_mask,E_BYTE(%a6)
73no_e3_1:
74 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
75 fmovemx USER_FP0(%a6),%fp0-%fp3
76 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
77 frestore (%a7)+
78 unlk %a6
79 bral real_unfl
80|
81| It is possible to have either inex2 or inex1 exceptions with the
82| unfl. If the inex enable bit is set in the FPCR, and either
83| inex2 or inex1 occurred, we must clean up and branch to the
84| real inex handler.
85|
86ck_inex:
87 moveb FPCR_ENABLE(%a6),%d0
88 andb FPSR_EXCEPT(%a6),%d0
89 andib #0x3,%d0
90 beqs unfl_done
91
92|
93| Inexact enabled and reported, and we must take an inexact exception
94|
95take_inex:
96 btstb #E3,E_BYTE(%a6)
97 beqs no_e3_2
98|
99| Clear dirty bit on dest resister in the frame before branching
100| to b1238_fix.
101|
102 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
103 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
104 bsrl b1238_fix |test for bug1238 case
105 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
106 orl #sx_mask,E_BYTE(%a6)
107no_e3_2:
108 moveb #INEX_VEC,EXC_VEC+1(%a6)
109 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
110 fmovemx USER_FP0(%a6),%fp0-%fp3
111 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
112 frestore (%a7)+
113 unlk %a6
114 bral real_inex
115
116unfl_done:
117 bclrb #E3,E_BYTE(%a6)
118 beqs e1_set |if set then branch
119|
120| Clear dirty bit on dest resister in the frame before branching
121| to b1238_fix.
122|
123 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
124 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
125 bsrl b1238_fix |test for bug1238 case
126 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
127 orl #sx_mask,E_BYTE(%a6)
128 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
129 fmovemx USER_FP0(%a6),%fp0-%fp3
130 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
131 frestore (%a7)+
132 unlk %a6
133 bral fpsp_done
134e1_set:
135 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
136 fmovemx USER_FP0(%a6),%fp0-%fp3
137 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
138 unlk %a6
139 bral fpsp_done
140|
141| unf_res --- underflow result calculation
142|
143unf_res:
144 bsrl g_rndpr |returns RND_PREC in d0 0=ext,
145| ;1=sgl, 2=dbl
146| ;we need the RND_PREC in the
147| ;upper word for round
148 movew #0,-(%a7)
149 movew %d0,-(%a7) |copy RND_PREC to stack
150|
151|
152| If the exception bit set is E3, the exceptional operand from the
153| fpu is in WBTEMP; else it is in FPTEMP.
154|
155 btstb #E3,E_BYTE(%a6)
156 beqs unf_E1
157unf_E3:
158 lea WBTEMP(%a6),%a0 |a0 now points to operand
159|
160| Test for fsgldiv and fsglmul. If the inst was one of these, then
161| force the precision to extended for the denorm routine. Use
162| the user's precision for the round routine.
163|
164 movew CMDREG3B(%a6),%d1 |check for fsgldiv or fsglmul
165 andiw #0x7f,%d1
166 cmpiw #0x30,%d1 |check for sgldiv
167 beqs unf_sgl
168 cmpiw #0x33,%d1 |check for sglmul
169 bnes unf_cont |if not, use fpcr prec in round
170unf_sgl:
171 clrl %d0
172 movew #0x1,(%a7) |override g_rndpr precision
173| ;force single
174 bras unf_cont
175unf_E1:
176 lea FPTEMP(%a6),%a0 |a0 now points to operand
177unf_cont:
178 bclrb #sign_bit,LOCAL_EX(%a0) |clear sign bit
179 sne LOCAL_SGN(%a0) |store sign
180
181 bsrl denorm |returns denorm, a0 points to it
182|
183| WARNING:
184| ;d0 has guard,round sticky bit
185| ;make sure that it is not corrupted
186| ;before it reaches the round subroutine
187| ;also ensure that a0 isn't corrupted
188
189|
190| Set up d1 for round subroutine d1 contains the PREC/MODE
191| information respectively on upper/lower register halves.
192|
193 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get mode from FPCR
194| ;mode in lower d1
195 addl (%a7)+,%d1 |merge PREC/MODE
196|
197| WARNING: a0 and d0 are assumed to be intact between the denorm and
198| round subroutines. All code between these two subroutines
199| must not corrupt a0 and d0.
200|
201|
202| Perform Round
203| Input: a0 points to input operand
204| d0{31:29} has guard, round, sticky
205| d1{01:00} has rounding mode
206| d1{17:16} has rounding precision
207| Output: a0 points to rounded operand
208|
209
210 bsrl round |returns rounded denorm at (a0)
211|
212| Differentiate between store to memory vs. store to register
213|
214unf_store:
215 bsrl g_opcls |returns opclass in d0{2:0}
216 cmpib #0x3,%d0
217 bnes not_opc011
218|
219| At this point, a store to memory is pending
220|
221opc011:
222 bsrl g_dfmtou
223 tstb %d0
224 beqs ext_opc011 |If extended, do not subtract
225| ;If destination format is sgl/dbl,
226 tstb LOCAL_HI(%a0) |If rounded result is normal,don't
227| ;subtract
228 bmis ext_opc011
229 subqw #1,LOCAL_EX(%a0) |account for denorm bias vs.
230| ;normalized bias
231| ; normalized denormalized
232| ;single $7f $7e
233| ;double $3ff $3fe
234|
235ext_opc011:
236 bsrl store |stores to memory
237 bras unf_done |finish up
238
239|
240| At this point, a store to a float register is pending
241|
242not_opc011:
243 bsrl store |stores to float register
244| ;a0 is not corrupted on a store to a
245| ;float register.
246|
247| Set the condition codes according to result
248|
249 tstl LOCAL_HI(%a0) |check upper mantissa
250 bnes ck_sgn
251 tstl LOCAL_LO(%a0) |check lower mantissa
252 bnes ck_sgn
253 bsetb #z_bit,FPSR_CC(%a6) |set condition codes if zero
254ck_sgn:
255 btstb #sign_bit,LOCAL_EX(%a0) |check the sign bit
256 beqs unf_done
257 bsetb #neg_bit,FPSR_CC(%a6)
258
259|
260| Finish.
261|
262unf_done:
263 btstb #inex2_bit,FPSR_EXCEPT(%a6)
264 beqs no_aunfl
265 bsetb #aunfl_bit,FPSR_AEXCEPT(%a6)
266no_aunfl:
267 rts
268
269 |end
diff --git a/arch/m68k/fpsp040/x_unimp.S b/arch/m68k/fpsp040/x_unimp.S
new file mode 100644
index 000000000000..920cb9410e9e
--- /dev/null
+++ b/arch/m68k/fpsp040/x_unimp.S
@@ -0,0 +1,77 @@
1|
2| x_unimp.sa 3.3 7/1/91
3|
4| fpsp_unimp --- FPSP handler for unimplemented instruction
5| exception.
6|
7| Invoked when the user program encounters a floating-point
8| op-code that hardware does not support. Trap vector# 11
9| (See table 8-1 MC68030 User's Manual).
10|
11|
12| Note: An fsave for an unimplemented inst. will create a short
13| fsave stack.
14|
15| Input: 1. Six word stack frame for unimplemented inst, four word
16| for illegal
17| (See table 8-7 MC68030 User's Manual).
18| 2. Unimp (short) fsave state frame created here by fsave
19| instruction.
20|
21|
22| Copyright (C) Motorola, Inc. 1990
23| All Rights Reserved
24|
25| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
26| The copyright notice above does not evidence any
27| actual or intended publication of such source code.
28
29X_UNIMP: |idnt 2,1 | Motorola 040 Floating Point Software Package
30
31 |section 8
32
33#include "fpsp.h"
34
35 |xref get_op
36 |xref do_func
37 |xref sto_res
38 |xref gen_except
39 |xref fpsp_fmt_error
40
41 .global fpsp_unimp
42 .global uni_2
43fpsp_unimp:
44 link %a6,#-LOCAL_SIZE
45 fsave -(%a7)
46uni_2:
47 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
48 fmovemx %fp0-%fp3,USER_FP0(%a6)
49 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
50 moveb (%a7),%d0 |test for valid version num
51 andib #0xf0,%d0 |test for $4x
52 cmpib #VER_4,%d0 |must be $4x or exit
53 bnel fpsp_fmt_error
54|
55| Temporary D25B Fix
56| The following lines are used to ensure that the FPSR
57| exception byte and condition codes are clear before proceeding
58|
59 movel USER_FPSR(%a6),%d0
60 andl #0xFF00FF,%d0 |clear all but accrued exceptions
61 movel %d0,USER_FPSR(%a6)
62 fmovel #0,%FPSR |clear all user bits
63 fmovel #0,%FPCR |clear all user exceptions for FPSP
64
65 clrb UFLG_TMP(%a6) |clr flag for unsupp data
66
67 bsrl get_op |go get operand(s)
68 clrb STORE_FLG(%a6)
69 bsrl do_func |do the function
70 fsave -(%a7) |capture possible exc state
71 tstb STORE_FLG(%a6)
72 bnes no_store |if STORE_FLG is set, no store
73 bsrl sto_res |store the result in user space
74no_store:
75 bral gen_except |post any exceptions and return
76
77 |end
diff --git a/arch/m68k/fpsp040/x_unsupp.S b/arch/m68k/fpsp040/x_unsupp.S
new file mode 100644
index 000000000000..4ec57285b683
--- /dev/null
+++ b/arch/m68k/fpsp040/x_unsupp.S
@@ -0,0 +1,83 @@
1|
2| x_unsupp.sa 3.3 7/1/91
3|
4| fpsp_unsupp --- FPSP handler for unsupported data type exception
5|
6| Trap vector #55 (See table 8-1 Mc68030 User's manual).
7| Invoked when the user program encounters a data format (packed) that
8| hardware does not support or a data type (denormalized numbers or un-
9| normalized numbers).
10| Normalizes denorms and unnorms, unpacks packed numbers then stores
11| them back into the machine to let the 040 finish the operation.
12|
13| Unsupp calls two routines:
14| 1. get_op - gets the operand(s)
15| 2. res_func - restore the function back into the 040 or
16| if fmove.p fpm,<ea> then pack source (fpm)
17| and store in users memory <ea>.
18|
19| Input: Long fsave stack frame
20|
21|
22
23| Copyright (C) Motorola, Inc. 1990
24| All Rights Reserved
25|
26| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
27| The copyright notice above does not evidence any
28| actual or intended publication of such source code.
29
30X_UNSUPP: |idnt 2,1 | Motorola 040 Floating Point Software Package
31
32 |section 8
33
34#include "fpsp.h"
35
36 |xref get_op
37 |xref res_func
38 |xref gen_except
39 |xref fpsp_fmt_error
40
41 .global fpsp_unsupp
42fpsp_unsupp:
43|
44 link %a6,#-LOCAL_SIZE
45 fsave -(%a7)
46 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
47 fmovemx %fp0-%fp3,USER_FP0(%a6)
48 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
49
50
51 moveb (%a7),VER_TMP(%a6) |save version number
52 moveb (%a7),%d0 |test for valid version num
53 andib #0xf0,%d0 |test for $4x
54 cmpib #VER_4,%d0 |must be $4x or exit
55 bnel fpsp_fmt_error
56
57 fmovel #0,%FPSR |clear all user status bits
58 fmovel #0,%FPCR |clear all user control bits
59|
60| The following lines are used to ensure that the FPSR
61| exception byte and condition codes are clear before proceeding,
62| except in the case of fmove, which leaves the cc's intact.
63|
64unsupp_con:
65 movel USER_FPSR(%a6),%d1
66 btst #5,CMDREG1B(%a6) |looking for fmove out
67 bne fmove_con
68 andl #0xFF00FF,%d1 |clear all but aexcs and qbyte
69 bras end_fix
70fmove_con:
71 andl #0x0FFF40FF,%d1 |clear all but cc's, snan bit, aexcs, and qbyte
72end_fix:
73 movel %d1,USER_FPSR(%a6)
74
75 st UFLG_TMP(%a6) |set flag for unsupp data
76
77 bsrl get_op |everything okay, go get operand(s)
78 bsrl res_func |fix up stack frame so can restore it
79 clrl -(%a7)
80 moveb VER_TMP(%a6),(%a7) |move idle fmt word to top of stack
81 bral gen_except
82|
83 |end
diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
new file mode 100644
index 000000000000..89b6317899e3
--- /dev/null
+++ b/arch/m68k/hp300/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/hp300 source directory
3#
4
5obj-y := ksyms.o config.o ints.o time.o reboot.o
diff --git a/arch/m68k/hp300/README.hp300 b/arch/m68k/hp300/README.hp300
new file mode 100644
index 000000000000..47073fbd400d
--- /dev/null
+++ b/arch/m68k/hp300/README.hp300
@@ -0,0 +1,14 @@
1HP300 notes
2-----------
3
4The Linux/HP web page is at <http://www.tazenda.demon.co.uk/phil/linux-hp/>
5
6Currently only 9000/340 machines have been tested. Any amount of RAM should
7work now but I've only tried 16MB and 12MB.
8
9The serial console is probably broken at the moment but the Topcat/HIL keyboard
10combination seems to work for me. Your mileage may vary.
11
12The LANCE driver works after a fashion but only if you reset the chip before
13every packet. This doesn't make for very speedy operation.
14
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
new file mode 100644
index 000000000000..a0b854f3f94a
--- /dev/null
+++ b/arch/m68k/hp300/config.c
@@ -0,0 +1,279 @@
1/*
2 * linux/arch/m68k/hp300/config.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific initialisation code. It gets
7 * called by setup.c.
8 */
9
10#include <linux/config.h>
11#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/string.h>
14#include <linux/kernel.h>
15#include <linux/console.h>
16
17#include <asm/bootinfo.h>
18#include <asm/machdep.h>
19#include <asm/blinken.h>
20#include <asm/io.h> /* readb() and writeb() */
21#include <asm/hp300hw.h>
22#include <asm/rtc.h>
23
24#include "ints.h"
25#include "time.h"
26
27unsigned long hp300_model;
28unsigned long hp300_uart_scode = -1;
29unsigned char ledstate;
30
31static char s_hp330[] __initdata = "330";
32static char s_hp340[] __initdata = "340";
33static char s_hp345[] __initdata = "345";
34static char s_hp360[] __initdata = "360";
35static char s_hp370[] __initdata = "370";
36static char s_hp375[] __initdata = "375";
37static char s_hp380[] __initdata = "380";
38static char s_hp385[] __initdata = "385";
39static char s_hp400[] __initdata = "400";
40static char s_hp425t[] __initdata = "425t";
41static char s_hp425s[] __initdata = "425s";
42static char s_hp425e[] __initdata = "425e";
43static char s_hp433t[] __initdata = "433t";
44static char s_hp433s[] __initdata = "433s";
45static char *hp300_models[] __initdata = {
46 [HP_320] = NULL,
47 [HP_330] = s_hp330,
48 [HP_340] = s_hp340,
49 [HP_345] = s_hp345,
50 [HP_350] = NULL,
51 [HP_360] = s_hp360,
52 [HP_370] = s_hp370,
53 [HP_375] = s_hp375,
54 [HP_380] = s_hp380,
55 [HP_385] = s_hp385,
56 [HP_400] = s_hp400,
57 [HP_425T] = s_hp425t,
58 [HP_425S] = s_hp425s,
59 [HP_425E] = s_hp425e,
60 [HP_433T] = s_hp433t,
61 [HP_433S] = s_hp433s,
62};
63
64static char hp300_model_name[13] = "HP9000/";
65
66extern void hp300_reset(void);
67extern irqreturn_t (*hp300_default_handler[])(int, void *, struct pt_regs *);
68extern int show_hp300_interrupts(struct seq_file *, void *);
69#ifdef CONFIG_SERIAL_8250_CONSOLE
70extern int hp300_setup_serial_console(void) __init;
71#endif
72
73int __init hp300_parse_bootinfo(const struct bi_record *record)
74{
75 int unknown = 0;
76 const unsigned long *data = record->data;
77
78 switch (record->tag) {
79 case BI_HP300_MODEL:
80 hp300_model = *data;
81 break;
82
83 case BI_HP300_UART_SCODE:
84 hp300_uart_scode = *data;
85 break;
86
87 case BI_HP300_UART_ADDR:
88 /* serial port address: ignored here */
89 break;
90
91 default:
92 unknown = 1;
93 }
94
95 return unknown;
96}
97
98#ifdef CONFIG_HEARTBEAT
99static void hp300_pulse(int x)
100{
101 if (x)
102 blinken_leds(0x10, 0);
103 else
104 blinken_leds(0, 0x10);
105}
106#endif
107
108static void hp300_get_model(char *model)
109{
110 strcpy(model, hp300_model_name);
111}
112
113#define RTCBASE 0xf0420000
114#define RTC_DATA 0x1
115#define RTC_CMD 0x3
116
117#define RTC_BUSY 0x02
118#define RTC_DATA_RDY 0x01
119
120#define rtc_busy() (in_8(RTCBASE + RTC_CMD) & RTC_BUSY)
121#define rtc_data_available() (in_8(RTCBASE + RTC_CMD) & RTC_DATA_RDY)
122#define rtc_status() (in_8(RTCBASE + RTC_CMD))
123#define rtc_command(x) out_8(RTCBASE + RTC_CMD, (x))
124#define rtc_read_data() (in_8(RTCBASE + RTC_DATA))
125#define rtc_write_data(x) out_8(RTCBASE + RTC_DATA, (x))
126
127#define RTC_SETREG 0xe0
128#define RTC_WRITEREG 0xc2
129#define RTC_READREG 0xc3
130
131#define RTC_REG_SEC2 0
132#define RTC_REG_SEC1 1
133#define RTC_REG_MIN2 2
134#define RTC_REG_MIN1 3
135#define RTC_REG_HOUR2 4
136#define RTC_REG_HOUR1 5
137#define RTC_REG_WDAY 6
138#define RTC_REG_DAY2 7
139#define RTC_REG_DAY1 8
140#define RTC_REG_MON2 9
141#define RTC_REG_MON1 10
142#define RTC_REG_YEAR2 11
143#define RTC_REG_YEAR1 12
144
145#define RTC_HOUR1_24HMODE 0x8
146
147#define RTC_STAT_MASK 0xf0
148#define RTC_STAT_RDY 0x40
149
150static inline unsigned char hp300_rtc_read(unsigned char reg)
151{
152 unsigned char s, ret;
153 unsigned long flags;
154
155 local_irq_save(flags);
156
157 while (rtc_busy());
158 rtc_command(RTC_SETREG);
159 while (rtc_busy());
160 rtc_write_data(reg);
161 while (rtc_busy());
162 rtc_command(RTC_READREG);
163
164 do {
165 while (!rtc_data_available());
166 s = rtc_status();
167 ret = rtc_read_data();
168 } while ((s & RTC_STAT_MASK) != RTC_STAT_RDY);
169
170 local_irq_restore(flags);
171
172 return ret;
173}
174
175static inline unsigned char hp300_rtc_write(unsigned char reg,
176 unsigned char val)
177{
178 unsigned char s, ret;
179 unsigned long flags;
180
181 local_irq_save(flags);
182
183 while (rtc_busy());
184 rtc_command(RTC_SETREG);
185 while (rtc_busy());
186 rtc_write_data((val << 4) | reg);
187 while (rtc_busy());
188 rtc_command(RTC_WRITEREG);
189 while (rtc_busy());
190 rtc_command(RTC_READREG);
191
192 do {
193 while (!rtc_data_available());
194 s = rtc_status();
195 ret = rtc_read_data();
196 } while ((s & RTC_STAT_MASK) != RTC_STAT_RDY);
197
198 local_irq_restore(flags);
199
200 return ret;
201}
202
203static int hp300_hwclk(int op, struct rtc_time *t)
204{
205 if (!op) { /* read */
206 t->tm_sec = hp300_rtc_read(RTC_REG_SEC1) * 10 +
207 hp300_rtc_read(RTC_REG_SEC2);
208 t->tm_min = hp300_rtc_read(RTC_REG_MIN1) * 10 +
209 hp300_rtc_read(RTC_REG_MIN2);
210 t->tm_hour = (hp300_rtc_read(RTC_REG_HOUR1) & 3) * 10 +
211 hp300_rtc_read(RTC_REG_HOUR2);
212 t->tm_wday = -1;
213 t->tm_mday = hp300_rtc_read(RTC_REG_DAY1) * 10 +
214 hp300_rtc_read(RTC_REG_DAY2);
215 t->tm_mon = hp300_rtc_read(RTC_REG_MON1) * 10 +
216 hp300_rtc_read(RTC_REG_MON2) - 1;
217 t->tm_year = hp300_rtc_read(RTC_REG_YEAR1) * 10 +
218 hp300_rtc_read(RTC_REG_YEAR2);
219 if (t->tm_year <= 69)
220 t->tm_year += 100;
221 } else {
222 hp300_rtc_write(RTC_REG_SEC1, t->tm_sec / 10);
223 hp300_rtc_write(RTC_REG_SEC2, t->tm_sec % 10);
224 hp300_rtc_write(RTC_REG_MIN1, t->tm_min / 10);
225 hp300_rtc_write(RTC_REG_MIN2, t->tm_min % 10);
226 hp300_rtc_write(RTC_REG_HOUR1,
227 ((t->tm_hour / 10) & 3) | RTC_HOUR1_24HMODE);
228 hp300_rtc_write(RTC_REG_HOUR2, t->tm_hour % 10);
229 hp300_rtc_write(RTC_REG_DAY1, t->tm_mday / 10);
230 hp300_rtc_write(RTC_REG_DAY2, t->tm_mday % 10);
231 hp300_rtc_write(RTC_REG_MON1, (t->tm_mon + 1) / 10);
232 hp300_rtc_write(RTC_REG_MON2, (t->tm_mon + 1) % 10);
233 if (t->tm_year >= 100)
234 t->tm_year -= 100;
235 hp300_rtc_write(RTC_REG_YEAR1, t->tm_year / 10);
236 hp300_rtc_write(RTC_REG_YEAR2, t->tm_year % 10);
237 }
238
239 return 0;
240}
241
242static unsigned int hp300_get_ss(void)
243{
244 return hp300_rtc_read(RTC_REG_SEC1) * 10 +
245 hp300_rtc_read(RTC_REG_SEC2);
246}
247
248void __init config_hp300(void)
249{
250 mach_sched_init = hp300_sched_init;
251 mach_init_IRQ = hp300_init_IRQ;
252 mach_request_irq = hp300_request_irq;
253 mach_free_irq = hp300_free_irq;
254 mach_get_model = hp300_get_model;
255 mach_get_irq_list = show_hp300_interrupts;
256 mach_gettimeoffset = hp300_gettimeoffset;
257 mach_default_handler = &hp300_default_handler;
258 mach_hwclk = hp300_hwclk;
259 mach_get_ss = hp300_get_ss;
260 mach_reset = hp300_reset;
261#ifdef CONFIG_HEARTBEAT
262 mach_heartbeat = hp300_pulse;
263#endif
264#ifdef CONFIG_DUMMY_CONSOLE
265 conswitchp = &dummy_con;
266#endif
267 mach_max_dma_address = 0xffffffff;
268
269 if (hp300_model >= HP_330 && hp300_model <= HP_433S && hp300_model != HP_350) {
270 printk(KERN_INFO "Detected HP9000 model %s\n", hp300_models[hp300_model-HP_320]);
271 strcat(hp300_model_name, hp300_models[hp300_model-HP_320]);
272 }
273 else {
274 panic("Unknown HP9000 Model");
275 }
276#ifdef CONFIG_SERIAL_8250_CONSOLE
277 hp300_setup_serial_console();
278#endif
279}
diff --git a/arch/m68k/hp300/hp300map.map b/arch/m68k/hp300/hp300map.map
new file mode 100644
index 000000000000..6b45f0abc957
--- /dev/null
+++ b/arch/m68k/hp300/hp300map.map
@@ -0,0 +1,252 @@
1# HP300 kernel keymap. This uses 7 modifier combinations.
2keymaps 0-2,4-5,8,12
3# Change the above line into
4# keymaps 0-2,4-6,8,12
5# in case you want the entries
6# altgr control keycode 83 = Boot
7# altgr control keycode 111 = Boot
8# below.
9#
10# In fact AltGr is used very little, and one more keymap can
11# be saved by mapping AltGr to Alt (and adapting a few entries):
12# keycode 100 = Alt
13#
14keycode 1 =
15keycode 2 = Alt
16keycode 3 = Alt
17keycode 4 = Shift
18keycode 5 = Shift
19keycode 6 = Control
20keycode 7 =
21keycode 8 =
22keycode 9 =
23keycode 10 =
24keycode 11 =
25keycode 12 =
26keycode 13 =
27keycode 14 =
28keycode 15 =
29keycode 16 =
30keycode 17 =
31keycode 18 =
32keycode 19 =
33keycode 20 =
34keycode 21 =
35keycode 22 =
36keycode 23 =
37keycode 24 = b
38keycode 25 = v
39keycode 26 = c
40keycode 27 = x
41keycode 28 = z
42keycode 29 =
43keycode 30 =
44keycode 31 = Escape Delete
45keycode 32 =
46keycode 33 =
47keycode 34 =
48keycode 35 =
49keycode 36 =
50keycode 37 =
51keycode 38 =
52keycode 39 =
53keycode 40 = h
54keycode 41 = g
55keycode 42 = f
56keycode 43 = d
57keycode 44 = s
58keycode 45 = a
59keycode 46 =
60keycode 47 = Caps_Lock
61keycode 48 = u
62keycode 49 = y
63keycode 50 = t
64keycode 51 = r
65keycode 52 = e
66keycode 53 = w
67keycode 54 = q
68keycode 55 = Tab Tab
69 alt keycode 55 = Meta_Tab
70keycode 56 = seven ampersand
71keycode 57 = six asciicircum
72keycode 58 = five percent
73keycode 59 = four dollar
74keycode 60 = three numbersign
75keycode 61 = two at at
76keycode 62 = one exclam exclam
77keycode 63 = grave asciitilde
78 control keycode 63 = nul
79 alt keycode 63 = Meta_grave
80keycode 64 =
81keycode 65 =
82keycode 66 =
83keycode 67 =
84keycode 68 =
85keycode 69 =
86keycode 70 =
87keycode 71 =
88keycode 72 =
89keycode 73 = F4
90 control keycode 73 = Console_4
91keycode 74 = F3
92 control keycode 74 = Console_3
93keycode 75 = F2
94 control keycode 75 = Console_2
95keycode 76 = F1
96 control keycode 76 = Console_1
97keycode 77 =
98keycode 78 =
99keycode 79 =
100keycode 80 =
101keycode 81 = F5
102 control keycode 81 = Console_5
103keycode 82 = F6
104 control keycode 82 = Console_6
105keycode 83 = F7
106 control keycode 83 = Console_7
107keycode 84 = F8
108 control keycode 84 = Console_8
109keycode 85 =
110keycode 86 =
111keycode 87 =
112keycode 88 = eight asterisk asterisk
113keycode 89 = nine parenleft bracketleft
114keycode 90 = zero parenright bracketright
115keycode 91 = minus underscore
116keycode 92 = equal plus
117keycode 93 = BackSpace
118keycode 94 =
119keycode 95 =
120keycode 96 = i
121keycode 97 = o
122keycode 98 = p
123keycode 99 = bracketleft braceleft
124keycode 100 = bracketright braceright
125keycode 101 = backslash bar
126 control keycode 101 = Control_backslash
127 alt keycode 101 = Meta_backslash
128keycode 102 =
129keycode 103 =
130keycode 104 = j
131keycode 105 = k
132keycode 106 = l
133keycode 107 = semicolon colon
134 alt keycode 107 = Meta_semicolon
135keycode 108 = apostrophe quotedbl
136 control keycode 108 = Control_g
137 alt keycode 108 = Meta_apostrophe
138keycode 109 = Return
139keycode 110 =
140keycode 111 =
141keycode 112 = m
142keycode 113 = comma less
143keycode 114 = period greater
144keycode 115 = slash question
145keycode 116 =
146keycode 117 =
147keycode 118 =
148keycode 119 =
149keycode 120 = n
150keycode 121 = space space
151keycode 122 =
152keycode 123 =
153keycode 124 = Left
154keycode 125 = Down
155keycode 126 = Up
156keycode 127 = Right
157string F1 = "\033[[A"
158string F2 = "\033[[B"
159string F3 = "\033[[C"
160string F4 = "\033[[D"
161string F5 = "\033[[E"
162string F6 = "\033[17~"
163string F7 = "\033[18~"
164string F8 = "\033[19~"
165string F9 = "\033[20~"
166string F10 = "\033[21~"
167string F11 = "\033[23~"
168string F12 = "\033[24~"
169string F13 = "\033[25~"
170string F14 = "\033[26~"
171string F15 = "\033[28~"
172string F16 = "\033[29~"
173string F17 = "\033[31~"
174string F18 = "\033[32~"
175string F19 = "\033[33~"
176string F20 = "\033[34~"
177string Find = "\033[1~"
178string Insert = "\033[2~"
179string Remove = "\033[3~"
180string Select = "\033[4~"
181string Prior = "\033[5~"
182string Next = "\033[6~"
183string Macro = "\033[M"
184string Pause = "\033[P"
185compose '`' 'A' to 'À'
186compose '`' 'a' to 'à'
187compose '\'' 'A' to 'Á'
188compose '\'' 'a' to 'á'
189compose '^' 'A' to 'Â'
190compose '^' 'a' to 'â'
191compose '~' 'A' to 'Ã'
192compose '~' 'a' to 'ã'
193compose '"' 'A' to 'Ä'
194compose '"' 'a' to 'ä'
195compose 'O' 'A' to 'Å'
196compose 'o' 'a' to 'å'
197compose '0' 'A' to 'Å'
198compose '0' 'a' to 'å'
199compose 'A' 'A' to 'Å'
200compose 'a' 'a' to 'å'
201compose 'A' 'E' to 'Æ'
202compose 'a' 'e' to 'æ'
203compose ',' 'C' to 'Ç'
204compose ',' 'c' to 'ç'
205compose '`' 'E' to 'È'
206compose '`' 'e' to 'è'
207compose '\'' 'E' to 'É'
208compose '\'' 'e' to 'é'
209compose '^' 'E' to 'Ê'
210compose '^' 'e' to 'ê'
211compose '"' 'E' to 'Ë'
212compose '"' 'e' to 'ë'
213compose '`' 'I' to 'Ì'
214compose '`' 'i' to 'ì'
215compose '\'' 'I' to 'Í'
216compose '\'' 'i' to 'í'
217compose '^' 'I' to 'Î'
218compose '^' 'i' to 'î'
219compose '"' 'I' to 'Ï'
220compose '"' 'i' to 'ï'
221compose '-' 'D' to 'Ð'
222compose '-' 'd' to 'ð'
223compose '~' 'N' to 'Ñ'
224compose '~' 'n' to 'ñ'
225compose '`' 'O' to 'Ò'
226compose '`' 'o' to 'ò'
227compose '\'' 'O' to 'Ó'
228compose '\'' 'o' to 'ó'
229compose '^' 'O' to 'Ô'
230compose '^' 'o' to 'ô'
231compose '~' 'O' to 'Õ'
232compose '~' 'o' to 'õ'
233compose '"' 'O' to 'Ö'
234compose '"' 'o' to 'ö'
235compose '/' 'O' to 'Ø'
236compose '/' 'o' to 'ø'
237compose '`' 'U' to 'Ù'
238compose '`' 'u' to 'ù'
239compose '\'' 'U' to 'Ú'
240compose '\'' 'u' to 'ú'
241compose '^' 'U' to 'Û'
242compose '^' 'u' to 'û'
243compose '"' 'U' to 'Ü'
244compose '"' 'u' to 'ü'
245compose '\'' 'Y' to 'Ý'
246compose '\'' 'y' to 'ý'
247compose 'T' 'H' to 'Þ'
248compose 't' 'h' to 'þ'
249compose 's' 's' to 'ß'
250compose '"' 'y' to 'ÿ'
251compose 's' 'z' to 'ß'
252compose 'i' 'j' to 'ÿ'
diff --git a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c
new file mode 100644
index 000000000000..0c5bb403e893
--- /dev/null
+++ b/arch/m68k/hp300/ints.c
@@ -0,0 +1,175 @@
1/*
2 * linux/arch/m68k/hp300/ints.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific interrupt handling.
7 * We only use the autovector interrupts, and therefore we need to
8 * maintain lists of devices sharing each ipl.
9 * [ipl list code added by Peter Maydell <pmaydell@chiark.greenend.org.uk> 06/1998]
10 */
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/init.h>
15#include <linux/sched.h>
16#include <linux/kernel_stat.h>
17#include <linux/interrupt.h>
18#include <linux/spinlock.h>
19#include <asm/machdep.h>
20#include <asm/irq.h>
21#include <asm/io.h>
22#include <asm/system.h>
23#include <asm/traps.h>
24#include <asm/ptrace.h>
25#include <asm/errno.h>
26#include "ints.h"
27
28/* Each ipl has a linked list of interrupt service routines.
29 * Service routines are added via hp300_request_irq() and removed
30 * via hp300_free_irq(). The device driver should set IRQ_FLG_FAST
31 * if it needs to be serviced early (eg FIFOless UARTs); this will
32 * cause it to be added at the front of the queue rather than
33 * the back.
34 * Currently IRQ_FLG_SLOW and flags=0 are treated identically; if
35 * we needed three levels of priority we could distinguish them
36 * but this strikes me as mildly ugly...
37 */
38
39/* we start with no entries in any list */
40static irq_node_t *hp300_irq_list[HP300_NUM_IRQS];
41
42static spinlock_t irqlist_lock;
43
44/* This handler receives all interrupts, dispatching them to the registered handlers */
45static irqreturn_t hp300_int_handler(int irq, void *dev_id, struct pt_regs *fp)
46{
47 irq_node_t *t;
48 /* We just give every handler on the chain an opportunity to handle
49 * the interrupt, in priority order.
50 */
51 for(t = hp300_irq_list[irq]; t; t=t->next)
52 t->handler(irq, t->dev_id, fp);
53 /* We could put in some accounting routines, checks for stray interrupts,
54 * etc, in here. Note that currently we can't tell whether or not
55 * a handler handles the interrupt, though.
56 */
57 return IRQ_HANDLED;
58}
59
60static irqreturn_t hp300_badint(int irq, void *dev_id, struct pt_regs *fp)
61{
62 num_spurious += 1;
63 return IRQ_NONE;
64}
65
66irqreturn_t (*hp300_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
67 [0] = hp300_badint,
68 [1] = hp300_int_handler,
69 [2] = hp300_int_handler,
70 [3] = hp300_int_handler,
71 [4] = hp300_int_handler,
72 [5] = hp300_int_handler,
73 [6] = hp300_int_handler,
74 [7] = hp300_int_handler
75};
76
77/* dev_id had better be unique to each handler because it's the only way we have
78 * to distinguish handlers when removing them...
79 *
80 * It would be pretty easy to support IRQ_FLG_LOCK (handler is not replacable)
81 * and IRQ_FLG_REPLACE (handler replaces existing one with this dev_id)
82 * if we wanted to. IRQ_FLG_FAST is needed for devices where interrupt latency
83 * matters (eg the dreaded FIFOless UART...)
84 */
85int hp300_request_irq(unsigned int irq,
86 irqreturn_t (*handler) (int, void *, struct pt_regs *),
87 unsigned long flags, const char *devname, void *dev_id)
88{
89 irq_node_t *t, *n = new_irq_node();
90
91 if (!n) /* oops, no free nodes */
92 return -ENOMEM;
93
94 spin_lock_irqsave(&irqlist_lock, flags);
95
96 if (!hp300_irq_list[irq]) {
97 /* no list yet */
98 hp300_irq_list[irq] = n;
99 n->next = NULL;
100 } else if (flags & IRQ_FLG_FAST) {
101 /* insert at head of list */
102 n->next = hp300_irq_list[irq];
103 hp300_irq_list[irq] = n;
104 } else {
105 /* insert at end of list */
106 for(t = hp300_irq_list[irq]; t->next; t = t->next)
107 /* do nothing */;
108 n->next = NULL;
109 t->next = n;
110 }
111
112 /* Fill in n appropriately */
113 n->handler = handler;
114 n->flags = flags;
115 n->dev_id = dev_id;
116 n->devname = devname;
117 spin_unlock_irqrestore(&irqlist_lock, flags);
118 return 0;
119}
120
121void hp300_free_irq(unsigned int irq, void *dev_id)
122{
123 irq_node_t *t;
124 unsigned long flags;
125
126 spin_lock_irqsave(&irqlist_lock, flags);
127
128 t = hp300_irq_list[irq];
129 if (!t) /* no handlers at all for that IRQ */
130 {
131 printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq);
132 spin_unlock_irqrestore(&irqlist_lock, flags);
133 return;
134 }
135
136 if (t->dev_id == dev_id)
137 { /* removing first handler on chain */
138 t->flags = IRQ_FLG_STD; /* we probably don't really need these */
139 t->dev_id = NULL;
140 t->devname = NULL;
141 t->handler = NULL; /* frees this irq_node_t */
142 hp300_irq_list[irq] = t->next;
143 spin_unlock_irqrestore(&irqlist_lock, flags);
144 return;
145 }
146
147 /* OK, must be removing from middle of the chain */
148
149 for (t = hp300_irq_list[irq]; t->next && t->next->dev_id != dev_id; t = t->next)
150 /* do nothing */;
151 if (!t->next)
152 {
153 printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq);
154 spin_unlock_irqrestore(&irqlist_lock, flags);
155 return;
156 }
157 /* remove the entry after t: */
158 t->next->flags = IRQ_FLG_STD;
159 t->next->dev_id = NULL;
160 t->next->devname = NULL;
161 t->next->handler = NULL;
162 t->next = t->next->next;
163
164 spin_unlock_irqrestore(&irqlist_lock, flags);
165}
166
167int show_hp300_interrupts(struct seq_file *p, void *v)
168{
169 return 0;
170}
171
172void __init hp300_init_IRQ(void)
173{
174 spin_lock_init(&irqlist_lock);
175}
diff --git a/arch/m68k/hp300/ints.h b/arch/m68k/hp300/ints.h
new file mode 100644
index 000000000000..8cfabe2f3840
--- /dev/null
+++ b/arch/m68k/hp300/ints.h
@@ -0,0 +1,9 @@
1extern void hp300_init_IRQ(void);
2extern void (*hp300_handlers[8])(int, void *, struct pt_regs *);
3extern void hp300_free_irq(unsigned int irq, void *dev_id);
4extern int hp300_request_irq(unsigned int irq,
5 irqreturn_t (*handler) (int, void *, struct pt_regs *),
6 unsigned long flags, const char *devname, void *dev_id);
7
8/* number of interrupts, includes 0 (what's that?) */
9#define HP300_NUM_IRQS 8
diff --git a/arch/m68k/hp300/ksyms.c b/arch/m68k/hp300/ksyms.c
new file mode 100644
index 000000000000..8202830763d1
--- /dev/null
+++ b/arch/m68k/hp300/ksyms.c
@@ -0,0 +1,9 @@
1/*
2 * linux/arch/m68k/hp300/ksyms.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific kernel symbols. None yet. :-)
7 */
8
9#include <linux/module.h>
diff --git a/arch/m68k/hp300/reboot.S b/arch/m68k/hp300/reboot.S
new file mode 100644
index 000000000000..52eb852e6b04
--- /dev/null
+++ b/arch/m68k/hp300/reboot.S
@@ -0,0 +1,16 @@
1/*
2 * linux/arch/m68k/hp300/reboot.S
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * Do the dirty work of rebooting the machine. Basically we need to undo all the
7 * good stuff that head.S did when we started up. The caches and MMU must be
8 * disabled and then we jump back to the PROM. This is a bit gruesome but we put
9 * a brave face on it.
10 */
11
12/* XXX Doesn't work yet. Not sure why and can't be bothered to fix it at the moment. */
13
14 .globl hp300_reset
15hp300_reset:
16 jmp hp300_reset
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
new file mode 100644
index 000000000000..8da5b1b31e61
--- /dev/null
+++ b/arch/m68k/hp300/time.c
@@ -0,0 +1,78 @@
1/*
2 * linux/arch/m68k/hp300/time.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific time handling code.
7 */
8
9#include <asm/ptrace.h>
10#include <linux/types.h>
11#include <linux/init.h>
12#include <linux/sched.h>
13#include <linux/kernel_stat.h>
14#include <linux/interrupt.h>
15#include <asm/machdep.h>
16#include <asm/irq.h>
17#include <asm/io.h>
18#include <asm/system.h>
19#include <asm/traps.h>
20#include <asm/blinken.h>
21#include "ints.h"
22
23/* Clock hardware definitions */
24
25#define CLOCKBASE 0xf05f8000
26
27#define CLKCR1 0x1
28#define CLKCR2 0x3
29#define CLKCR3 CLKCR1
30#define CLKSR CLKCR2
31#define CLKMSB1 0x5
32#define CLKMSB2 0x9
33#define CLKMSB3 0xD
34
35/* This is for machines which generate the exact clock. */
36#define USECS_PER_JIFFY (1000000/HZ)
37
38#define INTVAL ((10000 / 4) - 1)
39
40static irqreturn_t hp300_tick(int irq, void *dev_id, struct pt_regs *regs)
41{
42 unsigned long tmp;
43 irqreturn_t (*vector)(int, void *, struct pt_regs *) = dev_id;
44 in_8(CLOCKBASE + CLKSR);
45 asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE));
46 /* Turn off the network and SCSI leds */
47 blinken_leds(0, 0xe0);
48 return vector(irq, NULL, regs);
49}
50
51unsigned long hp300_gettimeoffset(void)
52{
53 /* Read current timer 1 value */
54 unsigned char lsb, msb1, msb2;
55 unsigned short ticks;
56
57 msb1 = in_8(CLOCKBASE + 5);
58 lsb = in_8(CLOCKBASE + 7);
59 msb2 = in_8(CLOCKBASE + 5);
60 if (msb1 != msb2)
61 /* A carry happened while we were reading. Read it again */
62 lsb = in_8(CLOCKBASE + 7);
63 ticks = INTVAL - ((msb2 << 8) | lsb);
64 return (USECS_PER_JIFFY * ticks) / INTVAL;
65}
66
67void __init hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
68{
69 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */
70 out_8(CLOCKBASE + CLKCR1, 0x1); /* reset */
71
72 asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
73
74 cpu_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
75
76 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */
77 out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */
78}
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
new file mode 100644
index 000000000000..8ef9987b49ab
--- /dev/null
+++ b/arch/m68k/hp300/time.h
@@ -0,0 +1,4 @@
1extern void hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *));
2extern unsigned long hp300_gettimeoffset (void);
3
4
diff --git a/arch/m68k/ifpsp060/CHANGES b/arch/m68k/ifpsp060/CHANGES
new file mode 100644
index 000000000000..c1e712dfc2e7
--- /dev/null
+++ b/arch/m68k/ifpsp060/CHANGES
@@ -0,0 +1,120 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29
30CHANGES SINCE LAST RELEASE:
31---------------------------
32
331) "movep" emulation where data was being read from memory
34was reading the intermediate bytes. Emulation now only
35reads the required bytes.
36
372) "flogn", "flog2", and "flog10" of "1" was setting the
38Inexact FPSR bit. Emulation now does not set Inexact for
39this case.
40
413) For an opclass three FP instruction where the effective addressing
42mode was pre-decrement or post-increment and the address register
43was A0 or A1, the address register was not being updated as a result
44of the operation. This has been corrected.
45
464) Beta B.2 version had the following erratum:
47
48 Scenario:
49 ---------
50 If {i,d}mem_{read,write}_{byte,word,long}() returns
51 a failing value to the 68060SP, the package ignores
52 this return value and continues with program execution
53 as if it never received a failing value.
54
55 Effect:
56 -------
57 For example, if a user executed "fsin.x ADDR,fp0" where
58 ADDR should cause a "segmentation violation", the memory read
59 requested by the package should return a failing value
60 to the package. Since the package currently ignores this
61 return value, the user program will continue to the
62 next instruction, and the result created in fp0 will be
63 undefined.
64
65 Fix:
66 ----
67 This has been fixed in the current release.
68
69 Notes:
70 ------
71 Upon receiving a non-zero (failing) return value from
72 a {i,d}mem_{read,write}_{byte,word,long}() "call-out",
73 the package creates a 16-byte access error stack frame
74 from the current exception stack frame and exits
75 through the "call-out" _real_access(). This is the process
76 as described in the MC68060 User's Manual.
77
78 For instruction read access errors, the info stacked is:
79 SR = SR at time of exception
80 PC = PC of instruction being emulated
81 VOFF = $4008 (stack frame format type)
82 ADDRESS = PC of instruction being emulated
83 FSLW = FAULT STATUS LONGWORD
84
85 The valid FSLW bits are:
86 bit 27 = 1 (misaligned bit)
87 bit 24 = 1 (read)
88 bit 23 = 0 (write)
89 bit 22:21 = 10 (SIZE = word)
90 bit 20:19 = 00 (TT)
91 bit 18:16 = x10 (TM; x = 1 for supervisor mode)
92 bit 15 = 1 (IO)
93 bit 0 = 1 (Software Emulation Error)
94
95 all other bits are EQUAL TO ZERO and can be set by the _real_access()
96 "call-out" stub by the user as appropriate. The MC68060 User's Manual
97 stated that ONLY "bit 0" would be set. The 060SP attempts to set a few
98 other bits.
99
100 For data read/write access errors, the info stacked is:
101 SR = SR at time of exception
102 PC = PC of instruction being emulated
103 VOFF = $4008 (stack frame format type)
104 ADDRESS = Address of source or destination operand
105 FSLW = FAULT STATUS LONGWORD
106
107 The valid FSLW bits are:
108 bit 27 = 0 (misaligned bit)
109 bit 24 = x (read; 1 if read, 0 if write)
110 bit 23 = x (write; 1 if write, 0 if read)
111 bit 22:21 = xx (SIZE; see MC68060 User's Manual)
112 bit 20:19 = 00 (TT)
113 bit 18:16 = x01 (TM; x = 1 for supervisor mode)
114 bit 15 = 0 (IO)
115 bit 0 = 1 (Software Emulation Error)
116
117 all other bits are EQUAL TO ZERO and can be set by the _real_access()
118 "call-out" stub by the user as appropriate. The MC68060 User's Manual
119 stated that ONLY "bit 0" would be set. The 060SP attempts to set a few
120 other bits.
diff --git a/arch/m68k/ifpsp060/MISC b/arch/m68k/ifpsp060/MISC
new file mode 100644
index 000000000000..b7e644b94ae2
--- /dev/null
+++ b/arch/m68k/ifpsp060/MISC
@@ -0,0 +1,201 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29RELEASE FILE VERSIONS:
30-----------------------
31
32fpsp.sa
33----------
34freal.s : 2.4
35hdr.fpu : 2.4
36x_fovfl.s : 2.16
37x_funfl.s : 2.19
38x_funsupp.s : 2.27
39x_effadd.s : 2.21
40x_foperr.s : 2.9
41x_fsnan.s : 2.12
42x_finex.s : 2.14
43x_fdz.s : 2.5
44x_fline.s : 2.5
45x_funimp.s : 2.27
46fsin.s : 2.6
47ftan.s : 2.6
48fatan.s : 2.3
49fasin.s : 2.3
50facos.s : 2.5
51fetox.s : 2.4
52fgetem.s : 2.5
53fcosh.s : 2.4
54fsinh.s : 2.5
55ftanh.s : 2.3
56flogn.s : 2.6
57fatanh.s : 2.4
58flog2.s : 2.4
59ftwotox.s : 2.4
60fmovecr.s : 2.5
61fscale.s : 2.5
62frem_mod.s : 2.6
63fkern.s : 2.6
64fkern2.s : 2.5
65fgen_except.s: 2.7
66foptbl.s : 2.3
67fmul.s : 2.5
68fin.s : 2.4
69fdiv.s : 2.5
70fneg.s : 2.4
71ftst.s : 2.3
72fint.s : 2.3
73fintrz.s : 2.3
74fabs.s : 2.4
75fcmp.s : 2.4
76fsglmul.s : 2.5
77fsgldiv.s : 2.8
78fadd.s : 2.6
79fsub.s : 2.6
80fsqrt.s : 2.4
81fmisc.s : 2.3
82fdbcc.s : 2.8
83ftrapcc.s : 2.5
84fscc.s : 2.6
85fmovm.s : 2.15
86fctrl.s : 2.6
87fcalc_ea.s : 2.7
88fmem.s : 2.9
89fout.s : 2.9
90ireg.s : 2.6
91fdenorm.s : 2.3
92fround.s : 2.4
93fnorm.s : 2.3
94foptag_set.s: 2.4
95fresult.s : 2.3
96fpack.s : 2.6
97fdecbin.s : 2.4
98fbindec.s : 2.5
99fbinstr.s : 2.3
100faccess.s : 2.3
101
102pfpsp.sa
103----------
104freal.s : 2.4
105hdr.fpu : 2.4
106x_fovfl.s : 2.16
107x_funfl.s : 2.19
108x_funsupp.s : 2.27
109x_effadd.s : 2.21
110x_foperr.s : 2.9
111x_fsnan.s : 2.12
112x_finex.s : 2.14
113x_fdz.s : 2.5
114x_fline2.s : 2.3
115fcalc_ea.s : 2.7
116foptbl2.s : 2.4
117fmovm.s : 2.15
118fctrl.s : 2.6
119fmisc.s : 2.3
120fdenorm.s : 2.3
121fround.s : 2.4
122fnorm.s : 2.3
123foptag_set.s: 2.4
124fresult.s : 2.3
125fout.s : 2.9
126fmul.s : 2.5
127fin.s : 2.4
128fdiv.s : 2.5
129fneg.s : 2.4
130ftst.s : 2.3
131fint.s : 2.3
132fintrz.s : 2.3
133fabs.s : 2.4
134fcmp.s : 2.4
135fsglmul.s : 2.5
136fsgldiv.s : 2.8
137fadd.s : 2.6
138fsub.s : 2.6
139fsqrt.s : 2.4
140ireg.s : 2.6
141fpack.s : 2.6
142fdecbin.s : 2.4
143fbindec.s : 2.5
144fbinstr.s : 2.3
145faccess.s : 2.3
146
147fplsp.sa
148----------
149lfptop.s : 2.3
150hdr.fpu : 2.4
151fsin.s : 2.6
152ftan.s : 2.6
153fatan.s : 2.3
154fasin.s : 2.3
155facos.s : 2.5
156fetox.s : 2.4
157fgetem.s : 2.5
158fcosh.s : 2.4
159fsinh.s : 2.5
160ftanh.s : 2.3
161flogn.s : 2.6
162fatanh.s : 2.4
163flog2.s : 2.4
164ftwotox.s : 2.4
165fscale.s : 2.5
166frem_mod.s : 2.6
167l_support.s : 2.15
168fnorm.s : 2.3
169
170isp.sa
171----------
172ireal.s : 2.4
173hdr.int : 2.4
174x_uieh.s : 2.13
175icalc_ea.s : 2.11
176imovep.s : 2.8
177ichk2cmp2.s : 2.6
178idiv64.s : 2.10
179imul64.s :
180icas2.s : 2.11
181icas.s : 2.12
182icas2_core.s: 2.6
183icas_core.s : 2.6
184
185ilsp.sa
186----------
187litop.s : 2.2
188l_idiv64.s : 2.8
189l_imul64.s : 2.6
190l_ichk2cmp2.s: 2.5
191
192ex. files
193----------
194wrk/fskeleton.s: 2.2
195wrk/iskeleton.s: 2.2
196wrk/os.s : 2.1
197
198tests
199----------
200itest.s : 2.2
201ftest.s : 2.1
diff --git a/arch/m68k/ifpsp060/Makefile b/arch/m68k/ifpsp060/Makefile
new file mode 100644
index 000000000000..2fe8472cb5e3
--- /dev/null
+++ b/arch/m68k/ifpsp060/Makefile
@@ -0,0 +1,10 @@
1# Makefile for 680x0 Linux 68060 integer/floating point support package
2#
3# This file is subject to the terms and conditions of the GNU General Public
4# License. See the file "README.legal" in the main directory of this archive
5# for more details.
6
7obj-y := fskeleton.o iskeleton.o os.o
8
9EXTRA_AFLAGS := -traditional
10EXTRA_LDFLAGS := -x
diff --git a/arch/m68k/ifpsp060/README b/arch/m68k/ifpsp060/README
new file mode 100644
index 000000000000..e3bced429bd3
--- /dev/null
+++ b/arch/m68k/ifpsp060/README
@@ -0,0 +1,71 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29Files in this directory:
30-------------------------
31
32fpsp.sa Full FP Kernel Module - hex image
33fpsp.s Full FP Kernel Module - source code
34fpsp.doc Full FP Kernel Module - on-line documentation
35
36pfpsp.sa Partial FP Kernel Module - hex image
37pfpsp.s Partial FP Kernel Module - source code
38
39fplsp.sa FP Library Module - hex image
40fplsp.s FP Library Module - source code
41fplsp.doc FP Library Module - on-line documentation
42
43isp.sa Integer Unimplemented Kernel Module - hex image
44isp.s Integer Unimplemented Kernel Module - source code
45isp.doc Integer Unimplemented Kernel Module - on-line doc
46
47ilsp.sa Integer Unimplemented Library Module - hex image
48ilsp.s Integer Unimplemented Library Module - source code
49ilsp.doc Integer Unimplemented Library Module - on-line doc
50
51fskeleton.s Sample Call-outs needed by fpsp.sa and pfpsp.sa
52
53iskeleton.s Sample Call-outs needed by isp.sa
54
55os.s Sample Call-outs needed by fpsp.sa, pfpsp.sa, and isp.sa
56
57ftest.sa Simple test program to test that {p}fpsp.sa
58 was connected properly; hex image
59ftest.s above test; source code
60
61itest.sa Simple test program to test that isp.sa was
62 connected properly; hex image
63itest.s above test; source code
64
65test.doc on-line documentation for {i,f}test.sa
66
67README This file
68
69ERRATA Known errata for this release
70
71MISC Release file version numbers
diff --git a/arch/m68k/ifpsp060/TEST.DOC b/arch/m68k/ifpsp060/TEST.DOC
new file mode 100644
index 000000000000..5e5900cb2dc4
--- /dev/null
+++ b/arch/m68k/ifpsp060/TEST.DOC
@@ -0,0 +1,208 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2968060 SOFTWARE PACKAGE (Kernel version) SIMPLE TESTS
30-----------------------------------------------------
31
32The files itest.sa and ftest.sa contain simple tests to check
33the state of the 68060ISP and 68060FPSP once they have been installed.
34
35Release file format:
36--------------------
37The release files itest.sa and ftest.sa are essentially
38hexadecimal images of the actual tests. This format is the
39ONLY format that will be supported. The hex images were created
40by assembling the source code and then converting the resulting
41binary output images into ASCII text files. The hexadecimal
42numbers are listed using the Motorola Assembly syntax assembler
43directive "dc.l" (define constant longword). The files can be
44converted to other assembly syntaxes by using any word processor
45with a global search and replace function.
46
47To assist in assembling and linking these modules with other modules,
48the installer should add symbolic labels to the top of the files.
49This will allow the calling routines to access the entry points
50of these packages.
51
52The source code itest.s and ftest.s have been included but only
53for documentation purposes.
54
55Release file structure:
56-----------------------
57
58(top of module)
59 -----------------
60 | | - 128 byte-sized section
61 (1) | Call-Out | - 4 bytes per entry (user fills these in)
62 | |
63 -----------------
64 | | - 8 bytes per entry
65 (2) | Entry Point | - user does "bsr" or "jsr" to this address
66 | |
67 -----------------
68 | | - code section
69 (3) ~ ~
70 | |
71 -----------------
72(bottom of module)
73
74The first section of this module is the "Call-out" section. This section
75is NOT INCLUDED in {i,f}test.sa (an example "Call-out" section is provided at
76the end of this file). The purpose of this section is to allow the test
77routines to reference external printing functions that must be provided
78by the host operating system. This section MUST be exactly 128 bytes in
79size. There are 32 fields, each 4 bytes in size. Each field corresponds
80to a function required by the test packages (these functions and their
81location are listed in "68060{ISP,FPSP}-TEST call-outs" below). Each field
82entry should contain the address of the corresponding function RELATIVE to
83the starting address of the "call-out" section. The "Call-out" section must
84sit adjacent to the {i,f}test.sa image in memory. Since itest.sa and ftest.sa
85are individual tests, they each require their own "Call-out" sections.
86
87The second section, the "Entry-point" section, is used by external routines
88to access the test routines. Since the {i,f}test.sa hex files contain
89no symbol names, this section contains function entry points that are fixed
90with respect to the top of the package. The currently defined entry-points
91are listed in section "68060{ISP,FPSP}-TEST entry points" below. A calling
92routine would simply execute a "bsr" or "jsr" that jumped to the selected
93function entry-point.
94
95For example, to run the 060ISP test, write a program that includes the
96itest.sa data and execute something similar to:
97
98 bsr _060ISP_TEST+128+0
99
100(_060ISP_TEST is the starting address of the "Call-out" section; the "Call-out"
101section is 128 bytes long; and the 68060ISP test entry point is located
1020 bytes from the top of the "Entry-point" section.)
103
104The third section is the code section. After entering through an "Entry-point",
105the entry code jumps to the appropriate test code within the code section.
106
10768060ISP-TEST Call-outs:
108------------------------
1090x0: _print_string()
1100x4: _print_number()
111
11268060FPSP-TEST Call-outs:
113-------------------------
1140x0: _print_string()
1150x4: _print_number()
116
117The test packages call _print_string() and _print_number()
118as subroutines and expect the main program to print a string
119or a number to a file or to the screen.
120In "C"-like fashion, the test program calls:
121
122 print_string("Test passed");
123
124 or
125
126 print_number(20);
127
128For _print_string(), the test programs pass a longword address
129of the string on the stack. For _print_number(), the test programs pass
130a longword number to be printed.
131
132For debugging purposes, after the main program performs a "print"
133for a test package, it should flush the output so that it's not
134buffered. In this way, if the test program crashes, at least the previous
135statements printed will be seen.
136
13768060ISP-TEST Entry-points:
138---------------------------
1390x0: integer test
140
14168060FPSP-TEST Entry-points:
142----------------------------
1430x00: main fp test
1440x08: FP unimplemented test
1450x10: FP enabled snan/operr/ovfl/unfl/dz/inex
146
147The floating-point unit test has 3 entry points which will require
1483 different calls to the package if each of the three following tests
149is desired:
150
151main fp test: tests (1) unimp effective address exception
152 (2) unsupported data type exceptions
153 (3) non-maskable overflow/underflow exceptions
154
155FP unimplemented: tests FP unimplemented exception. this one is
156 separate from the previous tests for systems that don't
157 want FP unimplemented instructions.
158
159FP enabled: tests enabled snan/operr/ovfl/unfl/dz/inex.
160 basically, it enables each of these exceptions and forces
161 each using an implemented FP instruction. this process
162 exercises _fpsp_{snan,operr,ovfl,unfl,dz,inex}() and
163 _real_{snan,operr,ovfl,unfl,dz,inex}(). the test expects
164 _real_XXXX() to do nothing except clear the exception
165 and "rte". if a system's _real_XXXX() handler creates an
166 alternate result, the test will print "failed" but this
167 is acceptable.
168
169Miscellaneous:
170--------------
171Again, itest.sa and ftest.sa are simple tests and do not thoroughly
172test all 68060SP connections. For example, they do not test connections
173to _real_access(), _real_trace(), _real_trap(), etc. because these
174will be system-implemented several different ways and the test packages
175must remain system independent.
176
177Example test package set-up:
178----------------------------
179_print_str:
180 . # provided by system
181 rts
182
183_print_num:
184 . # provided by system
185 rts
186
187 .
188 .
189 bsr _060FPSP_TEST+128+0
190 .
191 .
192 rts
193
194# beginning of "Call-out" section; provided by integrator.
195# MUST be 128 bytes long.
196_060FPSP_TEST:
197 long _print_str - _060FPSP_TEST
198 long _print_num - _060FPSP_TEST
199 space 120
200
201# ftest.sa starts here; start of "Entry-point" section.
202 long 0x60ff0000, 0x00002346
203 long 0x60ff0000, 0x00018766
204 long 0x60ff0000, 0x00023338
205 long 0x24377299, 0xab2643ea
206 .
207 .
208 .
diff --git a/arch/m68k/ifpsp060/fplsp.doc b/arch/m68k/ifpsp060/fplsp.doc
new file mode 100644
index 000000000000..fb637c436762
--- /dev/null
+++ b/arch/m68k/ifpsp060/fplsp.doc
@@ -0,0 +1,231 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29
3068060 FLOATING-POINT SOFTWARE PACKAGE (Library version)
31--------------------------------------------------------
32
33The file fplsp.sa contains the "Library version" of the
3468060SP Floating-Point Software Package. The routines
35included in this module can be used to emulate the
36FP instructions not implemented in 68060 hardware. These
37instructions normally take exception vector #11
38"FP Unimplemented Instruction".
39
40By re-compiling a program that uses these instructions, and
41making subroutine calls in place of the unimplemented
42instructions, a program can avoid the overhead associated
43with taking the exception.
44
45Release file format:
46--------------------
47The file fplsp.sa is essentially a hexadecimal image of the
48release package. This is the ONLY format which will be supported.
49The hex image was created by assembling the source code and
50then converting the resulting binary output image into an
51ASCII text file. The hexadecimal numbers are listed
52using the Motorola Assembly Syntax assembler directive "dc.l"
53(define constant longword). The file can be converted to other
54assembly syntaxes by using any word processor with a global
55search and replace function.
56
57To assist in assembling and linking this module with other modules,
58the installer should add a symbolic label to the top of the file.
59This will allow calling routines to access the entry points
60of this package.
61
62The source code fplsp.s has also been included but only for
63documentation purposes.
64
65Release file structure:
66-----------------------
67The file fplsp.sa contains an "Entry-Point" section and a
68code section. The FPLSP has no "Call-Out" section. The first section
69is the "Entry-Point" section. In order to access a function in the
70package, a program must "bsr" or "jsr" to the location listed
71below in "68060FPLSP entry points" that corresponds to the desired
72function. A branch instruction located at the selected entry point
73within the package will then enter the correct emulation code routine.
74
75The entry point addresses at the beginning of the package will remain
76fixed so that a program calling the routines will not have to be
77re-compiled with every new 68060FPLSP release.
78
79There are 3 entry-points for each instruction type: single precision,
80double precision, and extended precision.
81
82As an example, the "fsin" library instruction can be passed an
83extended precision operand if program executes:
84
85# fsin.x fp0
86
87 fmovm.x &0x01,-(%sp) # pass operand on stack
88 bsr.l _060FPLSP_TOP+0x1a8 # branch to fsin routine
89 add.l &0xc,%sp # clear operand from stack
90
91Upon return, fp0 holds the correct result. The FPSR is
92set correctly. The FPCR is unchanged. The FPIAR is undefined.
93
94Another example. This time, a dyadic operation:
95
96# frem.s %fp1,%fp0
97
98 fmov.s %fp1,-(%sp) # pass src operand
99 fmov.s %fp0,-(%sp) # pass dst operand
100 bsr.l _060FPLSP_TOP+0x168 # branch to frem routine
101 addq.l &0x8,%sp # clear operands from stack
102
103Again, the result is returned in fp0. Note that BOTH operands
104are passed in single precision format.
105
106Exception reporting:
107--------------------
108The package takes exceptions according to the FPCR value upon subroutine
109entry. If an exception should be reported, then the package forces
110this exception using implemented floating-point instructions.
111For example, if the instruction being emulated should cause a
112floating-point Operand Error exception, then the library routine
113executes an FMUL of a zero and an infinity to force the OPERR
114exception. Although the FPIAR will be undefined for the enabled
115Operand Error exception handler, the user will at least be able
116to record that the event occurred.
117
118Miscellaneous:
119--------------
120The package does not attempt to correctly emulate instructions
121with Signalling NAN inputs. Use of SNANs should be avoided with
122this package.
123
124The fabs/fadd/fdiv/fint/fintrz/fmul/fneg/fsqrt/fsub entry points
125are provided for the convenience of older compilers that make
126subroutine calls for all fp instructions. The code does NOT emulate
127the instruction but rather simply executes it.
128
12968060FPLSP entry points:
130------------------------
131_060FPLSP_TOP:
1320x000: _060LSP__facoss_
1330x008: _060LSP__facosd_
1340x010: _060LSP__facosx_
1350x018: _060LSP__fasins_
1360x020: _060LSP__fasind_
1370x028: _060LSP__fasinx_
1380x030: _060LSP__fatans_
1390x038: _060LSP__fatand_
1400x040: _060LSP__fatanx_
1410x048: _060LSP__fatanhs_
1420x050: _060LSP__fatanhd_
1430x058: _060LSP__fatanhx_
1440x060: _060LSP__fcoss_
1450x068: _060LSP__fcosd_
1460x070: _060LSP__fcosx_
1470x078: _060LSP__fcoshs_
1480x080: _060LSP__fcoshd_
1490x088: _060LSP__fcoshx_
1500x090: _060LSP__fetoxs_
1510x098: _060LSP__fetoxd_
1520x0a0: _060LSP__fetoxx_
1530x0a8: _060LSP__fetoxm1s_
1540x0b0: _060LSP__fetoxm1d_
1550x0b8: _060LSP__fetoxm1x_
1560x0c0: _060LSP__fgetexps_
1570x0c8: _060LSP__fgetexpd_
1580x0d0: _060LSP__fgetexpx_
1590x0d8: _060LSP__fgetmans_
1600x0e0: _060LSP__fgetmand_
1610x0e8: _060LSP__fgetmanx_
1620x0f0: _060LSP__flog10s_
1630x0f8: _060LSP__flog10d_
1640x100: _060LSP__flog10x_
1650x108: _060LSP__flog2s_
1660x110: _060LSP__flog2d_
1670x118: _060LSP__flog2x_
1680x120: _060LSP__flogns_
1690x128: _060LSP__flognd_
1700x130: _060LSP__flognx_
1710x138: _060LSP__flognp1s_
1720x140: _060LSP__flognp1d_
1730x148: _060LSP__flognp1x_
1740x150: _060LSP__fmods_
1750x158: _060LSP__fmodd_
1760x160: _060LSP__fmodx_
1770x168: _060LSP__frems_
1780x170: _060LSP__fremd_
1790x178: _060LSP__fremx_
1800x180: _060LSP__fscales_
1810x188: _060LSP__fscaled_
1820x190: _060LSP__fscalex_
1830x198: _060LSP__fsins_
1840x1a0: _060LSP__fsind_
1850x1a8: _060LSP__fsinx_
1860x1b0: _060LSP__fsincoss_
1870x1b8: _060LSP__fsincosd_
1880x1c0: _060LSP__fsincosx_
1890x1c8: _060LSP__fsinhs_
1900x1d0: _060LSP__fsinhd_
1910x1d8: _060LSP__fsinhx_
1920x1e0: _060LSP__ftans_
1930x1e8: _060LSP__ftand_
1940x1f0: _060LSP__ftanx_
1950x1f8: _060LSP__ftanhs_
1960x200: _060LSP__ftanhd_
1970x208: _060LSP__ftanhx_
1980x210: _060LSP__ftentoxs_
1990x218: _060LSP__ftentoxd_
2000x220: _060LSP__ftentoxx_
2010x228: _060LSP__ftwotoxs_
2020x230: _060LSP__ftwotoxd_
2030x238: _060LSP__ftwotoxx_
204
2050x240: _060LSP__fabss_
2060x248: _060LSP__fabsd_
2070x250: _060LSP__fabsx_
2080x258: _060LSP__fadds_
2090x260: _060LSP__faddd_
2100x268: _060LSP__faddx_
2110x270: _060LSP__fdivs_
2120x278: _060LSP__fdivd_
2130x280: _060LSP__fdivx_
2140x288: _060LSP__fints_
2150x290: _060LSP__fintd_
2160x298: _060LSP__fintx_
2170x2a0: _060LSP__fintrzs_
2180x2a8: _060LSP__fintrzd_
2190x2b0: _060LSP__fintrzx_
2200x2b8: _060LSP__fmuls_
2210x2c0: _060LSP__fmuld_
2220x2c8: _060LSP__fmulx_
2230x2d0: _060LSP__fnegs_
2240x2d8: _060LSP__fnegd_
2250x2e0: _060LSP__fnegx_
2260x2e8: _060LSP__fsqrts_
2270x2f0: _060LSP__fsqrtd_
2280x2f8: _060LSP__fsqrtx_
2290x300: _060LSP__fsubs_
2300x308: _060LSP__fsubd_
2310x310: _060LSP__fsubx_
diff --git a/arch/m68k/ifpsp060/fplsp.sa b/arch/m68k/ifpsp060/fplsp.sa
new file mode 100644
index 000000000000..8826df0329e6
--- /dev/null
+++ b/arch/m68k/ifpsp060/fplsp.sa
@@ -0,0 +1,1946 @@
1 dc.l $60ff0000,$238e0000,$60ff0000,$24200000
2 dc.l $60ff0000,$24b60000,$60ff0000,$11060000
3 dc.l $60ff0000,$11980000,$60ff0000,$122e0000
4 dc.l $60ff0000,$0f160000,$60ff0000,$0fa80000
5 dc.l $60ff0000,$103e0000,$60ff0000,$12ae0000
6 dc.l $60ff0000,$13400000,$60ff0000,$13d60000
7 dc.l $60ff0000,$05ae0000,$60ff0000,$06400000
8 dc.l $60ff0000,$06d60000,$60ff0000,$213e0000
9 dc.l $60ff0000,$21d00000,$60ff0000,$22660000
10 dc.l $60ff0000,$16160000,$60ff0000,$16a80000
11 dc.l $60ff0000,$173e0000,$60ff0000,$0aee0000
12 dc.l $60ff0000,$0b800000,$60ff0000,$0c160000
13 dc.l $60ff0000,$24a60000,$60ff0000,$25380000
14 dc.l $60ff0000,$25ce0000,$60ff0000,$26660000
15 dc.l $60ff0000,$26f80000,$60ff0000,$278e0000
16 dc.l $60ff0000,$1d160000,$60ff0000,$1da80000
17 dc.l $60ff0000,$1e3e0000,$60ff0000,$1ed60000
18 dc.l $60ff0000,$1f680000,$60ff0000,$1ffe0000
19 dc.l $60ff0000,$1b0e0000,$60ff0000,$1ba00000
20 dc.l $60ff0000,$1c360000,$60ff0000,$08860000
21 dc.l $60ff0000,$09180000,$60ff0000,$09ae0000
22 dc.l $60ff0000,$2bf00000,$60ff0000,$2ca40000
23 dc.l $60ff0000,$2d580000,$60ff0000,$29980000
24 dc.l $60ff0000,$2a4c0000,$60ff0000,$2b000000
25 dc.l $60ff0000,$2e000000,$60ff0000,$2eb40000
26 dc.l $60ff0000,$2f680000,$60ff0000,$029e0000
27 dc.l $60ff0000,$03300000,$60ff0000,$03c60000
28 dc.l $60ff0000,$27660000,$60ff0000,$27fe0000
29 dc.l $60ff0000,$289a0000,$60ff0000,$061e0000
30 dc.l $60ff0000,$06b00000,$60ff0000,$07460000
31 dc.l $60ff0000,$12ee0000,$60ff0000,$13800000
32 dc.l $60ff0000,$14160000,$60ff0000,$0b760000
33 dc.l $60ff0000,$0c080000,$60ff0000,$0c9e0000
34 dc.l $60ff0000,$18460000,$60ff0000,$18d80000
35 dc.l $60ff0000,$196e0000,$60ff0000,$16560000
36 dc.l $60ff0000,$16e80000,$60ff0000,$177e0000
37 dc.l $60ff0000,$72fe0000,$60ff0000,$72fe0000
38 dc.l $60ff0000,$72fe0000,$60ff0000,$71be0000
39 dc.l $60ff0000,$71d40000,$60ff0000,$71ea0000
40 dc.l $60ff0000,$72840000,$60ff0000,$729a0000
41 dc.l $60ff0000,$72b00000,$60ff0000,$72fe0000
42 dc.l $60ff0000,$72fe0000,$60ff0000,$72fe0000
43 dc.l $60ff0000,$72fe0000,$60ff0000,$72fe0000
44 dc.l $60ff0000,$72fe0000,$60ff0000,$71f20000
45 dc.l $60ff0000,$72080000,$60ff0000,$721e0000
46 dc.l $60ff0000,$72860000,$60ff0000,$72860000
47 dc.l $60ff0000,$72860000,$60ff0000,$72860000
48 dc.l $60ff0000,$72860000,$60ff0000,$72860000
49 dc.l $60ff0000,$71600000,$60ff0000,$71760000
50 dc.l $60ff0000,$718c0000,$51fc51fc,$51fc51fc
51 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
52 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
53 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
54 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
55 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
56 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
57 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
58 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
59 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
60 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
61 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
62 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
63 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
64 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
65 dc.l $40c62d38,$d3d64634,$3d6f90ae,$b1e75cc7
66 dc.l $40000000,$c90fdaa2,$2168c235,$00000000
67 dc.l $3fff0000,$c90fdaa2,$2168c235,$00000000
68 dc.l $3fe45f30,$6dc9c883,$4e56ff40,$48ee0303
69 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
70 dc.l $90000000,$0000f22e,$44000008,$f22e6800
71 dc.l $ff6c41ee,$ff6c61ff,$00006c76,$1d40ff4e
72 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
73 dc.l $4a016608,$61ff0000,$2ddc6030,$0c010001
74 dc.l $660861ff,$00007124,$60220c01,$00026608
75 dc.l $61ff0000,$6d226014,$0c010003,$660861ff
76 dc.l $00006f4c,$600661ff,$00002f8e,$4cee0303
77 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
78 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
79 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
80 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
81 dc.l $61ff0000,$6bdc1d40,$ff4e1200,$02ae00ff
82 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
83 dc.l $660861ff,$00002d3e,$60300c01,$00016608
84 dc.l $61ff0000,$70866022,$0c010002,$660861ff
85 dc.l $00006c84,$60140c01,$00036608,$61ff0000
86 dc.l $6eae6006,$61ff0000,$2ef04cee,$0303ff9c
87 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
88 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
89 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
90 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
91 dc.l $00100008,$61ff0000,$6b381d40,$ff4e1200
92 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
93 dc.l $660861ff,$00002c9e,$60300c01,$00016608
94 dc.l $61ff0000,$6fe66022,$0c010002,$660861ff
95 dc.l $00006be4,$60140c01,$00036608,$61ff0000
96 dc.l $6e0e6006,$61ff0000,$2e504cee,$0303ff9c
97 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
98 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
99 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
100 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
101 dc.l $00006a9e,$1d40ff4e,$120002ae,$00ff00ff
102 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
103 dc.l $2c0e6030,$0c010001,$660861ff,$00006fc8
104 dc.l $60220c01,$00026608,$61ff0000,$6b4a6014
105 dc.l $0c010003,$660861ff,$00006d74,$600661ff
106 dc.l $00002dbc,$4cee0303,$ff9cf22e,$9800ff60
107 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
108 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
109 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
110 dc.l $6800ff6c,$41eeff6c,$61ff0000,$6a041d40
111 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
112 dc.l $ff631d41,$ff4e4a01,$660861ff,$00002b70
113 dc.l $60300c01,$00016608,$61ff0000,$6f2a6022
114 dc.l $0c010002,$660861ff,$00006aac,$60140c01
115 dc.l $00036608,$61ff0000,$6cd66006,$61ff0000
116 dc.l $2d1e4cee,$0303ff9c,$f22e9800,$ff60f22e
117 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
118 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
119 dc.l $90000000,$000041ee,$ff6c216e,$00080000
120 dc.l $216e000c,$0004216e,$00100008,$61ff0000
121 dc.l $69601d40,$ff4e1200,$02ae00ff,$00ffff64
122 dc.l $4280102e,$ff634a01,$660861ff,$00002ad0
123 dc.l $60300c01,$00016608,$61ff0000,$6e8a6022
124 dc.l $0c010002,$660861ff,$00006a0c,$60140c01
125 dc.l $00036608,$61ff0000,$6c366006,$61ff0000
126 dc.l $2c7e4cee,$0303ff9c,$f22e9800,$ff60f22e
127 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
128 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
129 dc.l $90000000,$0000f22e,$44000008,$f22e6800
130 dc.l $ff6c41ee,$ff6c61ff,$000068c6,$1d40ff4e
131 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
132 dc.l $4a016608,$61ff0000,$4e686030,$0c010001
133 dc.l $660861ff,$00006d74,$60220c01,$00026608
134 dc.l $61ff0000,$6d946014,$0c010003,$660861ff
135 dc.l $00006b9c,$600661ff,$00004f14,$4cee0303
136 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
137 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
138 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
139 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
140 dc.l $61ff0000,$682c1d40,$ff4e1200,$02ae00ff
141 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
142 dc.l $660861ff,$00004dca,$60300c01,$00016608
143 dc.l $61ff0000,$6cd66022,$0c010002,$660861ff
144 dc.l $00006cf6,$60140c01,$00036608,$61ff0000
145 dc.l $6afe6006,$61ff0000,$4e764cee,$0303ff9c
146 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
147 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
148 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
149 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
150 dc.l $00100008,$61ff0000,$67881d40,$ff4e1200
151 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
152 dc.l $660861ff,$00004d2a,$60300c01,$00016608
153 dc.l $61ff0000,$6c366022,$0c010002,$660861ff
154 dc.l $00006c56,$60140c01,$00036608,$61ff0000
155 dc.l $6a5e6006,$61ff0000,$4dd64cee,$0303ff9c
156 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
157 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
158 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
159 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
160 dc.l $000066ee,$1d40ff4e,$120002ae,$00ff00ff
161 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
162 dc.l $59b26030,$0c010001,$660861ff,$00006b9c
163 dc.l $60220c01,$00026608,$61ff0000,$6bf26014
164 dc.l $0c010003,$660861ff,$000069c4,$600661ff
165 dc.l $00005ad4,$4cee0303,$ff9cf22e,$9800ff60
166 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
167 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
168 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
169 dc.l $6800ff6c,$41eeff6c,$61ff0000,$66541d40
170 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
171 dc.l $ff631d41,$ff4e4a01,$660861ff,$00005914
172 dc.l $60300c01,$00016608,$61ff0000,$6afe6022
173 dc.l $0c010002,$660861ff,$00006b54,$60140c01
174 dc.l $00036608,$61ff0000,$69266006,$61ff0000
175 dc.l $5a364cee,$0303ff9c,$f22e9800,$ff60f22e
176 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
177 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
178 dc.l $90000000,$000041ee,$ff6c216e,$00080000
179 dc.l $216e000c,$0004216e,$00100008,$61ff0000
180 dc.l $65b01d40,$ff4e1200,$02ae00ff,$00ffff64
181 dc.l $4280102e,$ff634a01,$660861ff,$00005874
182 dc.l $60300c01,$00016608,$61ff0000,$6a5e6022
183 dc.l $0c010002,$660861ff,$00006ab4,$60140c01
184 dc.l $00036608,$61ff0000,$68866006,$61ff0000
185 dc.l $59964cee,$0303ff9c,$f22e9800,$ff60f22e
186 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
187 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
188 dc.l $90000000,$0000f22e,$44000008,$f22e6800
189 dc.l $ff6c41ee,$ff6c61ff,$00006516,$1d40ff4e
190 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
191 dc.l $4a016608,$61ff0000,$46c46030,$0c010001
192 dc.l $660861ff,$000069c4,$60220c01,$00026608
193 dc.l $61ff0000,$6a246014,$0c010003,$660861ff
194 dc.l $000067ec,$600661ff,$00004948,$4cee0303
195 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
196 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
197 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
198 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
199 dc.l $61ff0000,$647c1d40,$ff4e1200,$02ae00ff
200 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
201 dc.l $660861ff,$00004626,$60300c01,$00016608
202 dc.l $61ff0000,$69266022,$0c010002,$660861ff
203 dc.l $00006986,$60140c01,$00036608,$61ff0000
204 dc.l $674e6006,$61ff0000,$48aa4cee,$0303ff9c
205 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
206 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
207 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
208 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
209 dc.l $00100008,$61ff0000,$63d81d40,$ff4e1200
210 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
211 dc.l $660861ff,$00004586,$60300c01,$00016608
212 dc.l $61ff0000,$68866022,$0c010002,$660861ff
213 dc.l $000068e6,$60140c01,$00036608,$61ff0000
214 dc.l $66ae6006,$61ff0000,$480a4cee,$0303ff9c
215 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
216 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
217 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
218 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
219 dc.l $0000633e,$1d40ff4e,$120002ae,$00ff00ff
220 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
221 dc.l $49c46030,$0c010001,$660861ff,$000067ec
222 dc.l $60220c01,$00026608,$61ff0000,$68546014
223 dc.l $0c010003,$660861ff,$00006614,$600661ff
224 dc.l $00004afa,$4cee0303,$ff9cf22e,$9800ff60
225 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
226 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
227 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
228 dc.l $6800ff6c,$41eeff6c,$61ff0000,$62a41d40
229 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
230 dc.l $ff631d41,$ff4e4a01,$660861ff,$00004926
231 dc.l $60300c01,$00016608,$61ff0000,$674e6022
232 dc.l $0c010002,$660861ff,$000067b6,$60140c01
233 dc.l $00036608,$61ff0000,$65766006,$61ff0000
234 dc.l $4a5c4cee,$0303ff9c,$f22e9800,$ff60f22e
235 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
236 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
237 dc.l $90000000,$000041ee,$ff6c216e,$00080000
238 dc.l $216e000c,$0004216e,$00100008,$61ff0000
239 dc.l $62001d40,$ff4e1200,$02ae00ff,$00ffff64
240 dc.l $4280102e,$ff634a01,$660861ff,$00004886
241 dc.l $60300c01,$00016608,$61ff0000,$66ae6022
242 dc.l $0c010002,$660861ff,$00006716,$60140c01
243 dc.l $00036608,$61ff0000,$64d66006,$61ff0000
244 dc.l $49bc4cee,$0303ff9c,$f22e9800,$ff60f22e
245 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
246 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
247 dc.l $90000000,$0000f22e,$44000008,$f22e6800
248 dc.l $ff6c41ee,$ff6c61ff,$00006166,$1d40ff4e
249 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
250 dc.l $4a016608,$61ff0000,$391c6030,$0c010001
251 dc.l $660861ff,$00006614,$60220c01,$00026608
252 dc.l $61ff0000,$66b86014,$0c010003,$660861ff
253 dc.l $0000643c,$600661ff,$00003b28,$4cee0303
254 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
255 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
256 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
257 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
258 dc.l $61ff0000,$60cc1d40,$ff4e1200,$02ae00ff
259 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
260 dc.l $660861ff,$0000387e,$60300c01,$00016608
261 dc.l $61ff0000,$65766022,$0c010002,$660861ff
262 dc.l $0000661a,$60140c01,$00036608,$61ff0000
263 dc.l $639e6006,$61ff0000,$3a8a4cee,$0303ff9c
264 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
265 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
266 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
267 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
268 dc.l $00100008,$61ff0000,$60281d40,$ff4e1200
269 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
270 dc.l $660861ff,$000037de,$60300c01,$00016608
271 dc.l $61ff0000,$64d66022,$0c010002,$660861ff
272 dc.l $0000657a,$60140c01,$00036608,$61ff0000
273 dc.l $62fe6006,$61ff0000,$39ea4cee,$0303ff9c
274 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
275 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
276 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
277 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
278 dc.l $00005f8e,$1d40ff4e,$120002ae,$00ff00ff
279 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
280 dc.l $39886030,$0c010001,$660861ff,$0000643c
281 dc.l $60220c01,$00026608,$61ff0000,$603a6014
282 dc.l $0c010003,$660861ff,$00006264,$600661ff
283 dc.l $00003a04,$4cee0303,$ff9cf22e,$9800ff60
284 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
285 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
286 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
287 dc.l $6800ff6c,$41eeff6c,$61ff0000,$5ef41d40
288 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
289 dc.l $ff631d41,$ff4e4a01,$660861ff,$000038ea
290 dc.l $60300c01,$00016608,$61ff0000,$639e6022
291 dc.l $0c010002,$660861ff,$00005f9c,$60140c01
292 dc.l $00036608,$61ff0000,$61c66006,$61ff0000
293 dc.l $39664cee,$0303ff9c,$f22e9800,$ff60f22e
294 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
295 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
296 dc.l $90000000,$000041ee,$ff6c216e,$00080000
297 dc.l $216e000c,$0004216e,$00100008,$61ff0000
298 dc.l $5e501d40,$ff4e1200,$02ae00ff,$00ffff64
299 dc.l $4280102e,$ff634a01,$660861ff,$0000384a
300 dc.l $60300c01,$00016608,$61ff0000,$62fe6022
301 dc.l $0c010002,$660861ff,$00005efc,$60140c01
302 dc.l $00036608,$61ff0000,$61266006,$61ff0000
303 dc.l $38c64cee,$0303ff9c,$f22e9800,$ff60f22e
304 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
305 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
306 dc.l $90000000,$0000f22e,$44000008,$f22e6800
307 dc.l $ff6c41ee,$ff6c61ff,$00005db6,$1d40ff4e
308 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
309 dc.l $4a016608,$61ff0000,$51d46030,$0c010001
310 dc.l $660861ff,$00006264,$60220c01,$00026608
311 dc.l $61ff0000,$5e626014,$0c010003,$660861ff
312 dc.l $0000608c,$600661ff,$00005224,$4cee0303
313 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
314 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
315 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
316 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
317 dc.l $61ff0000,$5d1c1d40,$ff4e1200,$02ae00ff
318 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
319 dc.l $660861ff,$00005136,$60300c01,$00016608
320 dc.l $61ff0000,$61c66022,$0c010002,$660861ff
321 dc.l $00005dc4,$60140c01,$00036608,$61ff0000
322 dc.l $5fee6006,$61ff0000,$51864cee,$0303ff9c
323 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
324 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
325 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
326 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
327 dc.l $00100008,$61ff0000,$5c781d40,$ff4e1200
328 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
329 dc.l $660861ff,$00005096,$60300c01,$00016608
330 dc.l $61ff0000,$61266022,$0c010002,$660861ff
331 dc.l $00005d24,$60140c01,$00036608,$61ff0000
332 dc.l $5f4e6006,$61ff0000,$50e64cee,$0303ff9c
333 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
334 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
335 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
336 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
337 dc.l $00005bde,$1d40ff4e,$120002ae,$00ff00ff
338 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
339 dc.l $28066030,$0c010001,$660861ff,$0000608c
340 dc.l $60220c01,$00026608,$61ff0000,$5c8a6014
341 dc.l $0c010003,$660861ff,$00005eb4,$600661ff
342 dc.l $00002938,$4cee0303,$ff9cf22e,$9800ff60
343 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
344 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
345 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
346 dc.l $6800ff6c,$41eeff6c,$61ff0000,$5b441d40
347 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
348 dc.l $ff631d41,$ff4e4a01,$660861ff,$00002768
349 dc.l $60300c01,$00016608,$61ff0000,$5fee6022
350 dc.l $0c010002,$660861ff,$00005bec,$60140c01
351 dc.l $00036608,$61ff0000,$5e166006,$61ff0000
352 dc.l $289a4cee,$0303ff9c,$f22e9800,$ff60f22e
353 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
354 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
355 dc.l $90000000,$000041ee,$ff6c216e,$00080000
356 dc.l $216e000c,$0004216e,$00100008,$61ff0000
357 dc.l $5aa01d40,$ff4e1200,$02ae00ff,$00ffff64
358 dc.l $4280102e,$ff634a01,$660861ff,$000026c8
359 dc.l $60300c01,$00016608,$61ff0000,$5f4e6022
360 dc.l $0c010002,$660861ff,$00005b4c,$60140c01
361 dc.l $00036608,$61ff0000,$5d766006,$61ff0000
362 dc.l $27fa4cee,$0303ff9c,$f22e9800,$ff60f22e
363 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
364 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
365 dc.l $90000000,$0000f22e,$44000008,$f22e6800
366 dc.l $ff6c41ee,$ff6c61ff,$00005a06,$1d40ff4e
367 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
368 dc.l $4a016608,$61ff0000,$39e46030,$0c010001
369 dc.l $660861ff,$00005f30,$60220c01,$00026608
370 dc.l $61ff0000,$5f026014,$0c010003,$660861ff
371 dc.l $00005cdc,$600661ff,$00003b5e,$4cee0303
372 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
373 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
374 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
375 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
376 dc.l $61ff0000,$596c1d40,$ff4e1200,$02ae00ff
377 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
378 dc.l $660861ff,$00003946,$60300c01,$00016608
379 dc.l $61ff0000,$5e926022,$0c010002,$660861ff
380 dc.l $00005e64,$60140c01,$00036608,$61ff0000
381 dc.l $5c3e6006,$61ff0000,$3ac04cee,$0303ff9c
382 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
383 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
384 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
385 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
386 dc.l $00100008,$61ff0000,$58c81d40,$ff4e1200
387 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
388 dc.l $660861ff,$000038a6,$60300c01,$00016608
389 dc.l $61ff0000,$5df26022,$0c010002,$660861ff
390 dc.l $00005dc4,$60140c01,$00036608,$61ff0000
391 dc.l $5b9e6006,$61ff0000,$3a204cee,$0303ff9c
392 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
393 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
394 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
395 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
396 dc.l $0000582e,$1d40ff4e,$120002ae,$00ff00ff
397 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
398 dc.l $522e6030,$0c010001,$660861ff,$00005d58
399 dc.l $60220c01,$00026608,$61ff0000,$5d2a6014
400 dc.l $0c010003,$660861ff,$00005b04,$600661ff
401 dc.l $000052d6,$4cee0303,$ff9cf22e,$9800ff60
402 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
403 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
404 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
405 dc.l $6800ff6c,$41eeff6c,$61ff0000,$57941d40
406 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
407 dc.l $ff631d41,$ff4e4a01,$660861ff,$00005190
408 dc.l $60300c01,$00016608,$61ff0000,$5cba6022
409 dc.l $0c010002,$660861ff,$00005c8c,$60140c01
410 dc.l $00036608,$61ff0000,$5a666006,$61ff0000
411 dc.l $52384cee,$0303ff9c,$f22e9800,$ff60f22e
412 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
413 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
414 dc.l $90000000,$000041ee,$ff6c216e,$00080000
415 dc.l $216e000c,$0004216e,$00100008,$61ff0000
416 dc.l $56f01d40,$ff4e1200,$02ae00ff,$00ffff64
417 dc.l $4280102e,$ff634a01,$660861ff,$000050f0
418 dc.l $60300c01,$00016608,$61ff0000,$5c1a6022
419 dc.l $0c010002,$660861ff,$00005bec,$60140c01
420 dc.l $00036608,$61ff0000,$59c66006,$61ff0000
421 dc.l $51984cee,$0303ff9c,$f22e9800,$ff60f22e
422 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
423 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
424 dc.l $90000000,$0000f22e,$44000008,$f22e6800
425 dc.l $ff6c41ee,$ff6c61ff,$00005656,$1d40ff4e
426 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
427 dc.l $4a016608,$61ff0000,$514e6030,$0c010001
428 dc.l $660861ff,$00005b80,$60220c01,$00026608
429 dc.l $61ff0000,$5b526014,$0c010003,$660861ff
430 dc.l $0000592c,$600661ff,$0000524c,$4cee0303
431 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
432 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
433 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
434 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
435 dc.l $61ff0000,$55bc1d40,$ff4e1200,$02ae00ff
436 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
437 dc.l $660861ff,$000050b0,$60300c01,$00016608
438 dc.l $61ff0000,$5ae26022,$0c010002,$660861ff
439 dc.l $00005ab4,$60140c01,$00036608,$61ff0000
440 dc.l $588e6006,$61ff0000,$51ae4cee,$0303ff9c
441 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
442 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
443 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
444 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
445 dc.l $00100008,$61ff0000,$55181d40,$ff4e1200
446 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
447 dc.l $660861ff,$00005010,$60300c01,$00016608
448 dc.l $61ff0000,$5a426022,$0c010002,$660861ff
449 dc.l $00005a14,$60140c01,$00036608,$61ff0000
450 dc.l $57ee6006,$61ff0000,$510e4cee,$0303ff9c
451 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
452 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
453 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
454 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
455 dc.l $0000547e,$1d40ff4e,$120002ae,$00ff00ff
456 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
457 dc.l $45026030,$0c010001,$660861ff,$000054c8
458 dc.l $60220c01,$00026608,$61ff0000,$59826014
459 dc.l $0c010003,$660861ff,$00005754,$600661ff
460 dc.l $00004682,$4cee0303,$ff9cf22e,$9800ff60
461 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
462 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
463 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
464 dc.l $6800ff6c,$41eeff6c,$61ff0000,$53e41d40
465 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
466 dc.l $ff631d41,$ff4e4a01,$660861ff,$00004464
467 dc.l $60300c01,$00016608,$61ff0000,$542a6022
468 dc.l $0c010002,$660861ff,$000058e4,$60140c01
469 dc.l $00036608,$61ff0000,$56b66006,$61ff0000
470 dc.l $45e44cee,$0303ff9c,$f22e9800,$ff60f22e
471 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
472 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
473 dc.l $90000000,$000041ee,$ff6c216e,$00080000
474 dc.l $216e000c,$0004216e,$00100008,$61ff0000
475 dc.l $53401d40,$ff4e1200,$02ae00ff,$00ffff64
476 dc.l $4280102e,$ff634a01,$660861ff,$000043c4
477 dc.l $60300c01,$00016608,$61ff0000,$538a6022
478 dc.l $0c010002,$660861ff,$00005844,$60140c01
479 dc.l $00036608,$61ff0000,$56166006,$61ff0000
480 dc.l $45444cee,$0303ff9c,$f22e9800,$ff60f22e
481 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
482 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
483 dc.l $90000000,$0000f22e,$44000008,$f22e6800
484 dc.l $ff6c41ee,$ff6c61ff,$000052a6,$1d40ff4e
485 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
486 dc.l $4a016608,$61ff0000,$476c6030,$0c010001
487 dc.l $660861ff,$000052f0,$60220c01,$00026608
488 dc.l $61ff0000,$57aa6014,$0c010003,$660861ff
489 dc.l $0000557c,$600661ff,$0000476a,$4cee0303
490 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
491 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
492 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
493 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
494 dc.l $61ff0000,$520c1d40,$ff4e1200,$02ae00ff
495 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
496 dc.l $660861ff,$000046ce,$60300c01,$00016608
497 dc.l $61ff0000,$52526022,$0c010002,$660861ff
498 dc.l $0000570c,$60140c01,$00036608,$61ff0000
499 dc.l $54de6006,$61ff0000,$46cc4cee,$0303ff9c
500 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
501 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
502 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
503 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
504 dc.l $00100008,$61ff0000,$51681d40,$ff4e1200
505 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
506 dc.l $660861ff,$0000462e,$60300c01,$00016608
507 dc.l $61ff0000,$51b26022,$0c010002,$660861ff
508 dc.l $0000566c,$60140c01,$00036608,$61ff0000
509 dc.l $543e6006,$61ff0000,$462c4cee,$0303ff9c
510 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
511 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
512 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
513 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
514 dc.l $000050ce,$1d40ff4e,$120002ae,$00ff00ff
515 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
516 dc.l $45e46030,$0c010001,$660861ff,$00005118
517 dc.l $60220c01,$00026608,$61ff0000,$55d26014
518 dc.l $0c010003,$660861ff,$000053a4,$600661ff
519 dc.l $0000460c,$4cee0303,$ff9cf22e,$9800ff60
520 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
521 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
522 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
523 dc.l $6800ff6c,$41eeff6c,$61ff0000,$50341d40
524 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
525 dc.l $ff631d41,$ff4e4a01,$660861ff,$00004546
526 dc.l $60300c01,$00016608,$61ff0000,$507a6022
527 dc.l $0c010002,$660861ff,$00005534,$60140c01
528 dc.l $00036608,$61ff0000,$53066006,$61ff0000
529 dc.l $456e4cee,$0303ff9c,$f22e9800,$ff60f22e
530 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
531 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
532 dc.l $90000000,$000041ee,$ff6c216e,$00080000
533 dc.l $216e000c,$0004216e,$00100008,$61ff0000
534 dc.l $4f901d40,$ff4e1200,$02ae00ff,$00ffff64
535 dc.l $4280102e,$ff634a01,$660861ff,$000044a6
536 dc.l $60300c01,$00016608,$61ff0000,$4fda6022
537 dc.l $0c010002,$660861ff,$00005494,$60140c01
538 dc.l $00036608,$61ff0000,$52666006,$61ff0000
539 dc.l $44ce4cee,$0303ff9c,$f22e9800,$ff60f22e
540 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
541 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
542 dc.l $90000000,$0000f22e,$44000008,$f22e6800
543 dc.l $ff6c41ee,$ff6c61ff,$00004ef6,$1d40ff4e
544 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
545 dc.l $4a016608,$61ff0000,$33da6030,$0c010001
546 dc.l $660861ff,$00005420,$60220c01,$00026608
547 dc.l $61ff0000,$53ca6014,$0c010003,$660861ff
548 dc.l $000051cc,$600661ff,$0000344c,$4cee0303
549 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
550 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
551 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
552 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
553 dc.l $61ff0000,$4e5c1d40,$ff4e1200,$02ae00ff
554 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
555 dc.l $660861ff,$0000333c,$60300c01,$00016608
556 dc.l $61ff0000,$53826022,$0c010002,$660861ff
557 dc.l $0000532c,$60140c01,$00036608,$61ff0000
558 dc.l $512e6006,$61ff0000,$33ae4cee,$0303ff9c
559 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
560 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
561 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
562 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
563 dc.l $00100008,$61ff0000,$4db81d40,$ff4e1200
564 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
565 dc.l $660861ff,$0000329c,$60300c01,$00016608
566 dc.l $61ff0000,$52e26022,$0c010002,$660861ff
567 dc.l $0000528c,$60140c01,$00036608,$61ff0000
568 dc.l $508e6006,$61ff0000,$330e4cee,$0303ff9c
569 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
570 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
571 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
572 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
573 dc.l $00004d1e,$1d40ff4e,$120002ae,$00ff00ff
574 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
575 dc.l $27cc6030,$0c010001,$660861ff,$00005284
576 dc.l $60220c01,$00026608,$61ff0000,$4dca6014
577 dc.l $0c010003,$660861ff,$00004ff4,$600661ff
578 dc.l $0000282a,$4cee0303,$ff9cf22e,$9800ff60
579 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
580 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
581 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
582 dc.l $6800ff6c,$41eeff6c,$61ff0000,$4c841d40
583 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
584 dc.l $ff631d41,$ff4e4a01,$660861ff,$0000272e
585 dc.l $60300c01,$00016608,$61ff0000,$51e66022
586 dc.l $0c010002,$660861ff,$00004d2c,$60140c01
587 dc.l $00036608,$61ff0000,$4f566006,$61ff0000
588 dc.l $278c4cee,$0303ff9c,$f22e9800,$ff60f22e
589 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
590 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
591 dc.l $90000000,$000041ee,$ff6c216e,$00080000
592 dc.l $216e000c,$0004216e,$00100008,$61ff0000
593 dc.l $4be01d40,$ff4e1200,$02ae00ff,$00ffff64
594 dc.l $4280102e,$ff634a01,$660861ff,$0000268e
595 dc.l $60300c01,$00016608,$61ff0000,$51466022
596 dc.l $0c010002,$660861ff,$00004c8c,$60140c01
597 dc.l $00036608,$61ff0000,$4eb66006,$61ff0000
598 dc.l $26ec4cee,$0303ff9c,$f22e9800,$ff60f22e
599 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
600 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
601 dc.l $90000000,$0000f22e,$44000008,$f22e6800
602 dc.l $ff6c41ee,$ff6c61ff,$00004b46,$1d40ff4e
603 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
604 dc.l $4a016608,$61ff0000,$2fb06030,$0c010001
605 dc.l $660861ff,$00004ff4,$60220c01,$00026608
606 dc.l $61ff0000,$4bf26014,$0c010003,$660861ff
607 dc.l $00004e1c,$600661ff,$00002f9a,$4cee0303
608 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
609 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
610 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
611 dc.l $f22e5400,$0008f22e,$6800ff6c,$41eeff6c
612 dc.l $61ff0000,$4aac1d40,$ff4e1200,$02ae00ff
613 dc.l $00ffff64,$4280102e,$ff631d41,$ff4e4a01
614 dc.l $660861ff,$00002f12,$60300c01,$00016608
615 dc.l $61ff0000,$4f566022,$0c010002,$660861ff
616 dc.l $00004b54,$60140c01,$00036608,$61ff0000
617 dc.l $4d7e6006,$61ff0000,$2efc4cee,$0303ff9c
618 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
619 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
620 dc.l $f22ef0c0,$ffdcf23c,$90000000,$000041ee
621 dc.l $ff6c216e,$00080000,$216e000c,$0004216e
622 dc.l $00100008,$61ff0000,$4a081d40,$ff4e1200
623 dc.l $02ae00ff,$00ffff64,$4280102e,$ff634a01
624 dc.l $660861ff,$00002e72,$60300c01,$00016608
625 dc.l $61ff0000,$4eb66022,$0c010002,$660861ff
626 dc.l $00004ab4,$60140c01,$00036608,$61ff0000
627 dc.l $4cde6006,$61ff0000,$2e5c4cee,$0303ff9c
628 dc.l $f22e9800,$ff60f22e,$d040ffe8,$4e5e4e75
629 dc.l $4e56ff40,$48ee0303,$ff9cf22e,$b800ff60
630 dc.l $f22ef0c0,$ffdcf23c,$90000000,$0000f22e
631 dc.l $44000008,$f22e6800,$ff6c41ee,$ff6c61ff
632 dc.l $0000496e,$1d40ff4e,$120002ae,$00ff00ff
633 dc.l $ff644280,$102eff63,$4a016608,$61ff0000
634 dc.l $2e0c6030,$0c010001,$660861ff,$00004e1c
635 dc.l $60220c01,$00026608,$61ff0000,$4a1a6014
636 dc.l $0c010003,$660861ff,$00004c44,$600661ff
637 dc.l $00002e08,$4cee0303,$ff9cf22e,$9800ff60
638 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
639 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
640 dc.l $f23c9000,$00000000,$f22e5400,$0008f22e
641 dc.l $6800ff6c,$41eeff6c,$61ff0000,$48d41d40
642 dc.l $ff4e1200,$02ae00ff,$00ffff64,$4280102e
643 dc.l $ff631d41,$ff4e4a01,$660861ff,$00002d6e
644 dc.l $60300c01,$00016608,$61ff0000,$4d7e6022
645 dc.l $0c010002,$660861ff,$0000497c,$60140c01
646 dc.l $00036608,$61ff0000,$4ba66006,$61ff0000
647 dc.l $2d6a4cee,$0303ff9c,$f22e9800,$ff60f22e
648 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
649 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
650 dc.l $90000000,$000041ee,$ff6c216e,$00080000
651 dc.l $216e000c,$0004216e,$00100008,$61ff0000
652 dc.l $48301d40,$ff4e1200,$02ae00ff,$00ffff64
653 dc.l $4280102e,$ff634a01,$660861ff,$00002cce
654 dc.l $60300c01,$00016608,$61ff0000,$4cde6022
655 dc.l $0c010002,$660861ff,$000048dc,$60140c01
656 dc.l $00036608,$61ff0000,$4b066006,$61ff0000
657 dc.l $2cca4cee,$0303ff9c,$f22e9800,$ff60f22e
658 dc.l $d040ffe8,$4e5e4e75,$4e56ff40,$48ee0303
659 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
660 dc.l $90000000,$0000f22e,$44000008,$f22e6800
661 dc.l $ff6c41ee,$ff6c61ff,$00004796,$1d40ff4e
662 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
663 dc.l $4a016608,$61ff0000,$0af46030,$0c010001
664 dc.l $660861ff,$00004d18,$60220c01,$00026608
665 dc.l $61ff0000,$4d386014,$0c010003,$660861ff
666 dc.l $00004d34,$600661ff,$00000d58,$4cee0303
667 dc.l $ff9cf22e,$9800ff60,$f227e003,$f21fd040
668 dc.l $f21fd080,$4e5e4e75,$4e56ff40,$48ee0303
669 dc.l $ff9cf22e,$b800ff60,$f22ef0c0,$ffdcf23c
670 dc.l $90000000,$0000f22e,$54000008,$f22e6800
671 dc.l $ff6c41ee,$ff6c61ff,$000046f6,$1d40ff4e
672 dc.l $120002ae,$00ff00ff,$ff644280,$102eff63
673 dc.l $1d41ff4e,$4a016608,$61ff0000,$0a506030
674 dc.l $0c010001,$660861ff,$00004c74,$60220c01
675 dc.l $00026608,$61ff0000,$4c946014,$0c010003
676 dc.l $660861ff,$00004c90,$600661ff,$00000cb4
677 dc.l $4cee0303,$ff9cf22e,$9800ff60,$f227e003
678 dc.l $f21fd040,$f21fd080,$4e5e4e75,$4e56ff40
679 dc.l $48ee0303,$ff9cf22e,$b800ff60,$f22ef0c0
680 dc.l $ffdcf23c,$90000000,$000041ee,$ff6c216e
681 dc.l $00080000,$216e000c,$0004216e,$00100008
682 dc.l $61ff0000,$464c1d40,$ff4e1200,$02ae00ff
683 dc.l $00ffff64,$4280102e,$ff634a01,$660861ff
684 dc.l $000009aa,$60300c01,$00016608,$61ff0000
685 dc.l $4bce6022,$0c010002,$660861ff,$00004bee
686 dc.l $60140c01,$00036608,$61ff0000,$4bea6006
687 dc.l $61ff0000,$0c0e4cee,$0303ff9c,$f22e9800
688 dc.l $ff60f227,$e003f21f,$d040f21f,$d0804e5e
689 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
690 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
691 dc.l $f22e4400,$0008f22e,$6800ff78,$41eeff78
692 dc.l $61ff0000,$45ac1d40,$ff4ff22e,$4400000c
693 dc.l $f22e6800,$ff6c41ee,$ff6c61ff,$00004592
694 dc.l $1d40ff4e,$220002ae,$00ff00ff,$ff644280
695 dc.l $102eff63,$41eeff6c,$43eeff78,$4a016608
696 dc.l $61ff0000,$4c466030,$0c010001,$660861ff
697 dc.l $00004c64,$60220c01,$00026608,$61ff0000
698 dc.l $4c846014,$0c010003,$660861ff,$00004d16
699 dc.l $600661ff,$00004c14,$4cee0303,$ff9cf22e
700 dc.l $9800ff60,$f22ed040,$ffe84e5e,$4e754e56
701 dc.l $ff4048ee,$0303ff9c,$f22eb800,$ff60f22e
702 dc.l $f0c0ffdc,$f23c9000,$00000000,$f22e5400
703 dc.l $0008f22e,$6800ff78,$41eeff78,$61ff0000
704 dc.l $44f01d40,$ff4ff22e,$54000010,$f22e6800
705 dc.l $ff6c41ee,$ff6c61ff,$000044d6,$1d40ff4e
706 dc.l $220002ae,$00ff00ff,$ff644280,$102eff63
707 dc.l $41eeff6c,$43eeff78,$4a016608,$61ff0000
708 dc.l $4b8a6030,$0c010001,$660861ff,$00004ba8
709 dc.l $60220c01,$00026608,$61ff0000,$4bc86014
710 dc.l $0c010003,$660861ff,$00004c5a,$600661ff
711 dc.l $00004b58,$4cee0303,$ff9cf22e,$9800ff60
712 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
713 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
714 dc.l $f23c9000,$00000000,$41eeff78,$216e0008
715 dc.l $0000216e,$000c0004,$216e0010,$000861ff
716 dc.l $0000442e,$1d40ff4f,$41eeff6c,$216e0014
717 dc.l $0000216e,$00180004,$216e001c,$000861ff
718 dc.l $0000440e,$1d40ff4e,$220002ae,$00ff00ff
719 dc.l $ff644280,$102eff63,$41eeff6c,$43eeff78
720 dc.l $4a016608,$61ff0000,$4ac26030,$0c010001
721 dc.l $660861ff,$00004ae0,$60220c01,$00026608
722 dc.l $61ff0000,$4b006014,$0c010003,$660861ff
723 dc.l $00004b92,$600661ff,$00004a90,$4cee0303
724 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
725 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
726 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
727 dc.l $f22e4400,$0008f22e,$6800ff78,$41eeff78
728 dc.l $61ff0000,$436c1d40,$ff4ff22e,$4400000c
729 dc.l $f22e6800,$ff6c41ee,$ff6c61ff,$00004352
730 dc.l $1d40ff4e,$220002ae,$00ff00ff,$ff644280
731 dc.l $102eff63,$41eeff6c,$43eeff78,$4a016608
732 dc.l $61ff0000,$491c6030,$0c010001,$660861ff
733 dc.l $0000493a,$60220c01,$00026608,$61ff0000
734 dc.l $495a6014,$0c010003,$660861ff,$00004ad6
735 dc.l $600661ff,$000048ea,$4cee0303,$ff9cf22e
736 dc.l $9800ff60,$f22ed040,$ffe84e5e,$4e754e56
737 dc.l $ff4048ee,$0303ff9c,$f22eb800,$ff60f22e
738 dc.l $f0c0ffdc,$f23c9000,$00000000,$f22e5400
739 dc.l $0008f22e,$6800ff78,$41eeff78,$61ff0000
740 dc.l $42b01d40,$ff4ff22e,$54000010,$f22e6800
741 dc.l $ff6c41ee,$ff6c61ff,$00004296,$1d40ff4e
742 dc.l $220002ae,$00ff00ff,$ff644280,$102eff63
743 dc.l $41eeff6c,$43eeff78,$4a016608,$61ff0000
744 dc.l $48606030,$0c010001,$660861ff,$0000487e
745 dc.l $60220c01,$00026608,$61ff0000,$489e6014
746 dc.l $0c010003,$660861ff,$00004a1a,$600661ff
747 dc.l $0000482e,$4cee0303,$ff9cf22e,$9800ff60
748 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
749 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
750 dc.l $f23c9000,$00000000,$41eeff78,$216e0008
751 dc.l $0000216e,$000c0004,$216e0010,$000861ff
752 dc.l $000041ee,$1d40ff4f,$41eeff6c,$216e0014
753 dc.l $0000216e,$00180004,$216e001c,$000861ff
754 dc.l $000041ce,$1d40ff4e,$220002ae,$00ff00ff
755 dc.l $ff644280,$102eff63,$41eeff6c,$43eeff78
756 dc.l $4a016608,$61ff0000,$47986030,$0c010001
757 dc.l $660861ff,$000047b6,$60220c01,$00026608
758 dc.l $61ff0000,$47d66014,$0c010003,$660861ff
759 dc.l $00004952,$600661ff,$00004766,$4cee0303
760 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
761 dc.l $4e754e56,$ff4048ee,$0303ff9c,$f22eb800
762 dc.l $ff60f22e,$f0c0ffdc,$f23c9000,$00000000
763 dc.l $f22e4400,$0008f22e,$6800ff78,$41eeff78
764 dc.l $61ff0000,$412c1d40,$ff4ff22e,$4400000c
765 dc.l $f22e6800,$ff6c41ee,$ff6c61ff,$00004112
766 dc.l $1d40ff4e,$220002ae,$00ff00ff,$ff644280
767 dc.l $102eff63,$41eeff6c,$43eeff78,$4a016608
768 dc.l $61ff0000,$484a6030,$0c010001,$660861ff
769 dc.l $0000486a,$60220c01,$00026608,$61ff0000
770 dc.l $488a6014,$0c010003,$660861ff,$00004896
771 dc.l $600661ff,$00004818,$4cee0303,$ff9cf22e
772 dc.l $9800ff60,$f22ed040,$ffe84e5e,$4e754e56
773 dc.l $ff4048ee,$0303ff9c,$f22eb800,$ff60f22e
774 dc.l $f0c0ffdc,$f23c9000,$00000000,$f22e5400
775 dc.l $0008f22e,$6800ff78,$41eeff78,$61ff0000
776 dc.l $40701d40,$ff4ff22e,$54000010,$f22e6800
777 dc.l $ff6c41ee,$ff6c61ff,$00004056,$1d40ff4e
778 dc.l $220002ae,$00ff00ff,$ff644280,$102eff63
779 dc.l $41eeff6c,$43eeff78,$4a016608,$61ff0000
780 dc.l $478e6030,$0c010001,$660861ff,$000047ae
781 dc.l $60220c01,$00026608,$61ff0000,$47ce6014
782 dc.l $0c010003,$660861ff,$000047da,$600661ff
783 dc.l $0000475c,$4cee0303,$ff9cf22e,$9800ff60
784 dc.l $f22ed040,$ffe84e5e,$4e754e56,$ff4048ee
785 dc.l $0303ff9c,$f22eb800,$ff60f22e,$f0c0ffdc
786 dc.l $f23c9000,$00000000,$41eeff78,$216e0008
787 dc.l $0000216e,$000c0004,$216e0010,$000861ff
788 dc.l $00003fae,$1d40ff4f,$41eeff6c,$216e0014
789 dc.l $0000216e,$00180004,$216e001c,$000861ff
790 dc.l $00003f8e,$1d40ff4e,$220002ae,$00ff00ff
791 dc.l $ff644280,$102eff63,$41eeff6c,$43eeff78
792 dc.l $4a016608,$61ff0000,$46c66030,$0c010001
793 dc.l $660861ff,$000046e6,$60220c01,$00026608
794 dc.l $61ff0000,$47066014,$0c010003,$660861ff
795 dc.l $00004712,$600661ff,$00004694,$4cee0303
796 dc.l $ff9cf22e,$9800ff60,$f22ed040,$ffe84e5e
797 dc.l $4e75bd6a,$aa77ccc9,$94f53de6,$12097aae
798 dc.l $8da1be5a,$e6452a11,$8ae43ec7,$1de3a534
799 dc.l $1531bf2a,$01a01a01,$8b590000,$00000000
800 dc.l $00003ff8,$00008888,$88888888,$59af0000
801 dc.l $0000bffc,$0000aaaa,$aaaaaaaa,$aa990000
802 dc.l $00003d2a,$c4d0d601,$1ee3bda9,$396f9f45
803 dc.l $ac193e21,$eed90612,$c972be92,$7e4fb79d
804 dc.l $9fcf3efa,$01a01a01,$d4230000,$00000000
805 dc.l $0000bff5,$0000b60b,$60b60b61,$d4380000
806 dc.l $00003ffa,$0000aaaa,$aaaaaaaa,$ab5ebf00
807 dc.l $00002d7c,$00000000,$ff5c6008,$2d7c0000
808 dc.l $0001ff5c,$f2104800,$f22e6800,$ff842210
809 dc.l $32280004,$02817fff,$ffff0c81,$3fd78000
810 dc.l $6c046000,$01780c81,$4004bc7e,$6d046000
811 dc.l $0468f200,$0080f23a,$54a3d186,$43fb0170
812 dc.l $00000866,$f22e6080,$ff58222e,$ff58e981
813 dc.l $d3c1f219,$4828f211,$4428222e,$ff58d2ae
814 dc.l $ff5ce299,$0c810000,$00006d00,$0088f227
815 dc.l $e00cf22e,$6800ff84,$f2000023,$f23a5580
816 dc.l $fed2f23a,$5500fed4,$f2000080,$f20004a3
817 dc.l $e2990281,$80000000,$b3aeff84,$f20005a3
818 dc.l $f2000523,$f23a55a2,$febaf23a,$5522febc
819 dc.l $f20005a3,$f2000523,$f23a55a2,$feb6f23a
820 dc.l $4922fec0,$f2000ca3,$f2000123,$f23a48a2
821 dc.l $fec2f22e,$4823ff84,$f20008a2,$f2000423
822 dc.l $f21fd030,$f2009000,$f22e4822,$ff8460ff
823 dc.l $00004006,$f227e00c,$f2000023,$f23a5500
824 dc.l $fea2f23a,$5580fea4,$f2000080,$f20004a3
825 dc.l $f22e6800,$ff84e299,$02818000,$0000f200
826 dc.l $0523b3ae,$ff840281,$80000000,$f20005a3
827 dc.l $00813f80,$00002d41,$ff54f23a,$5522fe74
828 dc.l $f23a55a2,$fe76f200,$0523f200,$05a3f23a
829 dc.l $5522fe70,$f23a49a2,$fe7af200,$0523f200
830 dc.l $0ca3f23a,$4922fe7c,$f23a44a2,$fe82f200
831 dc.l $0823f200,$0422f22e,$4823ff84,$f21fd030
832 dc.l $f2009000,$f22e4422,$ff5460ff,$00003f6a
833 dc.l $0c813fff,$80006eff,$00000300,$222eff5c
834 dc.l $0c810000,$00006e14,$f2009000,$123c0003
835 dc.l $f22e4800,$ff8460ff,$00003f36,$f23c4400
836 dc.l $3f800000,$f2009000,$f23c4422,$80800000
837 dc.l $60ff0000,$3f2c60ff,$00003f64,$f23c4400
838 dc.l $3f800000,$60ff0000,$3f182d7c,$00000004
839 dc.l $ff5cf210,$4800f22e,$6800ff84,$22103228
840 dc.l $00040281,$7fffffff,$0c813fd7,$80006c04
841 dc.l $60000240,$0c814004,$bc7e6d04,$6000027a
842 dc.l $f2000080,$f23a54a3,$cf9843fb,$01700000
843 dc.l $0678f22e,$6080ff58,$222eff58,$e981d3c1
844 dc.l $f2194828,$f2114428,$222eff58,$e2990c81
845 dc.l $00000000,$6c000106,$f227e004,$f22e6800
846 dc.l $ff84f200,$0023f23a,$5480fce8,$f23a5500
847 dc.l $fd32f200,$00a3f200,$01232f02,$2401e29a
848 dc.l $02828000,$0000b382,$02828000,$0000f23a
849 dc.l $54a2fcc8,$f23a5522,$fd12f200,$00a3b5ae
850 dc.l $ff84241f,$f2000123,$e2990281,$80000000
851 dc.l $2d7c3f80,$0000ff54,$b3aeff54,$f23a54a2
852 dc.l $fca2f23a,$5522fcec,$f20000a3,$f2000123
853 dc.l $f22e6800,$ff90f23a,$54a2fc90,$b3aeff90
854 dc.l $f23a5522,$fcd6f200,$00a3f200,$0123f23a
855 dc.l $54a2fc80,$f23a5522,$fccaf200,$00a3f200
856 dc.l $0123f23a,$48a2fc7c,$f23a4922,$fcc6f200
857 dc.l $00a3f200,$0123f23a,$48a2fc78,$f23a4922
858 dc.l $fcc2f200,$00a3f200,$0823f22e,$48a3ff84
859 dc.l $f23a4422,$fcbaf22e,$4823ff90,$f21fd020
860 dc.l $f2009000,$f22e48a2,$ff8461ff,$00003e22
861 dc.l $f22e4422,$ff5460ff,$00003d9e,$f227e004
862 dc.l $f22e6800,$ff84f200,$0023f23a,$5480fc34
863 dc.l $f23a5500,$fbdef200,$00a3f22e,$6800ff90
864 dc.l $f2000123,$e2990281,$80000000,$f23a54a2
865 dc.l $fc1af23a,$5522fbc4,$b3aeff84,$b3aeff90
866 dc.l $f20000a3,$00813f80,$00002d41,$ff54f200
867 dc.l $0123f23a,$54a2fbfc,$f23a5522,$fba6f200
868 dc.l $00a3f200,$0123f23a,$54a2fbf0,$f23a5522
869 dc.l $fb9af200,$00a3f200,$0123f23a,$54a2fbe4
870 dc.l $f23a5522,$fb8ef200,$00a3f200,$0123f23a
871 dc.l $48a2fbe0,$f23a4922,$fb8af200,$00a3f200
872 dc.l $0123f23a,$48a2fbdc,$f23a4922,$fb86f200
873 dc.l $00a3f200,$0823f23a,$44a2fbd4,$f22e4823
874 dc.l $ff84f22e,$48a3ff90,$f21fd020,$f2009000
875 dc.l $f22e44a2,$ff5461ff,$00003d36,$f22e4822
876 dc.l $ff8460ff,$00003cb2,$0c813fff,$80006e00
877 dc.l $0048f23c,$44803f80,$0000f200,$9000f23c
878 dc.l $44a80080,$000061ff,$00003d06,$f200b000
879 dc.l $123c0003,$f22e4800,$ff8460ff,$00003c72
880 dc.l $2f00f23c,$44803f80,$000061ff,$00003ce2
881 dc.l $201f60ff,$00003ca8,$f227e03c,$2f02f23c
882 dc.l $44800000,$00000c81,$7ffeffff,$66523d7c
883 dc.l $7ffeff84,$2d7cc90f,$daa2ff88,$42aeff8c
884 dc.l $3d7c7fdc,$ff902d7c,$85a308d3,$ff9442ae
885 dc.l $ff98f200,$003af294,$000e002e,$0080ff84
886 dc.l $002e0080,$ff90f22e,$4822ff84,$f2000080
887 dc.l $f22e4822,$ff90f200,$00a8f22e,$48a2ff90
888 dc.l $f22e6800,$ff84322e,$ff842241,$02810000
889 dc.l $7fff0481,$00003fff,$0c810000,$001c6f0e
890 dc.l $04810000,$001b1d7c,$0000ff58,$60084281
891 dc.l $1d7c0001,$ff58243c,$00003ffe,$94812d7c
892 dc.l $a2f9836e,$ff882d7c,$4e44152a,$ff8c3d42
893 dc.l $ff84f200,$0100f22e,$4923ff84,$24094842
894 dc.l $02828000,$00000082,$5f000000,$2d42ff54
895 dc.l $f22e4522,$ff54f22e,$4528ff54,$24010682
896 dc.l $00003fff,$3d42ff84,$2d7cc90f,$daa2ff88
897 dc.l $42aeff8c,$06810000,$3fdd3d41,$ff902d7c
898 dc.l $85a308d3,$ff9442ae,$ff98122e,$ff58f200
899 dc.l $0a00f22e,$4a23ff84,$f2000a80,$f22e4aa3
900 dc.l $ff90f200,$1180f200,$15a2f200,$0e28f200
901 dc.l $0c28f200,$1622f200,$0180f200,$10a8f200
902 dc.l $04220c01,$00006e00,$000ef200,$01a8f200
903 dc.l $0ca26000,$ff0cf22e,$6100ff58,$241ff21f
904 dc.l $d03c222e,$ff5c0c81,$00000004,$6d00fa4c
905 dc.l $6000fc36,$3ea0b759,$f50f8688,$bef2baa5
906 dc.l $a8924f04,$bf346f59,$b39ba65f,$00000000
907 dc.l $00000000,$3ff60000,$e073d3fc,$199c4a00
908 dc.l $00000000,$3ff90000,$d23cd684,$15d95fa1
909 dc.l $00000000,$bffc0000,$8895a6c5,$fb423bca
910 dc.l $00000000,$bffd0000,$eef57e0d,$a84bc8ce
911 dc.l $00000000,$3ffc0000,$a2f9836e,$4e44152a
912 dc.l $00000000,$40010000,$c90fdaa2,$00000000
913 dc.l $00000000,$3fdf0000,$85a308d4,$00000000
914 dc.l $00000000,$c0040000,$c90fdaa2,$2168c235
915 dc.l $21800000,$c0040000,$c2c75bcd,$105d7c23
916 dc.l $a0d00000,$c0040000,$bc7edcf7,$ff523611
917 dc.l $a1e80000,$c0040000,$b6365e22,$ee46f000
918 dc.l $21480000,$c0040000,$afeddf4d,$dd3ba9ee
919 dc.l $a1200000,$c0040000,$a9a56078,$cc3063dd
920 dc.l $21fc0000,$c0040000,$a35ce1a3,$bb251dcb
921 dc.l $21100000,$c0040000,$9d1462ce,$aa19d7b9
922 dc.l $a1580000,$c0040000,$96cbe3f9,$990e91a8
923 dc.l $21e00000,$c0040000,$90836524,$88034b96
924 dc.l $20b00000,$c0040000,$8a3ae64f,$76f80584
925 dc.l $a1880000,$c0040000,$83f2677a,$65ecbf73
926 dc.l $21c40000,$c0030000,$fb53d14a,$a9c2f2c2
927 dc.l $20000000,$c0030000,$eec2d3a0,$87ac669f
928 dc.l $21380000,$c0030000,$e231d5f6,$6595da7b
929 dc.l $a1300000,$c0030000,$d5a0d84c,$437f4e58
930 dc.l $9fc00000,$c0030000,$c90fdaa2,$2168c235
931 dc.l $21000000,$c0030000,$bc7edcf7,$ff523611
932 dc.l $a1680000,$c0030000,$afeddf4d,$dd3ba9ee
933 dc.l $a0a00000,$c0030000,$a35ce1a3,$bb251dcb
934 dc.l $20900000,$c0030000,$96cbe3f9,$990e91a8
935 dc.l $21600000,$c0030000,$8a3ae64f,$76f80584
936 dc.l $a1080000,$c0020000,$fb53d14a,$a9c2f2c2
937 dc.l $1f800000,$c0020000,$e231d5f6,$6595da7b
938 dc.l $a0b00000,$c0020000,$c90fdaa2,$2168c235
939 dc.l $20800000,$c0020000,$afeddf4d,$dd3ba9ee
940 dc.l $a0200000,$c0020000,$96cbe3f9,$990e91a8
941 dc.l $20e00000,$c0010000,$fb53d14a,$a9c2f2c2
942 dc.l $1f000000,$c0010000,$c90fdaa2,$2168c235
943 dc.l $20000000,$c0010000,$96cbe3f9,$990e91a8
944 dc.l $20600000,$c0000000,$c90fdaa2,$2168c235
945 dc.l $1f800000,$bfff0000,$c90fdaa2,$2168c235
946 dc.l $1f000000,$00000000,$00000000,$00000000
947 dc.l $00000000,$3fff0000,$c90fdaa2,$2168c235
948 dc.l $9f000000,$40000000,$c90fdaa2,$2168c235
949 dc.l $9f800000,$40010000,$96cbe3f9,$990e91a8
950 dc.l $a0600000,$40010000,$c90fdaa2,$2168c235
951 dc.l $a0000000,$40010000,$fb53d14a,$a9c2f2c2
952 dc.l $9f000000,$40020000,$96cbe3f9,$990e91a8
953 dc.l $a0e00000,$40020000,$afeddf4d,$dd3ba9ee
954 dc.l $20200000,$40020000,$c90fdaa2,$2168c235
955 dc.l $a0800000,$40020000,$e231d5f6,$6595da7b
956 dc.l $20b00000,$40020000,$fb53d14a,$a9c2f2c2
957 dc.l $9f800000,$40030000,$8a3ae64f,$76f80584
958 dc.l $21080000,$40030000,$96cbe3f9,$990e91a8
959 dc.l $a1600000,$40030000,$a35ce1a3,$bb251dcb
960 dc.l $a0900000,$40030000,$afeddf4d,$dd3ba9ee
961 dc.l $20a00000,$40030000,$bc7edcf7,$ff523611
962 dc.l $21680000,$40030000,$c90fdaa2,$2168c235
963 dc.l $a1000000,$40030000,$d5a0d84c,$437f4e58
964 dc.l $1fc00000,$40030000,$e231d5f6,$6595da7b
965 dc.l $21300000,$40030000,$eec2d3a0,$87ac669f
966 dc.l $a1380000,$40030000,$fb53d14a,$a9c2f2c2
967 dc.l $a0000000,$40040000,$83f2677a,$65ecbf73
968 dc.l $a1c40000,$40040000,$8a3ae64f,$76f80584
969 dc.l $21880000,$40040000,$90836524,$88034b96
970 dc.l $a0b00000,$40040000,$96cbe3f9,$990e91a8
971 dc.l $a1e00000,$40040000,$9d1462ce,$aa19d7b9
972 dc.l $21580000,$40040000,$a35ce1a3,$bb251dcb
973 dc.l $a1100000,$40040000,$a9a56078,$cc3063dd
974 dc.l $a1fc0000,$40040000,$afeddf4d,$dd3ba9ee
975 dc.l $21200000,$40040000,$b6365e22,$ee46f000
976 dc.l $a1480000,$40040000,$bc7edcf7,$ff523611
977 dc.l $21e80000,$40040000,$c2c75bcd,$105d7c23
978 dc.l $20d00000,$40040000,$c90fdaa2,$2168c235
979 dc.l $a1800000,$f2104800,$22103228,$00040281
980 dc.l $7fffffff,$0c813fd7,$80006c04,$60000134
981 dc.l $0c814004,$bc7e6d04,$60000144,$f2000080
982 dc.l $f23a54a3,$c6dc43fa,$fdbcf201,$6080e981
983 dc.l $d3c1f219,$4828f211,$4428ea99,$02818000
984 dc.l $0000f227,$e00c0c81,$00000000,$6d000072
985 dc.l $f2000080,$f20004a3,$f23a5580,$faf8f23a
986 dc.l $5500fafa,$f20005a3,$f2000523,$f23a55a2
987 dc.l $faf4f23a,$4922fafe,$f20005a3,$f2000523
988 dc.l $f23a49a2,$fb00f23a,$4922fb0a,$f20005a3
989 dc.l $f2000523,$f23a49a2,$fb0cf200,$0123f200
990 dc.l $0ca3f200,$0822f23c,$44a23f80,$0000f21f
991 dc.l $d030f200,$9000f200,$042060ff,$0000357a
992 dc.l $f2000080,$f2000023,$f23a5580,$fa88f23a
993 dc.l $5500fa8a,$f20001a3,$f2000123,$f23a55a2
994 dc.l $fa84f23a,$4922fa8e,$f20001a3,$f2000123
995 dc.l $f23a49a2,$fa90f23a,$4922fa9a,$f20001a3
996 dc.l $f2000123,$f23a49a2,$fa9cf200,$0523f200
997 dc.l $0c23f200,$08a2f23c,$44223f80,$0000f21f
998 dc.l $d030f227,$68800a97,$80000000,$f2009000
999 dc.l $f21f4820,$60ff0000,$35000c81,$3fff8000
1000 dc.l $6e1cf227,$6800f200,$9000123c,$0003f21f
1001 dc.l $480060ff,$000034da,$60ff0000,$3522f227
1002 dc.l $e03c2f02,$f23c4480,$00000000,$0c817ffe
1003 dc.l $ffff6652,$3d7c7ffe,$ff842d7c,$c90fdaa2
1004 dc.l $ff8842ae,$ff8c3d7c,$7fdcff90,$2d7c85a3
1005 dc.l $08d3ff94,$42aeff98,$f200003a,$f294000e
1006 dc.l $002e0080,$ff84002e,$0080ff90,$f22e4822
1007 dc.l $ff84f200,$0080f22e,$4822ff90,$f20000a8
1008 dc.l $f22e48a2,$ff90f22e,$6800ff84,$322eff84
1009 dc.l $22410281,$00007fff,$04810000,$3fff0c81
1010 dc.l $0000001c,$6f0e0481,$0000001b,$1d7c0000
1011 dc.l $ff586008,$42811d7c,$0001ff58,$243c0000
1012 dc.l $3ffe9481,$2d7ca2f9,$836eff88,$2d7c4e44
1013 dc.l $152aff8c,$3d42ff84,$f2000100,$f22e4923
1014 dc.l $ff842409,$48420282,$80000000,$00825f00
1015 dc.l $00002d42,$ff54f22e,$4522ff54,$f22e4528
1016 dc.l $ff542401,$06820000,$3fff3d42,$ff842d7c
1017 dc.l $c90fdaa2,$ff8842ae,$ff8c0681,$00003fdd
1018 dc.l $3d41ff90,$2d7c85a3,$08d3ff94,$42aeff98
1019 dc.l $122eff58,$f2000a00,$f22e4a23,$ff84f200
1020 dc.l $0a80f22e,$4aa3ff90,$f2001180,$f20015a2
1021 dc.l $f2000e28,$f2000c28,$f2001622,$f2000180
1022 dc.l $f20010a8,$f2000422,$0c010000,$6e00000e
1023 dc.l $f20001a8,$f2000ca2,$6000ff0c,$f22e6100
1024 dc.l $ff54241f,$f21fd03c,$222eff54,$e2996000
1025 dc.l $fd72bff6,$687e3149,$87d84002,$ac6934a2
1026 dc.l $6db3bfc2,$476f4e1d,$a28e3fb3,$44447f87
1027 dc.l $6989bfb7,$44ee7faf,$45db3fbc,$71c64694
1028 dc.l $0220bfc2,$49249218,$72f93fc9,$99999999
1029 dc.l $8fa9bfd5,$55555555,$5555bfb7,$0bf39853
1030 dc.l $9e6a3fbc,$7187962d,$1d7dbfc2,$49248271
1031 dc.l $07b83fc9,$99999996,$263ebfd5,$55555555
1032 dc.l $55363fff,$0000c90f,$daa22168,$c2350000
1033 dc.l $0000bfff,$0000c90f,$daa22168,$c2350000
1034 dc.l $00000001,$00008000,$00000000,$00000000
1035 dc.l $00008001,$00008000,$00000000,$00000000
1036 dc.l $00003ffb,$000083d1,$52c5060b,$7a510000
1037 dc.l $00003ffb,$00008bc8,$54456549,$8b8b0000
1038 dc.l $00003ffb,$000093be,$40601762,$6b0d0000
1039 dc.l $00003ffb,$00009bb3,$078d35ae,$c2020000
1040 dc.l $00003ffb,$0000a3a6,$9a525ddc,$e7de0000
1041 dc.l $00003ffb,$0000ab98,$e9436276,$56190000
1042 dc.l $00003ffb,$0000b389,$e502f9c5,$98620000
1043 dc.l $00003ffb,$0000bb79,$7e436b09,$e6fb0000
1044 dc.l $00003ffb,$0000c367,$a5c739e5,$f4460000
1045 dc.l $00003ffb,$0000cb54,$4c61cff7,$d5c60000
1046 dc.l $00003ffb,$0000d33f,$62f82488,$533e0000
1047 dc.l $00003ffb,$0000db28,$da816240,$4c770000
1048 dc.l $00003ffb,$0000e310,$a4078ad3,$4f180000
1049 dc.l $00003ffb,$0000eaf6,$b0a8188e,$e1eb0000
1050 dc.l $00003ffb,$0000f2da,$f1949dbe,$79d50000
1051 dc.l $00003ffb,$0000fabd,$581361d4,$7e3e0000
1052 dc.l $00003ffc,$00008346,$ac210959,$ecc40000
1053 dc.l $00003ffc,$00008b23,$2a083042,$82d80000
1054 dc.l $00003ffc,$000092fb,$70b8d29a,$e2f90000
1055 dc.l $00003ffc,$00009acf,$476f5ccd,$1cb40000
1056 dc.l $00003ffc,$0000a29e,$76304954,$f23f0000
1057 dc.l $00003ffc,$0000aa68,$c5d08ab8,$52300000
1058 dc.l $00003ffc,$0000b22d,$fffd9d53,$9f830000
1059 dc.l $00003ffc,$0000b9ed,$ef453e90,$0ea50000
1060 dc.l $00003ffc,$0000c1a8,$5f1cc75e,$3ea50000
1061 dc.l $00003ffc,$0000c95d,$1be82813,$8de60000
1062 dc.l $00003ffc,$0000d10b,$f300840d,$2de40000
1063 dc.l $00003ffc,$0000d8b4,$b2ba6bc0,$5e7a0000
1064 dc.l $00003ffc,$0000e057,$2a6bb423,$35f60000
1065 dc.l $00003ffc,$0000e7f3,$2a70ea9c,$aa8f0000
1066 dc.l $00003ffc,$0000ef88,$843264ec,$efaa0000
1067 dc.l $00003ffc,$0000f717,$0a28ecc0,$66660000
1068 dc.l $00003ffd,$0000812f,$d288332d,$ad320000
1069 dc.l $00003ffd,$000088a8,$d1b1218e,$4d640000
1070 dc.l $00003ffd,$00009012,$ab3f23e4,$aee80000
1071 dc.l $00003ffd,$0000976c,$c3d411e7,$f1b90000
1072 dc.l $00003ffd,$00009eb6,$89493889,$a2270000
1073 dc.l $00003ffd,$0000a5ef,$72c34487,$361b0000
1074 dc.l $00003ffd,$0000ad17,$00baf07a,$72270000
1075 dc.l $00003ffd,$0000b42c,$bcfafd37,$efb70000
1076 dc.l $00003ffd,$0000bb30,$3a940ba8,$0f890000
1077 dc.l $00003ffd,$0000c221,$15c6fcae,$bbaf0000
1078 dc.l $00003ffd,$0000c8fe,$f3e68633,$12210000
1079 dc.l $00003ffd,$0000cfc9,$8330b400,$0c700000
1080 dc.l $00003ffd,$0000d680,$7aa1102c,$5bf90000
1081 dc.l $00003ffd,$0000dd23,$99bc3125,$2aa30000
1082 dc.l $00003ffd,$0000e3b2,$a8556b8f,$c5170000
1083 dc.l $00003ffd,$0000ea2d,$764f6431,$59890000
1084 dc.l $00003ffd,$0000f3bf,$5bf8bad1,$a21d0000
1085 dc.l $00003ffe,$0000801c,$e39e0d20,$5c9a0000
1086 dc.l $00003ffe,$00008630,$a2dada1e,$d0660000
1087 dc.l $00003ffe,$00008c1a,$d445f3e0,$9b8c0000
1088 dc.l $00003ffe,$000091db,$8f1664f3,$50e20000
1089 dc.l $00003ffe,$00009773,$1420365e,$538c0000
1090 dc.l $00003ffe,$00009ce1,$c8e6a0b8,$cdba0000
1091 dc.l $00003ffe,$0000a228,$32dbcada,$ae090000
1092 dc.l $00003ffe,$0000a746,$f2ddb760,$22940000
1093 dc.l $00003ffe,$0000ac3e,$c0fb997d,$d6a20000
1094 dc.l $00003ffe,$0000b110,$688aebdc,$6f6a0000
1095 dc.l $00003ffe,$0000b5bc,$c49059ec,$c4b00000
1096 dc.l $00003ffe,$0000ba44,$bc7dd470,$782f0000
1097 dc.l $00003ffe,$0000bea9,$4144fd04,$9aac0000
1098 dc.l $00003ffe,$0000c2eb,$4abb6616,$28b60000
1099 dc.l $00003ffe,$0000c70b,$d54ce602,$ee140000
1100 dc.l $00003ffe,$0000cd00,$0549adec,$71590000
1101 dc.l $00003ffe,$0000d484,$57d2d8ea,$4ea30000
1102 dc.l $00003ffe,$0000db94,$8da712de,$ce3b0000
1103 dc.l $00003ffe,$0000e238,$55f969e8,$096a0000
1104 dc.l $00003ffe,$0000e877,$1129c435,$32590000
1105 dc.l $00003ffe,$0000ee57,$c16e0d37,$9c0d0000
1106 dc.l $00003ffe,$0000f3e1,$0211a87c,$37790000
1107 dc.l $00003ffe,$0000f919,$039d758b,$8d410000
1108 dc.l $00003ffe,$0000fe05,$8b8f6493,$5fb30000
1109 dc.l $00003fff,$00008155,$fb497b68,$5d040000
1110 dc.l $00003fff,$00008388,$9e3549d1,$08e10000
1111 dc.l $00003fff,$0000859c,$fa76511d,$724b0000
1112 dc.l $00003fff,$00008795,$2ecfff81,$31e70000
1113 dc.l $00003fff,$00008973,$2fd19557,$641b0000
1114 dc.l $00003fff,$00008b38,$cad10193,$2a350000
1115 dc.l $00003fff,$00008ce7,$a8d8301e,$e6b50000
1116 dc.l $00003fff,$00008f46,$a39e2eae,$52810000
1117 dc.l $00003fff,$0000922d,$a7d79188,$84870000
1118 dc.l $00003fff,$000094d1,$9fcbdedf,$52410000
1119 dc.l $00003fff,$0000973a,$b94419d2,$a08b0000
1120 dc.l $00003fff,$0000996f,$f00e08e1,$0b960000
1121 dc.l $00003fff,$00009b77,$3f951232,$1da70000
1122 dc.l $00003fff,$00009d55,$cc320f93,$56240000
1123 dc.l $00003fff,$00009f10,$0575006c,$c5710000
1124 dc.l $00003fff,$0000a0a9,$c290d97c,$c06c0000
1125 dc.l $00003fff,$0000a226,$59ebebc0,$630a0000
1126 dc.l $00003fff,$0000a388,$b4aff6ef,$0ec90000
1127 dc.l $00003fff,$0000a4d3,$5f1061d2,$92c40000
1128 dc.l $00003fff,$0000a608,$95dcfbe3,$187e0000
1129 dc.l $00003fff,$0000a72a,$51dc7367,$beac0000
1130 dc.l $00003fff,$0000a83a,$51530956,$168f0000
1131 dc.l $00003fff,$0000a93a,$20077539,$546e0000
1132 dc.l $00003fff,$0000aa9e,$7245023b,$26050000
1133 dc.l $00003fff,$0000ac4c,$84ba6fe4,$d58f0000
1134 dc.l $00003fff,$0000adce,$4a4a606b,$97120000
1135 dc.l $00003fff,$0000af2a,$2dcd8d26,$3c9c0000
1136 dc.l $00003fff,$0000b065,$6f81f222,$65c70000
1137 dc.l $00003fff,$0000b184,$65150f71,$496a0000
1138 dc.l $00003fff,$0000b28a,$aa156f9a,$da350000
1139 dc.l $00003fff,$0000b37b,$44ff3766,$b8950000
1140 dc.l $00003fff,$0000b458,$c3dce963,$04330000
1141 dc.l $00003fff,$0000b525,$529d5622,$46bd0000
1142 dc.l $00003fff,$0000b5e2,$cca95f9d,$88cc0000
1143 dc.l $00003fff,$0000b692,$cada7aca,$1ada0000
1144 dc.l $00003fff,$0000b736,$aea7a692,$58380000
1145 dc.l $00003fff,$0000b7cf,$ab287e9f,$7b360000
1146 dc.l $00003fff,$0000b85e,$cc66cb21,$98350000
1147 dc.l $00003fff,$0000b8e4,$fd5a20a5,$93da0000
1148 dc.l $00003fff,$0000b99f,$41f64aff,$9bb50000
1149 dc.l $00003fff,$0000ba7f,$1e17842b,$be7b0000
1150 dc.l $00003fff,$0000bb47,$12857637,$e17d0000
1151 dc.l $00003fff,$0000bbfa,$be8a4788,$df6f0000
1152 dc.l $00003fff,$0000bc9d,$0fad2b68,$9d790000
1153 dc.l $00003fff,$0000bd30,$6a39471e,$cd860000
1154 dc.l $00003fff,$0000bdb6,$c731856a,$f18a0000
1155 dc.l $00003fff,$0000be31,$cac502e8,$0d700000
1156 dc.l $00003fff,$0000bea2,$d55ce331,$94e20000
1157 dc.l $00003fff,$0000bf0b,$10b7c031,$28f00000
1158 dc.l $00003fff,$0000bf6b,$7a18dacb,$778d0000
1159 dc.l $00003fff,$0000bfc4,$ea4663fa,$18f60000
1160 dc.l $00003fff,$0000c018,$1bde8b89,$a4540000
1161 dc.l $00003fff,$0000c065,$b066cfbf,$64390000
1162 dc.l $00003fff,$0000c0ae,$345f5634,$0ae60000
1163 dc.l $00003fff,$0000c0f2,$22919cb9,$e6a70000
1164 dc.l $0000f210,$48002210,$32280004,$f22e6800
1165 dc.l $ff840281,$7fffffff,$0c813ffb,$80006c04
1166 dc.l $600000d0,$0c814002,$ffff6f04,$6000014c
1167 dc.l $02aef800,$0000ff88,$00ae0400,$0000ff88
1168 dc.l $2d7c0000,$0000ff8c,$f2000080,$f22e48a3
1169 dc.l $ff84f22e,$4828ff84,$f23c44a2,$3f800000
1170 dc.l $f2000420,$2f022401,$02810000,$78000282
1171 dc.l $7fff0000,$04823ffb,$0000e282,$d282ee81
1172 dc.l $43faf780,$d3c12d59,$ff902d59,$ff942d59
1173 dc.l $ff98222e,$ff840281,$80000000,$83aeff90
1174 dc.l $241ff227,$e004f200,$0080f200,$04a3f23a
1175 dc.l $5500f6a0,$f2000522,$f2000523,$f20000a3
1176 dc.l $f23a5522,$f696f23a,$54a3f698,$f20008a3
1177 dc.l $f2000422,$f21fd020,$f2009000,$f22e4822
1178 dc.l $ff9060ff,$000029d2,$0c813fff,$80006e00
1179 dc.l $008a0c81,$3fd78000,$6d00006c,$f227e00c
1180 dc.l $f2000023,$f2000080,$f20004a3,$f23a5500
1181 dc.l $f65af23a,$5580f65c,$f2000523,$f20005a3
1182 dc.l $f23a5522,$f656f23a,$55a2f658,$f2000523
1183 dc.l $f2000ca3,$f23a5522,$f652f23a,$54a2f654
1184 dc.l $f2000123,$f22e4823,$ff84f200,$08a2f200
1185 dc.l $0423f21f,$d030f200,$9000f22e,$4822ff84
1186 dc.l $60ff0000,$2954f200,$9000123c,$0003f22e
1187 dc.l $4800ff84,$60ff0000,$29380c81,$40638000
1188 dc.l $6e00008e,$f227e00c,$f23c4480,$bf800000
1189 dc.l $f20000a0,$f2000400,$f2000023,$f22e6880
1190 dc.l $ff84f200,$0080f200,$04a3f23a,$5580f5ec
1191 dc.l $f23a5500,$f5eef200,$05a3f200,$0523f23a
1192 dc.l $55a2f5e8,$f23a5522,$f5eaf200,$0ca3f200
1193 dc.l $0123f23a,$54a2f5e4,$f22e4823,$ff84f200
1194 dc.l $08a2f200,$0423f22e,$4822ff84,$f21fd030
1195 dc.l $f2009000,$4a106a0c,$f23a4822,$f5d660ff
1196 dc.l $000028c6,$f23a4822,$f5ba60ff,$000028b2
1197 dc.l $4a106a16,$f23a4800,$f5baf200,$9000f23a
1198 dc.l $4822f5c0,$60ff0000,$28a0f23a,$4800f594
1199 dc.l $f2009000,$f23a4822,$f5ba60ff,$00002882
1200 dc.l $60ff0000,$28baf210,$48002210,$32280004
1201 dc.l $02817fff,$ffff0c81,$3fff8000,$6c4e0c81
1202 dc.l $3fd78000,$6d00007c,$f23c4480,$3f800000
1203 dc.l $f20000a8,$f227e004,$f23c4500,$3f800000
1204 dc.l $f2000122,$f20008a3,$f21fd020,$f2000484
1205 dc.l $f2000420,$f227e001,$41d761ff,$fffffd66
1206 dc.l $dffc0000,$000c60ff,$0000280e,$f2000018
1207 dc.l $f23c4438,$3f800000,$f2d20000,$265af23a
1208 dc.l $4800b8ae,$22100281,$80000000,$00813f80
1209 dc.l $00002f01,$f2009000,$f21f4423,$60ff0000
1210 dc.l $27d8f200,$9000123c,$0003f210,$480060ff
1211 dc.l $000027be,$60ff0000,$2806f210,$48002210
1212 dc.l $32280004,$02817fff,$ffff0c81,$3fff8000
1213 dc.l $6c44f23c,$44803f80,$0000f200,$00a2f200
1214 dc.l $001af23c,$44223f80,$0000f200,$0420f200
1215 dc.l $00042f00,$4280f227,$e00141d7,$61ffffff
1216 dc.l $fcc4dffc,$0000000c,$f21f9000,$f2000022
1217 dc.l $60ff0000,$276cf200,$0018f23c,$44383f80
1218 dc.l $0000f2d2,$000025b0,$4a106a18,$f23a4800
1219 dc.l $b7f0f200,$9000f23c,$44220080,$000060ff
1220 dc.l $0000273e,$60ff0000,$2988f200,$9000f23a
1221 dc.l $4800b7de,$60ff0000,$27283fdc,$000082e3
1222 dc.l $08654361,$c4c60000,$00003fa5,$55555555
1223 dc.l $4cc13fc5,$55555555,$4a543f81,$11111117
1224 dc.l $43853fa5,$55555555,$4f5a3fc5,$55555555
1225 dc.l $55550000,$00000000,$00003ec7,$1de3a577
1226 dc.l $46823efa,$01a019d7,$cb683f2a,$01a01a01
1227 dc.l $9df33f56,$c16c16c1,$70e23f81,$11111111
1228 dc.l $11113fa5,$55555555,$55553ffc,$0000aaaa
1229 dc.l $aaaaaaaa,$aaab0000,$000048b0,$00000000
1230 dc.l $00003730,$00000000,$00003fff,$00008000
1231 dc.l $00000000,$00000000,$00003fff,$00008164
1232 dc.l $d1f3bc03,$07749f84,$1a9b3fff,$000082cd
1233 dc.l $8698ac2b,$a1d89fc1,$d5b93fff,$0000843a
1234 dc.l $28c3acde,$4048a072,$83693fff,$000085aa
1235 dc.l $c367cc48,$7b141fc5,$c95c3fff,$0000871f
1236 dc.l $61969e8d,$10101ee8,$5c9f3fff,$00008898
1237 dc.l $0e8092da,$85289fa2,$07293fff,$00008a14
1238 dc.l $d575496e,$fd9ca07b,$f9af3fff,$00008b95
1239 dc.l $c1e3ea8b,$d6e8a002,$0dcf3fff,$00008d1a
1240 dc.l $df5b7e5b,$a9e4205a,$63da3fff,$00008ea4
1241 dc.l $398b45cd,$53c01eb7,$00513fff,$00009031
1242 dc.l $dc431466,$b1dc1f6e,$b0293fff,$000091c3
1243 dc.l $d373ab11,$c338a078,$14943fff,$0000935a
1244 dc.l $2b2f13e6,$e92c9eb3,$19b03fff,$000094f4
1245 dc.l $efa8fef7,$09602017,$457d3fff,$00009694
1246 dc.l $2d372018,$5a001f11,$d5373fff,$00009837
1247 dc.l $f0518db8,$a9709fb9,$52dd3fff,$000099e0
1248 dc.l $459320b7,$fa641fe4,$30873fff,$00009b8d
1249 dc.l $39b9d54e,$55381fa2,$a8183fff,$00009d3e
1250 dc.l $d9a72cff,$b7501fde,$494d3fff,$00009ef5
1251 dc.l $326091a1,$11ac2050,$48903fff,$0000a0b0
1252 dc.l $510fb971,$4fc4a073,$691c3fff,$0000a270
1253 dc.l $43030c49,$68181f9b,$7a053fff,$0000a435
1254 dc.l $15ae09e6,$80a0a079,$71263fff,$0000a5fe
1255 dc.l $d6a9b151,$38eca071,$a1403fff,$0000a7cd
1256 dc.l $93b4e965,$3568204f,$62da3fff,$0000a9a1
1257 dc.l $5ab4ea7c,$0ef81f28,$3c4a3fff,$0000ab7a
1258 dc.l $39b5a93e,$d3389f9a,$7fdc3fff,$0000ad58
1259 dc.l $3eea42a1,$4ac8a05b,$3fac3fff,$0000af3b
1260 dc.l $78ad690a,$43741fdf,$26103fff,$0000b123
1261 dc.l $f581d2ac,$25909f70,$5f903fff,$0000b311
1262 dc.l $c412a911,$2488201f,$678a3fff,$0000b504
1263 dc.l $f333f9de,$64841f32,$fb133fff,$0000b6fd
1264 dc.l $91e328d1,$77902003,$8b303fff,$0000b8fb
1265 dc.l $af4762fb,$9ee8200d,$c3cc3fff,$0000baff
1266 dc.l $5ab2133e,$45fc9f8b,$2ae63fff,$0000bd08
1267 dc.l $a39f580c,$36c0a02b,$bf703fff,$0000bf17
1268 dc.l $99b67a73,$1084a00b,$f5183fff,$0000c12c
1269 dc.l $4cca6670,$9458a041,$dd413fff,$0000c346
1270 dc.l $ccda2497,$64089fdf,$137b3fff,$0000c567
1271 dc.l $2a115506,$dadc201f,$15683fff,$0000c78d
1272 dc.l $74c8abb9,$b15c1fc1,$3a2e3fff,$0000c9b9
1273 dc.l $bd866e2f,$27a4a03f,$8f033fff,$0000cbec
1274 dc.l $14fef272,$7c5c1ff4,$907d3fff,$0000ce24
1275 dc.l $8c151f84,$80e49e6e,$53e43fff,$0000d063
1276 dc.l $33daef2b,$25941fd6,$d45c3fff,$0000d2a8
1277 dc.l $1d91f12a,$e45ca076,$edb93fff,$0000d4f3
1278 dc.l $5aabcfed,$fa209fa6,$de213fff,$0000d744
1279 dc.l $fccad69d,$6af41ee6,$9a2f3fff,$0000d99d
1280 dc.l $15c278af,$d7b4207f,$439f3fff,$0000dbfb
1281 dc.l $b797daf2,$3754201e,$c2073fff,$0000de60
1282 dc.l $f4825e0e,$91249e8b,$e1753fff,$0000e0cc
1283 dc.l $deec2a94,$e1102003,$2c4b3fff,$0000e33f
1284 dc.l $8972be8a,$5a502004,$dff53fff,$0000e5b9
1285 dc.l $06e77c83,$48a81e72,$f47a3fff,$0000e839
1286 dc.l $6a503c4b,$dc681f72,$2f223fff,$0000eac0
1287 dc.l $c6e7dd24,$3930a017,$e9453fff,$0000ed4f
1288 dc.l $301ed994,$2b841f40,$1a5b3fff,$0000efe4
1289 dc.l $b99bdcda,$f5cc9fb9,$a9e33fff,$0000f281
1290 dc.l $773c59ff,$b1382074,$4c053fff,$0000f525
1291 dc.l $7d152486,$cc2c1f77,$3a193fff,$0000f7d0
1292 dc.l $df730ad1,$3bb81ffe,$90d53fff,$0000fa83
1293 dc.l $b2db722a,$033ca041,$ed223fff,$0000fd3e
1294 dc.l $0c0cf486,$c1741f85,$3f3a2210,$02817fff
1295 dc.l $00000c81,$3fbe0000,$6c0660ff,$00000108
1296 dc.l $32280004,$0c81400c,$b1676d06,$60ff0000
1297 dc.l $010cf210,$4800f200,$0080f23c,$442342b8
1298 dc.l $aa3bf227,$e00c2d7c,$00000000,$ff58f201
1299 dc.l $600043fa,$fbb6f201,$40002d41,$ff540281
1300 dc.l $0000003f,$e989d3c1,$222eff54,$ec810641
1301 dc.l $3fff3d7a,$fb06ff54,$f2000100,$f23c4423
1302 dc.l $bc317218,$f23a4923,$faf2f200,$0422f200
1303 dc.l $0822f200,$0080f200,$04a3f23c,$45003ab6
1304 dc.l $0b70f200,$0523f200,$0580f23c,$45a33c08
1305 dc.l $8895f23a,$5522fad4,$f23a55a2,$fad6f200
1306 dc.l $05233d41,$ff842d7c,$80000000,$ff8842ae
1307 dc.l $ff8cf200,$05a3f23c,$45223f00,$0000f200
1308 dc.l $01a3f200,$0523f200,$0c22f219,$4880f200
1309 dc.l $0822f200,$0423f21f,$d030f211,$4422f200
1310 dc.l $0422222e,$ff584a81,$6706f22e,$4823ff90
1311 dc.l $f2009000,$123c0000,$f22e4823,$ff8460ff
1312 dc.l $0000216e,$f210d080,$f2009000,$f23c4422
1313 dc.l $3f800000,$60ff0000,$21680c81,$400cb27c
1314 dc.l $6e66f210,$4800f200,$0080f23c,$442342b8
1315 dc.l $aa3bf227,$e00c2d7c,$00000001,$ff58f201
1316 dc.l $600043fa,$faa6f201,$40002d41,$ff540281
1317 dc.l $0000003f,$e989d3c1,$222eff54,$ec812d41
1318 dc.l $ff54e281,$93aeff54,$06413fff,$3d41ff90
1319 dc.l $2d7c8000,$0000ff94,$42aeff98,$222eff54
1320 dc.l $06413fff,$6000fed2,$4a106bff,$00001fbc
1321 dc.l $60ff0000,$20ae2f10,$02978000,$00000097
1322 dc.l $00800000,$f23c4400,$3f800000,$f2009000
1323 dc.l $f21f4422,$60ff0000,$20c82210,$02817fff
1324 dc.l $00000c81,$3ffd0000,$6c0660ff,$0000015e
1325 dc.l $32280004,$0c814004,$c2156f06,$60ff0000
1326 dc.l $026cf210,$4800f200,$0080f23c,$442342b8
1327 dc.l $aa3bf227,$e00cf201,$600043fa,$f9eef201
1328 dc.l $40002d41,$ff540281,$0000003f,$e989d3c1
1329 dc.l $222eff54,$ec812d41,$ff54f200,$0100f23c
1330 dc.l $4423bc31,$7218f23a,$4923f930,$f2000422
1331 dc.l $f2000822,$06413fff,$f2000080,$f20004a3
1332 dc.l $f23c4500,$3950097b,$f2000523,$f2000580
1333 dc.l $f23c45a3,$3ab60b6a,$f23a5522,$f91ef23a
1334 dc.l $55a2f920,$3d41ff84,$2d7c8000,$0000ff88
1335 dc.l $42aeff8c,$f2000523,$222eff54,$4441f200
1336 dc.l $05a30641,$3ffff23a,$5522f900,$f23c45a2
1337 dc.l $3f000000,$f2000523,$00418000,$3d41ff90
1338 dc.l $2d7c8000,$0000ff94,$42aeff98,$f2000ca3
1339 dc.l $f2000123,$f2000422,$f2000822,$f21fd030
1340 dc.l $f2114823,$222eff54,$0c810000,$003f6f1a
1341 dc.l $f2294480,$000cf22e,$48a2ff90,$f2000422
1342 dc.l $f2114822,$60ff0000,$00340c81,$fffffffd
1343 dc.l $6c16f229,$4422000c,$f2114822,$f22e4822
1344 dc.l $ff9060ff,$00000016,$f2194880,$f2114422
1345 dc.l $f22e48a2,$ff90f200,$0422f200,$9000f22e
1346 dc.l $4823ff84,$60ff0000,$1f500c81,$3fbe0000
1347 dc.l $6c6c0c81,$00330000,$6d2c2d7c,$80010000
1348 dc.l $ff842d7c,$80000000,$ff8842ae,$ff8cf210
1349 dc.l $4800f200,$9000123c,$0002f22e,$4822ff84
1350 dc.l $60ff0000,$1f0cf210,$4800f23a,$5423f86c
1351 dc.l $2d7c8001,$0000ff84,$2d7c8000,$0000ff88
1352 dc.l $42aeff8c,$f22e4822,$ff84f200,$9000123c
1353 dc.l $0000f23a,$5423f84c,$60ff0000,$1ed4f210
1354 dc.l $4800f200,$0023f227,$e00cf23c,$44802f30
1355 dc.l $caa8f200,$00a3f23c,$4500310f,$8290f23c
1356 dc.l $44a232d7,$3220f200,$0123f200,$00a3f23c
1357 dc.l $45223493,$f281f23a,$54a2f7c0,$f2000123
1358 dc.l $f20000a3,$f23a5522,$f7baf23a,$54a2f7bc
1359 dc.l $f2000123,$f20000a3,$f23a5522,$f7b6f23a
1360 dc.l $54a2f7b8,$f2000123,$f20000a3,$f23a5522
1361 dc.l $f7b2f23a,$48a2f7b4,$f2000123,$f20000a3
1362 dc.l $f2000123,$f21048a3,$f23c4423,$3f000000
1363 dc.l $f20008a2,$f21fd030,$f2000422,$f2009000
1364 dc.l $f2104822,$60ff0000,$1e302210,$0c810000
1365 dc.l $00006e00,$fbacf23c,$4400bf80,$0000f200
1366 dc.l $9000f23c,$44220080,$000060ff,$00001e1a
1367 dc.l $60ff0000,$1e4a3028,$00000880,$000f0440
1368 dc.l $3ffff200,$50006d02,$4e751d7c,$0008ff64
1369 dc.l $4e7561ff,$00002342,$44400440,$3ffff200
1370 dc.l $50001d7c,$0008ff64,$4e753028,$00000040
1371 dc.l $7fff0880,$000e2d68,$0004ff88,$2d680008
1372 dc.l $ff8c3d40,$ff84f22e,$4800ff84,$6b024e75
1373 dc.l $1d7c0008,$ff644e75,$61ff0000,$22fc60ca
1374 dc.l $7ffb0000,$80000000,$00000000,$00000000
1375 dc.l $f2104800,$22103228,$00040281,$7fffffff
1376 dc.l $0c81400c,$b1676e42,$f2000018,$2f004280
1377 dc.l $f227e001,$41d761ff,$fffffad2,$dffc0000
1378 dc.l $000cf23c,$44233f00,$0000201f,$f23c4480
1379 dc.l $3e800000,$f20000a0,$f2009000,$123c0002
1380 dc.l $f2000422,$60ff0000,$1d280c81,$400cb2b3
1381 dc.l $6e3cf200,$0018f23a,$5428adb6,$f23a5428
1382 dc.l $adb82f00,$4280f227,$e00141d7,$61ffffff
1383 dc.l $fa7cdffc,$0000000c,$201ff200,$9000123c
1384 dc.l $0000f23a,$4823ff5a,$60ff0000,$1ce460ff
1385 dc.l $00001cb0,$f23c4400,$3f800000,$f2009000
1386 dc.l $f23c4422,$00800000,$60ff0000,$1cd4f210
1387 dc.l $48002210,$32280004,$22410281,$7fffffff
1388 dc.l $0c81400c,$b1676e62,$f2000018,$48e78040
1389 dc.l $f227e001,$41d74280,$61ffffff,$fbe0dffc
1390 dc.l $0000000c,$f23c9000,$00000000,$4cdf0201
1391 dc.l $f2000080,$f23c44a2,$3f800000,$f2276800
1392 dc.l $f2000420,$22090281,$80000000,$00813f00
1393 dc.l $0000f21f,$48222f01,$f2009000,$123c0000
1394 dc.l $f21f4423,$60ff0000,$1c480c81,$400cb2b3
1395 dc.l $6eff0000,$1bc2f200,$0018f23a,$5428acd2
1396 dc.l $2f3c0000,$00002f3c,$80000000,$22090281
1397 dc.l $80000000,$00817ffb,$00002f01,$f23a5428
1398 dc.l $acb82f00,$4280f227,$e00141d7,$61ffffff
1399 dc.l $f97cdffc,$0000000c,$201ff200,$9000123c
1400 dc.l $0000f21f,$482360ff,$00001be6,$60ff0000
1401 dc.l $1c2ef210,$4800f22e,$6800ff84,$22103228
1402 dc.l $00042d41,$ff840281,$7fffffff,$0c813fd7
1403 dc.l $80006d00,$00740c81,$3fffddce,$6e00006a
1404 dc.l $222eff84,$2d41ff5c,$02817fff,$00000681
1405 dc.l $00010000,$2d41ff84,$02ae8000,$0000ff5c
1406 dc.l $f22e4800,$ff842f00,$4280f227,$e00141d7
1407 dc.l $61ffffff,$fac8dffc,$0000000c,$201ff200
1408 dc.l $0080f23c,$44a24000,$0000222e,$ff5cf22e
1409 dc.l $6880ff84,$b3aeff84,$f2009000,$f22e4820
1410 dc.l $ff8460ff,$00001b52,$0c813fff,$80006d00
1411 dc.l $00880c81,$40048aa1,$6e000092,$222eff84
1412 dc.l $2d41ff5c,$02817fff,$00000681,$00010000
1413 dc.l $2d41ff84,$02ae8000,$0000ff5c,$222eff5c
1414 dc.l $f22e4800,$ff842f00,$4280f227,$e00141d7
1415 dc.l $61ffffff,$f878dffc,$0000000c,$201f222e
1416 dc.l $ff5cf23c,$44223f80,$00000a81,$c0000000
1417 dc.l $f2014480,$f20000a0,$222eff5c,$00813f80
1418 dc.l $0000f201,$4400f200,$9000123c,$0002f200
1419 dc.l $042260ff,$00001ac2,$f2009000,$123c0003
1420 dc.l $f22e4800,$ff8460ff,$00001aa6,$222eff84
1421 dc.l $02818000,$00000081,$3f800000,$f2014400
1422 dc.l $02818000,$00000a81,$80800000,$f2009000
1423 dc.l $f2014422,$60ff0000,$1a8060ff,$00001ac0
1424 dc.l $3ffe0000,$b17217f7,$d1cf79ac,$00000000
1425 dc.l $3f800000,$00000000,$7f800000,$bf800000
1426 dc.l $3fc2499a,$b5e4040b,$bfc555b5,$848cb7db
1427 dc.l $3fc99999,$987d8730,$bfcfffff,$ff6f7e97
1428 dc.l $3fd55555,$555555a4,$bfe00000,$00000008
1429 dc.l $3f175496,$add7dad6,$3f3c71c2,$fe80c7e0
1430 dc.l $3f624924,$928bccff,$3f899999,$999995ec
1431 dc.l $3fb55555,$55555555,$40000000,$00000000
1432 dc.l $3f990000,$80000000,$00000000,$00000000
1433 dc.l $3ffe0000,$fe03f80f,$e03f80fe,$00000000
1434 dc.l $3ff70000,$ff015358,$833c47e2,$00000000
1435 dc.l $3ffe0000,$fa232cf2,$52138ac0,$00000000
1436 dc.l $3ff90000,$bdc8d83e,$ad88d549,$00000000
1437 dc.l $3ffe0000,$f6603d98,$0f6603da,$00000000
1438 dc.l $3ffa0000,$9cf43dcf,$f5eafd48,$00000000
1439 dc.l $3ffe0000,$f2b9d648,$0f2b9d65,$00000000
1440 dc.l $3ffa0000,$da16eb88,$cb8df614,$00000000
1441 dc.l $3ffe0000,$ef2eb71f,$c4345238,$00000000
1442 dc.l $3ffb0000,$8b29b775,$1bd70743,$00000000
1443 dc.l $3ffe0000,$ebbdb2a5,$c1619c8c,$00000000
1444 dc.l $3ffb0000,$a8d839f8,$30c1fb49,$00000000
1445 dc.l $3ffe0000,$e865ac7b,$7603a197,$00000000
1446 dc.l $3ffb0000,$c61a2eb1,$8cd907ad,$00000000
1447 dc.l $3ffe0000,$e525982a,$f70c880e,$00000000
1448 dc.l $3ffb0000,$e2f2a47a,$de3a18af,$00000000
1449 dc.l $3ffe0000,$e1fc780e,$1fc780e2,$00000000
1450 dc.l $3ffb0000,$ff64898e,$df55d551,$00000000
1451 dc.l $3ffe0000,$dee95c4c,$a037ba57,$00000000
1452 dc.l $3ffc0000,$8db956a9,$7b3d0148,$00000000
1453 dc.l $3ffe0000,$dbeb61ee,$d19c5958,$00000000
1454 dc.l $3ffc0000,$9b8fe100,$f47ba1de,$00000000
1455 dc.l $3ffe0000,$d901b203,$6406c80e,$00000000
1456 dc.l $3ffc0000,$a9372f1d,$0da1bd17,$00000000
1457 dc.l $3ffe0000,$d62b80d6,$2b80d62c,$00000000
1458 dc.l $3ffc0000,$b6b07f38,$ce90e46b,$00000000
1459 dc.l $3ffe0000,$d3680d36,$80d3680d,$00000000
1460 dc.l $3ffc0000,$c3fd0329,$06488481,$00000000
1461 dc.l $3ffe0000,$d0b69fcb,$d2580d0b,$00000000
1462 dc.l $3ffc0000,$d11de0ff,$15ab18ca,$00000000
1463 dc.l $3ffe0000,$ce168a77,$25080ce1,$00000000
1464 dc.l $3ffc0000,$de1433a1,$6c66b150,$00000000
1465 dc.l $3ffe0000,$cb8727c0,$65c393e0,$00000000
1466 dc.l $3ffc0000,$eae10b5a,$7ddc8add,$00000000
1467 dc.l $3ffe0000,$c907da4e,$871146ad,$00000000
1468 dc.l $3ffc0000,$f7856e5e,$e2c9b291,$00000000
1469 dc.l $3ffe0000,$c6980c69,$80c6980c,$00000000
1470 dc.l $3ffd0000,$82012ca5,$a68206d7,$00000000
1471 dc.l $3ffe0000,$c4372f85,$5d824ca6,$00000000
1472 dc.l $3ffd0000,$882c5fcd,$7256a8c5,$00000000
1473 dc.l $3ffe0000,$c1e4bbd5,$95f6e947,$00000000
1474 dc.l $3ffd0000,$8e44c60b,$4ccfd7de,$00000000
1475 dc.l $3ffe0000,$bfa02fe8,$0bfa02ff,$00000000
1476 dc.l $3ffd0000,$944ad09e,$f4351af6,$00000000
1477 dc.l $3ffe0000,$bd691047,$07661aa3,$00000000
1478 dc.l $3ffd0000,$9a3eecd4,$c3eaa6b2,$00000000
1479 dc.l $3ffe0000,$bb3ee721,$a54d880c,$00000000
1480 dc.l $3ffd0000,$a0218434,$353f1de8,$00000000
1481 dc.l $3ffe0000,$b92143fa,$36f5e02e,$00000000
1482 dc.l $3ffd0000,$a5f2fcab,$bbc506da,$00000000
1483 dc.l $3ffe0000,$b70fbb5a,$19be3659,$00000000
1484 dc.l $3ffd0000,$abb3b8ba,$2ad362a5,$00000000
1485 dc.l $3ffe0000,$b509e68a,$9b94821f,$00000000
1486 dc.l $3ffd0000,$b1641795,$ce3ca97b,$00000000
1487 dc.l $3ffe0000,$b30f6352,$8917c80b,$00000000
1488 dc.l $3ffd0000,$b7047551,$5d0f1c61,$00000000
1489 dc.l $3ffe0000,$b11fd3b8,$0b11fd3c,$00000000
1490 dc.l $3ffd0000,$bc952afe,$ea3d13e1,$00000000
1491 dc.l $3ffe0000,$af3addc6,$80af3ade,$00000000
1492 dc.l $3ffd0000,$c2168ed0,$f458ba4a,$00000000
1493 dc.l $3ffe0000,$ad602b58,$0ad602b6,$00000000
1494 dc.l $3ffd0000,$c788f439,$b3163bf1,$00000000
1495 dc.l $3ffe0000,$ab8f69e2,$8359cd11,$00000000
1496 dc.l $3ffd0000,$ccecac08,$bf04565d,$00000000
1497 dc.l $3ffe0000,$a9c84a47,$a07f5638,$00000000
1498 dc.l $3ffd0000,$d2420487,$2dd85160,$00000000
1499 dc.l $3ffe0000,$a80a80a8,$0a80a80b,$00000000
1500 dc.l $3ffd0000,$d7894992,$3bc3588a,$00000000
1501 dc.l $3ffe0000,$a655c439,$2d7b73a8,$00000000
1502 dc.l $3ffd0000,$dcc2c4b4,$9887dacc,$00000000
1503 dc.l $3ffe0000,$a4a9cf1d,$96833751,$00000000
1504 dc.l $3ffd0000,$e1eebd3e,$6d6a6b9e,$00000000
1505 dc.l $3ffe0000,$a3065e3f,$ae7cd0e0,$00000000
1506 dc.l $3ffd0000,$e70d785c,$2f9f5bdc,$00000000
1507 dc.l $3ffe0000,$a16b312e,$a8fc377d,$00000000
1508 dc.l $3ffd0000,$ec1f392c,$5179f283,$00000000
1509 dc.l $3ffe0000,$9fd809fd,$809fd80a,$00000000
1510 dc.l $3ffd0000,$f12440d3,$e36130e6,$00000000
1511 dc.l $3ffe0000,$9e4cad23,$dd5f3a20,$00000000
1512 dc.l $3ffd0000,$f61cce92,$346600bb,$00000000
1513 dc.l $3ffe0000,$9cc8e160,$c3fb19b9,$00000000
1514 dc.l $3ffd0000,$fb091fd3,$8145630a,$00000000
1515 dc.l $3ffe0000,$9b4c6f9e,$f03a3caa,$00000000
1516 dc.l $3ffd0000,$ffe97042,$bfa4c2ad,$00000000
1517 dc.l $3ffe0000,$99d722da,$bde58f06,$00000000
1518 dc.l $3ffe0000,$825efced,$49369330,$00000000
1519 dc.l $3ffe0000,$9868c809,$868c8098,$00000000
1520 dc.l $3ffe0000,$84c37a7a,$b9a905c9,$00000000
1521 dc.l $3ffe0000,$97012e02,$5c04b809,$00000000
1522 dc.l $3ffe0000,$87224c2e,$8e645fb7,$00000000
1523 dc.l $3ffe0000,$95a02568,$095a0257,$00000000
1524 dc.l $3ffe0000,$897b8cac,$9f7de298,$00000000
1525 dc.l $3ffe0000,$94458094,$45809446,$00000000
1526 dc.l $3ffe0000,$8bcf55de,$c4cd05fe,$00000000
1527 dc.l $3ffe0000,$92f11384,$0497889c,$00000000
1528 dc.l $3ffe0000,$8e1dc0fb,$89e125e5,$00000000
1529 dc.l $3ffe0000,$91a2b3c4,$d5e6f809,$00000000
1530 dc.l $3ffe0000,$9066e68c,$955b6c9b,$00000000
1531 dc.l $3ffe0000,$905a3863,$3e06c43b,$00000000
1532 dc.l $3ffe0000,$92aade74,$c7be59e0,$00000000
1533 dc.l $3ffe0000,$8f1779d9,$fdc3a219,$00000000
1534 dc.l $3ffe0000,$94e9bff6,$15845643,$00000000
1535 dc.l $3ffe0000,$8dda5202,$37694809,$00000000
1536 dc.l $3ffe0000,$9723a1b7,$20134203,$00000000
1537 dc.l $3ffe0000,$8ca29c04,$6514e023,$00000000
1538 dc.l $3ffe0000,$995899c8,$90eb8990,$00000000
1539 dc.l $3ffe0000,$8b70344a,$139bc75a,$00000000
1540 dc.l $3ffe0000,$9b88bdaa,$3a3dae2f,$00000000
1541 dc.l $3ffe0000,$8a42f870,$5669db46,$00000000
1542 dc.l $3ffe0000,$9db4224f,$ffe1157c,$00000000
1543 dc.l $3ffe0000,$891ac73a,$e9819b50,$00000000
1544 dc.l $3ffe0000,$9fdadc26,$8b7a12da,$00000000
1545 dc.l $3ffe0000,$87f78087,$f78087f8,$00000000
1546 dc.l $3ffe0000,$a1fcff17,$ce733bd4,$00000000
1547 dc.l $3ffe0000,$86d90544,$7a34acc6,$00000000
1548 dc.l $3ffe0000,$a41a9e8f,$5446fb9f,$00000000
1549 dc.l $3ffe0000,$85bf3761,$2cee3c9b,$00000000
1550 dc.l $3ffe0000,$a633cd7e,$6771cd8b,$00000000
1551 dc.l $3ffe0000,$84a9f9c8,$084a9f9d,$00000000
1552 dc.l $3ffe0000,$a8489e60,$0b435a5e,$00000000
1553 dc.l $3ffe0000,$83993052,$3fbe3368,$00000000
1554 dc.l $3ffe0000,$aa59233c,$cca4bd49,$00000000
1555 dc.l $3ffe0000,$828cbfbe,$b9a020a3,$00000000
1556 dc.l $3ffe0000,$ac656dae,$6bcc4985,$00000000
1557 dc.l $3ffe0000,$81848da8,$faf0d277,$00000000
1558 dc.l $3ffe0000,$ae6d8ee3,$60bb2468,$00000000
1559 dc.l $3ffe0000,$80808080,$80808081,$00000000
1560 dc.l $3ffe0000,$b07197a2,$3c46c654,$00000000
1561 dc.l $f2104800,$2d7c0000,$0000ff54,$22103228
1562 dc.l $00042d50,$ff842d68,$0004ff88,$2d680008
1563 dc.l $ff8c0c81,$00000000,$6d000182,$0c813ffe
1564 dc.l $f07d6d0a,$0c813fff,$88416f00,$00e2e081
1565 dc.l $e0810481,$00003fff,$d2aeff54,$41faf7b2
1566 dc.l $f2014080,$2d7c3fff,$0000ff84,$2d6eff88
1567 dc.l $ff9402ae,$fe000000,$ff9400ae,$01000000
1568 dc.l $ff94222e,$ff940281,$7e000000,$e081e081
1569 dc.l $e881d1c1,$f22e4800,$ff842d7c,$3fff0000
1570 dc.l $ff9042ae,$ff98f22e,$4828ff90,$f227e00c
1571 dc.l $f2104823,$f23a48a3,$f6c8f200,$0100f200
1572 dc.l $0923f22e,$6880ff84,$f2000980,$f2000880
1573 dc.l $f23a54a3,$f6ccf23a,$5523f6ce,$f23a54a2
1574 dc.l $f6d0f23a,$5522f6d2,$f2000ca3,$f2000d23
1575 dc.l $f23a54a2,$f6ccf23a,$5522f6ce,$f2000ca3
1576 dc.l $d1fc0000,$0010f200,$0d23f200,$00a3f200
1577 dc.l $0822f210,$48a2f21f,$d030f200,$0422f200
1578 dc.l $9000f22e,$4822ff84,$60ff0000,$10ccf23c
1579 dc.l $58380001,$f2c10000,$1318f200,$0080f23a
1580 dc.l $44a8f64e,$f23a4422,$f648f200,$04a2f200
1581 dc.l $00a0f227,$e00cf200,$0400f200,$0023f22e
1582 dc.l $6880ff84,$f2000080,$f20004a3,$f23a5580
1583 dc.l $f660f23a,$5500f662,$f20005a3,$f2000523
1584 dc.l $f23a55a2,$f65cf23a,$5522f65e,$f2000ca3
1585 dc.l $f2000123,$f23a54a2,$f658f22e,$4823ff84
1586 dc.l $f20008a2,$f21fd030,$f2000423,$f2009000
1587 dc.l $f22e4822,$ff8460ff,$0000103e,$60ff0000
1588 dc.l $0e962d7c,$ffffff9c,$ff5448e7,$3f002610
1589 dc.l $28280004,$2a280008,$42824a84,$66342805
1590 dc.l $42857420,$4286edc4,$6000edac,$d4862d43
1591 dc.l $ff842d44,$ff882d45,$ff8c4482,$2d42ff54
1592 dc.l $f22e4800,$ff844cdf,$00fc41ee,$ff846000
1593 dc.l $fe0c4286,$edc46000,$2406edac,$2e05edad
1594 dc.l $44860686,$00000020,$ecaf8887,$2d43ff84
1595 dc.l $2d44ff88,$2d45ff8c,$44822d42,$ff54f22e
1596 dc.l $4800ff84,$4cdf00fc,$41eeff84,$6000fdce
1597 dc.l $f2104800,$f2000018,$f23a4838,$f5a4f292
1598 dc.l $0014f200,$9000123c,$0003f210,$480060ff
1599 dc.l $00000f7e,$f2104800,$2d7c0000,$0000ff54
1600 dc.l $f2000080,$f23a4422,$f508f22e,$6800ff84
1601 dc.l $3d6eff88,$ff86222e,$ff840c81,$00000000
1602 dc.l $6f0000da,$0c813ffe,$80006d00,$fda20c81
1603 dc.l $3fffc000,$6e00fd98,$0c813ffe,$f07d6d00
1604 dc.l $001a0c81,$3fff8841,$6e000010,$f20004a2
1605 dc.l $f23a4422,$f4bc6000,$fe762d6e,$ff88ff94
1606 dc.l $02aefe00,$0000ff94,$00ae0100,$0000ff94
1607 dc.l $0c813fff,$80006c44,$f23a4400,$f4fc2d7c
1608 dc.l $3fff0000,$ff9042ae,$ff98f22e,$4828ff90
1609 dc.l $222eff94,$02817e00,$0000e081,$e081e881
1610 dc.l $f20004a2,$f227e00c,$f2000422,$41faf4e2
1611 dc.l $d1c1f23a,$4480f466,$6000fd76,$f23a4400
1612 dc.l $f4502d7c,$3fff0000,$ff9042ae,$ff98f22e
1613 dc.l $4828ff90,$222eff94,$02817e00,$0000e081
1614 dc.l $e081e881,$f2000422,$f227e00c,$41faf4a2
1615 dc.l $d1c1f23a,$4480f41e,$6000fd36,$0c810000
1616 dc.l $00006d10,$f23a4400,$f414f200,$900060ff
1617 dc.l $00000c4e,$f23a4400,$f3fcf200,$900060ff
1618 dc.l $00000cb4,$60ff0000,$0e962210,$32280004
1619 dc.l $02817fff,$ffff0c81,$3fff8000,$6c56f210
1620 dc.l $4818f200,$0080f200,$049af200,$0022f23c
1621 dc.l $44a23f80,$0000f200,$04202210,$02818000
1622 dc.l $00000081,$3f000000,$2f012f00,$4280f227
1623 dc.l $e00141d7,$61ffffff,$fe5adffc,$0000000c
1624 dc.l $201ff200,$9000123c,$0000f21f,$442360ff
1625 dc.l $00000dde,$f2104818,$f23c4438,$3f800000
1626 dc.l $f2d20000,$0c3260ff,$00000bb6,$60ff0000
1627 dc.l $0e0e3ffd,$0000de5b,$d8a93728,$71950000
1628 dc.l $00003fff,$0000b8aa,$3b295c17,$f0bc0000
1629 dc.l $0000f23c,$58000001,$f2104838,$f2c10000
1630 dc.l $0ff02210,$6d000090,$2f004280,$61ffffff
1631 dc.l $fba2f21f,$9000f23a,$4823ffb8,$60ff0000
1632 dc.l $0d782210,$6d000070,$2f004280,$61ffffff
1633 dc.l $fd34f21f,$9000f23a,$4823ff98,$60ff0000
1634 dc.l $0d682210,$6d000050,$22280008,$662e2228
1635 dc.l $00040281,$7fffffff,$66223210,$02810000
1636 dc.l $7fff0481,$00003fff,$67ff0000,$0f84f200
1637 dc.l $9000f201,$400060ff,$00000d1e,$2f004280
1638 dc.l $61ffffff,$fb2ef21f,$9000f23a,$4823ff54
1639 dc.l $60ff0000,$0d0460ff,$00000b5c,$22106d00
1640 dc.l $fff62f00,$428061ff,$fffffcba,$f21f9000
1641 dc.l $f23a4823,$ff2e60ff,$00000cee,$406a934f
1642 dc.l $0979a371,$3f734413,$509f8000,$bfcd0000
1643 dc.l $c0219dc1,$da994fd2,$00000000,$40000000
1644 dc.l $935d8ddd,$aaa8ac17,$00000000,$3ffe0000
1645 dc.l $b17217f7,$d1cf79ac,$00000000,$3f56c16d
1646 dc.l $6f7bd0b2,$3f811112,$302c712c,$3fa55555
1647 dc.l $55554cc1,$3fc55555,$55554a54,$3fe00000
1648 dc.l $00000000,$00000000,$00000000,$3fff0000
1649 dc.l $80000000,$00000000,$3f738000,$3fff0000
1650 dc.l $8164d1f3,$bc030773,$3fbef7ca,$3fff0000
1651 dc.l $82cd8698,$ac2ba1d7,$3fbdf8a9,$3fff0000
1652 dc.l $843a28c3,$acde4046,$3fbcd7c9,$3fff0000
1653 dc.l $85aac367,$cc487b15,$bfbde8da,$3fff0000
1654 dc.l $871f6196,$9e8d1010,$3fbde85c,$3fff0000
1655 dc.l $88980e80,$92da8527,$3fbebbf1,$3fff0000
1656 dc.l $8a14d575,$496efd9a,$3fbb80ca,$3fff0000
1657 dc.l $8b95c1e3,$ea8bd6e7,$bfba8373,$3fff0000
1658 dc.l $8d1adf5b,$7e5ba9e6,$bfbe9670,$3fff0000
1659 dc.l $8ea4398b,$45cd53c0,$3fbdb700,$3fff0000
1660 dc.l $9031dc43,$1466b1dc,$3fbeeeb0,$3fff0000
1661 dc.l $91c3d373,$ab11c336,$3fbbfd6d,$3fff0000
1662 dc.l $935a2b2f,$13e6e92c,$bfbdb319,$3fff0000
1663 dc.l $94f4efa8,$fef70961,$3fbdba2b,$3fff0000
1664 dc.l $96942d37,$20185a00,$3fbe91d5,$3fff0000
1665 dc.l $9837f051,$8db8a96f,$3fbe8d5a,$3fff0000
1666 dc.l $99e04593,$20b7fa65,$bfbcde7b,$3fff0000
1667 dc.l $9b8d39b9,$d54e5539,$bfbebaaf,$3fff0000
1668 dc.l $9d3ed9a7,$2cffb751,$bfbd86da,$3fff0000
1669 dc.l $9ef53260,$91a111ae,$bfbebedd,$3fff0000
1670 dc.l $a0b0510f,$b9714fc2,$3fbcc96e,$3fff0000
1671 dc.l $a2704303,$0c496819,$bfbec90b,$3fff0000
1672 dc.l $a43515ae,$09e6809e,$3fbbd1db,$3fff0000
1673 dc.l $a5fed6a9,$b15138ea,$3fbce5eb,$3fff0000
1674 dc.l $a7cd93b4,$e965356a,$bfbec274,$3fff0000
1675 dc.l $a9a15ab4,$ea7c0ef8,$3fbea83c,$3fff0000
1676 dc.l $ab7a39b5,$a93ed337,$3fbecb00,$3fff0000
1677 dc.l $ad583eea,$42a14ac6,$3fbe9301,$3fff0000
1678 dc.l $af3b78ad,$690a4375,$bfbd8367,$3fff0000
1679 dc.l $b123f581,$d2ac2590,$bfbef05f,$3fff0000
1680 dc.l $b311c412,$a9112489,$3fbdfb3c,$3fff0000
1681 dc.l $b504f333,$f9de6484,$3fbeb2fb,$3fff0000
1682 dc.l $b6fd91e3,$28d17791,$3fbae2cb,$3fff0000
1683 dc.l $b8fbaf47,$62fb9ee9,$3fbcdc3c,$3fff0000
1684 dc.l $baff5ab2,$133e45fb,$3fbee9aa,$3fff0000
1685 dc.l $bd08a39f,$580c36bf,$bfbeaefd,$3fff0000
1686 dc.l $bf1799b6,$7a731083,$bfbcbf51,$3fff0000
1687 dc.l $c12c4cca,$66709456,$3fbef88a,$3fff0000
1688 dc.l $c346ccda,$24976407,$3fbd83b2,$3fff0000
1689 dc.l $c5672a11,$5506dadd,$3fbdf8ab,$3fff0000
1690 dc.l $c78d74c8,$abb9b15d,$bfbdfb17,$3fff0000
1691 dc.l $c9b9bd86,$6e2f27a3,$bfbefe3c,$3fff0000
1692 dc.l $cbec14fe,$f2727c5d,$bfbbb6f8,$3fff0000
1693 dc.l $ce248c15,$1f8480e4,$bfbcee53,$3fff0000
1694 dc.l $d06333da,$ef2b2595,$bfbda4ae,$3fff0000
1695 dc.l $d2a81d91,$f12ae45a,$3fbc9124,$3fff0000
1696 dc.l $d4f35aab,$cfedfa1f,$3fbeb243,$3fff0000
1697 dc.l $d744fcca,$d69d6af4,$3fbde69a,$3fff0000
1698 dc.l $d99d15c2,$78afd7b6,$bfb8bc61,$3fff0000
1699 dc.l $dbfbb797,$daf23755,$3fbdf610,$3fff0000
1700 dc.l $de60f482,$5e0e9124,$bfbd8be1,$3fff0000
1701 dc.l $e0ccdeec,$2a94e111,$3fbacb12,$3fff0000
1702 dc.l $e33f8972,$be8a5a51,$3fbb9bfe,$3fff0000
1703 dc.l $e5b906e7,$7c8348a8,$3fbcf2f4,$3fff0000
1704 dc.l $e8396a50,$3c4bdc68,$3fbef22f,$3fff0000
1705 dc.l $eac0c6e7,$dd24392f,$bfbdbf4a,$3fff0000
1706 dc.l $ed4f301e,$d9942b84,$3fbec01a,$3fff0000
1707 dc.l $efe4b99b,$dcdaf5cb,$3fbe8cac,$3fff0000
1708 dc.l $f281773c,$59ffb13a,$bfbcbb3f,$3fff0000
1709 dc.l $f5257d15,$2486cc2c,$3fbef73a,$3fff0000
1710 dc.l $f7d0df73,$0ad13bb9,$bfb8b795,$3fff0000
1711 dc.l $fa83b2db,$722a033a,$3fbef84b,$3fff0000
1712 dc.l $fd3e0c0c,$f486c175,$bfbef581,$f210d080
1713 dc.l $22103228,$0004f22e,$6800ff84,$02817fff
1714 dc.l $ffff0c81,$3fb98000,$6c046000,$00880c81
1715 dc.l $400d80c0,$6f046000,$007cf200,$0080f23c
1716 dc.l $44a34280,$0000f22e,$6080ff54,$2f0243fa
1717 dc.l $fbbcf22e,$4080ff54,$222eff54,$24010281
1718 dc.l $0000003f,$e981d3c1,$ec822202,$e2819481
1719 dc.l $06820000,$3ffff227,$e00cf23c,$44a33c80
1720 dc.l $00002d59,$ff842d59,$ff882d59,$ff8c3d59
1721 dc.l $ff90f200,$04283d59,$ff94426e,$ff9642ae
1722 dc.l $ff98d36e,$ff84f23a,$4823fb22,$d36eff90
1723 dc.l $60000100,$0c813fff,$80006e12,$f2009000
1724 dc.l $f23c4422,$3f800000,$60ff0000,$07b4222e
1725 dc.l $ff840c81,$00000000,$6d0660ff,$00000764
1726 dc.l $60ff0000,$0666f200,$9000f23c,$44003f80
1727 dc.l $00002210,$00810080,$0001f201,$442260ff
1728 dc.l $0000077e,$f210d080,$22103228,$0004f22e
1729 dc.l $6800ff84,$02817fff,$ffff0c81,$3fb98000
1730 dc.l $6c046000,$ff900c81,$400b9b07,$6f046000
1731 dc.l $ff84f200,$0080f23a,$54a3fa62,$f22e6080
1732 dc.l $ff542f02,$43fafac6,$f22e4080,$ff54222e
1733 dc.l $ff542401,$02810000,$003fe981,$d3c1ec82
1734 dc.l $2202e281,$94810682,$00003fff,$f227e00c
1735 dc.l $f2000500,$f23a54a3,$fa2c2d59,$ff84f23a
1736 dc.l $4923fa2a,$2d59ff88,$2d59ff8c,$f2000428
1737 dc.l $3d59ff90,$f2000828,$3d59ff94,$426eff96
1738 dc.l $42aeff98,$f23a4823,$fa14d36e,$ff84d36e
1739 dc.l $ff90f200,$0080f200,$04a3f23a,$5500fa1e
1740 dc.l $f23a5580,$fa20f200,$0523f200,$05a3f23a
1741 dc.l $5522fa1a,$f23a55a2,$fa1cf200,$0523f200
1742 dc.l $05a3f23a,$5522fa16,$f20001a3,$f2000523
1743 dc.l $f2000c22,$f2000822,$f21fd030,$f22e4823
1744 dc.l $ff84f22e,$4822ff90,$f22e4822,$ff84f200
1745 dc.l $90003d42,$ff84241f,$2d7c8000,$0000ff88
1746 dc.l $42aeff8c,$123c0000,$f22e4823,$ff8460ff
1747 dc.l $0000063e,$f2009000,$f23c4400,$3f800000
1748 dc.l $22100081,$00800001,$f2014422,$60ff0000
1749 dc.l $06302f00,$32290000,$5beeff54,$02810000
1750 dc.l $7fff3028,$00000240,$7fff0c40,$3fff6d00
1751 dc.l $00c00c40,$400c6e00,$00a4f228,$48030000
1752 dc.l $f2006000,$f23c8800,$00000000,$4a290004
1753 dc.l $6b5e2f00,$3d690000,$ff842d69,$0004ff88
1754 dc.l $2d690008,$ff8c41ee,$ff8461ff,$00000b2a
1755 dc.l $4480d09f,$f22ed080,$ff840c40,$c0016c36
1756 dc.l $f21f9000,$223c8000,$00000480,$ffffc001
1757 dc.l $44800c00,$00206c0a,$e0a942a7,$2f0142a7
1758 dc.l $60280400,$0020e0a9,$2f0142a7,$42a7601a
1759 dc.l $f229d080,$0000f21f,$90000640,$3fff4840
1760 dc.l $42a72f3c,$80000000,$2f00f200,$b000123c
1761 dc.l $0000f21f,$482360ff,$0000054c,$201fc149
1762 dc.l $4a290000,$6bff0000,$041c60ff,$00000464
1763 dc.l $4a290004,$6a16201f,$f2009000,$123c0003
1764 dc.l $f2294800,$000060ff,$0000051c,$201f2049
1765 dc.l $60ff0000,$05860001,$00008000,$00000000
1766 dc.l $00000000,$0000422e,$ff652f00,$422eff5c
1767 dc.l $600c422e,$ff652f00,$1d7c0001,$ff5c48e7
1768 dc.l $3f003628,$00003d43,$ff580283,$00007fff
1769 dc.l $28280004,$2a280008,$4a83663c,$263c0000
1770 dc.l $3ffe4a84,$66162805,$42850483,$00000020
1771 dc.l $4286edc4,$6000edac,$96866022,$4286edc4
1772 dc.l $60009686,$edac2e05,$edad4486,$06860000
1773 dc.l $0020ecaf,$88876006,$06830000,$3ffe3029
1774 dc.l $00003d40,$ff5a322e,$ff58b181,$02810000
1775 dc.l $80003d41,$ff5e0280,$00007fff,$22290004
1776 dc.l $24290008,$4a80663c,$203c0000,$3ffe4a81
1777 dc.l $66162202,$42820480,$00000020,$4286edc1
1778 dc.l $6000eda9,$90866022,$4286edc1,$60009086
1779 dc.l $eda92e02,$edaa4486,$06860000,$0020ecaf
1780 dc.l $82876006,$06800000,$3ffe2d43,$ff542f00
1781 dc.l $90834286,$4283227c,$00000000,$4a806c06
1782 dc.l $201f6000,$006a588f,$4a866e0e,$b2846608
1783 dc.l $b4856604,$60000136,$65089485,$93844286
1784 dc.l $52834a80,$670ed683,$d482e391,$55c65289
1785 dc.l $538060d4,$202eff54,$4a816616,$22024282
1786 dc.l $04800000,$00204286,$edc16000,$eda99086
1787 dc.l $601c4286,$edc16000,$6b149086,$eda92e02
1788 dc.l $edaa4486,$06860000,$0020ecaf,$82870c80
1789 dc.l $000041fe,$6c2a3d40,$ff902d41,$ff942d42
1790 dc.l $ff982c2e,$ff543d46,$ff842d44,$ff882d45
1791 dc.l $ff8cf22e,$4800ff90,$1d7c0001,$ff5d6036
1792 dc.l $2d41ff94,$2d42ff98,$04800000,$3ffe3d40
1793 dc.l $ff902c2e,$ff540486,$00003ffe,$2d46ff54
1794 dc.l $f22e4800,$ff903d46,$ff842d44,$ff882d45
1795 dc.l $ff8c422e,$ff5d4a2e,$ff5c6722,$2c2eff54
1796 dc.l $5386b086,$6d186e0e,$b2846608,$b4856604
1797 dc.l $6000007a,$6508f22e,$4828ff84,$52833c2e
1798 dc.l $ff5a6c04,$f200001a,$42863c2e,$ff5e7e08
1799 dc.l $eeae0283,$0000007f,$86861d43,$ff654cdf
1800 dc.l $00fc201f,$f2009000,$4a2eff5d,$6710123c
1801 dc.l $0000f23a,$4823fdc0,$60ff0000,$02ca123c
1802 dc.l $0003f200,$000060ff,$000002bc,$52830c80
1803 dc.l $00000008,$6c04e1ab,$60024283,$f23c4400
1804 dc.l $00000000,$422eff5d,$6000ff94,$2c030286
1805 dc.l $00000001,$4a866700,$ff865283,$3c2eff5a
1806 dc.l $0a860000,$80003d46,$ff5a6000,$ff723028
1807 dc.l $00000240,$7fff0c40,$7fff6738,$08280007
1808 dc.l $00046706,$103c0000,$4e754a40,$66184aa8
1809 dc.l $0004660c,$4aa80008,$6606103c,$00014e75
1810 dc.l $103c0004,$4e7561ff,$000007f6,$4e75103c
1811 dc.l $00064e75,$4aa80008,$66122028,$00040280
1812 dc.l $7fffffff,$6606103c,$00024e75,$103c0003
1813 dc.l $4e757fff,$0000ffff,$ffffffff,$ffff4a28
1814 dc.l $00006a38,$00ae0a00,$0410ff64,$082e0002
1815 dc.l $ff62660a,$f23c4400,$ff800000,$4e75f22e
1816 dc.l $d080ffdc,$f22e9000,$ff60f23c,$4480bf80
1817 dc.l $0000f23c,$44a00000,$00004e75,$00ae0200
1818 dc.l $0410ff64,$082e0002,$ff62660a,$f23c4400
1819 dc.l $7f800000,$4e75f22e,$d080ffdc,$f22e9000
1820 dc.l $ff60f23c,$44803f80,$0000f23c,$44a00000
1821 dc.l $00004e75,$00ae0100,$2080ff64,$082e0005
1822 dc.l $ff626608,$f23ad080,$ff6a4e75,$f22ed080
1823 dc.l $ffdcf22e,$9000ff60,$f227e004,$f23c4500
1824 dc.l $7f800000,$f23c4523,$00000000,$f21fd020
1825 dc.l $4e757ffe,$0000ffff,$ffffffff,$fffffffe
1826 dc.l $0000ffff,$ffffffff,$ffff0000,$00008000
1827 dc.l $00000000,$00008000,$00008000,$00000000
1828 dc.l $00004a28,$00006a26,$00ae0800,$0a28ff64
1829 dc.l $f22e9000,$ff60f23a,$d080ffdc,$f23a4823
1830 dc.l $ffcaf200,$a800e198,$1d40ff64,$4e75006e
1831 dc.l $0a28ff66,$f22e9000,$ff60f23a,$d080ffac
1832 dc.l $f2000023,$f200a800,$e1981d40,$ff644e75
1833 dc.l $00ae0000,$1048ff64,$12000201,$00c06700
1834 dc.l $005a3d68,$0000ff84,$2d680004,$ff882d68
1835 dc.l $0008ff8c,$41eeff84,$48e7c080,$61ff0000
1836 dc.l $06184cdf,$01030c01,$00406610,$4aa80008
1837 dc.l $66184a28,$00076612,$60000020,$22280008
1838 dc.l $02810000,$07ff6700,$001200ae,$00000200
1839 dc.l $ff646006,$006e1248,$ff664a28,$00006a22
1840 dc.l $f22e9000,$ff60f23a,$d080ff14,$f23a4823
1841 dc.l $ff02f200,$a800e198,$00000000,$1d40ff64
1842 dc.l $4e75f22e,$9000ff60,$f23ad080,$fee6f23a
1843 dc.l $4823fee0,$f200a800,$e1981d40,$ff644e75
1844 dc.l $006e1248,$ff66f22e,$9000ff60,$f23ad080
1845 dc.l $fec2f23a,$4823febc,$f200a800,$e1981d40
1846 dc.l $ff644e75,$f200a800,$81aeff64,$6020f200
1847 dc.l $a80081ae,$ff64f294,$000ef281,$0032006e
1848 dc.l $0208ff66,$600800ae,$08000208,$ff64082e
1849 dc.l $0001ff62,$66024e75,$f22e9000,$ff60f23c
1850 dc.l $44803f80,$0000f23a,$48a2fe80,$4e751d7c
1851 dc.l $0004ff64,$006e0208,$ff664e75,$f22e9000
1852 dc.l $ff60f228,$48000000,$f200a800,$00800000
1853 dc.l $0a2881ae,$ff644e75,$f22e9000,$ff60f228
1854 dc.l $48000000,$f200a800,$81aeff64,$4e754e75
1855 dc.l $f2294800,$00004a29,$00006b08,$1d7c0001
1856 dc.l $ff644e75,$1d7c0009,$ff644e75,$f2284800
1857 dc.l $00004a28,$00006b08,$1d7c0001,$ff644e75
1858 dc.l $1d7c0009,$ff644e75,$f227b000,$f23c9000
1859 dc.l $00000000,$f22f4400,$0008f21f,$9000f22f
1860 dc.l $44220008,$4e75f227,$b000f23c,$90000000
1861 dc.l $0000f22f,$54000008,$f21f9000,$f22f5422
1862 dc.l $000c4e75,$f22fd080,$0004f22f,$48220010
1863 dc.l $4e75f227,$b000f23c,$90000000,$0000f22f
1864 dc.l $44000008,$f21f9000,$f22f4428,$00084e75
1865 dc.l $f227b000,$f23c9000,$00000000,$f22f5400
1866 dc.l $0008f21f,$9000f22f,$5428000c,$4e75f22f
1867 dc.l $d0800004,$f22f4828,$00104e75,$f227b000
1868 dc.l $f23c9000,$00000000,$f22f4400,$0008f21f
1869 dc.l $9000f22f,$44230008,$4e75f227,$b000f23c
1870 dc.l $90000000,$0000f22f,$54000008,$f21f9000
1871 dc.l $f22f5423,$000c4e75,$f22fd080,$0004f22f
1872 dc.l $48230010,$4e75f227,$b000f23c,$90000000
1873 dc.l $0000f22f,$44000008,$f21f9000,$f22f4420
1874 dc.l $00084e75,$f227b000,$f23c9000,$00000000
1875 dc.l $f22f5400,$0008f21f,$9000f22f,$5420000c
1876 dc.l $4e75f22f,$d0800004,$f22f4820,$00104e75
1877 dc.l $f22f4418,$00044e75,$f22f5418,$00044e75
1878 dc.l $f22f4818,$00044e75,$f22f441a,$00044e75
1879 dc.l $f22f541a,$00044e75,$f22f481a,$00044e75
1880 dc.l $f22f4404,$00044e75,$f22f5404,$00044e75
1881 dc.l $f22f4804,$00044e75,$f22f4401,$00044e75
1882 dc.l $f22f5401,$00044e75,$f22f4801,$00044e75
1883 dc.l $f22f4403,$00044e75,$f22f5403,$00044e75
1884 dc.l $f22f4803,$00044e75,$4a280000,$6b10f23c
1885 dc.l $44000000,$00001d7c,$0004ff64,$4e75f23c
1886 dc.l $44008000,$00001d7c,$000cff64,$4e754a29
1887 dc.l $00006bea,$60d84a28,$00006b10,$f23c4400
1888 dc.l $7f800000,$1d7c0002,$ff644e75,$f23c4400
1889 dc.l $ff800000,$1d7c000a,$ff644e75,$4a290000
1890 dc.l $6bea60d8,$4a280000,$6ba460d0,$4a280000
1891 dc.l $6b00fba2,$60c64a28,$00006b16,$60be4a28
1892 dc.l $00006b0e,$f23c4400,$3f800000,$422eff64
1893 dc.l $4e75f23c,$4400bf80,$00001d7c,$0008ff64
1894 dc.l $4e753fff,$0000c90f,$daa22168,$c235bfff
1895 dc.l $0000c90f,$daa22168,$c2354a28,$00006b0e
1896 dc.l $f2009000,$f23a4800,$ffda6000,$fcf2f200
1897 dc.l $9000f23a,$4800ffd8,$6000fcec,$f23c4480
1898 dc.l $3f800000,$4a280000,$6a10f23c,$44008000
1899 dc.l $00001d7c,$000cff64,$4e75f23c,$44000000
1900 dc.l $00001d7c,$0004ff64,$4e75f23a,$4880fa84
1901 dc.l $6000fb02,$f2284880,$00006000,$fd30122e
1902 dc.l $ff4f67ff,$fffff782,$0c010001,$67000078
1903 dc.l $0c010002,$67ffffff,$fade0c01,$000467ff
1904 dc.l $fffff766,$60ffffff,$fcea122e,$ff4f67ff
1905 dc.l $fffffac4,$0c010001,$67ffffff,$faba0c01
1906 dc.l $000267ff,$fffffab0,$0c010004,$67ffffff
1907 dc.l $faa660ff,$fffffcbc,$122eff4f,$67ff0000
1908 dc.l $00440c01,$000167ff,$0000001e,$0c010002
1909 dc.l $67ffffff,$fa820c01,$000467ff,$00000026
1910 dc.l $60ffffff,$fc8e1228,$00001029,$0000b101
1911 dc.l $02010080,$1d41ff65,$4a006a00,$fe526000
1912 dc.l $fe5e422e,$ff652f00,$12280000,$10290000
1913 dc.l $b1010201,$00801d41,$ff650c2e,$0004ff4f
1914 dc.l $660c41e9,$0000201f,$60ffffff,$fc2ef21f
1915 dc.l $9000f229,$48000000,$4a290000,$6b024e75
1916 dc.l $1d7c0008,$ff644e75,$122eff4f,$67ffffff
1917 dc.l $f6a40c01,$00016700,$ff8e0c01,$000267ff
1918 dc.l $fffff9f4,$0c010004,$67ffffff,$f68860ff
1919 dc.l $fffffc00,$122eff4f,$67ffffff,$f9da0c01
1920 dc.l $000167ff,$fffff9d0,$0c010002,$67ffffff
1921 dc.l $f9c60c01,$000467ff,$fffff9bc,$60ffffff
1922 dc.l $fbd2122e,$ff4f6700,$ff5a0c01,$00016700
1923 dc.l $ff360c01,$000267ff,$fffff99c,$0c010004
1924 dc.l $67ffffff,$ff4060ff,$fffffba8,$122eff4f
1925 dc.l $67ffffff,$f5000c01,$000167ff,$fffffd92
1926 dc.l $0c010002,$67ffffff,$fdb60c01,$000467ff
1927 dc.l $fffff4e2,$60ffffff,$fb7a122e,$ff4f67ff
1928 dc.l $fffff4d2,$0c010001,$67ffffff,$fd640c01
1929 dc.l $000267ff,$fffffd88,$0c010004,$67ffffff
1930 dc.l $f4b460ff,$fffffb4c,$122eff4f,$67ffffff
1931 dc.l $f9260c01,$000367ff,$fffffb38,$60ffffff
1932 dc.l $f916122e,$ff4f0c01,$000367ff,$fffffb24
1933 dc.l $60ffffff,$fb3a2f02,$2f032028,$00042228
1934 dc.l $0008edc0,$2000671a,$e5a8e9c1,$30228083
1935 dc.l $e5a92140,$00042141,$00082002,$261f241f
1936 dc.l $4e75edc1,$2000e5a9,$06820000,$00202141
1937 dc.l $000442a8,$00082002,$261f241f,$4e75ede8
1938 dc.l $00000004,$660eede8,$00000008,$67000074
1939 dc.l $06400020,$42813228,$00000241,$7fffb041
1940 dc.l $6e1c9240,$30280000,$02408000,$82403141
1941 dc.l $000061ff,$ffffff82,$103c0000,$4e750c01
1942 dc.l $00206e20,$e9e80840,$00042140,$00042028
1943 dc.l $0008e3a8,$21400008,$02688000,$0000103c
1944 dc.l $00044e75,$04410020,$20280008,$e3a82140
1945 dc.l $000442a8,$00080268,$80000000,$103c0004
1946 dc.l $4e750268,$80000000,$103c0001,$4e7551fc
diff --git a/arch/m68k/ifpsp060/fpsp.doc b/arch/m68k/ifpsp060/fpsp.doc
new file mode 100644
index 000000000000..408315209e62
--- /dev/null
+++ b/arch/m68k/ifpsp060/fpsp.doc
@@ -0,0 +1,295 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2968060 FLOATING-POINT SOFTWARE PACKAGE (Kernel version)
30-------------------------------------------------------
31
32The file fpsp.sa contains the 68060 Floating-Point Software
33Package. This package is essentially a set of exception handlers
34that can be integrated into an operating system.
35These exception handlers emulate Unimplemented FP instructions,
36instructions using unimplemented data types, and instructions
37using unimplemented addressing modes. In addition, this package
38includes exception handlers to provide full IEEE-754 compliant
39exception handling.
40
41Release file format:
42--------------------
43The file fpsp.sa is essentially a hexadecimal image of the
44release package. This is the ONLY format which will be supported.
45The hex image was created by assembling the source code and
46then converting the resulting binary output image into an
47ASCII text file. The hexadecimal numbers are listed
48using the Motorola Assembly Syntax assembler directive "dc.l"
49(define constant longword). The file can be converted to other
50assembly syntaxes by using any word processor with a global
51search and replace function.
52
53To assist in assembling and linking this module with other modules,
54the installer should add a symbolic label to the top of the file.
55This will allow calling routines to access the entry points
56of this package.
57
58The source code fpsp.s has also been included but only for
59documentation purposes.
60
61Release file structure:
62-----------------------
63
64(top of module)
65 -----------------
66 | | - 128 byte-sized section
67 (1) | Call-Out | - 4 bytes per entry (user fills these in)
68 | | - example routines in fskeleton.s
69 -----------------
70 | | - 8 bytes per entry
71 (2) | Entry Point | - user does "bra" or "jmp" to this address
72 | |
73 -----------------
74 | | - code section
75 (3) ~ ~
76 | |
77 -----------------
78(bottom of module)
79
80The first section of this module is the "Call-out" section. This section
81is NOT INCLUDED in fpsp.sa (an example "Call-out" section is provided at
82the end of the file fskeleton.s). The purpose of this section is to allow
83the FPSP routines to reference external functions that must be provided
84by the host operating system. This section MUST be exactly 128 bytes in
85size. There are 32 fields, each 4 bytes in size. Each field corresponds
86to a function required by the FPSP (these functions and their location are
87listed in "68060FPSP call-outs" below). Each field entry should contain
88the address of the corresponding function RELATIVE to the starting address
89of the "call-out" section. The "Call-out" section must sit adjacent to the
90fpsp.sa image in memory.
91
92The second section, the "Entry-point" section, is used by external routines
93to access the functions within the FPSP. Since the fpsp.sa hex file contains
94no symbol names, this section contains function entry points that are fixed
95with respect to the top of the package. The currently defined entry-points
96are listed in section "68060 FPSP entry points" below. A calling routine
97would simply execute a "bra" or "jmp" that jumped to the selected function
98entry-point.
99
100For example, if the 68060 hardware took a "Line-F Emulator" exception
101(vector #11), the operating system should execute something similar to:
102
103 bra _060FPSP_TOP+128+48
104
105(_060FPSP_TOP is the starting address of the "Call-out" section; the "Call-out"
106section is 128 bytes long; and the F-Line FPSP handler entry point is located
10748 bytes from the top of the "Entry-point" section.)
108
109The third section is the code section. After entering through an "Entry-point",
110the entry code jumps to the appropriate emulation code within the code section.
111
11268060FPSP call-outs: (details in fskeleton.s)
113--------------------
1140x000: _060_real_bsun
1150x004: _060_real_snan
1160x008: _060_real_operr
1170x00c: _060_real_ovfl
1180x010: _060_real_unfl
1190x014: _060_real_dz
1200x018: _060_real_inex
1210x01c: _060_real_fline
1220x020: _060_real_fpu_disabled
1230x024: _060_real_trap
1240x028: _060_real_trace
1250x02c: _060_real_access
1260x030: _060_fpsp_done
127
1280x034: (Motorola reserved)
1290x038: (Motorola reserved)
1300x03c: (Motorola reserved)
131
1320x040: _060_imem_read
1330x044: _060_dmem_read
1340x048: _060_dmem_write
1350x04c: _060_imem_read_word
1360x050: _060_imem_read_long
1370x054: _060_dmem_read_byte
1380x058: _060_dmem_read_word
1390x05c: _060_dmem_read_long
1400x060: _060_dmem_write_byte
1410x064: _060_dmem_write_word
1420x068: _060_dmem_write_long
143
1440x06c: (Motorola reserved)
1450x070: (Motorola reserved)
1460x074: (Motorola reserved)
1470x078: (Motorola reserved)
1480x07c: (Motorola reserved)
149
15068060FPSP entry points:
151-----------------------
1520x000: _060_fpsp_snan
1530x008: _060_fpsp_operr
1540x010: _060_fpsp_ovfl
1550x018: _060_fpsp_unfl
1560x020: _060_fpsp_dz
1570x028: _060_fpsp_inex
1580x030: _060_fpsp_fline
1590x038: _060_fpsp_unsupp
1600x040: _060_fpsp_effadd
161
162
163
164Miscellaneous:
165--------------
166
167_060_fpsp_snan:
168----------------
169- documented in 3.5 of 060SP spec.
170- Basic flow:
171 exception taken ---> enter _060_fpsp_snan --|
172 |
173 always exits through _060_real_snan <----
174
175_060_fpsp_operr:
176----------------
177- documented in 3.5 of 060SP spec.
178- Basic flow:
179 exception taken ---> enter _060_fpsp_operr --|
180 |
181 always exits through _060_real_operr <-----
182
183_060_fpsp_dz:
184----------------
185- documented in 3.7 of 060SP spec.
186- Basic flow:
187 exception taken ---> enter _060_fpsp_dz --|
188 |
189 always exits through _060_real_dz <----
190
191_060_fpsp_inex:
192----------------
193- documented in 3.6 of 060SP spec.
194- Basic flow:
195 exception taken ---> enter _060_fpsp_inex --|
196 |
197 always exits through _060_real_inex <----
198
199
200_060_fpsp_ovfl:
201----------------
202- documented in 3.4 of 060SP spec.
203- Basic flow:
204 exception taken ---> enter _060_fpsp_ovfl --|
205 |
206 may exit through _060_real_inex <---|
207 or |
208 may exit through _060_real_ovfl <---|
209 or |
210 may exit through _060_fpsp_done <---|
211
212_060_fpsp_unfl:
213----------------
214- documented in 3.4 of 060SP spec.
215- Basic flow:
216 exception taken ---> enter _060_fpsp_unfl --|
217 |
218 may exit through _060_real_inex <---|
219 or |
220 may exit through _060_real_unfl <---|
221 or |
222 may exit through _060_fpsp_done <---|
223
224
225_060_fpsp_fline:
226-----------------
227- not fully documented in 060SP spec.
228- Basic flow:
229 exception taken ---> enter _060_fpsp_fline --|
230 |
231 -------------------------------------------
232 | | |
233 v v v
234 (unimplemented (fpu disabled) (possible F-line illegal)
235 stack frame) | v
236 | v special case "fmovecr"?
237 | exit through |
238 | _060_real_fpu_disabled -------------
239 | | |
240 | ^ v v
241 | | (yes) (no)
242 | | v v
243 | | fpu disabled? exit through
244 | | | _060_real_fline
245 v | -------------
246 | | | |
247 | | v v
248 | |-----------(yes) (no)
249 | |
250 |----<------------------------------------|
251 |
252 |
253 |----> may exit through _060_real_trace
254 |
255 |----> may exit through _060_real_trap
256 |
257 |----> may exit through _060_real_bsun
258 |
259 |----> may exit through _060_fpsp_done
260
261
262_060_fpsp_unsupp:
263------------------
264- documented in 3.1 of 060SP spec.
265- Basic flow:
266 exception taken ---> enter _060_fpsp_unsupp --|
267 |
268 |
269 may exit through _060_real_snan <----|
270 or |
271 may exit through _060_real_operr <----|
272 or |
273 may exit through _060_real_ovfl <----|
274 or |
275 may exit through _060_real_unfl <----|
276 or |
277 may exit through _060_real_inex <----|
278 or |
279 may exit through _060_real_trace <----|
280 or |
281 may exit through _060_fpsp_done <----|
282
283
284_060_fpsp_effadd:
285------------------
286- documented in 3.3 of 060 spec.
287- Basic flow:
288 exception taken ---> enter _060_fpsp_effadd --|
289 |
290 |
291 may exit through _060_real_trace <----|
292 or |
293 may exit through _060_real_fpu_disabled <----|
294 or |
295 may exit through _060_fpsp_done <----|
diff --git a/arch/m68k/ifpsp060/fpsp.sa b/arch/m68k/ifpsp060/fpsp.sa
new file mode 100644
index 000000000000..d69486a44bc4
--- /dev/null
+++ b/arch/m68k/ifpsp060/fpsp.sa
@@ -0,0 +1,3401 @@
1 .long 0x60ff0000,0x17400000,0x60ff0000,0x15f40000
2 .long 0x60ff0000,0x02b60000,0x60ff0000,0x04700000
3 .long 0x60ff0000,0x1b100000,0x60ff0000,0x19aa0000
4 .long 0x60ff0000,0x1b5a0000,0x60ff0000,0x062e0000
5 .long 0x60ff0000,0x102c0000,0x51fc51fc,0x51fc51fc
6 .long 0x51fc51fc,0x51fc51fc,0x51fc51fc,0x51fc51fc
7 .long 0x51fc51fc,0x51fc51fc,0x51fc51fc,0x51fc51fc
8 .long 0x51fc51fc,0x51fc51fc,0x51fc51fc,0x51fc51fc
9 .long 0x2f00203a,0xff2c487b,0x0930ffff,0xfef8202f
10 .long 0x00044e74,0x00042f00,0x203afef2,0x487b0930
11 .long 0xfffffee2,0x202f0004,0x4e740004,0x2f00203a
12 .long 0xfee0487b,0x0930ffff,0xfecc202f,0x00044e74
13 .long 0x00042f00,0x203afed2,0x487b0930,0xfffffeb6
14 .long 0x202f0004,0x4e740004,0x2f00203a,0xfea4487b
15 .long 0x0930ffff,0xfea0202f,0x00044e74,0x00042f00
16 .long 0x203afe96,0x487b0930,0xfffffe8a,0x202f0004
17 .long 0x4e740004,0x2f00203a,0xfe7c487b,0x0930ffff
18 .long 0xfe74202f,0x00044e74,0x00042f00,0x203afe76
19 .long 0x487b0930,0xfffffe5e,0x202f0004,0x4e740004
20 .long 0x2f00203a,0xfe68487b,0x0930ffff,0xfe48202f
21 .long 0x00044e74,0x00042f00,0x203afe56,0x487b0930
22 .long 0xfffffe32,0x202f0004,0x4e740004,0x2f00203a
23 .long 0xfe44487b,0x0930ffff,0xfe1c202f,0x00044e74
24 .long 0x00042f00,0x203afe32,0x487b0930,0xfffffe06
25 .long 0x202f0004,0x4e740004,0x2f00203a,0xfe20487b
26 .long 0x0930ffff,0xfdf0202f,0x00044e74,0x00042f00
27 .long 0x203afe1e,0x487b0930,0xfffffdda,0x202f0004
28 .long 0x4e740004,0x2f00203a,0xfe0c487b,0x0930ffff
29 .long 0xfdc4202f,0x00044e74,0x00042f00,0x203afdfa
30 .long 0x487b0930,0xfffffdae,0x202f0004,0x4e740004
31 .long 0x2f00203a,0xfde8487b,0x0930ffff,0xfd98202f
32 .long 0x00044e74,0x00042f00,0x203afdd6,0x487b0930
33 .long 0xfffffd82,0x202f0004,0x4e740004,0x2f00203a
34 .long 0xfdc4487b,0x0930ffff,0xfd6c202f,0x00044e74
35 .long 0x00042f00,0x203afdb2,0x487b0930,0xfffffd56
36 .long 0x202f0004,0x4e740004,0x2f00203a,0xfda0487b
37 .long 0x0930ffff,0xfd40202f,0x00044e74,0x00042f00
38 .long 0x203afd8e,0x487b0930,0xfffffd2a,0x202f0004
39 .long 0x4e740004,0x2f00203a,0xfd7c487b,0x0930ffff
40 .long 0xfd14202f,0x00044e74,0x00042f00,0x203afd6a
41 .long 0x487b0930,0xfffffcfe,0x202f0004,0x4e740004
42 .long 0x40c62d38,0xd3d64634,0x3d6f90ae,0xb1e75cc7
43 .long 0x40000000,0xc90fdaa2,0x2168c235,0x00000000
44 .long 0x3fff0000,0xc90fdaa2,0x2168c235,0x00000000
45 .long 0x3fe45f30,0x6dc9c883,0x4e56ff40,0xf32eff6c
46 .long 0x48ee0303,0xff9cf22e,0xbc00ff60,0xf22ef0c0
47 .long 0xffdc2d6e,0xff68ff44,0x206eff44,0x58aeff44
48 .long 0x61ffffff,0xff042d40,0xff40082e,0x0005ff42
49 .long 0x66000116,0x41eeff6c,0x61ff0000,0x051c41ee
50 .long 0xff6c61ff,0x0000c1dc,0x1d40ff4e,0x082e0005
51 .long 0xff436726,0xe9ee0183,0xff4261ff,0x0000bd22
52 .long 0x41eeff78,0x61ff0000,0xc1ba0c00,0x00066606
53 .long 0x61ff0000,0xc11e1d40,0xff4f4280,0x102eff63
54 .long 0x122eff43,0x0241007f,0x02ae00ff,0x01ffff64
55 .long 0xf23c9000,0x00000000,0xf23c8800,0x00000000
56 .long 0x41eeff6c,0x43eeff78,0x223b1530,0x00007112
57 .long 0x4ebb1930,0x0000710a,0xe9ee0183,0xff4261ff
58 .long 0x0000bd4e,0x082e0004,0xff626622,0x082e0001
59 .long 0xff626644,0xf22ed0c0,0xffdcf22e,0x9c00ff60
60 .long 0x4cee0303,0xff9c4e5e,0x60ffffff,0xfcc6f22e
61 .long 0xf040ff6c,0x3d7ce005,0xff6ef22e,0xd0c0ffdc
62 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0xf36eff6c
63 .long 0x4e5e60ff,0xfffffcb2,0xf22ef040,0xff6c1d7c
64 .long 0x00c4000b,0x3d7ce001,0xff6ef22e,0xd0c0ffdc
65 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0xf36eff6c
66 .long 0x4e5e60ff,0xfffffcae,0x1d7c0000,0xff4e4280
67 .long 0x102eff63,0x02aeffff,0x00ffff64,0xf23c9000
68 .long 0x00000000,0xf23c8800,0x00000000,0x41eeff6c
69 .long 0x61ff0000,0xb2ce082e,0x0004ff62,0x6600ff70
70 .long 0x082e0001,0xff626600,0xff90f22e,0xd0c0ffdc
71 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0x4e5e0817
72 .long 0x000767ff,0xfffffc0c,0xf22fa400,0x00083f7c
73 .long 0x20240006,0x60ffffff,0xfcec4e56,0xff40f32e
74 .long 0xff6c48ee,0x0303ff9c,0xf22ebc00,0xff60f22e
75 .long 0xf0c0ffdc,0x2d6eff68,0xff44206e,0xff4458ae
76 .long 0xff4461ff,0xfffffd42,0x2d40ff40,0x082e0005
77 .long 0xff426600,0x013241ee,0xff6c61ff,0x0000035a
78 .long 0x41eeff6c,0x61ff0000,0xc01a1d40,0xff4e082e
79 .long 0x0005ff43,0x672e082e,0x0004ff43,0x6626e9ee
80 .long 0x0183ff42,0x61ff0000,0xbb5841ee,0xff7861ff
81 .long 0x0000bff0,0x0c000006,0x660661ff,0x0000bf54
82 .long 0x1d40ff4f,0x4280102e,0xff63122e,0xff430241
83 .long 0x007f02ae,0x00ff01ff,0xff64f23c,0x90000000
84 .long 0x0000f23c,0x88000000,0x000041ee,0xff6c43ee
85 .long 0xff78223b,0x15300000,0x6f484ebb,0x19300000
86 .long 0x6f40e9ee,0x0183ff42,0x61ff0000,0xbb84082e
87 .long 0x0003ff62,0x6622082e,0x0001ff62,0x664ef22e
88 .long 0xd0c0ffdc,0xf22e9c00,0xff604cee,0x0303ff9c
89 .long 0x4e5e60ff,0xfffffafc,0x082e0003,0xff666700
90 .long 0xffd6f22e,0xf040ff6c,0x3d7ce003,0xff6ef22e
91 .long 0xd0c0ffdc,0xf22e9c00,0xff604cee,0x0303ff9c
92 .long 0xf36eff6c,0x4e5e60ff,0xfffffaf4,0x082e0001
93 .long 0xff666700,0xffaaf22e,0xf040ff6c,0x1d7c00c4
94 .long 0x000b3d7c,0xe001ff6e,0xf22ed0c0,0xffdcf22e
95 .long 0x9c00ff60,0x4cee0303,0xff9cf36e,0xff6c4e5e
96 .long 0x60ffffff,0xfad01d7c,0x0000ff4e,0x4280102e
97 .long 0xff6302ae,0xffff00ff,0xff64f23c,0x90000000
98 .long 0x0000f23c,0x88000000,0x000041ee,0xff6c61ff
99 .long 0x0000b0f0,0x082e0003,0xff626600,0xff66082e
100 .long 0x0001ff62,0x6600ff90,0xf22ed0c0,0xffdcf22e
101 .long 0x9c00ff60,0x4cee0303,0xff9c4e5e,0x08170007
102 .long 0x67ffffff,0xfa2ef22f,0xa4000008,0x3f7c2024
103 .long 0x000660ff,0xfffffb0e,0x4e56ff40,0xf32eff6c
104 .long 0x48ee0303,0xff9cf22e,0xbc00ff60,0xf22ef0c0
105 .long 0xffdc082e,0x00050004,0x66084e68,0x2d48ffd8
106 .long 0x600841ee,0x00102d48,0xffd82d6e,0xff68ff44
107 .long 0x206eff44,0x58aeff44,0x61ffffff,0xfb4c2d40
108 .long 0xff40422e,0xff4a082e,0x0005ff42,0x66000208
109 .long 0xe9ee0006,0xff420c00,0x00136700,0x049e02ae
110 .long 0x00ff00ff,0xff64f23c,0x90000000,0x0000f23c
111 .long 0x88000000,0x000041ee,0xff6c61ff,0x0000013a
112 .long 0x41eeff6c,0x61ff0000,0xbdfa0c00,0x00066606
113 .long 0x61ff0000,0xbd5e1d40,0xff4ee9ee,0x0183ff42
114 .long 0x082e0005,0xff436728,0x0c2e003a,0xff436720
115 .long 0x61ff0000,0xb92c41ee,0xff7861ff,0x0000bdc4
116 .long 0x0c000006,0x660661ff,0x0000bd28,0x1d40ff4f
117 .long 0x4280102e,0xff63e9ee,0x1047ff43,0x41eeff6c
118 .long 0x43eeff78,0x223b1d30,0x00006d36,0x4ebb1930
119 .long 0x00006d2e,0x102eff62,0x6634102e,0xff430200
120 .long 0x00380c00,0x0038670c,0xe9ee0183,0xff4261ff
121 .long 0x0000b95e,0xf22ed0c0,0xffdcf22e,0x9c00ff60
122 .long 0x4cee0303,0xff9c4e5e,0x60ffffff,0xf8e6c02e
123 .long 0xff66edc0,0x06086614,0x082e0004,0xff6667ba
124 .long 0x082e0001,0xff6267b2,0x60000066,0x04800000
125 .long 0x00180c00,0x00066614,0x082e0003,0xff666600
126 .long 0x004a082e,0x0004ff66,0x66000046,0x2f0061ff
127 .long 0x000007e0,0x201f3d7b,0x0222ff6e,0xf22ed0c0
128 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9cf36e
129 .long 0xff6c4e5e,0x60ffffff,0xf87ae000,0xe006e004
130 .long 0xe005e003,0xe002e001,0xe001303c,0x000460bc
131 .long 0x303c0003,0x60b6e9ee,0x0006ff42,0x0c000011
132 .long 0x67080c00,0x00156750,0x4e753028,0x00000240
133 .long 0x7fff0c40,0x3f806708,0x0c40407f,0x672c4e75
134 .long 0x02a87fff,0xffff0004,0x671861ff,0x0000bbbc
135 .long 0x44400640,0x3f810268,0x80000000,0x81680000
136 .long 0x4e750268,0x80000000,0x4e750228,0x007f0004
137 .long 0x00687fff,0x00004e75,0x30280000,0x02407fff
138 .long 0x0c403c00,0x67080c40,0x43ff67de,0x4e7502a8
139 .long 0x7fffffff,0x00046606,0x4aa80008,0x67c461ff
140 .long 0x0000bb68,0x44400640,0x3c010268,0x80000000
141 .long 0x81680000,0x4e75e9ee,0x00c3ff42,0x0c000003
142 .long 0x670004a2,0x0c000007,0x6700049a,0x02aeffff
143 .long 0x00ffff64,0xf23c9000,0x00000000,0xf23c8800
144 .long 0x00000000,0x302eff6c,0x02407fff,0x671041ee
145 .long 0xff6c61ff,0x0000bb5c,0x1d40ff4e,0x60061d7c
146 .long 0x0004ff4e,0x4280102e,0xff6341ee,0xff6c2d56
147 .long 0xffd461ff,0x0000adec,0x102eff62,0x66000086
148 .long 0x2caeffd4,0x082e0005,0x00046626,0x206effd8
149 .long 0x4e60f22e,0xd0c0ffdc,0xf22e9c00,0xff604cee
150 .long 0x0303ff9c,0x4e5e0817,0x0007667a,0x60ffffff
151 .long 0xf7220c2e,0x0008ff4a,0x66d8f22e,0xf080ff6c
152 .long 0xf22ed0c0,0xffdcf22e,0x9c00ff60,0x4cee0303
153 .long 0xff9c2c56,0x2f6f00c4,0x00b82f6f,0x00c800bc
154 .long 0x2f6f002c,0x00c42f6f,0x003000c8,0x2f6f0034
155 .long 0x00ccdffc,0x000000b8,0x08170007,0x662860ff
156 .long 0xfffff6d0,0xc02eff66,0xedc00608,0x662a082e
157 .long 0x0004ff66,0x6700ff6a,0x082e0001,0xff626700
158 .long 0xff606000,0x01663f7c,0x20240006,0xf22fa400
159 .long 0x000860ff,0xfffff78e,0x04800000,0x0018303b
160 .long 0x020a4efb,0x00064afc,0x00080000,0x0000003a
161 .long 0x00640094,0x00000140,0x0000f22e,0xd0c0ffdc
162 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0x3d7c30d8
163 .long 0x000a3d7c,0xe006ff6e,0xf36eff6c,0x4e5e60ff
164 .long 0xfffff6d4,0xf22ed0c0,0xffdcf22e,0x9c00ff60
165 .long 0x4cee0303,0xff9c3d7c,0x30d0000a,0x3d7ce004
166 .long 0xff6ef36e,0xff6c4e5e,0x60ffffff,0xf694f22e
167 .long 0xf040ff6c,0xf22ed0c0,0xffdcf22e,0x9c00ff60
168 .long 0x4cee0303,0xff9c3d7c,0x30d4000a,0x3d7ce005
169 .long 0xff6ef36e,0xff6c4e5e,0x60ffffff,0xf60c2cae
170 .long 0xffd4082e,0x00050004,0x66000038,0x206effd8
171 .long 0x4e60f22e,0xf040ff6c,0xf22ed0c0,0xffdcf22e
172 .long 0x9c00ff60,0x4cee0303,0xff9c3d7c,0x30cc000a
173 .long 0x3d7ce003,0xff6ef36e,0xff6c4e5e,0x60ffffff
174 .long 0xf5de0c2e,0x0008ff4a,0x66c8f22e,0xf080ff6c
175 .long 0xf22ef040,0xff78f22e,0xd0c0ffdc,0xf22e9c00
176 .long 0xff604cee,0x0303ff9c,0x3d7c30cc,0x000a3d7c
177 .long 0xe003ff7a,0xf36eff78,0x2c562f6f,0x00c400b8
178 .long 0x2f6f00c8,0x00bc2f6f,0x00cc00c0,0x2f6f002c
179 .long 0x00c42f6f,0x003000c8,0x2f6f0034,0x00ccdffc
180 .long 0x000000b8,0x60ffffff,0xf576f22e,0xf040ff6c
181 .long 0xf22ed0c0,0xffdcf22e,0x9c00ff60,0x4cee0303
182 .long 0xff9c3d7c,0x30c4000a,0x3d7ce001,0xff6ef36e
183 .long 0xff6c4e5e,0x60ffffff,0xf55c02ae,0x00ff00ff
184 .long 0xff64f23c,0x90000000,0x0000f23c,0x88000000
185 .long 0x000061ff,0x0000bdba,0x41eeff6c,0x61ff0000
186 .long 0xb9621d40,0xff4ee9ee,0x0183ff42,0x082e0005
187 .long 0xff436728,0x0c2e003a,0xff436720,0x61ff0000
188 .long 0xb4a041ee,0xff7861ff,0x0000b938,0x0c000006
189 .long 0x660661ff,0x0000b89c,0x1d40ff4f,0x4280102e
190 .long 0xff63e9ee,0x1047ff43,0x41eeff6c,0x43eeff78
191 .long 0x223b1d30,0x000068aa,0x4ebb1930,0x000068a2
192 .long 0x102eff62,0x6600008a,0x102eff43,0x02000038
193 .long 0x0c000038,0x670ce9ee,0x0183ff42,0x61ff0000
194 .long 0xb4d0082e,0x00050004,0x6600002a,0x206effd8
195 .long 0x4e60f22e,0xd0c0ffdc,0xf22e9c00,0xff604cee
196 .long 0x0303ff9c,0x4e5e0817,0x00076600,0x012660ff
197 .long 0xfffff440,0x082e0002,0xff4a67d6,0xf22ed0c0
198 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9c4e5e
199 .long 0x2f6f0004,0x00102f6f,0x0000000c,0xdffc0000
200 .long 0x000c0817,0x00076600,0x00ea60ff,0xfffff404
201 .long 0xc02eff66,0xedc00608,0x6618082e,0x0004ff66
202 .long 0x6700ff66,0x082e0001,0xff626700,0xff5c6000
203 .long 0x006e0480,0x00000018,0x0c000006,0x6d14082e
204 .long 0x0003ff66,0x66000060,0x082e0004,0xff666600
205 .long 0x004e082e,0x00050004,0x66000054,0x206effd8
206 .long 0x4e603d7b,0x022aff6e,0xf22ed0c0,0xffdcf22e
207 .long 0x9c00ff60,0x4cee0303,0xff9cf36e,0xff6c4e5e
208 .long 0x08170007,0x6600006c,0x60ffffff,0xf386e000
209 .long 0xe006e004,0xe005e003,0xe002e001,0xe001303c
210 .long 0x00036000,0xffae303c,0x00046000,0xffa6082e
211 .long 0x0002ff4a,0x67ac3d7b,0x02d6ff6e,0xf22ed0c0
212 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9cf36e
213 .long 0xff6c4e5e,0x2f6f0004,0x00102f6f,0x0000000c
214 .long 0xdffc0000,0x000c0817,0x00076606,0x60ffffff
215 .long 0xf3223f7c,0x20240006,0xf22fa400,0x000860ff
216 .long 0xfffff402,0x02aeffff,0x00ffff64,0xf23c9000
217 .long 0x00000000,0xf23c8800,0x00000000,0xe9ee0183
218 .long 0xff4261ff,0x0000b22a,0x41eeff6c,0x61ff0000
219 .long 0xb7520c00,0x00066606,0x61ff0000,0xb6b61d40
220 .long 0xff4e4280,0x102eff63,0x41eeff6c,0x2d56ffd4
221 .long 0x61ff0000,0xa94e102e,0xff626600,0x00842cae
222 .long 0xffd4082e,0x00050004,0x6628206e,0xffd84e60
223 .long 0xf22ed0c0,0xffdcf22e,0x9c00ff60,0x4cee0303
224 .long 0xff9c4e5e,0x08170007,0x6600ff68,0x60ffffff
225 .long 0xf282082e,0x0003ff4a,0x67d6f22e,0xd0c0ffdc
226 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0x2c562f6f
227 .long 0x00c400b8,0x2f6f00c8,0x00bc2f6f,0x003800c4
228 .long 0x2f6f003c,0x00c82f6f,0x004000cc,0xdffc0000
229 .long 0x00b80817,0x00076600,0xff1a60ff,0xfffff234
230 .long 0xc02eff66,0xedc00608,0x6700ff74,0x2caeffd4
231 .long 0x0c00001a,0x6e0000e8,0x67000072,0x082e0005
232 .long 0x0004660a,0x206effd8,0x4e606000,0xfb8e0c2e
233 .long 0x0008ff4a,0x6600fb84,0xf22ed0c0,0xffdcf22e
234 .long 0x9c00ff60,0x4cee0303,0xff9c3d7c,0x30d8000a
235 .long 0x3d7ce006,0xff6ef36e,0xff6c2c56,0x2f6f00c4
236 .long 0x00b82f6f,0x00c800bc,0x2f6f00cc,0x00c02f6f
237 .long 0x003800c4,0x2f6f003c,0x00c82f6f,0x004000cc
238 .long 0xdffc0000,0x00b860ff,0xfffff22c,0x082e0005
239 .long 0x00046600,0x000c206e,0xffd84e60,0x6000fb46
240 .long 0x0c2e0008,0xff4a6600,0xfb3cf22e,0xd0c0ffdc
241 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0x3d7c30d0
242 .long 0x000a3d7c,0xe004ff6e,0xf36eff6c,0x2c562f6f
243 .long 0x00c400b8,0x2f6f00c8,0x00bc2f6f,0x00cc00c0
244 .long 0x2f6f0038,0x00c42f6f,0x003c00c8,0x2f6f0040
245 .long 0x00ccdffc,0x000000b8,0x60ffffff,0xf1a4082e
246 .long 0x00050004,0x6600000c,0x206effd8,0x4e606000
247 .long 0xfbda0c2e,0x0008ff4a,0x6600fbd0,0xf22ed0c0
248 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9c3d7c
249 .long 0x30c4000a,0x3d7ce001,0xff6ef36e,0xff6c2c56
250 .long 0x2f6f00c4,0x00b82f6f,0x00c800bc,0x2f6f00cc
251 .long 0x00c02f6f,0x003800c4,0x2f6f003c,0x00c82f6f
252 .long 0x004000cc,0xdffc0000,0x00b860ff,0xfffff106
253 .long 0xe9ee00c3,0xff420c00,0x00016708,0x0c000005
254 .long 0x67344e75,0x302eff6c,0x02407fff,0x67260c40
255 .long 0x3f806e20,0x44400640,0x3f81222e,0xff70e0a9
256 .long 0x08c1001f,0x2d41ff70,0x026e8000,0xff6c006e
257 .long 0x3f80ff6c,0x4e75302e,0xff6c0240,0x7fff673a
258 .long 0x0c403c00,0x6e344a2e,0xff6c5bee,0xff6e3d40
259 .long 0xff6c4280,0x41eeff6c,0x323c3c01,0x61ff0000
260 .long 0xb156303c,0x3c004a2e,0xff6e6704,0x08c0000f
261 .long 0x08ee0007,0xff703d40,0xff6c4e75,0x082e0005
262 .long 0x000467ff,0xfffff176,0x2d680000,0xff782d68
263 .long 0x0004ff7c,0x2d680008,0xff804281,0x4e752f00
264 .long 0x4e7a0808,0x08000001,0x66000460,0x201f4e56
265 .long 0xff4048ee,0x0303ff9c,0xf22ebc00,0xff60f22e
266 .long 0xf0c0ffdc,0x2d6e0006,0xff44206e,0xff4458ae
267 .long 0xff4461ff,0xfffff152,0x2d40ff40,0x4a406b00
268 .long 0x020e02ae,0x00ff00ff,0xff640800,0x000a6618
269 .long 0x206eff44,0x43eeff6c,0x700c61ff,0xfffff0d2
270 .long 0x4a816600,0x04926048,0x206eff44,0x43eeff6c
271 .long 0x700c61ff,0xfffff0ba,0x4a816600,0x047ae9ee
272 .long 0x004fff6c,0x0c407fff,0x6726102e,0xff6f0200
273 .long 0x000f660c,0x4aaeff70,0x66064aae,0xff746710
274 .long 0x41eeff6c,0x61ff0000,0xb88cf22e,0xf080ff6c
275 .long 0x06ae0000,0x000cff44,0x41eeff6c,0x61ff0000
276 .long 0xb3c21d40,0xff4e0c00,0x0006660a,0x61ff0000
277 .long 0xb3221d40,0xff4e422e,0xff53082e,0x0005ff43
278 .long 0x6748082e,0x0004ff43,0x662ce9ee,0x0183ff42
279 .long 0x61ff0000,0xaeec41ee,0xff7861ff,0x0000b384
280 .long 0x1d40ff4f,0x0c000006,0x662061ff,0x0000b2e4
281 .long 0x1d40ff4f,0x6014082e,0x0003ff43,0x670c50ee
282 .long 0xff53082e,0x0001ff43,0x67c04280,0x102eff63
283 .long 0x122eff43,0x0241007f,0xf23c9000,0x00000000
284 .long 0xf23c8800,0x00000000,0x41eeff6c,0x43eeff78
285 .long 0x223b1530,0x000062ca,0x4ebb1930,0x000062c2
286 .long 0x102eff62,0x66404a2e,0xff53660c,0xe9ee0183
287 .long 0xff4261ff,0x0000aefa,0x2d6e0006,0xff682d6e
288 .long 0xff440006,0xf22ed0c0,0xffdcf22e,0x9c00ff60
289 .long 0x4cee0303,0xff9c4e5e,0x08170007,0x66000096
290 .long 0x60ffffff,0xee6ec02e,0xff66edc0,0x06086612
291 .long 0x082e0004,0xff6667ae,0x082e0001,0xff6267ac
292 .long 0x60340480,0x00000018,0x0c000006,0x6610082e
293 .long 0x0004ff66,0x6620082e,0x0003ff66,0x66203d7b
294 .long 0x0206ff6e,0x601ee002,0xe006e004,0xe005e003
295 .long 0xe002e001,0xe0013d7c,0xe005ff6e,0x60063d7c
296 .long 0xe003ff6e,0x2d6e0006,0xff682d6e,0xff440006
297 .long 0xf22ed0c0,0xffdcf22e,0x9c00ff60,0x4cee0303
298 .long 0xff9cf36e,0xff6c4e5e,0x08170007,0x660660ff
299 .long 0xffffede0,0x2f173f6f,0x00080004,0x3f7c2024
300 .long 0x0006f22f,0xa4000008,0x60ffffff,0xeeb80800
301 .long 0x000e6700,0x01c2082e,0x00050004,0x66164e68
302 .long 0x2d48ffd8,0x61ff0000,0x9564206e,0xffd84e60
303 .long 0x600001aa,0x422eff4a,0x41ee000c,0x2d48ffd8
304 .long 0x61ff0000,0x95480c2e,0x0008ff4a,0x67000086
305 .long 0x0c2e0004,0xff4a6600,0x0184082e,0x00070004
306 .long 0x66363dae,0x00040804,0x2daeff44,0x08063dbc
307 .long 0x00f0080a,0x41f60804,0x2d480004,0xf22ed0c0
308 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9c4e5e
309 .long 0x2e5f60ff,0xffffed3c,0x3dae0004,0x08002dae
310 .long 0xff440802,0x3dbc2024,0x08062dae,0x00060808
311 .long 0x41f60800,0x2d480004,0xf22ed0c0,0xffdcf22e
312 .long 0x9c00ff60,0x4cee0303,0xff9c4e5e,0x2e5f60ff
313 .long 0xffffedf2,0x1d41000a,0x1d40000b,0xf22ed0c0
314 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9c2f16
315 .long 0x2f002f01,0x2f2eff44,0x4280102e,0x000b4480
316 .long 0x082e0007,0x0004671c,0x3dae0004,0x08002dae
317 .long 0x00060808,0x2d9f0802,0x3dbc2024,0x08064876
318 .long 0x08006014,0x3dae0004,0x08042d9f,0x08063dbc
319 .long 0x00f0080a,0x48760804,0x4281122e,0x000a4a01
320 .long 0x6a0cf236,0xf080080c,0x06800000,0x000ce309
321 .long 0x6a0cf236,0xf040080c,0x06800000,0x000ce309
322 .long 0x6a0cf236,0xf020080c,0x06800000,0x000ce309
323 .long 0x6a0cf236,0xf010080c,0x06800000,0x000ce309
324 .long 0x6a0cf236,0xf008080c,0x06800000,0x000ce309
325 .long 0x6a0cf236,0xf004080c,0x06800000,0x000ce309
326 .long 0x6a0cf236,0xf002080c,0x06800000,0x000ce309
327 .long 0x6a06f236,0xf001080c,0x222f0004,0x202f0008
328 .long 0x2c6f000c,0x2e5f0817,0x000767ff,0xffffec04
329 .long 0x60ffffff,0xecf061ff,0x00009bda,0xf22ed0c0
330 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9c082e
331 .long 0x00070004,0x660e2d6e,0xff440006,0x4e5e60ff
332 .long 0xffffebd0,0x2c563f6f,0x00c400c0,0x2f6f00c6
333 .long 0x00c82f6f,0x000400c2,0x3f7c2024,0x00c6dffc
334 .long 0x000000c0,0x60ffffff,0xec9c201f,0x4e56ff40
335 .long 0x48ee0303,0xff9c2d6e,0x0006ff44,0x206eff44
336 .long 0x58aeff44,0x61ffffff,0xed002d40,0xff404a40
337 .long 0x6b047010,0x60260800,0x000e6610,0xe9c014c3
338 .long 0x700c0c01,0x00076614,0x58806010,0x428061ff
339 .long 0x0000967c,0x202eff44,0x90ae0006,0x3d40000a
340 .long 0x4cee0303,0xff9c4e5e,0x518f2f00,0x3f6f000c
341 .long 0x00042f6f,0x000e0006,0x4280302f,0x00122f6f
342 .long 0x00060010,0xd1af0006,0x3f7c402c,0x000a201f
343 .long 0x60ffffff,0xebe44e7a,0x08080800,0x0001660c
344 .long 0xf22e9c00,0xff60f22e,0xd0c0ffdc,0x4cee0303
345 .long 0xff9c4e5e,0x514f2eaf,0x00083f6f,0x000c0004
346 .long 0x3f7c4008,0x00062f6f,0x00020008,0x2f7c0942
347 .long 0x8001000c,0x08170005,0x670608ef,0x0002000d
348 .long 0x60ffffff,0xebd64fee,0xff404e7a,0x18080801
349 .long 0x0001660c,0xf22ed0c0,0xffdcf22f,0x9c000020
350 .long 0x2c562f6f,0x00c400bc,0x3f6f00c8,0x00c03f7c
351 .long 0x400800c2,0x2f4800c4,0x3f4000c8,0x3f7c0001
352 .long 0x00ca4cef,0x0303005c,0xdefc00bc,0x60a64e56
353 .long 0xff40f32e,0xff6c48ee,0x0303ff9c,0xf22ebc00
354 .long 0xff60f22e,0xf0c0ffdc,0x2d6eff68,0xff44206e
355 .long 0xff4458ae,0xff4461ff,0xffffebce,0x2d40ff40
356 .long 0x0800000d,0x662841ee,0xff6c61ff,0xfffff1ea
357 .long 0xf22ed0c0,0xffdcf22e,0x9c00ff60,0x4cee0303
358 .long 0xff9cf36e,0xff6c4e5e,0x60ffffff,0xea94322e
359 .long 0xff6c0241,0x7fff0c41,0x7fff661a,0x4aaeff74
360 .long 0x660c222e,0xff700281,0x7fffffff,0x67082d6e
361 .long 0xff70ff54,0x6012223c,0x7fffffff,0x4a2eff6c
362 .long 0x6a025281,0x2d41ff54,0xe9c004c3,0x122eff41
363 .long 0x307b0206,0x4efb8802,0x006c0000,0x0000ff98
364 .long 0x003e0000,0x00100000,0x102eff54,0x0c010007
365 .long 0x6f16206e,0x000c61ff,0xffffeb86,0x4a8166ff
366 .long 0x0000bca8,0x6000ff6a,0x02410007,0x61ff0000
367 .long 0xa8046000,0xff5c302e,0xff540c01,0x00076f16
368 .long 0x206e000c,0x61ffffff,0xeb6e4a81,0x66ff0000
369 .long 0xbc886000,0xff3c0241,0x000761ff,0x0000a79a
370 .long 0x6000ff2e,0x202eff54,0x0c010007,0x6f16206e
371 .long 0x000c61ff,0xffffeb56,0x4a8166ff,0x0000bc68
372 .long 0x6000ff0e,0x02410007,0x61ff0000,0xa7306000
373 .long 0xff004e56,0xff40f32e,0xff6c48ee,0x0303ff9c
374 .long 0xf22ebc00,0xff60f22e,0xf0c0ffdc,0x2d6eff68
375 .long 0xff44206e,0xff4458ae,0xff4461ff,0xffffea8a
376 .long 0x2d40ff40,0x0800000d,0x6600002a,0x41eeff6c
377 .long 0x61ffffff,0xf0a4f22e,0xd0c0ffdc,0xf22e9c00
378 .long 0xff604cee,0x0303ff9c,0xf36eff6c,0x4e5e60ff
379 .long 0xffffe964,0xe9c004c3,0x122eff41,0x307b0206
380 .long 0x4efb8802,0x007400a6,0x015a0000,0x00420104
381 .long 0x00100000,0x102eff70,0x08c00006,0x0c010007
382 .long 0x6f16206e,0x000c61ff,0xffffea76,0x4a8166ff
383 .long 0x0000bb98,0x6000ffa0,0x02410007,0x61ff0000
384 .long 0xa6f46000,0xff92302e,0xff7008c0,0x000e0c01
385 .long 0x00076f16,0x206e000c,0x61ffffff,0xea5a4a81
386 .long 0x66ff0000,0xbb746000,0xff6e0241,0x000761ff
387 .long 0x0000a686,0x6000ff60,0x202eff70,0x08c0001e
388 .long 0x0c010007,0x6f16206e,0x000c61ff,0xffffea3e
389 .long 0x4a8166ff,0x0000bb50,0x6000ff3c,0x02410007
390 .long 0x61ff0000,0xa6186000,0xff2e0c01,0x00076f2e
391 .long 0x202eff6c,0x02808000,0x00000080,0x7fc00000
392 .long 0x222eff70,0xe0898081,0x206e000c,0x61ffffff
393 .long 0xe9fc4a81,0x66ff0000,0xbb0e6000,0xfefa202e
394 .long 0xff6c0280,0x80000000,0x00807fc0,0x00002f01
395 .long 0x222eff70,0xe0898081,0x221f0241,0x000761ff
396 .long 0x0000a5ba,0x6000fed0,0x202eff6c,0x02808000
397 .long 0x00000080,0x7ff80000,0x222eff70,0x2d40ff84
398 .long 0x700be0a9,0x83aeff84,0x222eff70,0x02810000
399 .long 0x07ffe0b9,0x2d41ff88,0x222eff74,0xe0a983ae
400 .long 0xff8841ee,0xff84226e,0x000c7008,0x61ffffff
401 .long 0xe8cc4a81,0x66ff0000,0xba9c6000,0xfe7a422e
402 .long 0xff4a3d6e,0xff6cff84,0x426eff86,0x202eff70
403 .long 0x08c0001e,0x2d40ff88,0x2d6eff74,0xff8c082e
404 .long 0x00050004,0x66384e68,0x2d48ffd8,0x2d56ffd4
405 .long 0x61ff0000,0x98922248,0x2d48000c,0x206effd8
406 .long 0x4e602cae,0xffd441ee,0xff84700c,0x61ffffff
407 .long 0xe86c4a81,0x66ff0000,0xba4a6000,0xfe1a2d56
408 .long 0xffd461ff,0x00009860,0x22482d48,0x000c2cae
409 .long 0xffd40c2e,0x0008ff4a,0x66ccf22e,0xd0c0ffdc
410 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0xf36eff6c
411 .long 0x2c6effd4,0x2f6f00c4,0x00b82f6f,0x00c800bc
412 .long 0x2f6f00cc,0x00c02f6f,0x004400c4,0x2f6f0048
413 .long 0x00c82f6f,0x004c00cc,0xdffc0000,0x00b860ff
414 .long 0xffffe734,0x4e56ff40,0xf32eff6c,0x48ee0303
415 .long 0xff9cf22e,0xbc00ff60,0xf22ef0c0,0xffdc2d6e
416 .long 0xff68ff44,0x206eff44,0x58aeff44,0x61ffffff
417 .long 0xe7f82d40,0xff400800,0x000d6600,0x0106e9c0
418 .long 0x04c36622,0x0c6e401e,0xff6c661a,0xf23c9000
419 .long 0x00000000,0xf22e4000,0xff70f22e,0x6800ff6c
420 .long 0x3d7ce001,0xff6e41ee,0xff6c61ff,0xffffedea
421 .long 0x02ae00ff,0x01ffff64,0xf23c9000,0x00000000
422 .long 0xf23c8800,0x00000000,0xe9ee1006,0xff420c01
423 .long 0x00176700,0x009641ee,0xff6c61ff,0x0000aa84
424 .long 0x1d40ff4e,0x082e0005,0xff43672e,0x082e0004
425 .long 0xff436626,0xe9ee0183,0xff4261ff,0x0000a5c2
426 .long 0x41eeff78,0x61ff0000,0xaa5a0c00,0x00066606
427 .long 0x61ff0000,0xa9be1d40,0xff4f4280,0x102eff63
428 .long 0x122eff43,0x0241007f,0x41eeff6c,0x43eeff78
429 .long 0x223b1530,0x000059ca,0x4ebb1930,0x000059c2
430 .long 0xe9ee0183,0xff4261ff,0x0000a606,0xf22ed0c0
431 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9cf36e
432 .long 0xff6c4e5e,0x60ffffff,0xe5cc4280,0x102eff63
433 .long 0x122eff43,0x02810000,0x007f61ff,0x000043ce
434 .long 0x60be1d7c,0x0000ff4e,0x4280102e,0xff6302ae
435 .long 0xffff00ff,0xff6441ee,0xff6c61ff,0x00009be4
436 .long 0x60aa4e56,0xff40f32e,0xff6c48ee,0x0303ff9c
437 .long 0xf22ebc00,0xff60f22e,0xf0c0ffdc,0x2d6eff68
438 .long 0xff44206e,0xff4458ae,0xff4461ff,0xffffe69a
439 .long 0x2d40ff40,0x41eeff6c,0x61ffffff,0xecbcf22e
440 .long 0xd0c0ffdc,0xf22e9c00,0xff604cee,0x0303ff9c
441 .long 0xf36eff6c,0x4e5e60ff,0xffffe592,0x0c6f202c
442 .long 0x000667ff,0x000000aa,0x0c6f402c,0x000667ff
443 .long 0xffffe5a6,0x4e56ff40,0x48ee0303,0xff9c2d6e
444 .long 0x0006ff44,0x206eff44,0x58aeff44,0x61ffffff
445 .long 0xe638e9c0,0x100a0c41,0x03c86664,0xe9c01406
446 .long 0x0c010017,0x665a4e7a,0x08080800,0x0001672a
447 .long 0x4cee0303,0xff9c4e5e,0x518f3eaf,0x00082f6f
448 .long 0x000a0002,0x3f7c402c,0x00062f6f,0x0002000c
449 .long 0x58af0002,0x60ffffff,0xe5404cee,0x0303ff9c
450 .long 0x4e5ef22f,0x84000002,0x58af0002,0x2f172f6f
451 .long 0x00080004,0x1f7c0020,0x000660ff,0x00000012
452 .long 0x4cee0303,0xff9c4e5e,0x60ffffff,0xe4f64e56
453 .long 0xff4048ee,0x0303ff9c,0xf22ebc00,0xff60f22e
454 .long 0xf0c0ffdc,0x082e0005,0x00046608,0x4e682d48
455 .long 0xffd8600c,0x41ee0010,0x2d48ffd8,0x2d48ffd4
456 .long 0x2d6eff68,0xff44206e,0xff4458ae,0xff4461ff
457 .long 0xffffe576,0x2d40ff40,0xf23c9000,0x00000000
458 .long 0xf23c8800,0x00000000,0x422eff4a,0x08000016
459 .long 0x66000182,0x422eff53,0x02ae00ff,0x00ffff64
460 .long 0xe9c01406,0x0c010017,0x670000be,0x61ff0000
461 .long 0x95fc4280,0x102eff63,0x122eff43,0x0241003f
462 .long 0xe749822e,0xff4e43ee,0xff7841ee,0xff6c323b
463 .long 0x132002b2,0x4ebb1120,0x02ac102e,0xff626600
464 .long 0x00a2e9ee,0x0183ff42,0x61ff0000,0xa3e4f22e
465 .long 0xd0c0ffdc,0xf22e9c00,0xff604cee,0x0303ff9c
466 .long 0x0c2e0004,0xff4a672a,0x0c2e0008,0xff4a6722
467 .long 0x4e5e0817,0x000767ff,0xffffe358,0xf327f22f
468 .long 0xa4000014,0xf35f3f7c,0x20240006,0x60ffffff
469 .long 0xe434082e,0x00050004,0x660c2f08,0x206effd8
470 .long 0x4e60205f,0x60ca2f00,0x202effd8,0x90aeffd4
471 .long 0x2dae0008,0x08082dae,0x00040804,0x3d400004
472 .long 0x201f4e5e,0xded760aa,0x4280102e,0xff63122e
473 .long 0xff430281,0x0000007f,0x61ff0000,0x41506000
474 .long 0xff5ac02e,0xff66edc0,0x06086616,0x082e0004
475 .long 0xff666700,0xff4e082e,0x0001ff62,0x6700ff44
476 .long 0x603e0480,0x00000018,0x0c000006,0x6610082e
477 .long 0x0004ff66,0x662a082e,0x0003ff66,0x66302f00
478 .long 0x61ffffff,0xf1ee201f,0x3d7b0206,0xff6e602a
479 .long 0xe002e006,0xe004e005,0xe003e002,0xe001e001
480 .long 0x61ffffff,0xf1ce3d7c,0xe005ff6e,0x600c61ff
481 .long 0xfffff1c0,0x3d7ce003,0xff6ef22e,0xd0c0ffdc
482 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0xf36eff6c
483 .long 0x6000feee,0xe9c01283,0x0c010001,0x67000056
484 .long 0x0c010007,0x66000078,0xe9c01343,0x0c010002
485 .long 0x6d00006c,0x61ff0000,0x82780c2e,0x0002ff4a
486 .long 0x670000d2,0x0c2e0001,0xff4a6600,0x01002d6e
487 .long 0xff68000c,0x3d7c201c,0x000af22e,0xd0c0ffdc
488 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0x4e5e60ff
489 .long 0xffffe2dc,0x206eff44,0x54aeff44,0x61ffffff
490 .long 0xe3524a81,0x6600047c,0x48c061ff,0x00007e60
491 .long 0x0c2e0002,0xff4a6700,0x007c6000,0x00b061ff
492 .long 0x00008562,0x0c2e0002,0xff4a6700,0x0068082e
493 .long 0x00050004,0x660a206e,0xffd84e60,0x6000008e
494 .long 0x0c2e0008,0xff4a6600,0x0084f22e,0xd0c0ffdc
495 .long 0xf22e9c00,0xff604cee,0x0303ff9c,0x4e5e0817
496 .long 0x00076612,0x558f2eaf,0x00022f6f,0x00060004
497 .long 0x60ffffff,0xe17e558f,0x2eaf0002,0x3f6f0006
498 .long 0x00043f7c,0x20240006,0xf22fa400,0x000860ff
499 .long 0xffffe252,0x3d7c00c0,0x000e2d6e,0xff68000a
500 .long 0x3d6e0004,0x00083d7c,0xe000ff6e,0xf22ed0c0
501 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9cf36e
502 .long 0xff6c4e5e,0x588f60ff,0xffffe180,0xf22ed0c0
503 .long 0xffdcf22e,0x9c00ff60,0x4cee0303,0xff9c4e5e
504 .long 0x08170007,0x660660ff,0xffffe108,0xf22fa400
505 .long 0x00081f7c,0x00240007,0x60ffffff,0xe1e84afc
506 .long 0x01c00000,0x00000000,0x00000000,0x00000000
507 .long 0x00000000,0x00000000,0x00000000,0x00000000
508 .long 0x000028a4,0x4b1e4b4c,0x4f4c2982,0x4f3c0000
509 .long 0x00000000,0x00000000,0x00000000,0x00000000
510 .long 0x00000000,0x00000000,0x00000000,0x00000000
511 .long 0x00000000,0x00000000,0x00000000,0x00000000
512 .long 0x000035c6,0x4b1e4b82,0x4f4c371a,0x4f3c0000
513 .long 0x00000000,0x00000000,0x00000000,0x00000000
514 .long 0x000024b0,0x4b1e4b8c,0x4f4c2766,0x4f3c0000
515 .long 0x00002988,0x4b1e4b94,0x4f4c2af0,0x4f3c0000
516 .long 0x00001ab8,0x4b1e4bd0,0x4f4c1cf6,0x4f3c0000
517 .long 0x00000000,0x00000000,0x00000000,0x00000000
518 .long 0x00001cfc,0x4b1e4744,0x4f4c1daa,0x4f3c0000
519 .long 0x00003720,0x4b1e4744,0x4f4c37a2,0x4f3c0000
520 .long 0x00000468,0x4b1e4744,0x4f4c064c,0x4f3c0000
521 .long 0x00000f2a,0x4b1e4744,0x4f4c108e,0x4f3c0000
522 .long 0x000022e0,0x4b9a4b7a,0x4f4c248c,0x4f3c0000
523 .long 0x00003d02,0x4b9a4b7a,0x4f4c3ddc,0x4f3c0000
524 .long 0x00003dfa,0x4b9a4b7a,0x4f4c3f2a,0x4f3c0000
525 .long 0x00000000,0x00000000,0x00000000,0x00000000
526 .long 0x00003386,0x47324b82,0x4f4c3538,0x4f3c0000
527 .long 0x000037c8,0x47324b82,0x4f4c37f8,0x4f3c0000
528 .long 0x00003818,0x47324b82,0x4f4c3872,0x4f3c0000
529 .long 0x00000000,0x00000000,0x00000000,0x00000000
530 .long 0x00000000,0x00000000,0x00000000,0x00000000
531 .long 0x000027e6,0x4b9a4b52,0x4f4c288a,0x4f3c0000
532 .long 0x00000000,0x00000000,0x00000000,0x00000000
533 .long 0x00000000,0x00000000,0x00000000,0x00000000
534 .long 0x00001db0,0x4bd64744,0x4f4c1e40,0x4f3c0000
535 .long 0x00000472,0x4b9a4744,0x4f4c0652,0x4f3c0000
536 .long 0x0000276c,0x4b1e4744,0x4f4c2788,0x4f3c0000
537 .long 0x000027a0,0x4b1e4744,0x4f4c27ce,0x4f3c0000
538 .long 0x00000000,0x00000000,0x00000000,0x00000000
539 .long 0x00004ca4,0x4cda4d12,0x4ee24ca4,0x4ef40000
540 .long 0x00000000,0x00000000,0x00000000,0x00000000
541 .long 0x00000000,0x00000000,0x00000000,0x00000000
542 .long 0x00000000,0x00000000,0x00000000,0x00000000
543 .long 0x00004dac,0x4de24e1a,0x4ee24dac,0x4ef40000
544 .long 0x00004e4e,0x4e864ebe,0x4ee24e4e,0x4ef40000
545 .long 0x00000000,0x00000000,0x00000000,0x00000000
546 .long 0x00000000,0x00000000,0x00000000,0x00000000
547 .long 0x00000000,0x00000000,0x00000000,0x00000000
548 .long 0x00000000,0x00000000,0x00000000,0x00000000
549 .long 0x00000000,0x00000000,0x00000000,0x00000000
550 .long 0x00000000,0x00000000,0x00000000,0x00000000
551 .long 0x00000000,0x00000000,0x00000000,0x00000000
552 .long 0x00000000,0x00000000,0x00000000,0x00000000
553 .long 0x00000000,0x00000000,0x00000000,0x00000000
554 .long 0x00000660,0x4bf24c20,0x4c3008f6,0x4c400000
555 .long 0x00000660,0x4bf24c20,0x4c3008f6,0x4c400000
556 .long 0x00000660,0x4bf24c20,0x4c3008f6,0x4c400000
557 .long 0x00000660,0x4bf24c20,0x4c3008f6,0x4c400000
558 .long 0x00000660,0x4bf24c20,0x4c3008f6,0x4c400000
559 .long 0x00000660,0x4bf24c20,0x4c3008f6,0x4c400000
560 .long 0x00000660,0x4bf24c20,0x4c3008f6,0x4c400000
561 .long 0x00000660,0x4bf24c20,0x4c3008f6,0x4c400000
562 .long 0x00004cee,0x0303ff9c,0xf22e9c00,0xff60f22e
563 .long 0xd0c0ffdc,0x2d6eff68,0x00064e5e,0x2f173f6f
564 .long 0x00080004,0x3f7c4008,0x00062f6f,0x00020008
565 .long 0x2f7c0942,0x8001000c,0x08170005,0x670608ef
566 .long 0x0002000d,0x60ffffff,0xde32bd6a,0xaa77ccc9
567 .long 0x94f53de6,0x12097aae,0x8da1be5a,0xe6452a11
568 .long 0x8ae43ec7,0x1de3a534,0x1531bf2a,0x01a01a01
569 .long 0x8b590000,0x00000000,0x00003ff8,0x00008888
570 .long 0x88888888,0x59af0000,0x0000bffc,0x0000aaaa
571 .long 0xaaaaaaaa,0xaa990000,0x00003d2a,0xc4d0d601
572 .long 0x1ee3bda9,0x396f9f45,0xac193e21,0xeed90612
573 .long 0xc972be92,0x7e4fb79d,0x9fcf3efa,0x01a01a01
574 .long 0xd4230000,0x00000000,0x0000bff5,0x0000b60b
575 .long 0x60b60b61,0xd4380000,0x00003ffa,0x0000aaaa
576 .long 0xaaaaaaaa,0xab5ebf00,0x00002d7c,0x00000000
577 .long 0xff5c6008,0x2d7c0000,0x0001ff5c,0xf2104800
578 .long 0xf22e6800,0xff842210,0x32280004,0x02817fff
579 .long 0xffff0c81,0x3fd78000,0x6c046000,0x01780c81
580 .long 0x4004bc7e,0x6d046000,0x0468f200,0x0080f23a
581 .long 0x54a3de7e,0x43fb0170,0x00000866,0xf22e6080
582 .long 0xff58222e,0xff58e981,0xd3c1f219,0x4828f211
583 .long 0x4428222e,0xff58d2ae,0xff5ce299,0x0c810000
584 .long 0x00006d00,0x0088f227,0xe00cf22e,0x6800ff84
585 .long 0xf2000023,0xf23a5580,0xfed2f23a,0x5500fed4
586 .long 0xf2000080,0xf20004a3,0xe2990281,0x80000000
587 .long 0xb3aeff84,0xf20005a3,0xf2000523,0xf23a55a2
588 .long 0xfebaf23a,0x5522febc,0xf20005a3,0xf2000523
589 .long 0xf23a55a2,0xfeb6f23a,0x4922fec0,0xf2000ca3
590 .long 0xf2000123,0xf23a48a2,0xfec2f22e,0x4823ff84
591 .long 0xf20008a2,0xf2000423,0xf21fd030,0xf2009000
592 .long 0xf22e4822,0xff8460ff,0x00004364,0xf227e00c
593 .long 0xf2000023,0xf23a5500,0xfea2f23a,0x5580fea4
594 .long 0xf2000080,0xf20004a3,0xf22e6800,0xff84e299
595 .long 0x02818000,0x0000f200,0x0523b3ae,0xff840281
596 .long 0x80000000,0xf20005a3,0x00813f80,0x00002d41
597 .long 0xff54f23a,0x5522fe74,0xf23a55a2,0xfe76f200
598 .long 0x0523f200,0x05a3f23a,0x5522fe70,0xf23a49a2
599 .long 0xfe7af200,0x0523f200,0x0ca3f23a,0x4922fe7c
600 .long 0xf23a44a2,0xfe82f200,0x0823f200,0x0422f22e
601 .long 0x4823ff84,0xf21fd030,0xf2009000,0xf22e4422
602 .long 0xff5460ff,0x000042c8,0x0c813fff,0x80006eff
603 .long 0x00000300,0x222eff5c,0x0c810000,0x00006e14
604 .long 0xf2009000,0x123c0003,0xf22e4800,0xff8460ff
605 .long 0x0000428e,0xf23c4400,0x3f800000,0xf2009000
606 .long 0xf23c4422,0x80800000,0x60ff0000,0x428a60ff
607 .long 0x00004110,0xf23c4400,0x3f800000,0x60ff0000
608 .long 0x42762d7c,0x00000004,0xff5cf210,0x4800f22e
609 .long 0x6800ff84,0x22103228,0x00040281,0x7fffffff
610 .long 0x0c813fd7,0x80006c04,0x60000240,0x0c814004
611 .long 0xbc7e6d04,0x6000027a,0xf2000080,0xf23a54a3
612 .long 0xdc9043fb,0x01700000,0x0678f22e,0x6080ff58
613 .long 0x222eff58,0xe981d3c1,0xf2194828,0xf2114428
614 .long 0x222eff58,0xe2990c81,0x00000000,0x6c000106
615 .long 0xf227e004,0xf22e6800,0xff84f200,0x0023f23a
616 .long 0x5480fce8,0xf23a5500,0xfd32f200,0x00a3f200
617 .long 0x01232f02,0x2401e29a,0x02828000,0x0000b382
618 .long 0x02828000,0x0000f23a,0x54a2fcc8,0xf23a5522
619 .long 0xfd12f200,0x00a3b5ae,0xff84241f,0xf2000123
620 .long 0xe2990281,0x80000000,0x2d7c3f80,0x0000ff54
621 .long 0xb3aeff54,0xf23a54a2,0xfca2f23a,0x5522fcec
622 .long 0xf20000a3,0xf2000123,0xf22e6800,0xff90f23a
623 .long 0x54a2fc90,0xb3aeff90,0xf23a5522,0xfcd6f200
624 .long 0x00a3f200,0x0123f23a,0x54a2fc80,0xf23a5522
625 .long 0xfccaf200,0x00a3f200,0x0123f23a,0x48a2fc7c
626 .long 0xf23a4922,0xfcc6f200,0x00a3f200,0x0123f23a
627 .long 0x48a2fc78,0xf23a4922,0xfcc2f200,0x00a3f200
628 .long 0x0823f22e,0x48a3ff84,0xf23a4422,0xfcbaf22e
629 .long 0x4823ff90,0xf21fd020,0xf2009000,0xf22e48a2
630 .long 0xff8461ff,0x0000448e,0xf22e4422,0xff5460ff
631 .long 0x000040fc,0xf227e004,0xf22e6800,0xff84f200
632 .long 0x0023f23a,0x5480fc34,0xf23a5500,0xfbdef200
633 .long 0x00a3f22e,0x6800ff90,0xf2000123,0xe2990281
634 .long 0x80000000,0xf23a54a2,0xfc1af23a,0x5522fbc4
635 .long 0xb3aeff84,0xb3aeff90,0xf20000a3,0x00813f80
636 .long 0x00002d41,0xff54f200,0x0123f23a,0x54a2fbfc
637 .long 0xf23a5522,0xfba6f200,0x00a3f200,0x0123f23a
638 .long 0x54a2fbf0,0xf23a5522,0xfb9af200,0x00a3f200
639 .long 0x0123f23a,0x54a2fbe4,0xf23a5522,0xfb8ef200
640 .long 0x00a3f200,0x0123f23a,0x48a2fbe0,0xf23a4922
641 .long 0xfb8af200,0x00a3f200,0x0123f23a,0x48a2fbdc
642 .long 0xf23a4922,0xfb86f200,0x00a3f200,0x0823f23a
643 .long 0x44a2fbd4,0xf22e4823,0xff84f22e,0x48a3ff90
644 .long 0xf21fd020,0xf2009000,0xf22e44a2,0xff5461ff
645 .long 0x000043a2,0xf22e4822,0xff8460ff,0x00004010
646 .long 0x0c813fff,0x80006e00,0x0048f23c,0x44803f80
647 .long 0x0000f200,0x9000f23c,0x44a80080,0x000061ff
648 .long 0x00004372,0xf200b000,0x123c0003,0xf22e4800
649 .long 0xff8460ff,0x00003fca,0x2f00f23c,0x44803f80
650 .long 0x000061ff,0x0000434e,0x201f60ff,0x00003e54
651 .long 0xf227e03c,0x2f02f23c,0x44800000,0x00000c81
652 .long 0x7ffeffff,0x66523d7c,0x7ffeff84,0x2d7cc90f
653 .long 0xdaa2ff88,0x42aeff8c,0x3d7c7fdc,0xff902d7c
654 .long 0x85a308d3,0xff9442ae,0xff98f200,0x003af294
655 .long 0x000e002e,0x0080ff84,0x002e0080,0xff90f22e
656 .long 0x4822ff84,0xf2000080,0xf22e4822,0xff90f200
657 .long 0x00a8f22e,0x48a2ff90,0xf22e6800,0xff84322e
658 .long 0xff842241,0x02810000,0x7fff0481,0x00003fff
659 .long 0x0c810000,0x001c6f0e,0x04810000,0x001b1d7c
660 .long 0x0000ff58,0x60084281,0x1d7c0001,0xff58243c
661 .long 0x00003ffe,0x94812d7c,0xa2f9836e,0xff882d7c
662 .long 0x4e44152a,0xff8c3d42,0xff84f200,0x0100f22e
663 .long 0x4923ff84,0x24094842,0x02828000,0x00000082
664 .long 0x5f000000,0x2d42ff54,0xf22e4522,0xff54f22e
665 .long 0x4528ff54,0x24010682,0x00003fff,0x3d42ff84
666 .long 0x2d7cc90f,0xdaa2ff88,0x42aeff8c,0x06810000
667 .long 0x3fdd3d41,0xff902d7c,0x85a308d3,0xff9442ae
668 .long 0xff98122e,0xff58f200,0x0a00f22e,0x4a23ff84
669 .long 0xf2000a80,0xf22e4aa3,0xff90f200,0x1180f200
670 .long 0x15a2f200,0x0e28f200,0x0c28f200,0x1622f200
671 .long 0x0180f200,0x10a8f200,0x04220c01,0x00006e00
672 .long 0x000ef200,0x01a8f200,0x0ca26000,0xff0cf22e
673 .long 0x6100ff58,0x241ff21f,0xd03c222e,0xff5c0c81
674 .long 0x00000004,0x6d00fa4c,0x6000fc36,0x3ea0b759
675 .long 0xf50f8688,0xbef2baa5,0xa8924f04,0xbf346f59
676 .long 0xb39ba65f,0x00000000,0x00000000,0x3ff60000
677 .long 0xe073d3fc,0x199c4a00,0x00000000,0x3ff90000
678 .long 0xd23cd684,0x15d95fa1,0x00000000,0xbffc0000
679 .long 0x8895a6c5,0xfb423bca,0x00000000,0xbffd0000
680 .long 0xeef57e0d,0xa84bc8ce,0x00000000,0x3ffc0000
681 .long 0xa2f9836e,0x4e44152a,0x00000000,0x40010000
682 .long 0xc90fdaa2,0x00000000,0x00000000,0x3fdf0000
683 .long 0x85a308d4,0x00000000,0x00000000,0xc0040000
684 .long 0xc90fdaa2,0x2168c235,0x21800000,0xc0040000
685 .long 0xc2c75bcd,0x105d7c23,0xa0d00000,0xc0040000
686 .long 0xbc7edcf7,0xff523611,0xa1e80000,0xc0040000
687 .long 0xb6365e22,0xee46f000,0x21480000,0xc0040000
688 .long 0xafeddf4d,0xdd3ba9ee,0xa1200000,0xc0040000
689 .long 0xa9a56078,0xcc3063dd,0x21fc0000,0xc0040000
690 .long 0xa35ce1a3,0xbb251dcb,0x21100000,0xc0040000
691 .long 0x9d1462ce,0xaa19d7b9,0xa1580000,0xc0040000
692 .long 0x96cbe3f9,0x990e91a8,0x21e00000,0xc0040000
693 .long 0x90836524,0x88034b96,0x20b00000,0xc0040000
694 .long 0x8a3ae64f,0x76f80584,0xa1880000,0xc0040000
695 .long 0x83f2677a,0x65ecbf73,0x21c40000,0xc0030000
696 .long 0xfb53d14a,0xa9c2f2c2,0x20000000,0xc0030000
697 .long 0xeec2d3a0,0x87ac669f,0x21380000,0xc0030000
698 .long 0xe231d5f6,0x6595da7b,0xa1300000,0xc0030000
699 .long 0xd5a0d84c,0x437f4e58,0x9fc00000,0xc0030000
700 .long 0xc90fdaa2,0x2168c235,0x21000000,0xc0030000
701 .long 0xbc7edcf7,0xff523611,0xa1680000,0xc0030000
702 .long 0xafeddf4d,0xdd3ba9ee,0xa0a00000,0xc0030000
703 .long 0xa35ce1a3,0xbb251dcb,0x20900000,0xc0030000
704 .long 0x96cbe3f9,0x990e91a8,0x21600000,0xc0030000
705 .long 0x8a3ae64f,0x76f80584,0xa1080000,0xc0020000
706 .long 0xfb53d14a,0xa9c2f2c2,0x1f800000,0xc0020000
707 .long 0xe231d5f6,0x6595da7b,0xa0b00000,0xc0020000
708 .long 0xc90fdaa2,0x2168c235,0x20800000,0xc0020000
709 .long 0xafeddf4d,0xdd3ba9ee,0xa0200000,0xc0020000
710 .long 0x96cbe3f9,0x990e91a8,0x20e00000,0xc0010000
711 .long 0xfb53d14a,0xa9c2f2c2,0x1f000000,0xc0010000
712 .long 0xc90fdaa2,0x2168c235,0x20000000,0xc0010000
713 .long 0x96cbe3f9,0x990e91a8,0x20600000,0xc0000000
714 .long 0xc90fdaa2,0x2168c235,0x1f800000,0xbfff0000
715 .long 0xc90fdaa2,0x2168c235,0x1f000000,0x00000000
716 .long 0x00000000,0x00000000,0x00000000,0x3fff0000
717 .long 0xc90fdaa2,0x2168c235,0x9f000000,0x40000000
718 .long 0xc90fdaa2,0x2168c235,0x9f800000,0x40010000
719 .long 0x96cbe3f9,0x990e91a8,0xa0600000,0x40010000
720 .long 0xc90fdaa2,0x2168c235,0xa0000000,0x40010000
721 .long 0xfb53d14a,0xa9c2f2c2,0x9f000000,0x40020000
722 .long 0x96cbe3f9,0x990e91a8,0xa0e00000,0x40020000
723 .long 0xafeddf4d,0xdd3ba9ee,0x20200000,0x40020000
724 .long 0xc90fdaa2,0x2168c235,0xa0800000,0x40020000
725 .long 0xe231d5f6,0x6595da7b,0x20b00000,0x40020000
726 .long 0xfb53d14a,0xa9c2f2c2,0x9f800000,0x40030000
727 .long 0x8a3ae64f,0x76f80584,0x21080000,0x40030000
728 .long 0x96cbe3f9,0x990e91a8,0xa1600000,0x40030000
729 .long 0xa35ce1a3,0xbb251dcb,0xa0900000,0x40030000
730 .long 0xafeddf4d,0xdd3ba9ee,0x20a00000,0x40030000
731 .long 0xbc7edcf7,0xff523611,0x21680000,0x40030000
732 .long 0xc90fdaa2,0x2168c235,0xa1000000,0x40030000
733 .long 0xd5a0d84c,0x437f4e58,0x1fc00000,0x40030000
734 .long 0xe231d5f6,0x6595da7b,0x21300000,0x40030000
735 .long 0xeec2d3a0,0x87ac669f,0xa1380000,0x40030000
736 .long 0xfb53d14a,0xa9c2f2c2,0xa0000000,0x40040000
737 .long 0x83f2677a,0x65ecbf73,0xa1c40000,0x40040000
738 .long 0x8a3ae64f,0x76f80584,0x21880000,0x40040000
739 .long 0x90836524,0x88034b96,0xa0b00000,0x40040000
740 .long 0x96cbe3f9,0x990e91a8,0xa1e00000,0x40040000
741 .long 0x9d1462ce,0xaa19d7b9,0x21580000,0x40040000
742 .long 0xa35ce1a3,0xbb251dcb,0xa1100000,0x40040000
743 .long 0xa9a56078,0xcc3063dd,0xa1fc0000,0x40040000
744 .long 0xafeddf4d,0xdd3ba9ee,0x21200000,0x40040000
745 .long 0xb6365e22,0xee46f000,0xa1480000,0x40040000
746 .long 0xbc7edcf7,0xff523611,0x21e80000,0x40040000
747 .long 0xc2c75bcd,0x105d7c23,0x20d00000,0x40040000
748 .long 0xc90fdaa2,0x2168c235,0xa1800000,0xf2104800
749 .long 0x22103228,0x00040281,0x7fffffff,0x0c813fd7
750 .long 0x80006c04,0x60000134,0x0c814004,0xbc7e6d04
751 .long 0x60000144,0xf2000080,0xf23a54a3,0xd3d443fa
752 .long 0xfdbcf201,0x6080e981,0xd3c1f219,0x4828f211
753 .long 0x4428ea99,0x02818000,0x0000f227,0xe00c0c81
754 .long 0x00000000,0x6d000072,0xf2000080,0xf20004a3
755 .long 0xf23a5580,0xfaf8f23a,0x5500fafa,0xf20005a3
756 .long 0xf2000523,0xf23a55a2,0xfaf4f23a,0x4922fafe
757 .long 0xf20005a3,0xf2000523,0xf23a49a2,0xfb00f23a
758 .long 0x4922fb0a,0xf20005a3,0xf2000523,0xf23a49a2
759 .long 0xfb0cf200,0x0123f200,0x0ca3f200,0x0822f23c
760 .long 0x44a23f80,0x0000f21f,0xd030f200,0x9000f200
761 .long 0x042060ff,0x000038d8,0xf2000080,0xf2000023
762 .long 0xf23a5580,0xfa88f23a,0x5500fa8a,0xf20001a3
763 .long 0xf2000123,0xf23a55a2,0xfa84f23a,0x4922fa8e
764 .long 0xf20001a3,0xf2000123,0xf23a49a2,0xfa90f23a
765 .long 0x4922fa9a,0xf20001a3,0xf2000123,0xf23a49a2
766 .long 0xfa9cf200,0x0523f200,0x0c23f200,0x08a2f23c
767 .long 0x44223f80,0x0000f21f,0xd030f227,0x68800a97
768 .long 0x80000000,0xf2009000,0xf21f4820,0x60ff0000
769 .long 0x385e0c81,0x3fff8000,0x6e1cf227,0x6800f200
770 .long 0x9000123c,0x0003f21f,0x480060ff,0x00003832
771 .long 0x60ff0000,0x36cef227,0xe03c2f02,0xf23c4480
772 .long 0x00000000,0x0c817ffe,0xffff6652,0x3d7c7ffe
773 .long 0xff842d7c,0xc90fdaa2,0xff8842ae,0xff8c3d7c
774 .long 0x7fdcff90,0x2d7c85a3,0x08d3ff94,0x42aeff98
775 .long 0xf200003a,0xf294000e,0x002e0080,0xff84002e
776 .long 0x0080ff90,0xf22e4822,0xff84f200,0x0080f22e
777 .long 0x4822ff90,0xf20000a8,0xf22e48a2,0xff90f22e
778 .long 0x6800ff84,0x322eff84,0x22410281,0x00007fff
779 .long 0x04810000,0x3fff0c81,0x0000001c,0x6f0e0481
780 .long 0x0000001b,0x1d7c0000,0xff586008,0x42811d7c
781 .long 0x0001ff58,0x243c0000,0x3ffe9481,0x2d7ca2f9
782 .long 0x836eff88,0x2d7c4e44,0x152aff8c,0x3d42ff84
783 .long 0xf2000100,0xf22e4923,0xff842409,0x48420282
784 .long 0x80000000,0x00825f00,0x00002d42,0xff54f22e
785 .long 0x4522ff54,0xf22e4528,0xff542401,0x06820000
786 .long 0x3fff3d42,0xff842d7c,0xc90fdaa2,0xff8842ae
787 .long 0xff8c0681,0x00003fdd,0x3d41ff90,0x2d7c85a3
788 .long 0x08d3ff94,0x42aeff98,0x122eff58,0xf2000a00
789 .long 0xf22e4a23,0xff84f200,0x0a80f22e,0x4aa3ff90
790 .long 0xf2001180,0xf20015a2,0xf2000e28,0xf2000c28
791 .long 0xf2001622,0xf2000180,0xf20010a8,0xf2000422
792 .long 0x0c010000,0x6e00000e,0xf20001a8,0xf2000ca2
793 .long 0x6000ff0c,0xf22e6100,0xff54241f,0xf21fd03c
794 .long 0x222eff54,0xe2996000,0xfd72bff6,0x687e3149
795 .long 0x87d84002,0xac6934a2,0x6db3bfc2,0x476f4e1d
796 .long 0xa28e3fb3,0x44447f87,0x6989bfb7,0x44ee7faf
797 .long 0x45db3fbc,0x71c64694,0x0220bfc2,0x49249218
798 .long 0x72f93fc9,0x99999999,0x8fa9bfd5,0x55555555
799 .long 0x5555bfb7,0x0bf39853,0x9e6a3fbc,0x7187962d
800 .long 0x1d7dbfc2,0x49248271,0x07b83fc9,0x99999996
801 .long 0x263ebfd5,0x55555555,0x55363fff,0x0000c90f
802 .long 0xdaa22168,0xc2350000,0x0000bfff,0x0000c90f
803 .long 0xdaa22168,0xc2350000,0x00000001,0x00008000
804 .long 0x00000000,0x00000000,0x00008001,0x00008000
805 .long 0x00000000,0x00000000,0x00003ffb,0x000083d1
806 .long 0x52c5060b,0x7a510000,0x00003ffb,0x00008bc8
807 .long 0x54456549,0x8b8b0000,0x00003ffb,0x000093be
808 .long 0x40601762,0x6b0d0000,0x00003ffb,0x00009bb3
809 .long 0x078d35ae,0xc2020000,0x00003ffb,0x0000a3a6
810 .long 0x9a525ddc,0xe7de0000,0x00003ffb,0x0000ab98
811 .long 0xe9436276,0x56190000,0x00003ffb,0x0000b389
812 .long 0xe502f9c5,0x98620000,0x00003ffb,0x0000bb79
813 .long 0x7e436b09,0xe6fb0000,0x00003ffb,0x0000c367
814 .long 0xa5c739e5,0xf4460000,0x00003ffb,0x0000cb54
815 .long 0x4c61cff7,0xd5c60000,0x00003ffb,0x0000d33f
816 .long 0x62f82488,0x533e0000,0x00003ffb,0x0000db28
817 .long 0xda816240,0x4c770000,0x00003ffb,0x0000e310
818 .long 0xa4078ad3,0x4f180000,0x00003ffb,0x0000eaf6
819 .long 0xb0a8188e,0xe1eb0000,0x00003ffb,0x0000f2da
820 .long 0xf1949dbe,0x79d50000,0x00003ffb,0x0000fabd
821 .long 0x581361d4,0x7e3e0000,0x00003ffc,0x00008346
822 .long 0xac210959,0xecc40000,0x00003ffc,0x00008b23
823 .long 0x2a083042,0x82d80000,0x00003ffc,0x000092fb
824 .long 0x70b8d29a,0xe2f90000,0x00003ffc,0x00009acf
825 .long 0x476f5ccd,0x1cb40000,0x00003ffc,0x0000a29e
826 .long 0x76304954,0xf23f0000,0x00003ffc,0x0000aa68
827 .long 0xc5d08ab8,0x52300000,0x00003ffc,0x0000b22d
828 .long 0xfffd9d53,0x9f830000,0x00003ffc,0x0000b9ed
829 .long 0xef453e90,0x0ea50000,0x00003ffc,0x0000c1a8
830 .long 0x5f1cc75e,0x3ea50000,0x00003ffc,0x0000c95d
831 .long 0x1be82813,0x8de60000,0x00003ffc,0x0000d10b
832 .long 0xf300840d,0x2de40000,0x00003ffc,0x0000d8b4
833 .long 0xb2ba6bc0,0x5e7a0000,0x00003ffc,0x0000e057
834 .long 0x2a6bb423,0x35f60000,0x00003ffc,0x0000e7f3
835 .long 0x2a70ea9c,0xaa8f0000,0x00003ffc,0x0000ef88
836 .long 0x843264ec,0xefaa0000,0x00003ffc,0x0000f717
837 .long 0x0a28ecc0,0x66660000,0x00003ffd,0x0000812f
838 .long 0xd288332d,0xad320000,0x00003ffd,0x000088a8
839 .long 0xd1b1218e,0x4d640000,0x00003ffd,0x00009012
840 .long 0xab3f23e4,0xaee80000,0x00003ffd,0x0000976c
841 .long 0xc3d411e7,0xf1b90000,0x00003ffd,0x00009eb6
842 .long 0x89493889,0xa2270000,0x00003ffd,0x0000a5ef
843 .long 0x72c34487,0x361b0000,0x00003ffd,0x0000ad17
844 .long 0x00baf07a,0x72270000,0x00003ffd,0x0000b42c
845 .long 0xbcfafd37,0xefb70000,0x00003ffd,0x0000bb30
846 .long 0x3a940ba8,0x0f890000,0x00003ffd,0x0000c221
847 .long 0x15c6fcae,0xbbaf0000,0x00003ffd,0x0000c8fe
848 .long 0xf3e68633,0x12210000,0x00003ffd,0x0000cfc9
849 .long 0x8330b400,0x0c700000,0x00003ffd,0x0000d680
850 .long 0x7aa1102c,0x5bf90000,0x00003ffd,0x0000dd23
851 .long 0x99bc3125,0x2aa30000,0x00003ffd,0x0000e3b2
852 .long 0xa8556b8f,0xc5170000,0x00003ffd,0x0000ea2d
853 .long 0x764f6431,0x59890000,0x00003ffd,0x0000f3bf
854 .long 0x5bf8bad1,0xa21d0000,0x00003ffe,0x0000801c
855 .long 0xe39e0d20,0x5c9a0000,0x00003ffe,0x00008630
856 .long 0xa2dada1e,0xd0660000,0x00003ffe,0x00008c1a
857 .long 0xd445f3e0,0x9b8c0000,0x00003ffe,0x000091db
858 .long 0x8f1664f3,0x50e20000,0x00003ffe,0x00009773
859 .long 0x1420365e,0x538c0000,0x00003ffe,0x00009ce1
860 .long 0xc8e6a0b8,0xcdba0000,0x00003ffe,0x0000a228
861 .long 0x32dbcada,0xae090000,0x00003ffe,0x0000a746
862 .long 0xf2ddb760,0x22940000,0x00003ffe,0x0000ac3e
863 .long 0xc0fb997d,0xd6a20000,0x00003ffe,0x0000b110
864 .long 0x688aebdc,0x6f6a0000,0x00003ffe,0x0000b5bc
865 .long 0xc49059ec,0xc4b00000,0x00003ffe,0x0000ba44
866 .long 0xbc7dd470,0x782f0000,0x00003ffe,0x0000bea9
867 .long 0x4144fd04,0x9aac0000,0x00003ffe,0x0000c2eb
868 .long 0x4abb6616,0x28b60000,0x00003ffe,0x0000c70b
869 .long 0xd54ce602,0xee140000,0x00003ffe,0x0000cd00
870 .long 0x0549adec,0x71590000,0x00003ffe,0x0000d484
871 .long 0x57d2d8ea,0x4ea30000,0x00003ffe,0x0000db94
872 .long 0x8da712de,0xce3b0000,0x00003ffe,0x0000e238
873 .long 0x55f969e8,0x096a0000,0x00003ffe,0x0000e877
874 .long 0x1129c435,0x32590000,0x00003ffe,0x0000ee57
875 .long 0xc16e0d37,0x9c0d0000,0x00003ffe,0x0000f3e1
876 .long 0x0211a87c,0x37790000,0x00003ffe,0x0000f919
877 .long 0x039d758b,0x8d410000,0x00003ffe,0x0000fe05
878 .long 0x8b8f6493,0x5fb30000,0x00003fff,0x00008155
879 .long 0xfb497b68,0x5d040000,0x00003fff,0x00008388
880 .long 0x9e3549d1,0x08e10000,0x00003fff,0x0000859c
881 .long 0xfa76511d,0x724b0000,0x00003fff,0x00008795
882 .long 0x2ecfff81,0x31e70000,0x00003fff,0x00008973
883 .long 0x2fd19557,0x641b0000,0x00003fff,0x00008b38
884 .long 0xcad10193,0x2a350000,0x00003fff,0x00008ce7
885 .long 0xa8d8301e,0xe6b50000,0x00003fff,0x00008f46
886 .long 0xa39e2eae,0x52810000,0x00003fff,0x0000922d
887 .long 0xa7d79188,0x84870000,0x00003fff,0x000094d1
888 .long 0x9fcbdedf,0x52410000,0x00003fff,0x0000973a
889 .long 0xb94419d2,0xa08b0000,0x00003fff,0x0000996f
890 .long 0xf00e08e1,0x0b960000,0x00003fff,0x00009b77
891 .long 0x3f951232,0x1da70000,0x00003fff,0x00009d55
892 .long 0xcc320f93,0x56240000,0x00003fff,0x00009f10
893 .long 0x0575006c,0xc5710000,0x00003fff,0x0000a0a9
894 .long 0xc290d97c,0xc06c0000,0x00003fff,0x0000a226
895 .long 0x59ebebc0,0x630a0000,0x00003fff,0x0000a388
896 .long 0xb4aff6ef,0x0ec90000,0x00003fff,0x0000a4d3
897 .long 0x5f1061d2,0x92c40000,0x00003fff,0x0000a608
898 .long 0x95dcfbe3,0x187e0000,0x00003fff,0x0000a72a
899 .long 0x51dc7367,0xbeac0000,0x00003fff,0x0000a83a
900 .long 0x51530956,0x168f0000,0x00003fff,0x0000a93a
901 .long 0x20077539,0x546e0000,0x00003fff,0x0000aa9e
902 .long 0x7245023b,0x26050000,0x00003fff,0x0000ac4c
903 .long 0x84ba6fe4,0xd58f0000,0x00003fff,0x0000adce
904 .long 0x4a4a606b,0x97120000,0x00003fff,0x0000af2a
905 .long 0x2dcd8d26,0x3c9c0000,0x00003fff,0x0000b065
906 .long 0x6f81f222,0x65c70000,0x00003fff,0x0000b184
907 .long 0x65150f71,0x496a0000,0x00003fff,0x0000b28a
908 .long 0xaa156f9a,0xda350000,0x00003fff,0x0000b37b
909 .long 0x44ff3766,0xb8950000,0x00003fff,0x0000b458
910 .long 0xc3dce963,0x04330000,0x00003fff,0x0000b525
911 .long 0x529d5622,0x46bd0000,0x00003fff,0x0000b5e2
912 .long 0xcca95f9d,0x88cc0000,0x00003fff,0x0000b692
913 .long 0xcada7aca,0x1ada0000,0x00003fff,0x0000b736
914 .long 0xaea7a692,0x58380000,0x00003fff,0x0000b7cf
915 .long 0xab287e9f,0x7b360000,0x00003fff,0x0000b85e
916 .long 0xcc66cb21,0x98350000,0x00003fff,0x0000b8e4
917 .long 0xfd5a20a5,0x93da0000,0x00003fff,0x0000b99f
918 .long 0x41f64aff,0x9bb50000,0x00003fff,0x0000ba7f
919 .long 0x1e17842b,0xbe7b0000,0x00003fff,0x0000bb47
920 .long 0x12857637,0xe17d0000,0x00003fff,0x0000bbfa
921 .long 0xbe8a4788,0xdf6f0000,0x00003fff,0x0000bc9d
922 .long 0x0fad2b68,0x9d790000,0x00003fff,0x0000bd30
923 .long 0x6a39471e,0xcd860000,0x00003fff,0x0000bdb6
924 .long 0xc731856a,0xf18a0000,0x00003fff,0x0000be31
925 .long 0xcac502e8,0x0d700000,0x00003fff,0x0000bea2
926 .long 0xd55ce331,0x94e20000,0x00003fff,0x0000bf0b
927 .long 0x10b7c031,0x28f00000,0x00003fff,0x0000bf6b
928 .long 0x7a18dacb,0x778d0000,0x00003fff,0x0000bfc4
929 .long 0xea4663fa,0x18f60000,0x00003fff,0x0000c018
930 .long 0x1bde8b89,0xa4540000,0x00003fff,0x0000c065
931 .long 0xb066cfbf,0x64390000,0x00003fff,0x0000c0ae
932 .long 0x345f5634,0x0ae60000,0x00003fff,0x0000c0f2
933 .long 0x22919cb9,0xe6a70000,0x0000f210,0x48002210
934 .long 0x32280004,0xf22e6800,0xff840281,0x7fffffff
935 .long 0x0c813ffb,0x80006c04,0x600000d0,0x0c814002
936 .long 0xffff6f04,0x6000014c,0x02aef800,0x0000ff88
937 .long 0x00ae0400,0x0000ff88,0x2d7c0000,0x0000ff8c
938 .long 0xf2000080,0xf22e48a3,0xff84f22e,0x4828ff84
939 .long 0xf23c44a2,0x3f800000,0xf2000420,0x2f022401
940 .long 0x02810000,0x78000282,0x7fff0000,0x04823ffb
941 .long 0x0000e282,0xd282ee81,0x43faf780,0xd3c12d59
942 .long 0xff902d59,0xff942d59,0xff98222e,0xff840281
943 .long 0x80000000,0x83aeff90,0x241ff227,0xe004f200
944 .long 0x0080f200,0x04a3f23a,0x5500f6a0,0xf2000522
945 .long 0xf2000523,0xf20000a3,0xf23a5522,0xf696f23a
946 .long 0x54a3f698,0xf20008a3,0xf2000422,0xf21fd020
947 .long 0xf2009000,0xf22e4822,0xff9060ff,0x00002d30
948 .long 0x0c813fff,0x80006e00,0x008a0c81,0x3fd78000
949 .long 0x6d00006c,0xf227e00c,0xf2000023,0xf2000080
950 .long 0xf20004a3,0xf23a5500,0xf65af23a,0x5580f65c
951 .long 0xf2000523,0xf20005a3,0xf23a5522,0xf656f23a
952 .long 0x55a2f658,0xf2000523,0xf2000ca3,0xf23a5522
953 .long 0xf652f23a,0x54a2f654,0xf2000123,0xf22e4823
954 .long 0xff84f200,0x08a2f200,0x0423f21f,0xd030f200
955 .long 0x9000f22e,0x4822ff84,0x60ff0000,0x2cb2f200
956 .long 0x9000123c,0x0003f22e,0x4800ff84,0x60ff0000
957 .long 0x2c900c81,0x40638000,0x6e00008e,0xf227e00c
958 .long 0xf23c4480,0xbf800000,0xf20000a0,0xf2000400
959 .long 0xf2000023,0xf22e6880,0xff84f200,0x0080f200
960 .long 0x04a3f23a,0x5580f5ec,0xf23a5500,0xf5eef200
961 .long 0x05a3f200,0x0523f23a,0x55a2f5e8,0xf23a5522
962 .long 0xf5eaf200,0x0ca3f200,0x0123f23a,0x54a2f5e4
963 .long 0xf22e4823,0xff84f200,0x08a2f200,0x0423f22e
964 .long 0x4822ff84,0xf21fd030,0xf2009000,0x4a106a0c
965 .long 0xf23a4822,0xf5d660ff,0x00002c24,0xf23a4822
966 .long 0xf5ba60ff,0x00002c10,0x4a106a16,0xf23a4800
967 .long 0xf5baf200,0x9000f23a,0x4822f5c0,0x60ff0000
968 .long 0x2bfef23a,0x4800f594,0xf2009000,0xf23a4822
969 .long 0xf5ba60ff,0x00002be0,0x60ff0000,0x2a66f210
970 .long 0x48002210,0x32280004,0x02817fff,0xffff0c81
971 .long 0x3fff8000,0x6c4e0c81,0x3fd78000,0x6d00007c
972 .long 0xf23c4480,0x3f800000,0xf20000a8,0xf227e004
973 .long 0xf23c4500,0x3f800000,0xf2000122,0xf20008a3
974 .long 0xf21fd020,0xf2000484,0xf2000420,0xf227e001
975 .long 0x41d761ff,0xfffffd66,0xdffc0000,0x000c60ff
976 .long 0x00002b6c,0xf2000018,0xf23c4438,0x3f800000
977 .long 0xf2d20000,0x29d4f23a,0x4800c5a6,0x22100281
978 .long 0x80000000,0x00813f80,0x00002f01,0xf2009000
979 .long 0xf21f4423,0x60ff0000,0x2b36f200,0x9000123c
980 .long 0x0003f210,0x480060ff,0x00002b16,0x60ff0000
981 .long 0x29b2f210,0x48002210,0x32280004,0x02817fff
982 .long 0xffff0c81,0x3fff8000,0x6c44f23c,0x44803f80
983 .long 0x0000f200,0x00a2f200,0x001af23c,0x44223f80
984 .long 0x0000f200,0x0420f200,0x00042f00,0x4280f227
985 .long 0xe00141d7,0x61ffffff,0xfcc4dffc,0x0000000c
986 .long 0xf21f9000,0xf2000022,0x60ff0000,0x2acaf200
987 .long 0x0018f23c,0x44383f80,0x0000f2d2,0x0000292a
988 .long 0x4a106a18,0xf23a4800,0xc4e8f200,0x9000f23c
989 .long 0x44220080,0x000060ff,0x00002a9c,0x60ff0000
990 .long 0x2ce8f200,0x9000f23a,0x4800c4d6,0x60ff0000
991 .long 0x2a863fdc,0x000082e3,0x08654361,0xc4c60000
992 .long 0x00003fa5,0x55555555,0x4cc13fc5,0x55555555
993 .long 0x4a543f81,0x11111117,0x43853fa5,0x55555555
994 .long 0x4f5a3fc5,0x55555555,0x55550000,0x00000000
995 .long 0x00003ec7,0x1de3a577,0x46823efa,0x01a019d7
996 .long 0xcb683f2a,0x01a01a01,0x9df33f56,0xc16c16c1
997 .long 0x70e23f81,0x11111111,0x11113fa5,0x55555555
998 .long 0x55553ffc,0x0000aaaa,0xaaaaaaaa,0xaaab0000
999 .long 0x000048b0,0x00000000,0x00003730,0x00000000
1000 .long 0x00003fff,0x00008000,0x00000000,0x00000000
1001 .long 0x00003fff,0x00008164,0xd1f3bc03,0x07749f84
1002 .long 0x1a9b3fff,0x000082cd,0x8698ac2b,0xa1d89fc1
1003 .long 0xd5b93fff,0x0000843a,0x28c3acde,0x4048a072
1004 .long 0x83693fff,0x000085aa,0xc367cc48,0x7b141fc5
1005 .long 0xc95c3fff,0x0000871f,0x61969e8d,0x10101ee8
1006 .long 0x5c9f3fff,0x00008898,0x0e8092da,0x85289fa2
1007 .long 0x07293fff,0x00008a14,0xd575496e,0xfd9ca07b
1008 .long 0xf9af3fff,0x00008b95,0xc1e3ea8b,0xd6e8a002
1009 .long 0x0dcf3fff,0x00008d1a,0xdf5b7e5b,0xa9e4205a
1010 .long 0x63da3fff,0x00008ea4,0x398b45cd,0x53c01eb7
1011 .long 0x00513fff,0x00009031,0xdc431466,0xb1dc1f6e
1012 .long 0xb0293fff,0x000091c3,0xd373ab11,0xc338a078
1013 .long 0x14943fff,0x0000935a,0x2b2f13e6,0xe92c9eb3
1014 .long 0x19b03fff,0x000094f4,0xefa8fef7,0x09602017
1015 .long 0x457d3fff,0x00009694,0x2d372018,0x5a001f11
1016 .long 0xd5373fff,0x00009837,0xf0518db8,0xa9709fb9
1017 .long 0x52dd3fff,0x000099e0,0x459320b7,0xfa641fe4
1018 .long 0x30873fff,0x00009b8d,0x39b9d54e,0x55381fa2
1019 .long 0xa8183fff,0x00009d3e,0xd9a72cff,0xb7501fde
1020 .long 0x494d3fff,0x00009ef5,0x326091a1,0x11ac2050
1021 .long 0x48903fff,0x0000a0b0,0x510fb971,0x4fc4a073
1022 .long 0x691c3fff,0x0000a270,0x43030c49,0x68181f9b
1023 .long 0x7a053fff,0x0000a435,0x15ae09e6,0x80a0a079
1024 .long 0x71263fff,0x0000a5fe,0xd6a9b151,0x38eca071
1025 .long 0xa1403fff,0x0000a7cd,0x93b4e965,0x3568204f
1026 .long 0x62da3fff,0x0000a9a1,0x5ab4ea7c,0x0ef81f28
1027 .long 0x3c4a3fff,0x0000ab7a,0x39b5a93e,0xd3389f9a
1028 .long 0x7fdc3fff,0x0000ad58,0x3eea42a1,0x4ac8a05b
1029 .long 0x3fac3fff,0x0000af3b,0x78ad690a,0x43741fdf
1030 .long 0x26103fff,0x0000b123,0xf581d2ac,0x25909f70
1031 .long 0x5f903fff,0x0000b311,0xc412a911,0x2488201f
1032 .long 0x678a3fff,0x0000b504,0xf333f9de,0x64841f32
1033 .long 0xfb133fff,0x0000b6fd,0x91e328d1,0x77902003
1034 .long 0x8b303fff,0x0000b8fb,0xaf4762fb,0x9ee8200d
1035 .long 0xc3cc3fff,0x0000baff,0x5ab2133e,0x45fc9f8b
1036 .long 0x2ae63fff,0x0000bd08,0xa39f580c,0x36c0a02b
1037 .long 0xbf703fff,0x0000bf17,0x99b67a73,0x1084a00b
1038 .long 0xf5183fff,0x0000c12c,0x4cca6670,0x9458a041
1039 .long 0xdd413fff,0x0000c346,0xccda2497,0x64089fdf
1040 .long 0x137b3fff,0x0000c567,0x2a115506,0xdadc201f
1041 .long 0x15683fff,0x0000c78d,0x74c8abb9,0xb15c1fc1
1042 .long 0x3a2e3fff,0x0000c9b9,0xbd866e2f,0x27a4a03f
1043 .long 0x8f033fff,0x0000cbec,0x14fef272,0x7c5c1ff4
1044 .long 0x907d3fff,0x0000ce24,0x8c151f84,0x80e49e6e
1045 .long 0x53e43fff,0x0000d063,0x33daef2b,0x25941fd6
1046 .long 0xd45c3fff,0x0000d2a8,0x1d91f12a,0xe45ca076
1047 .long 0xedb93fff,0x0000d4f3,0x5aabcfed,0xfa209fa6
1048 .long 0xde213fff,0x0000d744,0xfccad69d,0x6af41ee6
1049 .long 0x9a2f3fff,0x0000d99d,0x15c278af,0xd7b4207f
1050 .long 0x439f3fff,0x0000dbfb,0xb797daf2,0x3754201e
1051 .long 0xc2073fff,0x0000de60,0xf4825e0e,0x91249e8b
1052 .long 0xe1753fff,0x0000e0cc,0xdeec2a94,0xe1102003
1053 .long 0x2c4b3fff,0x0000e33f,0x8972be8a,0x5a502004
1054 .long 0xdff53fff,0x0000e5b9,0x06e77c83,0x48a81e72
1055 .long 0xf47a3fff,0x0000e839,0x6a503c4b,0xdc681f72
1056 .long 0x2f223fff,0x0000eac0,0xc6e7dd24,0x3930a017
1057 .long 0xe9453fff,0x0000ed4f,0x301ed994,0x2b841f40
1058 .long 0x1a5b3fff,0x0000efe4,0xb99bdcda,0xf5cc9fb9
1059 .long 0xa9e33fff,0x0000f281,0x773c59ff,0xb1382074
1060 .long 0x4c053fff,0x0000f525,0x7d152486,0xcc2c1f77
1061 .long 0x3a193fff,0x0000f7d0,0xdf730ad1,0x3bb81ffe
1062 .long 0x90d53fff,0x0000fa83,0xb2db722a,0x033ca041
1063 .long 0xed223fff,0x0000fd3e,0x0c0cf486,0xc1741f85
1064 .long 0x3f3a2210,0x02817fff,0x00000c81,0x3fbe0000
1065 .long 0x6c0660ff,0x00000108,0x32280004,0x0c81400c
1066 .long 0xb1676d06,0x60ff0000,0x010cf210,0x4800f200
1067 .long 0x0080f23c,0x442342b8,0xaa3bf227,0xe00c2d7c
1068 .long 0x00000000,0xff58f201,0x600043fa,0xfbb6f201
1069 .long 0x40002d41,0xff540281,0x0000003f,0xe989d3c1
1070 .long 0x222eff54,0xec810641,0x3fff3d7a,0xfb06ff54
1071 .long 0xf2000100,0xf23c4423,0xbc317218,0xf23a4923
1072 .long 0xfaf2f200,0x0422f200,0x0822f200,0x0080f200
1073 .long 0x04a3f23c,0x45003ab6,0x0b70f200,0x0523f200
1074 .long 0x0580f23c,0x45a33c08,0x8895f23a,0x5522fad4
1075 .long 0xf23a55a2,0xfad6f200,0x05233d41,0xff842d7c
1076 .long 0x80000000,0xff8842ae,0xff8cf200,0x05a3f23c
1077 .long 0x45223f00,0x0000f200,0x01a3f200,0x0523f200
1078 .long 0x0c22f219,0x4880f200,0x0822f200,0x0423f21f
1079 .long 0xd030f211,0x4422f200,0x0422222e,0xff584a81
1080 .long 0x6706f22e,0x4823ff90,0xf2009000,0x123c0000
1081 .long 0xf22e4823,0xff8460ff,0x000024c6,0xf210d080
1082 .long 0xf2009000,0xf23c4422,0x3f800000,0x60ff0000
1083 .long 0x24c60c81,0x400cb27c,0x6e66f210,0x4800f200
1084 .long 0x0080f23c,0x442342b8,0xaa3bf227,0xe00c2d7c
1085 .long 0x00000001,0xff58f201,0x600043fa,0xfaa6f201
1086 .long 0x40002d41,0xff540281,0x0000003f,0xe989d3c1
1087 .long 0x222eff54,0xec812d41,0xff54e281,0x93aeff54
1088 .long 0x06413fff,0x3d41ff90,0x2d7c8000,0x0000ff94
1089 .long 0x42aeff98,0x222eff54,0x06413fff,0x6000fed2
1090 .long 0x4a106bff,0x00002370,0x60ff0000,0x24122f10
1091 .long 0x02978000,0x00000097,0x00800000,0xf23c4400
1092 .long 0x3f800000,0xf2009000,0xf21f4422,0x60ff0000
1093 .long 0x24262210,0x02817fff,0x00000c81,0x3ffd0000
1094 .long 0x6c0660ff,0x0000015e,0x32280004,0x0c814004
1095 .long 0xc2156f06,0x60ff0000,0x026cf210,0x4800f200
1096 .long 0x0080f23c,0x442342b8,0xaa3bf227,0xe00cf201
1097 .long 0x600043fa,0xf9eef201,0x40002d41,0xff540281
1098 .long 0x0000003f,0xe989d3c1,0x222eff54,0xec812d41
1099 .long 0xff54f200,0x0100f23c,0x4423bc31,0x7218f23a
1100 .long 0x4923f930,0xf2000422,0xf2000822,0x06413fff
1101 .long 0xf2000080,0xf20004a3,0xf23c4500,0x3950097b
1102 .long 0xf2000523,0xf2000580,0xf23c45a3,0x3ab60b6a
1103 .long 0xf23a5522,0xf91ef23a,0x55a2f920,0x3d41ff84
1104 .long 0x2d7c8000,0x0000ff88,0x42aeff8c,0xf2000523
1105 .long 0x222eff54,0x4441f200,0x05a30641,0x3ffff23a
1106 .long 0x5522f900,0xf23c45a2,0x3f000000,0xf2000523
1107 .long 0x00418000,0x3d41ff90,0x2d7c8000,0x0000ff94
1108 .long 0x42aeff98,0xf2000ca3,0xf2000123,0xf2000422
1109 .long 0xf2000822,0xf21fd030,0xf2114823,0x222eff54
1110 .long 0x0c810000,0x003f6f1a,0xf2294480,0x000cf22e
1111 .long 0x48a2ff90,0xf2000422,0xf2114822,0x60ff0000
1112 .long 0x00340c81,0xfffffffd,0x6c16f229,0x4422000c
1113 .long 0xf2114822,0xf22e4822,0xff9060ff,0x00000016
1114 .long 0xf2194880,0xf2114422,0xf22e48a2,0xff90f200
1115 .long 0x0422f200,0x9000f22e,0x4823ff84,0x60ff0000
1116 .long 0x22ae0c81,0x3fbe0000,0x6c6c0c81,0x00330000
1117 .long 0x6d2c2d7c,0x80010000,0xff842d7c,0x80000000
1118 .long 0xff8842ae,0xff8cf210,0x4800f200,0x9000123c
1119 .long 0x0002f22e,0x4822ff84,0x60ff0000,0x2264f210
1120 .long 0x4800f23a,0x5423f86c,0x2d7c8001,0x0000ff84
1121 .long 0x2d7c8000,0x0000ff88,0x42aeff8c,0xf22e4822
1122 .long 0xff84f200,0x9000123c,0x0000f23a,0x5423f84c
1123 .long 0x60ff0000,0x222cf210,0x4800f200,0x0023f227
1124 .long 0xe00cf23c,0x44802f30,0xcaa8f200,0x00a3f23c
1125 .long 0x4500310f,0x8290f23c,0x44a232d7,0x3220f200
1126 .long 0x0123f200,0x00a3f23c,0x45223493,0xf281f23a
1127 .long 0x54a2f7c0,0xf2000123,0xf20000a3,0xf23a5522
1128 .long 0xf7baf23a,0x54a2f7bc,0xf2000123,0xf20000a3
1129 .long 0xf23a5522,0xf7b6f23a,0x54a2f7b8,0xf2000123
1130 .long 0xf20000a3,0xf23a5522,0xf7b2f23a,0x48a2f7b4
1131 .long 0xf2000123,0xf20000a3,0xf2000123,0xf21048a3
1132 .long 0xf23c4423,0x3f000000,0xf20008a2,0xf21fd030
1133 .long 0xf2000422,0xf2009000,0xf2104822,0x60ff0000
1134 .long 0x218e2210,0x0c810000,0x00006e00,0xfbacf23c
1135 .long 0x4400bf80,0x0000f200,0x9000f23c,0x44220080
1136 .long 0x000060ff,0x00002178,0x60ff0000,0x1ff63028
1137 .long 0x00000880,0x000f0440,0x3ffff200,0x50006d02
1138 .long 0x4e751d7c,0x0008ff64,0x4e7561ff,0x00007cfc
1139 .long 0x44400440,0x3ffff200,0x50001d7c,0x0008ff64
1140 .long 0x4e753028,0x00000040,0x7fff0880,0x000e2d68
1141 .long 0x0004ff88,0x2d680008,0xff8c3d40,0xff84f22e
1142 .long 0x4800ff84,0x6b024e75,0x1d7c0008,0xff644e75
1143 .long 0x61ff0000,0x7cb660ca,0x7ffb0000,0x80000000
1144 .long 0x00000000,0x00000000,0xf2104800,0x22103228
1145 .long 0x00040281,0x7fffffff,0x0c81400c,0xb1676e42
1146 .long 0xf2000018,0x2f004280,0xf227e001,0x41d761ff
1147 .long 0xfffffad2,0xdffc0000,0x000cf23c,0x44233f00
1148 .long 0x0000201f,0xf23c4480,0x3e800000,0xf20000a0
1149 .long 0xf2009000,0x123c0002,0xf2000422,0x60ff0000
1150 .long 0x20800c81,0x400cb2b3,0x6e3cf200,0x0018f23a
1151 .long 0x5428baae,0xf23a5428,0xbab02f00,0x4280f227
1152 .long 0xe00141d7,0x61ffffff,0xfa7cdffc,0x0000000c
1153 .long 0x201ff200,0x9000123c,0x0000f23a,0x4823ff5a
1154 .long 0x60ff0000,0x203c60ff,0x00002014,0xf23c4400
1155 .long 0x3f800000,0xf2009000,0xf23c4422,0x00800000
1156 .long 0x60ff0000,0x2032f210,0x48002210,0x32280004
1157 .long 0x22410281,0x7fffffff,0x0c81400c,0xb1676e62
1158 .long 0xf2000018,0x48e78040,0xf227e001,0x41d74280
1159 .long 0x61ffffff,0xfbe0dffc,0x0000000c,0xf23c9000
1160 .long 0x00000000,0x4cdf0201,0xf2000080,0xf23c44a2
1161 .long 0x3f800000,0xf2276800,0xf2000420,0x22090281
1162 .long 0x80000000,0x00813f00,0x0000f21f,0x48222f01
1163 .long 0xf2009000,0x123c0000,0xf21f4423,0x60ff0000
1164 .long 0x1fa00c81,0x400cb2b3,0x6eff0000,0x1f4cf200
1165 .long 0x0018f23a,0x5428b9ca,0x2f3c0000,0x00002f3c
1166 .long 0x80000000,0x22090281,0x80000000,0x00817ffb
1167 .long 0x00002f01,0xf23a5428,0xb9b02f00,0x4280f227
1168 .long 0xe00141d7,0x61ffffff,0xf97cdffc,0x0000000c
1169 .long 0x201ff200,0x9000123c,0x0000f21f,0x482360ff
1170 .long 0x00001f3e,0x60ff0000,0x1ddaf210,0x4800f22e
1171 .long 0x6800ff84,0x22103228,0x00042d41,0xff840281
1172 .long 0x7fffffff,0x0c813fd7,0x80006d00,0x00740c81
1173 .long 0x3fffddce,0x6e00006a,0x222eff84,0x2d41ff5c
1174 .long 0x02817fff,0x00000681,0x00010000,0x2d41ff84
1175 .long 0x02ae8000,0x0000ff5c,0xf22e4800,0xff842f00
1176 .long 0x4280f227,0xe00141d7,0x61ffffff,0xfac8dffc
1177 .long 0x0000000c,0x201ff200,0x0080f23c,0x44a24000
1178 .long 0x0000222e,0xff5cf22e,0x6880ff84,0xb3aeff84
1179 .long 0xf2009000,0xf22e4820,0xff8460ff,0x00001eb0
1180 .long 0x0c813fff,0x80006d00,0x00880c81,0x40048aa1
1181 .long 0x6e000092,0x222eff84,0x2d41ff5c,0x02817fff
1182 .long 0x00000681,0x00010000,0x2d41ff84,0x02ae8000
1183 .long 0x0000ff5c,0x222eff5c,0xf22e4800,0xff842f00
1184 .long 0x4280f227,0xe00141d7,0x61ffffff,0xf878dffc
1185 .long 0x0000000c,0x201f222e,0xff5cf23c,0x44223f80
1186 .long 0x00000a81,0xc0000000,0xf2014480,0xf20000a0
1187 .long 0x222eff5c,0x00813f80,0x0000f201,0x4400f200
1188 .long 0x9000123c,0x0002f200,0x042260ff,0x00001e20
1189 .long 0xf2009000,0x123c0003,0xf22e4800,0xff8460ff
1190 .long 0x00001dfe,0x222eff84,0x02818000,0x00000081
1191 .long 0x3f800000,0xf2014400,0x02818000,0x00000a81
1192 .long 0x80800000,0xf2009000,0xf2014422,0x60ff0000
1193 .long 0x1dde60ff,0x00001c6c,0x3ffe0000,0xb17217f7
1194 .long 0xd1cf79ac,0x00000000,0x3f800000,0x00000000
1195 .long 0x7f800000,0xbf800000,0x3fc2499a,0xb5e4040b
1196 .long 0xbfc555b5,0x848cb7db,0x3fc99999,0x987d8730
1197 .long 0xbfcfffff,0xff6f7e97,0x3fd55555,0x555555a4
1198 .long 0xbfe00000,0x00000008,0x3f175496,0xadd7dad6
1199 .long 0x3f3c71c2,0xfe80c7e0,0x3f624924,0x928bccff
1200 .long 0x3f899999,0x999995ec,0x3fb55555,0x55555555
1201 .long 0x40000000,0x00000000,0x3f990000,0x80000000
1202 .long 0x00000000,0x00000000,0x3ffe0000,0xfe03f80f
1203 .long 0xe03f80fe,0x00000000,0x3ff70000,0xff015358
1204 .long 0x833c47e2,0x00000000,0x3ffe0000,0xfa232cf2
1205 .long 0x52138ac0,0x00000000,0x3ff90000,0xbdc8d83e
1206 .long 0xad88d549,0x00000000,0x3ffe0000,0xf6603d98
1207 .long 0x0f6603da,0x00000000,0x3ffa0000,0x9cf43dcf
1208 .long 0xf5eafd48,0x00000000,0x3ffe0000,0xf2b9d648
1209 .long 0x0f2b9d65,0x00000000,0x3ffa0000,0xda16eb88
1210 .long 0xcb8df614,0x00000000,0x3ffe0000,0xef2eb71f
1211 .long 0xc4345238,0x00000000,0x3ffb0000,0x8b29b775
1212 .long 0x1bd70743,0x00000000,0x3ffe0000,0xebbdb2a5
1213 .long 0xc1619c8c,0x00000000,0x3ffb0000,0xa8d839f8
1214 .long 0x30c1fb49,0x00000000,0x3ffe0000,0xe865ac7b
1215 .long 0x7603a197,0x00000000,0x3ffb0000,0xc61a2eb1
1216 .long 0x8cd907ad,0x00000000,0x3ffe0000,0xe525982a
1217 .long 0xf70c880e,0x00000000,0x3ffb0000,0xe2f2a47a
1218 .long 0xde3a18af,0x00000000,0x3ffe0000,0xe1fc780e
1219 .long 0x1fc780e2,0x00000000,0x3ffb0000,0xff64898e
1220 .long 0xdf55d551,0x00000000,0x3ffe0000,0xdee95c4c
1221 .long 0xa037ba57,0x00000000,0x3ffc0000,0x8db956a9
1222 .long 0x7b3d0148,0x00000000,0x3ffe0000,0xdbeb61ee
1223 .long 0xd19c5958,0x00000000,0x3ffc0000,0x9b8fe100
1224 .long 0xf47ba1de,0x00000000,0x3ffe0000,0xd901b203
1225 .long 0x6406c80e,0x00000000,0x3ffc0000,0xa9372f1d
1226 .long 0x0da1bd17,0x00000000,0x3ffe0000,0xd62b80d6
1227 .long 0x2b80d62c,0x00000000,0x3ffc0000,0xb6b07f38
1228 .long 0xce90e46b,0x00000000,0x3ffe0000,0xd3680d36
1229 .long 0x80d3680d,0x00000000,0x3ffc0000,0xc3fd0329
1230 .long 0x06488481,0x00000000,0x3ffe0000,0xd0b69fcb
1231 .long 0xd2580d0b,0x00000000,0x3ffc0000,0xd11de0ff
1232 .long 0x15ab18ca,0x00000000,0x3ffe0000,0xce168a77
1233 .long 0x25080ce1,0x00000000,0x3ffc0000,0xde1433a1
1234 .long 0x6c66b150,0x00000000,0x3ffe0000,0xcb8727c0
1235 .long 0x65c393e0,0x00000000,0x3ffc0000,0xeae10b5a
1236 .long 0x7ddc8add,0x00000000,0x3ffe0000,0xc907da4e
1237 .long 0x871146ad,0x00000000,0x3ffc0000,0xf7856e5e
1238 .long 0xe2c9b291,0x00000000,0x3ffe0000,0xc6980c69
1239 .long 0x80c6980c,0x00000000,0x3ffd0000,0x82012ca5
1240 .long 0xa68206d7,0x00000000,0x3ffe0000,0xc4372f85
1241 .long 0x5d824ca6,0x00000000,0x3ffd0000,0x882c5fcd
1242 .long 0x7256a8c5,0x00000000,0x3ffe0000,0xc1e4bbd5
1243 .long 0x95f6e947,0x00000000,0x3ffd0000,0x8e44c60b
1244 .long 0x4ccfd7de,0x00000000,0x3ffe0000,0xbfa02fe8
1245 .long 0x0bfa02ff,0x00000000,0x3ffd0000,0x944ad09e
1246 .long 0xf4351af6,0x00000000,0x3ffe0000,0xbd691047
1247 .long 0x07661aa3,0x00000000,0x3ffd0000,0x9a3eecd4
1248 .long 0xc3eaa6b2,0x00000000,0x3ffe0000,0xbb3ee721
1249 .long 0xa54d880c,0x00000000,0x3ffd0000,0xa0218434
1250 .long 0x353f1de8,0x00000000,0x3ffe0000,0xb92143fa
1251 .long 0x36f5e02e,0x00000000,0x3ffd0000,0xa5f2fcab
1252 .long 0xbbc506da,0x00000000,0x3ffe0000,0xb70fbb5a
1253 .long 0x19be3659,0x00000000,0x3ffd0000,0xabb3b8ba
1254 .long 0x2ad362a5,0x00000000,0x3ffe0000,0xb509e68a
1255 .long 0x9b94821f,0x00000000,0x3ffd0000,0xb1641795
1256 .long 0xce3ca97b,0x00000000,0x3ffe0000,0xb30f6352
1257 .long 0x8917c80b,0x00000000,0x3ffd0000,0xb7047551
1258 .long 0x5d0f1c61,0x00000000,0x3ffe0000,0xb11fd3b8
1259 .long 0x0b11fd3c,0x00000000,0x3ffd0000,0xbc952afe
1260 .long 0xea3d13e1,0x00000000,0x3ffe0000,0xaf3addc6
1261 .long 0x80af3ade,0x00000000,0x3ffd0000,0xc2168ed0
1262 .long 0xf458ba4a,0x00000000,0x3ffe0000,0xad602b58
1263 .long 0x0ad602b6,0x00000000,0x3ffd0000,0xc788f439
1264 .long 0xb3163bf1,0x00000000,0x3ffe0000,0xab8f69e2
1265 .long 0x8359cd11,0x00000000,0x3ffd0000,0xccecac08
1266 .long 0xbf04565d,0x00000000,0x3ffe0000,0xa9c84a47
1267 .long 0xa07f5638,0x00000000,0x3ffd0000,0xd2420487
1268 .long 0x2dd85160,0x00000000,0x3ffe0000,0xa80a80a8
1269 .long 0x0a80a80b,0x00000000,0x3ffd0000,0xd7894992
1270 .long 0x3bc3588a,0x00000000,0x3ffe0000,0xa655c439
1271 .long 0x2d7b73a8,0x00000000,0x3ffd0000,0xdcc2c4b4
1272 .long 0x9887dacc,0x00000000,0x3ffe0000,0xa4a9cf1d
1273 .long 0x96833751,0x00000000,0x3ffd0000,0xe1eebd3e
1274 .long 0x6d6a6b9e,0x00000000,0x3ffe0000,0xa3065e3f
1275 .long 0xae7cd0e0,0x00000000,0x3ffd0000,0xe70d785c
1276 .long 0x2f9f5bdc,0x00000000,0x3ffe0000,0xa16b312e
1277 .long 0xa8fc377d,0x00000000,0x3ffd0000,0xec1f392c
1278 .long 0x5179f283,0x00000000,0x3ffe0000,0x9fd809fd
1279 .long 0x809fd80a,0x00000000,0x3ffd0000,0xf12440d3
1280 .long 0xe36130e6,0x00000000,0x3ffe0000,0x9e4cad23
1281 .long 0xdd5f3a20,0x00000000,0x3ffd0000,0xf61cce92
1282 .long 0x346600bb,0x00000000,0x3ffe0000,0x9cc8e160
1283 .long 0xc3fb19b9,0x00000000,0x3ffd0000,0xfb091fd3
1284 .long 0x8145630a,0x00000000,0x3ffe0000,0x9b4c6f9e
1285 .long 0xf03a3caa,0x00000000,0x3ffd0000,0xffe97042
1286 .long 0xbfa4c2ad,0x00000000,0x3ffe0000,0x99d722da
1287 .long 0xbde58f06,0x00000000,0x3ffe0000,0x825efced
1288 .long 0x49369330,0x00000000,0x3ffe0000,0x9868c809
1289 .long 0x868c8098,0x00000000,0x3ffe0000,0x84c37a7a
1290 .long 0xb9a905c9,0x00000000,0x3ffe0000,0x97012e02
1291 .long 0x5c04b809,0x00000000,0x3ffe0000,0x87224c2e
1292 .long 0x8e645fb7,0x00000000,0x3ffe0000,0x95a02568
1293 .long 0x095a0257,0x00000000,0x3ffe0000,0x897b8cac
1294 .long 0x9f7de298,0x00000000,0x3ffe0000,0x94458094
1295 .long 0x45809446,0x00000000,0x3ffe0000,0x8bcf55de
1296 .long 0xc4cd05fe,0x00000000,0x3ffe0000,0x92f11384
1297 .long 0x0497889c,0x00000000,0x3ffe0000,0x8e1dc0fb
1298 .long 0x89e125e5,0x00000000,0x3ffe0000,0x91a2b3c4
1299 .long 0xd5e6f809,0x00000000,0x3ffe0000,0x9066e68c
1300 .long 0x955b6c9b,0x00000000,0x3ffe0000,0x905a3863
1301 .long 0x3e06c43b,0x00000000,0x3ffe0000,0x92aade74
1302 .long 0xc7be59e0,0x00000000,0x3ffe0000,0x8f1779d9
1303 .long 0xfdc3a219,0x00000000,0x3ffe0000,0x94e9bff6
1304 .long 0x15845643,0x00000000,0x3ffe0000,0x8dda5202
1305 .long 0x37694809,0x00000000,0x3ffe0000,0x9723a1b7
1306 .long 0x20134203,0x00000000,0x3ffe0000,0x8ca29c04
1307 .long 0x6514e023,0x00000000,0x3ffe0000,0x995899c8
1308 .long 0x90eb8990,0x00000000,0x3ffe0000,0x8b70344a
1309 .long 0x139bc75a,0x00000000,0x3ffe0000,0x9b88bdaa
1310 .long 0x3a3dae2f,0x00000000,0x3ffe0000,0x8a42f870
1311 .long 0x5669db46,0x00000000,0x3ffe0000,0x9db4224f
1312 .long 0xffe1157c,0x00000000,0x3ffe0000,0x891ac73a
1313 .long 0xe9819b50,0x00000000,0x3ffe0000,0x9fdadc26
1314 .long 0x8b7a12da,0x00000000,0x3ffe0000,0x87f78087
1315 .long 0xf78087f8,0x00000000,0x3ffe0000,0xa1fcff17
1316 .long 0xce733bd4,0x00000000,0x3ffe0000,0x86d90544
1317 .long 0x7a34acc6,0x00000000,0x3ffe0000,0xa41a9e8f
1318 .long 0x5446fb9f,0x00000000,0x3ffe0000,0x85bf3761
1319 .long 0x2cee3c9b,0x00000000,0x3ffe0000,0xa633cd7e
1320 .long 0x6771cd8b,0x00000000,0x3ffe0000,0x84a9f9c8
1321 .long 0x084a9f9d,0x00000000,0x3ffe0000,0xa8489e60
1322 .long 0x0b435a5e,0x00000000,0x3ffe0000,0x83993052
1323 .long 0x3fbe3368,0x00000000,0x3ffe0000,0xaa59233c
1324 .long 0xcca4bd49,0x00000000,0x3ffe0000,0x828cbfbe
1325 .long 0xb9a020a3,0x00000000,0x3ffe0000,0xac656dae
1326 .long 0x6bcc4985,0x00000000,0x3ffe0000,0x81848da8
1327 .long 0xfaf0d277,0x00000000,0x3ffe0000,0xae6d8ee3
1328 .long 0x60bb2468,0x00000000,0x3ffe0000,0x80808080
1329 .long 0x80808081,0x00000000,0x3ffe0000,0xb07197a2
1330 .long 0x3c46c654,0x00000000,0xf2104800,0x2d7c0000
1331 .long 0x0000ff54,0x22103228,0x00042d50,0xff842d68
1332 .long 0x0004ff88,0x2d680008,0xff8c0c81,0x00000000
1333 .long 0x6d000182,0x0c813ffe,0xf07d6d0a,0x0c813fff
1334 .long 0x88416f00,0x00e2e081,0xe0810481,0x00003fff
1335 .long 0xd2aeff54,0x41faf7b2,0xf2014080,0x2d7c3fff
1336 .long 0x0000ff84,0x2d6eff88,0xff9402ae,0xfe000000
1337 .long 0xff9400ae,0x01000000,0xff94222e,0xff940281
1338 .long 0x7e000000,0xe081e081,0xe881d1c1,0xf22e4800
1339 .long 0xff842d7c,0x3fff0000,0xff9042ae,0xff98f22e
1340 .long 0x4828ff90,0xf227e00c,0xf2104823,0xf23a48a3
1341 .long 0xf6c8f200,0x0100f200,0x0923f22e,0x6880ff84
1342 .long 0xf2000980,0xf2000880,0xf23a54a3,0xf6ccf23a
1343 .long 0x5523f6ce,0xf23a54a2,0xf6d0f23a,0x5522f6d2
1344 .long 0xf2000ca3,0xf2000d23,0xf23a54a2,0xf6ccf23a
1345 .long 0x5522f6ce,0xf2000ca3,0xd1fc0000,0x0010f200
1346 .long 0x0d23f200,0x00a3f200,0x0822f210,0x48a2f21f
1347 .long 0xd030f200,0x0422f200,0x9000f22e,0x4822ff84
1348 .long 0x60ff0000,0x142af23c,0x58380001,0xf2c10000
1349 .long 0x1678f200,0x0080f23a,0x44a8f64e,0xf23a4422
1350 .long 0xf648f200,0x04a2f200,0x00a0f227,0xe00cf200
1351 .long 0x0400f200,0x0023f22e,0x6880ff84,0xf2000080
1352 .long 0xf20004a3,0xf23a5580,0xf660f23a,0x5500f662
1353 .long 0xf20005a3,0xf2000523,0xf23a55a2,0xf65cf23a
1354 .long 0x5522f65e,0xf2000ca3,0xf2000123,0xf23a54a2
1355 .long 0xf658f22e,0x4823ff84,0xf20008a2,0xf21fd030
1356 .long 0xf2000423,0xf2009000,0xf22e4822,0xff8460ff
1357 .long 0x0000139c,0x60ff0000,0x12102d7c,0xffffff9c
1358 .long 0xff5448e7,0x3f002610,0x28280004,0x2a280008
1359 .long 0x42824a84,0x66342805,0x42857420,0x4286edc4
1360 .long 0x6000edac,0xd4862d43,0xff842d44,0xff882d45
1361 .long 0xff8c4482,0x2d42ff54,0xf22e4800,0xff844cdf
1362 .long 0x00fc41ee,0xff846000,0xfe0c4286,0xedc46000
1363 .long 0x2406edac,0x2e05edad,0x44860686,0x00000020
1364 .long 0xecaf8887,0x2d43ff84,0x2d44ff88,0x2d45ff8c
1365 .long 0x44822d42,0xff54f22e,0x4800ff84,0x4cdf00fc
1366 .long 0x41eeff84,0x6000fdce,0xf2104800,0xf2000018
1367 .long 0xf23a4838,0xf5a4f292,0x0014f200,0x9000123c
1368 .long 0x0003f210,0x480060ff,0x000012d6,0xf2104800
1369 .long 0x2d7c0000,0x0000ff54,0xf2000080,0xf23a4422
1370 .long 0xf508f22e,0x6800ff84,0x3d6eff88,0xff86222e
1371 .long 0xff840c81,0x00000000,0x6f0000da,0x0c813ffe
1372 .long 0x80006d00,0xfda20c81,0x3fffc000,0x6e00fd98
1373 .long 0x0c813ffe,0xf07d6d00,0x001a0c81,0x3fff8841
1374 .long 0x6e000010,0xf20004a2,0xf23a4422,0xf4bc6000
1375 .long 0xfe762d6e,0xff88ff94,0x02aefe00,0x0000ff94
1376 .long 0x00ae0100,0x0000ff94,0x0c813fff,0x80006c44
1377 .long 0xf23a4400,0xf4fc2d7c,0x3fff0000,0xff9042ae
1378 .long 0xff98f22e,0x4828ff90,0x222eff94,0x02817e00
1379 .long 0x0000e081,0xe081e881,0xf20004a2,0xf227e00c
1380 .long 0xf2000422,0x41faf4e2,0xd1c1f23a,0x4480f466
1381 .long 0x6000fd76,0xf23a4400,0xf4502d7c,0x3fff0000
1382 .long 0xff9042ae,0xff98f22e,0x4828ff90,0x222eff94
1383 .long 0x02817e00,0x0000e081,0xe081e881,0xf2000422
1384 .long 0xf227e00c,0x41faf4a2,0xd1c1f23a,0x4480f41e
1385 .long 0x6000fd36,0x0c810000,0x00006d10,0xf23a4400
1386 .long 0xf414f200,0x900060ff,0x00001014,0xf23a4400
1387 .long 0xf3fcf200,0x900060ff,0x0000102e,0x60ff0000
1388 .long 0x10422210,0x32280004,0x02817fff,0xffff0c81
1389 .long 0x3fff8000,0x6c56f210,0x4818f200,0x0080f200
1390 .long 0x049af200,0x0022f23c,0x44a23f80,0x0000f200
1391 .long 0x04202210,0x02818000,0x00000081,0x3f000000
1392 .long 0x2f012f00,0x4280f227,0xe00141d7,0x61ffffff
1393 .long 0xfe5adffc,0x0000000c,0x201ff200,0x9000123c
1394 .long 0x0000f21f,0x442360ff,0x00001136,0xf2104818
1395 .long 0xf23c4438,0x3f800000,0xf2d20000,0x0fac60ff
1396 .long 0x00000f7c,0x60ff0000,0x0fba3ffd,0x0000de5b
1397 .long 0xd8a93728,0x71950000,0x00003fff,0x0000b8aa
1398 .long 0x3b295c17,0xf0bc0000,0x0000f23c,0x58000001
1399 .long 0xf2104838,0xf2c10000,0x13502210,0x6d000090
1400 .long 0x2f004280,0x61ffffff,0xfba2f21f,0x9000f23a
1401 .long 0x4823ffb8,0x60ff0000,0x10d62210,0x6d000070
1402 .long 0x2f004280,0x61ffffff,0xfd34f21f,0x9000f23a
1403 .long 0x4823ff98,0x60ff0000,0x10c62210,0x6d000050
1404 .long 0x22280008,0x662e2228,0x00040281,0x7fffffff
1405 .long 0x66223210,0x02810000,0x7fff0481,0x00003fff
1406 .long 0x67ff0000,0x12e4f200,0x9000f201,0x400060ff
1407 .long 0x0000107c,0x2f004280,0x61ffffff,0xfb2ef21f
1408 .long 0x9000f23a,0x4823ff54,0x60ff0000,0x106260ff
1409 .long 0x00000ed6,0x22106d00,0xfff62f00,0x428061ff
1410 .long 0xfffffcba,0xf21f9000,0xf23a4823,0xff2e60ff
1411 .long 0x0000104c,0x406a934f,0x0979a371,0x3f734413
1412 .long 0x509f8000,0xbfcd0000,0xc0219dc1,0xda994fd2
1413 .long 0x00000000,0x40000000,0x935d8ddd,0xaaa8ac17
1414 .long 0x00000000,0x3ffe0000,0xb17217f7,0xd1cf79ac
1415 .long 0x00000000,0x3f56c16d,0x6f7bd0b2,0x3f811112
1416 .long 0x302c712c,0x3fa55555,0x55554cc1,0x3fc55555
1417 .long 0x55554a54,0x3fe00000,0x00000000,0x00000000
1418 .long 0x00000000,0x3fff0000,0x80000000,0x00000000
1419 .long 0x3f738000,0x3fff0000,0x8164d1f3,0xbc030773
1420 .long 0x3fbef7ca,0x3fff0000,0x82cd8698,0xac2ba1d7
1421 .long 0x3fbdf8a9,0x3fff0000,0x843a28c3,0xacde4046
1422 .long 0x3fbcd7c9,0x3fff0000,0x85aac367,0xcc487b15
1423 .long 0xbfbde8da,0x3fff0000,0x871f6196,0x9e8d1010
1424 .long 0x3fbde85c,0x3fff0000,0x88980e80,0x92da8527
1425 .long 0x3fbebbf1,0x3fff0000,0x8a14d575,0x496efd9a
1426 .long 0x3fbb80ca,0x3fff0000,0x8b95c1e3,0xea8bd6e7
1427 .long 0xbfba8373,0x3fff0000,0x8d1adf5b,0x7e5ba9e6
1428 .long 0xbfbe9670,0x3fff0000,0x8ea4398b,0x45cd53c0
1429 .long 0x3fbdb700,0x3fff0000,0x9031dc43,0x1466b1dc
1430 .long 0x3fbeeeb0,0x3fff0000,0x91c3d373,0xab11c336
1431 .long 0x3fbbfd6d,0x3fff0000,0x935a2b2f,0x13e6e92c
1432 .long 0xbfbdb319,0x3fff0000,0x94f4efa8,0xfef70961
1433 .long 0x3fbdba2b,0x3fff0000,0x96942d37,0x20185a00
1434 .long 0x3fbe91d5,0x3fff0000,0x9837f051,0x8db8a96f
1435 .long 0x3fbe8d5a,0x3fff0000,0x99e04593,0x20b7fa65
1436 .long 0xbfbcde7b,0x3fff0000,0x9b8d39b9,0xd54e5539
1437 .long 0xbfbebaaf,0x3fff0000,0x9d3ed9a7,0x2cffb751
1438 .long 0xbfbd86da,0x3fff0000,0x9ef53260,0x91a111ae
1439 .long 0xbfbebedd,0x3fff0000,0xa0b0510f,0xb9714fc2
1440 .long 0x3fbcc96e,0x3fff0000,0xa2704303,0x0c496819
1441 .long 0xbfbec90b,0x3fff0000,0xa43515ae,0x09e6809e
1442 .long 0x3fbbd1db,0x3fff0000,0xa5fed6a9,0xb15138ea
1443 .long 0x3fbce5eb,0x3fff0000,0xa7cd93b4,0xe965356a
1444 .long 0xbfbec274,0x3fff0000,0xa9a15ab4,0xea7c0ef8
1445 .long 0x3fbea83c,0x3fff0000,0xab7a39b5,0xa93ed337
1446 .long 0x3fbecb00,0x3fff0000,0xad583eea,0x42a14ac6
1447 .long 0x3fbe9301,0x3fff0000,0xaf3b78ad,0x690a4375
1448 .long 0xbfbd8367,0x3fff0000,0xb123f581,0xd2ac2590
1449 .long 0xbfbef05f,0x3fff0000,0xb311c412,0xa9112489
1450 .long 0x3fbdfb3c,0x3fff0000,0xb504f333,0xf9de6484
1451 .long 0x3fbeb2fb,0x3fff0000,0xb6fd91e3,0x28d17791
1452 .long 0x3fbae2cb,0x3fff0000,0xb8fbaf47,0x62fb9ee9
1453 .long 0x3fbcdc3c,0x3fff0000,0xbaff5ab2,0x133e45fb
1454 .long 0x3fbee9aa,0x3fff0000,0xbd08a39f,0x580c36bf
1455 .long 0xbfbeaefd,0x3fff0000,0xbf1799b6,0x7a731083
1456 .long 0xbfbcbf51,0x3fff0000,0xc12c4cca,0x66709456
1457 .long 0x3fbef88a,0x3fff0000,0xc346ccda,0x24976407
1458 .long 0x3fbd83b2,0x3fff0000,0xc5672a11,0x5506dadd
1459 .long 0x3fbdf8ab,0x3fff0000,0xc78d74c8,0xabb9b15d
1460 .long 0xbfbdfb17,0x3fff0000,0xc9b9bd86,0x6e2f27a3
1461 .long 0xbfbefe3c,0x3fff0000,0xcbec14fe,0xf2727c5d
1462 .long 0xbfbbb6f8,0x3fff0000,0xce248c15,0x1f8480e4
1463 .long 0xbfbcee53,0x3fff0000,0xd06333da,0xef2b2595
1464 .long 0xbfbda4ae,0x3fff0000,0xd2a81d91,0xf12ae45a
1465 .long 0x3fbc9124,0x3fff0000,0xd4f35aab,0xcfedfa1f
1466 .long 0x3fbeb243,0x3fff0000,0xd744fcca,0xd69d6af4
1467 .long 0x3fbde69a,0x3fff0000,0xd99d15c2,0x78afd7b6
1468 .long 0xbfb8bc61,0x3fff0000,0xdbfbb797,0xdaf23755
1469 .long 0x3fbdf610,0x3fff0000,0xde60f482,0x5e0e9124
1470 .long 0xbfbd8be1,0x3fff0000,0xe0ccdeec,0x2a94e111
1471 .long 0x3fbacb12,0x3fff0000,0xe33f8972,0xbe8a5a51
1472 .long 0x3fbb9bfe,0x3fff0000,0xe5b906e7,0x7c8348a8
1473 .long 0x3fbcf2f4,0x3fff0000,0xe8396a50,0x3c4bdc68
1474 .long 0x3fbef22f,0x3fff0000,0xeac0c6e7,0xdd24392f
1475 .long 0xbfbdbf4a,0x3fff0000,0xed4f301e,0xd9942b84
1476 .long 0x3fbec01a,0x3fff0000,0xefe4b99b,0xdcdaf5cb
1477 .long 0x3fbe8cac,0x3fff0000,0xf281773c,0x59ffb13a
1478 .long 0xbfbcbb3f,0x3fff0000,0xf5257d15,0x2486cc2c
1479 .long 0x3fbef73a,0x3fff0000,0xf7d0df73,0x0ad13bb9
1480 .long 0xbfb8b795,0x3fff0000,0xfa83b2db,0x722a033a
1481 .long 0x3fbef84b,0x3fff0000,0xfd3e0c0c,0xf486c175
1482 .long 0xbfbef581,0xf210d080,0x22103228,0x0004f22e
1483 .long 0x6800ff84,0x02817fff,0xffff0c81,0x3fb98000
1484 .long 0x6c046000,0x00880c81,0x400d80c0,0x6f046000
1485 .long 0x007cf200,0x0080f23c,0x44a34280,0x0000f22e
1486 .long 0x6080ff54,0x2f0243fa,0xfbbcf22e,0x4080ff54
1487 .long 0x222eff54,0x24010281,0x0000003f,0xe981d3c1
1488 .long 0xec822202,0xe2819481,0x06820000,0x3ffff227
1489 .long 0xe00cf23c,0x44a33c80,0x00002d59,0xff842d59
1490 .long 0xff882d59,0xff8c3d59,0xff90f200,0x04283d59
1491 .long 0xff94426e,0xff9642ae,0xff98d36e,0xff84f23a
1492 .long 0x4823fb22,0xd36eff90,0x60000100,0x0c813fff
1493 .long 0x80006e12,0xf2009000,0xf23c4422,0x3f800000
1494 .long 0x60ff0000,0x0b12222e,0xff840c81,0x00000000
1495 .long 0x6d0660ff,0x00000ac8,0x60ff0000,0x0a1af200
1496 .long 0x9000f23c,0x44003f80,0x00002210,0x00810080
1497 .long 0x0001f201,0x442260ff,0x00000adc,0xf210d080
1498 .long 0x22103228,0x0004f22e,0x6800ff84,0x02817fff
1499 .long 0xffff0c81,0x3fb98000,0x6c046000,0xff900c81
1500 .long 0x400b9b07,0x6f046000,0xff84f200,0x0080f23a
1501 .long 0x54a3fa62,0xf22e6080,0xff542f02,0x43fafac6
1502 .long 0xf22e4080,0xff54222e,0xff542401,0x02810000
1503 .long 0x003fe981,0xd3c1ec82,0x2202e281,0x94810682
1504 .long 0x00003fff,0xf227e00c,0xf2000500,0xf23a54a3
1505 .long 0xfa2c2d59,0xff84f23a,0x4923fa2a,0x2d59ff88
1506 .long 0x2d59ff8c,0xf2000428,0x3d59ff90,0xf2000828
1507 .long 0x3d59ff94,0x426eff96,0x42aeff98,0xf23a4823
1508 .long 0xfa14d36e,0xff84d36e,0xff90f200,0x0080f200
1509 .long 0x04a3f23a,0x5500fa1e,0xf23a5580,0xfa20f200
1510 .long 0x0523f200,0x05a3f23a,0x5522fa1a,0xf23a55a2
1511 .long 0xfa1cf200,0x0523f200,0x05a3f23a,0x5522fa16
1512 .long 0xf20001a3,0xf2000523,0xf2000c22,0xf2000822
1513 .long 0xf21fd030,0xf22e4823,0xff84f22e,0x4822ff90
1514 .long 0xf22e4822,0xff84f200,0x90003d42,0xff84241f
1515 .long 0x2d7c8000,0x0000ff88,0x42aeff8c,0x123c0000
1516 .long 0xf22e4823,0xff8460ff,0x00000996,0xf2009000
1517 .long 0xf23c4400,0x3f800000,0x22100081,0x00800001
1518 .long 0xf2014422,0x60ff0000,0x098e2f01,0xe8082200
1519 .long 0x02410003,0x0240000c,0x48403001,0x221f4a01
1520 .long 0x671e0c01,0x000a6f12,0x0c01000e,0x6f3c0c01
1521 .long 0x002f6f06,0x0c01003f,0x6f6260ff,0x00000baa
1522 .long 0x4a00660c,0x41fb0170,0x000000d6,0x60000086
1523 .long 0x0c000003,0x670a41fb,0x01700000,0x00d06074
1524 .long 0x41fb0170,0x000000d2,0x606a0401,0x000b4a00
1525 .long 0x661041fb,0x01700000,0x00cc0c01,0x00026f54
1526 .long 0x605a0c00,0x0003670a,0x41fb0170,0x000000f2
1527 .long 0x60e841fb,0x01700000,0x012460de,0x04010030
1528 .long 0x4a006616,0x41fb0170,0x0000014e,0x0c010001
1529 .long 0x6f220c01,0x00076f24,0x601a0c00,0x0003670a
1530 .long 0x41fb0170,0x000001f2,0x60e241fb,0x01700000
1531 .long 0x02a860d8,0x00ae0000,0x0208ff64,0xc2fc000c
1532 .long 0x48404a00,0x6608f230,0xd0801000,0x4e754840
1533 .long 0x3d701000,0xff902d70,0x1004ff94,0x2d701008
1534 .long 0xff982200,0x428041ee,0xff904268,0x000261ff
1535 .long 0x000062c6,0xf210d080,0x4e7551fc,0x40000000
1536 .long 0xc90fdaa2,0x2168c235,0x40000000,0xc90fdaa2
1537 .long 0x2168c234,0x40000000,0xc90fdaa2,0x2168c235
1538 .long 0x3ffd0000,0x9a209a84,0xfbcff798,0x40000000
1539 .long 0xadf85458,0xa2bb4a9a,0x3fff0000,0xb8aa3b29
1540 .long 0x5c17f0bc,0x3ffd0000,0xde5bd8a9,0x37287195
1541 .long 0x00000000,0x00000000,0x00000000,0x3ffd0000
1542 .long 0x9a209a84,0xfbcff798,0x40000000,0xadf85458
1543 .long 0xa2bb4a9a,0x3fff0000,0xb8aa3b29,0x5c17f0bb
1544 .long 0x3ffd0000,0xde5bd8a9,0x37287195,0x00000000
1545 .long 0x00000000,0x00000000,0x3ffd0000,0x9a209a84
1546 .long 0xfbcff799,0x40000000,0xadf85458,0xa2bb4a9b
1547 .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc,0x3ffd0000
1548 .long 0xde5bd8a9,0x37287195,0x00000000,0x00000000
1549 .long 0x00000000,0x3ffe0000,0xb17217f7,0xd1cf79ac
1550 .long 0x40000000,0x935d8ddd,0xaaa8ac17,0x3fff0000
1551 .long 0x80000000,0x00000000,0x40020000,0xa0000000
1552 .long 0x00000000,0x40050000,0xc8000000,0x00000000
1553 .long 0x400c0000,0x9c400000,0x00000000,0x40190000
1554 .long 0xbebc2000,0x00000000,0x40340000,0x8e1bc9bf
1555 .long 0x04000000,0x40690000,0x9dc5ada8,0x2b70b59e
1556 .long 0x40d30000,0xc2781f49,0xffcfa6d5,0x41a80000
1557 .long 0x93ba47c9,0x80e98ce0,0x43510000,0xaa7eebfb
1558 .long 0x9df9de8e,0x46a30000,0xe319a0ae,0xa60e91c7
1559 .long 0x4d480000,0xc9767586,0x81750c17,0x5a920000
1560 .long 0x9e8b3b5d,0xc53d5de5,0x75250000,0xc4605202
1561 .long 0x8a20979b,0x3ffe0000,0xb17217f7,0xd1cf79ab
1562 .long 0x40000000,0x935d8ddd,0xaaa8ac16,0x3fff0000
1563 .long 0x80000000,0x00000000,0x40020000,0xa0000000
1564 .long 0x00000000,0x40050000,0xc8000000,0x00000000
1565 .long 0x400c0000,0x9c400000,0x00000000,0x40190000
1566 .long 0xbebc2000,0x00000000,0x40340000,0x8e1bc9bf
1567 .long 0x04000000,0x40690000,0x9dc5ada8,0x2b70b59d
1568 .long 0x40d30000,0xc2781f49,0xffcfa6d5,0x41a80000
1569 .long 0x93ba47c9,0x80e98cdf,0x43510000,0xaa7eebfb
1570 .long 0x9df9de8d,0x46a30000,0xe319a0ae,0xa60e91c6
1571 .long 0x4d480000,0xc9767586,0x81750c17,0x5a920000
1572 .long 0x9e8b3b5d,0xc53d5de4,0x75250000,0xc4605202
1573 .long 0x8a20979a,0x3ffe0000,0xb17217f7,0xd1cf79ac
1574 .long 0x40000000,0x935d8ddd,0xaaa8ac17,0x3fff0000
1575 .long 0x80000000,0x00000000,0x40020000,0xa0000000
1576 .long 0x00000000,0x40050000,0xc8000000,0x00000000
1577 .long 0x400c0000,0x9c400000,0x00000000,0x40190000
1578 .long 0xbebc2000,0x00000000,0x40340000,0x8e1bc9bf
1579 .long 0x04000000,0x40690000,0x9dc5ada8,0x2b70b59e
1580 .long 0x40d30000,0xc2781f49,0xffcfa6d6,0x41a80000
1581 .long 0x93ba47c9,0x80e98ce0,0x43510000,0xaa7eebfb
1582 .long 0x9df9de8e,0x46a30000,0xe319a0ae,0xa60e91c7
1583 .long 0x4d480000,0xc9767586,0x81750c18,0x5a920000
1584 .long 0x9e8b3b5d,0xc53d5de5,0x75250000,0xc4605202
1585 .long 0x8a20979b,0x2f003229,0x00005bee,0xff540281
1586 .long 0x00007fff,0x30280000,0x02407fff,0x0c403fff
1587 .long 0x6d0000c0,0x0c40400c,0x6e0000a4,0xf2284803
1588 .long 0x0000f200,0x6000f23c,0x88000000,0x00004a29
1589 .long 0x00046b5e,0x2f003d69,0x0000ff84,0x2d690004
1590 .long 0xff882d69,0x0008ff8c,0x41eeff84,0x61ff0000
1591 .long 0x60ba4480,0xd09ff22e,0xd080ff84,0x0c40c001
1592 .long 0x6c36f21f,0x9000223c,0x80000000,0x0480ffff
1593 .long 0xc0014480,0x0c000020,0x6c0ae0a9,0x42a72f01
1594 .long 0x42a76028,0x04000020,0xe0a92f01,0x42a742a7
1595 .long 0x601af229,0xd0800000,0xf21f9000,0x06403fff
1596 .long 0x484042a7,0x2f3c8000,0x00002f00,0xf200b000
1597 .long 0x123c0000,0xf21f4823,0x60ff0000,0x04ce201f
1598 .long 0xc1494a29,0x00006bff,0x0000038c,0x60ff0000
1599 .long 0x03c44a29,0x00046a16,0x201ff200,0x9000123c
1600 .long 0x0003f229,0x48000000,0x60ff0000,0x049e201f
1601 .long 0x204960ff,0x000002e2,0x00010000,0x80000000
1602 .long 0x00000000,0x00000000,0x422eff65,0x2f00422e
1603 .long 0xff5c600c,0x422eff65,0x2f001d7c,0x0001ff5c
1604 .long 0x48e73f00,0x36280000,0x3d43ff58,0x02830000
1605 .long 0x7fff2828,0x00042a28,0x00084a83,0x663c263c
1606 .long 0x00003ffe,0x4a846616,0x28054285,0x04830000
1607 .long 0x00204286,0xedc46000,0xedac9686,0x60224286
1608 .long 0xedc46000,0x9686edac,0x2e05edad,0x44860686
1609 .long 0x00000020,0xecaf8887,0x60060683,0x00003ffe
1610 .long 0x30290000,0x3d40ff5a,0x322eff58,0xb1810281
1611 .long 0x00008000,0x3d41ff5e,0x02800000,0x7fff2229
1612 .long 0x00042429,0x00084a80,0x663c203c,0x00003ffe
1613 .long 0x4a816616,0x22024282,0x04800000,0x00204286
1614 .long 0xedc16000,0xeda99086,0x60224286,0xedc16000
1615 .long 0x9086eda9,0x2e02edaa,0x44860686,0x00000020
1616 .long 0xecaf8287,0x60060680,0x00003ffe,0x2d43ff54
1617 .long 0x2f009083,0x42864283,0x227c0000,0x00004a80
1618 .long 0x6c06201f,0x6000006a,0x588f4a86,0x6e0eb284
1619 .long 0x6608b485,0x66046000,0x01366508,0x94859384
1620 .long 0x42865283,0x4a80670e,0xd683d482,0xe39155c6
1621 .long 0x52895380,0x60d4202e,0xff544a81,0x66162202
1622 .long 0x42820480,0x00000020,0x4286edc1,0x6000eda9
1623 .long 0x9086601c,0x4286edc1,0x60006b14,0x9086eda9
1624 .long 0x2e02edaa,0x44860686,0x00000020,0xecaf8287
1625 .long 0x0c800000,0x41fe6c2a,0x3d40ff90,0x2d41ff94
1626 .long 0x2d42ff98,0x2c2eff54,0x3d46ff84,0x2d44ff88
1627 .long 0x2d45ff8c,0xf22e4800,0xff901d7c,0x0001ff5d
1628 .long 0x60362d41,0xff942d42,0xff980480,0x00003ffe
1629 .long 0x3d40ff90,0x2c2eff54,0x04860000,0x3ffe2d46
1630 .long 0xff54f22e,0x4800ff90,0x3d46ff84,0x2d44ff88
1631 .long 0x2d45ff8c,0x422eff5d,0x4a2eff5c,0x67222c2e
1632 .long 0xff545386,0xb0866d18,0x6e0eb284,0x6608b485
1633 .long 0x66046000,0x007a6508,0xf22e4828,0xff845283
1634 .long 0x3c2eff5a,0x6c04f200,0x001a4286,0x3c2eff5e
1635 .long 0x7e08eeae,0x02830000,0x007f8686,0x1d43ff65
1636 .long 0x4cdf00fc,0x201ff200,0x90004a2e,0xff5d6710
1637 .long 0x123c0000,0xf23a4823,0xfdc060ff,0x0000024c
1638 .long 0x123c0003,0xf2000000,0x60ff0000,0x023e5283
1639 .long 0x0c800000,0x00086c04,0xe1ab6002,0x4283f23c
1640 .long 0x44000000,0x0000422e,0xff5d6000,0xff942c03
1641 .long 0x02860000,0x00014a86,0x6700ff86,0x52833c2e
1642 .long 0xff5a0a86,0x00008000,0x3d46ff5a,0x6000ff72
1643 .long 0x7fff0000,0xffffffff,0xffffffff,0x4a280000
1644 .long 0x6b12f23c,0x44007f80,0x000000ae,0x02000410
1645 .long 0xff644e75,0xf23c4400,0xff800000,0x00ae0a00
1646 .long 0x0410ff64,0x4e7500ae,0x01002080,0xff64f23a
1647 .long 0xd080ffbe,0x4e7500ae,0x00000800,0xff646008
1648 .long 0x00ae0000,0x0a28ff64,0x22482200,0x020100c0
1649 .long 0x660e4a28,0x00006a18,0x08ee0003,0xff646010
1650 .long 0x2f094a28,0x00005bc1,0x61ff0000,0x0196225f
1651 .long 0xf210d080,0x102eff62,0x0200000a,0x66024e75
1652 .long 0x3d690000,0xff842d69,0x0004ff88,0x2d690008
1653 .long 0xff8c41ee,0xff8461ff,0x00005cd0,0x06800000
1654 .long 0x6000026e,0x8000ff84,0x816eff84,0xf22ed040
1655 .long 0xff844e75,0x00ae0000,0x0a28ff64,0x4a105bc1
1656 .long 0x61ff0000,0x013ef210,0xd080f23c,0x44800000
1657 .long 0x00004e75,0x00ae0000,0x0a28ff64,0x51c161ff
1658 .long 0x00000120,0xf210d080,0xf23c4480,0x00000000
1659 .long 0x4e7500ae,0x00001048,0xff641200,0x020100c0
1660 .long 0x675c4a28,0x00046b24,0x3d680000,0xff842d68
1661 .long 0x0004ff88,0x2d680008,0xff8c41ee,0xff8448e7
1662 .long 0xc08061ff,0x00005c44,0x4cdf0103,0x0c010040
1663 .long 0x660e4aa8,0x00086614,0x4a280007,0x660e601e
1664 .long 0x22280008,0x02810000,0x07ff6712,0x00ae0000
1665 .long 0x0200ff64,0x600800ae,0x00001248,0xff644a28
1666 .long 0x00005bc1,0x61ff0000,0x5f261d40,0xff64f210
1667 .long 0xd080f23c,0x44800000,0x00004e75,0x00ae0000
1668 .long 0x1248ff64,0x51c161ff,0x00005f04,0x1d40ff64
1669 .long 0xf210d080,0xf23c4480,0x00000000,0x4e75f327
1670 .long 0x4a2f0002,0x6b2edffc,0x0000000c,0xf294000e
1671 .long 0xf2810014,0x006e0208,0xff664e75,0x00ae0800
1672 .long 0x0208ff64,0x4e751d7c,0x0004ff64,0x006e0208
1673 .long 0xff664e75,0x006e0208,0xff6661ff,0x00000bae
1674 .long 0xdffc0000,0x000c4e75,0xf3274a2f,0x00026bea
1675 .long 0xdffc0000,0x000cf200,0xa80081ae,0xff644e75
1676 .long 0x00ae0000,0x0a28ff64,0x02410010,0xe8080200
1677 .long 0x000f8001,0x2200e309,0x1d7b000a,0xff6441fb
1678 .long 0x16204e75,0x04040400,0x04040400,0x04040400
1679 .long 0x00000000,0x0c0c080c,0x0c0c080c,0x0c0c080c
1680 .long 0x00000000,0x00000000,0x00000000,0x00000000
1681 .long 0x00000000,0x00000000,0x00000000,0x00000000
1682 .long 0x00000000,0x00000000,0x00000000,0x00000000
1683 .long 0x00000000,0x00000000,0x00000001,0x00000000
1684 .long 0x3f810000,0x00000000,0x00000000,0x00000000
1685 .long 0x3f810000,0x00000000,0x00000000,0x00000000
1686 .long 0x3f810000,0x00000000,0x00000000,0x00000000
1687 .long 0x3f810000,0x00000100,0x00000000,0x00000000
1688 .long 0x3c010000,0x00000000,0x00000000,0x00000000
1689 .long 0x3c010000,0x00000000,0x00000000,0x00000000
1690 .long 0x3c010000,0x00000000,0x00000000,0x00000000
1691 .long 0x3c010000,0x00000000,0x00000800,0x00000000
1692 .long 0x00000000,0x00000000,0x00000000,0x00000000
1693 .long 0x00000000,0x00000000,0x00000000,0x00000000
1694 .long 0x00000000,0x00000000,0x00000000,0x00000000
1695 .long 0x00000000,0x00000000,0x00000000,0x00000000
1696 .long 0x80000000,0x00000000,0x00000000,0x00000000
1697 .long 0x80000000,0x00000000,0x00000000,0x00000000
1698 .long 0x80000000,0x00000000,0x00000001,0x00000000
1699 .long 0x80000000,0x00000000,0x00000000,0x00000000
1700 .long 0xbf810000,0x00000000,0x00000000,0x00000000
1701 .long 0xbf810000,0x00000000,0x00000000,0x00000000
1702 .long 0xbf810000,0x00000100,0x00000000,0x00000000
1703 .long 0xbf810000,0x00000000,0x00000000,0x00000000
1704 .long 0xbc010000,0x00000000,0x00000000,0x00000000
1705 .long 0xbc010000,0x00000000,0x00000000,0x00000000
1706 .long 0xbc010000,0x00000000,0x00000800,0x00000000
1707 .long 0xbc010000,0x00000000,0x00000000,0x00000000
1708 .long 0x4a280000,0x6b10f23c,0x44000000,0x00001d7c
1709 .long 0x0004ff64,0x4e75f23c,0x44008000,0x00001d7c
1710 .long 0x000cff64,0x4e754a29,0x00006bea,0x60d84a28
1711 .long 0x00006b10,0xf23c4400,0x7f800000,0x1d7c0002
1712 .long 0xff644e75,0xf23c4400,0xff800000,0x1d7c000a
1713 .long 0xff644e75,0x4a290000,0x6bea60d8,0x4a280000
1714 .long 0x6ba460d0,0x4a280000,0x6b00fbbc,0x60c64a28
1715 .long 0x00006b16,0x60be4a28,0x00006b0e,0xf23c4400
1716 .long 0x3f800000,0x422eff64,0x4e75f23c,0x4400bf80
1717 .long 0x00001d7c,0x0008ff64,0x4e753fff,0x0000c90f
1718 .long 0xdaa22168,0xc235bfff,0x0000c90f,0xdaa22168
1719 .long 0xc2354a28,0x00006b0e,0xf2009000,0xf23a4800
1720 .long 0xffda6000,0xfcf0f200,0x9000f23a,0x4800ffd8
1721 .long 0x6000fcea,0xf23c4480,0x3f800000,0x4a280000
1722 .long 0x6a10f23c,0x44008000,0x00001d7c,0x000cff64
1723 .long 0x6040f23c,0x44000000,0x00001d7c,0x0004ff64
1724 .long 0x6030f23a,0x4880faea,0x61ff0000,0x00286000
1725 .long 0xfb16f228,0x48800000,0x61ff0000,0x00186000
1726 .long 0x030ef228,0x48800000,0x61ff0000,0x00086000
1727 .long 0x02ee102e,0xff430240,0x0007303b,0x02064efb
1728 .long 0x00020010,0x00180020,0x0026002c,0x00320038
1729 .long 0x003ef22e,0xf040ffdc,0x4e75f22e,0xf040ffe8
1730 .long 0x4e75f200,0x05004e75,0xf2000580,0x4e75f200
1731 .long 0x06004e75,0xf2000680,0x4e75f200,0x07004e75
1732 .long 0xf2000780,0x4e75122e,0xff4f67ff,0xfffff7dc
1733 .long 0x0c010001,0x67000096,0x0c010002,0x67ffffff
1734 .long 0xfa880c01,0x000467ff,0xfffff7c0,0x0c010005
1735 .long 0x67ff0000,0x024060ff,0x0000024a,0x122eff4f
1736 .long 0x67ffffff,0xfa640c01,0x000167ff,0xfffffa5a
1737 .long 0x0c010002,0x67ffffff,0xfa500c01,0x000467ff
1738 .long 0xfffffa46,0x0c010003,0x67ff0000,0x021860ff
1739 .long 0x00000202,0x122eff4f,0x67ff0000,0x004e0c01
1740 .long 0x000167ff,0x00000028,0x0c010002,0x67ffffff
1741 .long 0xfa180c01,0x000467ff,0x00000030,0x0c010003
1742 .long 0x67ff0000,0x01e060ff,0x000001ca,0x12280000
1743 .long 0x10290000,0xb1010201,0x00801d41,0xff654a00
1744 .long 0x6a00fdc4,0x6000fdd0,0x422eff65,0x2f001228
1745 .long 0x00001029,0x0000b101,0x02010080,0x1d41ff65
1746 .long 0x0c2e0004,0xff4f660c,0x41e90000,0x201f60ff
1747 .long 0xfffff9c6,0xf21f9000,0xf2294800,0x00004a29
1748 .long 0x00006b02,0x4e751d7c,0x0008ff64,0x4e75122e
1749 .long 0xff4f67ff,0xfffff6e0,0x0c010001,0x6700ff8e
1750 .long 0x0c010002,0x67ffffff,0xf9800c01,0x000467ff
1751 .long 0xfffff6c4,0x0c010003,0x67ff0000,0x014860ff
1752 .long 0x00000132,0x122eff4f,0x67ffffff,0xf95c0c01
1753 .long 0x000167ff,0xfffff952,0x0c010002,0x67ffffff
1754 .long 0xf9480c01,0x000467ff,0xfffff93e,0x0c010003
1755 .long 0x67ff0000,0x011060ff,0x000000fa,0x122eff4f
1756 .long 0x6700ff46,0x0c010001,0x6700ff22,0x0c010002
1757 .long 0x67ffffff,0xf9140c01,0x000467ff,0xffffff2c
1758 .long 0x0c010003,0x67ff0000,0x00dc60ff,0x000000c6
1759 .long 0x122eff4f,0x67ffffff,0xf51e0c01,0x000167ff
1760 .long 0xfffffce6,0x0c010002,0x67ffffff,0xfd0a0c01
1761 .long 0x000467ff,0xfffff500,0x0c010003,0x67ff0000
1762 .long 0x00a460ff,0x0000008e,0x122eff4f,0x67ffffff
1763 .long 0xf4e60c01,0x000167ff,0xfffffcae,0x0c010002
1764 .long 0x67ffffff,0xfcd20c01,0x000467ff,0xfffff4c8
1765 .long 0x0c010003,0x67ff0000,0x006c60ff,0x00000056
1766 .long 0x122eff4f,0x67ffffff,0xf8800c01,0x000367ff
1767 .long 0x00000052,0x0c010005,0x67ff0000,0x003860ff
1768 .long 0xfffff866,0x122eff4f,0x0c010003,0x67340c01
1769 .long 0x0005671e,0x6058122e,0xff4f0c01,0x00036708
1770 .long 0x0c010005,0x670c6036,0x00ae0100,0x4080ff64
1771 .long 0x6010f229,0x48000000,0xf200a800,0x81aeff64
1772 .long 0x4e75f229,0x48000000,0x4a290000,0x6b081d7c
1773 .long 0x0001ff64,0x4e751d7c,0x0009ff64,0x4e75f228
1774 .long 0x48000000,0xf200a800,0x81aeff64,0x4e75f228
1775 .long 0x48000000,0x4a280000,0x6bdc1d7c,0x0001ff64
1776 .long 0x4e751d7c,0x0009ff64,0x4e75122e,0xff4e67ff
1777 .long 0xffffd936,0x0c010001,0x67ffffff,0xfba60c01
1778 .long 0x000267ff,0xfffffbca,0x0c010004,0x67ffffff
1779 .long 0xd9f60c01,0x000367ff,0xffffffb6,0x60ffffff
1780 .long 0xffa0122e,0xff4e67ff,0xffffe620,0x0c010001
1781 .long 0x67ffffff,0xfb6e0c01,0x000267ff,0xfffffbc8
1782 .long 0x0c010004,0x67ffffff,0xe7560c01,0x000367ff
1783 .long 0xffffff7e,0x60ffffff,0xff68122e,0xff4e67ff
1784 .long 0xffffd4d2,0x0c010001,0x67ffffff,0xfb360c01
1785 .long 0x000267ff,0xfffffb9a,0x0c010004,0x67ffffff
1786 .long 0xd76a0c01,0x000367ff,0xffffff46,0x60ffffff
1787 .long 0xff30122e,0xff4e67ff,0xffffd972,0x0c010001
1788 .long 0x67ffffff,0xfafe0c01,0x000267ff,0xfffffb6a
1789 .long 0x0c010004,0x67ffffff,0xdabc0c01,0x000367ff
1790 .long 0xffffff0e,0x60ffffff,0xfef8122e,0xff4e67ff
1791 .long 0xffffca6a,0x0c010001,0x67ffffff,0xfac60c01
1792 .long 0x000267ff,0xfffffb6e,0x0c010004,0x67ffffff
1793 .long 0xcc8a0c01,0x000367ff,0xfffffed6,0x60ffffff
1794 .long 0xfec0122e,0xff4e67ff,0xffffcc76,0x0c010001
1795 .long 0x67ffffff,0xfa8e0c01,0x000267ff,0xfffff6aa
1796 .long 0x0c010004,0x67ffffff,0xcd060c01,0x000367ff
1797 .long 0xfffffe9e,0x60ffffff,0xfe88122e,0xff4e67ff
1798 .long 0xffffe662,0x0c010001,0x67ffffff,0xfa560c01
1799 .long 0x000267ff,0xfffff672,0x0c010004,0x67ffffff
1800 .long 0xe6c60c01,0x000367ff,0xfffffe66,0x60ffffff
1801 .long 0xfe50122e,0xff4e67ff,0xffffb372,0x0c010001
1802 .long 0x67ffffff,0xfa1e0c01,0x000267ff,0xfffff63a
1803 .long 0x0c010004,0x67ffffff,0xb5380c01,0x000367ff
1804 .long 0xfffffe2e,0x60ffffff,0xfe18122e,0xff4e67ff
1805 .long 0xffffbdfc,0x0c010001,0x67ffffff,0xf9e60c01
1806 .long 0x000267ff,0xfffff602,0x0c010004,0x67ffffff
1807 .long 0xbf420c01,0x000367ff,0xfffffdf6,0x60ffffff
1808 .long 0xfde0122e,0xff4e67ff,0xffffd17a,0x0c010001
1809 .long 0x67ffffff,0xfa2a0c01,0x000267ff,0xfffffa00
1810 .long 0x0c010004,0x67ffffff,0xd3080c01,0x000367ff
1811 .long 0xfffffdbe,0x60ffffff,0xfda8122e,0xff4e67ff
1812 .long 0xffffeb64,0x0c010001,0x67ffffff,0xf9f20c01
1813 .long 0x000267ff,0xfffff9c8,0x0c010004,0x67ffffff
1814 .long 0xec200c01,0x000367ff,0xfffffd86,0x60ffffff
1815 .long 0xfd70122e,0xff4e67ff,0xffffec24,0x0c010001
1816 .long 0x67ffffff,0xf9ba0c01,0x000267ff,0xfffff990
1817 .long 0x0c010004,0x67ffffff,0xed360c01,0x000367ff
1818 .long 0xfffffd4e,0x60ffffff,0xfd38122e,0xff4e67ff
1819 .long 0xffffe178,0x0c010001,0x67ffffff,0xf51a0c01
1820 .long 0x000267ff,0xfffff960,0x0c010004,0x67ffffff
1821 .long 0xe30c0c01,0x000367ff,0xfffffd16,0x60ffffff
1822 .long 0xfd00122e,0xff4e67ff,0xffffe582,0x0c010001
1823 .long 0x67ffffff,0xf4e20c01,0x000267ff,0xfffff928
1824 .long 0x0c010004,0x67ffffff,0xe5940c01,0x000367ff
1825 .long 0xfffffcde,0x60ffffff,0xfcc8122e,0xff4e67ff
1826 .long 0xffffe59a,0x0c010001,0x67ffffff,0xf4aa0c01
1827 .long 0x000267ff,0xfffff8f0,0x0c010004,0x67ffffff
1828 .long 0xe5d60c01,0x000367ff,0xfffffca6,0x60ffffff
1829 .long 0xfc90122e,0xff4e67ff,0xffffd530,0x0c010001
1830 .long 0x67ffffff,0xf8da0c01,0x000267ff,0xfffff888
1831 .long 0x0c010004,0x67ffffff,0xd5b60c01,0x000367ff
1832 .long 0xfffffc6e,0x60ffffff,0xfc58122e,0xff4e67ff
1833 .long 0xffffcac2,0x0c010001,0x67ffffff,0xf8de0c01
1834 .long 0x000267ff,0xfffff442,0x0c010004,0x67ffffff
1835 .long 0xcb340c01,0x000367ff,0xfffffc36,0x60ffffff
1836 .long 0xfc20122e,0xff4e67ff,0xffffb14c,0x0c010001
1837 .long 0x67ffffff,0xf86a0c01,0x000267ff,0xfffff40a
1838 .long 0x0c010004,0x67ffffff,0xb30e0c01,0x000367ff
1839 .long 0xfffffbfe,0x60ffffff,0xfbe8122e,0xff4e67ff
1840 .long 0xffffd40e,0x0c010001,0x67ffffff,0xf7b60c01
1841 .long 0x000267ff,0xfffff3d2,0x0c010004,0x67ffffff
1842 .long 0xd40c0c01,0x000367ff,0xfffffbc6,0x60ffffff
1843 .long 0xfbb0122e,0xff4e67ff,0xffffd40a,0x0c010001
1844 .long 0x67ffffff,0xf77e0c01,0x000267ff,0xfffff39a
1845 .long 0x0c010004,0x67ffffff,0xd41a0c01,0x000367ff
1846 .long 0xfffffb8e,0x60ffffff,0xfb78122e,0xff4e67ff
1847 .long 0xffffb292,0x0c010001,0x67ffffff,0xf81a0c01
1848 .long 0x000267ff,0xfffff83e,0x0c010004,0x67ffffff
1849 .long 0xb50a0c01,0x000367ff,0xfffff83a,0x60ffffff
1850 .long 0xf844122e,0xff4e67ff,0xfffff89e,0x0c010001
1851 .long 0x67ffffff,0xf8ca0c01,0x000267ff,0xfffff8f8
1852 .long 0x0c010004,0x67ffffff,0xf8800c01,0x000367ff
1853 .long 0xfffffab4,0x60ffffff,0xfac0122e,0xff4e67ff
1854 .long 0xfffff96e,0x0c010001,0x67ffffff,0xf99a0c01
1855 .long 0x000267ff,0xfffff9c8,0x0c010004,0x67ffffff
1856 .long 0xf9500c01,0x000367ff,0xfffffa7c,0x60ffffff
1857 .long 0xfa88122e,0xff4e67ff,0xfffff9d8,0x0c010001
1858 .long 0x67ffffff,0xfa060c01,0x000267ff,0xfffffa34
1859 .long 0x0c010004,0x67ffffff,0xf9ba0c01,0x000367ff
1860 .long 0xfffffa44,0x60ffffff,0xfa500c2f,0x00070003
1861 .long 0x673e1d7c,0x0000ff4e,0x1d7c0000,0xff4ff22e
1862 .long 0xf080ff78,0x41ef0004,0x43eeff78,0x0c010003
1863 .long 0x67160c01,0x00026708,0x61ff0000,0x02004e75
1864 .long 0x61ff0000,0x1b9e4e75,0x61ff0000,0x05e44e75
1865 .long 0x1d7c0004,0xff4e60c0,0x4afc006d,0x000005d2
1866 .long 0x00000fc8,0xfffffa6e,0x0000106c,0x00002314
1867 .long 0x00000000,0xfffffaa6,0x00000000,0xfffffade
1868 .long 0xfffffb16,0xfffffb4e,0x00000000,0xfffffb86
1869 .long 0xfffffbbe,0xfffffbf6,0xfffffc2e,0xfffffc66
1870 .long 0xfffffc9e,0xfffffcd6,0x00000000,0xfffffd0e
1871 .long 0xfffffd46,0xfffffd7e,0x00000000,0x00001112
1872 .long 0xfffffdb6,0x00000ca8,0x00000000,0xfffffdee
1873 .long 0xfffffe26,0xfffffe5e,0xfffffe96,0x0000089e
1874 .long 0xffffff06,0x00001b84,0x000001de,0x00001854
1875 .long 0xffffff3e,0xffffff76,0x00001512,0x00001f4c
1876 .long 0x00000000,0x00000000,0x00000000,0x00000000
1877 .long 0x00000000,0x00000000,0x00000000,0xfffffece
1878 .long 0xfffffece,0xfffffece,0xfffffece,0xfffffece
1879 .long 0xfffffece,0xfffffece,0xfffffece,0x000013b0
1880 .long 0x00000000,0x00000f56,0x00000000,0x00000000
1881 .long 0x00000000,0x00000000,0x00000000,0x000005c0
1882 .long 0x00002302,0x00000000,0x00000000,0x000005ca
1883 .long 0x0000230c,0x00000000,0x00000000,0x00000000
1884 .long 0x00000000,0x00000000,0x00000000,0x00000000
1885 .long 0x00000000,0x00000000,0x00000000,0x00000000
1886 .long 0x00000000,0x00000000,0x00000000,0x00000000
1887 .long 0x00000000,0x00000000,0x00000000,0x00001100
1888 .long 0x00000000,0x00000c96,0x00000000,0x0000110a
1889 .long 0x00000000,0x00000ca0,0x00000000,0x0000088c
1890 .long 0x00000000,0x00001b72,0x000001cc,0x00000896
1891 .long 0x00000000,0x00001b7c,0x000001d6,0x00001f3a
1892 .long 0x00000000,0x00000000,0x00000000,0x00001f44
1893 .long 0xffffc001,0xffffff81,0xfffffc01,0x00004000
1894 .long 0x0000007f,0x000003ff,0x02000030,0x00000040
1895 .long 0x60080200,0x00300000,0x00802d40,0xff5c4241
1896 .long 0x122eff4f,0xe709822e,0xff4e6600,0x02e43d69
1897 .long 0x0000ff90,0x2d690004,0xff942d69,0x0008ff98
1898 .long 0x3d680000,0xff842d68,0x0004ff88,0x2d680008
1899 .long 0xff8c61ff,0x000024ce,0x2f0061ff,0x00002572
1900 .long 0xd197322e,0xff5eec09,0x201fb0bb,0x14846700
1901 .long 0x011e6d00,0x0062b0bb,0x14846700,0x021a6e00
1902 .long 0x014af22e,0xd080ff90,0xf22e9000,0xff5cf23c
1903 .long 0x88000000,0x0000f22e,0x4823ff84,0xf201a800
1904 .long 0xf23c9000,0x00000000,0x83aeff64,0xf22ef080
1905 .long 0xff842f02,0x322eff84,0x24010281,0x00007fff
1906 .long 0x02428000,0x92808242,0x3d41ff84,0x241ff22e
1907 .long 0xd080ff84,0x4e75f22e,0xd080ff90,0xf22e9000
1908 .long 0xff5cf23c,0x88000000,0x0000f22e,0x4823ff84
1909 .long 0xf201a800,0xf23c9000,0x00000000,0x83aeff64
1910 .long 0x00ae0000,0x1048ff64,0x122eff62,0x02010013
1911 .long 0x661c082e,0x0003ff64,0x56c1202e,0xff5c61ff
1912 .long 0x00004fcc,0x812eff64,0xf210d080,0x4e75222e
1913 .long 0xff5c0201,0x00c06634,0xf22ef080,0xff842f02
1914 .long 0x322eff84,0x34010281,0x00007fff,0x92800481
1915 .long 0x00006000,0x02417fff,0x02428000,0x82423d41
1916 .long 0xff84241f,0xf22ed040,0xff8460a6,0xf22ed080
1917 .long 0xff90222e,0xff5c0201,0x0030f201,0x9000f22e
1918 .long 0x4823ff84,0xf23c9000,0x00000000,0x60aaf22e
1919 .long 0xd080ff90,0xf22e9000,0xff5cf23c,0x88000000
1920 .long 0x0000f22e,0x4823ff84,0xf201a800,0xf23c9000
1921 .long 0x00000000,0x83aeff64,0xf2000098,0xf23c58b8
1922 .long 0x0002f293,0xff3c6000,0xfee408ee,0x0003ff66
1923 .long 0xf22ed080,0xff90f23c,0x90000000,0x0010f23c
1924 .long 0x88000000,0x0000f22e,0x4823ff84,0xf201a800
1925 .long 0xf23c9000,0x00000000,0x83aeff64,0x122eff62
1926 .long 0x0201000b,0x6620f22e,0xf080ff84,0x41eeff84
1927 .long 0x222eff5c,0x61ff0000,0x4dd8812e,0xff64f22e
1928 .long 0xd080ff84,0x4e75f22e,0xd040ff90,0x222eff5c
1929 .long 0x020100c0,0x6652f22e,0x9000ff5c,0xf23c8800
1930 .long 0x00000000,0xf22e48a3,0xff84f23c,0x90000000
1931 .long 0x0000f22e,0xf040ff84,0x2f02322e,0xff842401
1932 .long 0x02810000,0x7fff0242,0x80009280,0x06810000
1933 .long 0x60000241,0x7fff8242,0x3d41ff84,0x241ff22e
1934 .long 0xd040ff84,0x6000ff80,0x222eff5c,0x02010030
1935 .long 0xf2019000,0x60a6f22e,0xd080ff90,0xf22e9000
1936 .long 0xff5cf23c,0x88000000,0x0000f22e,0x4823ff84
1937 .long 0xf201a800,0xf23c9000,0x00000000,0x83aeff64
1938 .long 0xf2000098,0xf23c58b8,0x0002f292,0xfde0f294
1939 .long 0xfefaf22e,0xd040ff90,0x222eff5c,0x020100c0
1940 .long 0x00010010,0xf2019000,0xf23c8800,0x00000000
1941 .long 0xf22e48a3,0xff84f23c,0x90000000,0x0000f200
1942 .long 0x0498f23c,0x58b80002,0xf293fda2,0x6000febc
1943 .long 0x323b120a,0x4efb1006,0x4afc0030,0xfd120072
1944 .long 0x00cc006c,0xfd120066,0x00000000,0x00720072
1945 .long 0x0060006c,0x00720066,0x00000000,0x009e0060
1946 .long 0x009e006c,0x009e0066,0x00000000,0x006c006c
1947 .long 0x006c006c,0x006c0066,0x00000000,0xfd120072
1948 .long 0x00cc006c,0xfd120066,0x00000000,0x00660066
1949 .long 0x00660066,0x00660066,0x00000000,0x60ff0000
1950 .long 0x230e60ff,0x00002284,0x60ff0000,0x227e1028
1951 .long 0x00001229,0x0000b101,0x6a10f23c,0x44008000
1952 .long 0x00001d7c,0x000cff64,0x4e75f23c,0x44000000
1953 .long 0x00001d7c,0x0004ff64,0x4e75f229,0xd0800000
1954 .long 0x10280000,0x12290000,0xb1016a10,0xf2000018
1955 .long 0xf200001a,0x1d7c000a,0xff644e75,0xf2000018
1956 .long 0x1d7c0002,0xff644e75,0xf228d080,0x00001028
1957 .long 0x00001229,0x0000b101,0x6ae260d0,0x02000030
1958 .long 0x00000040,0x60080200,0x00300000,0x00802d40
1959 .long 0xff5c122e,0xff4e6600,0x02620200,0x00c06600
1960 .long 0x007c4a28,0x00006a06,0x08ee0003,0xff64f228
1961 .long 0xd0800000,0x4e750200,0x00c06600,0x006008ee
1962 .long 0x0003ff66,0x4a280000,0x6a0608ee,0x0003ff64
1963 .long 0xf228d080,0x0000082e,0x0003ff62,0x66024e75
1964 .long 0x3d680000,0xff842d68,0x0004ff88,0x2d680008
1965 .long 0xff8c41ee,0xff8461ff,0x00004950,0x44400640
1966 .long 0x6000322e,0xff840241,0x80000240,0x7fff8041
1967 .long 0x3d40ff84,0xf22ed040,0xff844e75,0x0c000040
1968 .long 0x667e3d68,0x0000ff84,0x2d680004,0xff882d68
1969 .long 0x0008ff8c,0x61ff0000,0x206c0c80,0x0000007f
1970 .long 0x6c000092,0x0c80ffff,0xff816700,0x01786d00
1971 .long 0x00f4f23c,0x88000000,0x0000f22e,0x9000ff5c
1972 .long 0xf22e4800,0xff84f201,0xa800f23c,0x90000000
1973 .long 0x000083ae,0xff642f02,0xf22ef080,0xff84322e
1974 .long 0xff843401,0x02810000,0x7fff9280,0x02428000
1975 .long 0x84413d42,0xff84241f,0xf22ed080,0xff844e75
1976 .long 0x3d680000,0xff842d68,0x0004ff88,0x2d680008
1977 .long 0xff8c61ff,0x00001fee,0x0c800000,0x03ff6c00
1978 .long 0x00140c80,0xfffffc01,0x670000fa,0x6d000076
1979 .long 0x6000ff80,0x08ee0003,0xff664a2e,0xff846a06
1980 .long 0x08ee0003,0xff64122e,0xff620201,0x000b661a
1981 .long 0x41eeff84,0x222eff5c,0x61ff0000,0x4a74812e
1982 .long 0xff64f22e,0xd080ff84,0x4e752d6e,0xff88ff94
1983 .long 0x2d6eff8c,0xff98322e,0xff842f02,0x34010281
1984 .long 0x00007fff,0x92800242,0x80000681,0x00006000
1985 .long 0x02417fff,0x84413d42,0xff90f22e,0xd040ff90
1986 .long 0x241f60ac,0xf23c8800,0x00000000,0xf22e9000
1987 .long 0xff5cf22e,0x4800ff84,0xf23c9000,0x00000000
1988 .long 0xf201a800,0x83aeff64,0x00ae0000,0x1048ff64
1989 .long 0x122eff62,0x02010013,0x661c082e,0x0003ff64
1990 .long 0x56c1202e,0xff5c61ff,0x00004ae4,0x812eff64
1991 .long 0xf210d080,0x4e752f02,0x322eff84,0x24010281
1992 .long 0x00007fff,0x02428000,0x92800481,0x00006000
1993 .long 0x02417fff,0x82423d41,0xff84241f,0xf22ed040
1994 .long 0xff8460b6,0xf23c8800,0x00000000,0xf22e9000
1995 .long 0xff5cf22e,0x4800ff84,0xf201a800,0xf23c9000
1996 .long 0x00000000,0x83aeff64,0xf2000098,0xf23c58b8
1997 .long 0x0002f293,0xff746000,0xfe7e0c01,0x00046700
1998 .long 0xfdb60c01,0x000567ff,0x00001f98,0x0c010003
1999 .long 0x67ff0000,0x1fa2f228,0x48000000,0xf200a800
2000 .long 0xe1981d40,0xff644e75,0x51fc51fc,0x51fc51fc
2001 .long 0x00003fff,0x0000007e,0x000003fe,0xffffc001
2002 .long 0xffffff81,0xfffffc01,0x02000030,0x00000040
2003 .long 0x60080200,0x00300000,0x00802d40,0xff5c4241
2004 .long 0x122eff4f,0xe709822e,0xff4e6600,0x02d63d69
2005 .long 0x0000ff90,0x2d690004,0xff942d69,0x0008ff98
2006 .long 0x3d680000,0xff842d68,0x0004ff88,0x2d680008
2007 .long 0xff8c61ff,0x00001e0e,0x2f0061ff,0x00001eb2
2008 .long 0x4497d197,0x322eff5e,0xec09201f,0xb0bb148e
2009 .long 0x6f000074,0xb0bb1520,0xff7a6700,0x020c6e00
2010 .long 0x013cf22e,0xd080ff90,0xf22e9000,0xff5cf23c
2011 .long 0x88000000,0x0000f22e,0x4820ff84,0xf201a800
2012 .long 0xf23c9000,0x00000000,0x83aeff64,0xf22ef080
2013 .long 0xff842f02,0x322eff84,0x24010281,0x00007fff
2014 .long 0x02428000,0x92808242,0x3d41ff84,0x241ff22e
2015 .long 0xd080ff84,0x4e750000,0x7fff0000,0x407f0000
2016 .long 0x43ff201f,0x60c62f00,0xf22ed080,0xff90f22e
2017 .long 0x9000ff5c,0xf23c8800,0x00000000,0xf22e4820
2018 .long 0xff84f200,0xa800f23c,0x90000000,0x000081ae
2019 .long 0xff64f227,0xe0013017,0xdffc0000,0x000c0280
2020 .long 0x00007fff,0x9097b0bb,0x14ae6db6,0x201f00ae
2021 .long 0x00001048,0xff64122e,0xff620201,0x0013661c
2022 .long 0x082e0003,0xff6456c1,0x202eff5c,0x61ff0000
2023 .long 0x48de812e,0xff64f210,0xd0804e75,0x222eff5c
2024 .long 0x020100c0,0x6634f22e,0xf080ff84,0x2f02322e
2025 .long 0xff843401,0x02810000,0x7fff9280,0x04810000
2026 .long 0x60000241,0x7fff0242,0x80008242,0x3d41ff84
2027 .long 0x241ff22e,0xd040ff84,0x60a6f22e,0xd080ff90
2028 .long 0x222eff5c,0x02010030,0xf2019000,0xf22e4820
2029 .long 0xff84f23c,0x90000000,0x000060aa,0x08ee0003
2030 .long 0xff66f22e,0xd080ff90,0xf23c9000,0x00000010
2031 .long 0xf23c8800,0x00000000,0xf22e4820,0xff84f201
2032 .long 0xa800f23c,0x90000000,0x000083ae,0xff64122e
2033 .long 0xff620201,0x000b6620,0xf22ef080,0xff8441ee
2034 .long 0xff84222e,0xff5c61ff,0x00004726,0x812eff64
2035 .long 0xf22ed080,0xff844e75,0xf22ed040,0xff90222e
2036 .long 0xff5c0201,0x00c06652,0xf22e9000,0xff5cf23c
2037 .long 0x88000000,0x0000f22e,0x48a0ff84,0xf23c9000
2038 .long 0x00000000,0xf22ef040,0xff842f02,0x322eff84
2039 .long 0x24010281,0x00007fff,0x02428000,0x92800681
2040 .long 0x00006000,0x02417fff,0x82423d41,0xff84241f
2041 .long 0xf22ed040,0xff846000,0xff80222e,0xff5c0201
2042 .long 0x0030f201,0x900060a6,0xf22ed080,0xff90f22e
2043 .long 0x9000ff5c,0xf23c8800,0x00000000,0xf22e4820
2044 .long 0xff84f201,0xa800f23c,0x90000000,0x000083ae
2045 .long 0xff64f200,0x0098f23c,0x58b80001,0xf292fdee
2046 .long 0xf294fefa,0xf22ed040,0xff90222e,0xff5c0201
2047 .long 0x00c00001,0x0010f201,0x9000f23c,0x88000000
2048 .long 0x0000f22e,0x48a0ff84,0xf23c9000,0x00000000
2049 .long 0xf2000498,0xf23c58b8,0x0001f293,0xfdb06000
2050 .long 0xfebc323b,0x120a4efb,0x10064afc,0x0030fd20
2051 .long 0x009e0072,0x0060fd20,0x00660000,0x00000072
2052 .long 0x006c0072,0x00600072,0x00660000,0x000000d0
2053 .long 0x00d0006c,0x006000d0,0x00660000,0x00000060
2054 .long 0x00600060,0x00600060,0x00660000,0x0000fd20
2055 .long 0x009e0072,0x0060fd20,0x00660000,0x00000066
2056 .long 0x00660066,0x00660066,0x00660000,0x000060ff
2057 .long 0x00001bd8,0x60ff0000,0x1bd260ff,0x00001c50
2058 .long 0x10280000,0x12290000,0xb1016a10,0xf23c4400
2059 .long 0x80000000,0x1d7c000c,0xff644e75,0xf23c4400
2060 .long 0x00000000,0x1d7c0004,0xff644e75,0x006e0410
2061 .long 0xff661028,0x00001229,0x0000b101,0x6a10f23c
2062 .long 0x4400ff80,0x00001d7c,0x000aff64,0x4e75f23c
2063 .long 0x44007f80,0x00001d7c,0x0002ff64,0x4e751029
2064 .long 0x00001228,0x0000b101,0x6a16f229,0xd0800000
2065 .long 0xf2000018,0xf200001a,0x1d7c000a,0xff644e75
2066 .long 0xf229d080,0x0000f200,0x00181d7c,0x0002ff64
2067 .long 0x4e750200,0x00300000,0x00406008,0x02000030
2068 .long 0x00000080,0x2d40ff5c,0x122eff4e,0x66000276
2069 .long 0x020000c0,0x66000090,0x2d680004,0xff882d68
2070 .long 0x0008ff8c,0x30280000,0x0a408000,0x6a061d7c
2071 .long 0x0008ff64,0x3d40ff84,0xf22ed080,0xff844e75
2072 .long 0x020000c0,0x666008ee,0x0003ff66,0x2d680004
2073 .long 0xff882d68,0x0008ff8c,0x30280000,0x0a408000
2074 .long 0x6a061d7c,0x0008ff64,0x3d40ff84,0xf22ed080
2075 .long 0xff84082e,0x0003ff62,0x66024e75,0x41eeff84
2076 .long 0x61ff0000,0x42664440,0x06406000,0x322eff84
2077 .long 0x02418000,0x02407fff,0x80413d40,0xff84f22e
2078 .long 0xd040ff84,0x4e750c00,0x0040667e,0x3d680000
2079 .long 0xff842d68,0x0004ff88,0x2d680008,0xff8c61ff
2080 .long 0x00001982,0x0c800000,0x007f6c00,0x00900c80
2081 .long 0xffffff81,0x67000178,0x6d0000f4,0xf23c8800
2082 .long 0x00000000,0xf22e9000,0xff5cf22e,0x481aff84
2083 .long 0xf201a800,0xf23c9000,0x00000000,0x83aeff64
2084 .long 0x2f02f22e,0xf080ff84,0x322eff84,0x34010281
2085 .long 0x00007fff,0x92800242,0x80008441,0x3d42ff84
2086 .long 0x241ff22e,0xd080ff84,0x4e753d68,0x0000ff84
2087 .long 0x2d680004,0xff882d68,0x0008ff8c,0x61ff0000
2088 .long 0x19040c80,0x000003ff,0x6c120c80,0xfffffc01
2089 .long 0x670000fc,0x6d000078,0x6000ff82,0x08ee0003
2090 .long 0xff660a2e,0x0080ff84,0x6a0608ee,0x0003ff64
2091 .long 0x122eff62,0x0201000b,0x661a41ee,0xff84222e
2092 .long 0xff5c61ff,0x0000438a,0x812eff64,0xf22ed080
2093 .long 0xff844e75,0x2d6eff88,0xff942d6e,0xff8cff98
2094 .long 0x322eff84,0x2f022401,0x02810000,0x7fff0242
2095 .long 0x80009280,0x06810000,0x60000241,0x7fff8242
2096 .long 0x3d41ff90,0xf22ed040,0xff90241f,0x60acf23c
2097 .long 0x88000000,0x0000f22e,0x9000ff5c,0xf22e481a
2098 .long 0xff84f23c,0x90000000,0x0000f201,0xa80083ae
2099 .long 0xff6400ae,0x00001048,0xff64122e,0xff620201
2100 .long 0x0013661c,0x082e0003,0xff6456c1,0x202eff5c
2101 .long 0x61ff0000,0x43fa812e,0xff64f210,0xd0804e75
2102 .long 0x2f02322e,0xff842401,0x02810000,0x7fff0242
2103 .long 0x80009280,0x04810000,0x60000241,0x7fff8242
2104 .long 0x3d41ff84,0xf22ed040,0xff84241f,0x60b6f23c
2105 .long 0x88000000,0x0000f22e,0x9000ff5c,0xf22e481a
2106 .long 0xff84f201,0xa800f23c,0x90000000,0x000083ae
2107 .long 0xff64f200,0x0098f23c,0x58b80002,0xf293ff74
2108 .long 0x6000fe7e,0x0c010004,0x6700fdb6,0x0c010005
2109 .long 0x67ff0000,0x18ae0c01,0x000367ff,0x000018b8
2110 .long 0xf228481a,0x0000f200,0xa800e198,0x1d40ff64
2111 .long 0x4e75122e,0xff4e6610,0x4a280000,0x6b024e75
2112 .long 0x1d7c0008,0xff644e75,0x0c010001,0x67400c01
2113 .long 0x00026724,0x0c010005,0x67ff0000,0x18660c01
2114 .long 0x000367ff,0x00001870,0x4a280000,0x6b024e75
2115 .long 0x1d7c0008,0xff644e75,0x4a280000,0x6b081d7c
2116 .long 0x0002ff64,0x4e751d7c,0x000aff64,0x4e754a28
2117 .long 0x00006b08,0x1d7c0004,0xff644e75,0x1d7c000c
2118 .long 0xff644e75,0x122eff4e,0x66280200,0x0030f200
2119 .long 0x9000f23c,0x88000000,0x0000f228,0x48010000
2120 .long 0xf23c9000,0x00000000,0xf200a800,0x81aeff64
2121 .long 0x4e750c01,0x0001672e,0x0c010002,0x674e0c01
2122 .long 0x00046710,0x0c010005,0x67ff0000,0x17d660ff
2123 .long 0x000017e4,0x3d680000,0xff841d7c,0x0080ff88
2124 .long 0x41eeff84,0x60a44a28,0x00006b10,0xf23c4400
2125 .long 0x00000000,0x1d7c0004,0xff644e75,0xf23c4400
2126 .long 0x80000000,0x1d7c000c,0xff644e75,0xf228d080
2127 .long 0x00004a28,0x00006b08,0x1d7c0002,0xff644e75
2128 .long 0x1d7c000a,0xff644e75,0x122eff4e,0x6618f23c
2129 .long 0x88000000,0x0000f228,0x48030000,0xf200a800
2130 .long 0x81aeff64,0x4e750c01,0x0001672e,0x0c010002
2131 .long 0x674e0c01,0x00046710,0x0c010005,0x67ff0000
2132 .long 0x174260ff,0x00001750,0x3d680000,0xff841d7c
2133 .long 0x0080ff88,0x41eeff84,0x60b44a28,0x00006b10
2134 .long 0xf23c4400,0x00000000,0x1d7c0004,0xff644e75
2135 .long 0xf23c4400,0x80000000,0x1d7c000c,0xff644e75
2136 .long 0xf228d080,0x00004a28,0x00006b08,0x1d7c0002
2137 .long 0xff644e75,0x1d7c000a,0xff644e75,0x02000030
2138 .long 0x00000040,0x60080200,0x00300000,0x00802d40
2139 .long 0xff5c122e,0xff4e6600,0x025c0200,0x00c0667e
2140 .long 0x2d680004,0xff882d68,0x0008ff8c,0x32280000
2141 .long 0x0881000f,0x3d41ff84,0xf22ed080,0xff844e75
2142 .long 0x020000c0,0x665808ee,0x0003ff66,0x2d680004
2143 .long 0xff882d68,0x0008ff8c,0x30280000,0x0880000f
2144 .long 0x3d40ff84,0xf22ed080,0xff84082e,0x0003ff62
2145 .long 0x66024e75,0x41eeff84,0x61ff0000,0x3e0e4440
2146 .long 0x06406000,0x322eff84,0x02418000,0x02407fff
2147 .long 0x80413d40,0xff84f22e,0xd040ff84,0x4e750c00
2148 .long 0x0040667e,0x3d680000,0xff842d68,0x0004ff88
2149 .long 0x2d680008,0xff8c61ff,0x0000152a,0x0c800000
2150 .long 0x007f6c00,0x00900c80,0xffffff81,0x67000170
2151 .long 0x6d0000ec,0xf23c8800,0x00000000,0xf22e9000
2152 .long 0xff5cf22e,0x4818ff84,0xf201a800,0xf23c9000
2153 .long 0x00000000,0x83aeff64,0x2f02f22e,0xf080ff84
2154 .long 0x322eff84,0x24010281,0x00007fff,0x92800242
2155 .long 0x80008441,0x3d42ff84,0x241ff22e,0xd080ff84
2156 .long 0x4e753d68,0x0000ff84,0x2d680004,0xff882d68
2157 .long 0x0008ff8c,0x61ff0000,0x14ac0c80,0x000003ff
2158 .long 0x6c120c80,0xfffffc01,0x670000f4,0x6d000070
2159 .long 0x6000ff82,0x08ee0003,0xff6608ae,0x0007ff84
2160 .long 0x122eff62,0x0201000b,0x661a41ee,0xff84222e
2161 .long 0xff5c61ff,0x00003f3a,0x812eff64,0xf22ed080
2162 .long 0xff844e75,0x2d6eff88,0xff942d6e,0xff8cff98
2163 .long 0x322eff84,0x2f022401,0x02810000,0x7fff0242
2164 .long 0x80009280,0x06810000,0x60000241,0x7fff8242
2165 .long 0x3d41ff90,0xf22ed040,0xff90241f,0x60acf23c
2166 .long 0x88000000,0x0000f22e,0x9000ff5c,0xf22e4818
2167 .long 0xff84f23c,0x90000000,0x0000f201,0xa80083ae
2168 .long 0xff6400ae,0x00001048,0xff64122e,0xff620201
2169 .long 0x0013661c,0x082e0003,0xff6456c1,0x202eff5c
2170 .long 0x61ff0000,0x3faa812e,0xff64f210,0xd0804e75
2171 .long 0x2f02322e,0xff842401,0x02810000,0x7fff0242
2172 .long 0x80009280,0x04810000,0x60000241,0x7fff8242
2173 .long 0x3d41ff84,0xf22ed040,0xff84241f,0x60b6f23c
2174 .long 0x88000000,0x0000f22e,0x9000ff5c,0xf22e4818
2175 .long 0xff84f201,0xa800f23c,0x90000000,0x000083ae
2176 .long 0xff64f200,0x0098f23c,0x58b80002,0xf293ff74
2177 .long 0x6000fe86,0x0c010004,0x6700fdc6,0x0c010005
2178 .long 0x67ff0000,0x145e0c01,0x000367ff,0x00001468
2179 .long 0xf2284818,0x00000c01,0x00026708,0x1d7c0004
2180 .long 0xff644e75,0x1d7c0002,0xff644e75,0x4241122e
2181 .long 0xff4fe709,0x822eff4e,0x6618f229,0xd0800000
2182 .long 0xf2284838,0x0000f200,0xa800e198,0x1d40ff64
2183 .long 0x4e75323b,0x120a4efb,0x10064afc,0x0030ffdc
2184 .long 0xffdcffdc,0x006000f8,0x006e0000,0x0000ffdc
2185 .long 0xffdcffdc,0x0060007c,0x006e0000,0x0000ffdc
2186 .long 0xffdcffdc,0x0060007c,0x006e0000,0x00000060
2187 .long 0x00600060,0x00600060,0x006e0000,0x00000114
2188 .long 0x009c009c,0x006000bc,0x006e0000,0x0000006e
2189 .long 0x006e006e,0x006e006e,0x006e0000,0x000061ff
2190 .long 0x00001388,0x022e00f7,0xff644e75,0x61ff0000
2191 .long 0x137a022e,0x00f7ff64,0x4e753d68,0x0000ff84
2192 .long 0x20280004,0x08c0001f,0x2d40ff88,0x2d680008
2193 .long 0xff8c41ee,0xff846000,0xff422d69,0x0000ff84
2194 .long 0x20290004,0x08c0001f,0x2d40ff88,0x2d690008
2195 .long 0xff8c43ee,0xff846000,0xff223d69,0x0000ff90
2196 .long 0x3d680000,0xff842029,0x000408c0,0x001f2d40
2197 .long 0xff942028,0x000408c0,0x001f2d40,0xff882d69
2198 .long 0x0008ff98,0x2d680008,0xff8c43ee,0xff9041ee
2199 .long 0xff846000,0xfee61028,0x00001229,0x0000b101
2200 .long 0x6b00ff78,0x4a006b02,0x4e751d7c,0x0008ff64
2201 .long 0x4e751028,0x00001229,0x0000b101,0x6b00ff7c
2202 .long 0x4a006a02,0x4e751d7c,0x0008ff64,0x4e752d40
2203 .long 0xff5c4241,0x122eff4f,0xe709822e,0xff4e6600
2204 .long 0x02a03d69,0x0000ff90,0x2d690004,0xff942d69
2205 .long 0x0008ff98,0x3d680000,0xff842d68,0x0004ff88
2206 .long 0x2d680008,0xff8c61ff,0x0000119a,0x2f0061ff
2207 .long 0x0000123e,0xd09f0c80,0xffffc001,0x670000f8
2208 .long 0x6d000064,0x0c800000,0x40006700,0x01da6e00
2209 .long 0x0122f22e,0xd080ff90,0xf22e9000,0xff5cf23c
2210 .long 0x88000000,0x0000f22e,0x4827ff84,0xf201a800
2211 .long 0xf23c9000,0x00000000,0x83aeff64,0xf22ef080
2212 .long 0xff842f02,0x322eff84,0x24010281,0x00007fff
2213 .long 0x02428000,0x92808242,0x3d41ff84,0x241ff22e
2214 .long 0xd080ff84,0x4e75f22e,0xd080ff90,0xf22e9000
2215 .long 0xff5cf23c,0x88000000,0x0000f22e,0x4827ff84
2216 .long 0xf201a800,0xf23c9000,0x00000000,0x83aeff64
2217 .long 0x00ae0000,0x1048ff64,0x122eff62,0x02010013
2218 .long 0x6620082e,0x0003ff64,0x56c1202e,0xff5c0200
2219 .long 0x003061ff,0x00003c98,0x812eff64,0xf210d080
2220 .long 0x4e75f22e,0xf080ff84,0x2f02322e,0xff842401
2221 .long 0x02810000,0x7fff9280,0x04810000,0x60000241
2222 .long 0x7fff0242,0x80008242,0x3d41ff84,0x241ff22e
2223 .long 0xd040ff84,0x60acf22e,0xd080ff90,0xf22e9000
2224 .long 0xff5cf23c,0x88000000,0x0000f22e,0x4827ff84
2225 .long 0xf201a800,0xf23c9000,0x00000000,0x83aeff64
2226 .long 0xf2000098,0xf23c58b8,0x0002f293,0xff646000
2227 .long 0xff0c08ee,0x0003ff66,0xf22ed080,0xff90f23c
2228 .long 0x90000000,0x0010f23c,0x88000000,0x0000f22e
2229 .long 0x4827ff84,0xf201a800,0xf23c9000,0x00000000
2230 .long 0x83aeff64,0x122eff62,0x0201000b,0x6620f22e
2231 .long 0xf080ff84,0x41eeff84,0x222eff5c,0x61ff0000
2232 .long 0x3b56812e,0xff64f22e,0xd080ff84,0x4e75f22e
2233 .long 0xd040ff90,0xf22e9000,0xff5cf23c,0x88000000
2234 .long 0x0000f22e,0x48a7ff84,0xf23c9000,0x00000000
2235 .long 0xf22ef040,0xff842f02,0x322eff84,0x24010281
2236 .long 0x00007fff,0x02428000,0x92800681,0x00006000
2237 .long 0x02417fff,0x82423d41,0xff84241f,0xf22ed040
2238 .long 0xff846000,0xff8af22e,0xd080ff90,0xf22e9000
2239 .long 0xff5cf23c,0x88000000,0x0000f22e,0x4827ff84
2240 .long 0xf201a800,0xf23c9000,0x00000000,0x83aeff64
2241 .long 0xf2000098,0xf23c58b8,0x0002f292,0xfe20f294
2242 .long 0xff12f22e,0xd040ff90,0x222eff5c,0x020100c0
2243 .long 0x00010010,0xf2019000,0xf23c8800,0x00000000
2244 .long 0xf22e48a7,0xff84f23c,0x90000000,0x0000f200
2245 .long 0x0498f23c,0x58b80002,0xf293fde2,0x6000fed4
2246 .long 0x323b120a,0x4efb1006,0x4afc0030,0xfd560072
2247 .long 0x0078006c,0xfd560066,0x00000000,0x00720072
2248 .long 0x0060006c,0x00720066,0x00000000,0x007e0060
2249 .long 0x007e006c,0x007e0066,0x00000000,0x006c006c
2250 .long 0x006c006c,0x006c0066,0x00000000,0xfd560072
2251 .long 0x0078006c,0xfd560066,0x00000000,0x00660066
2252 .long 0x00660066,0x00660066,0x00000000,0x60ff0000
2253 .long 0x101e60ff,0x00000f94,0x60ff0000,0x0f8e60ff
2254 .long 0xffffed0e,0x60ffffff,0xed6260ff,0xffffed2e
2255 .long 0x2d40ff5c,0x4241122e,0xff4fe709,0x822eff4e
2256 .long 0x6600027c,0x3d690000,0xff902d69,0x0004ff94
2257 .long 0x2d690008,0xff983d68,0x0000ff84,0x2d680004
2258 .long 0xff882d68,0x0008ff8c,0x61ff0000,0x0e582f00
2259 .long 0x61ff0000,0x0efc4497,0xd197322e,0xff5eec09
2260 .long 0x201f0c80,0xffffc001,0x6f000064,0x0c800000
2261 .long 0x3fff6700,0x01b66e00,0x0100f22e,0xd080ff90
2262 .long 0xf22e9000,0xff5cf23c,0x88000000,0x0000f22e
2263 .long 0x4824ff84,0xf201a800,0xf23c9000,0x00000000
2264 .long 0x83aeff64,0xf22ef080,0xff842f02,0x322eff84
2265 .long 0x24010281,0x00007fff,0x02428000,0x92808242
2266 .long 0x3d41ff84,0x241ff22e,0xd080ff84,0x4e75f22e
2267 .long 0xd080ff90,0xf22e9000,0xff5cf23c,0x88000000
2268 .long 0x0000f22e,0x4824ff84,0xf201a800,0xf23c9000
2269 .long 0x00000000,0x83aeff64,0xf227e001,0x3217dffc
2270 .long 0x0000000c,0x02810000,0x7fff9280,0x0c810000
2271 .long 0x7fff6d90,0x006e1048,0xff66122e,0xff620201
2272 .long 0x00136620,0x082e0003,0xff6456c1,0x202eff5c
2273 .long 0x02000030,0x61ff0000,0x3936812e,0xff64f210
2274 .long 0xd0804e75,0xf22ef080,0xff842f02,0x322eff84
2275 .long 0x24010281,0x00007fff,0x02428000,0x92800481
2276 .long 0x00006000,0x02417fff,0x82423d41,0xff84241f
2277 .long 0xf22ed040,0xff8460ac,0x08ee0003,0xff66f22e
2278 .long 0xd080ff90,0xf23c9000,0x00000010,0xf23c8800
2279 .long 0x00000000,0xf22e4824,0xff84f201,0xa800f23c
2280 .long 0x90000000,0x000083ae,0xff64122e,0xff620201
2281 .long 0x000b6620,0xf22ef080,0xff8441ee,0xff84222e
2282 .long 0xff5c61ff,0x00003830,0x812eff64,0xf22ed080
2283 .long 0xff844e75,0xf22ed040,0xff90f22e,0x9000ff5c
2284 .long 0xf23c8800,0x00000000,0xf22e48a4,0xff84f23c
2285 .long 0x90000000,0x0000f22e,0xf040ff84,0x2f02322e
2286 .long 0xff842401,0x02810000,0x7fff0242,0x80009280
2287 .long 0x06810000,0x60000241,0x7fff8242,0x3d41ff84
2288 .long 0x241ff22e,0xd040ff84,0x608af22e,0xd080ff90
2289 .long 0xf22e9000,0xff5cf23c,0x88000000,0x0000f22e
2290 .long 0x4824ff84,0xf201a800,0xf23c9000,0x00000000
2291 .long 0x83aeff64,0xf2000098,0xf23c58b8,0x0001f292
2292 .long 0xfe44f294,0xff14f22e,0xd040ff90,0x42810001
2293 .long 0x0010f201,0x9000f23c,0x88000000,0x0000f22e
2294 .long 0x48a4ff84,0xf23c9000,0x00000000,0xf2000498
2295 .long 0xf23c58b8,0x0001f293,0xfe0c6000,0xfedc323b
2296 .long 0x120a4efb,0x10064afc,0x0030fd7a,0x00720078
2297 .long 0x0060fd7a,0x00660000,0x00000078,0x006c0078
2298 .long 0x00600078,0x00660000,0x0000007e,0x007e006c
2299 .long 0x0060007e,0x00660000,0x00000060,0x00600060
2300 .long 0x00600060,0x00660000,0x0000fd7a,0x00720078
2301 .long 0x0060fd7a,0x00660000,0x00000066,0x00660066
2302 .long 0x00660066,0x00660000,0x000060ff,0x00000c7c
2303 .long 0x60ff0000,0x0c7660ff,0x00000cf4,0x60ffffff
2304 .long 0xf0ce60ff,0xfffff09c,0x60ffffff,0xf0f40200
2305 .long 0x00300000,0x00406008,0x02000030,0x00000080
2306 .long 0x2d40ff5c,0x4241122e,0xff4fe709,0x822eff4e
2307 .long 0x6600024c,0x61ff0000,0x0a5cf22e,0xd080ff90
2308 .long 0xf23c8800,0x00000000,0xf22e9000,0xff5cf22e
2309 .long 0x4822ff84,0xf23c9000,0x00000000,0xf201a800
2310 .long 0x83aeff64,0xf281003c,0x2f02f227,0xe001322e
2311 .long 0xff5eec09,0x34170282,0x00007fff,0x9480b4bb
2312 .long 0x14246c38,0xb4bb142a,0x6d0000b8,0x67000184
2313 .long 0x32170241,0x80008242,0x3e81f21f,0xd080241f
2314 .long 0x4e754e75,0x00007fff,0x0000407f,0x000043ff
2315 .long 0x00000000,0x00003f81,0x00003c01,0x00ae0000
2316 .long 0x1048ff64,0x122eff62,0x02010013,0x6624dffc
2317 .long 0x0000000c,0x082e0003,0xff6456c1,0x202eff5c
2318 .long 0x61ff0000,0x366a812e,0xff64f210,0xd080241f
2319 .long 0x4e75122e,0xff5c0201,0x00c0661a,0x32170241
2320 .long 0x80000482,0x00006000,0x02427fff,0x82423e81
2321 .long 0xf21fd040,0x60bef22e,0xd080ff90,0x222eff5c
2322 .long 0x02010030,0xf2019000,0xf22e4822,0xff84f23c
2323 .long 0x90000000,0x0000dffc,0x0000000c,0xf227e001
2324 .long 0x60ba08ee,0x0003ff66,0xdffc0000,0x000cf22e
2325 .long 0xd080ff90,0xf23c9000,0x00000010,0xf23c8800
2326 .long 0x00000000,0xf22e4822,0xff84f23c,0x90000000
2327 .long 0x0000f201,0xa80083ae,0xff64122e,0xff620201
2328 .long 0x000b6622,0xf22ef080,0xff8441ee,0xff84222e
2329 .long 0xff5c61ff,0x000034ba,0x812eff64,0xf22ed080
2330 .long 0xff84241f,0x4e75f22e,0xd040ff90,0x222eff5c
2331 .long 0x020100c0,0x664ef22e,0x9000ff5c,0xf23c8800
2332 .long 0x00000000,0xf22e48a2,0xff84f23c,0x90000000
2333 .long 0x0000f22e,0xf040ff84,0x322eff84,0x24010281
2334 .long 0x00007fff,0x02428000,0x92800681,0x00006000
2335 .long 0x02417fff,0x82423d41,0xff84f22e,0xd040ff84
2336 .long 0x6000ff82,0x222eff5c,0x02010030,0xf2019000
2337 .long 0x60aa222e,0xff5c0201,0x00c06700,0xfe74222f
2338 .long 0x00040c81,0x80000000,0x6600fe66,0x4aaf0008
2339 .long 0x6600fe5e,0x082e0001,0xff666700,0xfe54f22e
2340 .long 0xd040ff90,0x222eff5c,0x020100c0,0x00010010
2341 .long 0xf2019000,0xf23c8800,0x00000000,0xf22e48a2
2342 .long 0xff84f23c,0x90000000,0x0000f200,0x0018f200
2343 .long 0x0498f200,0x0438f292,0xfeca6000,0xfe14323b
2344 .long 0x120a4efb,0x10064afc,0x0030fdaa,0x00e4011c
2345 .long 0x0060fdaa,0x00660000,0x000000bc,0x006c011c
2346 .long 0x006000bc,0x00660000,0x00000130,0x0130010c
2347 .long 0x00600130,0x00660000,0x00000060,0x00600060
2348 .long 0x00600060,0x00660000,0x0000fdaa,0x00e4011c
2349 .long 0x0060fdaa,0x00660000,0x00000066,0x00660066
2350 .long 0x00660066,0x00660000,0x000060ff,0x0000097c
2351 .long 0x60ff0000,0x09761028,0x00001229,0x0000b101
2352 .long 0x6b000016,0x4a006b2e,0xf23c4400,0x00000000
2353 .long 0x1d7c0004,0xff644e75,0x122eff5f,0x02010030
2354 .long 0x0c010020,0x6710f23c,0x44000000,0x00001d7c
2355 .long 0x0004ff64,0x4e75f23c,0x44008000,0x00001d7c
2356 .long 0x000cff64,0x4e753d68,0x0000ff84,0x2d680004
2357 .long 0xff882d68,0x0008ff8c,0x61ff0000,0x0828426e
2358 .long 0xff9042ae,0xff9442ae,0xff986000,0xfcce3d69
2359 .long 0x0000ff90,0x2d690004,0xff942d69,0x0008ff98
2360 .long 0x61ff0000,0x08ac426e,0xff8442ae,0xff8842ae
2361 .long 0xff8c6000,0xfca61028,0x00001229,0x0000b300
2362 .long 0x6bff0000,0x094af228,0xd0800000,0x4a280000
2363 .long 0x6a1c1d7c,0x000aff64,0x4e75f229,0xd0800000
2364 .long 0x4a290000,0x6a081d7c,0x000aff64,0x4e751d7c
2365 .long 0x0002ff64,0x4e750200,0x00300000,0x00406008
2366 .long 0x02000030,0x00000080,0x2d40ff5c,0x4241122e
2367 .long 0xff4fe709,0x822eff4e,0x6600024c,0x61ff0000
2368 .long 0x0694f22e,0xd080ff90,0xf23c8800,0x00000000
2369 .long 0xf22e9000,0xff5cf22e,0x4828ff84,0xf23c9000
2370 .long 0x00000000,0xf201a800,0x83aeff64,0xf281003c
2371 .long 0x2f02f227,0xe001322e,0xff5eec09,0x34170282
2372 .long 0x00007fff,0x9480b4bb,0x14246c38,0xb4bb142a
2373 .long 0x6d0000b8,0x67000184,0x32170241,0x80008242
2374 .long 0x3e81f21f,0xd080241f,0x4e754e75,0x00007fff
2375 .long 0x0000407f,0x000043ff,0x00000000,0x00003f81
2376 .long 0x00003c01,0x00ae0000,0x1048ff64,0x122eff62
2377 .long 0x02010013,0x6624dffc,0x0000000c,0x082e0003
2378 .long 0xff6456c1,0x202eff5c,0x61ff0000,0x32a2812e
2379 .long 0xff64f210,0xd080241f,0x4e75122e,0xff5c0201
2380 .long 0x00c0661a,0x32170241,0x80000482,0x00006000
2381 .long 0x02427fff,0x82423e81,0xf21fd040,0x60bef22e
2382 .long 0xd080ff90,0x222eff5c,0x02010030,0xf2019000
2383 .long 0xf22e4828,0xff84f23c,0x90000000,0x0000dffc
2384 .long 0x0000000c,0xf227e001,0x60ba08ee,0x0003ff66
2385 .long 0xdffc0000,0x000cf22e,0xd080ff90,0xf23c9000
2386 .long 0x00000010,0xf23c8800,0x00000000,0xf22e4828
2387 .long 0xff84f23c,0x90000000,0x0000f201,0xa80083ae
2388 .long 0xff64122e,0xff620201,0x000b6622,0xf22ef080
2389 .long 0xff8441ee,0xff84222e,0xff5c61ff,0x000030f2
2390 .long 0x812eff64,0xf22ed080,0xff84241f,0x4e75f22e
2391 .long 0xd040ff90,0x222eff5c,0x020100c0,0x664ef22e
2392 .long 0x9000ff5c,0xf23c8800,0x00000000,0xf22e48a8
2393 .long 0xff84f23c,0x90000000,0x0000f22e,0xf040ff84
2394 .long 0x322eff84,0x24010281,0x00007fff,0x02428000
2395 .long 0x92800681,0x00006000,0x02417fff,0x82423d41
2396 .long 0xff84f22e,0xd040ff84,0x6000ff82,0x222eff5c
2397 .long 0x02010030,0xf2019000,0x60aa222e,0xff5c0201
2398 .long 0x00c06700,0xfe74222f,0x00040c81,0x80000000
2399 .long 0x6600fe66,0x4aaf0008,0x6600fe5e,0x082e0001
2400 .long 0xff666700,0xfe54f22e,0xd040ff90,0x222eff5c
2401 .long 0x020100c0,0x00010010,0xf2019000,0xf23c8800
2402 .long 0x00000000,0xf22e48a8,0xff84f23c,0x90000000
2403 .long 0x0000f200,0x0018f200,0x0498f200,0x0438f292
2404 .long 0xfeca6000,0xfe14323b,0x120a4efb,0x10064afc
2405 .long 0x0030fdaa,0x00e2011a,0x0060fdaa,0x00660000
2406 .long 0x000000ba,0x006c011a,0x006000ba,0x00660000
2407 .long 0x00000130,0x0130010a,0x00600130,0x00660000
2408 .long 0x00000060,0x00600060,0x00600060,0x00660000
2409 .long 0x0000fdaa,0x00e2011a,0x0060fdaa,0x00660000
2410 .long 0x00000066,0x00660066,0x00660066,0x00660000
2411 .long 0x000060ff,0x000005b4,0x60ff0000,0x05ae1028
2412 .long 0x00001229,0x0000b300,0x6a144a00,0x6b2ef23c
2413 .long 0x44000000,0x00001d7c,0x0004ff64,0x4e75122e
2414 .long 0xff5f0201,0x00300c01,0x00206710,0xf23c4400
2415 .long 0x00000000,0x1d7c0004,0xff644e75,0xf23c4400
2416 .long 0x80000000,0x1d7c000c,0xff644e75,0x3d680000
2417 .long 0xff842d68,0x0004ff88,0x2d680008,0xff8c61ff
2418 .long 0x00000462,0x426eff90,0x42aeff94,0x42aeff98
2419 .long 0x6000fcd0,0x3d690000,0xff902d69,0x0004ff94
2420 .long 0x2d690008,0xff9861ff,0x000004e6,0x426eff84
2421 .long 0x42aeff88,0x42aeff8c,0x6000fca8,0x10280000
2422 .long 0x12290000,0xb3006aff,0x00000584,0xf228d080
2423 .long 0x0000f200,0x001af293,0x001e1d7c,0x000aff64
2424 .long 0x4e75f229,0xd0800000,0x4a290000,0x6a081d7c
2425 .long 0x000aff64,0x4e751d7c,0x0002ff64,0x4e750200
2426 .long 0x00300000,0x00406008,0x02000030,0x00000080
2427 .long 0x2d40ff5c,0x4241122e,0xff4e6600,0x02744a28
2428 .long 0x00006bff,0x00000528,0x020000c0,0x6648f22e
2429 .long 0x9000ff5c,0xf23c8800,0x00000000,0xf2104804
2430 .long 0xf201a800,0x83aeff64,0x4e754a28,0x00006bff
2431 .long 0x000004fc,0x020000c0,0x661c3d68,0x0000ff84
2432 .long 0x2d680004,0xff882d68,0x0008ff8c,0x61ff0000
2433 .long 0x03ae6000,0x003e0c00,0x00406600,0x00843d68
2434 .long 0x0000ff84,0x2d680004,0xff882d68,0x0008ff8c
2435 .long 0x61ff0000,0x038a0c80,0x0000007e,0x67000098
2436 .long 0x6e00009e,0x0c80ffff,0xff806700,0x01a46d00
2437 .long 0x0120f23c,0x88000000,0x0000f22e,0x9000ff5c
2438 .long 0xf22e4804,0xff84f201,0xa800f23c,0x90000000
2439 .long 0x000083ae,0xff642f02,0xf22ef080,0xff84322e
2440 .long 0xff842401,0x02810000,0x7fff9280,0x02428000
2441 .long 0x84413d42,0xff84241f,0xf22ed080,0xff844e75
2442 .long 0x3d680000,0xff842d68,0x0004ff88,0x2d680008
2443 .long 0xff8c61ff,0x00000308,0x0c800000,0x03fe6700
2444 .long 0x00166e1c,0x0c80ffff,0xfc006700,0x01246d00
2445 .long 0x00a06000,0xff7e082e,0x0000ff85,0x6600ff74
2446 .long 0x08ee0003,0xff66f23c,0x90000000,0x0010f23c
2447 .long 0x88000000,0x0000f22e,0x4804ff84,0xf201a800
2448 .long 0xf23c9000,0x00000000,0x83aeff64,0x122eff62
2449 .long 0x0201000b,0x6620f22e,0xf080ff84,0x41eeff84
2450 .long 0x222eff5c,0x61ff0000,0x2d28812e,0xff64f22e
2451 .long 0xd080ff84,0x4e752d6e,0xff88ff94,0x2d6eff8c
2452 .long 0xff98322e,0xff842f02,0x24010281,0x00007fff
2453 .long 0x02428000,0x92800681,0x00006000,0x02417fff
2454 .long 0x82423d41,0xff90f22e,0xd040ff90,0x241f60a6
2455 .long 0xf23c8800,0x00000000,0xf22e9000,0xff5cf22e
2456 .long 0x4804ff84,0xf23c9000,0x00000000,0xf201a800
2457 .long 0x83aeff64,0x00ae0000,0x1048ff64,0x122eff62
2458 .long 0x02010013,0x661c082e,0x0003ff64,0x56c1202e
2459 .long 0xff5c61ff,0x00002d98,0x812eff64,0xf210d080
2460 .long 0x4e752f02,0x322eff84,0x24010281,0x00007fff
2461 .long 0x02428000,0x92800481,0x00006000,0x02417fff
2462 .long 0x82423d41,0xff84f22e,0xd040ff84,0x241f60b6
2463 .long 0x082e0000,0xff856600,0xff78f23c,0x88000000
2464 .long 0x0000f22e,0x9000ff5c,0xf22e4804,0xff84f201
2465 .long 0xa800f23c,0x90000000,0x000083ae,0xff64f200
2466 .long 0x0080f23c,0x58b80001,0xf293ff6a,0x6000fe48
2467 .long 0x0c010004,0x6700fdb4,0x0c010001,0x67160c01
2468 .long 0x00026736,0x0c010005,0x67ff0000,0x023660ff
2469 .long 0x00000244,0x4a280000,0x6b10f23c,0x44000000
2470 .long 0x00001d7c,0x0004ff64,0x4e75f23c,0x44008000
2471 .long 0x00001d7c,0x000cff64,0x4e754a28,0x00006bff
2472 .long 0x0000026c,0xf228d080,0x00001d7c,0x0002ff64
2473 .long 0x4e752d68,0x0004ff88,0x2d690004,0xff942d68
2474 .long 0x0008ff8c,0x2d690008,0xff983028,0x00003229
2475 .long 0x00003d40,0xff843d41,0xff900240,0x7fff0241
2476 .long 0x7fff3d40,0xff543d41,0xff56b041,0x6cff0000
2477 .long 0x005c61ff,0x0000015a,0x2f000c2e,0x0004ff4e
2478 .long 0x661041ee,0xff8461ff,0x00002940,0x44403d40
2479 .long 0xff54302e,0xff560440,0x0042b06e,0xff546c1a
2480 .long 0x302eff54,0xd06f0002,0x322eff84,0x02418000
2481 .long 0x80413d40,0xff84201f,0x4e75026e,0x8000ff84
2482 .long 0x08ee0000,0xff85201f,0x4e7561ff,0x00000056
2483 .long 0x2f000c2e,0x0004ff4f,0x661041ee,0xff9061ff
2484 .long 0x000028e8,0x44403d40,0xff56302e,0xff540440
2485 .long 0x0042b06e,0xff566c1a,0x302eff56,0xd06f0002
2486 .long 0x322eff90,0x02418000,0x80413d40,0xff90201f
2487 .long 0x4e75026e,0x8000ff90,0x08ee0000,0xff91201f
2488 .long 0x4e75322e,0xff843001,0x02810000,0x7fff0240
2489 .long 0x80000040,0x3fff3d40,0xff840c2e,0x0004ff4e
2490 .long 0x670a203c,0x00003fff,0x90814e75,0x41eeff84
2491 .long 0x61ff0000,0x28764480,0x220060e6,0x0c2e0004
2492 .long 0xff4e673a,0x322eff84,0x02810000,0x7fff026e
2493 .long 0x8000ff84,0x08010000,0x6712006e,0x3fffff84
2494 .long 0x203c0000,0x3fff9081,0xe2804e75,0x006e3ffe
2495 .long 0xff84203c,0x00003ffe,0x9081e280,0x4e7541ee
2496 .long 0xff8461ff,0x00002824,0x08000000,0x6710006e
2497 .long 0x3fffff84,0x06800000,0x3fffe280,0x4e75006e
2498 .long 0x3ffeff84,0x06800000,0x3ffee280,0x4e75322e
2499 .long 0xff903001,0x02810000,0x7fff0240,0x80000040
2500 .long 0x3fff3d40,0xff900c2e,0x0004ff4f,0x670a203c
2501 .long 0x00003fff,0x90814e75,0x41eeff90,0x61ff0000
2502 .long 0x27ca4480,0x220060e6,0x0c2e0005,0xff4f6732
2503 .long 0x0c2e0003,0xff4f673e,0x0c2e0003,0xff4e6714
2504 .long 0x08ee0006,0xff7000ae,0x01004080,0xff6441ee
2505 .long 0xff6c6042,0x00ae0100,0x0000ff64,0x41eeff6c
2506 .long 0x603400ae,0x01004080,0xff6408ee,0x0006ff7c
2507 .long 0x41eeff78,0x602041ee,0xff780c2e,0x0005ff4e
2508 .long 0x66ff0000,0x000c00ae,0x00004080,0xff6400ae
2509 .long 0x01000000,0xff640828,0x00070000,0x670800ae
2510 .long 0x08000000,0xff64f210,0xd0804e75,0x00ae0100
2511 .long 0x2080ff64,0xf23bd080,0x01700000,0x00084e75
2512 .long 0x7fff0000,0xffffffff,0xffffffff,0x2d40ff54
2513 .long 0x302eff42,0x4281122e,0xff64e099,0xf2018800
2514 .long 0x323b0206,0x4efb1002,0x02340040,0x02f8030c
2515 .long 0x03200334,0x0348035c,0x03660352,0x033e032a
2516 .long 0x03160302,0x004a0238,0x023a0276,0x0054009e
2517 .long 0x0102014c,0x01b201fc,0x021801d8,0x018c0128
2518 .long 0x00de007a,0x02b6025a,0xf2810006,0x6000032a
2519 .long 0x4e75f28e,0x00066000,0x03204e75,0xf2920022
2520 .long 0x082e0000,0xff646700,0x031000ae,0x00008080
2521 .long 0xff64082e,0x0007ff62,0x6600032c,0x600002fa
2522 .long 0x4e75f29d,0x00066000,0x02f0082e,0x0000ff64
2523 .long 0x671200ae,0x00008080,0xff64082e,0x0007ff62
2524 .long 0x66000304,0x4e75f293,0x0022082e,0x0000ff64
2525 .long 0x670002c6,0x00ae0000,0x8080ff64,0x082e0007
2526 .long 0xff626600,0x02e26000,0x02b0082e,0x0000ff64
2527 .long 0x671200ae,0x00008080,0xff64082e,0x0007ff62
2528 .long 0x660002c4,0x4e75f29c,0x00066000,0x028c082e
2529 .long 0x0000ff64,0x671200ae,0x00008080,0xff64082e
2530 .long 0x0007ff62,0x660002a0,0x4e75f294,0x0022082e
2531 .long 0x0000ff64,0x67000262,0x00ae0000,0x8080ff64
2532 .long 0x082e0007,0xff626600,0x027e6000,0x024c4e75
2533 .long 0xf29b0006,0x60000242,0x082e0000,0xff646712
2534 .long 0x00ae0000,0x8080ff64,0x082e0007,0xff626600
2535 .long 0x02564e75,0xf2950022,0x082e0000,0xff646700
2536 .long 0x021800ae,0x00008080,0xff64082e,0x0007ff62
2537 .long 0x66000234,0x60000202,0x082e0000,0xff646712
2538 .long 0x00ae0000,0x8080ff64,0x082e0007,0xff626600
2539 .long 0x02164e75,0xf29a0006,0x600001de,0x082e0000
2540 .long 0xff646700,0x001400ae,0x00008080,0xff64082e
2541 .long 0x0007ff62,0x660001f0,0x4e75f296,0x0022082e
2542 .long 0x0000ff64,0x670001b2,0x00ae0000,0x8080ff64
2543 .long 0x082e0007,0xff626600,0x01ce6000,0x019c4e75
2544 .long 0xf2990006,0x60000192,0x082e0000,0xff646712
2545 .long 0x00ae0000,0x8080ff64,0x082e0007,0xff626600
2546 .long 0x01a64e75,0xf2970018,0x00ae0000,0x8080ff64
2547 .long 0x082e0007,0xff626600,0x018e6000,0x015c4e75
2548 .long 0xf2980006,0x60000152,0x00ae0000,0x8080ff64
2549 .long 0x082e0007,0xff626600,0x016e4e75,0x6000013a
2550 .long 0x4e75082e,0x0000ff64,0x6700012e,0x00ae0000
2551 .long 0x8080ff64,0x082e0007,0xff626600,0x014a6000
2552 .long 0x0118082e,0x0000ff64,0x671200ae,0x00008080
2553 .long 0xff64082e,0x0007ff62,0x6600012c,0x4e75f291
2554 .long 0x0022082e,0x0000ff64,0x670000ee,0x00ae0000
2555 .long 0x8080ff64,0x082e0007,0xff626600,0x010a6000
2556 .long 0x00d8082e,0x0000ff64,0x671200ae,0x00008080
2557 .long 0xff64082e,0x0007ff62,0x660000ec,0x4e75f29e
2558 .long 0x0022082e,0x0000ff64,0x670000ae,0x00ae0000
2559 .long 0x8080ff64,0x082e0007,0xff626600,0x00ca6000
2560 .long 0x0098082e,0x0000ff64,0x67000014,0x00ae0000
2561 .long 0x8080ff64,0x082e0007,0xff626600,0x00aa4e75
2562 .long 0xf2820006,0x60000072,0x4e75f28d,0x00066000
2563 .long 0x00684e75,0xf2830006,0x6000005e,0x4e75f28c
2564 .long 0x00066000,0x00544e75,0xf2840006,0x6000004a
2565 .long 0x4e75f28b,0x00066000,0x00404e75,0xf2850006
2566 .long 0x60000036,0x4e75f28a,0x00066000,0x002c4e75
2567 .long 0xf2860006,0x60000022,0x4e75f289,0x00066000
2568 .long 0x00184e75,0xf2870006,0x6000000e,0x4e75f288
2569 .long 0x00066000,0x00044e75,0x122eff41,0x02410007
2570 .long 0x61ff0000,0x1d665340,0x61ff0000,0x1dd00c40
2571 .long 0xffff6602,0x4e75202e,0xff54d0ae,0xff685880
2572 .long 0x2d400006,0x4e751d7c,0x0002ff4a,0x4e75302e
2573 .long 0xff424281,0x122eff64,0xe099f201,0x8800323b
2574 .long 0x02064efb,0x1002021e,0x004002e4,0x02f002fc
2575 .long 0x03080314,0x03200326,0x031a030e,0x030202f6
2576 .long 0x02ea0046,0x02200224,0x0260004c,0x009200f8
2577 .long 0x013e01a4,0x01ea0202,0x01c4017e,0x011800d2
2578 .long 0x006c02a2,0x0240f281,0x02ea4e75,0xf28e02e4
2579 .long 0x4e75f292,0x02de082e,0x0000ff64,0x671200ae
2580 .long 0x00008080,0xff64082e,0x0007ff62,0x660002cc
2581 .long 0x4e75f29d,0x00044e75,0x082e0000,0xff646700
2582 .long 0x02b200ae,0x00008080,0xff64082e,0x0007ff62
2583 .long 0x660002a8,0x6000029c,0xf293001e,0x082e0000
2584 .long 0xff646712,0x00ae0000,0x8080ff64,0x082e0007
2585 .long 0xff626600,0x02864e75,0x082e0000,0xff646700
2586 .long 0x027200ae,0x00008080,0xff64082e,0x0007ff62
2587 .long 0x66000268,0x6000025c,0xf29c0004,0x4e75082e
2588 .long 0x0000ff64,0x6700024c,0x00ae0000,0x8080ff64
2589 .long 0x082e0007,0xff626600,0x02426000,0x0236f294
2590 .long 0x0232082e,0x0000ff64,0x671200ae,0x00008080
2591 .long 0xff64082e,0x0007ff62,0x66000220,0x4e75f29b
2592 .long 0x00044e75,0x082e0000,0xff646700,0x020600ae
2593 .long 0x00008080,0xff64082e,0x0007ff62,0x660001fc
2594 .long 0x600001f0,0xf295001e,0x082e0000,0xff646712
2595 .long 0x00ae0000,0x8080ff64,0x082e0007,0xff626600
2596 .long 0x01da4e75,0x082e0000,0xff646700,0x01c600ae
2597 .long 0x00008080,0xff64082e,0x0007ff62,0x660001bc
2598 .long 0x600001b0,0xf29a0004,0x4e75082e,0x0000ff64
2599 .long 0x670001a0,0x00ae0000,0x8080ff64,0x082e0007
2600 .long 0xff626600,0x01966000,0x018af296,0x0186082e
2601 .long 0x0000ff64,0x671200ae,0x00008080,0xff64082e
2602 .long 0x0007ff62,0x66000174,0x4e75f299,0x00044e75
2603 .long 0x082e0000,0xff646700,0x015a00ae,0x00008080
2604 .long 0xff64082e,0x0007ff62,0x66000150,0x60000144
2605 .long 0xf2970140,0x00ae0000,0x8080ff64,0x082e0007
2606 .long 0xff626600,0x01364e75,0xf2980004,0x4e7500ae
2607 .long 0x00008080,0xff64082e,0x0007ff62,0x6600011c
2608 .long 0x60000110,0x4e756000,0x010a082e,0x0000ff64
2609 .long 0x671200ae,0x00008080,0xff64082e,0x0007ff62
2610 .long 0x660000f8,0x4e75082e,0x0000ff64,0x670000e4
2611 .long 0x00ae0000,0x8080ff64,0x082e0007,0xff626600
2612 .long 0x00da6000,0x00cef291,0x0020082e,0x0000ff64
2613 .long 0x67000014,0x00ae0000,0x8080ff64,0x082e0007
2614 .long 0xff626600,0x00b64e75,0x082e0000,0xff646700
2615 .long 0x00a200ae,0x00008080,0xff64082e,0x0007ff62
2616 .long 0x66000098,0x6000008c,0xf29e0020,0x082e0000
2617 .long 0xff646700,0x001400ae,0x00008080,0xff64082e
2618 .long 0x0007ff62,0x66000074,0x4e75082e,0x0000ff64
2619 .long 0x67000060,0x00ae0000,0x8080ff64,0x082e0007
2620 .long 0xff626600,0x00566000,0x004af282,0x00464e75
2621 .long 0xf28d0040,0x4e75f283,0x003a4e75,0xf28c0034
2622 .long 0x4e75f284,0x002e4e75,0xf28b0028,0x4e75f285
2623 .long 0x00224e75,0xf28a001c,0x4e75f286,0x00164e75
2624 .long 0xf2890010,0x4e75f287,0x000a4e75,0xf2880004
2625 .long 0x4e751d7c,0x0001ff4a,0x4e751d7c,0x0002ff4a
2626 .long 0x4e75302e,0xff424281,0x122eff64,0xe099f201
2627 .long 0x8800323b,0x02064efb,0x10020208,0x004002ac
2628 .long 0x02cc02ec,0x030c032c,0x034c035c,0x033c031c
2629 .long 0x02fc02dc,0x02bc0050,0x020e0214,0x02440060
2630 .long 0x00a400fa,0x013e0194,0x01d801f0,0x01b60172
2631 .long 0x011c00d8,0x00820278,0x022cf281,0x00084200
2632 .long 0x6000032e,0x50c06000,0x0328f28e,0x00084200
2633 .long 0x6000031e,0x50c06000,0x0318f292,0x001a4200
2634 .long 0x082e0000,0xff646700,0x030800ae,0x00008080
2635 .long 0xff646000,0x02f250c0,0x600002f6,0xf29d0008
2636 .long 0x42006000,0x02ec50c0,0x082e0000,0xff646700
2637 .long 0x02e000ae,0x00008080,0xff646000,0x02caf293
2638 .long 0x001a4200,0x082e0000,0xff646700,0x02c400ae
2639 .long 0x00008080,0xff646000,0x02ae50c0,0x082e0000
2640 .long 0xff646700,0x02ac00ae,0x00008080,0xff646000
2641 .long 0x0296f29c,0x00084200,0x60000296,0x50c0082e
2642 .long 0x0000ff64,0x6700028a,0x00ae0000,0x8080ff64
2643 .long 0x60000274,0xf294001a,0x4200082e,0x0000ff64
2644 .long 0x6700026e,0x00ae0000,0x8080ff64,0x60000258
2645 .long 0x50c06000,0x025cf29b,0x00084200,0x60000252
2646 .long 0x50c0082e,0x0000ff64,0x67000246,0x00ae0000
2647 .long 0x8080ff64,0x60000230,0xf295001a,0x4200082e
2648 .long 0x0000ff64,0x6700022a,0x00ae0000,0x8080ff64
2649 .long 0x60000214,0x50c0082e,0x0000ff64,0x67000212
2650 .long 0x00ae0000,0x8080ff64,0x600001fc,0xf29a0008
2651 .long 0x42006000,0x01fc50c0,0x082e0000,0xff646700
2652 .long 0x01f000ae,0x00008080,0xff646000,0x01daf296
2653 .long 0x001a4200,0x082e0000,0xff646700,0x01d400ae
2654 .long 0x00008080,0xff646000,0x01be50c0,0x600001c2
2655 .long 0xf2990008,0x42006000,0x01b850c0,0x082e0000
2656 .long 0xff646700,0x01ac00ae,0x00008080,0xff646000
2657 .long 0x0196f297,0x00104200,0x00ae0000,0x8080ff64
2658 .long 0x60000184,0x50c06000,0x0188f298,0x00084200
2659 .long 0x6000017e,0x50c000ae,0x00008080,0xff646000
2660 .long 0x01664200,0x6000016a,0x50c06000,0x01644200
2661 .long 0x082e0000,0xff646700,0x015800ae,0x00008080
2662 .long 0xff646000,0x014250c0,0x082e0000,0xff646700
2663 .long 0x014000ae,0x00008080,0xff646000,0x012af291
2664 .long 0x001a4200,0x082e0000,0xff646700,0x012400ae
2665 .long 0x00008080,0xff646000,0x010e50c0,0x082e0000
2666 .long 0xff646700,0x010c00ae,0x00008080,0xff646000
2667 .long 0x00f6f29e,0x001a4200,0x082e0000,0xff646700
2668 .long 0x00f000ae,0x00008080,0xff646000,0x00da50c0
2669 .long 0x082e0000,0xff646700,0x00d800ae,0x00008080
2670 .long 0xff646000,0x00c2f282,0x00084200,0x600000c2
2671 .long 0x50c06000,0x00bcf28d,0x00084200,0x600000b2
2672 .long 0x50c06000,0x00acf283,0x00084200,0x600000a2
2673 .long 0x50c06000,0x009cf28c,0x00084200,0x60000092
2674 .long 0x50c06000,0x008cf284,0x00084200,0x60000082
2675 .long 0x50c06000,0x007cf28b,0x00084200,0x60000072
2676 .long 0x50c06000,0x006cf285,0x00084200,0x60000062
2677 .long 0x50c06000,0x005cf28a,0x00084200,0x60000052
2678 .long 0x50c06000,0x004cf286,0x00084200,0x60000042
2679 .long 0x50c06000,0x003cf289,0x00084200,0x60000032
2680 .long 0x50c06000,0x002cf287,0x00084200,0x60000022
2681 .long 0x50c06000,0x001cf288,0x00084200,0x60000012
2682 .long 0x50c06000,0x000c082e,0x0007ff62,0x66000088
2683 .long 0x2040122e,0xff412001,0x02010038,0x66102200
2684 .long 0x02410007,0x200861ff,0x0000172a,0x4e750c01
2685 .long 0x0018671a,0x0c010020,0x67382008,0x206e000c
2686 .long 0x61ffffff,0x5a7c4a81,0x66000054,0x4e752008
2687 .long 0x206e000c,0x61ffffff,0x5a684a81,0x66000040
2688 .long 0x122eff41,0x02410007,0x700161ff,0x00001722
2689 .long 0x4e752008,0x206e000c,0x61ffffff,0x5a444a81
2690 .long 0x6600001c,0x122eff41,0x02410007,0x700161ff
2691 .long 0x0000174e,0x4e751d7c,0x0002ff4a,0x4e753d7c
2692 .long 0x00a1000a,0x60ff0000,0x2b86122e,0xff430241
2693 .long 0x0070e809,0x61ff0000,0x15b20280,0x000000ff
2694 .long 0x2f00103b,0x09200148,0x2f0061ff,0x00000340
2695 .long 0x201f221f,0x67000134,0x082e0005,0xff426700
2696 .long 0x00b8082e,0x0004ff42,0x6600001a,0x123b1120
2697 .long 0x021e082e,0x00050004,0x670a0c2e,0x0008ff4a
2698 .long 0x66024e75,0x22489fc0,0x41d74a01,0x6a0c20ee
2699 .long 0xffdc20ee,0xffe020ee,0xffe4e309,0x6a0c20ee
2700 .long 0xffe820ee,0xffec20ee,0xfff0e309,0x6a0af210
2701 .long 0xf020d1fc,0x0000000c,0xe3096a0a,0xf210f010
2702 .long 0xd1fc0000,0x000ce309,0x6a0af210,0xf008d1fc
2703 .long 0x0000000c,0xe3096a0a,0xf210f004,0xd1fc0000
2704 .long 0x000ce309,0x6a0af210,0xf002d1fc,0x0000000c
2705 .long 0xe3096a0a,0xf210f001,0xd1fc0000,0x000c2d49
2706 .long 0xff5441d7,0x2f0061ff,0xffff58b2,0x201fdfc0
2707 .long 0x4a816600,0x071e4e75,0x2d48ff54,0x9fc043d7
2708 .long 0x2f012f00,0x61ffffff,0x587e201f,0x4a816600
2709 .long 0x070e221f,0x41d74a01,0x6a0c2d58,0xffdc2d58
2710 .long 0xffe02d58,0xffe4e309,0x6a0c2d58,0xffe82d58
2711 .long 0xffec2d58,0xfff0e309,0x6a04f218,0xd020e309
2712 .long 0x6a04f218,0xd010e309,0x6a04f218,0xd008e309
2713 .long 0x6a04f218,0xd004e309,0x6a04f218,0xd002e309
2714 .long 0x6a04f218,0xd001dfc0,0x4e754e75,0x000c0c18
2715 .long 0x0c181824,0x0c181824,0x18242430,0x0c181824
2716 .long 0x18242430,0x18242430,0x2430303c,0x0c181824
2717 .long 0x18242430,0x18242430,0x2430303c,0x18242430
2718 .long 0x2430303c,0x2430303c,0x303c3c48,0x0c181824
2719 .long 0x18242430,0x18242430,0x2430303c,0x18242430
2720 .long 0x2430303c,0x2430303c,0x303c3c48,0x18242430
2721 .long 0x2430303c,0x2430303c,0x303c3c48,0x2430303c
2722 .long 0x303c3c48,0x303c3c48,0x3c484854,0x0c181824
2723 .long 0x18242430,0x18242430,0x2430303c,0x18242430
2724 .long 0x2430303c,0x2430303c,0x303c3c48,0x18242430
2725 .long 0x2430303c,0x2430303c,0x303c3c48,0x2430303c
2726 .long 0x303c3c48,0x303c3c48,0x3c484854,0x18242430
2727 .long 0x2430303c,0x2430303c,0x303c3c48,0x2430303c
2728 .long 0x303c3c48,0x303c3c48,0x3c484854,0x2430303c
2729 .long 0x303c3c48,0x303c3c48,0x3c484854,0x303c3c48
2730 .long 0x3c484854,0x3c484854,0x48545460,0x008040c0
2731 .long 0x20a060e0,0x109050d0,0x30b070f0,0x088848c8
2732 .long 0x28a868e8,0x189858d8,0x38b878f8,0x048444c4
2733 .long 0x24a464e4,0x149454d4,0x34b474f4,0x0c8c4ccc
2734 .long 0x2cac6cec,0x1c9c5cdc,0x3cbc7cfc,0x028242c2
2735 .long 0x22a262e2,0x129252d2,0x32b272f2,0x0a8a4aca
2736 .long 0x2aaa6aea,0x1a9a5ada,0x3aba7afa,0x068646c6
2737 .long 0x26a666e6,0x169656d6,0x36b676f6,0x0e8e4ece
2738 .long 0x2eae6eee,0x1e9e5ede,0x3ebe7efe,0x018141c1
2739 .long 0x21a161e1,0x119151d1,0x31b171f1,0x098949c9
2740 .long 0x29a969e9,0x199959d9,0x39b979f9,0x058545c5
2741 .long 0x25a565e5,0x159555d5,0x35b575f5,0x0d8d4dcd
2742 .long 0x2dad6ded,0x1d9d5ddd,0x3dbd7dfd,0x038343c3
2743 .long 0x23a363e3,0x139353d3,0x33b373f3,0x0b8b4bcb
2744 .long 0x2bab6beb,0x1b9b5bdb,0x3bbb7bfb,0x078747c7
2745 .long 0x27a767e7,0x179757d7,0x37b777f7,0x0f8f4fcf
2746 .long 0x2faf6fef,0x1f9f5fdf,0x3fbf7fff,0x2040302e
2747 .long 0xff403200,0x0240003f,0x02810000,0x0007303b
2748 .long 0x020a4efb,0x00064afc,0x00400000,0x00000000
2749 .long 0x00000000,0x00000000,0x00000000,0x00000000
2750 .long 0x00000000,0x00000000,0x00000080,0x0086008c
2751 .long 0x00900094,0x0098009c,0x00a000a6,0x00b600c6
2752 .long 0x00d200de,0x00ea00f6,0x01020118,0x01260134
2753 .long 0x013e0148,0x0152015c,0x0166017a,0x019801b6
2754 .long 0x01d201ee,0x020a0226,0x02420260,0x02600260
2755 .long 0x02600260,0x02600260,0x026002c0,0x02da02f4
2756 .long 0x03140000,0x00000000,0x0000206e,0xffa44e75
2757 .long 0x206effa8,0x4e75204a,0x4e75204b,0x4e75204c
2758 .long 0x4e75204d,0x4e752056,0x4e75206e,0xffd84e75
2759 .long 0x202effa4,0x2200d288,0x2d41ffa4,0x20404e75
2760 .long 0x202effa8,0x2200d288,0x2d41ffa8,0x20404e75
2761 .long 0x200a2200,0xd2882441,0x20404e75,0x200b2200
2762 .long 0xd2882641,0x20404e75,0x200c2200,0xd2882841
2763 .long 0x20404e75,0x200d2200,0xd2882a41,0x20404e75
2764 .long 0x20162200,0xd2882c81,0x20404e75,0x1d7c0004
2765 .long 0xff4a202e,0xffd82200,0xd2882d41,0xffd82040
2766 .long 0x4e75202e,0xffa49088,0x2d40ffa4,0x20404e75
2767 .long 0x202effa8,0x90882d40,0xffa82040,0x4e75200a
2768 .long 0x90882440,0x20404e75,0x200b9088,0x26402040
2769 .long 0x4e75200c,0x90882840,0x20404e75,0x200d9088
2770 .long 0x2a402040,0x4e752016,0x90882c80,0x20404e75
2771 .long 0x1d7c0008,0xff4a202e,0xffd89088,0x2d40ffd8
2772 .long 0x20404e75,0x206eff44,0x54aeff44,0x61ffffff
2773 .long 0x54a24a81,0x66ffffff,0x68203040,0xd1eeffa4
2774 .long 0x4e75206e,0xff4454ae,0xff4461ff,0xffff5484
2775 .long 0x4a8166ff,0xffff6802,0x3040d1ee,0xffa84e75
2776 .long 0x206eff44,0x54aeff44,0x61ffffff,0x54664a81
2777 .long 0x66ffffff,0x67e43040,0xd1ca4e75,0x206eff44
2778 .long 0x54aeff44,0x61ffffff,0x544a4a81,0x66ffffff
2779 .long 0x67c83040,0xd1cb4e75,0x206eff44,0x54aeff44
2780 .long 0x61ffffff,0x542e4a81,0x66ffffff,0x67ac3040
2781 .long 0xd1cc4e75,0x206eff44,0x54aeff44,0x61ffffff
2782 .long 0x54124a81,0x66ffffff,0x67903040,0xd1cd4e75
2783 .long 0x206eff44,0x54aeff44,0x61ffffff,0x53f64a81
2784 .long 0x66ffffff,0x67743040,0xd1d64e75,0x206eff44
2785 .long 0x54aeff44,0x61ffffff,0x53da4a81,0x66ffffff
2786 .long 0x67583040,0xd1eeffd8,0x4e755081,0x61ff0000
2787 .long 0x0fda2f00,0x206eff44,0x54aeff44,0x61ffffff
2788 .long 0x53b24a81,0x66ffffff,0x6730205f,0x08000008
2789 .long 0x660000e6,0x2d40ff54,0x2200e959,0x0241000f
2790 .long 0x61ff0000,0x0fa62f02,0x242eff54,0x0802000b
2791 .long 0x660248c0,0x2202ef59,0x02810000,0x0003e3a8
2792 .long 0x49c2d082,0xd1c0241f,0x4e75206e,0xff4454ae
2793 .long 0xff4461ff,0xffff535c,0x4a8166ff,0xffff66da
2794 .long 0x30404e75,0x206eff44,0x58aeff44,0x61ffffff
2795 .long 0x53584a81,0x66ffffff,0x66c02040,0x4e75206e
2796 .long 0xff4454ae,0xff4461ff,0xffff5328,0x4a8166ff
2797 .long 0xffff66a6,0x3040d1ee,0xff445588,0x4e75206e
2798 .long 0xff4454ae,0xff4461ff,0xffff5308,0x4a8166ff
2799 .long 0xffff6686,0x206eff44,0x55880800,0x00086600
2800 .long 0x00382d40,0xff542200,0xe9590241,0x000f61ff
2801 .long 0x00000ef8,0x2f02242e,0xff540802,0x000b6602
2802 .long 0x48c02202,0xef590281,0x00000003,0xe3a849c2
2803 .long 0xd082d1c0,0x241f4e75,0x08000006,0x670c48e7
2804 .long 0x3c002a00,0x26084282,0x60282d40,0xff54e9c0
2805 .long 0x140461ff,0x00000eb4,0x48e73c00,0x24002a2e
2806 .long 0xff542608,0x0805000b,0x660248c2,0xe9c50542
2807 .long 0xe1aa0805,0x00076702,0x4283e9c5,0x06820c00
2808 .long 0x00026d34,0x6718206e,0xff4458ae,0xff4461ff
2809 .long 0xffff5276,0x4a8166ff,0x000000b0,0x6018206e
2810 .long 0xff4454ae,0xff4461ff,0xffff5248,0x4a8166ff
2811 .long 0x00000098,0x48c0d680,0xe9c50782,0x6700006e
2812 .long 0x0c000002,0x6d346718,0x206eff44,0x58aeff44
2813 .long 0x61ffffff,0x52344a81,0x66ff0000,0x006e601c
2814 .long 0x206eff44,0x54aeff44,0x61ffffff,0x52064a81
2815 .long 0x66ff0000,0x005648c0,0x60024280,0x28000805
2816 .long 0x00026714,0x204361ff,0xffff5240,0x4a816600
2817 .long 0x0028d082,0xd0846018,0xd6822043,0x61ffffff
2818 .long 0x522a4a81,0x66000012,0xd0846004,0xd6822003
2819 .long 0x20404cdf,0x003c4e75,0x20434cdf,0x003c303c
2820 .long 0x010160ff,0xffff6582,0x4cdf003c,0x60ffffff
2821 .long 0x652861ff,0x000023c6,0x303c00e1,0x600a61ff
2822 .long 0x000023ba,0x303c0161,0x206eff54,0x60ffffff
2823 .long 0x6558102e,0xff420c00,0x009c6700,0x00b20c00
2824 .long 0x00986700,0x00740c00,0x00946736,0x206eff44
2825 .long 0x58aeff44,0x61ffffff,0x51704a81,0x66ffffff
2826 .long 0x64d82d40,0xff64206e,0xff4458ae,0xff4461ff
2827 .long 0xffff5156,0x4a8166ff,0xffff64be,0x2d40ff68
2828 .long 0x4e75206e,0xff4458ae,0xff4461ff,0xffff513a
2829 .long 0x4a8166ff,0xffff64a2,0x2d40ff60,0x206eff44
2830 .long 0x58aeff44,0x61ffffff,0x51204a81,0x66ffffff
2831 .long 0x64882d40,0xff684e75,0x206eff44,0x58aeff44
2832 .long 0x61ffffff,0x51044a81,0x66ffffff,0x646c2d40
2833 .long 0xff60206e,0xff4458ae,0xff4461ff,0xffff50ea
2834 .long 0x4a8166ff,0xffff6452,0x2d40ff64,0x4e75206e
2835 .long 0xff4458ae,0xff4461ff,0xffff50ce,0x4a8166ff
2836 .long 0xffff6436,0x2d40ff60,0x206eff44,0x58aeff44
2837 .long 0x61ffffff,0x50b44a81,0x66ffffff,0x641c2d40
2838 .long 0xff64206e,0xff4458ae,0xff4461ff,0xffff509a
2839 .long 0x4a8166ff,0xffff6402,0x2d40ff68,0x4e752040
2840 .long 0x102eff41,0x22000240,0x00380281,0x00000007
2841 .long 0x0c000018,0x67240c00,0x0020672c,0x80410c00
2842 .long 0x003c6706,0x206e000c,0x4e751d7c,0x0080ff4a
2843 .long 0x41f60162,0xff680004,0x4e752008,0x61ff0000
2844 .long 0x0d70206e,0x000c4e75,0x200861ff,0x00000db2
2845 .long 0x206e000c,0x0c00000c,0x67024e75,0x51882d48
2846 .long 0x000c4e75,0x102eff41,0x22000240,0x00380281
2847 .long 0x00000007,0x0c000018,0x670e0c00,0x00206700
2848 .long 0x0076206e,0x000c4e75,0x323b120e,0x206e000c
2849 .long 0x4efb1006,0x4afc0008,0x0010001a,0x0024002c
2850 .long 0x0034003c,0x0044004e,0x06ae0000,0x000cffa4
2851 .long 0x4e7506ae,0x0000000c,0xffa84e75,0xd5fc0000
2852 .long 0x000c4e75,0xd7fc0000,0x000c4e75,0xd9fc0000
2853 .long 0x000c4e75,0xdbfc0000,0x000c4e75,0x06ae0000
2854 .long 0x000cffd4,0x4e751d7c,0x0004ff4a,0x06ae0000
2855 .long 0x000cffd8,0x4e75323b,0x1214206e,0x000c5188
2856 .long 0x51ae000c,0x4efb1006,0x4afc0008,0x00100016
2857 .long 0x001c0020,0x00240028,0x002c0032,0x2d48ffa4
2858 .long 0x4e752d48,0xffa84e75,0x24484e75,0x26484e75
2859 .long 0x28484e75,0x2a484e75,0x2d48ffd4,0x4e752d48
2860 .long 0xffd81d7c,0x0008ff4a,0x4e75082e,0x0006ff42
2861 .long 0x6664102e,0xff430800,0x0005672c,0x08000004
2862 .long 0x670a0240,0x007f0c40,0x0038661c,0xe9ee0183
2863 .long 0xff4261ff,0x00000d6a,0x61ff0000,0x12060c00
2864 .long 0x00066722,0x1d40ff4f,0xe9ee00c3,0xff4261ff
2865 .long 0x00000cbe,0x61ff0000,0x11ea0c00,0x0006670e
2866 .long 0x1d40ff4e,0x4e7561ff,0x00001148,0x60d661ff
2867 .long 0x00001140,0x60ea302e,0xff420800,0x0005672c
2868 .long 0x08000004,0x670a0240,0x007f0c40,0x0038661c
2869 .long 0xe9ee0183,0xff4261ff,0x00000d06,0x61ff0000
2870 .long 0x11a20c00,0x00066726,0x1d40ff4f,0xe9ee00c3
2871 .long 0xff42e9ee,0x1283ff40,0x660000be,0x422eff4e
2872 .long 0xe9ee1343,0xff40303b,0x02124efb,0x000e61ff
2873 .long 0x000010e0,0x60d24afc,0x00080010,0x006a0000
2874 .long 0x0000002e,0x0000004c,0x000061ff,0x00000a5c
2875 .long 0xf2004000,0xf22ef080,0xff6cf281,0x00044e75
2876 .long 0x1d7c0001,0xff4e4e75,0x61ff0000,0x0a3ef200
2877 .long 0x5000f22e,0xf080ff6c,0xf2810004,0x4e751d7c
2878 .long 0x0001ff4e,0x4e7561ff,0x00000a20,0xf2005800
2879 .long 0xf22ef080,0xff6cf281,0x00044e75,0x1d7c0001
2880 .long 0xff4e4e75,0x61ff0000,0x0a022d40,0xff5441ee
2881 .long 0xff5461ff,0x000011de,0x1d40ff4e,0x0c000005
2882 .long 0x670001a4,0x0c000004,0x6700015e,0xf2104400
2883 .long 0xf22ef080,0xff6c4e75,0x422eff4e,0x303b020a
2884 .long 0x4efb0006,0x4afc0008,0x001000e2,0x027202b0
2885 .long 0x005601a0,0x009c0000,0x700461ff,0xfffffd22
2886 .long 0x0c2e0080,0xff4a6726,0x61ffffff,0x4dde4a81
2887 .long 0x66ff0000,0x1eecf200,0x4000f22e,0xf080ff6c
2888 .long 0xf2810004,0x4e751d7c,0x0001ff4e,0x4e7561ff
2889 .long 0xffff4d76,0x4a8166ff,0xffff6e8a,0x60d87002
2890 .long 0x61ffffff,0xfcdc0c2e,0x0080ff4a,0x672661ff
2891 .long 0xffff4d82,0x4a8166ff,0x00001e98,0xf2005000
2892 .long 0xf22ef080,0xff6cf281,0x00044e75,0x1d7c0001
2893 .long 0xff4e4e75,0x61ffffff,0x4d1a4a81,0x66ffffff
2894 .long 0x6e4460d8,0x700161ff,0xfffffc96,0x0c2e0080
2895 .long 0xff4a6726,0x61ffffff,0x4d264a81,0x66ff0000
2896 .long 0x1e42f200,0x5800f22e,0xf080ff6c,0xf2810004
2897 .long 0x4e751d7c,0x0001ff4e,0x4e7561ff,0xffff4cd4
2898 .long 0x4a8166ff,0xffff6dfe,0x60d87004,0x61ffffff
2899 .long 0xfc500c2e,0x0080ff4a,0x673e61ff,0xffff4d0c
2900 .long 0x2d40ff54,0x4a8166ff,0x00001e16,0x41eeff54
2901 .long 0x61ff0000,0x10a01d40,0xff4e0c00,0x00046700
2902 .long 0x00280c00,0x00056700,0x005ef22e,0x4400ff54
2903 .long 0xf22ef080,0xff6c4e75,0x61ffffff,0x4c8c4a81
2904 .long 0x66ffffff,0x6da060c4,0x426eff6c,0xe9d00257
2905 .long 0xe1882d40,0xff7042ae,0xff74426e,0xff6c0810
2906 .long 0x00076706,0x08ee0007,0xff6c41ee,0xff6c61ff
2907 .long 0x00000e78,0x323c3f81,0x9240836e,0xff6c1d7c
2908 .long 0x0000ff4e,0x4e753d7c,0x7fffff6c,0xe9d00257
2909 .long 0xe1882d40,0xff7042ae,0xff740810,0x00076706
2910 .long 0x08ee0007,0xff6c4e75,0x700861ff,0xfffffb92
2911 .long 0x0c2e0080,0xff4a6740,0x43eeff54,0x700861ff
2912 .long 0xffff4bc4,0x4a8166ff,0x00001d64,0x41eeff54
2913 .long 0x61ff0000,0x0f701d40,0xff4e0c00,0x00046700
2914 .long 0x002e0c00,0x00056700,0x0068f22e,0x5400ff54
2915 .long 0xf22ef080,0xff6c4e75,0x43eeff54,0x700861ff
2916 .long 0xffff4b6e,0x4a8166ff,0xffff6cda,0x60be426e
2917 .long 0xff6ce9d0,0x031f2d40,0xff70e9e8,0x02d50004
2918 .long 0x720be3a8,0x2d40ff74,0x08100007,0x670608ee
2919 .long 0x0007ff6c,0x41eeff6c,0x61ff0000,0x0dae323c
2920 .long 0x3c019240,0x836eff6c,0x1d7c0000,0xff4e4e75
2921 .long 0x3d7c7fff,0xff6ce9d0,0x031f2d40,0xff70e9e8
2922 .long 0x02d50004,0x720be3a8,0x2d40ff74,0x08100007
2923 .long 0x670608ee,0x0007ff6c,0x4e75700c,0x61ffffff
2924 .long 0xfac043ee,0xff6c700c,0x61ffffff,0x4afa4a81
2925 .long 0x66ff0000,0x1ca841ee,0xff6c61ff,0x00000e24
2926 .long 0x0c000006,0x67061d40,0xff4e4e75,0x61ff0000
2927 .long 0x0d821d40,0xff4e4e75,0x61ff0000,0x125441ee
2928 .long 0xff6c61ff,0x00000dfc,0x0c000006,0x67061d40
2929 .long 0xff4e4e75,0x61ff0000,0x0d5a1d40,0xff4e4e75
2930 .long 0xe9ee10c3,0xff42327b,0x120a4efb,0x98064afc
2931 .long 0x000800e0,0x01e00148,0x06200078,0x041a0010
2932 .long 0x06204a2e,0xff4e664c,0xf228d080,0x0000f200
2933 .long 0x9000f200,0x7800f23c,0x90000000,0x0000f201
2934 .long 0xa800836e,0xff66122e,0xff410201,0x00386714
2935 .long 0x206e000c,0x61ffffff,0x4ae84a81,0x66ff0000
2936 .long 0x1c0a4e75,0x122eff41,0x02410007,0x61ff0000
2937 .long 0x07644e75,0x22280000,0x02818000,0x00000081
2938 .long 0x00800000,0xf2014400,0x60a44a2e,0xff4e664c
2939 .long 0xf228d080,0x0000f200,0x9000f200,0x7000f23c
2940 .long 0x90000000,0x0000f201,0xa800836e,0xff66122e
2941 .long 0xff410201,0x00386714,0x206e000c,0x61ffffff
2942 .long 0x4a964a81,0x66ff0000,0x1bb04e75,0x122eff41
2943 .long 0x02410007,0x61ff0000,0x06c04e75,0x22280000
2944 .long 0x02818000,0x00000081,0x00800000,0xf2014400
2945 .long 0x60a44a2e,0xff4e664c,0xf228d080,0x0000f200
2946 .long 0x9000f200,0x6000f23c,0x90000000,0x0000f201
2947 .long 0xa800836e,0xff66122e,0xff410201,0x00386714
2948 .long 0x206e000c,0x61ffffff,0x4a444a81,0x66ff0000
2949 .long 0x1b564e75,0x122eff41,0x02410007,0x61ff0000
2950 .long 0x061c4e75,0x22280000,0x02818000,0x00000081
2951 .long 0x00800000,0xf2014400,0x60a43d68,0x0000ff84
2952 .long 0x426eff86,0x2d680004,0xff882d68,0x0008ff8c
2953 .long 0xf228d080,0x000061ff,0xfffff94c,0x224841ee
2954 .long 0xff84700c,0x0c2e0008,0xff4a6726,0x61ffffff
2955 .long 0x492c4a81,0x66000052,0x4a2eff4e,0x66024e75
2956 .long 0x08ee0003,0xff66102e,0xff620200,0x000a6616
2957 .long 0x4e7561ff,0xffff5788,0x4a816600,0x002c4a2e
2958 .long 0xff4e66dc,0x4e7541ee,0xff8461ff,0x00000b3c
2959 .long 0x44400240,0x7fff026e,0x8000ff84,0x816eff84
2960 .long 0xf22ed040,0xff844e75,0x2caeffd4,0x60ff0000
2961 .long 0x1ab20200,0x00300000,0x00402d40,0xff5c3028
2962 .long 0x00000240,0x7fff0c40,0x407e6e00,0x00e66700
2963 .long 0x01520c40,0x3f816d00,0x0058f228,0xd0800000
2964 .long 0xf22e9000,0xff5cf23c,0x88000000,0x0000f200
2965 .long 0x6400f23c,0x90000000,0x0000f201,0xa800836e
2966 .long 0xff66122e,0xff410201,0x00386714,0x206e000c
2967 .long 0x61ffffff,0x49184a81,0x66ff0000,0x1a2a4e75
2968 .long 0x122eff41,0x02410007,0x61ff0000,0x04f04e75
2969 .long 0x08ee0003,0xff663d68,0x0000ff84,0x2d680004
2970 .long 0xff882d68,0x0008ff8c,0x2f084280,0x0c2e0004
2971 .long 0xff4e660a,0x41eeff84,0x61ff0000,0x0a6e41ee
2972 .long 0xff84222e,0xff5c61ff,0x00000c86,0x41eeff84
2973 .long 0x61ff0000,0x034c122e,0xff410201,0x00386714
2974 .long 0x206e000c,0x61ffffff,0x48a44a81,0x66ff0000
2975 .long 0x19b6600e,0x122eff41,0x02410007,0x61ff0000
2976 .long 0x047c122e,0xff620201,0x000a6600,0x00b8588f
2977 .long 0x4e754a28,0x0007660e,0x4aa80008,0x6608006e
2978 .long 0x1048ff66,0x6006006e,0x1248ff66,0x2f084a28
2979 .long 0x00005bc1,0x202eff5c,0x61ff0000,0x0d12f210
2980 .long 0xd080f200,0x6400122e,0xff410201,0x00386714
2981 .long 0x206e000c,0x61ffffff,0x48344a81,0x66ff0000
2982 .long 0x1946600e,0x122eff41,0x02410007,0x61ff0000
2983 .long 0x040c122e,0xff620201,0x000a6600,0x007c588f
2984 .long 0x4e753228,0x00000241,0x80000041,0x3fff3d41
2985 .long 0xff842d68,0x0004ff88,0x2d680008,0xff8cf22e
2986 .long 0x9000ff5c,0xf22e4800,0xff84f23c,0x90000000
2987 .long 0x0000f200,0x0018f23c,0x58380002,0xf294fe7c
2988 .long 0x6000ff50,0x205f3d68,0x0000ff84,0x2d680004
2989 .long 0xff882d68,0x0008ff8c,0x0c2e0004,0xff4e662c
2990 .long 0x41eeff84,0x61ff0000,0x09424480,0x02407fff
2991 .long 0xefee004f,0xff846014,0x205f3d68,0x0000ff84
2992 .long 0x2d680004,0xff882d68,0x0008ff8c,0x08ae0007
2993 .long 0xff8456ee,0xff8641ee,0xff84122e,0xff5fe809
2994 .long 0x0241000c,0x4841122e,0xff5fe809,0x02410003
2995 .long 0x428061ff,0x00000782,0x4a2eff86,0x670608ee
2996 .long 0x0007ff84,0xf22ed040,0xff844e75,0x02000030
2997 .long 0x00000080,0x2d40ff5c,0x30280000,0x02407fff
2998 .long 0x0c4043fe,0x6e0000c8,0x67000120,0x0c403c01
2999 .long 0x6d000046,0xf228d080,0x0000f22e,0x9000ff5c
3000 .long 0xf23c8800,0x00000000,0xf22e7400,0xff54f23c
3001 .long 0x90000000,0x0000f200,0xa800816e,0xff66226e
3002 .long 0x000c41ee,0xff547008,0x61ffffff,0x46304a81
3003 .long 0x66ff0000,0x18004e75,0x08ee0003,0xff663d68
3004 .long 0x0000ff84,0x2d680004,0xff882d68,0x0008ff8c
3005 .long 0x2f084280,0x0c2e0004,0xff4e660a,0x41eeff84
3006 .long 0x61ff0000,0x084641ee,0xff84222e,0xff5c61ff
3007 .long 0x00000a5e,0x41eeff84,0x61ff0000,0x00d22d40
3008 .long 0xff542d41,0xff58226e,0x000c41ee,0xff547008
3009 .long 0x61ffffff,0x45c84a81,0x66ff0000,0x1798122e
3010 .long 0xff620201,0x000a6600,0xfe9c588f,0x4e753028
3011 .long 0x000a0240,0x07ff6608,0x006e1048,0xff666006
3012 .long 0x006e1248,0xff662f08,0x4a280000,0x5bc1202e
3013 .long 0xff5c61ff,0x00000af8,0xf210d080,0xf22e7400
3014 .long 0xff54226e,0x000c41ee,0xff547008,0x61ffffff
3015 .long 0x456c4a81,0x66ff0000,0x173c122e,0xff620201
3016 .long 0x000a6600,0xfe74588f,0x4e753228,0x00000241
3017 .long 0x80000041,0x3fff3d41,0xff842d68,0x0004ff88
3018 .long 0x2d680008,0xff8cf22e,0x9000ff5c,0xf22e4800
3019 .long 0xff84f23c,0x90000000,0x0000f200,0x0018f23c
3020 .long 0x58380002,0xf294feae,0x6000ff64,0x42803028
3021 .long 0x00000440,0x3fff0640,0x03ff4a28,0x00046b02
3022 .long 0x53404840,0xe9884a28,0x00006a04,0x08c0001f
3023 .long 0x22280004,0xe9c11054,0x80812d40,0xff542228
3024 .long 0x00047015,0xe1a92d41,0xff582228,0x0008e9c1
3025 .long 0x0015222e,0xff588280,0x202eff54,0x4e754280
3026 .long 0x30280000,0x04403fff,0x0640007f,0x4a280004
3027 .long 0x6b025340,0x4840ef88,0x4a280000,0x6a0408c0
3028 .long 0x001f2228,0x00040281,0x7fffff00,0xe0898081
3029 .long 0x4e7561ff,0xfffff490,0x2f08102e,0xff4e6600
3030 .long 0x0082082e,0x0004ff42,0x6712122e,0xff43e809
3031 .long 0x02410007,0x61ff0000,0x00926004,0x102eff43
3032 .long 0xebc00647,0x2f0041ee,0xff6c61ff,0x00000ed0
3033 .long 0x02aecfff,0xf00fff84,0x201f4a2e,0xff876616
3034 .long 0x4aaeff88,0x66104aae,0xff8c660a,0x4a806606
3035 .long 0x026ef000,0xff8441ee,0xff84225f,0x700c0c2e
3036 .long 0x0008ff4a,0x670e61ff,0xffff4412,0x4a816600
3037 .long 0xfb384e75,0x61ffffff,0x52864a81,0x6600fb2a
3038 .long 0x4e750c00,0x00046700,0xff7a41ee,0xff6c426e
3039 .long 0xff6e0c00,0x00056702,0x60c0006e,0x4080ff66
3040 .long 0x08ee0006,0xff7060b2,0x303b1206,0x4efb0002
3041 .long 0x00200026,0x002c0030,0x00340038,0x003c0040
3042 .long 0x0044004a,0x00500054,0x0058005c,0x00600064
3043 .long 0x202eff9c,0x4e75202e,0xffa04e75,0x20024e75
3044 .long 0x20034e75,0x20044e75,0x20054e75,0x20064e75
3045 .long 0x20074e75,0x202effa4,0x4e75202e,0xffa84e75
3046 .long 0x200a4e75,0x200b4e75,0x200c4e75,0x200d4e75
3047 .long 0x20164e75,0x202effd8,0x4e75323b,0x12064efb
3048 .long 0x10020010,0x0016001c,0x00200024,0x0028002c
3049 .long 0x00302d40,0xff9c4e75,0x2d40ffa0,0x4e752400
3050 .long 0x4e752600,0x4e752800,0x4e752a00,0x4e752c00
3051 .long 0x4e752e00,0x4e75323b,0x12064efb,0x10020010
3052 .long 0x0016001c,0x00200024,0x0028002c,0x00303d40
3053 .long 0xff9e4e75,0x3d40ffa2,0x4e753400,0x4e753600
3054 .long 0x4e753800,0x4e753a00,0x4e753c00,0x4e753e00
3055 .long 0x4e75323b,0x12064efb,0x10020010,0x0016001c
3056 .long 0x00200024,0x0028002c,0x00301d40,0xff9f4e75
3057 .long 0x1d40ffa3,0x4e751400,0x4e751600,0x4e751800
3058 .long 0x4e751a00,0x4e751c00,0x4e751e00,0x4e75323b
3059 .long 0x12064efb,0x10020010,0x0016001c,0x00200024
3060 .long 0x0028002c,0x0030d1ae,0xffa44e75,0xd1aeffa8
3061 .long 0x4e75d5c0,0x4e75d7c0,0x4e75d9c0,0x4e75dbc0
3062 .long 0x4e75d196,0x4e751d7c,0x0004ff4a,0x0c000001
3063 .long 0x6706d1ae,0xffd84e75,0x54aeffd8,0x4e75323b
3064 .long 0x12064efb,0x10020010,0x0016001c,0x00200024
3065 .long 0x0028002c,0x003091ae,0xffa44e75,0x91aeffa8
3066 .long 0x4e7595c0,0x4e7597c0,0x4e7599c0,0x4e759bc0
3067 .long 0x4e759196,0x4e751d7c,0x0008ff4a,0x0c000001
3068 .long 0x670691ae,0xffd84e75,0x55aeffd8,0x4e75303b
3069 .long 0x02064efb,0x00020010,0x00280040,0x004c0058
3070 .long 0x00640070,0x007c2d6e,0xffdcff6c,0x2d6effe0
3071 .long 0xff702d6e,0xffe4ff74,0x41eeff6c,0x4e752d6e
3072 .long 0xffe8ff6c,0x2d6effec,0xff702d6e,0xfff0ff74
3073 .long 0x41eeff6c,0x4e75f22e,0xf020ff6c,0x41eeff6c
3074 .long 0x4e75f22e,0xf010ff6c,0x41eeff6c,0x4e75f22e
3075 .long 0xf008ff6c,0x41eeff6c,0x4e75f22e,0xf004ff6c
3076 .long 0x41eeff6c,0x4e75f22e,0xf002ff6c,0x41eeff6c
3077 .long 0x4e75f22e,0xf001ff6c,0x41eeff6c,0x4e75303b
3078 .long 0x02064efb,0x00020010,0x00280040,0x004c0058
3079 .long 0x00640070,0x007c2d6e,0xffdcff78,0x2d6effe0
3080 .long 0xff7c2d6e,0xffe4ff80,0x41eeff78,0x4e752d6e
3081 .long 0xffe8ff78,0x2d6effec,0xff7c2d6e,0xfff0ff80
3082 .long 0x41eeff78,0x4e75f22e,0xf020ff78,0x41eeff78
3083 .long 0x4e75f22e,0xf010ff78,0x41eeff78,0x4e75f22e
3084 .long 0xf008ff78,0x41eeff78,0x4e75f22e,0xf004ff78
3085 .long 0x41eeff78,0x4e75f22e,0xf002ff78,0x41eeff78
3086 .long 0x4e75f22e,0xf001ff78,0x41eeff78,0x4e75303b
3087 .long 0x02064efb,0x00020010,0x00180020,0x002a0034
3088 .long 0x003e0048,0x0052f22e,0xf080ffdc,0x4e75f22e
3089 .long 0xf080ffe8,0x4e75f227,0xe001f21f,0xd0204e75
3090 .long 0xf227e001,0xf21fd010,0x4e75f227,0xe001f21f
3091 .long 0xd0084e75,0xf227e001,0xf21fd004,0x4e75f227
3092 .long 0xe001f21f,0xd0024e75,0xf227e001,0xf21fd001
3093 .long 0x4e750000,0x3f813c01,0xe408323b,0x02f63001
3094 .long 0x90680000,0x0c400042,0x6a164280,0x082e0001
3095 .long 0xff666704,0x08c0001d,0x61ff0000,0x001a4e75
3096 .long 0x203c2000,0x00003141,0x000042a8,0x000442a8
3097 .long 0x00084e75,0x2d680008,0xff542d40,0xff582001
3098 .long 0x92680000,0x6f100c41,0x00206d10,0x0c410040
3099 .long 0x6d506000,0x009a202e,0xff584e75,0x2f023140
3100 .long 0x00007020,0x90410c41,0x001d6d08,0x142eff58
3101 .long 0x852eff57,0xe9e82020,0x0004e9e8,0x18000004
3102 .long 0xe9ee0800,0xff542142,0x00042141,0x0008e8c0
3103 .long 0x009e6704,0x08c0001d,0x0280e000,0x0000241f
3104 .long 0x4e752f02,0x31400000,0x04410020,0x70209041
3105 .long 0x142eff58,0x852eff57,0xe9e82020,0x0004e9e8
3106 .long 0x18000004,0xe8c1009e,0x660ce8ee,0x081fff54
3107 .long 0x66042001,0x60062001,0x08c0001d,0x42a80004
3108 .long 0x21420008,0x0280e000,0x0000241f,0x4e753140
3109 .long 0x00000c41,0x00416d12,0x672442a8,0x000442a8
3110 .long 0x0008203c,0x20000000,0x4e752028,0x00042200
3111 .long 0x0280c000,0x00000281,0x3fffffff,0x60122028
3112 .long 0x00040280,0x80000000,0xe2880281,0x7fffffff
3113 .long 0x66164aa8,0x00086610,0x4a2eff58,0x660a42a8
3114 .long 0x000442a8,0x00084e75,0x08c0001d,0x42a80004
3115 .long 0x42a80008,0x4e7561ff,0x00000110,0x4a806700
3116 .long 0x00fa006e,0x0208ff66,0x327b1206,0x4efb9802
3117 .long 0x004000ea,0x00240008,0x4a280002,0x6b0000dc
3118 .long 0x70ff4841,0x0c010004,0x6700003e,0x6e000094
3119 .long 0x60000064,0x4a280002,0x6a0000c0,0x70ff4841
3120 .long 0x0c010004,0x67000022,0x6e000078,0x60000048
3121 .long 0xe3806400,0x00a64841,0x0c010004,0x6700000a
3122 .long 0x6e000060,0x60000030,0x06a80000,0x01000004
3123 .long 0x640ce4e8,0x0004e4e8,0x00065268,0x00004a80
3124 .long 0x66060268,0xfe000006,0x02a8ffff,0xff000004
3125 .long 0x42a80008,0x4e7552a8,0x0008641a,0x52a80004
3126 .long 0x6414e4e8,0x0004e4e8,0x0006e4e8,0x0008e4e8
3127 .long 0x000a5268,0x00004a80,0x66060228,0x00fe000b
3128 .long 0x4e7506a8,0x00000800,0x0008641a,0x52a80004
3129 .long 0x6414e4e8,0x0004e4e8,0x0006e4e8,0x0008e4e8
3130 .long 0x000a5268,0x00004a80,0x66060268,0xf000000a
3131 .long 0x02a8ffff,0xf8000008,0x4e754841,0x0c010004
3132 .long 0x6700ff86,0x6eea4e75,0x48414a01,0x66044841
3133 .long 0x4e7548e7,0x30000c01,0x00046622,0xe9e83602
3134 .long 0x0004741e,0xe5ab2428,0x00040282,0x0000003f
3135 .long 0x66284aa8,0x00086622,0x4a80661e,0x6020e9e8
3136 .long 0x35420008,0x741ee5ab,0x24280008,0x02820000
3137 .long 0x01ff6606,0x4a806602,0x600408c3,0x001d2003
3138 .long 0x4cdf000c,0x48414e75,0x2f022f03,0x20280004
3139 .long 0x22280008,0xedc02000,0x671ae5a8,0xe9c13022
3140 .long 0x8083e5a9,0x21400004,0x21410008,0x2002261f
3141 .long 0x241f4e75,0xedc12000,0xe5a90682,0x00000020
3142 .long 0x21410004,0x42a80008,0x2002261f,0x241f4e75
3143 .long 0xede80000,0x0004660e,0xede80000,0x00086700
3144 .long 0x00740640,0x00204281,0x32280000,0x02417fff
3145 .long 0xb0416e1c,0x92403028,0x00000240,0x80008240
3146 .long 0x31410000,0x61ffffff,0xff82103c,0x00004e75
3147 .long 0x0c010020,0x6e20e9e8,0x08400004,0x21400004
3148 .long 0x20280008,0xe3a82140,0x00080268,0x80000000
3149 .long 0x103c0004,0x4e750441,0x00202028,0x0008e3a8
3150 .long 0x21400004,0x42a80008,0x02688000,0x0000103c
3151 .long 0x00044e75,0x02688000,0x0000103c,0x00014e75
3152 .long 0x30280000,0x02407fff,0x0c407fff,0x67480828
3153 .long 0x00070004,0x6706103c,0x00004e75,0x4a406618
3154 .long 0x4aa80004,0x660c4aa8,0x00086606,0x103c0001
3155 .long 0x4e75103c,0x00044e75,0x4aa80004,0x66124aa8
3156 .long 0x0008660c,0x02688000,0x0000103c,0x00014e75
3157 .long 0x103c0006,0x4e754aa8,0x00086612,0x20280004
3158 .long 0x02807fff,0xffff6606,0x103c0002,0x4e750828
3159 .long 0x00060004,0x6706103c,0x00034e75,0x103c0005
3160 .long 0x4e752028,0x00002200,0x02807ff0,0x0000670e
3161 .long 0x0c807ff0,0x00006728,0x103c0000,0x4e750281
3162 .long 0x000fffff,0x66ff0000,0x00144aa8,0x000466ff
3163 .long 0x0000000a,0x103c0001,0x4e75103c,0x00044e75
3164 .long 0x0281000f,0xffff66ff,0x00000014,0x4aa80004
3165 .long 0x66ff0000,0x000a103c,0x00024e75,0x08010013
3166 .long 0x66ff0000,0x000a103c,0x00054e75,0x103c0003
3167 .long 0x4e752028,0x00002200,0x02807f80,0x0000670e
3168 .long 0x0c807f80,0x0000671e,0x103c0000,0x4e750281
3169 .long 0x007fffff,0x66ff0000,0x000a103c,0x00014e75
3170 .long 0x103c0004,0x4e750281,0x007fffff,0x66ff0000
3171 .long 0x000a103c,0x00024e75,0x08010016,0x66ff0000
3172 .long 0x000a103c,0x00054e75,0x103c0003,0x4e752f01
3173 .long 0x08280007,0x000056e8,0x00023228,0x00000241
3174 .long 0x7fff9240,0x31410000,0x2f08202f,0x00040240
3175 .long 0x00c0e848,0x61ffffff,0xfae22057,0x322f0006
3176 .long 0x024100c0,0xe8494841,0x322f0006,0x02410030
3177 .long 0xe84961ff,0xfffffc22,0x205f08a8,0x00070000
3178 .long 0x4a280002,0x670a08e8,0x00070000,0x42280002
3179 .long 0x42804aa8,0x0004660a,0x4aa80008,0x660408c0
3180 .long 0x0002082e,0x0001ff66,0x670608ee,0x0005ff67
3181 .long 0x588f4e75,0x2f010828,0x00070000,0x56e80002
3182 .long 0x32280000,0x02417fff,0x92403141,0x00002f08
3183 .long 0x428061ff,0xfffffa64,0x2057323c,0x00044841
3184 .long 0x322f0006,0x02410030,0xe84961ff,0xfffffbaa
3185 .long 0x205f08a8,0x00070000,0x4a280002,0x670a08e8
3186 .long 0x00070000,0x42280002,0x42804aa8,0x0004660a
3187 .long 0x4aa80008,0x660408c0,0x0002082e,0x0001ff66
3188 .long 0x670608ee,0x0005ff67,0x588f4e75,0x02410010
3189 .long 0xe8088200,0x3001e309,0x600e0241,0x00108200
3190 .long 0x48408200,0x3001e309,0x103b0008,0x41fb1620
3191 .long 0x4e750200,0x00020200,0x00020200,0x00020000
3192 .long 0x00000a08,0x0a080a08,0x0a080a08,0x0a087fff
3193 .long 0x00000000,0x00000000,0x00000000,0x00007ffe
3194 .long 0x0000ffff,0xffffffff,0xffff0000,0x00007ffe
3195 .long 0x0000ffff,0xffffffff,0xffff0000,0x00007fff
3196 .long 0x00000000,0x00000000,0x00000000,0x00007fff
3197 .long 0x00000000,0x00000000,0x00000000,0x0000407e
3198 .long 0x0000ffff,0xff000000,0x00000000,0x0000407e
3199 .long 0x0000ffff,0xff000000,0x00000000,0x00007fff
3200 .long 0x00000000,0x00000000,0x00000000,0x00007fff
3201 .long 0x00000000,0x00000000,0x00000000,0x000043fe
3202 .long 0x0000ffff,0xffffffff,0xf8000000,0x000043fe
3203 .long 0x0000ffff,0xffffffff,0xf8000000,0x00007fff
3204 .long 0x00000000,0x00000000,0x00000000,0x00000000
3205 .long 0x00000000,0x00000000,0x00000000,0x00000000
3206 .long 0x00000000,0x00000000,0x00000000,0x00000000
3207 .long 0x00000000,0x00000000,0x00000000,0x00000000
3208 .long 0x00000000,0x00000000,0x00000000,0x0000ffff
3209 .long 0x00000000,0x00000000,0x00000000,0x0000fffe
3210 .long 0x0000ffff,0xffffffff,0xffff0000,0x0000ffff
3211 .long 0x00000000,0x00000000,0x00000000,0x0000fffe
3212 .long 0x0000ffff,0xffffffff,0xffff0000,0x0000ffff
3213 .long 0x00000000,0x00000000,0x00000000,0x0000c07e
3214 .long 0x0000ffff,0xff000000,0x00000000,0x0000ffff
3215 .long 0x00000000,0x00000000,0x00000000,0x0000c07e
3216 .long 0x0000ffff,0xff000000,0x00000000,0x0000ffff
3217 .long 0x00000000,0x00000000,0x00000000,0x0000c3fe
3218 .long 0x0000ffff,0xffffffff,0xf8000000,0x0000ffff
3219 .long 0x00000000,0x00000000,0x00000000,0x0000c3fe
3220 .long 0x0000ffff,0xffffffff,0xf8000000,0x0000700c
3221 .long 0x61ffffff,0xe82c43ee,0xff6c700c,0x61ffffff
3222 .long 0x38664a81,0x66ff0000,0x0a14e9ee,0x004fff6c
3223 .long 0x0c407fff,0x66024e75,0x102eff6f,0x0200000f
3224 .long 0x660e4aae,0xff706608,0x4aaeff74,0x66024e75
3225 .long 0x41eeff6c,0x61ff0000,0x001cf22e,0xf080ff6c
3226 .long 0x4e750000,0x00000203,0x02030203,0x03020302
3227 .long 0x02032d68,0x0000ff84,0x2d680004,0xff882d68
3228 .long 0x0008ff8c,0x41eeff84,0x48e73c00,0xf227e001
3229 .long 0x74027604,0x28104281,0x4c3c1001,0x0000000a
3230 .long 0xe9c408c4,0xd2805803,0x51caffee,0x0804001e
3231 .long 0x67024481,0x04810000,0x00106c0e,0x44810084
3232 .long 0x40000000,0x00904000,0x00002f01,0x7201f23c
3233 .long 0x44000000,0x0000e9d0,0x0704f200,0x58222830
3234 .long 0x1c007600,0x7407f23c,0x44234120,0x0000e9c4
3235 .long 0x08c4f200,0x58225803,0x51caffec,0x52810c81
3236 .long 0x00000002,0x6fd80810,0x001f6704,0xf200001a
3237 .long 0x22170c81,0x0000001b,0x6f0000e4,0x0810001e
3238 .long 0x66744281,0x2810e9c4,0x07046624,0x52817a01
3239 .long 0x28305c00,0x66085081,0x52852830,0x5c004283
3240 .long 0x7407e9c4,0x08c46608,0x58835281,0x51cafff4
3241 .long 0x20012217,0x92806c10,0x44812810,0x00844000
3242 .long 0x00000090,0x40000000,0x43fb0170,0x00000666
3243 .long 0x4283f23c,0x44803f80,0x00007403,0xe2806406
3244 .long 0xf23148a3,0x38000683,0x0000000c,0x4a8066ec
3245 .long 0xf2000423,0x60684281,0x7a022830,0x5c006608
3246 .long 0x53855081,0x28305c00,0x761c7407,0xe9c408c4
3247 .long 0x66085983,0x528151ca,0xfff42001,0x22179280
3248 .long 0x6e104481,0x28100284,0xbfffffff,0x0290bfff
3249 .long 0xffff43fb,0x01700000,0x05fc4283,0xf23c4480
3250 .long 0x3f800000,0x7403e280,0x6406f231,0x48a33800
3251 .long 0x06830000,0x000c4a80,0x66ecf200,0x0420262e
3252 .long 0xff60e9c3,0x26822810,0xe582e9c4,0x0002d480
3253 .long 0x43fafe50,0x10312800,0x4283efc3,0x0682f203
3254 .long 0x9000e280,0x640a43fb,0x01700000,0x06446016
3255 .long 0xe280640a,0x43fb0170,0x000006d2,0x600843fb
3256 .long 0x01700000,0x05902001,0x6a084480,0x00904000
3257 .long 0x00004283,0xf23c4480,0x3f800000,0xe2806406
3258 .long 0xf23148a3,0x38000683,0x0000000c,0x4a8066ec
3259 .long 0x0810001e,0x6706f200,0x04206004,0xf2000423
3260 .long 0xf200a800,0x08800009,0x6706006e,0x0108ff66
3261 .long 0x588ff21f,0xd0404cdf,0x003cf23c,0x90000000
3262 .long 0x0000f23c,0x88000000,0x00004e75,0x3ffd0000
3263 .long 0x9a209a84,0xfbcff798,0x00000000,0x3ffd0000
3264 .long 0x9a209a84,0xfbcff799,0x00000000,0x3f800000
3265 .long 0x00000000,0x00000000,0x00000000,0x40000000
3266 .long 0x00000000,0x00000000,0x00000000,0x41200000
3267 .long 0x00000000,0x00000000,0x00000000,0x459a2800
3268 .long 0x00000000,0x00000000,0x00000000,0x00000000
3269 .long 0x03030202,0x03020203,0x02030302,0x48e73f20
3270 .long 0xf227e007,0xf23c9000,0x00000020,0x2d50ff58
3271 .long 0x2e00422e,0xff500c2e,0x0004ff4e,0x66000030
3272 .long 0x30100240,0x7fff2228,0x00042428,0x00085340
3273 .long 0xe38ae391,0x4a816cf6,0x4a406e04,0x50eeff50
3274 .long 0x02407fff,0x30802141,0x00042142,0x00082d50
3275 .long 0xff902d68,0x0004ff94,0x2d680008,0xff9802ae
3276 .long 0x7fffffff,0xff904a2e,0xff506708,0x2c3cffff
3277 .long 0xecbb6038,0x302eff90,0x3d7c3fff,0xff90f22e
3278 .long 0x4800ff90,0x04403fff,0xf2005022,0xf23a4428
3279 .long 0xff1cf293,0x000ef23a,0x4823ff02,0xf2066000
3280 .long 0x600af23a,0x4823fee6,0xf2066000,0xf23c8800
3281 .long 0x00000000,0x42454a87,0x6f042807,0x60062806
3282 .long 0x98875284,0x4a846f18,0x0c840000,0x00116f12
3283 .long 0x78114a87,0x6f0c00ae,0x00002080,0xff646002
3284 .long 0x78014a87,0x6e06be86,0x6d022c07,0x20065280
3285 .long 0x90844845,0x42454242,0x4a806c14,0x52450c80
3286 .long 0xffffecd4,0x6e080680,0x00000018,0x74184480
3287 .long 0xf23a4480,0xfe98e9ee,0x1682ff60,0xe349d245
3288 .long 0xe3494aae,0xff586c02,0x528145fa,0xfec01632
3289 .long 0x1800e98b,0xf2039000,0xe88b4a03,0x660a43fb
3290 .long 0x01700000,0x03706016,0xe20b640a,0x43fb0170
3291 .long 0x000003fe,0x600843fb,0x01700000,0x04904283
3292 .long 0xe2886406,0xf23148a3,0x38000683,0x0000000c
3293 .long 0x4a8066ec,0xf23c8800,0x00000000,0xf23c9000
3294 .long 0x00000010,0xf2104800,0xf2000018,0x4a456608
3295 .long 0xf2000420,0x6000008e,0x4a2eff50,0x67000072
3296 .long 0xf227e002,0x36170243,0x7fff0050,0x8000d650
3297 .long 0x04433fff,0xd6690024,0x04433fff,0xd6690030
3298 .long 0x04433fff,0x6b000048,0x02578000,0x87570250
3299 .long 0x7fff2f28,0x00082f28,0x00042f3c,0x3fff0000
3300 .long 0xf21fd080,0xf21f4823,0x2f29002c,0x2f290028
3301 .long 0x2f3c3fff,0x00002f29,0x00382f29,0x00342f3c
3302 .long 0x3fff0000,0xf21f4823,0xf21f4823,0x601660fe
3303 .long 0x4a42670c,0xf2294823,0x0024f229,0x48230030
3304 .long 0xf2000423,0xf200a800,0xf22e6800,0xff9045ee
3305 .long 0xff900800,0x0009670e,0x00aa0000,0x00010008
3306 .long 0xf22e4800,0xff902d6e,0xff60ff54,0x02ae0000
3307 .long 0x0030ff60,0x48e7c0c0,0x2f2eff54,0x2f2eff58
3308 .long 0x41eeff90,0xf2106800,0x4aaeff58,0x6c060090
3309 .long 0x80000000,0x2f2eff64,0xf22e9000,0xff60f23c
3310 .long 0x88000000,0x0000f22e,0x4801ff90,0xf200a800
3311 .long 0x816eff66,0x1d57ff64,0x588f2d5f,0xff582d5f
3312 .long 0xff544cdf,0x03032d6e,0xff58ff90,0x2d6eff54
3313 .long 0xff604845,0x4a4566ff,0x00000086,0xf23a4500
3314 .long 0xfcec2004,0x53804283,0xe2886406,0xf2314923
3315 .long 0x38000683,0x0000000c,0x4a8066ec,0x4a2eff50
3316 .long 0x670af200,0x001860ff,0x00000028,0xf2000018
3317 .long 0xf2000838,0xf293001a,0x53863a3c,0x0001f23c
3318 .long 0x90000000,0x0020f23a,0x4523fcc2,0x6000fda8
3319 .long 0xf23a4523,0xfcb8f200,0x0838f294,0x005cf292
3320 .long 0x000cf23a,0x4420fca6,0x5286604c,0x52863a3c
3321 .long 0x0001f23c,0x90000000,0x00206000,0xfd7af23a
3322 .long 0x4500fc6a,0x20044283,0xe2886406,0xf2314923
3323 .long 0x38000683,0x0000000c,0x4a8066ec,0xf2000018
3324 .long 0xf2000838,0xf28e0012,0xf23a4420,0xfc605286
3325 .long 0x5284f23a,0x4523fc56,0xf23c9000,0x00000010
3326 .long 0xf2000820,0x41eeff84,0xf2106800,0x24280004
3327 .long 0x26280008,0x42a80004,0x42a80008,0x20104840
3328 .long 0x67140480,0x00003ffd,0x4a806e0a,0x4480e28a
3329 .long 0xe29351c8,0xfffa4a82,0x66044a83,0x67104281
3330 .long 0x06830000,0x0080d581,0x0283ffff,0xff802004
3331 .long 0x568861ff,0x000002b0,0x4a2eff50,0x6728f200
3332 .long 0x003af281,0x000cf206,0x4000f200,0x0018602e
3333 .long 0x4a876d08,0xf23a4400,0xfbe46022,0xf2064000
3334 .long 0xf2000018,0x6018f200,0x003af28e,0x000af23a
3335 .long 0x4400fb9a,0x6008f206,0x4000f200,0x0018f229
3336 .long 0x48200018,0xf22e6800,0xff90242a,0x0004262a
3337 .long 0x00083012,0x670e0440,0x3ffd4440,0xe28ae293
3338 .long 0x51c8fffa,0x42810683,0x00000080,0xd5810283
3339 .long 0xffffff80,0x700441ee,0xff5461ff,0x00000228
3340 .long 0x202eff54,0x720ce2a8,0xefee010c,0xff84e2a8
3341 .long 0xefee0404,0xff844a00,0x670800ae,0x00002080
3342 .long 0xff644280,0x022e000f,0xff844aae,0xff586c02
3343 .long 0x70024a86,0x6c025280,0xefee0002,0xff84f23c
3344 .long 0x88000000,0x0000f21f,0xd0e04cdf,0x04fc4e75
3345 .long 0x40020000,0xa0000000,0x00000000,0x40050000
3346 .long 0xc8000000,0x00000000,0x400c0000,0x9c400000
3347 .long 0x00000000,0x40190000,0xbebc2000,0x00000000
3348 .long 0x40340000,0x8e1bc9bf,0x04000000,0x40690000
3349 .long 0x9dc5ada8,0x2b70b59e,0x40d30000,0xc2781f49
3350 .long 0xffcfa6d5,0x41a80000,0x93ba47c9,0x80e98ce0
3351 .long 0x43510000,0xaa7eebfb,0x9df9de8e,0x46a30000
3352 .long 0xe319a0ae,0xa60e91c7,0x4d480000,0xc9767586
3353 .long 0x81750c17,0x5a920000,0x9e8b3b5d,0xc53d5de5
3354 .long 0x75250000,0xc4605202,0x8a20979b,0x40020000
3355 .long 0xa0000000,0x00000000,0x40050000,0xc8000000
3356 .long 0x00000000,0x400c0000,0x9c400000,0x00000000
3357 .long 0x40190000,0xbebc2000,0x00000000,0x40340000
3358 .long 0x8e1bc9bf,0x04000000,0x40690000,0x9dc5ada8
3359 .long 0x2b70b59e,0x40d30000,0xc2781f49,0xffcfa6d6
3360 .long 0x41a80000,0x93ba47c9,0x80e98ce0,0x43510000
3361 .long 0xaa7eebfb,0x9df9de8e,0x46a30000,0xe319a0ae
3362 .long 0xa60e91c7,0x4d480000,0xc9767586,0x81750c18
3363 .long 0x5a920000,0x9e8b3b5d,0xc53d5de5,0x75250000
3364 .long 0xc4605202,0x8a20979b,0x40020000,0xa0000000
3365 .long 0x00000000,0x40050000,0xc8000000,0x00000000
3366 .long 0x400c0000,0x9c400000,0x00000000,0x40190000
3367 .long 0xbebc2000,0x00000000,0x40340000,0x8e1bc9bf
3368 .long 0x04000000,0x40690000,0x9dc5ada8,0x2b70b59d
3369 .long 0x40d30000,0xc2781f49,0xffcfa6d5,0x41a80000
3370 .long 0x93ba47c9,0x80e98cdf,0x43510000,0xaa7eebfb
3371 .long 0x9df9de8d,0x46a30000,0xe319a0ae,0xa60e91c6
3372 .long 0x4d480000,0xc9767586,0x81750c17,0x5a920000
3373 .long 0x9e8b3b5d,0xc53d5de4,0x75250000,0xc4605202
3374 .long 0x8a20979a,0x48e7ff00,0x7e015380,0x28022a03
3375 .long 0xe9c21003,0xe782e9c3,0x6003e783,0x8486e385
3376 .long 0xe3944846,0xd346d685,0x4e71d584,0x4e71d346
3377 .long 0x48464a47,0x67124847,0xe947de41,0x10c74847
3378 .long 0x424751c8,0xffc86012,0x48473e01,0x48475247
3379 .long 0x51c8ffba,0x4847e94f,0x10c74cdf,0x00ff4e75
3380 .long 0x70016100,0x00d63d7c,0x0121000a,0x6000007e
3381 .long 0x70026100,0x00c63d7c,0x0141000a,0x606e7004
3382 .long 0x610000b8,0x3d7c0101,0x000a6060,0x70086100
3383 .long 0x00aa3d7c,0x0161000a,0x6052700c,0x6100009c
3384 .long 0x3d7c0161,0x000a6044,0x70016100,0x008e3d7c
3385 .long 0x00a1000a,0x60367002,0x61000080,0x3d7c00c1
3386 .long 0x000a6028,0x70046100,0x00723d7c,0x0081000a
3387 .long 0x601a7008,0x61000064,0x3d7c00e1,0x000a600c
3388 .long 0x700c6100,0x00563d7c,0x00e1000a,0x2d6eff68
3389 .long 0x0006f22e,0xd0c0ffdc,0xf22e9c00,0xff604cee
3390 .long 0x0303ff9c,0x4e5e2f17,0x2f6f0008,0x00042f6f
3391 .long 0x000c0008,0x2f7c0000,0x0001000c,0x3f6f0006
3392 .long 0x000c3f7c,0x40080006,0x08170005,0x670608ef
3393 .long 0x0002000d,0x60ffffff,0x2d82122e,0xff410201
3394 .long 0x00380c01,0x00186700,0x000c0c01,0x00206700
3395 .long 0x00604e75,0x122eff41,0x02410007,0x323b1206
3396 .long 0x4efb1002,0x00100016,0x001c0020,0x00240028
3397 .long 0x002c0030,0x91aeffa4,0x4e7591ae,0xffa84e75
3398 .long 0x95c04e75,0x97c04e75,0x99c04e75,0x9bc04e75
3399 .long 0x91964e75,0x0c2e0030,0x000a6612,0x082e0005
3400 .long 0x0004660a,0x4e7a8800,0x91c04e7b,0x88004e75
3401 .long 0x448060a0,0x00000000,0x00000000,0x00000000
diff --git a/arch/m68k/ifpsp060/fskeleton.S b/arch/m68k/ifpsp060/fskeleton.S
new file mode 100644
index 000000000000..a45a4ff9d2af
--- /dev/null
+++ b/arch/m68k/ifpsp060/fskeleton.S
@@ -0,0 +1,342 @@
1|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2|MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3|M68000 Hi-Performance Microprocessor Division
4|M68060 Software Package
5|Production Release P1.00 -- October 10, 1994
6|
7|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8|
9|THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10|To the maximum extent permitted by applicable law,
11|MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12|INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13|and any warranty against infringement with regard to the SOFTWARE
14|(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15|
16|To the maximum extent permitted by applicable law,
17|IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18|(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19|BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20|ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21|Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22|
23|You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24|so long as this entire notice is retained without alteration in any modified and/or
25|redistributed versions, and that such modified versions are clearly identified as such.
26|No licenses are granted by implication, estoppel or otherwise under any patents
27|or trademarks of Motorola, Inc.
28|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29| fskeleton.s
30|
31| This file contains:
32| (1) example "Call-out"s
33| (2) example package entry code
34| (3) example "Call-out" table
35|
36
37#include <linux/linkage.h>
38
39|################################
40| (1) EXAMPLE CALL-OUTS #
41| #
42| _060_fpsp_done() #
43| _060_real_ovfl() #
44| _060_real_unfl() #
45| _060_real_operr() #
46| _060_real_snan() #
47| _060_real_dz() #
48| _060_real_inex() #
49| _060_real_bsun() #
50| _060_real_fline() #
51| _060_real_fpu_disabled() #
52| _060_real_trap() #
53|################################
54
55|
56| _060_fpsp_done():
57|
58| This is the main exit point for the 68060 Floating-Point
59| Software Package. For a normal exit, all 060FPSP routines call this
60| routine. The operating system can do system dependent clean-up or
61| simply execute an "rte" as with the sample code below.
62|
63 .global _060_fpsp_done
64_060_fpsp_done:
65 bral _060_isp_done | do the same as isp_done
66
67|
68| _060_real_ovfl():
69|
70| This is the exit point for the 060FPSP when an enabled overflow exception
71| is present. The routine below should point to the operating system handler
72| for enabled overflow conditions. The exception stack frame is an overflow
73| stack frame. The FP state frame holds the EXCEPTIONAL OPERAND.
74|
75| The sample routine below simply clears the exception status bit and
76| does an "rte".
77|
78 .global _060_real_ovfl
79_060_real_ovfl:
80 fsave -(%sp)
81 move.w #0x6000,0x2(%sp)
82 frestore (%sp)+
83 bral trap | jump to trap handler
84
85
86|
87| _060_real_unfl():
88|
89| This is the exit point for the 060FPSP when an enabled underflow exception
90| is present. The routine below should point to the operating system handler
91| for enabled underflow conditions. The exception stack frame is an underflow
92| stack frame. The FP state frame holds the EXCEPTIONAL OPERAND.
93|
94| The sample routine below simply clears the exception status bit and
95| does an "rte".
96|
97 .global _060_real_unfl
98_060_real_unfl:
99 fsave -(%sp)
100 move.w #0x6000,0x2(%sp)
101 frestore (%sp)+
102 bral trap | jump to trap handler
103
104|
105| _060_real_operr():
106|
107| This is the exit point for the 060FPSP when an enabled operand error exception
108| is present. The routine below should point to the operating system handler
109| for enabled operand error exceptions. The exception stack frame is an operand error
110| stack frame. The FP state frame holds the source operand of the faulting
111| instruction.
112|
113| The sample routine below simply clears the exception status bit and
114| does an "rte".
115|
116 .global _060_real_operr
117_060_real_operr:
118 fsave -(%sp)
119 move.w #0x6000,0x2(%sp)
120 frestore (%sp)+
121 bral trap | jump to trap handler
122
123|
124| _060_real_snan():
125|
126| This is the exit point for the 060FPSP when an enabled signalling NaN exception
127| is present. The routine below should point to the operating system handler
128| for enabled signalling NaN exceptions. The exception stack frame is a signalling NaN
129| stack frame. The FP state frame holds the source operand of the faulting
130| instruction.
131|
132| The sample routine below simply clears the exception status bit and
133| does an "rte".
134|
135 .global _060_real_snan
136_060_real_snan:
137 fsave -(%sp)
138 move.w #0x6000,0x2(%sp)
139 frestore (%sp)+
140 bral trap | jump to trap handler
141
142|
143| _060_real_dz():
144|
145| This is the exit point for the 060FPSP when an enabled divide-by-zero exception
146| is present. The routine below should point to the operating system handler
147| for enabled divide-by-zero exceptions. The exception stack frame is a divide-by-zero
148| stack frame. The FP state frame holds the source operand of the faulting
149| instruction.
150|
151| The sample routine below simply clears the exception status bit and
152| does an "rte".
153|
154 .global _060_real_dz
155_060_real_dz:
156 fsave -(%sp)
157 move.w #0x6000,0x2(%sp)
158 frestore (%sp)+
159 bral trap | jump to trap handler
160
161|
162| _060_real_inex():
163|
164| This is the exit point for the 060FPSP when an enabled inexact exception
165| is present. The routine below should point to the operating system handler
166| for enabled inexact exceptions. The exception stack frame is an inexact
167| stack frame. The FP state frame holds the source operand of the faulting
168| instruction.
169|
170| The sample routine below simply clears the exception status bit and
171| does an "rte".
172|
173 .global _060_real_inex
174_060_real_inex:
175 fsave -(%sp)
176 move.w #0x6000,0x2(%sp)
177 frestore (%sp)+
178 bral trap | jump to trap handler
179
180|
181| _060_real_bsun():
182|
183| This is the exit point for the 060FPSP when an enabled bsun exception
184| is present. The routine below should point to the operating system handler
185| for enabled bsun exceptions. The exception stack frame is a bsun
186| stack frame.
187|
188| The sample routine below clears the exception status bit, clears the NaN
189| bit in the FPSR, and does an "rte". The instruction that caused the
190| bsun will now be re-executed but with the NaN FPSR bit cleared.
191|
192 .global _060_real_bsun
193_060_real_bsun:
194| fsave -(%sp)
195
196 fmove.l %fpsr,-(%sp)
197 andi.b #0xfe,(%sp)
198 fmove.l (%sp)+,%fpsr
199
200 bral trap | jump to trap handler
201
202|
203| _060_real_fline():
204|
205| This is the exit point for the 060FPSP when an F-Line Illegal exception is
206| encountered. Three different types of exceptions can enter the F-Line exception
207| vector number 11: FP Unimplemented Instructions, FP implemented instructions when
208| the FPU is disabled, and F-Line Illegal instructions. The 060FPSP module
209| _fpsp_fline() distinguishes between the three and acts appropriately. F-Line
210| Illegals branch here.
211|
212 .global _060_real_fline
213_060_real_fline:
214 bral trap | jump to trap handler
215
216|
217| _060_real_fpu_disabled():
218|
219| This is the exit point for the 060FPSP when an FPU disabled exception is
220| encountered. Three different types of exceptions can enter the F-Line exception
221| vector number 11: FP Unimplemented Instructions, FP implemented instructions when
222| the FPU is disabled, and F-Line Illegal instructions. The 060FPSP module
223| _fpsp_fline() distinguishes between the three and acts appropriately. FPU disabled
224| exceptions branch here.
225|
226| The sample code below enables the FPU, sets the PC field in the exception stack
227| frame to the PC of the instruction causing the exception, and does an "rte".
228| The execution of the instruction then proceeds with an enabled floating-point
229| unit.
230|
231 .global _060_real_fpu_disabled
232_060_real_fpu_disabled:
233 move.l %d0,-(%sp) | enabled the fpu
234 .long 0x4E7A0808 |movec pcr,%d0
235 bclr #0x1,%d0
236 .long 0x4E7B0808 |movec %d0,pcr
237 move.l (%sp)+,%d0
238
239 move.l 0xc(%sp),0x2(%sp) | set "Current PC"
240 rte
241
242|
243| _060_real_trap():
244|
245| This is the exit point for the 060FPSP when an emulated "ftrapcc" instruction
246| discovers that the trap condition is true and it should branch to the operating
247| system handler for the trap exception vector number 7.
248|
249| The sample code below simply executes an "rte".
250|
251 .global _060_real_trap
252_060_real_trap:
253 bral trap | jump to trap handler
254
255|############################################################################
256
257|#################################
258| (2) EXAMPLE PACKAGE ENTRY CODE #
259|#################################
260
261 .global _060_fpsp_snan
262_060_fpsp_snan:
263 bra.l _FP_CALL_TOP+0x80+0x00
264
265 .global _060_fpsp_operr
266_060_fpsp_operr:
267 bra.l _FP_CALL_TOP+0x80+0x08
268
269 .global _060_fpsp_ovfl
270_060_fpsp_ovfl:
271 bra.l _FP_CALL_TOP+0x80+0x10
272
273 .global _060_fpsp_unfl
274_060_fpsp_unfl:
275 bra.l _FP_CALL_TOP+0x80+0x18
276
277 .global _060_fpsp_dz
278_060_fpsp_dz:
279 bra.l _FP_CALL_TOP+0x80+0x20
280
281 .global _060_fpsp_inex
282_060_fpsp_inex:
283 bra.l _FP_CALL_TOP+0x80+0x28
284
285 .global _060_fpsp_fline
286_060_fpsp_fline:
287 bra.l _FP_CALL_TOP+0x80+0x30
288
289 .global _060_fpsp_unsupp
290_060_fpsp_unsupp:
291 bra.l _FP_CALL_TOP+0x80+0x38
292
293 .global _060_fpsp_effadd
294_060_fpsp_effadd:
295 bra.l _FP_CALL_TOP+0x80+0x40
296
297|############################################################################
298
299|###############################
300| (3) EXAMPLE CALL-OUT SECTION #
301|###############################
302
303| The size of this section MUST be 128 bytes!!!
304
305_FP_CALL_TOP:
306 .long _060_real_bsun - _FP_CALL_TOP
307 .long _060_real_snan - _FP_CALL_TOP
308 .long _060_real_operr - _FP_CALL_TOP
309 .long _060_real_ovfl - _FP_CALL_TOP
310 .long _060_real_unfl - _FP_CALL_TOP
311 .long _060_real_dz - _FP_CALL_TOP
312 .long _060_real_inex - _FP_CALL_TOP
313 .long _060_real_fline - _FP_CALL_TOP
314 .long _060_real_fpu_disabled - _FP_CALL_TOP
315 .long _060_real_trap - _FP_CALL_TOP
316 .long _060_real_trace - _FP_CALL_TOP
317 .long _060_real_access - _FP_CALL_TOP
318 .long _060_fpsp_done - _FP_CALL_TOP
319
320 .long 0x00000000, 0x00000000, 0x00000000
321
322 .long _060_imem_read - _FP_CALL_TOP
323 .long _060_dmem_read - _FP_CALL_TOP
324 .long _060_dmem_write - _FP_CALL_TOP
325 .long _060_imem_read_word - _FP_CALL_TOP
326 .long _060_imem_read_long - _FP_CALL_TOP
327 .long _060_dmem_read_byte - _FP_CALL_TOP
328 .long _060_dmem_read_word - _FP_CALL_TOP
329 .long _060_dmem_read_long - _FP_CALL_TOP
330 .long _060_dmem_write_byte - _FP_CALL_TOP
331 .long _060_dmem_write_word - _FP_CALL_TOP
332 .long _060_dmem_write_long - _FP_CALL_TOP
333
334 .long 0x00000000
335
336 .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
337
338|############################################################################
339
340| 060 FPSP KERNEL PACKAGE NEEDS TO GO HERE!!!
341
342#include "fpsp.sa"
diff --git a/arch/m68k/ifpsp060/ftest.sa b/arch/m68k/ifpsp060/ftest.sa
new file mode 100644
index 000000000000..b365bc2fdec9
--- /dev/null
+++ b/arch/m68k/ifpsp060/ftest.sa
@@ -0,0 +1,371 @@
1 dc.l $60ff0000,$00d40000,$60ff0000,$016c0000
2 dc.l $60ff0000,$01a80000,$54657374,$696e6720
3 dc.l $36383036,$30204650,$53502073,$74617274
4 dc.l $65643a0a,$00546573,$74696e67,$20363830
5 dc.l $36302046,$50535020,$756e696d,$706c656d
6 dc.l $656e7465,$6420696e,$73747275,$6374696f
7 dc.l $6e207374,$61727465,$643a0a00,$54657374
8 dc.l $696e6720,$36383036,$30204650,$53502065
9 dc.l $78636570,$74696f6e,$20656e61,$626c6564
10 dc.l $20737461,$72746564,$3a0a0070,$61737365
11 dc.l $640a0020,$6661696c,$65640a00,$4a80660e
12 dc.l $487affe9,$61ff0000,$1642588f,$4e752f01
13 dc.l $61ff0000,$164c588f,$487affd9,$61ff0000
14 dc.l $162a588f,$4e754e56,$fe8048e7,$3f3cf227
15 dc.l $e0ff487a,$ff3461ff,$00001610,$588f42ae
16 dc.l $fea0487b,$01700000,$058061ff,$000015fc
17 dc.l $588f61ff,$00000588,$61ffffff,$ffa242ae
18 dc.l $fea0487b,$01700000,$126c61ff,$000015dc
19 dc.l $588f61ff,$00001280,$61ffffff,$ff8242ae
20 dc.l $fea0487b,$01700000,$0b6461ff,$000015bc
21 dc.l $61ff0000,$0b7261ff,$ffffff64,$42aefea0
22 dc.l $487b0170,$00000de2,$61ff0000,$159e61ff
23 dc.l $00000df0,$61ffffff,$ff464cdf,$3cfcf21f
24 dc.l $d0ff4e5e,$4e754e56,$fe8048e7,$3f3cf227
25 dc.l $e0ff487a,$feb161ff,$00001570,$588f42ae
26 dc.l $fea0487b,$01700000,$00fe61ff,$0000155c
27 dc.l $588f61ff,$00000110,$61ffffff,$ff024cdf
28 dc.l $3cfcf21f,$d0ff4e5e,$4e754e56,$fe8048e7
29 dc.l $3f3cf227,$e0ff487a,$fea461ff,$0000152c
30 dc.l $588f42ae,$fea0487b,$01700000,$0f1461ff
31 dc.l $00001518,$61ff0000,$0f1a61ff,$fffffec0
32 dc.l $42aefea0,$487b0170,$00000fd2,$61ff0000
33 dc.l $14fa61ff,$00000fd8,$61ffffff,$fea242ae
34 dc.l $fea0487b,$01700000,$0b6061ff,$000014dc
35 dc.l $61ff0000,$0b6a61ff,$fffffe84,$42aefea0
36 dc.l $487b0170,$00000c22,$61ff0000,$14be61ff
37 dc.l $00000c2c,$61ffffff,$fe6642ae,$fea0487b
38 dc.l $01700000,$105661ff,$000014a0,$61ff0000
39 dc.l $105a61ff,$fffffe48,$42aefea0,$487b0170
40 dc.l $00000da2,$61ff0000,$148261ff,$00000da8
41 dc.l $61ffffff,$fe2a4cdf,$3cfcf21f,$d0ff4e5e
42 dc.l $4e750955,$6e696d70,$6c656d65,$6e746564
43 dc.l $20465020,$696e7374,$72756374,$696f6e73
44 dc.l $2e2e2e00,$52aefea0,$4cfb3fff,$01700000
45 dc.l $1390f23b,$d0ff0170,$000013c6,$f23b9c00
46 dc.l $01700000,$141c3d7c,$0000fea6,$48ee7fff
47 dc.l $ff80f22e,$f0ffff20,$f22ebc00,$feb42d7c
48 dc.l $40000000,$fe802d7c,$c90fdaa2,$fe842d7c
49 dc.l $2168c235,$fe8844fc,$0000f22e,$480efe80
50 dc.l $42eefea4,$48ee7fff,$ffc0f22e,$f0fffec0
51 dc.l $f22ebc00,$fea82d7c,$bfbf0000,$ff202d7c
52 dc.l $80000000,$ff242d7c,$00000000,$ff282d7c
53 dc.l $08000208,$feb841fa,$ffc22d48,$febc61ff
54 dc.l $00001288,$4a0066ff,$000012ae,$61ff0000
55 dc.l $12b04a00,$66ff0000,$12a052ae,$fea04cfb
56 dc.l $3fff0170,$000012da,$f23bd0ff,$01700000
57 dc.l $1310f23b,$9c000170,$00001366,$3d7c0000
58 dc.l $fea648ee,$7fffff80,$f22ef0ff,$ff20f22e
59 dc.l $bc00feb4,$2d7c3ffe,$0000fe80,$2d7cc90f
60 dc.l $daa2fe84,$2d7c2168,$c235fe88,$44fc0000
61 dc.l $f22e480f,$fe8042ee,$fea448ee,$7fffffc0
62 dc.l $f22ef0ff,$fec0f22e,$bc00fea8,$2d7c3fff
63 dc.l $0000ff20,$2d7c8000,$0000ff24,$2d7c0000
64 dc.l $0000ff28,$2d7c0000,$0208feb8,$41faffc2
65 dc.l $2d48febc,$61ff0000,$11d24a00,$66ff0000
66 dc.l $11f861ff,$000011fa,$4a0066ff,$000011ea
67 dc.l $52aefea0,$4cfb3fff,$01700000,$1224f23b
68 dc.l $d0ff0170,$0000125a,$f23b9c00,$01700000
69 dc.l $12b03d7c,$0000fea6,$48ee7fff,$ff80f22e
70 dc.l $f0ffff20,$f22ebc00,$feb444fc,$0000f200
71 dc.l $5c3142ee,$fea448ee,$7fffffc0,$f22ef0ff
72 dc.l $fec0f22e,$bc00fea8,$2d7c4000,$0000ff20
73 dc.l $2d7c935d,$8dddff24,$2d7caaa8,$ac17ff28
74 dc.l $2d7c0000,$0208feb8,$41faffc4,$2d48febc
75 dc.l $61ff0000,$11364a00,$66ff0000,$115c61ff
76 dc.l $0000115e,$4a0066ff,$0000114e,$52aefea0
77 dc.l $4cfb3fff,$01700000,$1188f23b,$d0ff0170
78 dc.l $000011be,$f23b9c00,$01700000,$1214f23c
79 dc.l $88000f00,$00007e00,$3d7c0000,$fea648ee
80 dc.l $7fffff80,$f22ef0ff,$ff20f22e,$bc00feb4
81 dc.l $44fc0000,$f2470012,$42eefea4,$48ee7fff
82 dc.l $ffc0f22e,$f0fffec0,$f22ebc00,$fea82d7c
83 dc.l $0f008080,$feb841fa,$ffdc2d48,$febc61ff
84 dc.l $000010a8,$4a0066ff,$000010ce,$61ff0000
85 dc.l $10d04a00,$66ff0000,$10c052ae,$fea04cfb
86 dc.l $3fff0170,$000010fa,$f23bd0ff,$01700000
87 dc.l $1130f23b,$9c000170,$00001186,$f23c8800
88 dc.l $0f000000,$7e023d7c,$0000fea6,$48ee7fff
89 dc.l $ff80f22e,$f0ffff20,$f22ebc00,$feb444fc
90 dc.l $0000f24f,$0012fffc,$42eefea4,$48ee7fff
91 dc.l $ffc0f22e,$f0fffec0,$f22ebc00,$fea83d7c
92 dc.l $ffffff9e,$2d7c0f00,$8080feb8,$41faffd4
93 dc.l $2d48febc,$61ff0000,$10124a00,$66ff0000
94 dc.l $103861ff,$0000103a,$4a0066ff,$0000102a
95 dc.l $52aefea0,$4cfb3fff,$01700000,$1064f23b
96 dc.l $d0ff0170,$0000109a,$f23b9c00,$01700000
97 dc.l $10f0f23c,$88000f00,$00003d7c,$0000fea6
98 dc.l $48ee7fff,$ff80f22e,$f0ffff20,$f22ebc00
99 dc.l $feb444fc,$0000f27b,$0012abcd,$ef0142ee
100 dc.l $fea448ee,$7fffffc0,$f22ef0ff,$fec0f22e
101 dc.l $bc00fea8,$2d7c0f00,$8080feb8,$41faffd8
102 dc.l $2d48febc,$61ff0000,$0f824a00,$66ff0000
103 dc.l $0fa861ff,$00000faa,$4a0066ff,$00000f9a
104 dc.l $42804e75,$09556e69,$6d706c65,$6d656e74
105 dc.l $6564203c,$65613e2e,$2e2e0000,$52aefea0
106 dc.l $4cfb3fff,$01700000,$0fb8f23b,$d0ff0170
107 dc.l $00000fee,$f23b9c00,$01700000,$10443d7c
108 dc.l $0000fea6,$48ee7fff,$ff80f22e,$f0ffff20
109 dc.l $f22ebc00,$feb4f23c,$58000002,$44fc0000
110 dc.l $f23c4823,$c0000000,$80000000,$00000000
111 dc.l $42eefea4,$48ee7fff,$ffc0f22e,$f0fffec0
112 dc.l $f22ebc00,$fea82d7c,$c0010000,$ff202d7c
113 dc.l $80000000,$ff242d7c,$00000000,$ff282d7c
114 dc.l $08000000,$feb841fa,$ffb82d48,$febc61ff
115 dc.l $00000eb8,$4a0066ff,$00000ede,$61ff0000
116 dc.l $0ee04a00,$66ff0000,$0ed052ae,$fea04cfb
117 dc.l $3fff0170,$00000f0a,$f23bd0ff,$01700000
118 dc.l $0f40f23b,$9c000170,$00000f96,$3d7c0000
119 dc.l $fea648ee,$7fffff80,$f22ef0ff,$ff20f22e
120 dc.l $bc00feb4,$44fc0000,$f23c4c18,$c1230001
121 dc.l $23456789,$12345678,$42eefea4,$48ee7fff
122 dc.l $ffc0f22e,$f0fffec0,$f22ebc00,$fea82d7c
123 dc.l $3e660000,$ff202d7c,$d0ed23e8,$ff242d7c
124 dc.l $d14035bc,$ff282d7c,$00000108,$feb841fa
125 dc.l $ffb82d48,$febc61ff,$00000e10,$4a0066ff
126 dc.l $00000e36,$61ff0000,$0e384a00,$66ff0000
127 dc.l $0e2852ae,$fea04cfb,$3fff0170,$00000e62
128 dc.l $f23bd0ff,$01700000,$0e98f23b,$9c000170
129 dc.l $00000eee,$3d7c0000,$fea644fc,$000048ee
130 dc.l $7fffff80,$f22ef0ff,$ff20f22e,$bc00feb4
131 dc.l $f23c9800,$ffffffff,$ffffffff,$42eefea4
132 dc.l $48ee7fff,$ffc0f22e,$f0fffec0,$f22ebc00
133 dc.l $fea82d7c,$0000fff0,$feb42d7c,$0ffffff8
134 dc.l $feb861ff,$00000d84,$4a0066ff,$00000daa
135 dc.l $61ff0000,$0dac4a00,$66ff0000,$0d9c52ae
136 dc.l $fea04cfb,$3fff0170,$00000dd6,$f23bd0ff
137 dc.l $01700000,$0e0cf23b,$9c000170,$00000e62
138 dc.l $3d7c0000,$fea644fc,$000048ee,$7fffff80
139 dc.l $f22ef0ff,$ff20f22e,$bc00feb4,$f23c9400
140 dc.l $ffffffff,$ffffffff,$42eefea4,$48ee7fff
141 dc.l $ffc0f22e,$f0fffec0,$f22ebc00,$fea82d7c
142 dc.l $0000fff0,$feb42d7c,$ffffffff,$febc61ff
143 dc.l $00000cf8,$4a0066ff,$00000d1e,$61ff0000
144 dc.l $0d204a00,$66ff0000,$0d1052ae,$fea04cfb
145 dc.l $3fff0170,$00000d4a,$f23bd0ff,$01700000
146 dc.l $0d80f23b,$9c000170,$00000dd6,$3d7c0000
147 dc.l $fea644fc,$000048ee,$7fffff80,$f22ef0ff
148 dc.l $ff20f22e,$bc00feb4,$f23c8c00,$ffffffff
149 dc.l $ffffffff,$42eefea4,$48ee7fff,$ffc0f22e
150 dc.l $f0fffec0,$f22ebc00,$fea82d7c,$0ffffff8
151 dc.l $feb82d7c,$ffffffff,$febc61ff,$00000c6c
152 dc.l $4a0066ff,$00000c92,$61ff0000,$0c944a00
153 dc.l $66ff0000,$0c8452ae,$fea04cfb,$3fff0170
154 dc.l $00000cbe,$f23bd0ff,$01700000,$0cf4f23b
155 dc.l $9c000170,$00000d4a,$3d7c0000,$fea644fc
156 dc.l $000048ee,$7fffff80,$f22ef0ff,$ff20f22e
157 dc.l $bc00feb4,$f23c9c00,$ffffffff,$ffffffff
158 dc.l $ffffffff,$42eefea4,$48ee7fff,$ffc0f22e
159 dc.l $f0fffec0,$f22ebc00,$fea82d7c,$0000fff0
160 dc.l $feb42d7c,$0ffffff8,$feb82d7c,$ffffffff
161 dc.l $febc61ff,$00000bd4,$4a0066ff,$00000bfa
162 dc.l $61ff0000,$0bfc4a00,$66ff0000,$0bec52ae
163 dc.l $fea04cfb,$3fff0170,$00000c26,$f23bd0ff
164 dc.l $01700000,$0c5cf23b,$9c000170,$00000cb2
165 dc.l $f23c5800,$0001f23c,$58800002,$f23c5900
166 dc.l $0003f23c,$59800004,$f23c5a00,$0005f23c
167 dc.l $5a800006,$f23c5b00,$0007f23c,$5b800008
168 dc.l $f23c8400,$00000000,$70aa3d7c,$0000fea6
169 dc.l $48eeffff,$ff80f22e,$bc00feb4,$f22ef0ff
170 dc.l $ff2044fc,$0000f227,$e80042ee,$fea4f22e
171 dc.l $bc00fea8,$f23c4480,$7f800000,$f23c4580
172 dc.l $7f800000,$f23c4680,$7f800000,$f23c4780
173 dc.l $7f800000,$f21f4880,$f21f4980,$f21f4a80
174 dc.l $f21f4b80,$48eeffff,$ffc0f22e,$f0fffec0
175 dc.l $61ff0000,$0af64a00,$66ff0000,$0b1c61ff
176 dc.l $00000b1e,$4a0066ff,$00000b0e,$52aefea0
177 dc.l $4cfb3fff,$01700000,$0b48f23b,$d0ff0170
178 dc.l $00000b7e,$f23b9c00,$01700000,$0bd4f23c
179 dc.l $58000001,$f23c5880,$0002f23c,$59000003
180 dc.l $f23c5980,$0004f23c,$5a000005,$f23c5a80
181 dc.l $0006f23c,$5b000007,$f23c5b80,$0008f227
182 dc.l $6b00f227,$6a00f227,$6900f227,$6800f22e
183 dc.l $f0ffff20,$f23c4700,$7f800000,$f23c4600
184 dc.l $7f800000,$f23c4500,$7f800000,$f23c4400
185 dc.l $7f800000,$f23c8400,$00000000,$f23c8800
186 dc.l $00000000,$70aa3d7c,$0000fea6,$48eeffff
187 dc.l $ff80f22e,$bc00feb4,$44fc0000,$f21fd800
188 dc.l $42eefea4,$f22ebc00,$fea848ee,$ffffffc0
189 dc.l $f22ef0ff,$fec061ff,$00000a10,$4a0066ff
190 dc.l $00000a36,$61ff0000,$0a384a00,$66ff0000
191 dc.l $0a2852ae,$fea04cfb,$3fff0170,$00000a62
192 dc.l $f23bd0ff,$01700000,$0a98f23b,$9c000170
193 dc.l $00000aee,$f23c5800,$0001f23c,$58800002
194 dc.l $f23c5900,$0003f23c,$59800004,$f23c5a00
195 dc.l $0005f23c,$5a800006,$f23c5b00,$0007f23c
196 dc.l $5b800008,$f23c8400,$00000000,$203cffff
197 dc.l $ff003d7c,$0000fea6,$48eeffff,$ff80f22e
198 dc.l $bc00feb4,$f22ef0ff,$ff2044fc,$0000f227
199 dc.l $e80042ee,$fea4f22e,$bc00fea8,$48eeffff
200 dc.l $ffc0f22e,$f0fffec0,$61ff0000,$095e4a00
201 dc.l $66ff0000,$098461ff,$00000986,$4a0066ff
202 dc.l $00000976,$42804e75,$094e6f6e,$2d6d6173
203 dc.l $6b61626c,$65206f76,$6572666c,$6f772e2e
204 dc.l $2e0051fc,$52aefea0,$4cfb3fff,$01700000
205 dc.l $0990f23b,$d0ff0170,$000009c6,$f23b9c00
206 dc.l $01700000,$0a1c3d7c,$0000fea6,$48ee7fff
207 dc.l $ff80f22e,$f0ffff20,$f22ebc00,$feb4f23c
208 dc.l $58000002,$2d7c7ffe,$0000fe80,$2d7c8000
209 dc.l $0000fe84,$2d7c0000,$0000fe88,$44fc0000
210 dc.l $f22e4823,$fe8042ee,$fea448ee,$7fffffc0
211 dc.l $f22ef0ff,$fec0f22e,$bc00fea8,$2d7c7fff
212 dc.l $0000ff20,$2d7c0000,$0000ff24,$2d7c0000
213 dc.l $0000ff28,$2d7c0200,$1048feb8,$41faffc2
214 dc.l $2d48febc,$61ff0000,$08824a00,$66ff0000
215 dc.l $08a861ff,$000008aa,$4a0066ff,$0000089a
216 dc.l $42804e75,$09456e61,$626c6564,$206f7665
217 dc.l $72666c6f,$772e2e2e,$000051fc,$52aefea0
218 dc.l $4cfb3fff,$01700000,$08b8f23b,$d0ff0170
219 dc.l $000008ee,$f23b9c00,$01700000,$09443d7c
220 dc.l $0000fea6,$48ee7fff,$ff80f22e,$f0ffff20
221 dc.l $f23c9000,$00001000,$f22ebc00,$feb4f23c
222 dc.l $58000002,$2d7c7ffe,$0000fe80,$2d7c8000
223 dc.l $0000fe84,$2d7c0000,$0000fe88,$44fc0000
224 dc.l $f22e4823,$fe8042ee,$fea448ee,$7fffffc0
225 dc.l $f22ef0ff,$fec0f22e,$bc00fea8,$2d7c7fff
226 dc.l $0000ff20,$2d7c0000,$0000ff24,$2d7c0000
227 dc.l $0000ff28,$2d7c0200,$1048feb8,$41faffc2
228 dc.l $2d48febc,$61ff0000,$07a24a00,$66ff0000
229 dc.l $07c861ff,$000007ca,$4a0066ff,$000007ba
230 dc.l $42804e75,$09456e61,$626c6564,$20756e64
231 dc.l $6572666c,$6f772e2e,$2e0051fc,$52aefea0
232 dc.l $4cfb3fff,$01700000,$07d8f23b,$d0ff0170
233 dc.l $0000080e,$f23b9c00,$01700000,$08643d7c
234 dc.l $0000fea6,$48ee7fff,$ff80f22e,$f0ffff20
235 dc.l $f23c9000,$00000800,$f22ebc00,$feb42d7c
236 dc.l $00000000,$fe802d7c,$80000000,$fe842d7c
237 dc.l $00000000,$fe88f22e,$d080fe80,$44fc0000
238 dc.l $f23c5820,$000242ee,$fea448ee,$7fffffc0
239 dc.l $f22ef0ff,$fec0f22e,$bc00fea8,$2d7c0000
240 dc.l $0000ff20,$2d7c4000,$0000ff24,$2d7c0000
241 dc.l $0000ff28,$2d7c0000,$0800feb8,$41faffc2
242 dc.l $2d48febc,$61ff0000,$06c24a00,$66ff0000
243 dc.l $06e861ff,$000006ea,$4a0066ff,$000006da
244 dc.l $42804e75,$094e6f6e,$2d6d6173,$6b61626c
245 dc.l $6520756e,$64657266,$6c6f772e,$2e2e0000
246 dc.l $52aefea0,$4cfb3fff,$01700000,$06f4f23b
247 dc.l $d0ff0170,$0000072a,$f23b9c00,$01700000
248 dc.l $07803d7c,$0000fea6,$48ee7fff,$ff80f22e
249 dc.l $f0ffff20,$f22ebc00,$feb42d7c,$00000000
250 dc.l $fe802d7c,$80000000,$fe842d7c,$00000000
251 dc.l $fe88f22e,$d080fe80,$44fc0000,$f23c5820
252 dc.l $000242ee,$fea448ee,$7fffffc0,$f22ef0ff
253 dc.l $fec0f22e,$bc00fea8,$2d7c0000,$0000ff20
254 dc.l $2d7c4000,$0000ff24,$2d7c0000,$0000ff28
255 dc.l $2d7c0000,$0800feb8,$41faffc2,$2d48febc
256 dc.l $61ff0000,$05e64a00,$66ff0000,$060c61ff
257 dc.l $0000060e,$4a0066ff,$000005fe,$42804e75
258 dc.l $09456e61,$626c6564,$20696e65,$78616374
259 dc.l $2e2e2e00,$52aefea0,$4cfb3fff,$01700000
260 dc.l $0620f23b,$d0ff0170,$00000656,$f23b9c00
261 dc.l $01700000,$06ac3d7c,$0000fea6,$48ee7fff
262 dc.l $ff80f22e,$f0ffff20,$f23c9000,$00000200
263 dc.l $f22ebc00,$feb42d7c,$50000000,$fe802d7c
264 dc.l $80000000,$fe842d7c,$00000000,$fe88f22e
265 dc.l $d080fe80,$44fc0000,$f23c5822,$000242ee
266 dc.l $fea448ee,$7fffffc0,$f22ef0ff,$fec0f22e
267 dc.l $bc00fea8,$2d7c5000,$0000ff20,$2d7c8000
268 dc.l $0000ff24,$2d7c0000,$0000ff28,$2d7c0000
269 dc.l $0208feb8,$41faffc2,$2d48febc,$61ff0000
270 dc.l $050a4a00,$66ff0000,$053061ff,$00000532
271 dc.l $4a0066ff,$00000522,$42804e75,$09456e61
272 dc.l $626c6564,$20534e41,$4e2e2e2e,$000051fc
273 dc.l $52aefea0,$4cfb3fff,$01700000,$0544f23b
274 dc.l $d0ff0170,$0000057a,$f23b9c00,$01700000
275 dc.l $05d03d7c,$0000fea6,$48ee7fff,$ff80f22e
276 dc.l $f0ffff20,$f23c9000,$00004000,$f22ebc00
277 dc.l $feb42d7c,$ffff0000,$fe802d7c,$00000000
278 dc.l $fe842d7c,$00000001,$fe88f22e,$d080fe80
279 dc.l $44fc0000,$f23c5822,$000242ee,$fea448ee
280 dc.l $7fffffc0,$f22ef0ff,$fec0f22e,$bc00fea8
281 dc.l $2d7cffff,$0000ff20,$2d7c0000,$0000ff24
282 dc.l $2d7c0000,$0001ff28,$2d7c0900,$4080feb8
283 dc.l $41faffc2,$2d48febc,$61ff0000,$042e4a00
284 dc.l $66ff0000,$045461ff,$00000456,$4a0066ff
285 dc.l $00000446,$42804e75,$09456e61,$626c6564
286 dc.l $204f5045,$52522e2e,$2e0051fc,$52aefea0
287 dc.l $4cfb3fff,$01700000,$0468f23b,$d0ff0170
288 dc.l $0000049e,$f23b9c00,$01700000,$04f43d7c
289 dc.l $0000fea6,$48ee7fff,$ff80f22e,$f0ffff20
290 dc.l $f23c9000,$00002000,$f22ebc00,$feb42d7c
291 dc.l $ffff0000,$fe802d7c,$00000000,$fe842d7c
292 dc.l $00000000,$fe88f22e,$d080fe80,$44fc0000
293 dc.l $f23c4422,$7f800000,$42eefea4,$48ee7fff
294 dc.l $ffc0f22e,$f0fffec0,$f22ebc00,$fea82d7c
295 dc.l $ffff0000,$ff202d7c,$00000000,$ff242d7c
296 dc.l $00000000,$ff282d7c,$01002080,$feb841fa
297 dc.l $ffc02d48,$febc61ff,$00000350,$4a0066ff
298 dc.l $00000376,$61ff0000,$03784a00,$66ff0000
299 dc.l $03684280,$4e750945,$6e61626c,$65642044
300 dc.l $5a2e2e2e,$000051fc,$52aefea0,$4cfb3fff
301 dc.l $01700000,$038cf23b,$d0ff0170,$000003c2
302 dc.l $f23b9c00,$01700000,$04183d7c,$0000fea6
303 dc.l $48ee7fff,$ff80f22e,$f0ffff20,$f23c9000
304 dc.l $00000400,$f22ebc00,$feb42d7c,$40000000
305 dc.l $fe802d7c,$80000000,$fe842d7c,$00000000
306 dc.l $fe88f22e,$d080fe80,$44fc0000,$f23c5820
307 dc.l $000042ee,$fea448ee,$7fffffc0,$f22ef0ff
308 dc.l $fec0f22e,$bc00fea8,$2d7c4000,$0000ff20
309 dc.l $2d7c8000,$0000ff24,$2d7c0000,$0000ff28
310 dc.l $2d7c0200,$0410feb8,$41faffc2,$2d48febc
311 dc.l $61ff0000,$02764a00,$66ff0000,$029c61ff
312 dc.l $0000029e,$4a0066ff,$0000028e,$42804e75
313 dc.l $09556e69,$6d706c65,$6d656e74,$65642064
314 dc.l $61746120,$74797065,$2f666f72,$6d61742e
315 dc.l $2e2e0000,$52aefea0,$4cfb3fff,$01700000
316 dc.l $02a0f23b,$d0ff0170,$000002d6,$f23b9c00
317 dc.l $01700000,$032c3d7c,$0000fea6,$48ee7fff
318 dc.l $ff80f22e,$f0ffff20,$f22ebc00,$feb42d7c
319 dc.l $c03f0000,$fe802d7c,$00000000,$fe842d7c
320 dc.l $00000001,$fe88f23c,$58000002,$44fc0000
321 dc.l $f22e4823,$fe8042ee,$fea448ee,$7fffffc0
322 dc.l $f22ef0ff,$fec0f22e,$bc00fea8,$2d7cc001
323 dc.l $0000ff20,$2d7c8000,$0000ff24,$2d7c0000
324 dc.l $0000ff28,$2d7c0800,$0000feb8,$41faffc2
325 dc.l $2d48febc,$61ff0000,$01924a00,$66ff0000
326 dc.l $01b861ff,$000001ba,$4a0066ff,$000001aa
327 dc.l $52aefea0,$4cfb3fff,$01700000,$01e4f23b
328 dc.l $d0ff0170,$0000021a,$f23b9c00,$01700000
329 dc.l $02703d7c,$0000fea6,$48ee7fff,$ff80f22e
330 dc.l $f0ffff20,$f22ebc00,$feb42d7c,$80000000
331 dc.l $fe802d7c,$01000000,$fe842d7c,$00000000
332 dc.l $fe88f23c,$40007fff,$ffff44fc,$0000f22e
333 dc.l $4823fe80,$42eefea4,$48ee7fff,$ffc0f22e
334 dc.l $f0fffec0,$f22ebc00,$fea82d7c,$80170000
335 dc.l $ff202d7c,$fffffffe,$ff242d7c,$00000000
336 dc.l $ff282d7c,$08000000,$feb841fa,$ffc22d48
337 dc.l $febc61ff,$000000d4,$4a0066ff,$000000fa
338 dc.l $61ff0000,$00fc4a00,$66ff0000,$00ec52ae
339 dc.l $fea04cfb,$3fff0170,$00000126,$f23bd0ff
340 dc.l $01700000,$015cf23b,$9c000170,$000001b2
341 dc.l $3d7c0000,$fea648ee,$7fffff80,$f22ef0ff
342 dc.l $ff20f22e,$bc00feb4,$2d7cc123,$0001fe80
343 dc.l $2d7c2345,$6789fe84,$2d7c1234,$5678fe88
344 dc.l $44fc0000,$f22e4c18,$fe8042ee,$fea448ee
345 dc.l $7fffffc0,$f22ef0ff,$fec0f22e,$bc00fea8
346 dc.l $2d7c3e66,$0000ff20,$2d7cd0ed,$23e8ff24
347 dc.l $2d7cd140,$35bcff28,$2d7c0000,$0108feb8
348 dc.l $41faffc2,$2d48febc,$61ff0000,$001e4a00
349 dc.l $66ff0000,$004461ff,$00000046,$4a0066ff
350 dc.l $00000036,$42804e75,$41eeff80,$43eeffc0
351 dc.l $700eb189,$66ff0000,$001c51c8,$fff6302e
352 dc.l $fea6322e,$fea4b041,$66ff0000,$00084280
353 dc.l $4e757001,$4e75222e,$fea07001,$4e7541ee
354 dc.l $ff2043ee,$fec07017,$b18966ff,$0000002c
355 dc.l $51c8fff6,$41eefeb4,$43eefea8,$b18966ff
356 dc.l $00000018,$b18966ff,$00000010,$b18966ff
357 dc.l $00000008,$42804e75,$70014e75,$acacacac
358 dc.l $acacacac,$acacacac,$acacacac,$acacacac
359 dc.l $acacacac,$acacacac,$acacacac,$acacacac
360 dc.l $acacacac,$acacacac,$acacacac,$acacacac
361 dc.l $acacacac,$acacacac,$acacacac,$7fff0000
362 dc.l $ffffffff,$ffffffff,$7fff0000,$ffffffff
363 dc.l $ffffffff,$7fff0000,$ffffffff,$ffffffff
364 dc.l $7fff0000,$ffffffff,$ffffffff,$7fff0000
365 dc.l $ffffffff,$ffffffff,$7fff0000,$ffffffff
366 dc.l $ffffffff,$7fff0000,$ffffffff,$ffffffff
367 dc.l $7fff0000,$ffffffff,$ffffffff,$00000000
368 dc.l $00000000,$00000000,$2f00203a,$e884487b
369 dc.l $0930ffff,$e880202f,$00044e74,$00042f00
370 dc.l $203ae872,$487b0930,$ffffe86a,$202f0004
371 dc.l $4e740004,$00000000,$00000000,$00000000
diff --git a/arch/m68k/ifpsp060/ilsp.doc b/arch/m68k/ifpsp060/ilsp.doc
new file mode 100644
index 000000000000..f6fae6d900ae
--- /dev/null
+++ b/arch/m68k/ifpsp060/ilsp.doc
@@ -0,0 +1,150 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2968060 INTEGER SOFTWARE PACKAGE (Library version)
30-------------------------------------------------
31
32The file ilsp.s contains the "Library version" of the
3368060 Integer Software Package. Routines included in this
34module can be used to emulate 64-bit divide and multiply,
35and the "cmp2" instruction. These instructions are not
36implemented in hardware on the 68060 and normally take
37exception vector #61 "Unimplemented Integer Instruction".
38
39By re-compiling a program that uses these instructions, and
40making subroutine calls in place of the unimplemented
41instructions, a program can avoid the overhead associated with
42taking the exception.
43
44Release file format:
45--------------------
46The file ilsp.sa is essentially a hexadecimal image of the
47release package. This is the ONLY format which will be supported.
48The hex image was created by assembling the source code and
49then converting the resulting binary output image into an
50ASCII text file. The hexadecimal numbers are listed
51using the Motorola Assembly Syntax assembler directive "dc.l"
52(define constant longword). The file can be converted to other
53assembly syntaxes by using any word processor with a global
54search and replace function.
55
56To assist in assembling and linking this module with other modules,
57the installer should add a symbolic label to the top of the file.
58This will allow calling routines to access the entry points
59of this package.
60
61The source code ilsp.s has also been included but only for
62documentation purposes.
63
64Release file structure:
65-----------------------
66The file ilsp.sa contains an "Entry-Point" section and a
67code section. The ILSP has no "Call-Out" section. The first section
68is the "Entry-Point" section. In order to access a function in the
69package, a program must "bsr" or "jsr" to the location listed
70below in "68060ILSP Entry Points" that corresponds to the desired
71function. A branch instruction located at the selected entry point
72within the package will then enter the correct emulation code routine.
73
74The entry point addresses at the beginning of the package will remain
75fixed so that a program calling the routines will not have to be
76re-compiled with every new 68060ILSP release.
77
78For example, to use a 64-bit multiply instruction,
79do a "bsr" or "jsr" to the entry point defined by
80the 060ILSP entry table. A compiler generated code sequence
81for unsigned multiply could look like:
82
83# mulu.l <ea>,Dh:Dl
84# mulu.l _multiplier,%d1:%d0
85
86 subq.l &0x8,%sp # make room for result on stack
87 pea (%sp) # pass: result addr on stack
88 mov.l %d0,-(%sp) # pass: multiplicand on stack
89 mov.l _multiplier,-(%sp) # pass: multiplier on stack
90 bsr.l _060LISP_TOP+0x18 # branch to multiply routine
91 add.l &0xc,%sp # clear arguments from stack
92 mov.l (%sp)+,%d1 # load result[63:32]
93 mov.l (%sp)+,%d0 # load result[31:0]
94
95For a divide:
96
97# divu.l <ea>,Dr:Dq
98# divu.l _divisor,%d1:%d0
99
100 subq.l &0x8,%sp # make room for result on stack
101 pea (%sp) # pass: result addr on stack
102 mov.l %d0,-(%sp) # pass: dividend hi on stack
103 mov.l %d1,-(%sp) # pass: dividend hi on stack
104 mov.l _divisor,-(%sp) # pass: divisor on stack
105 bsr.l _060LISP_TOP+0x08 # branch to divide routine
106 add.l &0xc,%sp # clear arguments from stack
107 mov.l (%sp)+,%d1 # load remainder
108 mov.l (%sp)+,%d0 # load quotient
109
110The library routines also return the correct condition code
111register value. If this is important, then the caller of the library
112routine must make sure that the value isn't lost while popping
113other items off of the stack.
114
115An example of using the "cmp2" instruction is as follows:
116
117# cmp2.l <ea>,Rn
118# cmp2.l _bounds,%d0
119
120 pea _bounds # pass ptr to bounds
121 mov.l %d0,-(%sp) # pass Rn
122 bsr.l _060LSP_TOP_+0x48 # branch to "cmp2" routine
123 mov.w %cc,_tmp # save off condition codes
124 addq.l &0x8,%sp # clear arguments from stack
125
126Exception reporting:
127--------------------
128If the instruction being emulated is a divide and the source
129operand is a zero, then the library routine, as its last
130instruction, executes an implemented divide using a zero
131source operand so that an "Integer Divide-by-Zero" exception
132will be taken. Although the exception stack frame will not
133point to the correct instruction, the user will at least be able
134to record that such an event occurred if desired.
135
13668060ILSP entry points:
137-----------------------
138_060ILSP_TOP:
1390x000: _060LSP__idivs64_
1400x008: _060LSP__idivu64_
141
1420x010: _060LSP__imuls64_
1430x018: _060LSP__imulu64_
144
1450x020: _060LSP__cmp2_Ab_
1460x028: _060LSP__cmp2_Aw_
1470x030: _060LSP__cmp2_Al_
1480x038: _060LSP__cmp2_Db_
1490x040: _060LSP__cmp2_Dw_
1500x048: _060LSP__cmp2_Dl_
diff --git a/arch/m68k/ifpsp060/ilsp.sa b/arch/m68k/ifpsp060/ilsp.sa
new file mode 100644
index 000000000000..2757d502b012
--- /dev/null
+++ b/arch/m68k/ifpsp060/ilsp.sa
@@ -0,0 +1,101 @@
1 dc.l $60ff0000,$01fe0000,$60ff0000,$02080000
2 dc.l $60ff0000,$04900000,$60ff0000,$04080000
3 dc.l $60ff0000,$051e0000,$60ff0000,$053c0000
4 dc.l $60ff0000,$055a0000,$60ff0000,$05740000
5 dc.l $60ff0000,$05940000,$60ff0000,$05b40000
6 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
7 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
8 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
9 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
10 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
11 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
12 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
13 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
14 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
15 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
16 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
17 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
18 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
19 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
20 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
21 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
22 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
23 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
24 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
25 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
26 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
27 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
28 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
29 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
30 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
31 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
32 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
33 dc.l $4e56fff0,$48e73f00,$42eefff0,$50eeffff
34 dc.l $60104e56,$fff048e7,$3f0042ee,$fff051ee
35 dc.l $ffff2e2e,$00086700,$00ae2a2e,$000c2c2e
36 dc.l $00104a2e,$ffff671a,$4a875dee,$fffe6a02
37 dc.l $44874a85,$5deefffd,$6a0844fc,$00004086
38 dc.l $40854a85,$66164a86,$67000046,$be866306
39 dc.l $cb466000,$00124c47,$6005600a,$be85634c
40 dc.l $61ff0000,$00864a2e,$ffff6724,$4a2efffd
41 dc.l $67024485,$102efffe,$b12efffd,$670c0c86
42 dc.l $80000000,$62264486,$60060806,$001f661c
43 dc.l $026e0010,$fff044ee,$fff04a86,$48f60060
44 dc.l $01610014,$4cdf00fc,$4e5e4e75,$2a2e000c
45 dc.l $2c2e0010,$026e001c,$fff0006e,$0002fff0
46 dc.l $44eefff0,$60d62dae,$000c0161,$00142dae
47 dc.l $00100162,$00140004,$44eefff0,$4cdf00fc
48 dc.l $4e5e80fc,$00004e75,$0c870000,$ffff621e
49 dc.l $42814845,$48463a06,$8ac73205,$48463a06
50 dc.l $8ac74841,$32054245,$48452c01,$4e7542ae
51 dc.l $fff8422e,$fffc4281,$0807001f,$660e52ae
52 dc.l $fff8e38f,$e38ee395,$6000ffee,$26072405
53 dc.l $48424843,$b4436606,$323cffff,$600a2205
54 dc.l $82c30281,$0000ffff,$2f064246,$48462607
55 dc.l $2401c4c7,$4843c6c1,$28059883,$48443004
56 dc.l $38064a40,$6600000a,$b4846304,$538160de
57 dc.l $2f052c01,$48462a07,$61ff0000,$006a2405
58 dc.l $26062a1f,$2c1f9c83,$9b8264ff,$0000001a
59 dc.l $53814282,$26074843,$4243dc83,$db822607
60 dc.l $42434843,$da834a2e,$fffc6616,$3d41fff4
61 dc.l $42814845,$48463a06,$424650ee,$fffc6000
62 dc.l $ff6c3d41,$fff63c05,$48464845,$2e2efff8
63 dc.l $670a5387,$e28de296,$51cffffa,$2a062c2e
64 dc.l $fff44e75,$24062606,$28054843,$4844ccc5
65 dc.l $cac3c4c4,$c6c44284,$4846dc45,$d744dc42
66 dc.l $d7444846,$42454242,$48454842,$da82da83
67 dc.l $4e754e56,$fffc48e7,$380042ee,$fffc202e
68 dc.l $00086700,$005a222e,$000c6700,$00522400
69 dc.l $26002801,$48434844,$c0c1c2c3,$c4c4c6c4
70 dc.l $42844840,$d041d784,$d042d784,$48404241
71 dc.l $42424841,$4842d282,$d283382e,$fffc0204
72 dc.l $00104a81,$6a040004,$000844c4,$c34048f6
73 dc.l $00030161,$00104cdf,$001c4e5e,$4e754280
74 dc.l $4281382e,$fffc0204,$00100004,$000444c4
75 dc.l $60da4e56,$fffc48e7,$3c0042ee,$fffc202e
76 dc.l $000867da,$222e000c,$67d44205,$4a806c06
77 dc.l $44800005,$00014a81,$6c064481,$0a050001
78 dc.l $24002600,$28014843,$4844c0c1,$c2c3c4c4
79 dc.l $c6c44284,$4840d041,$d784d042,$d7844840
80 dc.l $42414242,$48414842,$d282d283,$4a056708
81 dc.l $46804681,$5280d384,$382efffc,$02040010
82 dc.l $4a816a04,$00040008,$44c4c340,$48f60003
83 dc.l $01610010,$4cdf003c,$4e5e4e75,$42804281
84 dc.l $382efffc,$02040010,$00040004,$44c460da
85 dc.l $4e56fffc,$48e73800,$42eefffc,$242e0008
86 dc.l $10360161,$000c1236,$0162000c,$000149c0
87 dc.l $49c16000,$00b84e56,$fffc48e7,$380042ee
88 dc.l $fffc242e,$00083036,$0161000c,$32360162
89 dc.l $000c0002,$48c048c1,$60000092,$4e56fffc
90 dc.l $48e73800,$42eefffc,$242e0008,$20360161
91 dc.l $000c2236,$0162000c,$00046000,$00704e56
92 dc.l $fffc48e7,$380042ee,$fffc242e,$00081036
93 dc.l $0161000c,$12360162,$000c0001,$49c049c1
94 dc.l $49c26000,$00484e56,$fffc48e7,$380042ee
95 dc.l $fffc242e,$00083036,$0161000c,$32360162
96 dc.l $000c0002,$48c048c1,$48c26000,$00204e56
97 dc.l $fffc48e7,$380042ee,$fffc242e,$00082036
98 dc.l $0161000c,$22360162,$000c0004,$948042c3
99 dc.l $02030004,$9280b282,$42c48604,$02030005
100 dc.l $382efffc,$0204001a,$880344c4,$4cdf001c
101 dc.l $4e5e4e75,$00000000,$00000000,$00000000
diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S
new file mode 100644
index 000000000000..803a6ecdda81
--- /dev/null
+++ b/arch/m68k/ifpsp060/iskeleton.S
@@ -0,0 +1,349 @@
1|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2|MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3|M68000 Hi-Performance Microprocessor Division
4|M68060 Software Package
5|Production Release P1.00 -- October 10, 1994
6|
7|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8|
9|THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10|To the maximum extent permitted by applicable law,
11|MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12|INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13|and any warranty against infringement with regard to the SOFTWARE
14|(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15|
16|To the maximum extent permitted by applicable law,
17|IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18|(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19|BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20|ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21|Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22|
23|You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24|so long as this entire notice is retained without alteration in any modified and/or
25|redistributed versions, and that such modified versions are clearly identified as such.
26|No licenses are granted by implication, estoppel or otherwise under any patents
27|or trademarks of Motorola, Inc.
28|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29| iskeleton.s
30|
31| This file contains:
32| (1) example "Call-out"s
33| (2) example package entry code
34| (3) example "Call-out" table
35|
36
37#include <linux/linkage.h>
38#include <asm/entry.h>
39#include <asm/offsets.h>
40
41
42|################################
43| (1) EXAMPLE CALL-OUTS #
44| #
45| _060_isp_done() #
46| _060_real_chk() #
47| _060_real_divbyzero() #
48| #
49| _060_real_cas() #
50| _060_real_cas2() #
51| _060_real_lock_page() #
52| _060_real_unlock_page() #
53|################################
54
55|
56| _060_isp_done():
57|
58| This is and example main exit point for the Unimplemented Integer
59| Instruction exception handler. For a normal exit, the
60| _isp_unimp() branches to here so that the operating system
61| can do any clean-up desired. The stack frame is the
62| Unimplemented Integer Instruction stack frame with
63| the PC pointing to the instruction following the instruction
64| just emulated.
65| To simply continue execution at the next instruction, just
66| do an "rte".
67|
68| Linux/68k: If returning to user space, check for needed reselections.
69
70 .global _060_isp_done
71_060_isp_done:
72 btst #0x5,%sp@ | supervisor bit set in saved SR?
73 beq .Lnotkern
74 rte
75.Lnotkern:
76 SAVE_ALL_INT
77 GET_CURRENT(%d0)
78 tstb %curptr@(TASK_NEEDRESCHED)
79 jne ret_from_exception | deliver signals,
80 | reschedule etc..
81 RESTORE_ALL
82
83|
84| _060_real_chk():
85|
86| This is an alternate exit point for the Unimplemented Integer
87| Instruction exception handler. If the instruction was a "chk2"
88| and the operand was out of bounds, then _isp_unimp() creates
89| a CHK exception stack frame from the Unimplemented Integer Instrcution
90| stack frame and branches to this routine.
91|
92| Linux/68k: commented out test for tracing
93
94 .global _060_real_chk
95_060_real_chk:
96| tst.b (%sp) | is tracing enabled?
97| bpls real_chk_end | no
98
99|
100| CHK FRAME TRACE FRAME
101| ***************** *****************
102| * Current PC * * Current PC *
103| ***************** *****************
104| * 0x2 * 0x018 * * 0x2 * 0x024 *
105| ***************** *****************
106| * Next * * Next *
107| * PC * * PC *
108| ***************** *****************
109| * SR * * SR *
110| ***************** *****************
111|
112| move.b #0x24,0x7(%sp) | set trace vecno
113| bral _060_real_trace
114
115real_chk_end:
116 bral trap | jump to trap handler
117
118|
119| _060_real_divbyzero:
120|
121| This is an alternate exit point for the Unimplemented Integer
122| Instruction exception handler isp_unimp(). If the instruction is a 64-bit
123| integer divide where the source operand is a zero, then the _isp_unimp()
124| creates a Divide-by-zero exception stack frame from the Unimplemented
125| Integer Instruction stack frame and branches to this routine.
126|
127| Remember that a trace exception may be pending. The code below performs
128| no action associated with the "chk" exception. If tracing is enabled,
129| then it create a Trace exception stack frame from the "chk" exception
130| stack frame and branches to the _real_trace() entry point.
131|
132| Linux/68k: commented out test for tracing
133
134 .global _060_real_divbyzero
135_060_real_divbyzero:
136| tst.b (%sp) | is tracing enabled?
137| bpls real_divbyzero_end | no
138
139|
140| DIVBYZERO FRAME TRACE FRAME
141| ***************** *****************
142| * Current PC * * Current PC *
143| ***************** *****************
144| * 0x2 * 0x014 * * 0x2 * 0x024 *
145| ***************** *****************
146| * Next * * Next *
147| * PC * * PC *
148| ***************** *****************
149| * SR * * SR *
150| ***************** *****************
151|
152| move.b #0x24,0x7(%sp) | set trace vecno
153| bral _060_real_trace
154
155real_divbyzero_end:
156 bral trap | jump to trap handler
157
158|##########################
159
160|
161| _060_real_cas():
162|
163| Entry point for the selected cas emulation code implementation.
164| If the implementation provided by the 68060ISP is sufficient,
165| then this routine simply re-enters the package through _isp_cas.
166|
167 .global _060_real_cas
168_060_real_cas:
169 bral _I_CALL_TOP+0x80+0x08
170
171|
172| _060_real_cas2():
173|
174| Entry point for the selected cas2 emulation code implementation.
175| If the implementation provided by the 68060ISP is sufficient,
176| then this routine simply re-enters the package through _isp_cas2.
177|
178 .global _060_real_cas2
179_060_real_cas2:
180 bral _I_CALL_TOP+0x80+0x10
181
182|
183| _060_lock_page():
184|
185| Entry point for the operating system`s routine to "lock" a page
186| from being paged out. This routine is needed by the cas/cas2
187| algorithms so that no page faults occur within the "core" code
188| region. Note: the routine must lock two pages if the operand
189| spans two pages.
190| NOTE: THE ROUTINE SHOULD RETURN AN FSLW VALUE IN D0 ON FAILURE
191| SO THAT THE 060SP CAN CREATE A PROPER ACCESS ERROR FRAME.
192| Arguments:
193| a0 = operand address
194| d0 = `xxxxxxff -> supervisor; `xxxxxx00 -> user
195| d1 = `xxxxxxff -> longword; `xxxxxx00 -> word
196| Expected outputs:
197| d0 = 0 -> success; non-zero -> failure
198|
199| Linux/m68k: Make sure the page is properly paged in, so we use
200| plpaw and handle any exception here. The kernel must not be
201| preempted until _060_unlock_page(), so that the page stays mapped.
202|
203 .global _060_real_lock_page
204_060_real_lock_page:
205 move.l %d2,-(%sp)
206 | load sfc/dfc
207 tst.b %d0
208 jne 1f
209 moveq #1,%d0
210 jra 2f
2111: moveq #5,%d0
2122: movec.l %dfc,%d2
213 movec.l %d0,%dfc
214 movec.l %d0,%sfc
215
216 clr.l %d0
217 | prefetch address
218 .chip 68060
219 move.l %a0,%a1
2201: plpaw (%a1)
221 addq.w #1,%a0
222 tst.b %d1
223 jeq 2f
224 addq.w #2,%a0
2252: plpaw (%a0)
2263: .chip 68k
227
228 | restore sfc/dfc
229 movec.l %d2,%dfc
230 movec.l %d2,%sfc
231 move.l (%sp)+,%d2
232 rts
233
234.section __ex_table,"a"
235 .align 4
236 .long 1b,11f
237 .long 2b,21f
238.previous
239.section .fixup,"ax"
240 .even
24111: move.l #0x020003c0,%d0
242 or.l %d2,%d0
243 swap %d0
244 jra 3b
24521: move.l #0x02000bc0,%d0
246 or.l %d2,%d0
247 swap %d0
248 jra 3b
249.previous
250
251|
252| _060_unlock_page():
253|
254| Entry point for the operating system`s routine to "unlock" a
255| page that has been "locked" previously with _real_lock_page.
256| Note: the routine must unlock two pages if the operand spans
257| two pages.
258| Arguments:
259| a0 = operand address
260| d0 = `xxxxxxff -> supervisor; `xxxxxx00 -> user
261| d1 = `xxxxxxff -> longword; `xxxxxx00 -> word
262|
263| Linux/m68k: perhaps reenable preemption here...
264
265 .global _060_real_unlock_page
266_060_real_unlock_page:
267 clr.l %d0
268 rts
269
270|###########################################################################
271
272|#################################
273| (2) EXAMPLE PACKAGE ENTRY CODE #
274|#################################
275
276 .global _060_isp_unimp
277_060_isp_unimp:
278 bral _I_CALL_TOP+0x80+0x00
279
280 .global _060_isp_cas
281_060_isp_cas:
282 bral _I_CALL_TOP+0x80+0x08
283
284 .global _060_isp_cas2
285_060_isp_cas2:
286 bral _I_CALL_TOP+0x80+0x10
287
288 .global _060_isp_cas_finish
289_060_isp_cas_finish:
290 bra.l _I_CALL_TOP+0x80+0x18
291
292 .global _060_isp_cas2_finish
293_060_isp_cas2_finish:
294 bral _I_CALL_TOP+0x80+0x20
295
296 .global _060_isp_cas_inrange
297_060_isp_cas_inrange:
298 bral _I_CALL_TOP+0x80+0x28
299
300 .global _060_isp_cas_terminate
301_060_isp_cas_terminate:
302 bral _I_CALL_TOP+0x80+0x30
303
304 .global _060_isp_cas_restart
305_060_isp_cas_restart:
306 bral _I_CALL_TOP+0x80+0x38
307
308|###########################################################################
309
310|###############################
311| (3) EXAMPLE CALL-OUT SECTION #
312|###############################
313
314| The size of this section MUST be 128 bytes!!!
315
316_I_CALL_TOP:
317 .long _060_real_chk - _I_CALL_TOP
318 .long _060_real_divbyzero - _I_CALL_TOP
319 .long _060_real_trace - _I_CALL_TOP
320 .long _060_real_access - _I_CALL_TOP
321 .long _060_isp_done - _I_CALL_TOP
322
323 .long _060_real_cas - _I_CALL_TOP
324 .long _060_real_cas2 - _I_CALL_TOP
325 .long _060_real_lock_page - _I_CALL_TOP
326 .long _060_real_unlock_page - _I_CALL_TOP
327
328 .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
329 .long 0x00000000, 0x00000000, 0x00000000
330
331 .long _060_imem_read - _I_CALL_TOP
332 .long _060_dmem_read - _I_CALL_TOP
333 .long _060_dmem_write - _I_CALL_TOP
334 .long _060_imem_read_word - _I_CALL_TOP
335 .long _060_imem_read_long - _I_CALL_TOP
336 .long _060_dmem_read_byte - _I_CALL_TOP
337 .long _060_dmem_read_word - _I_CALL_TOP
338 .long _060_dmem_read_long - _I_CALL_TOP
339 .long _060_dmem_write_byte - _I_CALL_TOP
340 .long _060_dmem_write_word - _I_CALL_TOP
341 .long _060_dmem_write_long - _I_CALL_TOP
342
343 .long 0x00000000
344 .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
345
346|###########################################################################
347
348| 060 INTEGER KERNEL PACKAGE MUST GO HERE!!!
349#include "isp.sa"
diff --git a/arch/m68k/ifpsp060/isp.doc b/arch/m68k/ifpsp060/isp.doc
new file mode 100644
index 000000000000..5a90fded3f0b
--- /dev/null
+++ b/arch/m68k/ifpsp060/isp.doc
@@ -0,0 +1,218 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2968060 INTEGER SOFTWARE PACKAGE (Kernel version)
30------------------------------------------------
31
32The file isp.sa contains the 68060 Integer Software Package.
33This package is essentially an exception handler that can be
34integrated into an operating system to handle the "Unimplemented
35Integer Instruction" exception vector #61.
36This exception is taken when any of the integer instructions
37not hardware implemented on the 68060 are encountered. The
38isp.sa provides full emulation support for these instructions.
39
40The unimplemented integer instructions are:
41 64-bit divide
42 64-bit multiply
43 movep
44 cmp2
45 chk2
46 cas (w/ a misaligned effective address)
47 cas2
48
49Release file format:
50--------------------
51The file isp.sa is essentially a hexadecimal image of the
52release package. This is the ONLY format which will be supported.
53The hex image was created by assembling the source code and
54then converting the resulting binary output image into an
55ASCII text file. The hexadecimal numbers are listed
56using the Motorola Assembly Syntax assembler directive "dc.l"
57(define constant longword). The file can be converted to other
58assembly syntaxes by using any word processor with a global
59search and replace function.
60
61To assist in assembling and linking this module with other modules,
62the installer should add a symbolic label to the top of the file.
63This will allow calling routines to access the entry points
64of this package.
65
66The source code isp.s has also been included but only for
67documentation purposes.
68
69Release file structure:
70-----------------------
71
72(top of module)
73 -----------------
74 | | - 128 byte-sized section
75 (1) | Call-Out | - 4 bytes per entry (user fills these in)
76 | | - example routines in iskeleton.s
77 -----------------
78 | | - 8 bytes per entry
79 (2) | Entry Point | - user does a "bra" or "jmp" to this address
80 | |
81 -----------------
82 | | - code section
83 (3) ~ ~
84 | |
85 -----------------
86(bottom of module)
87
88The first section of this module is the "Call-out" section. This section
89is NOT INCLUDED in isp.sa (an example "Call-out" section is provided at
90the end of the file iskeleton.s). The purpose of this section is to allow
91the ISP routines to reference external functions that must be provided
92by the host operating system. This section MUST be exactly 128 bytes in
93size. There are 32 fields, each 4 bytes in size. Each field corresponds
94to a function required by the ISP (these functions and their location are
95listed in "68060ISP call-outs" below). Each field entry should contain
96the address of the corresponding function RELATIVE to the starting address
97of the "call-out" section. The "Call-out" section must sit adjacent to the
98isp.sa image in memory.
99
100The second section, the "Entry-point" section, is used by external routines
101to access the functions within the ISP. Since the isp.sa hex file contains
102no symbol names, this section contains function entry points that are fixed
103with respect to the top of the package. The currently defined entry-points
104are listed in section "68060 ISP entry points" below. A calling routine
105would simply execute a "bra" or "jmp" that jumped to the selected function
106entry-point.
107
108For example, if the 68060 hardware took a "Unimplemented Integer Instruction"
109exception (vector #61), the operating system should execute something
110similar to:
111
112 bra _060ISP_TOP+128+0
113
114(_060ISP_TOP is the starting address of the "Call-out" section; the "Call-out"
115section is 128 bytes long; and the Unimplemented Integer ISP handler entry
116point is located 0 bytes from the top of the "Entry-point" section.)
117
118The third section is the code section. After entering through an "Entry-point",
119the entry code jumps to the appropriate emulation code within the code section.
120
12168060ISP call-outs: (details in iskeleton.s)
122--------------------
1230x000: _060_real_chk
1240x004: _060_real_divbyzero
1250x008: _060_real_trace
1260x00c: _060_real_access
1270x010: _060_isp_done
128
1290x014: _060_real_cas
1300x018: _060_real_cas2
1310x01c: _060_real_lock_page
1320x020: _060_real_unlock_page
133
1340x024: (Motorola reserved)
1350x028: (Motorola reserved)
1360x02c: (Motorola reserved)
1370x030: (Motorola reserved)
1380x034: (Motorola reserved)
1390x038: (Motorola reserved)
1400x03c: (Motorola reserved)
141
1420x040: _060_imem_read
1430x044: _060_dmem_read
1440x048: _060_dmem_write
1450x04c: _060_imem_read_word
1460x050: _060_imem_read_long
1470x054: _060_dmem_read_byte
1480x058: _060_dmem_read_word
1490x05c: _060_dmem_read_long
1500x060: _060_dmem_write_byte
1510x064: _060_dmem_write_word
1520x068: _060_dmem_write_long
153
1540x06c: (Motorola reserved)
1550x070: (Motorola reserved)
1560x074: (Motorola reserved)
1570x078: (Motorola reserved)
1580x07c: (Motorola reserved)
159
16068060ISP entry points:
161-----------------------
1620x000: _060_isp_unimp
163
1640x008: _060_isp_cas
1650x010: _060_isp_cas2
1660x018: _060_isp_cas_finish
1670x020: _060_isp_cas2_finish
1680x028: _060_isp_cas_inrange
1690x030: _060_isp_cas_terminate
1700x038: _060_isp_cas_restart
171
172Integrating cas/cas2:
173---------------------
174The instructions "cas2" and "cas" (when used with a misaligned effective
175address) take the Unimplemented Integer Instruction exception. When the
176060ISP is installed properly, these instructions will enter through the
177_060_isp_unimp() entry point of the ISP.
178
179After the 060ISP decodes the instruction type and fetches the appropriate
180data registers, and BEFORE the actual emulated transfers occur, the
181package calls either the "Call-out" _060_real_cas() or _060_real_cas2().
182If the emulation code provided by the 060ISP is sufficient for the
183host system (see isp.s source code), then these "Call-out"s should be
184made, by the system integrator, to point directly back into the package
185through the "Entry-point"s _060_isp_cas() or _060_isp_cas2().
186
187One other necessary action by the integrator is to supply the routines
188_060_real_lock_page() and _060_real_unlock_page(). These functions are
189defined further in iskeleton.s and the 68060 Software Package Specification.
190
191If the "core" emulation routines of either "cas" or "cas2" perform some
192actions which are too system-specific, then the system integrator must
193supply new emulation code. This new emulation code should reside within
194the functions _060_real_cas() or _060_real_cas2(). When this new emulation
195code has completed, then it should re-enter the 060ISP package through the
196"Entry-point" _060_isp_cas_finish() or _060_isp_cas2_finish().
197To see what the register state is upon entering _060_real_cas() or
198_060_real_cas2() and what it should be upon return to the package through
199_060_isp_cas_finish() or _060_isp_cas2_finish(), please refer to the
200source code in isp.s.
201
202Miscellaneous:
203--------------
204
205_060_isp_unimp:
206----------------
207- documented in 2.2 in spec.
208- Basic flow:
209 exception taken ---> enter _060_isp_unimp --|
210 |
211 |
212 may exit through _060_real_itrace <----|
213 or |
214 may exit through _060_real_chk <----|
215 or |
216 may exit through _060_real_divbyzero <----|
217 or |
218 may exit through _060_isp_done <----|
diff --git a/arch/m68k/ifpsp060/isp.sa b/arch/m68k/ifpsp060/isp.sa
new file mode 100644
index 000000000000..2f88d2a7d156
--- /dev/null
+++ b/arch/m68k/ifpsp060/isp.sa
@@ -0,0 +1,392 @@
1 .long 0x60ff0000,0x02360000,0x60ff0000,0x16260000
2 .long 0x60ff0000,0x12dc0000,0x60ff0000,0x11ea0000
3 .long 0x60ff0000,0x10de0000,0x60ff0000,0x12a40000
4 .long 0x60ff0000,0x12560000,0x60ff0000,0x122a0000
5 .long 0x51fc51fc,0x51fc51fc,0x51fc51fc,0x51fc51fc
6 .long 0x51fc51fc,0x51fc51fc,0x51fc51fc,0x51fc51fc
7 .long 0x51fc51fc,0x51fc51fc,0x51fc51fc,0x51fc51fc
8 .long 0x51fc51fc,0x51fc51fc,0x51fc51fc,0x51fc51fc
9 .long 0x2f00203a,0xfefc487b,0x0930ffff,0xfef8202f
10 .long 0x00044e74,0x00042f00,0x203afeea,0x487b0930
11 .long 0xfffffee2,0x202f0004,0x4e740004,0x2f00203a
12 .long 0xfed8487b,0x0930ffff,0xfecc202f,0x00044e74
13 .long 0x00042f00,0x203afec6,0x487b0930,0xfffffeb6
14 .long 0x202f0004,0x4e740004,0x2f00203a,0xfeb4487b
15 .long 0x0930ffff,0xfea0202f,0x00044e74,0x00042f00
16 .long 0x203afea2,0x487b0930,0xfffffe8a,0x202f0004
17 .long 0x4e740004,0x2f00203a,0xfe90487b,0x0930ffff
18 .long 0xfe74202f,0x00044e74,0x00042f00,0x203afe7e
19 .long 0x487b0930,0xfffffe5e,0x202f0004,0x4e740004
20 .long 0x2f00203a,0xfe6c487b,0x0930ffff,0xfe48202f
21 .long 0x00044e74,0x00042f00,0x203afe76,0x487b0930
22 .long 0xfffffe32,0x202f0004,0x4e740004,0x2f00203a
23 .long 0xfe64487b,0x0930ffff,0xfe1c202f,0x00044e74
24 .long 0x00042f00,0x203afe52,0x487b0930,0xfffffe06
25 .long 0x202f0004,0x4e740004,0x2f00203a,0xfe40487b
26 .long 0x0930ffff,0xfdf0202f,0x00044e74,0x00042f00
27 .long 0x203afe2e,0x487b0930,0xfffffdda,0x202f0004
28 .long 0x4e740004,0x2f00203a,0xfe1c487b,0x0930ffff
29 .long 0xfdc4202f,0x00044e74,0x00042f00,0x203afe0a
30 .long 0x487b0930,0xfffffdae,0x202f0004,0x4e740004
31 .long 0x2f00203a,0xfdf8487b,0x0930ffff,0xfd98202f
32 .long 0x00044e74,0x00042f00,0x203afde6,0x487b0930
33 .long 0xfffffd82,0x202f0004,0x4e740004,0x2f00203a
34 .long 0xfdd4487b,0x0930ffff,0xfd6c202f,0x00044e74
35 .long 0x00042f00,0x203afdc2,0x487b0930,0xfffffd56
36 .long 0x202f0004,0x4e740004,0x4e56ffa0,0x48ee3fff
37 .long 0xffc02d56,0xfff8082e,0x00050004,0x66084e68
38 .long 0x2d48fffc,0x600841ee,0x000c2d48,0xfffc422e
39 .long 0xffaa3d6e,0x0004ffa8,0x2d6e0006,0xffa4206e
40 .long 0xffa458ae,0xffa461ff,0xffffff26,0x2d40ffa0
41 .long 0x0800001e,0x67680800,0x00166628,0x61ff0000
42 .long 0x0cb0082e,0x00050004,0x670000ac,0x082e0002
43 .long 0xffaa6700,0x00a2082e,0x00070004,0x66000186
44 .long 0x600001b0,0x61ff0000,0x0a28082e,0x0002ffaa
45 .long 0x660e082e,0x0005ffaa,0x6600010a,0x60000078
46 .long 0x082e0005,0x000467ea,0x082e0005,0xffaa6600
47 .long 0x01264a2e,0x00046b00,0x014c6000,0x01760800
48 .long 0x0018670a,0x61ff0000,0x07ae6000,0x004a0800
49 .long 0x001b6730,0x48400c00,0x00fc670a,0x61ff0000
50 .long 0x0e926000,0x0032206e,0xffa454ae,0xffa461ff
51 .long 0xfffffe68,0x4a816600,0x019861ff,0x00000d20
52 .long 0x60000014,0x61ff0000,0x08c40c2e,0x0010ffaa
53 .long 0x66000004,0x605c1d6e,0xffa90005,0x082e0005
54 .long 0x00046606,0x206efffc,0x4e604cee,0x3fffffc0
55 .long 0x082e0007,0x00046612,0x2d6effa4,0x00062cae
56 .long 0xfff84e5e,0x60ffffff,0xfd622d6e,0xfff8fffc
57 .long 0x3d6e0004,0x00002d6e,0x00060008,0x2d6effa4
58 .long 0x00023d7c,0x20240006,0x598e4e5e,0x60ffffff
59 .long 0xfd0e1d6e,0xffa90005,0x4cee3fff,0xffc03cae
60 .long 0x00042d6e,0x00060008,0x2d6effa4,0x00023d7c
61 .long 0x20180006,0x2c6efff8,0xdffc0000,0x006060ff
62 .long 0xfffffcb0,0x1d6effa9,0x00054cee,0x3fffffc0
63 .long 0x3cae0004,0x2d6e0006,0x00082d6e,0xffa40002
64 .long 0x3d7c2014,0x00062c6e,0xfff8dffc,0x00000060
65 .long 0x60ffffff,0xfc941d6e,0xffa90005,0x4cee3fff
66 .long 0xffc02d6e,0x0006000c,0x3d7c2014,0x000a2d6e
67 .long 0xffa40006,0x2c6efff8,0xdffc0000,0x006460ff
68 .long 0xfffffc66,0x1d6effa9,0x00054cee,0x3fffffc0
69 .long 0x2d6e0006,0x000c3d7c,0x2024000a,0x2d6effa4
70 .long 0x00062c6e,0xfff8dffc,0x00000064,0x60ffffff
71 .long 0xfc4e1d6e,0xffa90005,0x4cee3fff,0xffc03d7c
72 .long 0x00f4000e,0x2d6effa4,0x000a3d6e,0x00040008
73 .long 0x2c6efff8,0xdffc0000,0x006860ff,0xfffffc4c
74 .long 0x2c882d40,0xfffc4fee,0xffc04cdf,0x7fff2f2f
75 .long 0x000c2f6f,0x00040010,0x2f6f000c,0x00042f6f
76 .long 0x0008000c,0x2f5f0004,0x3f7c4008,0x00066028
77 .long 0x4cee3fff,0xffc04e5e,0x514f2eaf,0x00083f6f
78 .long 0x000c0004,0x3f7c4008,0x00062f6f,0x00020008
79 .long 0x2f7c0942,0x8001000c,0x08170005,0x670608ef
80 .long 0x0002000d,0x60ffffff,0xfbcc0c2e,0x0040ffaa
81 .long 0x660c4280,0x102effab,0x2daeffac,0x0ce04e75
82 .long 0x2040302e,0xffa03200,0x0240003f,0x02810000
83 .long 0x0007303b,0x020a4efb,0x00064afc,0x00400000
84 .long 0x00000000,0x00000000,0x00000000,0x00000000
85 .long 0x00000000,0x00000000,0x00000000,0x00000080
86 .long 0x0086008c,0x00920098,0x009e00a4,0x00aa00b0
87 .long 0x00ce00ec,0x010a0128,0x01460164,0x01820196
88 .long 0x01b401d2,0x01f0020e,0x022c024a,0x0268027c
89 .long 0x029a02b8,0x02d602f4,0x03120330,0x034e036c
90 .long 0x036c036c,0x036c036c,0x036c036c,0x036c03d6
91 .long 0x03f0040a,0x042a03ca,0x00000000,0x0000206e
92 .long 0xffe04e75,0x206effe4,0x4e75206e,0xffe84e75
93 .long 0x206effec,0x4e75206e,0xfff04e75,0x206efff4
94 .long 0x4e75206e,0xfff84e75,0x206efffc,0x4e752008
95 .long 0x206effe0,0xd0882d40,0xffe02d48,0xffac1d7c
96 .long 0x0000ffab,0x1d7c0040,0xffaa4e75,0x2008206e
97 .long 0xffe4d088,0x2d40ffe4,0x2d48ffac,0x1d7c0001
98 .long 0xffab1d7c,0x0040ffaa,0x4e752008,0x206effe8
99 .long 0xd0882d40,0xffe82d48,0xffac1d7c,0x0002ffab
100 .long 0x1d7c0040,0xffaa4e75,0x2008206e,0xffecd088
101 .long 0x2d40ffec,0x2d48ffac,0x1d7c0003,0xffab1d7c
102 .long 0x0040ffaa,0x4e752008,0x206efff0,0xd0882d40
103 .long 0xfff02d48,0xffac1d7c,0x0004ffab,0x1d7c0040
104 .long 0xffaa4e75,0x2008206e,0xfff4d088,0x2d40fff4
105 .long 0x2d48ffac,0x1d7c0005,0xffab1d7c,0x0040ffaa
106 .long 0x4e752008,0x206efff8,0xd0882d40,0xfff82d48
107 .long 0xffac1d7c,0x0006ffab,0x1d7c0040,0xffaa4e75
108 .long 0x1d7c0004,0xffaa2008,0x206efffc,0xd0882d40
109 .long 0xfffc4e75,0x202effe0,0x2d40ffac,0x90882d40
110 .long 0xffe02040,0x1d7c0000,0xffab1d7c,0x0040ffaa
111 .long 0x4e75202e,0xffe42d40,0xffac9088,0x2d40ffe4
112 .long 0x20401d7c,0x0001ffab,0x1d7c0040,0xffaa4e75
113 .long 0x202effe8,0x2d40ffac,0x90882d40,0xffe82040
114 .long 0x1d7c0002,0xffab1d7c,0x0040ffaa,0x4e75202e
115 .long 0xffec2d40,0xffac9088,0x2d40ffec,0x20401d7c
116 .long 0x0003ffab,0x1d7c0040,0xffaa4e75,0x202efff0
117 .long 0x2d40ffac,0x90882d40,0xfff02040,0x1d7c0004
118 .long 0xffab1d7c,0x0040ffaa,0x4e75202e,0xfff42d40
119 .long 0xffac9088,0x2d40fff4,0x20401d7c,0x0005ffab
120 .long 0x1d7c0040,0xffaa4e75,0x202efff8,0x2d40ffac
121 .long 0x90882d40,0xfff82040,0x1d7c0006,0xffab1d7c
122 .long 0x0040ffaa,0x4e751d7c,0x0008ffaa,0x202efffc
123 .long 0x90882d40,0xfffc2040,0x4e75206e,0xffa454ae
124 .long 0xffa461ff,0xfffff9d4,0x4a8166ff,0xfffffd04
125 .long 0x3040d1ee,0xffe04e75,0x206effa4,0x54aeffa4
126 .long 0x61ffffff,0xf9b64a81,0x66ffffff,0xfce63040
127 .long 0xd1eeffe4,0x4e75206e,0xffa454ae,0xffa461ff
128 .long 0xfffff998,0x4a8166ff,0xfffffcc8,0x3040d1ee
129 .long 0xffe84e75,0x206effa4,0x54aeffa4,0x61ffffff
130 .long 0xf97a4a81,0x66ffffff,0xfcaa3040,0xd1eeffec
131 .long 0x4e75206e,0xffa454ae,0xffa461ff,0xfffff95c
132 .long 0x4a8166ff,0xfffffc8c,0x3040d1ee,0xfff04e75
133 .long 0x206effa4,0x54aeffa4,0x61ffffff,0xf93e4a81
134 .long 0x66ffffff,0xfc6e3040,0xd1eefff4,0x4e75206e
135 .long 0xffa454ae,0xffa461ff,0xfffff920,0x4a8166ff
136 .long 0xfffffc50,0x3040d1ee,0xfff84e75,0x206effa4
137 .long 0x54aeffa4,0x61ffffff,0xf9024a81,0x66ffffff
138 .long 0xfc323040,0xd1eefffc,0x4e752f01,0x206effa4
139 .long 0x54aeffa4,0x61ffffff,0xf8e24a81,0x66ffffff
140 .long 0xfc12221f,0x207614e0,0x08000008,0x670e48e7
141 .long 0x3c002a00,0x260860ff,0x000000ec,0x2f022200
142 .long 0xe9590241,0x000f2236,0x14c00800,0x000b6602
143 .long 0x48c12400,0xef5a0282,0x00000003,0xe5a949c0
144 .long 0xd081d1c0,0x241f4e75,0x1d7c0080,0xffaa206e
145 .long 0xffa44e75,0x206effa4,0x54aeffa4,0x61ffffff
146 .long 0xf87a4a81,0x66ffffff,0xfbaa3040,0x4e75206e
147 .long 0xffa458ae,0xffa461ff,0xfffff876,0x4a8166ff
148 .long 0xfffffb90,0x20404e75,0x206effa4,0x54aeffa4
149 .long 0x61ffffff,0xf8464a81,0x66ffffff,0xfb763040
150 .long 0xd1eeffa4,0x55884e75,0x206effa4,0x54aeffa4
151 .long 0x61ffffff,0xf8264a81,0x66ffffff,0xfb56206e
152 .long 0xffa45588,0x08000008,0x670e48e7,0x3c002a00
153 .long 0x260860ff,0x00000030,0x2f022200,0xe9590241
154 .long 0x000f2236,0x14c00800,0x000b6602,0x48c12400
155 .long 0xef5a0282,0x00000003,0xe5a949c0,0xd081d1c0
156 .long 0x241f4e75,0x08050006,0x67044282,0x6016e9c5
157 .long 0x24042436,0x24c00805,0x000b6602,0x48c2e9c5
158 .long 0x0542e1aa,0x08050007,0x67024283,0xe9c50682
159 .long 0x0c000002,0x6d346718,0x206effa4,0x58aeffa4
160 .long 0x61ffffff,0xf7ac4a81,0x66ffffff,0xfac66018
161 .long 0x206effa4,0x54aeffa4,0x61ffffff,0xf77e4a81
162 .long 0x66ffffff,0xfaae48c0,0xd680e9c5,0x07826700
163 .long 0x006a0c00,0x00026d34,0x6718206e,0xffa458ae
164 .long 0xffa461ff,0xfffff76a,0x4a8166ff,0xfffffa84
165 .long 0x601c206e,0xffa454ae,0xffa461ff,0xfffff73c
166 .long 0x4a8166ff,0xfffffa6c,0x48c06002,0x42802800
167 .long 0x08050002,0x67122043,0x61ffffff,0xf7764a81
168 .long 0x6624d082,0xd0846016,0xd6822043,0x61ffffff
169 .long 0xf7624a81,0x6610d084,0x6004d682,0x20032040
170 .long 0x4cdf003c,0x4e752043,0x203c0101,0x000160ff
171 .long 0xfffff9f0,0x322effa0,0x10010240,0x00072076
172 .long 0x04e0d0ee,0xffa20801,0x00076700,0x008c3001
173 .long 0xef580240,0x00072036,0x04c00801,0x00066752
174 .long 0x24002448,0xe19a2002,0x61ffffff,0xf71c4a81
175 .long 0x660000fc,0x544a204a,0xe19a2002,0x61ffffff
176 .long 0xf7084a81,0x660000e8,0x544a204a,0xe19a2002
177 .long 0x61ffffff,0xf6f44a81,0x660000d4,0x544a204a
178 .long 0xe19a2002,0x61ffffff,0xf6e04a81,0x660000c0
179 .long 0x4e752400,0x2448e048,0x61ffffff,0xf6cc4a81
180 .long 0x660000ac,0x544a204a,0x200261ff,0xfffff6ba
181 .long 0x4a816600,0x009a4e75,0x08010006,0x675c2448
182 .long 0x61ffffff,0xf6624a81,0x66000092,0x2400544a
183 .long 0x204a61ff,0xfffff650,0x4a816600,0x0080e14a
184 .long 0x1400544a,0x204a61ff,0xfffff63c,0x4a816600
185 .long 0x006ce18a,0x1400544a,0x204a61ff,0xfffff628
186 .long 0x4a816600,0x0058e18a,0x1400122e,0xffa0e209
187 .long 0x02410007,0x2d8214c0,0x4e752448,0x61ffffff
188 .long 0xf6064a81,0x66000036,0x2400544a,0x204a61ff
189 .long 0xfffff5f4,0x4a816600,0x0024e14a,0x1400122e
190 .long 0xffa0e209,0x02410007,0x3d8214c2,0x4e75204a
191 .long 0x203c00a1,0x000160ff,0xfffff8a8,0x204a203c
192 .long 0x01210001,0x60ffffff,0xf89a61ff,0xfffff914
193 .long 0x102effa2,0xe9180240,0x000f2436,0x04c00c2e
194 .long 0x0002ffa0,0x6d506728,0x244861ff,0xfffff5c4
195 .long 0x4a816600,0x009e2600,0x588a204a,0x61ffffff
196 .long 0xf5b24a81,0x6600008c,0x22002003,0x60000048
197 .long 0x244861ff,0xfffff59c,0x4a816600,0x00763200
198 .long 0x484048c0,0x48c1082e,0x0007ffa2,0x66000028
199 .long 0x48c26000,0x00222448,0x61ffffff,0xf5604a81
200 .long 0x6600005e,0x1200e048,0x49c049c1,0x082e0007
201 .long 0xffa26602,0x49c29480,0x42c30203,0x00049280
202 .long 0xb28242c4,0x86040203,0x0005382e,0xffa80204
203 .long 0x001a8803,0x3d44ffa8,0x082e0003,0xffa26602
204 .long 0x4e750804,0x00006602,0x4e751d7c,0x0010ffaa
205 .long 0x4e75204a,0x203c0101,0x000160ff,0xfffff7c4
206 .long 0x204a203c,0x01410001,0x60ffffff,0xf7b6102e
207 .long 0xffa10200,0x00386600,0x0208102e,0xffa10240
208 .long 0x00072e36,0x04c06700,0x00c0102e,0xffa3122e
209 .long 0xffa20240,0x0007e809,0x02410007,0x3d40ffb2
210 .long 0x3d41ffb4,0x2a3604c0,0x2c3614c0,0x082e0003
211 .long 0xffa2671a,0x4a875dee,0xffb06a02,0x44874a85
212 .long 0x5deeffb1,0x6a0844fc,0x00004086,0x40854a85
213 .long 0x66164a86,0x67000048,0xbe866306,0xcb466000
214 .long 0x00124c47,0x6005600a,0xbe85634e,0x61ff0000
215 .long 0x0068082e,0x0003ffa2,0x67244a2e,0xffb16702
216 .long 0x4485102e,0xffb0b12e,0xffb1670c,0x0c868000
217 .long 0x00006226,0x44866006,0x0806001f,0x661c44ee
218 .long 0xffa84a86,0x42eeffa8,0x302effb2,0x322effb4
219 .long 0x2d8504c0,0x2d8614c0,0x4e7508ee,0x0001ffa9
220 .long 0x08ae0000,0xffa94e75,0x022e001e,0xffa9002e
221 .long 0x0020ffaa,0x4e750c87,0x0000ffff,0x621e4281
222 .long 0x48454846,0x3a068ac7,0x32054846,0x3a068ac7
223 .long 0x48413205,0x42454845,0x2c014e75,0x42aeffbc
224 .long 0x422effb6,0x42810807,0x001f660e,0x52aeffbc
225 .long 0xe38fe38e,0xe3956000,0xffee2607,0x24054842
226 .long 0x4843b443,0x6606323c,0xffff600a,0x220582c3
227 .long 0x02810000,0xffff2f06,0x42464846,0x26072401
228 .long 0xc4c74843,0xc6c12805,0x98834844,0x30043806
229 .long 0x4a406600,0x000ab484,0x63045381,0x60de2f05
230 .long 0x2c014846,0x2a0761ff,0x0000006a,0x24052606
231 .long 0x2a1f2c1f,0x9c839b82,0x64ff0000,0x001a5381
232 .long 0x42822607,0x48434243,0xdc83db82,0x26074243
233 .long 0x4843da83,0x4a2effb6,0x66163d41,0xffb84281
234 .long 0x48454846,0x3a064246,0x50eeffb6,0x6000ff6c
235 .long 0x3d41ffba,0x3c054846,0x48452e2e,0xffbc670a
236 .long 0x5387e28d,0xe29651cf,0xfffa2a06,0x2c2effb8
237 .long 0x4e752406,0x26062805,0x48434844,0xccc5cac3
238 .long 0xc4c4c6c4,0x42844846,0xdc45d744,0xdc42d744
239 .long 0x48464245,0x42424845,0x4842da82,0xda834e75
240 .long 0x700461ff,0xfffff61c,0x0c2e0080,0xffaa6712
241 .long 0x244861ff,0xfffff2dc,0x4a81661e,0x2e006000
242 .long 0xfde658ae,0xffa461ff,0xfffff286,0x4a8166ff
243 .long 0xfffff5a0,0x2e006000,0xfdce61ff,0xfffff5ce
244 .long 0x204a203c,0x01010001,0x60ffffff,0xf556102e
245 .long 0xffa10c00,0x00076e00,0x00b40240,0x00072636
246 .long 0x04c0342e,0xffa24241,0x1202e95a,0x02420007
247 .long 0x283624c0,0x4a846700,0x00884a83,0x67000082
248 .long 0x422effb0,0x082e0003,0xffa26718,0x4a836c08
249 .long 0x4483002e,0x0001ffb0,0x4a846c08,0x44840a2e
250 .long 0x0001ffb0,0x2a032c03,0x2e044846,0x4847c6c4
251 .long 0xc8c6cac7,0xccc74287,0x4843d644,0xdd87d645
252 .long 0xdd874843,0x42444245,0x48444845,0xd885d886
253 .long 0x4a2effb0,0x67084683,0x46845283,0xd9872d83
254 .long 0x24c044fc,0x00002d84,0x14c042c7,0x02070008
255 .long 0x1c2effa9,0x02060010,0x8c071d46,0xffa94e75
256 .long 0x42b624c0,0x42b614c0,0x7e0460e4,0x700461ff
257 .long 0xfffff510,0x0c2e0080,0xffaa6714,0x244861ff
258 .long 0xfffff1d0,0x4a816600,0x00202600,0x6000ff34
259 .long 0x58aeffa4,0x61ffffff,0xf1784a81,0x66ffffff
260 .long 0xf4922600,0x6000ff1c,0x61ffffff,0xf4c0204a
261 .long 0x203c0101,0x000160ff,0xfffff448,0x2d40ffb4
262 .long 0x2200e958,0x0240000f,0x227604c0,0x2d49ffb0
263 .long 0x2001ec49,0x02410007,0x2a3614c0,0x02400007
264 .long 0x263604c0,0x3d40ffba,0x302effa2,0x2200e958
265 .long 0x0240000f,0x207604c0,0x2d48ffbc,0x2001ec49
266 .long 0x02410007,0x283614c0,0x02400007,0x243604c0
267 .long 0x3d40ffb8,0x082e0001,0xffa056c7,0x082e0005
268 .long 0x000456c6,0x24482649,0x22072006,0x61ffffff
269 .long 0xf05c204a,0x4a8066ff,0x000001c8,0x22072006
270 .long 0x204b61ff,0xfffff046,0x204b4a80,0x660a204a
271 .long 0x224b60ff,0xfffff020,0x2f002207,0x2006204a
272 .long 0x61ffffff,0xf03e201f,0x204b60ff,0x00000194
273 .long 0x082e0001,0xffa06648,0x44eeffa8,0xb0426602
274 .long 0xb24342ee,0xffa84a04,0x6610362e,0xffba3d81
275 .long 0x34c2342e,0xffb83d80,0x24c2082e,0x00050004
276 .long 0x56c22002,0x51c1206e,0xffbc61ff,0xffffeff4
277 .long 0x200251c1,0x206effb0,0x61ffffff,0xefe64e75
278 .long 0x44eeffa8,0xb0826602,0xb28342ee,0xffa84a04
279 .long 0x6610362e,0xffba2d81,0x34c0342e,0xffb82d80
280 .long 0x24c0082e,0x00050004,0x56c22002,0x50c1206e
281 .long 0xffbc61ff,0xffffefac,0x200250c1,0x206effb0
282 .long 0x61ffffff,0xef9e4e75,0x202effb4,0x6000feae
283 .long 0x082e0001,0xffa06610,0x700261ff,0xfffff364
284 .long 0x2d48ffb4,0x51c7600e,0x700461ff,0xfffff354
285 .long 0x2d48ffb4,0x50c7302e,0xffa22200,0xec480240
286 .long 0x00072436,0x04c00241,0x00072836,0x14c03d41
287 .long 0xffb8082e,0x00050004,0x56c62448,0x22072006
288 .long 0x61ffffff,0xef284a80,0x66000096,0x204a60ff
289 .long 0xffffeeee,0x082e0001,0xffa0662c,0x44eeffa8
290 .long 0xb04442ee,0xffa84a01,0x6608362e,0xffb83d80
291 .long 0x34c2206e,0xffb451c1,0x082e0005,0x000456c0
292 .long 0x61ffffff,0xeefe4e75,0x44eeffa8,0xb08442ee
293 .long 0xffa84a01,0x6608362e,0xffb82d80,0x34c0206e
294 .long 0xffb450c1,0x082e0005,0x000456c0,0x61ffffff
295 .long 0xeed24e75,0x4e7b6000,0x4e7b6001,0x0c2e00fc
296 .long 0xffa167ff,0xffffff24,0x206effb4,0x082e0001
297 .long 0xffa056c7,0x6000ff40,0x4e7b6000,0x4e7b6001
298 .long 0x24482f00,0x61ffffff,0xf264201f,0x588f518f
299 .long 0x518e721a,0x41ef0008,0x43ef0000,0x22d851c9
300 .long 0xfffc3d7c,0x4008000a,0x2d4a000c,0x2d400010
301 .long 0x4cee3fff,0xffc04e5e,0x60ffffff,0xedf84280
302 .long 0x43fb0170,0x000005ae,0xb3c86d0e,0x43fb0170
303 .long 0x00000010,0xb1c96d02,0x4e7570ff,0x4e754a06
304 .long 0x66047001,0x60027005,0x4a076700,0x01e42448
305 .long 0x26492848,0x2a49568c,0x568d220a,0x40c7007c
306 .long 0x07004e7a,0x60004e7b,0x00004e7b,0x0001f58a
307 .long 0xf58cf58b,0xf58df46a,0xf46cf46b,0xf46d2441
308 .long 0x56812841,0xf5caf5cc,0x247c8000,0x0000267c
309 .long 0xa0000000,0x287c0000,0x00002008,0x02000003
310 .long 0x671c0c00,0x00026700,0x00966000,0x010251fc
311 .long 0x4e7ba008,0x0e911000,0x0e900000,0x6002600e
312 .long 0xb082661c,0xb2836618,0x0e915800,0x6002600e
313 .long 0x4e7bb008,0x0e904800,0x4e7bc008,0x6034600e
314 .long 0x4e7bb008,0x0e900800,0x4e7bc008,0x6012600e
315 .long 0x4e714e71,0x4e714e71,0x4e714e71,0x4e7160b0
316 .long 0x4e7b6000,0x4e7b6001,0x46c751c4,0x60ffffff
317 .long 0xfd424e7b,0x60004e7b,0x600146c7,0x50c460ff
318 .long 0xfffffd30,0x51fc51fc,0x51fc51fc,0x51fc51fc
319 .long 0x4e7ba008,0x0e911000,0x0e900000,0x6002600e
320 .long 0xb082662c,0xb2836628,0x0e915800,0x6002600e
321 .long 0x48440e58,0x48004e7b,0xb0084844,0x6002600e
322 .long 0x0e504800,0x4e7bc008,0x6000ffa8,0x4e71600e
323 .long 0x48400e58,0x08004e7b,0xb0084840,0x6002600e
324 .long 0x0e500800,0x4e7bc008,0x6000ff76,0x4e71600e
325 .long 0x4e714e71,0x4e714e71,0x4e714e71,0x4e716090
326 .long 0x4e7ba008,0x0e911000,0x0e900000,0x6002600e
327 .long 0xb082663c,0xb2836638,0x0e915800,0x6002600e
328 .long 0xe19c0e18,0x48004844,0x0e584800,0x6002600e
329 .long 0xe19c4e7b,0xb0080e10,0x48006004,0x4e71600e
330 .long 0x4e7bc008,0x6000ff2c,0x4e714e71,0x4e71600e
331 .long 0xe1980e18,0x08004840,0x0e580800,0x6002600e
332 .long 0xe1984e7b,0xb0080e10,0x08006004,0x4e71600e
333 .long 0x4e7bc008,0x6000feea,0x4e714e71,0x4e71600c
334 .long 0x4e714e71,0x4e714e71,0x4e714e71,0x6000ff72
335 .long 0x24482649,0x28482a49,0x528c528d,0x220a40c7
336 .long 0x007c0700,0x4e7a6000,0x4e7b0000,0x4e7b0001
337 .long 0xf58af58c,0xf58bf58d,0xf46af46c,0xf46bf46d
338 .long 0x24415681,0x2841f5ca,0xf5cc247c,0x80000000
339 .long 0x267ca000,0x0000287c,0x00000000,0x20080800
340 .long 0x00006600,0x009a6016,0x51fc51fc,0x51fc51fc
341 .long 0x4e7ba008,0x0e511000,0x0e500000,0x6002600e
342 .long 0xb042661c,0xb2436618,0x0e515800,0x6002600e
343 .long 0x4e7bb008,0x0e504800,0x4e7bc008,0x6034600e
344 .long 0x4e7bb008,0x0e500800,0x4e7bc008,0x6012600e
345 .long 0x4e714e71,0x4e714e71,0x4e714e71,0x4e7160b0
346 .long 0x4e7b6000,0x4e7b6001,0x46c751c4,0x60ffffff
347 .long 0xfb624e7b,0x60004e7b,0x600146c7,0x50c460ff
348 .long 0xfffffb50,0x51fc51fc,0x51fc51fc,0x51fc51fc
349 .long 0x4e7ba008,0x0e511000,0x0e500000,0x6002600e
350 .long 0xb042662c,0xb2436628,0x0e515800,0x6002600e
351 .long 0xe09c0e18,0x48004e7b,0xb008e19c,0x6002600e
352 .long 0x0e104800,0x4e7bc008,0x6000ffa8,0x4e71600e
353 .long 0xe0980e18,0x08004e7b,0xb008e198,0x6002600e
354 .long 0x0e100800,0x4e7bc008,0x6000ff76,0x4e71600e
355 .long 0x4e714e71,0x4e714e71,0x4e714e71,0x4e716090
356 .long 0x4a066604,0x70016002,0x70054a07,0x660000c6
357 .long 0x22482448,0x528a2602,0xe04a40c7,0x007c0700
358 .long 0x4e7a6000,0x4e7b0000,0x4e7b0001,0xf589f58a
359 .long 0xf469f46a,0x227c8000,0x0000247c,0xa0000000
360 .long 0x267c0000,0x00006016,0x51fc51fc,0x51fc51fc
361 .long 0x4e7b9008,0x0e500000,0xb0446624,0x6002600e
362 .long 0x0e182800,0x4e7ba008,0x0e103800,0x6002600e
363 .long 0x4e7bb008,0x604c4e71,0x4e714e71,0x4e71600e
364 .long 0xe0980e18,0x08004e7b,0xa008e198,0x6002600e
365 .long 0x0e100800,0x4e7bb008,0x60164e71,0x4e71600e
366 .long 0x4e714e71,0x4e714e71,0x4e714e71,0x4e7160a0
367 .long 0x4e7b6000,0x4e7b6001,0x46c751c1,0x60ffffff
368 .long 0xfb164e7b,0x60004e7b,0x600146c7,0x50c160ff
369 .long 0xfffffb04,0x22482448,0x568a2208,0x08010000
370 .long 0x660000c2,0x26024842,0x40c7007c,0x07004e7a
371 .long 0x60004e7b,0x00004e7b,0x0001f589,0xf58af469
372 .long 0xf46a227c,0x80000000,0x247ca000,0x0000267c
373 .long 0x00000000,0x601851fc,0x51fc51fc,0x51fc51fc
374 .long 0x4e7b9008,0x0e900000,0xb0846624,0x6002600e
375 .long 0x0e582800,0x4e7ba008,0x0e503800,0x6002600e
376 .long 0x4e7bb008,0x604c4e71,0x4e714e71,0x4e71600e
377 .long 0x48400e58,0x08004840,0x4e7ba008,0x6002600e
378 .long 0x0e500800,0x4e7bb008,0x60164e71,0x4e71600e
379 .long 0x4e714e71,0x4e714e71,0x4e714e71,0x4e7160a0
380 .long 0x4e7b6000,0x4e7b6001,0x46c751c1,0x60ffffff
381 .long 0xfa464e7b,0x60004e7b,0x600146c7,0x50c160ff
382 .long 0xfffffa34,0x2a02e08a,0x26024842,0x40c7007c
383 .long 0x07004e7a,0x60004e7b,0x00004e7b,0x0001f589
384 .long 0xf58af469,0xf46a227c,0x80000000,0x247ca000
385 .long 0x0000267c,0x00000000,0x601451fc,0x51fc51fc
386 .long 0x4e7b9008,0x0e900000,0xb0846624,0x6002600e
387 .long 0x0e182800,0x0e583800,0x4e7ba008,0x6002600e
388 .long 0x0e105800,0x4e7bb008,0x6000ff88,0x4e71600e
389 .long 0xe1980e18,0x08004840,0x0e580800,0x6002600e
390 .long 0xe1984e7b,0xa0080e10,0x08006004,0x4e71600e
391 .long 0x4e7bb008,0x6000ff4a,0x4e714e71,0x4e71600e
392 .long 0x4e714e71,0x4e714e71,0x4e714e71,0x4e716090
diff --git a/arch/m68k/ifpsp060/itest.sa b/arch/m68k/ifpsp060/itest.sa
new file mode 100644
index 000000000000..7b15eaf63809
--- /dev/null
+++ b/arch/m68k/ifpsp060/itest.sa
@@ -0,0 +1,1281 @@
1 dc.l $60ff0000,$005c5465,$7374696e,$67203638
2 dc.l $30363020,$49535020,$73746172,$7465643a
3 dc.l $0a007061,$73736564,$0a002066,$61696c65
4 dc.l $640a0000,$4a80660e,$487affe8,$61ff0000
5 dc.l $4f9a588f,$4e752f01,$61ff0000,$4fa4588f
6 dc.l $487affd8,$61ff0000,$4f82588f,$4e754e56
7 dc.l $ff6048e7,$3f3c487a,$ff9e61ff,$00004f6c
8 dc.l $588f42ae,$ff78487b,$01700000,$00ea61ff
9 dc.l $00004f58,$588f61ff,$000000f0,$61ffffff
10 dc.l $ffa642ae,$ff78487b,$01700000,$0af661ff
11 dc.l $00004f38,$588f61ff,$00000af8,$61ffffff
12 dc.l $ff8642ae,$ff78487b,$01700000,$179c61ff
13 dc.l $00004f18,$588f61ff,$0000179c,$61ffffff
14 dc.l $ff6642ae,$ff78487b,$01700000,$038661ff
15 dc.l $00004ef8,$588f61ff,$00000380,$61ffffff
16 dc.l $ff4642ae,$ff78487b,$01700000,$202c61ff
17 dc.l $00004ed8,$588f2d7c,$00000002,$ff7461ff
18 dc.l $0000202c,$61ffffff,$ff1e42ae,$ff78487b
19 dc.l $01700000,$0d7c61ff,$00004eb0,$588f61ff
20 dc.l $00000d74,$61ffffff,$fefe42ae,$ff78487b
21 dc.l $01700000,$0f8e61ff,$00004e90,$588f61ff
22 dc.l $00000f88,$61ffffff,$fede4cdf,$3cfc4e5e
23 dc.l $4e750936,$342d6269,$74206d75,$6c746970
24 dc.l $6c792e2e,$2e0051fc,$52aeff78,$4cfb3fff
25 dc.l $01700000,$4e184281,$243c9999,$9999263c
26 dc.l $88888888,$3d7c0004,$ff7c44fc,$000048ee
27 dc.l $7fffff80,$4c013402,$42eeff7e,$48ee7fff
28 dc.l $ffc042ae,$ff8842ae,$ff8c61ff,$00004da6
29 dc.l $4a0066ff,$00004dcc,$52aeff78,$4cfb3fff
30 dc.l $01700000,$4dc8223c,$77777777,$243c9999
31 dc.l $99997600,$3d7c0004,$ff7c44fc,$000048ee
32 dc.l $7fffff80,$4c013402,$42eeff7e,$48ee7fff
33 dc.l $ffc042ae,$ff8842ae,$ff8c61ff,$00004d56
34 dc.l $4a0066ff,$00004d7c,$52aeff78,$4cfb3fff
35 dc.l $01700000,$4d787210,$243c6666,$66663d7c
36 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff804c01
37 dc.l $240242ee,$ff7e48ee,$7fffffc0,$2d7c0000
38 dc.l $0006ff88,$61ff0000,$4d0c4a00,$66ff0000
39 dc.l $4d3252ae,$ff784cfb,$3fff0170,$00004d2e
40 dc.l $223c5555,$55557400,$76033d7c,$0000ff7c
41 dc.l $44fc0000,$48ee7fff,$ff804c01,$340242ee
42 dc.l $ff7e48ee,$7fffffc0,$2d7c0000,$0000ff88
43 dc.l $2d7cffff,$ffffff8c,$61ff0000,$4cb84a00
44 dc.l $66ff0000,$4cde52ae,$ff784cfb,$3fff0170
45 dc.l $00004cda,$223c4000,$00007400,$76043d7c
46 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff804c01
47 dc.l $340242ee,$ff7e48ee,$7fffffc0,$2d7c0000
48 dc.l $0001ff88,$2d7c0000,$0000ff8c,$61ff0000
49 dc.l $4c644a00,$66ff0000,$4c8a52ae,$ff784cfb
50 dc.l $3fff0170,$00004c86,$72ff7400,$76ff3d7c
51 dc.l $0008ff7c,$44fc0000,$48ee7fff,$ff804c01
52 dc.l $340242ee,$ff7e48ee,$7fffffc0,$2d7cffff
53 dc.l $fffeff88,$2d7c0000,$0001ff8c,$61ff0000
54 dc.l $4c144a00,$66ff0000,$4c3a52ae,$ff784cfb
55 dc.l $3fff0170,$00004c36,$223c8000,$00007400
56 dc.l $76ff3d7c,$0000ff7c,$44fc0000,$48ee7fff
57 dc.l $ff804c01,$3c0242ee,$ff7e48ee,$7fffffc0
58 dc.l $2d7c0000,$0000ff88,$2d7c8000,$0000ff8c
59 dc.l $61ff0000,$4bc04a00,$66ff0000,$4be652ae
60 dc.l $ff784cfb,$3fff0170,$00004be2,$223c8000
61 dc.l $00007400,$76013d7c,$0008ff7c,$44fc0000
62 dc.l $48ee7fff,$ff804c01,$3c0242ee,$ff7e48ee
63 dc.l $7fffffc0,$2d7cffff,$ffffff88,$2d7c8000
64 dc.l $0000ff8c,$61ff0000,$4b6c4a00,$66ff0000
65 dc.l $4b9252ae,$ff784cfb,$3fff0170,$00004b8e
66 dc.l $72017400,$263c8000,$00003d7c,$0008ff7c
67 dc.l $44fc0000,$48ee7fff,$ff804c01,$3c0242ee
68 dc.l $ff7e48ee,$7fffffc0,$2d7cffff,$ffffff88
69 dc.l $2d7c8000,$0000ff8c,$61ff0000,$4b184a00
70 dc.l $66ff0000,$4b3e222e,$ff784280,$4e75096d
71 dc.l $6f766570,$2e2e2e00,$52aeff78,$4cfb3fff
72 dc.l $01700000,$4b2841ee,$ff60303c,$aaaa4228
73 dc.l $00004228,$00023d7c,$001fff7c,$44fc001f
74 dc.l $48ee7fff,$ff800188,$000042ee,$ff7e48ee
75 dc.l $7fffffc0,$12280002,$e1491228,$0000b041
76 dc.l $66ff0000,$4ade61ff,$00004aaa,$4a0066ff
77 dc.l $00004ad0,$52aeff78,$4cfb3fff,$01700000
78 dc.l $4acc41ee,$ff64303c,$aaaa42a8,$fffc4290
79 dc.l $42a80004,$3d7c001f,$ff7c44fc,$001f48ee
80 dc.l $7fffff80,$01880000,$42eeff7e,$48ee7fff
81 dc.l $ffc04aa8,$fffc66ff,$00004a88,$4aa80004
82 dc.l $66ff0000,$4a7e0c90,$aa00aa00,$66ff0000
83 dc.l $4a7261ff,$00004a3e,$4a0066ff,$00004a64
84 dc.l $52aeff78,$4cfb3fff,$01700000,$4a6041ee
85 dc.l $ff60303c,$aaaa4228,$00004228,$00023d7c
86 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff800188
87 dc.l $000042ee,$ff7e48ee,$7fffffc0,$12280002
88 dc.l $e1491228,$0000b041,$66ff0000,$4a1661ff
89 dc.l $000049e2,$4a0066ff,$00004a08,$52aeff78
90 dc.l $4cfb3fff,$01700000,$4a0441ee,$ff60117c
91 dc.l $00aa0000,$117c00aa,$00023d7c,$001fff7c
92 dc.l $44fc001f,$48ee7fff,$ff800108,$000042ee
93 dc.l $ff7e48ee,$7fffffc0,$3d7caaaa,$ff82323c
94 dc.l $aaaab041,$66ff0000,$49ba61ff,$00004986
95 dc.l $4a0066ff,$000049ac,$52aeff78,$4cfb3fff
96 dc.l $01700000,$49a841ee,$ff60203c,$aaaaaaaa
97 dc.l $42280000,$42280002,$42280004,$42280006
98 dc.l $3d7c001f,$ff7c44fc,$001f48ee,$7fffff80
99 dc.l $01c80000,$42eeff7e,$48ee7fff,$ffc01228
100 dc.l $0006e189,$12280004,$e1891228,$0002e189
101 dc.l $12280000,$b08166ff,$00004948,$61ff0000
102 dc.l $49144a00,$66ff0000,$493a52ae,$ff784cfb
103 dc.l $3fff0170,$00004936,$41eeff64,$203caaaa
104 dc.l $aaaa42a8,$fffc4290,$42a80004,$42a80008
105 dc.l $3d7c001f,$ff7c44fc,$001f48ee,$7fffff80
106 dc.l $01c80000,$42eeff7e,$48ee7fff,$ffc04aa8
107 dc.l $fffc66ff,$000048ec,$4aa80008,$66ff0000
108 dc.l $48e20c90,$aa00aa00,$66ff0000,$48d60ca8
109 dc.l $aa00aa00,$000466ff,$000048c8,$61ff0000
110 dc.l $48944a00,$66ff0000,$48ba52ae,$ff784cfb
111 dc.l $3fff0170,$000048b6,$41eeff60,$117c00aa
112 dc.l $0000117c,$00aa0002,$117c00aa,$0004117c
113 dc.l $00aa0006,$3d7c001f,$ff7c44fc,$001f48ee
114 dc.l $7fffff80,$01480000,$42eeff7e,$48ee7fff
115 dc.l $ffc02d7c,$aaaaaaaa,$ff80223c,$aaaaaaaa
116 dc.l $b08166ff,$0000485c,$61ff0000,$48284a00
117 dc.l $66ff0000,$484e52ae,$ff784cfb,$3fff0170
118 dc.l $0000484a,$41eeff60,$3e3caaaa,$42280000
119 dc.l $42280002,$3d7c001f,$ff7c44fc,$001f48ee
120 dc.l $7fffff80,$0f880000,$42eeff7e,$48ee7fff
121 dc.l $ffc01228,$0002e149,$12280000,$be4166ff
122 dc.l $00004800,$61ff0000,$47cc4a00,$66ff0000
123 dc.l $47f252ae,$ff784cfb,$3fff0170,$000047ee
124 dc.l $41eeff60,$117c00aa,$0000117c,$00aa0002
125 dc.l $3d7c001f,$ff7c44fc,$001f48ee,$7fffff80
126 dc.l $0f080000,$42eeff7e,$48ee7fff,$ffc03d7c
127 dc.l $aaaaff9e,$323caaaa,$be4166ff,$000047a4
128 dc.l $61ff0000,$47704a00,$66ff0000,$479652ae
129 dc.l $ff784cfb,$3fff0170,$00004792,$41eeff60
130 dc.l $303caaaa,$42280000,$42280002,$3d7c001f
131 dc.l $ff7c44fc,$001f48ee,$7fffff80,$01880000
132 dc.l $42eeff7e,$48ee7fff,$ffc01228,$0002e149
133 dc.l $12280000,$b04166ff,$00004748,$61ff0000
134 dc.l $47144a00,$66ff0000,$473a52ae,$ff784cfb
135 dc.l $3fff0170,$00004736,$41eeff60,$303caaaa
136 dc.l $42280008,$4228000a,$3d7c001f,$ff7c44fc
137 dc.l $001f48ee,$7fffff80,$01880008,$42eeff7e
138 dc.l $48ee7fff,$ffc01228,$000ae149,$12280008
139 dc.l $b04166ff,$000046ec,$61ff0000,$46b84a00
140 dc.l $66ff0000,$46de52ae,$ff784cfb,$3fff0170
141 dc.l $000046da,$41eeff60,$117c00aa,$0008117c
142 dc.l $00aa000a,$3d7c001f,$ff7c44fc,$001f48ee
143 dc.l $7fffff80,$01080008,$42eeff7e,$48ee7fff
144 dc.l $ffc03d7c,$aaaaff82,$323caaaa,$b04166ff
145 dc.l $00004690,$61ff0000,$465c4a00,$66ff0000
146 dc.l $468252ae,$ff784cfb,$3fff0170,$0000467e
147 dc.l $41eeff60,$203caaaa,$aaaa4228,$00084228
148 dc.l $000a4228,$000c4228,$000e3d7c,$001fff7c
149 dc.l $44fc001f,$48ee7fff,$ff8001c8,$000842ee
150 dc.l $ff7e48ee,$7fffffc0,$1228000e,$e1891228
151 dc.l $000ce189,$1228000a,$e1891228,$0008b081
152 dc.l $66ff0000,$461e61ff,$000045ea,$4a0066ff
153 dc.l $00004610,$52aeff78,$4cfb3fff,$01700000
154 dc.l $460c41ee,$ff60117c,$00aa0008,$117c00aa
155 dc.l $000a117c,$00aa000c,$117c00aa,$000e3d7c
156 dc.l $001fff7c,$44fc001f,$48ee7fff,$ff800148
157 dc.l $000842ee,$ff7e48ee,$7fffffc0,$2d7caaaa
158 dc.l $aaaaff80,$223caaaa,$aaaab081,$66ff0000
159 dc.l $45b261ff,$0000457e,$4a0066ff,$000045a4
160 dc.l $52aeff78,$4cfb3fff,$01700000,$45a041ee
161 dc.l $ff68303c,$aaaa4228,$fff84228,$fffa3d7c
162 dc.l $001fff7c,$44fc001f,$48ee7fff,$ff800188
163 dc.l $fff842ee,$ff7e48ee,$7fffffc0,$1228fffa
164 dc.l $e1491228,$fff8b041,$66ff0000,$455661ff
165 dc.l $00004522,$4a0066ff,$00004548,$52aeff78
166 dc.l $4cfb3fff,$01700000,$454441ee,$ff68117c
167 dc.l $00aafff8,$117c00aa,$fffa3d7c,$001fff7c
168 dc.l $44fc001f,$48ee7fff,$ff800108,$fff842ee
169 dc.l $ff7e48ee,$7fffffc0,$3d7caaaa,$ff82323c
170 dc.l $aaaab041,$66ff0000,$44fa61ff,$000044c6
171 dc.l $4a0066ff,$000044ec,$52aeff78,$4cfb3fff
172 dc.l $01700000,$44e841ee,$ff68203c,$aaaaaaaa
173 dc.l $4228fff8,$4228fffa,$4228fffc,$42280000
174 dc.l $3d7c001f,$ff7c44fc,$001f48ee,$7fffff80
175 dc.l $01c8fff8,$42eeff7e,$48ee7fff,$ffc01228
176 dc.l $fffee189,$1228fffc,$e1891228,$fffae189
177 dc.l $1228fff8,$b08166ff,$00004488,$61ff0000
178 dc.l $44544a00,$66ff0000,$447a52ae,$ff784cfb
179 dc.l $3fff0170,$00004476,$41eeff68,$117c00aa
180 dc.l $fff8117c,$00aafffa,$117c00aa,$fffc117c
181 dc.l $00aa0000,$3d7c001f,$ff7c44fc,$001f48ee
182 dc.l $7fffff80,$0148fff8,$42eeff7e,$48ee7fff
183 dc.l $ffc02d7c,$aaaaaaaa,$ff80223c,$aaaaaaaa
184 dc.l $b08166ff,$0000441c,$61ff0000,$43e84a00
185 dc.l $66ff0000,$440e222e,$ff784280,$4e750936
186 dc.l $342d6269,$74206469,$76696465,$2e2e2e00
187 dc.l $52aeff78,$52aeff78,$4cfb3fff,$01700000
188 dc.l $43ec7201,$74007600,$3d7c0014,$ff7c44fc
189 dc.l $001f48ee,$7fffff80,$4c413402,$42eeff7e
190 dc.l $48ee7fff,$ffc061ff,$0000438a,$4a0066ff
191 dc.l $000043b0,$52aeff78,$4cfb3fff,$01700000
192 dc.l $43ac223c,$44444444,$7400263c,$55555555
193 dc.l $3d7c0010,$ff7c44fc,$001f48ee,$7fffff80
194 dc.l $4c413402,$42eeff7e,$48ee7fff,$ffc02d7c
195 dc.l $11111111,$ff882d7c,$00000001,$ff8c61ff
196 dc.l $00004332,$4a0066ff,$00004358,$52aeff78
197 dc.l $4cfb3fff,$01700000,$4354223c,$55555555
198 dc.l $7400263c,$44444444,$3d7c0014,$ff7c44fc
199 dc.l $001f48ee,$7fffff80,$4c413402,$42eeff7e
200 dc.l $48ee7fff,$ffc02d7c,$44444444,$ff882d7c
201 dc.l $00000000,$ff8c61ff,$000042da,$4a0066ff
202 dc.l $00004300,$52aeff78,$4cfb3fff,$01700000
203 dc.l $42fc223c,$11111111,$243c4444,$4444263c
204 dc.l $44444444,$3d7c001e,$ff7c44fc,$001d48ee
205 dc.l $7fffff80,$4c413402,$42eeff7e,$48ee7fff
206 dc.l $ffc061ff,$0000428e,$4a0066ff,$000042b4
207 dc.l $52aeff78,$4cfb3fff,$01700000,$42b072fe
208 dc.l $74017602,$3d7c001e,$ff7c44fc,$001d48ee
209 dc.l $7fffff80,$4c413c02,$42eeff7e,$48ee7fff
210 dc.l $ffc061ff,$0000424e,$4a0066ff,$00004274
211 dc.l $52aeff78,$4cfb3fff,$01700000,$427072fe
212 dc.l $74017600,$3d7c0018,$ff7c44fc,$001d48ee
213 dc.l $7fffff80,$4c413c02,$42eeff7e,$48ee7fff
214 dc.l $ffc02d7c,$00000000,$ff882d7c,$80000000
215 dc.l $ff8c61ff,$000041fe,$4a0066ff,$00004224
216 dc.l $52aeff78,$4cfb3fff,$01700000,$42207202
217 dc.l $74017600,$3d7c001e,$ff7c44fc,$001d48ee
218 dc.l $7fffff80,$4c413c02,$42eeff7e,$48ee7fff
219 dc.l $ffc061ff,$000041be,$4a0066ff,$000041e4
220 dc.l $52aeff78,$4cfb3fff,$01700000,$41e072ff
221 dc.l $74fe76ff,$3d7c0008,$ff7c44fc,$000048ee
222 dc.l $7fffff80,$4c413402,$42eeff7e,$48ee7fff
223 dc.l $ffc061ff,$0000417e,$4a0066ff,$000041a4
224 dc.l $52aeff78,$4cfb3fff,$01700000,$41a072ff
225 dc.l $74fe76ff,$3d7c0008,$ff7c44fc,$000048ee
226 dc.l $7fffff80,$4c7c2402,$ffffffff,$42eeff7e
227 dc.l $48ee7fff,$ffc02d7c,$ffffffff,$ff8861ff
228 dc.l $00004132,$4a0066ff,$00004158,$52aeff78
229 dc.l $4cfb3fff,$01700000,$4154223c,$0000ffff
230 dc.l $7401263c,$55555555,$3d7c0000,$ff7c44fc
231 dc.l $000048ee,$7fffff80,$4c413402,$42eeff7e
232 dc.l $48ee7fff,$ffc02d7c,$0000aaab,$ff882d7c
233 dc.l $00015556,$ff8c61ff,$000040da,$4a0066ff
234 dc.l $00004100,$222eff78,$42804e75,$09636173
235 dc.l $2e2e2e00,$52aeff78,$4cfb3fff,$01700000
236 dc.l $40ec41ee,$ff6130bc,$aaaa323c,$aaaa343c
237 dc.l $bbbb3d7c,$0014ff7c,$44fc0010,$48ee7fff
238 dc.l $ff800cd0,$008142ee,$ff7e3610,$3d7cbbbb
239 dc.l $ff8e48ee,$7fffffc0,$61ff0000,$40784a00
240 dc.l $66ff0000,$409e52ae,$ff784cfb,$3fff0170
241 dc.l $0000409a,$41eeff61,$30bceeee,$323caaaa
242 dc.l $343cbbbb,$3d7c0000,$ff7c44fc,$000048ee
243 dc.l $7fffff80,$0cd00081,$42eeff7e,$36103d7c
244 dc.l $eeeeff86,$3d7ceeee,$ff8e48ee,$7fffffc0
245 dc.l $61ff0000,$40204a00,$66ff0000,$404652ae
246 dc.l $ff784cfb,$3fff0170,$00004042,$41eeff62
247 dc.l $20bcaaaa,$aaaa223c,$aaaaaaaa,$243cbbbb
248 dc.l $bbbb3d7c,$0004ff7c,$44fc0000,$48ee7fff
249 dc.l $ff800ed0,$008142ee,$ff7e2610,$2d7cbbbb
250 dc.l $bbbbff8c,$48ee7fff,$ffc061ff,$00003fc6
251 dc.l $4a0066ff,$00003fec,$52aeff78,$4cfb3fff
252 dc.l $01700000,$3fe841ee,$ff6220bc,$eeeeeeee
253 dc.l $223caaaa,$aaaa243c,$bbbbbbbb,$3d7c0000
254 dc.l $ff7c44fc,$000048ee,$7fffff80,$0ed00081
255 dc.l $42eeff7e,$26102d7c,$eeeeeeee,$ff842d7c
256 dc.l $eeeeeeee,$ff8c48ee,$7fffffc0,$61ff0000
257 dc.l $3f644a00,$66ff0000,$3f8a52ae,$ff784cfb
258 dc.l $3fff0170,$00003f86,$41eeff61,$20bcaaaa
259 dc.l $aaaa223c,$aaaaaaaa,$243cbbbb,$bbbb3d7c
260 dc.l $0004ff7c,$44fc0000,$48ee7fff,$ff800ed0
261 dc.l $008142ee,$ff7e2610,$2d7cbbbb,$bbbbff8c
262 dc.l $48ee7fff,$ffc061ff,$00003f0a,$4a0066ff
263 dc.l $00003f30,$52aeff78,$4cfb3fff,$01700000
264 dc.l $3f2c41ee,$ff6120bc,$7fffffff,$223c8000
265 dc.l $0000243c,$bbbbbbbb,$3d7c001b,$ff7c44fc
266 dc.l $001048ee,$7fffff80,$0ed00081,$42eeff7e
267 dc.l $26102d7c,$7fffffff,$ff842d7c,$7fffffff
268 dc.l $ff8c48ee,$7fffffc0,$61ff0000,$3ea84a00
269 dc.l $66ff0000,$3ece222e,$ff784280,$4e750963
270 dc.l $6173322e,$2e2e0000,$52aeff78,$4cfb3fff
271 dc.l $01700000,$3eb841ee,$ff6043ee,$ff6420bc
272 dc.l $aaaaaaaa,$22bcbbbb,$bbbb223c,$aaaaaaaa
273 dc.l $243cbbbb,$bbbb263c,$cccccccc,$283cdddd
274 dc.l $dddd3d7c,$0014ff7c,$44fc0010,$48ee7fff
275 dc.l $ff800efc,$80c19102,$42eeff7e,$2a102c11
276 dc.l $2d7ccccc,$ccccff94,$2d7cdddd,$ddddff98
277 dc.l $48ee7fff,$ffc061ff,$00003e1a,$4a0066ff
278 dc.l $00003e40,$52aeff78,$4cfb3fff,$01700000
279 dc.l $3e3c41ee,$ff6143ee,$ff6520bc,$aaaaaaaa
280 dc.l $22bcbbbb,$bbbb223c,$aaaaaaaa,$243cbbbb
281 dc.l $bbbb263c,$cccccccc,$283cdddd,$dddd3d7c
282 dc.l $0014ff7c,$44fc0010,$48ee7fff,$ff800efc
283 dc.l $80c19102,$42eeff7e,$2a102c11,$2d7ccccc
284 dc.l $ccccff94,$2d7cdddd,$ddddff98,$48ee7fff
285 dc.l $ffc061ff,$00003d9e,$4a0066ff,$00003dc4
286 dc.l $52aeff78,$4cfb3fff,$01700000,$3dc041ee
287 dc.l $ff6243ee,$ff6620bc,$aaaaaaaa,$22bcbbbb
288 dc.l $bbbb223c,$aaaaaaaa,$243cbbbb,$bbbb263c
289 dc.l $cccccccc,$283cdddd,$dddd3d7c,$0014ff7c
290 dc.l $44fc0010,$48ee7fff,$ff800efc,$80c19102
291 dc.l $42eeff7e,$2a102c11,$2d7ccccc,$ccccff94
292 dc.l $2d7cdddd,$ddddff98,$48ee7fff,$ffc061ff
293 dc.l $00003d22,$4a0066ff,$00003d48,$52aeff78
294 dc.l $4cfb3fff,$01700000,$3d4441ee,$ff6043ee
295 dc.l $ff6420bc,$eeeeeeee,$22bcbbbb,$bbbb223c
296 dc.l $aaaaaaaa,$243cbbbb,$bbbb263c,$cccccccc
297 dc.l $283cdddd,$dddd3d7c,$0000ff7c,$44fc0000
298 dc.l $48ee7fff,$ff800efc,$80c19102,$42eeff7e
299 dc.l $2a102c11,$2d7ceeee,$eeeeff84,$2d7cbbbb
300 dc.l $bbbbff88,$2d7ceeee,$eeeeff94,$2d7cbbbb
301 dc.l $bbbbff98,$48ee7fff,$ffc061ff,$00003c96
302 dc.l $4a0066ff,$00003cbc,$52aeff78,$4cfb3fff
303 dc.l $01700000,$3cb841ee,$ff6143ee,$ff6520bc
304 dc.l $eeeeeeee,$22bcbbbb,$bbbb223c,$aaaaaaaa
305 dc.l $243cbbbb,$bbbb263c,$cccccccc,$283cdddd
306 dc.l $dddd3d7c,$0000ff7c,$44fc0000,$48ee7fff
307 dc.l $ff800efc,$80c19102,$42eeff7e,$2a102c11
308 dc.l $2d7ceeee,$eeeeff84,$2d7cbbbb,$bbbbff88
309 dc.l $2d7ceeee,$eeeeff94,$2d7cbbbb,$bbbbff98
310 dc.l $48ee7fff,$ffc061ff,$00003c0a,$4a0066ff
311 dc.l $00003c30,$52aeff78,$4cfb3fff,$01700000
312 dc.l $3c2c41ee,$ff6243ee,$ff6620bc,$eeeeeeee
313 dc.l $22bcbbbb,$bbbb223c,$aaaaaaaa,$243cbbbb
314 dc.l $bbbb263c,$cccccccc,$283cdddd,$dddd3d7c
315 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff800efc
316 dc.l $80c19102,$42eeff7e,$2a102c11,$2d7ceeee
317 dc.l $eeeeff84,$2d7cbbbb,$bbbbff88,$2d7ceeee
318 dc.l $eeeeff94,$2d7cbbbb,$bbbbff98,$48ee7fff
319 dc.l $ffc061ff,$00003b7e,$4a0066ff,$00003ba4
320 dc.l $52aeff78,$4cfb3fff,$01700000,$3ba041ee
321 dc.l $ff6043ee,$ff6420bc,$aaaaaaaa,$22bceeee
322 dc.l $eeee223c,$aaaaaaaa,$243cbbbb,$bbbb263c
323 dc.l $cccccccc,$283cdddd,$dddd3d7c,$0000ff7c
324 dc.l $44fc0000,$48ee7fff,$ff800efc,$80c19102
325 dc.l $42eeff7e,$2a102c11,$2d7caaaa,$aaaaff84
326 dc.l $2d7ceeee,$eeeeff88,$2d7caaaa,$aaaaff94
327 dc.l $2d7ceeee,$eeeeff98,$48ee7fff,$ffc061ff
328 dc.l $00003af2,$4a0066ff,$00003b18,$52aeff78
329 dc.l $4cfb3fff,$01700000,$3b1441ee,$ff6143ee
330 dc.l $ff6520bc,$aaaaaaaa,$22bceeee,$eeee223c
331 dc.l $aaaaaaaa,$243cbbbb,$bbbb263c,$cccccccc
332 dc.l $283cdddd,$dddd3d7c,$0000ff7c,$44fc0000
333 dc.l $48ee7fff,$ff800efc,$80c19102,$42eeff7e
334 dc.l $2a102c11,$2d7caaaa,$aaaaff84,$2d7ceeee
335 dc.l $eeeeff88,$2d7caaaa,$aaaaff94,$2d7ceeee
336 dc.l $eeeeff98,$48ee7fff,$ffc061ff,$00003a66
337 dc.l $4a0066ff,$00003a8c,$52aeff78,$4cfb3fff
338 dc.l $01700000,$3a8841ee,$ff6243ee,$ff6620bc
339 dc.l $aaaaaaaa,$22bc7fff,$ffff223c,$aaaaaaaa
340 dc.l $243c8000,$0000263c,$cccccccc,$283cdddd
341 dc.l $dddd3d7c,$000bff7c,$44fc0000,$48ee7fff
342 dc.l $ff800efc,$80c19102,$42eeff7e,$2a102c11
343 dc.l $2d7caaaa,$aaaaff84,$2d7c7fff,$ffffff88
344 dc.l $2d7caaaa,$aaaaff94,$2d7c7fff,$ffffff98
345 dc.l $48ee7fff,$ffc061ff,$000039da,$4a0066ff
346 dc.l $00003a00,$52aeff78,$4cfb3fff,$01700000
347 dc.l $39fc41ee,$ff6043ee,$ff6430bc,$aaaa32bc
348 dc.l $bbbb323c,$aaaa343c,$bbbb363c,$cccc383c
349 dc.l $dddd3d7c,$0014ff7c,$44fc0010,$48ee7fff
350 dc.l $ff800cfc,$80c19102,$42eeff7e,$3a103c11
351 dc.l $3d7ccccc,$ff963d7c,$ddddff9a,$48ee7fff
352 dc.l $ffc061ff,$0000396e,$4a0066ff,$00003994
353 dc.l $52aeff78,$4cfb3fff,$01700000,$399041ee
354 dc.l $ff6143ee,$ff6530bc,$aaaa32bc,$bbbb323c
355 dc.l $aaaa343c,$bbbb363c,$cccc383c,$dddd3d7c
356 dc.l $0004ff7c,$44fc0000,$48ee7fff,$ff800cfc
357 dc.l $80c19102,$42eeff7e,$3a103c11,$3d7ccccc
358 dc.l $ff963d7c,$ddddff9a,$48ee7fff,$ffc061ff
359 dc.l $00003902,$4a0066ff,$00003928,$52aeff78
360 dc.l $4cfb3fff,$01700000,$392441ee,$ff6043ee
361 dc.l $ff6430bc,$eeee32bc,$bbbb323c,$aaaa343c
362 dc.l $bbbb363c,$cccc383c,$dddd3d7c,$0000ff7c
363 dc.l $44fc0000,$48ee7fff,$ff800cfc,$80c19102
364 dc.l $42eeff7e,$3a103c11,$3d7ceeee,$ff863d7c
365 dc.l $bbbbff8a,$3d7ceeee,$ff963d7c,$bbbbff9a
366 dc.l $48ee7fff,$ffc061ff,$0000388a,$4a0066ff
367 dc.l $000038b0,$52aeff78,$4cfb3fff,$01700000
368 dc.l $38ac41ee,$ff6143ee,$ff6530bc,$eeee32bc
369 dc.l $bbbb323c,$aaaa343c,$bbbb363c,$cccc383c
370 dc.l $dddd3d7c,$0000ff7c,$44fc0000,$48ee7fff
371 dc.l $ff800cfc,$80c19102,$42eeff7e,$3a103c11
372 dc.l $3d7ceeee,$ff863d7c,$bbbbff8a,$3d7ceeee
373 dc.l $ff963d7c,$bbbbff9a,$48ee7fff,$ffc061ff
374 dc.l $00003812,$4a0066ff,$00003838,$52aeff78
375 dc.l $4cfb3fff,$01700000,$383441ee,$ff6043ee
376 dc.l $ff6430bc,$aaaa32bc,$eeee323c,$aaaa343c
377 dc.l $bbbb363c,$cccc383c,$dddd3d7c,$0000ff7c
378 dc.l $44fc0000,$48ee7fff,$ff800cfc,$80c19102
379 dc.l $42eeff7e,$3a103c11,$3d7caaaa,$ff863d7c
380 dc.l $eeeeff8a,$3d7caaaa,$ff963d7c,$eeeeff9a
381 dc.l $48ee7fff,$ffc061ff,$0000379a,$4a0066ff
382 dc.l $000037c0,$52aeff78,$4cfb3fff,$01700000
383 dc.l $37bc41ee,$ff6143ee,$ff6530bc,$aaaa32bc
384 dc.l $7fff323c,$aaaa343c,$8000363c,$cccc383c
385 dc.l $dddd3d7c,$001bff7c,$44fc0010,$48ee7fff
386 dc.l $ff800cfc,$80c19102,$42eeff7e,$3a103c11
387 dc.l $3d7caaaa,$ff863d7c,$7fffff8a,$3d7caaaa
388 dc.l $ff963d7c,$7fffff9a,$48ee7fff,$ffc061ff
389 dc.l $00003722,$4a0066ff,$00003748,$222eff78
390 dc.l $42804e75,$09636d70,$322c6368,$6b322e2e
391 dc.l $2e0051fc,$52aeff78,$4cfb3fff,$01700000
392 dc.l $372c3d7c,$2040ff60,$223c1111,$11203d7c
393 dc.l $0004ff7c,$44fc0000,$48ee7fff,$ff8000ee
394 dc.l $1000ff60,$42eeff7e,$48ee7fff,$ffc061ff
395 dc.l $000036c2,$4a0066ff,$000036e8,$52aeff78
396 dc.l $4cfb3fff,$01700000,$36e43d7c,$2040ff60
397 dc.l $227c0000,$00403d7c,$0004ff7c,$44fc0000
398 dc.l $48ee7fff,$ff8000ee,$9000ff60,$42eeff7e
399 dc.l $48ee7fff,$ffc061ff,$0000367a,$4a0066ff
400 dc.l $000036a0,$52aeff78,$4cfb3fff,$01700000
401 dc.l $369c3d7c,$2040ff60,$223c1111,$11303d7c
402 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff8000ee
403 dc.l $1800ff60,$42eeff7e,$48ee7fff,$ffc061ff
404 dc.l $00003632,$4a0066ff,$00003658,$52aeff78
405 dc.l $4cfb3fff,$01700000,$36543d7c,$2040ff60
406 dc.l $227c0000,$00103d7c,$0001ff7c,$44fc0000
407 dc.l $48ee7fff,$ff8000ee,$9000ff60,$42eeff7e
408 dc.l $48ee7fff,$ffc061ff,$000035ea,$4a0066ff
409 dc.l $00003610,$52aeff78,$4cfb3fff,$01700000
410 dc.l $360c3d7c,$2040ff60,$223c1111,$11503d7c
411 dc.l $0001ff7c,$44fc0000,$48ee7fff,$ff8000ee
412 dc.l $1000ff60,$42eeff7e,$48ee7fff,$ffc061ff
413 dc.l $000035a2,$4a0066ff,$000035c8,$52aeff78
414 dc.l $4cfb3fff,$01700000,$35c43d7c,$2040ff60
415 dc.l $227c0000,$00903d7c,$0001ff7c,$44fc0000
416 dc.l $48ee7fff,$ff8000ee,$9000ff60,$42eeff7e
417 dc.l $48ee7fff,$ffc061ff,$0000355a,$4a0066ff
418 dc.l $00003580,$52aeff78,$4cfb3fff,$01700000
419 dc.l $357c2d7c,$2000a000,$ff60223c,$11112000
420 dc.l $3d7c0004,$ff7c44fc,$000048ee,$7fffff80
421 dc.l $02ee1000,$ff6042ee,$ff7e48ee,$7fffffc0
422 dc.l $61ff0000,$35104a00,$66ff0000,$353652ae
423 dc.l $ff784cfb,$3fff0170,$00003532,$2d7c2000
424 dc.l $a000ff60,$227cffff,$a0003d7c,$0004ff7c
425 dc.l $44fc0000,$48ee7fff,$ff8002ee,$9000ff60
426 dc.l $42eeff7e,$48ee7fff,$ffc061ff,$000034c6
427 dc.l $4a0066ff,$000034ec,$52aeff78,$4cfb3fff
428 dc.l $01700000,$34e82d7c,$2000a000,$ff60223c
429 dc.l $11113000,$3d7c0000,$ff7c44fc,$000048ee
430 dc.l $7fffff80,$02ee1800,$ff6042ee,$ff7e48ee
431 dc.l $7fffffc0,$61ff0000,$347c4a00,$66ff0000
432 dc.l $34a252ae,$ff784cfb,$3fff0170,$0000349e
433 dc.l $2d7c2000,$a000ff60,$227cffff,$90003d7c
434 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff8002ee
435 dc.l $9000ff60,$42eeff7e,$48ee7fff,$ffc061ff
436 dc.l $00003432,$4a0066ff,$00003458,$52aeff78
437 dc.l $4cfb3fff,$01700000,$34542d7c,$2000a000
438 dc.l $ff60223c,$11111000,$3d7c0001,$ff7c44fc
439 dc.l $000048ee,$7fffff80,$02ee1000,$ff6042ee
440 dc.l $ff7e48ee,$7fffffc0,$61ff0000,$33e84a00
441 dc.l $66ff0000,$340e52ae,$ff784cfb,$3fff0170
442 dc.l $0000340a,$2d7c2000,$a000ff60,$227cffff
443 dc.l $b0003d7c,$0001ff7c,$44fc0000,$48ee7fff
444 dc.l $ff8002ee,$9000ff60,$42eeff7e,$48ee7fff
445 dc.l $ffc061ff,$0000339e,$4a0066ff,$000033c4
446 dc.l $52aeff78,$4cfb3fff,$01700000,$33c02d7c
447 dc.l $a0000000,$ff602d7c,$c0000000,$ff64223c
448 dc.l $a0000000,$3d7c000c,$ff7c44fc,$000848ee
449 dc.l $7fffff80,$04ee1000,$ff6042ee,$ff7e48ee
450 dc.l $7fffffc0,$61ff0000,$334c4a00,$66ff0000
451 dc.l $337252ae,$ff784cfb,$3fff0170,$0000336e
452 dc.l $2d7ca000,$0000ff60,$2d7cc000,$0000ff64
453 dc.l $227cc000,$00003d7c,$000cff7c,$44fc0008
454 dc.l $48ee7fff,$ff8004ee,$9000ff60,$42eeff7e
455 dc.l $48ee7fff,$ffc061ff,$000032fa,$4a0066ff
456 dc.l $00003320,$52aeff78,$4cfb3fff,$01700000
457 dc.l $331c2d7c,$a0000000,$ff602d7c,$c0000000
458 dc.l $ff64223c,$b0000000,$3d7c0008,$ff7c44fc
459 dc.l $000848ee,$7fffff80,$04ee1800,$ff6042ee
460 dc.l $ff7e48ee,$7fffffc0,$61ff0000,$32a84a00
461 dc.l $66ff0000,$32ce52ae,$ff784cfb,$3fff0170
462 dc.l $000032ca,$2d7ca000,$0000ff60,$2d7cc000
463 dc.l $0000ff64,$227c1000,$00003d7c,$0009ff7c
464 dc.l $44fc0008,$48ee7fff,$ff8004ee,$9000ff60
465 dc.l $42eeff7e,$48ee7fff,$ffc061ff,$00003256
466 dc.l $4a0066ff,$0000327c,$52aeff78,$4cfb3fff
467 dc.l $01700000,$32782d7c,$a0000000,$ff602d7c
468 dc.l $c0000000,$ff64223c,$90000000,$3d7c0009
469 dc.l $ff7c44fc,$000848ee,$7fffff80,$04ee1000
470 dc.l $ff6042ee,$ff7e48ee,$7fffffc0,$61ff0000
471 dc.l $32044a00,$66ff0000,$322a52ae,$ff784cfb
472 dc.l $3fff0170,$00003226,$2d7ca000,$0000ff60
473 dc.l $2d7cc000,$0000ff64,$227cd000,$00003d7c
474 dc.l $0009ff7c,$44fc0008,$48ee7fff,$ff8004ee
475 dc.l $9000ff60,$42eeff7e,$48ee7fff,$ffc061ff
476 dc.l $000031b2,$4a0066ff,$000031d8,$52aeff78
477 dc.l $4cfb3fff,$01700000,$31d43d7c,$a040ff60
478 dc.l $223c1111,$11a03d7c,$0004ff7c,$44fc0000
479 dc.l $48ee7fff,$ff8000ee,$1000ff60,$42eeff7e
480 dc.l $48ee7fff,$ffc061ff,$0000316a,$4a0066ff
481 dc.l $00003190,$52aeff78,$4cfb3fff,$01700000
482 dc.l $318c3d7c,$a040ff60,$227c0000,$00403d7c
483 dc.l $0004ff7c,$44fc0000,$48ee7fff,$ff8000ee
484 dc.l $9800ff60,$42eeff7e,$48ee7fff,$ffc061ff
485 dc.l $00003122,$4a0066ff,$00003148,$52aeff78
486 dc.l $4cfb3fff,$01700000,$31443d7c,$a040ff60
487 dc.l $223c1111,$11b03d7c,$0000ff7c,$44fc0000
488 dc.l $48ee7fff,$ff8000ee,$1000ff60,$42eeff7e
489 dc.l $48ee7fff,$ffc061ff,$000030da,$4a0066ff
490 dc.l $00003100,$52aeff78,$4cfb3fff,$01700000
491 dc.l $30fc3d7c,$a040ff60,$227c0000,$00103d7c
492 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff8000ee
493 dc.l $9000ff60,$42eeff7e,$48ee7fff,$ffc061ff
494 dc.l $00003092,$4a0066ff,$000030b8,$52aeff78
495 dc.l $4cfb3fff,$01700000,$30b43d7c,$a040ff60
496 dc.l $223c1111,$11903d7c,$0001ff7c,$44fc0000
497 dc.l $48ee7fff,$ff8000ee,$1000ff60,$42eeff7e
498 dc.l $48ee7fff,$ffc061ff,$0000304a,$4a0066ff
499 dc.l $00003070,$52aeff78,$4cfb3fff,$01700000
500 dc.l $306c3d7c,$a040ff60,$227c0000,$00503d7c
501 dc.l $0001ff7c,$44fc0000,$48ee7fff,$ff8000ee
502 dc.l $9000ff60,$42eeff7e,$48ee7fff,$ffc061ff
503 dc.l $00003002,$4a0066ff,$00003028,$52aeff78
504 dc.l $4cfb3fff,$01700000,$30243d7c,$a0c0ff60
505 dc.l $223c1111,$11a03d7c,$0004ff7c,$44fc0000
506 dc.l $48ee7fff,$ff8000ee,$1000ff60,$42eeff7e
507 dc.l $48ee7fff,$ffc061ff,$00002fba,$4a0066ff
508 dc.l $00002fe0,$52aeff78,$4cfb3fff,$01700000
509 dc.l $2fdc3d7c,$a0c0ff60,$227cffff,$ffc03d7c
510 dc.l $0004ff7c,$44fc0000,$48ee7fff,$ff8000ee
511 dc.l $9000ff60,$42eeff7e,$48ee7fff,$ffc061ff
512 dc.l $00002f72,$4a0066ff,$00002f98,$52aeff78
513 dc.l $4cfb3fff,$01700000,$2f943d7c,$a0c0ff60
514 dc.l $223c1111,$11b03d7c,$0000ff7c,$44fc0000
515 dc.l $48ee7fff,$ff8000ee,$1800ff60,$42eeff7e
516 dc.l $48ee7fff,$ffc061ff,$00002f2a,$4a0066ff
517 dc.l $00002f50,$52aeff78,$4cfb3fff,$01700000
518 dc.l $2f4c3d7c,$a0c0ff60,$227c1111,$11903d7c
519 dc.l $0001ff7c,$44fc0000,$48ee7fff,$ff8000ee
520 dc.l $9000ff60,$42eeff7e,$48ee7fff,$ffc061ff
521 dc.l $00002ee2,$4a0066ff,$00002f08,$52aeff78
522 dc.l $4cfb3fff,$01700000,$2f043d7c,$a0c0ff60
523 dc.l $223c1111,$11d03d7c,$0001ff7c,$44fc0000
524 dc.l $48ee7fff,$ff8000ee,$1000ff60,$42eeff7e
525 dc.l $48ee7fff,$ffc061ff,$00002e9a,$4a0066ff
526 dc.l $00002ec0,$52aeff78,$4cfb3fff,$01700000
527 dc.l $2ebc3d7c,$a0c0ff60,$227c0000,$00503d7c
528 dc.l $001bff7c,$44fc001f,$48ee7fff,$ff8000ee
529 dc.l $9000ff60,$42eeff7e,$48ee7fff,$ffc061ff
530 dc.l $00002e52,$4a0066ff,$00002e78,$222eff78
531 dc.l $42804e75,$09456666,$65637469,$76652061
532 dc.l $64647265,$73736573,$2e2e2e00,$52aeff78
533 dc.l $4cfb3fff,$01700000,$2e544282,$760241ee
534 dc.l $ff743d7c,$0000ff7c,$44fc0000,$48eeffff
535 dc.l $ff804c10,$340242ee,$ff7e48ee,$ffffffc0
536 dc.l $2d7c0000,$0004ff8c,$61ff0000,$2de84a00
537 dc.l $66ff0000,$2e0e52ae,$ff784cfb,$3fff0170
538 dc.l $00002e0a,$42827602,$41eeff74,$3d7c0000
539 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c183402
540 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
541 dc.l $ff8c41ee,$ff782d48,$ffa061ff,$00002d96
542 dc.l $4a0066ff,$00002dbc,$52aeff78,$4cfb3fff
543 dc.l $01700000,$2db84282,$760241ee,$ff783d7c
544 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c20
545 dc.l $340242ee,$ff7e48ee,$ffffffc0,$2d7c0000
546 dc.l $0004ff8c,$41eeff74,$2d48ffa0,$61ff0000
547 dc.l $2d444a00,$66ff0000,$2d6a52ae,$ff784cfb
548 dc.l $3fff0170,$00002d66,$42827602,$41ee0f74
549 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
550 dc.l $4c283402,$f00042ee,$ff7e48ee,$ffffffc0
551 dc.l $2d7c0000,$0004ff8c,$61ff0000,$2cf84a00
552 dc.l $66ff0000,$2d1e52ae,$ff784cfb,$3fff0170
553 dc.l $00002d1a,$42827602,$41eeef74,$3d7c0000
554 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c283402
555 dc.l $100042ee,$ff7e48ee,$ffffffc0,$2d7c0000
556 dc.l $0004ff8c,$61ff0000,$2cac4a00,$66ff0000
557 dc.l $2cd252ae,$ff7852ae,$ff7852ae,$ff784cfb
558 dc.l $3fff0170,$00002cc6,$42827602,$3d7c0000
559 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c3c3402
560 dc.l $00000002,$42eeff7e,$48eeffff,$ffc02d7c
561 dc.l $00000004,$ff8c61ff,$00002c5a,$4a0066ff
562 dc.l $00002c80,$52aeff78,$60040000,$00024cfb
563 dc.l $3fff0170,$00002c76,$42827602,$3d7c0000
564 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c3a3402
565 dc.l $ffda42ee,$ff7e48ee,$ffffffc0,$2d7c0000
566 dc.l $0004ff8c,$61ff0000,$2c0c4a00,$66ff0000
567 dc.l $2c3252ae,$ff784cfb,$3fff0170,$00002c2e
568 dc.l $42827602,$43eeff78,$3d7c0000,$ff7c44fc
569 dc.l $000048ee,$ffffff80,$4c213402,$42eeff7e
570 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c41ee
571 dc.l $ff742d48,$ffa461ff,$00002bba,$4a0066ff
572 dc.l $00002be0,$52aeff78,$4cfb3fff,$01700000
573 dc.l $2bdc4282,$760245ee,$ff783d7c,$0000ff7c
574 dc.l $44fc0000,$48eeffff,$ff804c22,$340242ee
575 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
576 dc.l $41eeff74,$2d48ffa8,$61ff0000,$2b684a00
577 dc.l $66ff0000,$2b8e52ae,$ff784cfb,$3fff0170
578 dc.l $00002b8a,$42827602,$47eeff78,$3d7c0000
579 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c233402
580 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
581 dc.l $ff8c41ee,$ff742d48,$ffac61ff,$00002b16
582 dc.l $4a0066ff,$00002b3c,$52aeff78,$4cfb3fff
583 dc.l $01700000,$2b384282,$760249ee,$ff783d7c
584 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c24
585 dc.l $340242ee,$ff7e48ee,$ffffffc0,$2d7c0000
586 dc.l $0004ff8c,$41eeff74,$2d48ffb0,$61ff0000
587 dc.l $2ac44a00,$66ff0000,$2aea52ae,$ff784cfb
588 dc.l $3fff0170,$00002ae6,$42827602,$4beeff78
589 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
590 dc.l $4c253402,$42eeff7e,$48eeffff,$ffc02d7c
591 dc.l $00000004,$ff8c41ee,$ff742d48,$ffb461ff
592 dc.l $00002a72,$4a0066ff,$00002a98,$52aeff78
593 dc.l $4cfb3fff,$01700000,$2a94224e,$42827602
594 dc.l $4de9ff78,$337c0000,$ff7c44fc,$000048e9
595 dc.l $ffffff80,$4c263402,$42e9ff7e,$48e9ffff
596 dc.l $ffc0237c,$00000004,$ff8c41e9,$ff742348
597 dc.l $ffb82c49,$61ff0000,$2a1c4a00,$66ff0000
598 dc.l $2a4252ae,$ff784cfb,$3fff0170,$00002a3e
599 dc.l $42827602,$204f4fee,$ff783d7c,$0000ff7c
600 dc.l $44fc0000,$48eeffff,$ff804c27,$340242ee
601 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
602 dc.l $43eeff74,$2d49ffbc,$2e4861ff,$000029c6
603 dc.l $4a0066ff,$000029ec,$52aeff78,$4cfb3fff
604 dc.l $01700000,$29e84282,$760241ee,$ff7478f0
605 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
606 dc.l $4c303402,$401042ee,$ff7e48ee,$ffffffc0
607 dc.l $2d7c0000,$0004ff8c,$61ff0000,$29784a00
608 dc.l $66ff0000,$299e52ae,$ff784cfb,$3fff0170
609 dc.l $0000299a,$42827602,$41eeff74,$78f83d7c
610 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c30
611 dc.l $34024210,$42eeff7e,$48eeffff,$ffc02d7c
612 dc.l $00000004,$ff8c61ff,$0000292a,$4a0066ff
613 dc.l $00002950,$52aeff78,$4cfb3fff,$01700000
614 dc.l $294c4282,$760241ee,$ff7478fc,$3d7c0000
615 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c303402
616 dc.l $441042ee,$ff7e48ee,$ffffffc0,$2d7c0000
617 dc.l $0004ff8c,$61ff0000,$28dc4a00,$66ff0000
618 dc.l $290252ae,$ff784cfb,$3fff0170,$000028fe
619 dc.l $42827602,$41eeff74,$78fe3d7c,$0000ff7c
620 dc.l $44fc0000,$48eeffff,$ff804c30,$34024610
621 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
622 dc.l $ff8c61ff,$0000288e,$4a0066ff,$000028b4
623 dc.l $52aeff78,$4cfb3fff,$01700000,$28b04282
624 dc.l $760241ee,$ff7478f0,$3d7c0000,$ff7c44fc
625 dc.l $000048ee,$ffffff80,$4c303402,$481042ee
626 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
627 dc.l $61ff0000,$28404a00,$66ff0000,$286652ae
628 dc.l $ff784cfb,$3fff0170,$00002862,$42827602
629 dc.l $41eeff74,$78f83d7c,$0000ff7c,$44fc0000
630 dc.l $48eeffff,$ff804c30,$34024a10,$42eeff7e
631 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
632 dc.l $000027f2,$4a0066ff,$00002818,$52aeff78
633 dc.l $4cfb3fff,$01700000,$28144282,$760241ee
634 dc.l $ff7478fc,$3d7c0000,$ff7c44fc,$000048ee
635 dc.l $ffffff80,$4c303402,$4c1042ee,$ff7e48ee
636 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
637 dc.l $27a44a00,$66ff0000,$27ca52ae,$ff784cfb
638 dc.l $3fff0170,$000027c6,$42827602,$41eeff74
639 dc.l $78fe3d7c,$0000ff7c,$44fc0000,$48eeffff
640 dc.l $ff804c30,$34024e10,$42eeff7e,$48eeffff
641 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00002756
642 dc.l $4a0066ff,$0000277c,$52aeff78,$4cfb3fff
643 dc.l $01700000,$27784282,$760241ee,$ff74287c
644 dc.l $fffffffe,$3d7c0000,$ff7c44fc,$000048ee
645 dc.l $ffffff80,$4c303402,$ce1042ee,$ff7e48ee
646 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
647 dc.l $27044a00,$66ff0000,$272a52ae,$ff784cfb
648 dc.l $3fff0170,$00002726,$42827602,$41eeff74
649 dc.l $287c0000,$00023d7c,$0000ff7c,$44fc0000
650 dc.l $48eeffff,$ff804c30,$3402cef0,$42eeff7e
651 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
652 dc.l $000026b2,$4a0066ff,$000026d8,$52aeff78
653 dc.l $4cfb3fff,$01700000,$26d44282,$760243ee
654 dc.l $ff7478f0,$3d7c0000,$ff7c44fc,$000048ee
655 dc.l $ffffff80,$4c313402,$401042ee,$ff7e48ee
656 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
657 dc.l $26644a00,$66ff0000,$268a52ae,$ff784cfb
658 dc.l $3fff0170,$00002686,$42827602,$45eeff74
659 dc.l $78f03d7c,$0000ff7c,$44fc0000,$48eeffff
660 dc.l $ff804c32,$34024010,$42eeff7e,$48eeffff
661 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00002616
662 dc.l $4a0066ff,$0000263c,$52aeff78,$4cfb3fff
663 dc.l $01700000,$26384282,$760247ee,$ff7478f0
664 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
665 dc.l $4c333402,$401042ee,$ff7e48ee,$ffffffc0
666 dc.l $2d7c0000,$0004ff8c,$61ff0000,$25c84a00
667 dc.l $66ff0000,$25ee52ae,$ff784cfb,$3fff0170
668 dc.l $000025ea,$42827602,$49eeff74,$78f03d7c
669 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c34
670 dc.l $34024010,$42eeff7e,$48eeffff,$ffc02d7c
671 dc.l $00000004,$ff8c61ff,$0000257a,$4a0066ff
672 dc.l $000025a0,$52aeff78,$4cfb3fff,$01700000
673 dc.l $259c4282,$76024bee,$ff7478f0,$3d7c0000
674 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c353402
675 dc.l $401042ee,$ff7e48ee,$ffffffc0,$2d7c0000
676 dc.l $0004ff8c,$61ff0000,$252c4a00,$66ff0000
677 dc.l $255252ae,$ff784cfb,$3fff0170,$0000254e
678 dc.l $224e4282,$76024de9,$ff7478f0,$337c0000
679 dc.l $ff7c44fc,$000048e9,$ffffff80,$4c363402
680 dc.l $401042e9,$ff7e48e9,$ffffffc0,$237c0000
681 dc.l $0004ff8c,$2c4961ff,$000024da,$4a0066ff
682 dc.l $00002500,$52aeff78,$4cfb3fff,$01700000
683 dc.l $24fc4282,$7602204f,$4feeff74,$78f03d7c
684 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c37
685 dc.l $34024010,$42eeff7e,$48eeffff,$ffc02d7c
686 dc.l $00000004,$ff8c2e48,$61ff0000,$24884a00
687 dc.l $66ff0000,$24ae52ae,$ff784cfb,$3fff0170
688 dc.l $000024aa,$42827602,$43eeff74,$3d7c0000
689 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c113402
690 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
691 dc.l $ff8c61ff,$0000243e,$4a0066ff,$00002464
692 dc.l $52aeff78,$4cfb3fff,$01700000,$24604282
693 dc.l $760245ee,$ff743d7c,$0000ff7c,$44fc0000
694 dc.l $48eeffff,$ff804c12,$340242ee,$ff7e48ee
695 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
696 dc.l $23f44a00,$66ff0000,$241a52ae,$ff784cfb
697 dc.l $3fff0170,$00002416,$42827602,$47eeff74
698 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
699 dc.l $4c133402,$42eeff7e,$48eeffff,$ffc02d7c
700 dc.l $00000004,$ff8c61ff,$000023aa,$4a0066ff
701 dc.l $000023d0,$52aeff78,$4cfb3fff,$01700000
702 dc.l $23cc4282,$760249ee,$ff743d7c,$0000ff7c
703 dc.l $44fc0000,$48eeffff,$ff804c14,$340242ee
704 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
705 dc.l $61ff0000,$23604a00,$66ff0000,$238652ae
706 dc.l $ff784cfb,$3fff0170,$00002382,$42827602
707 dc.l $4beeff74,$3d7c0000,$ff7c44fc,$000048ee
708 dc.l $ffffff80,$4c153402,$42eeff7e,$48eeffff
709 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00002316
710 dc.l $4a0066ff,$0000233c,$52aeff78,$4cfb3fff
711 dc.l $01700000,$2338224e,$42827602,$4de9ff74
712 dc.l $337c0000,$ff7c44fc,$000048e9,$ffffff80
713 dc.l $4c163402,$42e9ff7e,$48e9ffff,$ffc0237c
714 dc.l $00000004,$ff8c2c49,$61ff0000,$22c84a00
715 dc.l $66ff0000,$22ee52ae,$ff784cfb,$3fff0170
716 dc.l $000022ea,$42827602,$204f4fee,$ff743d7c
717 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c17
718 dc.l $340242ee,$ff7e48ee,$ffffffc0,$2d7c0000
719 dc.l $0004ff8c,$2e4861ff,$0000227a,$4a0066ff
720 dc.l $000022a0,$52aeff78,$4cfb3fff,$01700000
721 dc.l $229c4282,$760243ee,$ff743d7c,$0000ff7c
722 dc.l $44fc0000,$48eeffff,$ff804c19,$340242ee
723 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
724 dc.l $41eeff78,$2d48ffa4,$61ff0000,$22284a00
725 dc.l $66ff0000,$224e52ae,$ff784cfb,$3fff0170
726 dc.l $0000224a,$42827602,$45eeff74,$3d7c0000
727 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c1a3402
728 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
729 dc.l $ff8c41ee,$ff782d48,$ffa861ff,$000021d6
730 dc.l $4a0066ff,$000021fc,$52aeff78,$4cfb3fff
731 dc.l $01700000,$21f84282,$760247ee,$ff743d7c
732 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c1b
733 dc.l $340242ee,$ff7e48ee,$ffffffc0,$2d7c0000
734 dc.l $0004ff8c,$41eeff78,$2d48ffac,$61ff0000
735 dc.l $21844a00,$66ff0000,$21aa52ae,$ff784cfb
736 dc.l $3fff0170,$000021a6,$42827602,$49eeff74
737 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
738 dc.l $4c1c3402,$42eeff7e,$48eeffff,$ffc02d7c
739 dc.l $00000004,$ff8c41ee,$ff782d48,$ffb061ff
740 dc.l $00002132,$4a0066ff,$00002158,$52aeff78
741 dc.l $4cfb3fff,$01700000,$21544282,$76024bee
742 dc.l $ff743d7c,$0000ff7c,$44fc0000,$48eeffff
743 dc.l $ff804c1d,$340242ee,$ff7e48ee,$ffffffc0
744 dc.l $2d7c0000,$0004ff8c,$41eeff78,$2d48ffb4
745 dc.l $61ff0000,$20e04a00,$66ff0000,$210652ae
746 dc.l $ff784cfb,$3fff0170,$00002102,$224e4282
747 dc.l $76024de9,$ff74337c,$0000ff7c,$44fc0000
748 dc.l $48e9ffff,$ff804c1e,$340242e9,$ff7e48e9
749 dc.l $ffffffc0,$237c0000,$0004ff8c,$41e9ff78
750 dc.l $2348ffb8,$2c4961ff,$0000208a,$4a0066ff
751 dc.l $000020b0,$52aeff78,$4cfb3fff,$01700000
752 dc.l $20ac4282,$7602204f,$4feeff74,$3d7c0000
753 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c1f3402
754 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
755 dc.l $ff8c43ee,$ff782d49,$ffbc2e48,$61ff0000
756 dc.l $20344a00,$66ff0000,$205a52ae,$ff784cfb
757 dc.l $3fff0170,$00002056,$42827602,$43eeef74
758 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
759 dc.l $4c293402,$100042ee,$ff7e48ee,$ffffffc0
760 dc.l $2d7c0000,$0004ff8c,$61ff0000,$1fe84a00
761 dc.l $66ff0000,$200e52ae,$ff784cfb,$3fff0170
762 dc.l $0000200a,$42827602,$45eeef74,$3d7c0000
763 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c2a3402
764 dc.l $100042ee,$ff7e48ee,$ffffffc0,$2d7c0000
765 dc.l $0004ff8c,$61ff0000,$1f9c4a00,$66ff0000
766 dc.l $1fc252ae,$ff784cfb,$3fff0170,$00001fbe
767 dc.l $42827602,$47eeef74,$3d7c0000,$ff7c44fc
768 dc.l $000048ee,$ffffff80,$4c2b3402,$100042ee
769 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
770 dc.l $61ff0000,$1f504a00,$66ff0000,$1f7652ae
771 dc.l $ff784cfb,$3fff0170,$00001f72,$42827602
772 dc.l $49eeef74,$3d7c0000,$ff7c44fc,$000048ee
773 dc.l $ffffff80,$4c2c3402,$100042ee,$ff7e48ee
774 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
775 dc.l $1f044a00,$66ff0000,$1f2a52ae,$ff784cfb
776 dc.l $3fff0170,$00001f26,$42827602,$4beeef74
777 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
778 dc.l $4c2d3402,$100042ee,$ff7e48ee,$ffffffc0
779 dc.l $2d7c0000,$0004ff8c,$61ff0000,$1eb84a00
780 dc.l $66ff0000,$1ede52ae,$ff784cfb,$3fff0170
781 dc.l $00001eda,$224e4282,$76024de9,$ef74337c
782 dc.l $0000ff7c,$44fc0000,$48e9ffff,$ff804c2e
783 dc.l $34021000,$42e9ff7e,$48e9ffff,$ffc0237c
784 dc.l $00000004,$ff8c2c49,$61ff0000,$1e684a00
785 dc.l $66ff0000,$1e8e52ae,$ff784cfb,$3fff0170
786 dc.l $00001e8a,$42827602,$204f4fee,$ef743d7c
787 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c2f
788 dc.l $34021000,$42eeff7e,$48eeffff,$ffc02d7c
789 dc.l $00000004,$ff8c2e48,$61ff0000,$1e184a00
790 dc.l $66ff0000,$1e3e52ae,$ff784cfb,$3fff0170
791 dc.l $00001e3a,$42827602,$41ee0f74,$3d7c0000
792 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c283402
793 dc.l $f00042ee,$ff7e48ee,$ffffffc0,$2d7c0000
794 dc.l $0004ff8c,$61ff0000,$1dcc4a00,$66ff0000
795 dc.l $1df252ae,$ff786004,$00000002,$4cfb3fff
796 dc.l $01700000,$1de84282,$76023d7c,$0000ff7c
797 dc.l $44fc0000,$48eeffff,$ff804c3a,$3402ffda
798 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
799 dc.l $ff8c61ff,$00001d7e,$4a0066ff,$00001da4
800 dc.l $52aeff78,$4cfb3fff,$01700000,$1da04282
801 dc.l $760247ee,$ff7478f0,$3d7c0000,$ff7c44fc
802 dc.l $000048ee,$ffffff80,$4c333402,$401042ee
803 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
804 dc.l $61ff0000,$1d304a00,$66ff0000,$1d5652ae
805 dc.l $ff784cfb,$3fff0170,$00001d52,$42827602
806 dc.l $47eeff74,$78f83d7c,$0000ff7c,$44fc0000
807 dc.l $48eeffff,$ff804c33,$34024210,$42eeff7e
808 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
809 dc.l $00001ce2,$4a0066ff,$00001d08,$52aeff78
810 dc.l $4cfb3fff,$01700000,$1d044282,$760247ee
811 dc.l $ff7478fc,$3d7c0000,$ff7c44fc,$000048ee
812 dc.l $ffffff80,$4c333402,$441042ee,$ff7e48ee
813 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
814 dc.l $1c944a00,$66ff0000,$1cba52ae,$ff784cfb
815 dc.l $3fff0170,$00001cb6,$42827602,$47eeff74
816 dc.l $78fe3d7c,$0000ff7c,$44fc0000,$48eeffff
817 dc.l $ff804c33,$34024610,$42eeff7e,$48eeffff
818 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00001c46
819 dc.l $4a0066ff,$00001c6c,$52aeff78,$4cfb3fff
820 dc.l $01700000,$1c684282,$760247ee,$ff7478f0
821 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
822 dc.l $4c333402,$481042ee,$ff7e48ee,$ffffffc0
823 dc.l $2d7c0000,$0004ff8c,$61ff0000,$1bf84a00
824 dc.l $66ff0000,$1c1e52ae,$ff784cfb,$3fff0170
825 dc.l $00001c1a,$42827602,$47eeff74,$78f83d7c
826 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c33
827 dc.l $34024a10,$42eeff7e,$48eeffff,$ffc02d7c
828 dc.l $00000004,$ff8c61ff,$00001baa,$4a0066ff
829 dc.l $00001bd0,$52aeff78,$4cfb3fff,$01700000
830 dc.l $1bcc4282,$760247ee,$ff7478fc,$3d7c0000
831 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c333402
832 dc.l $4c1042ee,$ff7e48ee,$ffffffc0,$2d7c0000
833 dc.l $0004ff8c,$61ff0000,$1b5c4a00,$66ff0000
834 dc.l $1b8252ae,$ff784cfb,$3fff0170,$00001b7e
835 dc.l $42827602,$47eeff74,$78fe3d7c,$0000ff7c
836 dc.l $44fc0000,$48eeffff,$ff804c33,$34024e10
837 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
838 dc.l $ff8c61ff,$00001b0e,$4a0066ff,$00001b34
839 dc.l $52aeff78,$4cfb3fff,$01700000,$1b304282
840 dc.l $760247ee,$ff74287c,$00000002,$3d7c0000
841 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c333402
842 dc.l $cef042ee,$ff7e48ee,$ffffffc0,$2d7c0000
843 dc.l $0004ff8c,$61ff0000,$1abc4a00,$66ff0000
844 dc.l $1ae252ae,$ff784cfb,$3fff0170,$00001ade
845 dc.l $42827602,$47eeff74,$287c0000,$00023d7c
846 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c33
847 dc.l $34020750,$42eeff7e,$48eeffff,$ffc02d7c
848 dc.l $00000004,$ff8c61ff,$00001a6a,$4a0066ff
849 dc.l $00001a90,$52aeff78,$4cfb3fff,$01700000
850 dc.l $1a8c4282,$760247ee,$ff74284b,$d9fc0000
851 dc.l $00103d7c,$0000ff7c,$44fc0000,$48eeffff
852 dc.l $ff804c30,$3402c9a0,$fff042ee,$ff7e48ee
853 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
854 dc.l $1a144a00,$66ff0000,$1a3a52ae,$ff784cfb
855 dc.l $3fff0170,$00001a36,$42827602,$47eeff74
856 dc.l $287c0000,$00023d7c,$0000ff7c,$44fc0000
857 dc.l $48eeffff,$ff804c33,$3402cef0,$42eeff7e
858 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
859 dc.l $000019c2,$4a0066ff,$000019e8,$52aeff78
860 dc.l $60040000,$00024cfb,$3fff0170,$000019de
861 dc.l $42827602,$47eeff74,$78f03d7c,$0000ff7c
862 dc.l $44fc0000,$48eeffff,$ff804c3b,$340240e4
863 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
864 dc.l $ff8c61ff,$0000196e,$4a0066ff,$00001994
865 dc.l $52aeff78,$60040000,$00024cfb,$3fff0170
866 dc.l $0000198a,$42827602,$41eeff74,$78f83d7c
867 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff804c3b
868 dc.l $340242e4,$42eeff7e,$48ee7fff,$ffc02d7c
869 dc.l $00000004,$ff8c61ff,$0000191a,$4a0066ff
870 dc.l $00001940,$52aeff78,$60040000,$00024cfb
871 dc.l $3fff0170,$00001936,$42827602,$41eeff74
872 dc.l $78fc3d7c,$0000ff7c,$44fc0000,$48ee7fff
873 dc.l $ff804c3b,$340244e4,$42eeff7e,$48ee7fff
874 dc.l $ffc02d7c,$00000004,$ff8c61ff,$000018c6
875 dc.l $4a0066ff,$000018ec,$52aeff78,$60040000
876 dc.l $00024cfb,$3fff0170,$000018e2,$42827602
877 dc.l $41eeff74,$78fe3d7c,$0000ff7c,$44fc0000
878 dc.l $48ee7fff,$ff804c3b,$340246e4,$42eeff7e
879 dc.l $48ee7fff,$ffc02d7c,$00000004,$ff8c61ff
880 dc.l $00001872,$4a0066ff,$00001898,$52aeff78
881 dc.l $60040000,$00024cfb,$3fff0170,$0000188e
882 dc.l $42827602,$41eeff74,$78f03d7c,$0000ff7c
883 dc.l $44fc0000,$48ee7fff,$ff804c3b,$340248e4
884 dc.l $42eeff7e,$48ee7fff,$ffc02d7c,$00000004
885 dc.l $ff8c61ff,$0000181e,$4a0066ff,$00001844
886 dc.l $52aeff78,$60040000,$00024cfb,$3fff0170
887 dc.l $0000183a,$42827602,$41eeff74,$78f83d7c
888 dc.l $0000ff7c,$44fc0000,$48ee7fff,$ff804c3b
889 dc.l $34024ae4,$42eeff7e,$48ee7fff,$ffc02d7c
890 dc.l $00000004,$ff8c61ff,$000017ca,$4a0066ff
891 dc.l $000017f0,$52aeff78,$60040000,$00024cfb
892 dc.l $3fff0170,$000017e6,$42827602,$41eeff74
893 dc.l $78fc3d7c,$0000ff7c,$44fc0000,$48ee7fff
894 dc.l $ff804c3b,$34024ce4,$42eeff7e,$48ee7fff
895 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00001776
896 dc.l $4a0066ff,$0000179c,$52aeff78,$60040000
897 dc.l $00024cfb,$3fff0170,$00001792,$42827602
898 dc.l $41eeff74,$78fe3d7c,$0000ff7c,$44fc0000
899 dc.l $48ee7fff,$ff804c3b,$34024ee4,$42eeff7e
900 dc.l $48ee7fff,$ffc02d7c,$00000004,$ff8c61ff
901 dc.l $00001722,$4a0066ff,$00001748,$52aeff78
902 dc.l $60040000,$00024cfb,$3fff0170,$0000173e
903 dc.l $42827602,$47eeff74,$287cffff,$fffe3d7c
904 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c3b
905 dc.l $3402cee0,$42eeff7e,$48eeffff,$ffc02d7c
906 dc.l $00000004,$ff8c61ff,$000016ca,$4a0066ff
907 dc.l $000016f0,$52aeff78,$60040000,$00024cfb
908 dc.l $3fff0170,$000016e6,$42827602,$47eeff74
909 dc.l $287c0000,$00023d7c,$0000ff7c,$44fc0000
910 dc.l $48eeffff,$ff804c3b,$34020760,$ffd042ee
911 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
912 dc.l $61ff0000,$16704a00,$66ff0000,$169652ae
913 dc.l $ff7852ae,$ff784cfb,$3fff0170,$0000168e
914 dc.l $42827602,$47f9ffff,$ff74287c,$00000002
915 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
916 dc.l $4c3b3402,$cf300000,$000a42ee,$ff7e48ee
917 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$60040000
918 dc.l $000261ff,$0000160e,$4a0066ff,$00001634
919 dc.l $52aeff78,$60040000,$00024cfb,$3fff0170
920 dc.l $0000162a,$42827602,$43eeff74,$78f03d7c
921 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c3b
922 dc.l $340240e4,$42eeff7e,$48eeffff,$ffc02d7c
923 dc.l $00000004,$ff8c61ff,$000015ba,$4a0066ff
924 dc.l $000015e0,$52aeff78,$60040000,$00024cfb
925 dc.l $3fff0170,$000015d6,$42827602,$41eeff74
926 dc.l $78f83d7c,$0000ff7c,$44fc0000,$48eeffff
927 dc.l $ff804c3b,$340242e4,$42eeff7e,$48eeffff
928 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00001566
929 dc.l $4a0066ff,$0000158c,$52aeff78,$60040000
930 dc.l $00024cfb,$3fff0170,$00001582,$42827602
931 dc.l $41eeff74,$78fc3d7c,$0000ff7c,$44fc0000
932 dc.l $48eeffff,$ff804c3b,$340244e4,$42eeff7e
933 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
934 dc.l $00001512,$4a0066ff,$00001538,$52aeff78
935 dc.l $60040000,$00024cfb,$3fff0170,$0000152e
936 dc.l $42827602,$41eeff74,$78fe3d7c,$0000ff7c
937 dc.l $44fc0000,$48eeffff,$ff804c3b,$340246e4
938 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
939 dc.l $ff8c61ff,$000014be,$4a0066ff,$000014e4
940 dc.l $52aeff78,$60040000,$00024cfb,$3fff0170
941 dc.l $000014da,$42827602,$41eeff74,$78f03d7c
942 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c3b
943 dc.l $340248e4,$42eeff7e,$48eeffff,$ffc02d7c
944 dc.l $00000004,$ff8c61ff,$0000146a,$4a0066ff
945 dc.l $00001490,$52aeff78,$60040000,$00024cfb
946 dc.l $3fff0170,$00001486,$42827602,$41eeff74
947 dc.l $78f83d7c,$0000ff7c,$44fc0000,$48eeffff
948 dc.l $ff804c3b,$34024ae4,$42eeff7e,$48eeffff
949 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00001416
950 dc.l $4a0066ff,$0000143c,$52aeff78,$60040000
951 dc.l $00024cfb,$3fff0170,$00001432,$42827602
952 dc.l $41eeff74,$78fc3d7c,$0000ff7c,$44fc0000
953 dc.l $48eeffff,$ff804c3b,$34024ce4,$42eeff7e
954 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
955 dc.l $000013c2,$4a0066ff,$000013e8,$52aeff78
956 dc.l $60040000,$00024cfb,$3fff0170,$000013de
957 dc.l $42827602,$41eeff74,$78fe3d7c,$0000ff7c
958 dc.l $44fc0000,$48eeffff,$ff804c3b,$34024ee4
959 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
960 dc.l $ff8c61ff,$0000136e,$4a0066ff,$00001394
961 dc.l $52aeff78,$4cfb3fff,$01700000,$13904282
962 dc.l $760241ee,$ff7478fe,$3d7c0000,$ff7c44fc
963 dc.l $000048ee,$ffffff80,$4c3b3402,$4e2642ee
964 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
965 dc.l $60040000,$000261ff,$0000131a,$4a0066ff
966 dc.l $00001340,$52aeff78,$4cfb3fff,$01700000
967 dc.l $133c4282,$760247ee,$ef7449ee,$ff70288b
968 dc.l $78f03d7c,$0000ff7c,$44fc0000,$48eeffff
969 dc.l $ff804c34,$34024122,$00101000,$42eeff7e
970 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
971 dc.l $000012c2,$4a0066ff,$000012e8,$52aeff78
972 dc.l $4cfb3fff,$01700000,$12e44282,$760247ee
973 dc.l $ef7449ee,$ff70288b,$78f83d7c,$0000ff7c
974 dc.l $44fc0000,$48eeffff,$ff804c34,$34024322
975 dc.l $00101000,$42eeff7e,$48eeffff,$ffc02d7c
976 dc.l $00000004,$ff8c61ff,$0000126a,$4a0066ff
977 dc.l $00001290,$52aeff78,$4cfb3fff,$01700000
978 dc.l $128c4282,$760247ee,$ef7449ee,$ff70288b
979 dc.l $78fc3d7c,$0000ff7c,$44fc0000,$48eeffff
980 dc.l $ff804c34,$34024522,$00101000,$42eeff7e
981 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
982 dc.l $00001212,$4a0066ff,$00001238,$52aeff78
983 dc.l $4cfb3fff,$01700000,$12344282,$760247ee
984 dc.l $ef7449ee,$ff70288b,$78fe3d7c,$0000ff7c
985 dc.l $44fc0000,$48eeffff,$ff804c34,$34024722
986 dc.l $00101000,$42eeff7e,$48eeffff,$ffc02d7c
987 dc.l $00000004,$ff8c61ff,$000011ba,$4a0066ff
988 dc.l $000011e0,$52aeff78,$4cfb3fff,$01700000
989 dc.l $11dc4282,$760247ee,$ef7449ee,$ff70288b
990 dc.l $78f03d7c,$0000ff7c,$44fc0000,$48eeffff
991 dc.l $ff804c34,$34024922,$00101000,$42eeff7e
992 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
993 dc.l $00001162,$4a0066ff,$00001188,$52aeff78
994 dc.l $4cfb3fff,$01700000,$11844282,$760247ee
995 dc.l $ef7449ee,$ff70288b,$78f83d7c,$0000ff7c
996 dc.l $44fc0000,$48eeffff,$ff804c34,$34024b22
997 dc.l $00101000,$42eeff7e,$48eeffff,$ffc02d7c
998 dc.l $00000004,$ff8c61ff,$0000110a,$4a0066ff
999 dc.l $00001130,$52aeff78,$4cfb3fff,$01700000
1000 dc.l $112c4282,$760247ee,$ef7449ee,$ff70288b
1001 dc.l $78fc3d7c,$0000ff7c,$44fc0000,$48eeffff
1002 dc.l $ff804c34,$34024d22,$00101000,$42eeff7e
1003 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
1004 dc.l $000010b2,$4a0066ff,$000010d8,$52aeff78
1005 dc.l $4cfb3fff,$01700000,$10d44282,$760247ee
1006 dc.l $ef7449ee,$ff70288b,$78fe3d7c,$0000ff7c
1007 dc.l $44fc0000,$48eeffff,$ff804c34,$34024f22
1008 dc.l $00101000,$42eeff7e,$48eeffff,$ffc02d7c
1009 dc.l $00000004,$ff8c61ff,$0000105a,$4a0066ff
1010 dc.l $00001080,$52aeff78,$4cfb3fff,$01700000
1011 dc.l $107c4282,$760247ee,$ef7449ee,$ff70288b
1012 dc.l $78fe3d7c,$0000ff7c,$44fc0000,$48eeffff
1013 dc.l $ff804c34,$34024f33,$00000010,$00001000
1014 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1015 dc.l $ff8c61ff,$00000ffe,$4a0066ff,$00001024
1016 dc.l $52aeff78,$4cfb3fff,$01700000,$10204282
1017 dc.l $760247ee,$ef7449ee,$ff70288b,$78fe3d7c
1018 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c34
1019 dc.l $34020753,$00001000,$42eeff7e,$48eeffff
1020 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00000fa6
1021 dc.l $4a0066ff,$00000fcc,$52aeff78,$4cfb3fff
1022 dc.l $01700000,$0fc84282,$760247ee,$ef7449ee
1023 dc.l $ff70288b,$78fe3d7c,$0000ff7c,$44fc0000
1024 dc.l $48eeffff,$ff804c34,$34020753,$00001000
1025 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1026 dc.l $ff8c61ff,$00000f4e,$4a0066ff,$00000f74
1027 dc.l $52aeff78,$4cfb3fff,$01700000,$0f704282
1028 dc.l $760247ee,$ef7449ee,$ff70288b,$78f0d88c
1029 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
1030 dc.l $4c303402,$49b30000,$00100000,$100042ee
1031 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
1032 dc.l $61ff0000,$0ef04a00,$66ff0000,$0f1652ae
1033 dc.l $ff7852ae,$ff784cfb,$3fff0170,$00000f0e
1034 dc.l $224e4282,$760247e9,$0f7449e9,$ff70288b
1035 dc.l $2c7cffff,$fffe337c,$0000ff7c,$44fc0000
1036 dc.l $48e9ffff,$ff804c34,$3402ef22,$0010f000
1037 dc.l $42e9ff7e,$48e9ffff,$ffc0237c,$00000004
1038 dc.l $ff8c2c49,$61ff0000,$0e8c4a00,$66ff0000
1039 dc.l $0eb252ae,$ff784cfb,$3fff0170,$00000eae
1040 dc.l $224e4282,$760247e9,$0f7449e9,$ff70288b
1041 dc.l $2c7c0000,$0002337c,$0000ff7c,$44fc0000
1042 dc.l $48e9ffff,$ff804c34,$3402ef22,$fff0f000
1043 dc.l $42e9ff7e,$48e9ffff,$ffc0237c,$00000004
1044 dc.l $ff8c2c49,$61ff0000,$0e2c4a00,$66ff0000
1045 dc.l $0e5252ae,$ff784cfb,$3fff0170,$00000e4e
1046 dc.l $42827602,$47eeff54,$49eeff70,$288b99fc
1047 dc.l $00000010,$78103d7c,$0000ff7c,$44fc0000
1048 dc.l $48eeffff,$ff804c34,$34024126,$00100010
1049 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1050 dc.l $ff8c61ff,$00000dce,$4a0066ff,$00000df4
1051 dc.l $52aeff78,$4cfb3fff,$01700000,$0df04282
1052 dc.l $760247ee,$ff5449ee,$ff70288b,$99fc0000
1053 dc.l $00107808,$3d7c0000,$ff7c44fc,$000048ee
1054 dc.l $ffffff80,$4c343402,$43260010,$001042ee
1055 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
1056 dc.l $61ff0000,$0d704a00,$66ff0000,$0d9652ae
1057 dc.l $ff784cfb,$3fff0170,$00000d92,$42827602
1058 dc.l $47eeff54,$49eeff70,$288b99fc,$00000010
1059 dc.l $78043d7c,$0000ff7c,$44fc0000,$48eeffff
1060 dc.l $ff804c34,$34024526,$00100010,$42eeff7e
1061 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
1062 dc.l $00000d12,$4a0066ff,$00000d38,$52aeff78
1063 dc.l $4cfb3fff,$01700000,$0d344282,$760247ee
1064 dc.l $ff5449ee,$ff70288b,$99fc0000,$00107802
1065 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
1066 dc.l $4c343402,$47260010,$001042ee,$ff7e48ee
1067 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
1068 dc.l $0cb44a00,$66ff0000,$0cda52ae,$ff784cfb
1069 dc.l $3fff0170,$00000cd6,$42827602,$47eeff54
1070 dc.l $49eeff70,$288b99fc,$00000010,$78103d7c
1071 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c34
1072 dc.l $34024926,$00100010,$42eeff7e,$48eeffff
1073 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00000c56
1074 dc.l $4a0066ff,$00000c7c,$52aeff78,$4cfb3fff
1075 dc.l $01700000,$0c784282,$760247ee,$ff5449ee
1076 dc.l $ff70288b,$99fc0000,$00107808,$3d7c0000
1077 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c343402
1078 dc.l $43260010,$001042ee,$ff7e48ee,$ffffffc0
1079 dc.l $2d7c0000,$0004ff8c,$61ff0000,$0bf84a00
1080 dc.l $66ff0000,$0c1e52ae,$ff784cfb,$3fff0170
1081 dc.l $00000c1a,$42827602,$47eeff54,$49eeff70
1082 dc.l $288b99fc,$00000010,$78043d7c,$0000ff7c
1083 dc.l $44fc0000,$48eeffff,$ff804c34,$34024d26
1084 dc.l $00100010,$42eeff7e,$48eeffff,$ffc02d7c
1085 dc.l $00000004,$ff8c61ff,$00000b9a,$4a0066ff
1086 dc.l $00000bc0,$52aeff78,$4cfb3fff,$01700000
1087 dc.l $0bbc4282,$760247ee,$ff5449ee,$ff70288b
1088 dc.l $99fc0000,$00107802,$3d7c0000,$ff7c44fc
1089 dc.l $000048ee,$ffffff80,$4c343402,$4f260010
1090 dc.l $001042ee,$ff7e48ee,$ffffffc0,$2d7c0000
1091 dc.l $0004ff8c,$61ff0000,$0b3c4a00,$66ff0000
1092 dc.l $0b6252ae,$ff784cfb,$3fff0170,$00000b5e
1093 dc.l $42827602,$47eeff54,$49eeff70,$288b99fc
1094 dc.l $00000010,$78023d7c,$0000ff7c,$44fc0000
1095 dc.l $48eeffff,$ff804c34,$34024f37,$00000010
1096 dc.l $00000010,$42eeff7e,$48eeffff,$ffc02d7c
1097 dc.l $00000004,$ff8c61ff,$00000ada,$4a0066ff
1098 dc.l $00000b00,$52aeff78,$4cfb3fff,$01700000
1099 dc.l $0afc4282,$760247ee,$ff5449ee,$ff70288b
1100 dc.l $78023d7c,$0000ff7c,$44fc0000,$48eeffff
1101 dc.l $ff804c34,$34020753,$00000020,$42eeff7e
1102 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
1103 dc.l $00000a82,$4a0066ff,$00000aa8,$52aeff78
1104 dc.l $4cfb3fff,$01700000,$0aa4204f,$42827602
1105 dc.l $47eeff54,$4feeff70,$2e8b7820,$3d7c0000
1106 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c373402
1107 dc.l $491542ee,$ff7e48ee,$ffffffc0,$2d7c0000
1108 dc.l $0004ff8c,$2e4861ff,$00000a2a,$4a0066ff
1109 dc.l $00000a50,$52aeff78,$52aeff78,$4cfb3fff
1110 dc.l $01700000,$0a48224e,$42827602,$47e9ff74
1111 dc.l $4de9ff70,$2c8bddfc,$00000010,$2a7cffff
1112 dc.l $fffe337c,$0000ff7c,$44fc0000,$48e9ffff
1113 dc.l $ff804c36,$3402df27,$fff00000,$001042e9
1114 dc.l $ff7e48e9,$ffffffc0,$237c0000,$0004ff8c
1115 dc.l $2c4961ff,$000009be,$4a0066ff,$000009e4
1116 dc.l $222eff78,$42804e75,$52aeff78,$4cfb3fff
1117 dc.l $01700000,$09d84282,$760247fa,$ef7449fa
1118 dc.l $ff70288b,$78f03d7c,$0000ff7c,$44fc0000
1119 dc.l $48eeffff,$ff804c3b,$34024122,$ff801000
1120 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1121 dc.l $ff8c61ff,$0000095e,$4a0066ff,$00000984
1122 dc.l $52aeff78,$4cfb3fff,$01700000,$09804282
1123 dc.l $760247fa,$ef7449fa,$ff70288b,$78f83d7c
1124 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c3b
1125 dc.l $34024322,$ff801000,$42eeff7e,$48eeffff
1126 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00000906
1127 dc.l $4a0066ff,$0000092c,$52aeff78,$4cfb3fff
1128 dc.l $01700000,$09284282,$760247fa,$ef7449fa
1129 dc.l $ff70288b,$78fc3d7c,$0000ff7c,$44fc0000
1130 dc.l $48eeffff,$ff804c3b,$34024522,$ff801000
1131 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1132 dc.l $ff8c61ff,$000008ae,$4a0066ff,$000008d4
1133 dc.l $52aeff78,$4cfb3fff,$01700000,$08d04282
1134 dc.l $760247fa,$ef7449fa,$ff70288b,$78fe3d7c
1135 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c3b
1136 dc.l $34024722,$ff801000,$42eeff7e,$48eeffff
1137 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00000856
1138 dc.l $4a0066ff,$0000087c,$52aeff78,$4cfb3fff
1139 dc.l $01700000,$08784282,$760247fa,$ef7449fa
1140 dc.l $ff70288b,$78f03d7c,$0000ff7c,$44fc0000
1141 dc.l $48eeffff,$ff804c3b,$34024922,$ff801000
1142 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1143 dc.l $ff8c61ff,$000007fe,$4a0066ff,$00000824
1144 dc.l $52aeff78,$4cfb3fff,$01700000,$08204282
1145 dc.l $760247fa,$ef7449fa,$ff70288b,$78f83d7c
1146 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c3b
1147 dc.l $34024b22,$ff801000,$42eeff7e,$48eeffff
1148 dc.l $ffc02d7c,$00000004,$ff8c61ff,$000007a6
1149 dc.l $4a0066ff,$000007cc,$52aeff78,$4cfb3fff
1150 dc.l $01700000,$07c84282,$760247fa,$ef7449fa
1151 dc.l $ff70288b,$78fc3d7c,$0000ff7c,$44fc0000
1152 dc.l $48eeffff,$ff804c3b,$34024d22,$ff801000
1153 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1154 dc.l $ff8c61ff,$0000074e,$4a0066ff,$00000774
1155 dc.l $52aeff78,$4cfb3fff,$01700000,$07704282
1156 dc.l $760247fa,$ef7449fa,$ff70288b,$78fe3d7c
1157 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c3b
1158 dc.l $34024f22,$ff801000,$42eeff7e,$48eeffff
1159 dc.l $ffc02d7c,$00000004,$ff8c61ff,$000006f6
1160 dc.l $4a0066ff,$0000071c,$52aeff78,$4cfb3fff
1161 dc.l $01700000,$07184282,$760247fa,$ef7449fa
1162 dc.l $ff70288b,$78fe3d7c,$0000ff7c,$44fc0000
1163 dc.l $48eeffff,$ff804c3b,$34024f33,$ffffff80
1164 dc.l $00001000,$42eeff7e,$48eeffff,$ffc02d7c
1165 dc.l $00000004,$ff8c61ff,$0000069a,$4a0066ff
1166 dc.l $000006c0,$52aeff78,$4cfb3fff,$01700000
1167 dc.l $06bc4282,$760247fa,$ef7449fa,$ff70288b
1168 dc.l $78fe3d7c,$0000ff7c,$44fc0000,$48eeffff
1169 dc.l $ff804c3b,$34020773,$ffffff70,$00001000
1170 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1171 dc.l $ff8c61ff,$0000063e,$4a0066ff,$00000664
1172 dc.l $52aeff78,$4cfb3fff,$01700000,$06604282
1173 dc.l $760247fa,$ef7449fa,$ff70288b,$280c3d7c
1174 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c30
1175 dc.l $34024993,$00001000,$42eeff7e,$48eeffff
1176 dc.l $ffc02d7c,$00000004,$ff8c61ff,$000005e6
1177 dc.l $4a0066ff,$0000060c,$52aeff78,$4cfb3fff
1178 dc.l $01700000,$06084282,$760247fa,$ef7449fa
1179 dc.l $ff70288b,$78f0d88c,$3d7c0000,$ff7c44fc
1180 dc.l $000048ee,$ffffff80,$4c303402,$49b30000
1181 dc.l $00100000,$100042ee,$ff7e48ee,$ffffffc0
1182 dc.l $2d7c0000,$0004ff8c,$61ff0000,$05884a00
1183 dc.l $66ff0000,$05ae52ae,$ff784282,$760247fa
1184 dc.l $ff7449fa,$ff70288b,$78f03d7c,$0000ff7c
1185 dc.l $44fc0000,$48eeffff,$ff804c30,$340201f1
1186 dc.l $ffffff70,$42eeff7e,$48eeffff,$ffc02d7c
1187 dc.l $00000004,$ff8c61ff,$0000053a,$4a0066ff
1188 dc.l $00000560,$52aeff78,$4cfb3fff,$01700000
1189 dc.l $055c4282,$760247fa,$0f7449fa,$ff70288b
1190 dc.l $2c7c0000,$00023d7c,$0000ff7c,$44fc0000
1191 dc.l $48eeffff,$ff804c3b,$3402ef22,$ff60f000
1192 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1193 dc.l $ff8c61ff,$000004de,$4a0066ff,$00000504
1194 dc.l $52aeff78,$4cfb3fff,$01700000,$0500204f
1195 dc.l $42827602,$47fa0f74,$49faff70,$288b2e7c
1196 dc.l $00000002,$3d7c0000,$ff7c44fc,$000048ee
1197 dc.l $ffffff80,$4c3b3402,$ff22ff60,$f00042ee
1198 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
1199 dc.l $2e4861ff,$0000047e,$4a0066ff,$000004a4
1200 dc.l $52aeff78,$4cfb3fff,$01700000,$04a04282
1201 dc.l $760247fa,$ff5449fa,$ff70288b,$99fc0000
1202 dc.l $00107810,$3d7c0000,$ff7c44fc,$000048ee
1203 dc.l $ffffff80,$4c3b3402,$4126ff70,$001042ee
1204 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
1205 dc.l $61ff0000,$04204a00,$66ff0000,$044652ae
1206 dc.l $ff784cfb,$3fff0170,$00000442,$42827602
1207 dc.l $47faff54,$49faff70,$288b99fc,$00000010
1208 dc.l $78083d7c,$0000ff7c,$44fc0000,$48eeffff
1209 dc.l $ff804c3b,$34024326,$ff700010,$42eeff7e
1210 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c61ff
1211 dc.l $000003c2,$4a0066ff,$000003e8,$52aeff78
1212 dc.l $4cfb3fff,$01700000,$03e44282,$760247fa
1213 dc.l $ff5449fa,$ff70288b,$99fc0000,$00107804
1214 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
1215 dc.l $4c3b3402,$4526ff70,$001042ee,$ff7e48ee
1216 dc.l $ffffffc0,$2d7c0000,$0004ff8c,$61ff0000
1217 dc.l $03644a00,$66ff0000,$038a52ae,$ff784cfb
1218 dc.l $3fff0170,$00000386,$42827602,$47faff54
1219 dc.l $49faff70,$288b99fc,$00000010,$78023d7c
1220 dc.l $0000ff7c,$44fc0000,$48eeffff,$ff804c3b
1221 dc.l $34024726,$ff700010,$42eeff7e,$48eeffff
1222 dc.l $ffc02d7c,$00000004,$ff8c61ff,$00000306
1223 dc.l $4a0066ff,$0000032c,$52aeff78,$4cfb3fff
1224 dc.l $01700000,$03284282,$760247fa,$ff5449fa
1225 dc.l $ff70288b,$99fc0000,$00107810,$3d7c0000
1226 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c3b3402
1227 dc.l $4926ff70,$001042ee,$ff7e48ee,$ffffffc0
1228 dc.l $2d7c0000,$0004ff8c,$61ff0000,$02a84a00
1229 dc.l $66ff0000,$02ce52ae,$ff784cfb,$3fff0170
1230 dc.l $000002ca,$42827602,$47faff54,$49faff70
1231 dc.l $288b99fc,$00000010,$78083d7c,$0000ff7c
1232 dc.l $44fc0000,$48eeffff,$ff804c3b,$34024326
1233 dc.l $ff700010,$42eeff7e,$48eeffff,$ffc02d7c
1234 dc.l $00000004,$ff8c61ff,$0000024a,$4a0066ff
1235 dc.l $00000270,$52aeff78,$4cfb3fff,$01700000
1236 dc.l $026c4282,$760247fa,$ff5449fa,$ff70288b
1237 dc.l $99fc0000,$00107804,$3d7c0000,$ff7c44fc
1238 dc.l $000048ee,$ffffff80,$4c3b3402,$4d26ff70
1239 dc.l $001042ee,$ff7e48ee,$ffffffc0,$2d7c0000
1240 dc.l $0004ff8c,$61ff0000,$01ec4a00,$66ff0000
1241 dc.l $021252ae,$ff784cfb,$3fff0170,$0000020e
1242 dc.l $42827602,$47faff54,$49faff70,$288b99fc
1243 dc.l $00000010,$78023d7c,$0000ff7c,$44fc0000
1244 dc.l $48eeffff,$ff804c3b,$34024f26,$ff700010
1245 dc.l $42eeff7e,$48eeffff,$ffc02d7c,$00000004
1246 dc.l $ff8c61ff,$0000018e,$4a0066ff,$000001b4
1247 dc.l $52aeff78,$4cfb3fff,$01700000,$01b04282
1248 dc.l $760247fa,$ff5449fa,$ff70288b,$99fc0000
1249 dc.l $00107802,$3d7c0000,$ff7c44fc,$000048ee
1250 dc.l $ffffff80,$4c3b3402,$4f37ffff,$ff700000
1251 dc.l $001042ee,$ff7e48ee,$ffffffc0,$2d7c0000
1252 dc.l $0004ff8c,$61ff0000,$012c4a00,$66ff0000
1253 dc.l $015252ae,$ff784cfb,$3fff0170,$0000014e
1254 dc.l $42827602,$47faff54,$49faff70,$288b7802
1255 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
1256 dc.l $4c3b3402,$0773ffff,$ff700000,$002042ee
1257 dc.l $ff7e48ee,$ffffffc0,$2d7c0000,$0004ff8c
1258 dc.l $61ff0000,$00d04a00,$66ff0000,$00f652ae
1259 dc.l $ff784cfb,$3fff0170,$000000f2,$42827602
1260 dc.l $47faff54,$49faff70,$288b7804,$3d7c0000
1261 dc.l $ff7c44fc,$000048ee,$ffffff80,$4c303402
1262 dc.l $4fb5ffff,$ff7042ee,$ff7e48ee,$ffffffc0
1263 dc.l $2d7c0000,$0004ff8c,$61ff0000,$00784a00
1264 dc.l $66ff0000,$009e52ae,$ff784cfb,$3fff0170
1265 dc.l $0000009a,$204f4282,$760247fa,$ff744dfa
1266 dc.l $ff702c8b,$ddfc0000,$00102e7c,$fffffffe
1267 dc.l $3d7c0000,$ff7c44fc,$000048ee,$ffffff80
1268 dc.l $4c3b3402,$ff27ff70,$00000010,$42eeff7e
1269 dc.l $48eeffff,$ffc02d7c,$00000004,$ff8c2e48
1270 dc.l $61ff0000,$00104a00,$66ff0000,$00364280
1271 dc.l $4e7541ee,$ff8043ee,$ffc0700e,$b18966ff
1272 dc.l $0000001c,$51c8fff6,$302eff7c,$322eff7e
1273 dc.l $b04166ff,$00000008,$42804e75,$70014e75
1274 dc.l $222eff78,$70014e75,$acacacac,$acacacac
1275 dc.l $acacacac,$acacacac,$acacacac,$acacacac
1276 dc.l $acacacac,$acacacac,$acacacac,$acacacac
1277 dc.l $acacacac,$acacacac,$acacacac,$acacacac
1278 dc.l $acacacac,$acacacac,$2f00203a,$afa4487b
1279 dc.l $0930ffff,$afa0202f,$00044e74,$00042f00
1280 dc.l $203aaf92,$487b0930,$ffffaf8a,$202f0004
1281 dc.l $4e740004,$00000000,$00000000,$00000000
diff --git a/arch/m68k/ifpsp060/os.S b/arch/m68k/ifpsp060/os.S
new file mode 100644
index 000000000000..aa4df87a6c42
--- /dev/null
+++ b/arch/m68k/ifpsp060/os.S
@@ -0,0 +1,396 @@
1|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2|MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3|M68000 Hi-Performance Microprocessor Division
4|M68060 Software Package
5|Production Release P1.00 -- October 10, 1994
6|
7|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8|
9|THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10|To the maximum extent permitted by applicable law,
11|MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12|INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13|and any warranty against infringement with regard to the SOFTWARE
14|(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15|
16|To the maximum extent permitted by applicable law,
17|IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18|(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19|BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20|ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21|Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22|
23|You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24|so long as this entire notice is retained without alteration in any modified and/or
25|redistributed versions, and that such modified versions are clearly identified as such.
26|No licenses are granted by implication, estoppel or otherwise under any patents
27|or trademarks of Motorola, Inc.
28|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29| os.s
30|
31| This file contains:
32| - example "Call-Out"s required by both the ISP and FPSP.
33|
34
35#include <linux/linkage.h>
36
37|################################
38| EXAMPLE CALL-OUTS #
39| #
40| _060_dmem_write() #
41| _060_dmem_read() #
42| _060_imem_read() #
43| _060_dmem_read_byte() #
44| _060_dmem_read_word() #
45| _060_dmem_read_long() #
46| _060_imem_read_word() #
47| _060_imem_read_long() #
48| _060_dmem_write_byte() #
49| _060_dmem_write_word() #
50| _060_dmem_write_long() #
51| #
52| _060_real_trace() #
53| _060_real_access() #
54|################################
55
56|
57| Each IO routine checks to see if the memory write/read is to/from user
58| or supervisor application space. The examples below use simple "move"
59| instructions for supervisor mode applications and call _copyin()/_copyout()
60| for user mode applications.
61| When installing the 060SP, the _copyin()/_copyout() equivalents for a
62| given operating system should be substituted.
63|
64| The addresses within the 060SP are guaranteed to be on the stack.
65| The result is that Unix processes are allowed to sleep as a consequence
66| of a page fault during a _copyout.
67|
68| Linux/68k: The _060_[id]mem_{read,write}_{byte,word,long} functions
69| (i.e. all the known length <= 4) are implemented by single moves
70| statements instead of (more expensive) copy{in,out} calls, if
71| working in user space
72
73|
74| _060_dmem_write():
75|
76| Writes to data memory while in supervisor mode.
77|
78| INPUTS:
79| a0 - supervisor source address
80| a1 - user destination address
81| d0 - number of bytes to write
82| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
83| OUTPUTS:
84| d1 - 0 = success, !0 = failure
85|
86 .global _060_dmem_write
87_060_dmem_write:
88 subq.l #1,%d0
89 btst #0x5,0x4(%a6) | check for supervisor state
90 beqs user_write
91super_write:
92 move.b (%a0)+,(%a1)+ | copy 1 byte
93 dbra %d0,super_write | quit if --ctr < 0
94 clr.l %d1 | return success
95 rts
96user_write:
97 move.b (%a0)+,%d1 | copy 1 byte
98copyoutae:
99 movs.b %d1,(%a1)+
100 dbra %d0,user_write | quit if --ctr < 0
101 clr.l %d1 | return success
102 rts
103
104|
105| _060_imem_read(), _060_dmem_read():
106|
107| Reads from data/instruction memory while in supervisor mode.
108|
109| INPUTS:
110| a0 - user source address
111| a1 - supervisor destination address
112| d0 - number of bytes to read
113| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
114| OUTPUTS:
115| d1 - 0 = success, !0 = failure
116|
117 .global _060_imem_read
118 .global _060_dmem_read
119_060_imem_read:
120_060_dmem_read:
121 subq.l #1,%d0
122 btst #0x5,0x4(%a6) | check for supervisor state
123 beqs user_read
124super_read:
125 move.b (%a0)+,(%a1)+ | copy 1 byte
126 dbra %d0,super_read | quit if --ctr < 0
127 clr.l %d1 | return success
128 rts
129user_read:
130copyinae:
131 movs.b (%a0)+,%d1
132 move.b %d1,(%a1)+ | copy 1 byte
133 dbra %d0,user_read | quit if --ctr < 0
134 clr.l %d1 | return success
135 rts
136
137|
138| _060_dmem_read_byte():
139|
140| Read a data byte from user memory.
141|
142| INPUTS:
143| a0 - user source address
144| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
145| OUTPUTS:
146| d0 - data byte in d0
147| d1 - 0 = success, !0 = failure
148|
149 .global _060_dmem_read_byte
150_060_dmem_read_byte:
151 clr.l %d0 | clear whole longword
152 clr.l %d1 | assume success
153 btst #0x5,0x4(%a6) | check for supervisor state
154 bnes dmrbs | supervisor
155dmrbuae:movs.b (%a0),%d0 | fetch user byte
156 rts
157dmrbs: move.b (%a0),%d0 | fetch super byte
158 rts
159
160|
161| _060_dmem_read_word():
162|
163| Read a data word from user memory.
164|
165| INPUTS:
166| a0 - user source address
167| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
168| OUTPUTS:
169| d0 - data word in d0
170| d1 - 0 = success, !0 = failure
171|
172| _060_imem_read_word():
173|
174| Read an instruction word from user memory.
175|
176| INPUTS:
177| a0 - user source address
178| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
179| OUTPUTS:
180| d0 - instruction word in d0
181| d1 - 0 = success, !0 = failure
182|
183 .global _060_dmem_read_word
184 .global _060_imem_read_word
185_060_dmem_read_word:
186_060_imem_read_word:
187 clr.l %d1 | assume success
188 clr.l %d0 | clear whole longword
189 btst #0x5,0x4(%a6) | check for supervisor state
190 bnes dmrws | supervisor
191dmrwuae:movs.w (%a0), %d0 | fetch user word
192 rts
193dmrws: move.w (%a0), %d0 | fetch super word
194 rts
195
196|
197| _060_dmem_read_long():
198|
199
200|
201| INPUTS:
202| a0 - user source address
203| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
204| OUTPUTS:
205| d0 - data longword in d0
206| d1 - 0 = success, !0 = failure
207|
208| _060_imem_read_long():
209|
210| Read an instruction longword from user memory.
211|
212| INPUTS:
213| a0 - user source address
214| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
215| OUTPUTS:
216| d0 - instruction longword in d0
217| d1 - 0 = success, !0 = failure
218|
219 .global _060_dmem_read_long
220 .global _060_imem_read_long
221_060_dmem_read_long:
222_060_imem_read_long:
223 clr.l %d1 | assume success
224 btst #0x5,0x4(%a6) | check for supervisor state
225 bnes dmrls | supervisor
226dmrluae:movs.l (%a0),%d0 | fetch user longword
227 rts
228dmrls: move.l (%a0),%d0 | fetch super longword
229 rts
230
231|
232| _060_dmem_write_byte():
233|
234| Write a data byte to user memory.
235|
236| INPUTS:
237| a0 - user destination address
238| d0 - data byte in d0
239| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
240| OUTPUTS:
241| d1 - 0 = success, !0 = failure
242|
243 .global _060_dmem_write_byte
244_060_dmem_write_byte:
245 clr.l %d1 | assume success
246 btst #0x5,0x4(%a6) | check for supervisor state
247 bnes dmwbs | supervisor
248dmwbuae:movs.b %d0,(%a0) | store user byte
249 rts
250dmwbs: move.b %d0,(%a0) | store super byte
251 rts
252
253|
254| _060_dmem_write_word():
255|
256| Write a data word to user memory.
257|
258| INPUTS:
259| a0 - user destination address
260| d0 - data word in d0
261| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
262| OUTPUTS:
263| d1 - 0 = success, !0 = failure
264|
265 .global _060_dmem_write_word
266_060_dmem_write_word:
267 clr.l %d1 | assume success
268 btst #0x5,0x4(%a6) | check for supervisor state
269 bnes dmwws | supervisor
270dmwwu:
271dmwwuae:movs.w %d0,(%a0) | store user word
272 bras dmwwr
273dmwws: move.w %d0,(%a0) | store super word
274dmwwr: clr.l %d1 | return success
275 rts
276
277|
278| _060_dmem_write_long():
279|
280| Write a data longword to user memory.
281|
282| INPUTS:
283| a0 - user destination address
284| d0 - data longword in d0
285| 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode
286| OUTPUTS:
287| d1 - 0 = success, !0 = failure
288|
289 .global _060_dmem_write_long
290_060_dmem_write_long:
291 clr.l %d1 | assume success
292 btst #0x5,0x4(%a6) | check for supervisor state
293 bnes dmwls | supervisor
294dmwluae:movs.l %d0,(%a0) | store user longword
295 rts
296dmwls: move.l %d0,(%a0) | store super longword
297 rts
298
299
300#if 0
301|###############################################
302
303|
304| Use these routines if your kernel doesn't have _copyout/_copyin equivalents.
305| Assumes that D0/D1/A0/A1 are scratch registers. The _copyin/_copyout
306| below assume that the SFC/DFC have been set previously.
307|
308| Linux/68k: These are basically non-inlined versions of
309| memcpy_{to,from}fs, but without long-transfer optimization
310| Note: Assumed that SFC/DFC are pointing correctly to user data
311| space... Should be right, or are there any exceptions?
312
313|
314| int _copyout(supervisor_addr, user_addr, nbytes)
315|
316 .global _copyout
317_copyout:
318 move.l 4(%sp),%a0 | source
319 move.l 8(%sp),%a1 | destination
320 move.l 12(%sp),%d0 | count
321 subq.l #1,%d0
322moreout:
323 move.b (%a0)+,%d1 | fetch supervisor byte
324copyoutae:
325 movs.b %d1,(%a1)+ | store user byte
326 dbra %d0,moreout | are we through yet?
327 moveq #0,%d0 | return success
328 rts
329
330|
331| int _copyin(user_addr, supervisor_addr, nbytes)
332|
333 .global _copyin
334_copyin:
335 move.l 4(%sp),%a0 | source
336 move.l 8(%sp),%a1 | destination
337 move.l 12(%sp),%d0 | count
338 subq.l #1,%d0
339morein:
340copyinae:
341 movs.b (%a0)+,%d1 | fetch user byte
342 move.b %d1,(%a1)+ | write supervisor byte
343 dbra %d0,morein | are we through yet?
344 moveq #0,%d0 | return success
345 rts
346#endif
347
348|###########################################################################
349
350|
351| _060_real_trace():
352|
353| This is the exit point for the 060FPSP when an instruction is being traced
354| and there are no other higher priority exceptions pending for this instruction
355| or they have already been processed.
356|
357| The sample code below simply executes an "rte".
358|
359 .global _060_real_trace
360_060_real_trace:
361 bral trap
362
363|
364| _060_real_access():
365|
366| This is the exit point for the 060FPSP when an access error exception
367| is encountered. The routine below should point to the operating system
368| handler for access error exceptions. The exception stack frame is an
369| 8-word access error frame.
370|
371| The sample routine below simply executes an "rte" instruction which
372| is most likely the incorrect thing to do and could put the system
373| into an infinite loop.
374|
375 .global _060_real_access
376_060_real_access:
377 bral buserr
378
379
380
381| Execption handling for movs access to illegal memory
382 .section .fixup,#alloc,#execinstr
383 .even
3841: moveq #-1,%d1
385 rts
386.section __ex_table,#alloc
387 .align 4
388 .long dmrbuae,1b
389 .long dmrwuae,1b
390 .long dmrluae,1b
391 .long dmwbuae,1b
392 .long dmwwuae,1b
393 .long dmwluae,1b
394 .long copyoutae,1b
395 .long copyinae,1b
396 .text
diff --git a/arch/m68k/ifpsp060/pfpsp.sa b/arch/m68k/ifpsp060/pfpsp.sa
new file mode 100644
index 000000000000..d276b27f1f6f
--- /dev/null
+++ b/arch/m68k/ifpsp060/pfpsp.sa
@@ -0,0 +1,1730 @@
1 dc.l $60ff0000,$17400000,$60ff0000,$15f40000
2 dc.l $60ff0000,$02b60000,$60ff0000,$04700000
3 dc.l $60ff0000,$1b100000,$60ff0000,$19aa0000
4 dc.l $60ff0000,$1b5a0000,$60ff0000,$062e0000
5 dc.l $60ff0000,$102c0000,$51fc51fc,$51fc51fc
6 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
7 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
8 dc.l $51fc51fc,$51fc51fc,$51fc51fc,$51fc51fc
9 dc.l $2f00203a,$ff2c487b,$0930ffff,$fef8202f
10 dc.l $00044e74,$00042f00,$203afef2,$487b0930
11 dc.l $fffffee2,$202f0004,$4e740004,$2f00203a
12 dc.l $fee0487b,$0930ffff,$fecc202f,$00044e74
13 dc.l $00042f00,$203afed2,$487b0930,$fffffeb6
14 dc.l $202f0004,$4e740004,$2f00203a,$fea4487b
15 dc.l $0930ffff,$fea0202f,$00044e74,$00042f00
16 dc.l $203afe96,$487b0930,$fffffe8a,$202f0004
17 dc.l $4e740004,$2f00203a,$fe7c487b,$0930ffff
18 dc.l $fe74202f,$00044e74,$00042f00,$203afe76
19 dc.l $487b0930,$fffffe5e,$202f0004,$4e740004
20 dc.l $2f00203a,$fe68487b,$0930ffff,$fe48202f
21 dc.l $00044e74,$00042f00,$203afe56,$487b0930
22 dc.l $fffffe32,$202f0004,$4e740004,$2f00203a
23 dc.l $fe44487b,$0930ffff,$fe1c202f,$00044e74
24 dc.l $00042f00,$203afe32,$487b0930,$fffffe06
25 dc.l $202f0004,$4e740004,$2f00203a,$fe20487b
26 dc.l $0930ffff,$fdf0202f,$00044e74,$00042f00
27 dc.l $203afe1e,$487b0930,$fffffdda,$202f0004
28 dc.l $4e740004,$2f00203a,$fe0c487b,$0930ffff
29 dc.l $fdc4202f,$00044e74,$00042f00,$203afdfa
30 dc.l $487b0930,$fffffdae,$202f0004,$4e740004
31 dc.l $2f00203a,$fde8487b,$0930ffff,$fd98202f
32 dc.l $00044e74,$00042f00,$203afdd6,$487b0930
33 dc.l $fffffd82,$202f0004,$4e740004,$2f00203a
34 dc.l $fdc4487b,$0930ffff,$fd6c202f,$00044e74
35 dc.l $00042f00,$203afdb2,$487b0930,$fffffd56
36 dc.l $202f0004,$4e740004,$2f00203a,$fda0487b
37 dc.l $0930ffff,$fd40202f,$00044e74,$00042f00
38 dc.l $203afd8e,$487b0930,$fffffd2a,$202f0004
39 dc.l $4e740004,$2f00203a,$fd7c487b,$0930ffff
40 dc.l $fd14202f,$00044e74,$00042f00,$203afd6a
41 dc.l $487b0930,$fffffcfe,$202f0004,$4e740004
42 dc.l $40c62d38,$d3d64634,$3d6f90ae,$b1e75cc7
43 dc.l $40000000,$c90fdaa2,$2168c235,$00000000
44 dc.l $3fff0000,$c90fdaa2,$2168c235,$00000000
45 dc.l $3fe45f30,$6dc9c883,$4e56ff40,$f32eff6c
46 dc.l $48ee0303,$ff9cf22e,$bc00ff60,$f22ef0c0
47 dc.l $ffdc2d6e,$ff68ff44,$206eff44,$58aeff44
48 dc.l $61ffffff,$ff042d40,$ff40082e,$0005ff42
49 dc.l $66000116,$41eeff6c,$61ff0000,$051c41ee
50 dc.l $ff6c61ff,$00002aec,$1d40ff4e,$082e0005
51 dc.l $ff436726,$e9ee0183,$ff4261ff,$00005cac
52 dc.l $41eeff78,$61ff0000,$2aca0c00,$00066606
53 dc.l $61ff0000,$2a2e1d40,$ff4f4280,$102eff63
54 dc.l $122eff43,$0241007f,$02ae00ff,$01ffff64
55 dc.l $f23c9000,$00000000,$f23c8800,$00000000
56 dc.l $41eeff6c,$43eeff78,$223b1530,$00001974
57 dc.l $4ebb1930,$0000196c,$e9ee0183,$ff4261ff
58 dc.l $00005cd8,$082e0004,$ff626622,$082e0001
59 dc.l $ff626644,$f22ed0c0,$ffdcf22e,$9c00ff60
60 dc.l $4cee0303,$ff9c4e5e,$60ffffff,$fcc6f22e
61 dc.l $f040ff6c,$3d7ce005,$ff6ef22e,$d0c0ffdc
62 dc.l $f22e9c00,$ff604cee,$0303ff9c,$f36eff6c
63 dc.l $4e5e60ff,$fffffcb2,$f22ef040,$ff6c1d7c
64 dc.l $00c4000b,$3d7ce001,$ff6ef22e,$d0c0ffdc
65 dc.l $f22e9c00,$ff604cee,$0303ff9c,$f36eff6c
66 dc.l $4e5e60ff,$fffffcae,$1d7c0000,$ff4e4280
67 dc.l $102eff63,$02aeffff,$00ffff64,$f23c9000
68 dc.l $00000000,$f23c8800,$00000000,$41eeff6c
69 dc.l $61ff0000,$2e0c082e,$0004ff62,$6600ff70
70 dc.l $082e0001,$ff626600,$ff90f22e,$d0c0ffdc
71 dc.l $f22e9c00,$ff604cee,$0303ff9c,$4e5e0817
72 dc.l $000767ff,$fffffc0c,$f22fa400,$00083f7c
73 dc.l $20240006,$60ffffff,$fcec4e56,$ff40f32e
74 dc.l $ff6c48ee,$0303ff9c,$f22ebc00,$ff60f22e
75 dc.l $f0c0ffdc,$2d6eff68,$ff44206e,$ff4458ae
76 dc.l $ff4461ff,$fffffd42,$2d40ff40,$082e0005
77 dc.l $ff426600,$013241ee,$ff6c61ff,$0000035a
78 dc.l $41eeff6c,$61ff0000,$292a1d40,$ff4e082e
79 dc.l $0005ff43,$672e082e,$0004ff43,$6626e9ee
80 dc.l $0183ff42,$61ff0000,$5ae241ee,$ff7861ff
81 dc.l $00002900,$0c000006,$660661ff,$00002864
82 dc.l $1d40ff4f,$4280102e,$ff63122e,$ff430241
83 dc.l $007f02ae,$00ff01ff,$ff64f23c,$90000000
84 dc.l $0000f23c,$88000000,$000041ee,$ff6c43ee
85 dc.l $ff78223b,$15300000,$17aa4ebb,$19300000
86 dc.l $17a2e9ee,$0183ff42,$61ff0000,$5b0e082e
87 dc.l $0003ff62,$6622082e,$0001ff62,$664ef22e
88 dc.l $d0c0ffdc,$f22e9c00,$ff604cee,$0303ff9c
89 dc.l $4e5e60ff,$fffffafc,$082e0003,$ff666700
90 dc.l $ffd6f22e,$f040ff6c,$3d7ce003,$ff6ef22e
91 dc.l $d0c0ffdc,$f22e9c00,$ff604cee,$0303ff9c
92 dc.l $f36eff6c,$4e5e60ff,$fffffaf4,$082e0001
93 dc.l $ff666700,$ffaaf22e,$f040ff6c,$1d7c00c4
94 dc.l $000b3d7c,$e001ff6e,$f22ed0c0,$ffdcf22e
95 dc.l $9c00ff60,$4cee0303,$ff9cf36e,$ff6c4e5e
96 dc.l $60ffffff,$fad01d7c,$0000ff4e,$4280102e
97 dc.l $ff6302ae,$ffff00ff,$ff64f23c,$90000000
98 dc.l $0000f23c,$88000000,$000041ee,$ff6c61ff
99 dc.l $00002c2e,$082e0003,$ff626600,$ff66082e
100 dc.l $0001ff62,$6600ff90,$f22ed0c0,$ffdcf22e
101 dc.l $9c00ff60,$4cee0303,$ff9c4e5e,$08170007
102 dc.l $67ffffff,$fa2ef22f,$a4000008,$3f7c2024
103 dc.l $000660ff,$fffffb0e,$4e56ff40,$f32eff6c
104 dc.l $48ee0303,$ff9cf22e,$bc00ff60,$f22ef0c0
105 dc.l $ffdc082e,$00050004,$66084e68,$2d48ffd8
106 dc.l $600841ee,$00102d48,$ffd82d6e,$ff68ff44
107 dc.l $206eff44,$58aeff44,$61ffffff,$fb4c2d40
108 dc.l $ff40422e,$ff4a082e,$0005ff42,$66000208
109 dc.l $e9ee0006,$ff420c00,$00136700,$049e02ae
110 dc.l $00ff00ff,$ff64f23c,$90000000,$0000f23c
111 dc.l $88000000,$000041ee,$ff6c61ff,$0000013a
112 dc.l $41eeff6c,$61ff0000,$270a0c00,$00066606
113 dc.l $61ff0000,$266e1d40,$ff4ee9ee,$0183ff42
114 dc.l $082e0005,$ff436728,$0c2e003a,$ff436720
115 dc.l $61ff0000,$58b641ee,$ff7861ff,$000026d4
116 dc.l $0c000006,$660661ff,$00002638,$1d40ff4f
117 dc.l $4280102e,$ff63e9ee,$1047ff43,$41eeff6c
118 dc.l $43eeff78,$223b1d30,$00001598,$4ebb1930
119 dc.l $00001590,$102eff62,$6634102e,$ff430200
120 dc.l $00380c00,$0038670c,$e9ee0183,$ff4261ff
121 dc.l $000058e8,$f22ed0c0,$ffdcf22e,$9c00ff60
122 dc.l $4cee0303,$ff9c4e5e,$60ffffff,$f8e6c02e
123 dc.l $ff66edc0,$06086614,$082e0004,$ff6667ba
124 dc.l $082e0001,$ff6267b2,$60000066,$04800000
125 dc.l $00180c00,$00066614,$082e0003,$ff666600
126 dc.l $004a082e,$0004ff66,$66000046,$2f0061ff
127 dc.l $000007e0,$201f3d7b,$0222ff6e,$f22ed0c0
128 dc.l $ffdcf22e,$9c00ff60,$4cee0303,$ff9cf36e
129 dc.l $ff6c4e5e,$60ffffff,$f87ae000,$e006e004
130 dc.l $e005e003,$e002e001,$e001303c,$000460bc
131 dc.l $303c0003,$60b6e9ee,$0006ff42,$0c000011
132 dc.l $67080c00,$00156750,$4e753028,$00000240
133 dc.l $7fff0c40,$3f806708,$0c40407f,$672c4e75
134 dc.l $02a87fff,$ffff0004,$671861ff,$000024cc
135 dc.l $44400640,$3f810268,$80000000,$81680000
136 dc.l $4e750268,$80000000,$4e750228,$007f0004
137 dc.l $00687fff,$00004e75,$30280000,$02407fff
138 dc.l $0c403c00,$67080c40,$43ff67de,$4e7502a8
139 dc.l $7fffffff,$00046606,$4aa80008,$67c461ff
140 dc.l $00002478,$44400640,$3c010268,$80000000
141 dc.l $81680000,$4e75e9ee,$00c3ff42,$0c000003
142 dc.l $670004a2,$0c000007,$6700049a,$02aeffff
143 dc.l $00ffff64,$f23c9000,$00000000,$f23c8800
144 dc.l $00000000,$302eff6c,$02407fff,$671041ee
145 dc.l $ff6c61ff,$0000246c,$1d40ff4e,$60061d7c
146 dc.l $0004ff4e,$4280102e,$ff6341ee,$ff6c2d56
147 dc.l $ffd461ff,$0000292a,$102eff62,$66000086
148 dc.l $2caeffd4,$082e0005,$00046626,$206effd8
149 dc.l $4e60f22e,$d0c0ffdc,$f22e9c00,$ff604cee
150 dc.l $0303ff9c,$4e5e0817,$0007667a,$60ffffff
151 dc.l $f7220c2e,$0008ff4a,$66d8f22e,$f080ff6c
152 dc.l $f22ed0c0,$ffdcf22e,$9c00ff60,$4cee0303
153 dc.l $ff9c2c56,$2f6f00c4,$00b82f6f,$00c800bc
154 dc.l $2f6f002c,$00c42f6f,$003000c8,$2f6f0034
155 dc.l $00ccdffc,$000000b8,$08170007,$662860ff
156 dc.l $fffff6d0,$c02eff66,$edc00608,$662a082e
157 dc.l $0004ff66,$6700ff6a,$082e0001,$ff626700
158 dc.l $ff606000,$01663f7c,$20240006,$f22fa400
159 dc.l $000860ff,$fffff78e,$04800000,$0018303b
160 dc.l $020a4efb,$00064afc,$00080000,$0000003a
161 dc.l $00640094,$00000140,$0000f22e,$d0c0ffdc
162 dc.l $f22e9c00,$ff604cee,$0303ff9c,$3d7c30d8
163 dc.l $000a3d7c,$e006ff6e,$f36eff6c,$4e5e60ff
164 dc.l $fffff6d4,$f22ed0c0,$ffdcf22e,$9c00ff60
165 dc.l $4cee0303,$ff9c3d7c,$30d0000a,$3d7ce004
166 dc.l $ff6ef36e,$ff6c4e5e,$60ffffff,$f694f22e
167 dc.l $f040ff6c,$f22ed0c0,$ffdcf22e,$9c00ff60
168 dc.l $4cee0303,$ff9c3d7c,$30d4000a,$3d7ce005
169 dc.l $ff6ef36e,$ff6c4e5e,$60ffffff,$f60c2cae
170 dc.l $ffd4082e,$00050004,$66000038,$206effd8
171 dc.l $4e60f22e,$f040ff6c,$f22ed0c0,$ffdcf22e
172 dc.l $9c00ff60,$4cee0303,$ff9c3d7c,$30cc000a
173 dc.l $3d7ce003,$ff6ef36e,$ff6c4e5e,$60ffffff
174 dc.l $f5de0c2e,$0008ff4a,$66c8f22e,$f080ff6c
175 dc.l $f22ef040,$ff78f22e,$d0c0ffdc,$f22e9c00
176 dc.l $ff604cee,$0303ff9c,$3d7c30cc,$000a3d7c
177 dc.l $e003ff7a,$f36eff78,$2c562f6f,$00c400b8
178 dc.l $2f6f00c8,$00bc2f6f,$00cc00c0,$2f6f002c
179 dc.l $00c42f6f,$003000c8,$2f6f0034,$00ccdffc
180 dc.l $000000b8,$60ffffff,$f576f22e,$f040ff6c
181 dc.l $f22ed0c0,$ffdcf22e,$9c00ff60,$4cee0303
182 dc.l $ff9c3d7c,$30c4000a,$3d7ce001,$ff6ef36e
183 dc.l $ff6c4e5e,$60ffffff,$f55c02ae,$00ff00ff
184 dc.l $ff64f23c,$90000000,$0000f23c,$88000000
185 dc.l $000061ff,$00005548,$41eeff6c,$61ff0000
186 dc.l $22721d40,$ff4ee9ee,$0183ff42,$082e0005
187 dc.l $ff436728,$0c2e003a,$ff436720,$61ff0000
188 dc.l $542a41ee,$ff7861ff,$00002248,$0c000006
189 dc.l $660661ff,$000021ac,$1d40ff4f,$4280102e
190 dc.l $ff63e9ee,$1047ff43,$41eeff6c,$43eeff78
191 dc.l $223b1d30,$0000110c,$4ebb1930,$00001104
192 dc.l $102eff62,$6600008a,$102eff43,$02000038
193 dc.l $0c000038,$670ce9ee,$0183ff42,$61ff0000
194 dc.l $545a082e,$00050004,$6600002a,$206effd8
195 dc.l $4e60f22e,$d0c0ffdc,$f22e9c00,$ff604cee
196 dc.l $0303ff9c,$4e5e0817,$00076600,$012660ff
197 dc.l $fffff440,$082e0002,$ff4a67d6,$f22ed0c0
198 dc.l $ffdcf22e,$9c00ff60,$4cee0303,$ff9c4e5e
199 dc.l $2f6f0004,$00102f6f,$0000000c,$dffc0000
200 dc.l $000c0817,$00076600,$00ea60ff,$fffff404
201 dc.l $c02eff66,$edc00608,$6618082e,$0004ff66
202 dc.l $6700ff66,$082e0001,$ff626700,$ff5c6000
203 dc.l $006e0480,$00000018,$0c000006,$6d14082e
204 dc.l $0003ff66,$66000060,$082e0004,$ff666600
205 dc.l $004e082e,$00050004,$66000054,$206effd8
206 dc.l $4e603d7b,$022aff6e,$f22ed0c0,$ffdcf22e
207 dc.l $9c00ff60,$4cee0303,$ff9cf36e,$ff6c4e5e
208 dc.l $08170007,$6600006c,$60ffffff,$f386e000
209 dc.l $e006e004,$e005e003,$e002e001,$e001303c
210 dc.l $00036000,$ffae303c,$00046000,$ffa6082e
211 dc.l $0002ff4a,$67ac3d7b,$02d6ff6e,$f22ed0c0
212 dc.l $ffdcf22e,$9c00ff60,$4cee0303,$ff9cf36e
213 dc.l $ff6c4e5e,$2f6f0004,$00102f6f,$0000000c
214 dc.l $dffc0000,$000c0817,$00076606,$60ffffff
215 dc.l $f3223f7c,$20240006,$f22fa400,$000860ff
216 dc.l $fffff402,$02aeffff,$00ffff64,$f23c9000
217 dc.l $00000000,$f23c8800,$00000000,$e9ee0183
218 dc.l $ff4261ff,$000051b4,$41eeff6c,$61ff0000
219 dc.l $20620c00,$00066606,$61ff0000,$1fc61d40
220 dc.l $ff4e4280,$102eff63,$41eeff6c,$2d56ffd4
221 dc.l $61ff0000,$248c102e,$ff626600,$00842cae
222 dc.l $ffd4082e,$00050004,$6628206e,$ffd84e60
223 dc.l $f22ed0c0,$ffdcf22e,$9c00ff60,$4cee0303
224 dc.l $ff9c4e5e,$08170007,$6600ff68,$60ffffff
225 dc.l $f282082e,$0003ff4a,$67d6f22e,$d0c0ffdc
226 dc.l $f22e9c00,$ff604cee,$0303ff9c,$2c562f6f
227 dc.l $00c400b8,$2f6f00c8,$00bc2f6f,$003800c4
228 dc.l $2f6f003c,$00c82f6f,$004000cc,$dffc0000
229 dc.l $00b80817,$00076600,$ff1a60ff,$fffff234
230 dc.l $c02eff66,$edc00608,$6700ff74,$2caeffd4
231 dc.l $0c00001a,$6e0000e8,$67000072,$082e0005
232 dc.l $0004660a,$206effd8,$4e606000,$fb8e0c2e
233 dc.l $0008ff4a,$6600fb84,$f22ed0c0,$ffdcf22e
234 dc.l $9c00ff60,$4cee0303,$ff9c3d7c,$30d8000a
235 dc.l $3d7ce006,$ff6ef36e,$ff6c2c56,$2f6f00c4
236 dc.l $00b82f6f,$00c800bc,$2f6f00cc,$00c02f6f
237 dc.l $003800c4,$2f6f003c,$00c82f6f,$004000cc
238 dc.l $dffc0000,$00b860ff,$fffff22c,$082e0005
239 dc.l $00046600,$000c206e,$ffd84e60,$6000fb46
240 dc.l $0c2e0008,$ff4a6600,$fb3cf22e,$d0c0ffdc
241 dc.l $f22e9c00,$ff604cee,$0303ff9c,$3d7c30d0
242 dc.l $000a3d7c,$e004ff6e,$f36eff6c,$2c562f6f
243 dc.l $00c400b8,$2f6f00c8,$00bc2f6f,$00cc00c0
244 dc.l $2f6f0038,$00c42f6f,$003c00c8,$2f6f0040
245 dc.l $00ccdffc,$000000b8,$60ffffff,$f1a4082e
246 dc.l $00050004,$6600000c,$206effd8,$4e606000
247 dc.l $fbda0c2e,$0008ff4a,$6600fbd0,$f22ed0c0
248 dc.l $ffdcf22e,$9c00ff60,$4cee0303,$ff9c3d7c
249 dc.l $30c4000a,$3d7ce001,$ff6ef36e,$ff6c2c56
250 dc.l $2f6f00c4,$00b82f6f,$00c800bc,$2f6f00cc
251 dc.l $00c02f6f,$003800c4,$2f6f003c,$00c82f6f
252 dc.l $004000cc,$dffc0000,$00b860ff,$fffff106
253 dc.l $e9ee00c3,$ff420c00,$00016708,$0c000005
254 dc.l $67344e75,$302eff6c,$02407fff,$67260c40
255 dc.l $3f806e20,$44400640,$3f81222e,$ff70e0a9
256 dc.l $08c1001f,$2d41ff70,$026e8000,$ff6c006e
257 dc.l $3f80ff6c,$4e75302e,$ff6c0240,$7fff673a
258 dc.l $0c403c00,$6e344a2e,$ff6c5bee,$ff6e3d40
259 dc.l $ff6c4280,$41eeff6c,$323c3c01,$61ff0000
260 dc.l $1a66303c,$3c004a2e,$ff6e6704,$08c0000f
261 dc.l $08ee0007,$ff703d40,$ff6c4e75,$082e0005
262 dc.l $000467ff,$fffff176,$2d680000,$ff782d68
263 dc.l $0004ff7c,$2d680008,$ff804281,$4e752f00
264 dc.l $4e7a0808,$08000001,$66000460,$201f4e56
265 dc.l $ff4048ee,$0303ff9c,$f22ebc00,$ff60f22e
266 dc.l $f0c0ffdc,$2d6e0006,$ff44206e,$ff4458ae
267 dc.l $ff4461ff,$fffff152,$2d40ff40,$4a406b00
268 dc.l $020e02ae,$00ff00ff,$ff640800,$000a6618
269 dc.l $206eff44,$43eeff6c,$700c61ff,$fffff0d2
270 dc.l $4a816600,$04926048,$206eff44,$43eeff6c
271 dc.l $700c61ff,$fffff0ba,$4a816600,$047ae9ee
272 dc.l $004fff6c,$0c407fff,$6726102e,$ff6f0200
273 dc.l $000f660c,$4aaeff70,$66064aae,$ff746710
274 dc.l $41eeff6c,$61ff0000,$501af22e,$f080ff6c
275 dc.l $06ae0000,$000cff44,$41eeff6c,$61ff0000
276 dc.l $1cd21d40,$ff4e0c00,$0006660a,$61ff0000
277 dc.l $1c321d40,$ff4e422e,$ff53082e,$0005ff43
278 dc.l $6748082e,$0004ff43,$662ce9ee,$0183ff42
279 dc.l $61ff0000,$4e7641ee,$ff7861ff,$00001c94
280 dc.l $1d40ff4f,$0c000006,$662061ff,$00001bf4
281 dc.l $1d40ff4f,$6014082e,$0003ff43,$670c50ee
282 dc.l $ff53082e,$0001ff43,$67c04280,$102eff63
283 dc.l $122eff43,$0241007f,$f23c9000,$00000000
284 dc.l $f23c8800,$00000000,$41eeff6c,$43eeff78
285 dc.l $223b1530,$00000b2c,$4ebb1930,$00000b24
286 dc.l $102eff62,$66404a2e,$ff53660c,$e9ee0183
287 dc.l $ff4261ff,$00004e84,$2d6e0006,$ff682d6e
288 dc.l $ff440006,$f22ed0c0,$ffdcf22e,$9c00ff60
289 dc.l $4cee0303,$ff9c4e5e,$08170007,$66000096
290 dc.l $60ffffff,$ee6ec02e,$ff66edc0,$06086612
291 dc.l $082e0004,$ff6667ae,$082e0001,$ff6267ac
292 dc.l $60340480,$00000018,$0c000006,$6610082e
293 dc.l $0004ff66,$6620082e,$0003ff66,$66203d7b
294 dc.l $0206ff6e,$601ee002,$e006e004,$e005e003
295 dc.l $e002e001,$e0013d7c,$e005ff6e,$60063d7c
296 dc.l $e003ff6e,$2d6e0006,$ff682d6e,$ff440006
297 dc.l $f22ed0c0,$ffdcf22e,$9c00ff60,$4cee0303
298 dc.l $ff9cf36e,$ff6c4e5e,$08170007,$660660ff
299 dc.l $ffffede0,$2f173f6f,$00080004,$3f7c2024
300 dc.l $0006f22f,$a4000008,$60ffffff,$eeb80800
301 dc.l $000e6700,$01c2082e,$00050004,$66164e68
302 dc.l $2d48ffd8,$61ff0000,$0bce206e,$ffd84e60
303 dc.l $600001aa,$422eff4a,$41ee000c,$2d48ffd8
304 dc.l $61ff0000,$0bb20c2e,$0008ff4a,$67000086
305 dc.l $0c2e0004,$ff4a6600,$0184082e,$00070004
306 dc.l $66363dae,$00040804,$2daeff44,$08063dbc
307 dc.l $00f0080a,$41f60804,$2d480004,$f22ed0c0
308 dc.l $ffdcf22e,$9c00ff60,$4cee0303,$ff9c4e5e
309 dc.l $2e5f60ff,$ffffed3c,$3dae0004,$08002dae
310 dc.l $ff440802,$3dbc2024,$08062dae,$00060808
311 dc.l $41f60800,$2d480004,$f22ed0c0,$ffdcf22e
312 dc.l $9c00ff60,$4cee0303,$ff9c4e5e,$2e5f60ff
313 dc.l $ffffedf2,$1d41000a,$1d40000b,$f22ed0c0
314 dc.l $ffdcf22e,$9c00ff60,$4cee0303,$ff9c2f16
315 dc.l $2f002f01,$2f2eff44,$4280102e,$000b4480
316 dc.l $082e0007,$0004671c,$3dae0004,$08002dae
317 dc.l $00060808,$2d9f0802,$3dbc2024,$08064876
318 dc.l $08006014,$3dae0004,$08042d9f,$08063dbc
319 dc.l $00f0080a,$48760804,$4281122e,$000a4a01
320 dc.l $6a0cf236,$f080080c,$06800000,$000ce309
321 dc.l $6a0cf236,$f040080c,$06800000,$000ce309
322 dc.l $6a0cf236,$f020080c,$06800000,$000ce309
323 dc.l $6a0cf236,$f010080c,$06800000,$000ce309
324 dc.l $6a0cf236,$f008080c,$06800000,$000ce309
325 dc.l $6a0cf236,$f004080c,$06800000,$000ce309
326 dc.l $6a0cf236,$f002080c,$06800000,$000ce309
327 dc.l $6a06f236,$f001080c,$222f0004,$202f0008
328 dc.l $2c6f000c,$2e5f0817,$000767ff,$ffffec04
329 dc.l $60ffffff,$ecf061ff,$00001244,$f22ed0c0
330 dc.l $ffdcf22e,$9c00ff60,$4cee0303,$ff9c082e
331 dc.l $00070004,$660e2d6e,$ff440006,$4e5e60ff
332 dc.l $ffffebd0,$2c563f6f,$00c400c0,$2f6f00c6
333 dc.l $00c82f6f,$000400c2,$3f7c2024,$00c6dffc
334 dc.l $000000c0,$60ffffff,$ec9c201f,$4e56ff40
335 dc.l $48ee0303,$ff9c2d6e,$0006ff44,$206eff44
336 dc.l $58aeff44,$61ffffff,$ed002d40,$ff404a40
337 dc.l $6b047010,$60260800,$000e6610,$e9c014c3
338 dc.l $700c0c01,$00076614,$58806010,$428061ff
339 dc.l $00000ce6,$202eff44,$90ae0006,$3d40000a
340 dc.l $4cee0303,$ff9c4e5e,$518f2f00,$3f6f000c
341 dc.l $00042f6f,$000e0006,$4280302f,$00122f6f
342 dc.l $00060010,$d1af0006,$3f7c402c,$000a201f
343 dc.l $60ffffff,$ebe44e7a,$08080800,$0001660c
344 dc.l $f22e9c00,$ff60f22e,$d0c0ffdc,$4cee0303
345 dc.l $ff9c4e5e,$514f2eaf,$00083f6f,$000c0004
346 dc.l $3f7c4008,$00062f6f,$00020008,$2f7c0942
347 dc.l $8001000c,$08170005,$670608ef,$0002000d
348 dc.l $60ffffff,$ebd64fee,$ff404e7a,$18080801
349 dc.l $0001660c,$f22ed0c0,$ffdcf22f,$9c000020
350 dc.l $2c562f6f,$00c400bc,$3f6f00c8,$00c03f7c
351 dc.l $400800c2,$2f4800c4,$3f4000c8,$3f7c0001
352 dc.l $00ca4cef,$0303005c,$defc00bc,$60a64e56
353 dc.l $ff40f32e,$ff6c48ee,$0303ff9c,$f22ebc00
354 dc.l $ff60f22e,$f0c0ffdc,$2d6eff68,$ff44206e
355 dc.l $ff4458ae,$ff4461ff,$ffffebce,$2d40ff40
356 dc.l $0800000d,$662841ee,$ff6c61ff,$fffff1ea
357 dc.l $f22ed0c0,$ffdcf22e,$9c00ff60,$4cee0303
358 dc.l $ff9cf36e,$ff6c4e5e,$60ffffff,$ea94322e
359 dc.l $ff6c0241,$7fff0c41,$7fff661a,$4aaeff74
360 dc.l $660c222e,$ff700281,$7fffffff,$67082d6e
361 dc.l $ff70ff54,$6012223c,$7fffffff,$4a2eff6c
362 dc.l $6a025281,$2d41ff54,$e9c004c3,$122eff41
363 dc.l $307b0206,$4efb8802,$006c0000,$0000ff98
364 dc.l $003e0000,$00100000,$102eff54,$0c010007
365 dc.l $6f16206e,$000c61ff,$ffffeb86,$4a8166ff
366 dc.l $00005436,$6000ff6a,$02410007,$61ff0000
367 dc.l $478e6000,$ff5c302e,$ff540c01,$00076f16
368 dc.l $206e000c,$61ffffff,$eb6e4a81,$66ff0000
369 dc.l $54166000,$ff3c0241,$000761ff,$00004724
370 dc.l $6000ff2e,$202eff54,$0c010007,$6f16206e
371 dc.l $000c61ff,$ffffeb56,$4a8166ff,$000053f6
372 dc.l $6000ff0e,$02410007,$61ff0000,$46ba6000
373 dc.l $ff004e56,$ff40f32e,$ff6c48ee,$0303ff9c
374 dc.l $f22ebc00,$ff60f22e,$f0c0ffdc,$2d6eff68
375 dc.l $ff44206e,$ff4458ae,$ff4461ff,$ffffea8a
376 dc.l $2d40ff40,$0800000d,$6600002a,$41eeff6c
377 dc.l $61ffffff,$f0a4f22e,$d0c0ffdc,$f22e9c00
378 dc.l $ff604cee,$0303ff9c,$f36eff6c,$4e5e60ff
379 dc.l $ffffe964,$e9c004c3,$122eff41,$307b0206
380 dc.l $4efb8802,$007400a6,$015a0000,$00420104
381 dc.l $00100000,$102eff70,$08c00006,$0c010007
382 dc.l $6f16206e,$000c61ff,$ffffea76,$4a8166ff
383 dc.l $00005326,$6000ffa0,$02410007,$61ff0000
384 dc.l $467e6000,$ff92302e,$ff7008c0,$000e0c01
385 dc.l $00076f16,$206e000c,$61ffffff,$ea5a4a81
386 dc.l $66ff0000,$53026000,$ff6e0241,$000761ff
387 dc.l $00004610,$6000ff60,$202eff70,$08c0001e
388 dc.l $0c010007,$6f16206e,$000c61ff,$ffffea3e
389 dc.l $4a8166ff,$000052de,$6000ff3c,$02410007
390 dc.l $61ff0000,$45a26000,$ff2e0c01,$00076f2e
391 dc.l $202eff6c,$02808000,$00000080,$7fc00000
392 dc.l $222eff70,$e0898081,$206e000c,$61ffffff
393 dc.l $e9fc4a81,$66ff0000,$529c6000,$fefa202e
394 dc.l $ff6c0280,$80000000,$00807fc0,$00002f01
395 dc.l $222eff70,$e0898081,$221f0241,$000761ff
396 dc.l $00004544,$6000fed0,$202eff6c,$02808000
397 dc.l $00000080,$7ff80000,$222eff70,$2d40ff84
398 dc.l $700be0a9,$83aeff84,$222eff70,$02810000
399 dc.l $07ffe0b9,$2d41ff88,$222eff74,$e0a983ae
400 dc.l $ff8841ee,$ff84226e,$000c7008,$61ffffff
401 dc.l $e8cc4a81,$66ff0000,$522a6000,$fe7a422e
402 dc.l $ff4a3d6e,$ff6cff84,$426eff86,$202eff70
403 dc.l $08c0001e,$2d40ff88,$2d6eff74,$ff8c082e
404 dc.l $00050004,$66384e68,$2d48ffd8,$2d56ffd4
405 dc.l $61ff0000,$02c22248,$2d48000c,$206effd8
406 dc.l $4e602cae,$ffd441ee,$ff84700c,$61ffffff
407 dc.l $e86c4a81,$66ff0000,$51d86000,$fe1a2d56
408 dc.l $ffd461ff,$00000290,$22482d48,$000c2cae
409 dc.l $ffd40c2e,$0008ff4a,$66ccf22e,$d0c0ffdc
410 dc.l $f22e9c00,$ff604cee,$0303ff9c,$f36eff6c
411 dc.l $2c6effd4,$2f6f00c4,$00b82f6f,$00c800bc
412 dc.l $2f6f00cc,$00c02f6f,$004400c4,$2f6f0048
413 dc.l $00c82f6f,$004c00cc,$dffc0000,$00b860ff
414 dc.l $ffffe734,$4e56ff40,$f32eff6c,$48ee0303
415 dc.l $ff9cf22e,$bc00ff60,$f22ef0c0,$ffdc2d6e
416 dc.l $ff68ff44,$206eff44,$58aeff44,$61ffffff
417 dc.l $e7f82d40,$ff400800,$000d6600,$0106e9c0
418 dc.l $04c36622,$0c6e401e,$ff6c661a,$f23c9000
419 dc.l $00000000,$f22e4000,$ff70f22e,$6800ff6c
420 dc.l $3d7ce001,$ff6e41ee,$ff6c61ff,$ffffedea
421 dc.l $02ae00ff,$01ffff64,$f23c9000,$00000000
422 dc.l $f23c8800,$00000000,$e9ee1006,$ff420c01
423 dc.l $00176700,$009641ee,$ff6c61ff,$00001394
424 dc.l $1d40ff4e,$082e0005,$ff43672e,$082e0004
425 dc.l $ff436626,$e9ee0183,$ff4261ff,$0000454c
426 dc.l $41eeff78,$61ff0000,$136a0c00,$00066606
427 dc.l $61ff0000,$12ce1d40,$ff4f4280,$102eff63
428 dc.l $122eff43,$0241007f,$41eeff6c,$43eeff78
429 dc.l $223b1530,$0000022c,$4ebb1930,$00000224
430 dc.l $e9ee0183,$ff4261ff,$00004590,$f22ed0c0
431 dc.l $ffdcf22e,$9c00ff60,$4cee0303,$ff9cf36e
432 dc.l $ff6c4e5e,$60ffffff,$e5cc4280,$102eff63
433 dc.l $122eff43,$02810000,$007f61ff,$00000396
434 dc.l $60be1d7c,$0000ff4e,$4280102e,$ff6302ae
435 dc.l $ffff00ff,$ff6441ee,$ff6c61ff,$00001722
436 dc.l $60aa4e56,$ff40f32e,$ff6c48ee,$0303ff9c
437 dc.l $f22ebc00,$ff60f22e,$f0c0ffdc,$2d6eff68
438 dc.l $ff44206e,$ff4458ae,$ff4461ff,$ffffe69a
439 dc.l $2d40ff40,$41eeff6c,$61ffffff,$ecbcf22e
440 dc.l $d0c0ffdc,$f22e9c00,$ff604cee,$0303ff9c
441 dc.l $f36eff6c,$4e5e60ff,$ffffe592,$0c6f402c
442 dc.l $000667ff,$ffffe5b2,$60ffffff,$e5962040
443 dc.l $102eff41,$22000240,$00380281,$00000007
444 dc.l $0c000018,$67240c00,$0020672c,$80410c00
445 dc.l $003c6706,$206e000c,$4e751d7c,$0080ff4a
446 dc.l $41f60162,$ff680004,$4e752008,$61ff0000
447 dc.l $42ca206e,$000c4e75,$200861ff,$0000430c
448 dc.l $206e000c,$0c00000c,$67024e75,$51882d48
449 dc.l $000c4e75,$102eff41,$22000240,$00380281
450 dc.l $00000007,$0c000018,$670e0c00,$00206700
451 dc.l $0076206e,$000c4e75,$323b120e,$206e000c
452 dc.l $4efb1006,$4afc0008,$0010001a,$0024002c
453 dc.l $0034003c,$0044004e,$06ae0000,$000cffa4
454 dc.l $4e7506ae,$0000000c,$ffa84e75,$d5fc0000
455 dc.l $000c4e75,$d7fc0000,$000c4e75,$d9fc0000
456 dc.l $000c4e75,$dbfc0000,$000c4e75,$06ae0000
457 dc.l $000cffd4,$4e751d7c,$0004ff4a,$06ae0000
458 dc.l $000cffd8,$4e75323b,$1214206e,$000c5188
459 dc.l $51ae000c,$4efb1006,$4afc0008,$00100016
460 dc.l $001c0020,$00240028,$002c0032,$2d48ffa4
461 dc.l $4e752d48,$ffa84e75,$24484e75,$26484e75
462 dc.l $28484e75,$2a484e75,$2d48ffd4,$4e752d48
463 dc.l $ffd81d7c,$0008ff4a,$4e754afc,$006d0000
464 dc.l $20700000,$2a660000,$00000000,$2b0a0000
465 dc.l $3db20000,$00000000,$00000000,$00000000
466 dc.l $00000000,$00000000,$00000000,$00000000
467 dc.l $00000000,$00000000,$00000000,$00000000
468 dc.l $00000000,$00000000,$00000000,$00000000
469 dc.l $00000000,$00000000,$00000000,$00000000
470 dc.l $2bb00000,$00000000,$27460000,$00000000
471 dc.l $00000000,$00000000,$00000000,$00000000
472 dc.l $233c0000,$00000000,$36220000,$1c7c0000
473 dc.l $32f20000,$00000000,$00000000,$2fb00000
474 dc.l $39ea0000,$00000000,$00000000,$00000000
475 dc.l $00000000,$00000000,$00000000,$00000000
476 dc.l $00000000,$00000000,$00000000,$00000000
477 dc.l $00000000,$00000000,$00000000,$00000000
478 dc.l $2e4e0000,$00000000,$29f40000,$00000000
479 dc.l $00000000,$00000000,$00000000,$00000000
480 dc.l $205e0000,$3da00000,$00000000,$00000000
481 dc.l $20680000,$3daa0000,$00000000,$00000000
482 dc.l $00000000,$00000000,$00000000,$00000000
483 dc.l $00000000,$00000000,$00000000,$00000000
484 dc.l $00000000,$00000000,$00000000,$00000000
485 dc.l $00000000,$00000000,$00000000,$00000000
486 dc.l $2b9e0000,$00000000,$27340000,$00000000
487 dc.l $2ba80000,$00000000,$273e0000,$00000000
488 dc.l $232a0000,$00000000,$36100000,$1c6a0000
489 dc.l $23340000,$00000000,$361a0000,$1c740000
490 dc.l $39d80000,$00000000,$00000000,$00000000
491 dc.l $39e260fe,$122eff43,$02410070,$e80961ff
492 dc.l $00003ed2,$02800000,$00ff2f00,$103b0920
493 dc.l $01482f00,$61ff0000,$0340201f,$221f6700
494 dc.l $0134082e,$0005ff42,$670000b8,$082e0004
495 dc.l $ff426600,$001a123b,$1120021e,$082e0005
496 dc.l $0004670a,$0c2e0008,$ff4a6602,$4e752248
497 dc.l $9fc041d7,$4a016a0c,$20eeffdc,$20eeffe0
498 dc.l $20eeffe4,$e3096a0c,$20eeffe8,$20eeffec
499 dc.l $20eefff0,$e3096a0a,$f210f020,$d1fc0000
500 dc.l $000ce309,$6a0af210,$f010d1fc,$0000000c
501 dc.l $e3096a0a,$f210f008,$d1fc0000,$000ce309
502 dc.l $6a0af210,$f004d1fc,$0000000c,$e3096a0a
503 dc.l $f210f002,$d1fc0000,$000ce309,$6a0af210
504 dc.l $f001d1fc,$0000000c,$2d49ff54,$41d72f00
505 dc.l $61ffffff,$e248201f,$dfc04a81,$6600071e
506 dc.l $4e752d48,$ff549fc0,$43d72f01,$2f0061ff
507 dc.l $ffffe214,$201f4a81,$6600070e,$221f41d7
508 dc.l $4a016a0c,$2d58ffdc,$2d58ffe0,$2d58ffe4
509 dc.l $e3096a0c,$2d58ffe8,$2d58ffec,$2d58fff0
510 dc.l $e3096a04,$f218d020,$e3096a04,$f218d010
511 dc.l $e3096a04,$f218d008,$e3096a04,$f218d004
512 dc.l $e3096a04,$f218d002,$e3096a04,$f218d001
513 dc.l $dfc04e75,$4e75000c,$0c180c18,$18240c18
514 dc.l $18241824,$24300c18,$18241824,$24301824
515 dc.l $24302430,$303c0c18,$18241824,$24301824
516 dc.l $24302430,$303c1824,$24302430,$303c2430
517 dc.l $303c303c,$3c480c18,$18241824,$24301824
518 dc.l $24302430,$303c1824,$24302430,$303c2430
519 dc.l $303c303c,$3c481824,$24302430,$303c2430
520 dc.l $303c303c,$3c482430,$303c303c,$3c48303c
521 dc.l $3c483c48,$48540c18,$18241824,$24301824
522 dc.l $24302430,$303c1824,$24302430,$303c2430
523 dc.l $303c303c,$3c481824,$24302430,$303c2430
524 dc.l $303c303c,$3c482430,$303c303c,$3c48303c
525 dc.l $3c483c48,$48541824,$24302430,$303c2430
526 dc.l $303c303c,$3c482430,$303c303c,$3c48303c
527 dc.l $3c483c48,$48542430,$303c303c,$3c48303c
528 dc.l $3c483c48,$4854303c,$3c483c48,$48543c48
529 dc.l $48544854,$54600080,$40c020a0,$60e01090
530 dc.l $50d030b0,$70f00888,$48c828a8,$68e81898
531 dc.l $58d838b8,$78f80484,$44c424a4,$64e41494
532 dc.l $54d434b4,$74f40c8c,$4ccc2cac,$6cec1c9c
533 dc.l $5cdc3cbc,$7cfc0282,$42c222a2,$62e21292
534 dc.l $52d232b2,$72f20a8a,$4aca2aaa,$6aea1a9a
535 dc.l $5ada3aba,$7afa0686,$46c626a6,$66e61696
536 dc.l $56d636b6,$76f60e8e,$4ece2eae,$6eee1e9e
537 dc.l $5ede3ebe,$7efe0181,$41c121a1,$61e11191
538 dc.l $51d131b1,$71f10989,$49c929a9,$69e91999
539 dc.l $59d939b9,$79f90585,$45c525a5,$65e51595
540 dc.l $55d535b5,$75f50d8d,$4dcd2dad,$6ded1d9d
541 dc.l $5ddd3dbd,$7dfd0383,$43c323a3,$63e31393
542 dc.l $53d333b3,$73f30b8b,$4bcb2bab,$6beb1b9b
543 dc.l $5bdb3bbb,$7bfb0787,$47c727a7,$67e71797
544 dc.l $57d737b7,$77f70f8f,$4fcf2faf,$6fef1f9f
545 dc.l $5fdf3fbf,$7fff2040,$302eff40,$32000240
546 dc.l $003f0281,$00000007,$303b020a,$4efb0006
547 dc.l $4afc0040,$00000000,$00000000,$00000000
548 dc.l $00000000,$00000000,$00000000,$00000000
549 dc.l $00000000,$00800086,$008c0090,$00940098
550 dc.l $009c00a0,$00a600b6,$00c600d2,$00de00ea
551 dc.l $00f60102,$01180126,$0134013e,$01480152
552 dc.l $015c0166,$017a0198,$01b601d2,$01ee020a
553 dc.l $02260242,$02600260,$02600260,$02600260
554 dc.l $02600260,$02c002da,$02f40314,$00000000
555 dc.l $00000000,$206effa4,$4e75206e,$ffa84e75
556 dc.l $204a4e75,$204b4e75,$204c4e75,$204d4e75
557 dc.l $20564e75,$206effd8,$4e75202e,$ffa42200
558 dc.l $d2882d41,$ffa42040,$4e75202e,$ffa82200
559 dc.l $d2882d41,$ffa82040,$4e75200a,$2200d288
560 dc.l $24412040,$4e75200b,$2200d288,$26412040
561 dc.l $4e75200c,$2200d288,$28412040,$4e75200d
562 dc.l $2200d288,$2a412040,$4e752016,$2200d288
563 dc.l $2c812040,$4e751d7c,$0004ff4a,$202effd8
564 dc.l $2200d288,$2d41ffd8,$20404e75,$202effa4
565 dc.l $90882d40,$ffa42040,$4e75202e,$ffa89088
566 dc.l $2d40ffa8,$20404e75,$200a9088,$24402040
567 dc.l $4e75200b,$90882640,$20404e75,$200c9088
568 dc.l $28402040,$4e75200d,$90882a40,$20404e75
569 dc.l $20169088,$2c802040,$4e751d7c,$0008ff4a
570 dc.l $202effd8,$90882d40,$ffd82040,$4e75206e
571 dc.l $ff4454ae,$ff4461ff,$ffffde38,$4a8166ff
572 dc.l $fffff1b6,$3040d1ee,$ffa44e75,$206eff44
573 dc.l $54aeff44,$61ffffff,$de1a4a81,$66ffffff
574 dc.l $f1983040,$d1eeffa8,$4e75206e,$ff4454ae
575 dc.l $ff4461ff,$ffffddfc,$4a8166ff,$fffff17a
576 dc.l $3040d1ca,$4e75206e,$ff4454ae,$ff4461ff
577 dc.l $ffffdde0,$4a8166ff,$fffff15e,$3040d1cb
578 dc.l $4e75206e,$ff4454ae,$ff4461ff,$ffffddc4
579 dc.l $4a8166ff,$fffff142,$3040d1cc,$4e75206e
580 dc.l $ff4454ae,$ff4461ff,$ffffdda8,$4a8166ff
581 dc.l $fffff126,$3040d1cd,$4e75206e,$ff4454ae
582 dc.l $ff4461ff,$ffffdd8c,$4a8166ff,$fffff10a
583 dc.l $3040d1d6,$4e75206e,$ff4454ae,$ff4461ff
584 dc.l $ffffdd70,$4a8166ff,$fffff0ee,$3040d1ee
585 dc.l $ffd84e75,$508161ff,$000038fa,$2f00206e
586 dc.l $ff4454ae,$ff4461ff,$ffffdd48,$4a8166ff
587 dc.l $fffff0c6,$205f0800,$00086600,$00e62d40
588 dc.l $ff542200,$e9590241,$000f61ff,$000038c6
589 dc.l $2f02242e,$ff540802,$000b6602,$48c02202
590 dc.l $ef590281,$00000003,$e3a849c2,$d082d1c0
591 dc.l $241f4e75,$206eff44,$54aeff44,$61ffffff
592 dc.l $dcf24a81,$66ffffff,$f0703040,$4e75206e
593 dc.l $ff4458ae,$ff4461ff,$ffffdcee,$4a8166ff
594 dc.l $fffff056,$20404e75,$206eff44,$54aeff44
595 dc.l $61ffffff,$dcbe4a81,$66ffffff,$f03c3040
596 dc.l $d1eeff44,$55884e75,$206eff44,$54aeff44
597 dc.l $61ffffff,$dc9e4a81,$66ffffff,$f01c206e
598 dc.l $ff445588,$08000008,$66000038,$2d40ff54
599 dc.l $2200e959,$0241000f,$61ff0000,$38182f02
600 dc.l $242eff54,$0802000b,$660248c0,$2202ef59
601 dc.l $02810000,$0003e3a8,$49c2d082,$d1c0241f
602 dc.l $4e750800,$0006670c,$48e73c00,$2a002608
603 dc.l $42826028,$2d40ff54,$e9c01404,$61ff0000
604 dc.l $37d448e7,$3c002400,$2a2eff54,$26080805
605 dc.l $000b6602,$48c2e9c5,$0542e1aa,$08050007
606 dc.l $67024283,$e9c50682,$0c000002,$6d346718
607 dc.l $206eff44,$58aeff44,$61ffffff,$dc0c4a81
608 dc.l $66ff0000,$00b06018,$206eff44,$54aeff44
609 dc.l $61ffffff,$dbde4a81,$66ff0000,$009848c0
610 dc.l $d680e9c5,$07826700,$006e0c00,$00026d34
611 dc.l $6718206e,$ff4458ae,$ff4461ff,$ffffdbca
612 dc.l $4a8166ff,$0000006e,$601c206e,$ff4454ae
613 dc.l $ff4461ff,$ffffdb9c,$4a8166ff,$00000056
614 dc.l $48c06002,$42802800,$08050002,$67142043
615 dc.l $61ffffff,$dbd64a81,$66000028,$d082d084
616 dc.l $6018d682,$204361ff,$ffffdbc0,$4a816600
617 dc.l $0012d084,$6004d682,$20032040,$4cdf003c
618 dc.l $4e752043,$4cdf003c,$303c0101,$60ffffff
619 dc.l $ef184cdf,$003c60ff,$ffffeebe,$61ff0000
620 dc.l $44ea303c,$00e1600a,$61ff0000,$44de303c
621 dc.l $0161206e,$ff5460ff,$ffffeeee,$102eff42
622 dc.l $0c00009c,$670000b2,$0c000098,$67000074
623 dc.l $0c000094,$6736206e,$ff4458ae,$ff4461ff
624 dc.l $ffffdb06,$4a8166ff,$ffffee6e,$2d40ff64
625 dc.l $206eff44,$58aeff44,$61ffffff,$daec4a81
626 dc.l $66ffffff,$ee542d40,$ff684e75,$206eff44
627 dc.l $58aeff44,$61ffffff,$dad04a81,$66ffffff
628 dc.l $ee382d40,$ff60206e,$ff4458ae,$ff4461ff
629 dc.l $ffffdab6,$4a8166ff,$ffffee1e,$2d40ff68
630 dc.l $4e75206e,$ff4458ae,$ff4461ff,$ffffda9a
631 dc.l $4a8166ff,$ffffee02,$2d40ff60,$206eff44
632 dc.l $58aeff44,$61ffffff,$da804a81,$66ffffff
633 dc.l $ede82d40,$ff644e75,$206eff44,$58aeff44
634 dc.l $61ffffff,$da644a81,$66ffffff,$edcc2d40
635 dc.l $ff60206e,$ff4458ae,$ff4461ff,$ffffda4a
636 dc.l $4a8166ff,$ffffedb2,$2d40ff64,$206eff44
637 dc.l $58aeff44,$61ffffff,$da304a81,$66ffffff
638 dc.l $ed982d40,$ff684e75,$2d680004,$ff882d69
639 dc.l $0004ff94,$2d680008,$ff8c2d69,$0008ff98
640 dc.l $30280000,$32290000,$3d40ff84,$3d41ff90
641 dc.l $02407fff,$02417fff,$3d40ff54,$3d41ff56
642 dc.l $b0416cff,$0000005c,$61ff0000,$015a2f00
643 dc.l $0c2e0004,$ff4e6610,$41eeff84,$61ff0000
644 dc.l $04fa4440,$3d40ff54,$302eff56,$04400042
645 dc.l $b06eff54,$6c1a302e,$ff54d06f,$0002322e
646 dc.l $ff840241,$80008041,$3d40ff84,$201f4e75
647 dc.l $026e8000,$ff8408ee,$0000ff85,$201f4e75
648 dc.l $61ff0000,$00562f00,$0c2e0004,$ff4f6610
649 dc.l $41eeff90,$61ff0000,$04a24440,$3d40ff56
650 dc.l $302eff54,$04400042,$b06eff56,$6c1a302e
651 dc.l $ff56d06f,$0002322e,$ff900241,$80008041
652 dc.l $3d40ff90,$201f4e75,$026e8000,$ff9008ee
653 dc.l $0000ff91,$201f4e75,$322eff84,$30010281
654 dc.l $00007fff,$02408000,$00403fff,$3d40ff84
655 dc.l $0c2e0004,$ff4e670a,$203c0000,$3fff9081
656 dc.l $4e7541ee,$ff8461ff,$00000430,$44802200
657 dc.l $60e60c2e,$0004ff4e,$673a322e,$ff840281
658 dc.l $00007fff,$026e8000,$ff840801,$00006712
659 dc.l $006e3fff,$ff84203c,$00003fff,$9081e280
660 dc.l $4e75006e,$3ffeff84,$203c0000,$3ffe9081
661 dc.l $e2804e75,$41eeff84,$61ff0000,$03de0800
662 dc.l $00006710,$006e3fff,$ff840680,$00003fff
663 dc.l $e2804e75,$006e3ffe,$ff840680,$00003ffe
664 dc.l $e2804e75,$322eff90,$30010281,$00007fff
665 dc.l $02408000,$00403fff,$3d40ff90,$0c2e0004
666 dc.l $ff4f670a,$203c0000,$3fff9081,$4e7541ee
667 dc.l $ff9061ff,$00000384,$44802200,$60e60c2e
668 dc.l $0005ff4f,$67320c2e,$0003ff4f,$673e0c2e
669 dc.l $0003ff4e,$671408ee,$0006ff70,$00ae0100
670 dc.l $4080ff64,$41eeff6c,$604200ae,$01000000
671 dc.l $ff6441ee,$ff6c6034,$00ae0100,$4080ff64
672 dc.l $08ee0006,$ff7c41ee,$ff786020,$41eeff78
673 dc.l $0c2e0005,$ff4e66ff,$0000000c,$00ae0000
674 dc.l $4080ff64,$00ae0100,$0000ff64,$08280007
675 dc.l $00006708,$00ae0800,$0000ff64,$f210d080
676 dc.l $4e7500ae,$01002080,$ff64f23b,$d0800170
677 dc.l $00000008,$4e757fff,$0000ffff,$ffffffff
678 dc.l $ffff0000,$3f813c01,$e408323b,$02f63001
679 dc.l $90680000,$0c400042,$6a164280,$082e0001
680 dc.l $ff666704,$08c0001d,$61ff0000,$001a4e75
681 dc.l $203c2000,$00003141,$000042a8,$000442a8
682 dc.l $00084e75,$2d680008,$ff542d40,$ff582001
683 dc.l $92680000,$6f100c41,$00206d10,$0c410040
684 dc.l $6d506000,$009a202e,$ff584e75,$2f023140
685 dc.l $00007020,$90410c41,$001d6d08,$142eff58
686 dc.l $852eff57,$e9e82020,$0004e9e8,$18000004
687 dc.l $e9ee0800,$ff542142,$00042141,$0008e8c0
688 dc.l $009e6704,$08c0001d,$0280e000,$0000241f
689 dc.l $4e752f02,$31400000,$04410020,$70209041
690 dc.l $142eff58,$852eff57,$e9e82020,$0004e9e8
691 dc.l $18000004,$e8c1009e,$660ce8ee,$081fff54
692 dc.l $66042001,$60062001,$08c0001d,$42a80004
693 dc.l $21420008,$0280e000,$0000241f,$4e753140
694 dc.l $00000c41,$00416d12,$672442a8,$000442a8
695 dc.l $0008203c,$20000000,$4e752028,$00042200
696 dc.l $0280c000,$00000281,$3fffffff,$60122028
697 dc.l $00040280,$80000000,$e2880281,$7fffffff
698 dc.l $66164aa8,$00086610,$4a2eff58,$660a42a8
699 dc.l $000442a8,$00084e75,$08c0001d,$42a80004
700 dc.l $42a80008,$4e7561ff,$00000110,$4a806700
701 dc.l $00fa006e,$0208ff66,$327b1206,$4efb9802
702 dc.l $004000ea,$00240008,$4a280002,$6b0000dc
703 dc.l $70ff4841,$0c010004,$6700003e,$6e000094
704 dc.l $60000064,$4a280002,$6a0000c0,$70ff4841
705 dc.l $0c010004,$67000022,$6e000078,$60000048
706 dc.l $e3806400,$00a64841,$0c010004,$6700000a
707 dc.l $6e000060,$60000030,$06a80000,$01000004
708 dc.l $640ce4e8,$0004e4e8,$00065268,$00004a80
709 dc.l $66060268,$fe000006,$02a8ffff,$ff000004
710 dc.l $42a80008,$4e7552a8,$0008641a,$52a80004
711 dc.l $6414e4e8,$0004e4e8,$0006e4e8,$0008e4e8
712 dc.l $000a5268,$00004a80,$66060228,$00fe000b
713 dc.l $4e7506a8,$00000800,$0008641a,$52a80004
714 dc.l $6414e4e8,$0004e4e8,$0006e4e8,$0008e4e8
715 dc.l $000a5268,$00004a80,$66060268,$f000000a
716 dc.l $02a8ffff,$f8000008,$4e754841,$0c010004
717 dc.l $6700ff86,$6eea4e75,$48414a01,$66044841
718 dc.l $4e7548e7,$30000c01,$00046622,$e9e83602
719 dc.l $0004741e,$e5ab2428,$00040282,$0000003f
720 dc.l $66284aa8,$00086622,$4a80661e,$6020e9e8
721 dc.l $35420008,$741ee5ab,$24280008,$02820000
722 dc.l $01ff6606,$4a806602,$600408c3,$001d2003
723 dc.l $4cdf000c,$48414e75,$2f022f03,$20280004
724 dc.l $22280008,$edc02000,$671ae5a8,$e9c13022
725 dc.l $8083e5a9,$21400004,$21410008,$2002261f
726 dc.l $241f4e75,$edc12000,$e5a90682,$00000020
727 dc.l $21410004,$42a80008,$2002261f,$241f4e75
728 dc.l $ede80000,$0004660e,$ede80000,$00086700
729 dc.l $00740640,$00204281,$32280000,$02417fff
730 dc.l $b0416e1c,$92403028,$00000240,$80008240
731 dc.l $31410000,$61ffffff,$ff82103c,$00004e75
732 dc.l $0c010020,$6e20e9e8,$08400004,$21400004
733 dc.l $20280008,$e3a82140,$00080268,$80000000
734 dc.l $103c0004,$4e750441,$00202028,$0008e3a8
735 dc.l $21400004,$42a80008,$02688000,$0000103c
736 dc.l $00044e75,$02688000,$0000103c,$00014e75
737 dc.l $30280000,$02407fff,$0c407fff,$67480828
738 dc.l $00070004,$6706103c,$00004e75,$4a406618
739 dc.l $4aa80004,$660c4aa8,$00086606,$103c0001
740 dc.l $4e75103c,$00044e75,$4aa80004,$66124aa8
741 dc.l $0008660c,$02688000,$0000103c,$00014e75
742 dc.l $103c0006,$4e754aa8,$00086612,$20280004
743 dc.l $02807fff,$ffff6606,$103c0002,$4e750828
744 dc.l $00060004,$6706103c,$00034e75,$103c0005
745 dc.l $4e752028,$00002200,$02807ff0,$0000670e
746 dc.l $0c807ff0,$00006728,$103c0000,$4e750281
747 dc.l $000fffff,$66ff0000,$00144aa8,$000466ff
748 dc.l $0000000a,$103c0001,$4e75103c,$00044e75
749 dc.l $0281000f,$ffff66ff,$00000014,$4aa80004
750 dc.l $66ff0000,$000a103c,$00024e75,$08010013
751 dc.l $66ff0000,$000a103c,$00054e75,$103c0003
752 dc.l $4e752028,$00002200,$02807f80,$0000670e
753 dc.l $0c807f80,$0000671e,$103c0000,$4e750281
754 dc.l $007fffff,$66ff0000,$000a103c,$00014e75
755 dc.l $103c0004,$4e750281,$007fffff,$66ff0000
756 dc.l $000a103c,$00024e75,$08010016,$66ff0000
757 dc.l $000a103c,$00054e75,$103c0003,$4e752f01
758 dc.l $08280007,$000056e8,$00023228,$00000241
759 dc.l $7fff9240,$31410000,$2f08202f,$00040240
760 dc.l $00c0e848,$61ffffff,$fae22057,$322f0006
761 dc.l $024100c0,$e8494841,$322f0006,$02410030
762 dc.l $e84961ff,$fffffc22,$205f08a8,$00070000
763 dc.l $4a280002,$670a08e8,$00070000,$42280002
764 dc.l $42804aa8,$0004660a,$4aa80008,$660408c0
765 dc.l $0002082e,$0001ff66,$670608ee,$0005ff67
766 dc.l $588f4e75,$2f010828,$00070000,$56e80002
767 dc.l $32280000,$02417fff,$92403141,$00002f08
768 dc.l $428061ff,$fffffa64,$2057323c,$00044841
769 dc.l $322f0006,$02410030,$e84961ff,$fffffbaa
770 dc.l $205f08a8,$00070000,$4a280002,$670a08e8
771 dc.l $00070000,$42280002,$42804aa8,$0004660a
772 dc.l $4aa80008,$660408c0,$0002082e,$0001ff66
773 dc.l $670608ee,$0005ff67,$588f4e75,$02410010
774 dc.l $e8088200,$3001e309,$600e0241,$00108200
775 dc.l $48408200,$3001e309,$103b0008,$41fb1620
776 dc.l $4e750200,$00020200,$00020200,$00020000
777 dc.l $00000a08,$0a080a08,$0a080a08,$0a087fff
778 dc.l $00000000,$00000000,$00000000,$00007ffe
779 dc.l $0000ffff,$ffffffff,$ffff0000,$00007ffe
780 dc.l $0000ffff,$ffffffff,$ffff0000,$00007fff
781 dc.l $00000000,$00000000,$00000000,$00007fff
782 dc.l $00000000,$00000000,$00000000,$0000407e
783 dc.l $0000ffff,$ff000000,$00000000,$0000407e
784 dc.l $0000ffff,$ff000000,$00000000,$00007fff
785 dc.l $00000000,$00000000,$00000000,$00007fff
786 dc.l $00000000,$00000000,$00000000,$000043fe
787 dc.l $0000ffff,$ffffffff,$f8000000,$000043fe
788 dc.l $0000ffff,$ffffffff,$f8000000,$00007fff
789 dc.l $00000000,$00000000,$00000000,$00000000
790 dc.l $00000000,$00000000,$00000000,$00000000
791 dc.l $00000000,$00000000,$00000000,$00000000
792 dc.l $00000000,$00000000,$00000000,$00000000
793 dc.l $00000000,$00000000,$00000000,$0000ffff
794 dc.l $00000000,$00000000,$00000000,$0000fffe
795 dc.l $0000ffff,$ffffffff,$ffff0000,$0000ffff
796 dc.l $00000000,$00000000,$00000000,$0000fffe
797 dc.l $0000ffff,$ffffffff,$ffff0000,$0000ffff
798 dc.l $00000000,$00000000,$00000000,$0000c07e
799 dc.l $0000ffff,$ff000000,$00000000,$0000ffff
800 dc.l $00000000,$00000000,$00000000,$0000c07e
801 dc.l $0000ffff,$ff000000,$00000000,$0000ffff
802 dc.l $00000000,$00000000,$00000000,$0000c3fe
803 dc.l $0000ffff,$ffffffff,$f8000000,$0000ffff
804 dc.l $00000000,$00000000,$00000000,$0000c3fe
805 dc.l $0000ffff,$ffffffff,$f8000000,$0000e9ee
806 dc.l $10c3ff42,$327b120a,$4efb9806,$4afc0008
807 dc.l $00e001e0,$01480620,$0078041a,$00100620
808 dc.l $4a2eff4e,$664cf228,$d0800000,$f2009000
809 dc.l $f2007800,$f23c9000,$00000000,$f201a800
810 dc.l $836eff66,$122eff41,$02010038,$6714206e
811 dc.l $000c61ff,$ffffcfaa,$4a8166ff,$0000385a
812 dc.l $4e75122e,$ff410241,$000761ff,$00002bb0
813 dc.l $4e752228,$00000281,$80000000,$00810080
814 dc.l $0000f201,$440060a4,$4a2eff4e,$664cf228
815 dc.l $d0800000,$f2009000,$f2007000,$f23c9000
816 dc.l $00000000,$f201a800,$836eff66,$122eff41
817 dc.l $02010038,$6714206e,$000c61ff,$ffffcf58
818 dc.l $4a8166ff,$00003800,$4e75122e,$ff410241
819 dc.l $000761ff,$00002b0c,$4e752228,$00000281
820 dc.l $80000000,$00810080,$0000f201,$440060a4
821 dc.l $4a2eff4e,$664cf228,$d0800000,$f2009000
822 dc.l $f2006000,$f23c9000,$00000000,$f201a800
823 dc.l $836eff66,$122eff41,$02010038,$6714206e
824 dc.l $000c61ff,$ffffcf06,$4a8166ff,$000037a6
825 dc.l $4e75122e,$ff410241,$000761ff,$00002a68
826 dc.l $4e752228,$00000281,$80000000,$00810080
827 dc.l $0000f201,$440060a4,$3d680000,$ff84426e
828 dc.l $ff862d68,$0004ff88,$2d680008,$ff8cf228
829 dc.l $d0800000,$61ffffff,$e83e2248,$41eeff84
830 dc.l $700c0c2e,$0008ff4a,$672661ff,$ffffcdee
831 dc.l $4a816600,$00524a2e,$ff4e6602,$4e7508ee
832 dc.l $0003ff66,$102eff62,$0200000a,$66164e75
833 dc.l $61ffffff,$dc4a4a81,$6600002c,$4a2eff4e
834 dc.l $66dc4e75,$41eeff84,$61ffffff,$f90e4440
835 dc.l $02407fff,$026e8000,$ff84816e,$ff84f22e
836 dc.l $d040ff84,$4e752cae,$ffd460ff,$00003702
837 dc.l $02000030,$00000040,$2d40ff5c,$30280000
838 dc.l $02407fff,$0c40407e,$6e0000e6,$67000152
839 dc.l $0c403f81,$6d000058,$f228d080,$0000f22e
840 dc.l $9000ff5c,$f23c8800,$00000000,$f2006400
841 dc.l $f23c9000,$00000000,$f201a800,$836eff66
842 dc.l $122eff41,$02010038,$6714206e,$000c61ff
843 dc.l $ffffcdda,$4a8166ff,$0000367a,$4e75122e
844 dc.l $ff410241,$000761ff,$0000293c,$4e7508ee
845 dc.l $0003ff66,$3d680000,$ff842d68,$0004ff88
846 dc.l $2d680008,$ff8c2f08,$42800c2e,$0004ff4e
847 dc.l $660a41ee,$ff8461ff,$fffff840,$41eeff84
848 dc.l $222eff5c,$61ffffff,$fa5841ee,$ff8461ff
849 dc.l $0000034c,$122eff41,$02010038,$6714206e
850 dc.l $000c61ff,$ffffcd66,$4a8166ff,$00003606
851 dc.l $600e122e,$ff410241,$000761ff,$000028c8
852 dc.l $122eff62,$0201000a,$660000b8,$588f4e75
853 dc.l $4a280007,$660e4aa8,$00086608,$006e1048
854 dc.l $ff666006,$006e1248,$ff662f08,$4a280000
855 dc.l $5bc1202e,$ff5c61ff,$fffffae4,$f210d080
856 dc.l $f2006400,$122eff41,$02010038,$6714206e
857 dc.l $000c61ff,$ffffccf6,$4a8166ff,$00003596
858 dc.l $600e122e,$ff410241,$000761ff,$00002858
859 dc.l $122eff62,$0201000a,$6600007c,$588f4e75
860 dc.l $32280000,$02418000,$00413fff,$3d41ff84
861 dc.l $2d680004,$ff882d68,$0008ff8c,$f22e9000
862 dc.l $ff5cf22e,$4800ff84,$f23c9000,$00000000
863 dc.l $f2000018,$f23c5838,$0002f294,$fe7c6000
864 dc.l $ff50205f,$3d680000,$ff842d68,$0004ff88
865 dc.l $2d680008,$ff8c0c2e,$0004ff4e,$662c41ee
866 dc.l $ff8461ff,$fffff714,$44800240,$7fffefee
867 dc.l $004fff84,$6014205f,$3d680000,$ff842d68
868 dc.l $0004ff88,$2d680008,$ff8c08ae,$0007ff84
869 dc.l $56eeff86,$41eeff84,$122eff5f,$e8090241
870 dc.l $000c4841,$122eff5f,$e8090241,$00034280
871 dc.l $61ffffff,$f5544a2e,$ff866706,$08ee0007
872 dc.l $ff84f22e,$d040ff84,$4e750200,$00300000
873 dc.l $00802d40,$ff5c3028,$00000240,$7fff0c40
874 dc.l $43fe6e00,$00c86700,$01200c40,$3c016d00
875 dc.l $0046f228,$d0800000,$f22e9000,$ff5cf23c
876 dc.l $88000000,$0000f22e,$7400ff54,$f23c9000
877 dc.l $00000000,$f200a800,$816eff66,$226e000c
878 dc.l $41eeff54,$700861ff,$ffffcaf2,$4a8166ff
879 dc.l $00003450,$4e7508ee,$0003ff66,$3d680000
880 dc.l $ff842d68,$0004ff88,$2d680008,$ff8c2f08
881 dc.l $42800c2e,$0004ff4e,$660a41ee,$ff8461ff
882 dc.l $fffff618,$41eeff84,$222eff5c,$61ffffff
883 dc.l $f83041ee,$ff8461ff,$000000d2,$2d40ff54
884 dc.l $2d41ff58,$226e000c,$41eeff54,$700861ff
885 dc.l $ffffca8a,$4a8166ff,$000033e8,$122eff62
886 dc.l $0201000a,$6600fe9c,$588f4e75,$3028000a
887 dc.l $024007ff,$6608006e,$1048ff66,$6006006e
888 dc.l $1248ff66,$2f084a28,$00005bc1,$202eff5c
889 dc.l $61ffffff,$f8caf210,$d080f22e,$7400ff54
890 dc.l $226e000c,$41eeff54,$700861ff,$ffffca2e
891 dc.l $4a8166ff,$0000338c,$122eff62,$0201000a
892 dc.l $6600fe74,$588f4e75,$32280000,$02418000
893 dc.l $00413fff,$3d41ff84,$2d680004,$ff882d68
894 dc.l $0008ff8c,$f22e9000,$ff5cf22e,$4800ff84
895 dc.l $f23c9000,$00000000,$f2000018,$f23c5838
896 dc.l $0002f294,$feae6000,$ff644280,$30280000
897 dc.l $04403fff,$064003ff,$4a280004,$6b025340
898 dc.l $4840e988,$4a280000,$6a0408c0,$001f2228
899 dc.l $0004e9c1,$10548081,$2d40ff54,$22280004
900 dc.l $7015e1a9,$2d41ff58,$22280008,$e9c10015
901 dc.l $222eff58,$8280202e,$ff544e75,$42803028
902 dc.l $00000440,$3fff0640,$007f4a28,$00046b02
903 dc.l $53404840,$ef884a28,$00006a04,$08c0001f
904 dc.l $22280004,$02817fff,$ff00e089,$80814e75
905 dc.l $61ffffff,$e3822f08,$102eff4e,$66000082
906 dc.l $082e0004,$ff426712,$122eff43,$e8090241
907 dc.l $000761ff,$000024de,$6004102e,$ff43ebc0
908 dc.l $06472f00,$41eeff6c,$61ff0000,$2b2002ae
909 dc.l $cffff00f,$ff84201f,$4a2eff87,$66164aae
910 dc.l $ff886610,$4aaeff8c,$660a4a80,$6606026e
911 dc.l $f000ff84,$41eeff84,$225f700c,$0c2e0008
912 dc.l $ff4a670e,$61ffffff,$c8d44a81,$6600fb38
913 dc.l $4e7561ff,$ffffd748,$4a816600,$fb2a4e75
914 dc.l $0c000004,$6700ff7a,$41eeff6c,$426eff6e
915 dc.l $0c000005,$670260c0,$006e4080,$ff6608ee
916 dc.l $0006ff70,$60b251fc,$51fc51fc,$51fc51fc
917 dc.l $ffffc001,$ffffff81,$fffffc01,$00004000
918 dc.l $0000007f,$000003ff,$02000030,$00000040
919 dc.l $60080200,$00300000,$00802d40,$ff5c4241
920 dc.l $122eff4f,$e709822e,$ff4e6600,$02e43d69
921 dc.l $0000ff90,$2d690004,$ff942d69,$0008ff98
922 dc.l $3d680000,$ff842d68,$0004ff88,$2d680008
923 dc.l $ff8c61ff,$ffffef24,$2f0061ff,$ffffefc8
924 dc.l $d197322e,$ff5eec09,$201fb0bb,$14846700
925 dc.l $011e6d00,$0062b0bb,$14846700,$021a6e00
926 dc.l $014af22e,$d080ff90,$f22e9000,$ff5cf23c
927 dc.l $88000000,$0000f22e,$4823ff84,$f201a800
928 dc.l $f23c9000,$00000000,$83aeff64,$f22ef080
929 dc.l $ff842f02,$322eff84,$24010281,$00007fff
930 dc.l $02428000,$92808242,$3d41ff84,$241ff22e
931 dc.l $d080ff84,$4e75f22e,$d080ff90,$f22e9000
932 dc.l $ff5cf23c,$88000000,$0000f22e,$4823ff84
933 dc.l $f201a800,$f23c9000,$00000000,$83aeff64
934 dc.l $00ae0000,$1048ff64,$122eff62,$02010013
935 dc.l $661c082e,$0003ff64,$56c1202e,$ff5c61ff
936 dc.l $fffff5dc,$812eff64,$f210d080,$4e75222e
937 dc.l $ff5c0201,$00c06634,$f22ef080,$ff842f02
938 dc.l $322eff84,$34010281,$00007fff,$92800481
939 dc.l $00006000,$02417fff,$02428000,$82423d41
940 dc.l $ff84241f,$f22ed040,$ff8460a6,$f22ed080
941 dc.l $ff90222e,$ff5c0201,$0030f201,$9000f22e
942 dc.l $4823ff84,$f23c9000,$00000000,$60aaf22e
943 dc.l $d080ff90,$f22e9000,$ff5cf23c,$88000000
944 dc.l $0000f22e,$4823ff84,$f201a800,$f23c9000
945 dc.l $00000000,$83aeff64,$f2000098,$f23c58b8
946 dc.l $0002f293,$ff3c6000,$fee408ee,$0003ff66
947 dc.l $f22ed080,$ff90f23c,$90000000,$0010f23c
948 dc.l $88000000,$0000f22e,$4823ff84,$f201a800
949 dc.l $f23c9000,$00000000,$83aeff64,$122eff62
950 dc.l $0201000b,$6620f22e,$f080ff84,$41eeff84
951 dc.l $222eff5c,$61ffffff,$f3e8812e,$ff64f22e
952 dc.l $d080ff84,$4e75f22e,$d040ff90,$222eff5c
953 dc.l $020100c0,$6652f22e,$9000ff5c,$f23c8800
954 dc.l $00000000,$f22e48a3,$ff84f23c,$90000000
955 dc.l $0000f22e,$f040ff84,$2f02322e,$ff842401
956 dc.l $02810000,$7fff0242,$80009280,$06810000
957 dc.l $60000241,$7fff8242,$3d41ff84,$241ff22e
958 dc.l $d040ff84,$6000ff80,$222eff5c,$02010030
959 dc.l $f2019000,$60a6f22e,$d080ff90,$f22e9000
960 dc.l $ff5cf23c,$88000000,$0000f22e,$4823ff84
961 dc.l $f201a800,$f23c9000,$00000000,$83aeff64
962 dc.l $f2000098,$f23c58b8,$0002f292,$fde0f294
963 dc.l $fefaf22e,$d040ff90,$222eff5c,$020100c0
964 dc.l $00010010,$f2019000,$f23c8800,$00000000
965 dc.l $f22e48a3,$ff84f23c,$90000000,$0000f200
966 dc.l $0498f23c,$58b80002,$f293fda2,$6000febc
967 dc.l $323b120a,$4efb1006,$4afc0030,$fd120072
968 dc.l $00cc006c,$fd120066,$00000000,$00720072
969 dc.l $0060006c,$00720066,$00000000,$009e0060
970 dc.l $009e006c,$009e0066,$00000000,$006c006c
971 dc.l $006c006c,$006c0066,$00000000,$fd120072
972 dc.l $00cc006c,$fd120066,$00000000,$00660066
973 dc.l $00660066,$00660066,$00000000,$60ffffff
974 dc.l $ed6460ff,$ffffecda,$60ffffff,$ecd41028
975 dc.l $00001229,$0000b101,$6a10f23c,$44008000
976 dc.l $00001d7c,$000cff64,$4e75f23c,$44000000
977 dc.l $00001d7c,$0004ff64,$4e75f229,$d0800000
978 dc.l $10280000,$12290000,$b1016a10,$f2000018
979 dc.l $f200001a,$1d7c000a,$ff644e75,$f2000018
980 dc.l $1d7c0002,$ff644e75,$f228d080,$00001028
981 dc.l $00001229,$0000b101,$6ae260d0,$02000030
982 dc.l $00000040,$60080200,$00300000,$00802d40
983 dc.l $ff5c122e,$ff4e6600,$02620200,$00c06600
984 dc.l $007c4a28,$00006a06,$08ee0003,$ff64f228
985 dc.l $d0800000,$4e750200,$00c06600,$006008ee
986 dc.l $0003ff66,$4a280000,$6a0608ee,$0003ff64
987 dc.l $f228d080,$0000082e,$0003ff62,$66024e75
988 dc.l $3d680000,$ff842d68,$0004ff88,$2d680008
989 dc.l $ff8c41ee,$ff8461ff,$ffffef60,$44400640
990 dc.l $6000322e,$ff840241,$80000240,$7fff8041
991 dc.l $3d40ff84,$f22ed040,$ff844e75,$0c000040
992 dc.l $667e3d68,$0000ff84,$2d680004,$ff882d68
993 dc.l $0008ff8c,$61ffffff,$eac20c80,$0000007f
994 dc.l $6c000092,$0c80ffff,$ff816700,$01786d00
995 dc.l $00f4f23c,$88000000,$0000f22e,$9000ff5c
996 dc.l $f22e4800,$ff84f201,$a800f23c,$90000000
997 dc.l $000083ae,$ff642f02,$f22ef080,$ff84322e
998 dc.l $ff843401,$02810000,$7fff9280,$02428000
999 dc.l $84413d42,$ff84241f,$f22ed080,$ff844e75
1000 dc.l $3d680000,$ff842d68,$0004ff88,$2d680008
1001 dc.l $ff8c61ff,$ffffea44,$0c800000,$03ff6c00
1002 dc.l $00140c80,$fffffc01,$670000fa,$6d000076
1003 dc.l $6000ff80,$08ee0003,$ff664a2e,$ff846a06
1004 dc.l $08ee0003,$ff64122e,$ff620201,$000b661a
1005 dc.l $41eeff84,$222eff5c,$61ffffff,$f084812e
1006 dc.l $ff64f22e,$d080ff84,$4e752d6e,$ff88ff94
1007 dc.l $2d6eff8c,$ff98322e,$ff842f02,$34010281
1008 dc.l $00007fff,$92800242,$80000681,$00006000
1009 dc.l $02417fff,$84413d42,$ff90f22e,$d040ff90
1010 dc.l $241f60ac,$f23c8800,$00000000,$f22e9000
1011 dc.l $ff5cf22e,$4800ff84,$f23c9000,$00000000
1012 dc.l $f201a800,$83aeff64,$00ae0000,$1048ff64
1013 dc.l $122eff62,$02010013,$661c082e,$0003ff64
1014 dc.l $56c1202e,$ff5c61ff,$fffff0f4,$812eff64
1015 dc.l $f210d080,$4e752f02,$322eff84,$24010281
1016 dc.l $00007fff,$02428000,$92800481,$00006000
1017 dc.l $02417fff,$82423d41,$ff84241f,$f22ed040
1018 dc.l $ff8460b6,$f23c8800,$00000000,$f22e9000
1019 dc.l $ff5cf22e,$4800ff84,$f201a800,$f23c9000
1020 dc.l $00000000,$83aeff64,$f2000098,$f23c58b8
1021 dc.l $0002f293,$ff746000,$fe7e0c01,$00046700
1022 dc.l $fdb60c01,$000567ff,$ffffe9ee,$0c010003
1023 dc.l $67ffffff,$e9f8f228,$48000000,$f200a800
1024 dc.l $e1981d40,$ff644e75,$51fc51fc,$51fc51fc
1025 dc.l $00003fff,$0000007e,$000003fe,$ffffc001
1026 dc.l $ffffff81,$fffffc01,$02000030,$00000040
1027 dc.l $60080200,$00300000,$00802d40,$ff5c4241
1028 dc.l $122eff4f,$e709822e,$ff4e6600,$02d63d69
1029 dc.l $0000ff90,$2d690004,$ff942d69,$0008ff98
1030 dc.l $3d680000,$ff842d68,$0004ff88,$2d680008
1031 dc.l $ff8c61ff,$ffffe864,$2f0061ff,$ffffe908
1032 dc.l $4497d197,$322eff5e,$ec09201f,$b0bb148e
1033 dc.l $6f000074,$b0bb1520,$ff7a6700,$020c6e00
1034 dc.l $013cf22e,$d080ff90,$f22e9000,$ff5cf23c
1035 dc.l $88000000,$0000f22e,$4820ff84,$f201a800
1036 dc.l $f23c9000,$00000000,$83aeff64,$f22ef080
1037 dc.l $ff842f02,$322eff84,$24010281,$00007fff
1038 dc.l $02428000,$92808242,$3d41ff84,$241ff22e
1039 dc.l $d080ff84,$4e750000,$7fff0000,$407f0000
1040 dc.l $43ff201f,$60c62f00,$f22ed080,$ff90f22e
1041 dc.l $9000ff5c,$f23c8800,$00000000,$f22e4820
1042 dc.l $ff84f200,$a800f23c,$90000000,$000081ae
1043 dc.l $ff64f227,$e0013017,$dffc0000,$000c0280
1044 dc.l $00007fff,$9097b0bb,$14ae6db6,$201f00ae
1045 dc.l $00001048,$ff64122e,$ff620201,$0013661c
1046 dc.l $082e0003,$ff6456c1,$202eff5c,$61ffffff
1047 dc.l $eeee812e,$ff64f210,$d0804e75,$222eff5c
1048 dc.l $020100c0,$6634f22e,$f080ff84,$2f02322e
1049 dc.l $ff843401,$02810000,$7fff9280,$04810000
1050 dc.l $60000241,$7fff0242,$80008242,$3d41ff84
1051 dc.l $241ff22e,$d040ff84,$60a6f22e,$d080ff90
1052 dc.l $222eff5c,$02010030,$f2019000,$f22e4820
1053 dc.l $ff84f23c,$90000000,$000060aa,$08ee0003
1054 dc.l $ff66f22e,$d080ff90,$f23c9000,$00000010
1055 dc.l $f23c8800,$00000000,$f22e4820,$ff84f201
1056 dc.l $a800f23c,$90000000,$000083ae,$ff64122e
1057 dc.l $ff620201,$000b6620,$f22ef080,$ff8441ee
1058 dc.l $ff84222e,$ff5c61ff,$ffffed36,$812eff64
1059 dc.l $f22ed080,$ff844e75,$f22ed040,$ff90222e
1060 dc.l $ff5c0201,$00c06652,$f22e9000,$ff5cf23c
1061 dc.l $88000000,$0000f22e,$48a0ff84,$f23c9000
1062 dc.l $00000000,$f22ef040,$ff842f02,$322eff84
1063 dc.l $24010281,$00007fff,$02428000,$92800681
1064 dc.l $00006000,$02417fff,$82423d41,$ff84241f
1065 dc.l $f22ed040,$ff846000,$ff80222e,$ff5c0201
1066 dc.l $0030f201,$900060a6,$f22ed080,$ff90f22e
1067 dc.l $9000ff5c,$f23c8800,$00000000,$f22e4820
1068 dc.l $ff84f201,$a800f23c,$90000000,$000083ae
1069 dc.l $ff64f200,$0098f23c,$58b80001,$f292fdee
1070 dc.l $f294fefa,$f22ed040,$ff90222e,$ff5c0201
1071 dc.l $00c00001,$0010f201,$9000f23c,$88000000
1072 dc.l $0000f22e,$48a0ff84,$f23c9000,$00000000
1073 dc.l $f2000498,$f23c58b8,$0001f293,$fdb06000
1074 dc.l $febc323b,$120a4efb,$10064afc,$0030fd20
1075 dc.l $009e0072,$0060fd20,$00660000,$00000072
1076 dc.l $006c0072,$00600072,$00660000,$000000d0
1077 dc.l $00d0006c,$006000d0,$00660000,$00000060
1078 dc.l $00600060,$00600060,$00660000,$0000fd20
1079 dc.l $009e0072,$0060fd20,$00660000,$00000066
1080 dc.l $00660066,$00660066,$00660000,$000060ff
1081 dc.l $ffffe62e,$60ffffff,$e62860ff,$ffffe6a6
1082 dc.l $10280000,$12290000,$b1016a10,$f23c4400
1083 dc.l $80000000,$1d7c000c,$ff644e75,$f23c4400
1084 dc.l $00000000,$1d7c0004,$ff644e75,$006e0410
1085 dc.l $ff661028,$00001229,$0000b101,$6a10f23c
1086 dc.l $4400ff80,$00001d7c,$000aff64,$4e75f23c
1087 dc.l $44007f80,$00001d7c,$0002ff64,$4e751029
1088 dc.l $00001228,$0000b101,$6a16f229,$d0800000
1089 dc.l $f2000018,$f200001a,$1d7c000a,$ff644e75
1090 dc.l $f229d080,$0000f200,$00181d7c,$0002ff64
1091 dc.l $4e750200,$00300000,$00406008,$02000030
1092 dc.l $00000080,$2d40ff5c,$122eff4e,$66000276
1093 dc.l $020000c0,$66000090,$2d680004,$ff882d68
1094 dc.l $0008ff8c,$30280000,$0a408000,$6a061d7c
1095 dc.l $0008ff64,$3d40ff84,$f22ed080,$ff844e75
1096 dc.l $020000c0,$666008ee,$0003ff66,$2d680004
1097 dc.l $ff882d68,$0008ff8c,$30280000,$0a408000
1098 dc.l $6a061d7c,$0008ff64,$3d40ff84,$f22ed080
1099 dc.l $ff84082e,$0003ff62,$66024e75,$41eeff84
1100 dc.l $61ffffff,$e8764440,$06406000,$322eff84
1101 dc.l $02418000,$02407fff,$80413d40,$ff84f22e
1102 dc.l $d040ff84,$4e750c00,$0040667e,$3d680000
1103 dc.l $ff842d68,$0004ff88,$2d680008,$ff8c61ff
1104 dc.l $ffffe3d8,$0c800000,$007f6c00,$00900c80
1105 dc.l $ffffff81,$67000178,$6d0000f4,$f23c8800
1106 dc.l $00000000,$f22e9000,$ff5cf22e,$481aff84
1107 dc.l $f201a800,$f23c9000,$00000000,$83aeff64
1108 dc.l $2f02f22e,$f080ff84,$322eff84,$34010281
1109 dc.l $00007fff,$92800242,$80008441,$3d42ff84
1110 dc.l $241ff22e,$d080ff84,$4e753d68,$0000ff84
1111 dc.l $2d680004,$ff882d68,$0008ff8c,$61ffffff
1112 dc.l $e35a0c80,$000003ff,$6c120c80,$fffffc01
1113 dc.l $670000fc,$6d000078,$6000ff82,$08ee0003
1114 dc.l $ff660a2e,$0080ff84,$6a0608ee,$0003ff64
1115 dc.l $122eff62,$0201000b,$661a41ee,$ff84222e
1116 dc.l $ff5c61ff,$ffffe99a,$812eff64,$f22ed080
1117 dc.l $ff844e75,$2d6eff88,$ff942d6e,$ff8cff98
1118 dc.l $322eff84,$2f022401,$02810000,$7fff0242
1119 dc.l $80009280,$06810000,$60000241,$7fff8242
1120 dc.l $3d41ff90,$f22ed040,$ff90241f,$60acf23c
1121 dc.l $88000000,$0000f22e,$9000ff5c,$f22e481a
1122 dc.l $ff84f23c,$90000000,$0000f201,$a80083ae
1123 dc.l $ff6400ae,$00001048,$ff64122e,$ff620201
1124 dc.l $0013661c,$082e0003,$ff6456c1,$202eff5c
1125 dc.l $61ffffff,$ea0a812e,$ff64f210,$d0804e75
1126 dc.l $2f02322e,$ff842401,$02810000,$7fff0242
1127 dc.l $80009280,$04810000,$60000241,$7fff8242
1128 dc.l $3d41ff84,$f22ed040,$ff84241f,$60b6f23c
1129 dc.l $88000000,$0000f22e,$9000ff5c,$f22e481a
1130 dc.l $ff84f201,$a800f23c,$90000000,$000083ae
1131 dc.l $ff64f200,$0098f23c,$58b80002,$f293ff74
1132 dc.l $6000fe7e,$0c010004,$6700fdb6,$0c010005
1133 dc.l $67ffffff,$e3040c01,$000367ff,$ffffe30e
1134 dc.l $f228481a,$0000f200,$a800e198,$1d40ff64
1135 dc.l $4e75122e,$ff4e6610,$4a280000,$6b024e75
1136 dc.l $1d7c0008,$ff644e75,$0c010001,$67400c01
1137 dc.l $00026724,$0c010005,$67ffffff,$e2bc0c01
1138 dc.l $000367ff,$ffffe2c6,$4a280000,$6b024e75
1139 dc.l $1d7c0008,$ff644e75,$4a280000,$6b081d7c
1140 dc.l $0002ff64,$4e751d7c,$000aff64,$4e754a28
1141 dc.l $00006b08,$1d7c0004,$ff644e75,$1d7c000c
1142 dc.l $ff644e75,$122eff4e,$66280200,$0030f200
1143 dc.l $9000f23c,$88000000,$0000f228,$48010000
1144 dc.l $f23c9000,$00000000,$f200a800,$81aeff64
1145 dc.l $4e750c01,$0001672e,$0c010002,$674e0c01
1146 dc.l $00046710,$0c010005,$67ffffff,$e22c60ff
1147 dc.l $ffffe23a,$3d680000,$ff841d7c,$0080ff88
1148 dc.l $41eeff84,$60a44a28,$00006b10,$f23c4400
1149 dc.l $00000000,$1d7c0004,$ff644e75,$f23c4400
1150 dc.l $80000000,$1d7c000c,$ff644e75,$f228d080
1151 dc.l $00004a28,$00006b08,$1d7c0002,$ff644e75
1152 dc.l $1d7c000a,$ff644e75,$122eff4e,$6618f23c
1153 dc.l $88000000,$0000f228,$48030000,$f200a800
1154 dc.l $81aeff64,$4e750c01,$0001672e,$0c010002
1155 dc.l $674e0c01,$00046710,$0c010005,$67ffffff
1156 dc.l $e19860ff,$ffffe1a6,$3d680000,$ff841d7c
1157 dc.l $0080ff88,$41eeff84,$60b44a28,$00006b10
1158 dc.l $f23c4400,$00000000,$1d7c0004,$ff644e75
1159 dc.l $f23c4400,$80000000,$1d7c000c,$ff644e75
1160 dc.l $f228d080,$00004a28,$00006b08,$1d7c0002
1161 dc.l $ff644e75,$1d7c000a,$ff644e75,$02000030
1162 dc.l $00000040,$60080200,$00300000,$00802d40
1163 dc.l $ff5c122e,$ff4e6600,$025c0200,$00c0667e
1164 dc.l $2d680004,$ff882d68,$0008ff8c,$32280000
1165 dc.l $0881000f,$3d41ff84,$f22ed080,$ff844e75
1166 dc.l $020000c0,$665808ee,$0003ff66,$2d680004
1167 dc.l $ff882d68,$0008ff8c,$30280000,$0880000f
1168 dc.l $3d40ff84,$f22ed080,$ff84082e,$0003ff62
1169 dc.l $66024e75,$41eeff84,$61ffffff,$e41e4440
1170 dc.l $06406000,$322eff84,$02418000,$02407fff
1171 dc.l $80413d40,$ff84f22e,$d040ff84,$4e750c00
1172 dc.l $0040667e,$3d680000,$ff842d68,$0004ff88
1173 dc.l $2d680008,$ff8c61ff,$ffffdf80,$0c800000
1174 dc.l $007f6c00,$00900c80,$ffffff81,$67000170
1175 dc.l $6d0000ec,$f23c8800,$00000000,$f22e9000
1176 dc.l $ff5cf22e,$4818ff84,$f201a800,$f23c9000
1177 dc.l $00000000,$83aeff64,$2f02f22e,$f080ff84
1178 dc.l $322eff84,$24010281,$00007fff,$92800242
1179 dc.l $80008441,$3d42ff84,$241ff22e,$d080ff84
1180 dc.l $4e753d68,$0000ff84,$2d680004,$ff882d68
1181 dc.l $0008ff8c,$61ffffff,$df020c80,$000003ff
1182 dc.l $6c120c80,$fffffc01,$670000f4,$6d000070
1183 dc.l $6000ff82,$08ee0003,$ff6608ae,$0007ff84
1184 dc.l $122eff62,$0201000b,$661a41ee,$ff84222e
1185 dc.l $ff5c61ff,$ffffe54a,$812eff64,$f22ed080
1186 dc.l $ff844e75,$2d6eff88,$ff942d6e,$ff8cff98
1187 dc.l $322eff84,$2f022401,$02810000,$7fff0242
1188 dc.l $80009280,$06810000,$60000241,$7fff8242
1189 dc.l $3d41ff90,$f22ed040,$ff90241f,$60acf23c
1190 dc.l $88000000,$0000f22e,$9000ff5c,$f22e4818
1191 dc.l $ff84f23c,$90000000,$0000f201,$a80083ae
1192 dc.l $ff6400ae,$00001048,$ff64122e,$ff620201
1193 dc.l $0013661c,$082e0003,$ff6456c1,$202eff5c
1194 dc.l $61ffffff,$e5ba812e,$ff64f210,$d0804e75
1195 dc.l $2f02322e,$ff842401,$02810000,$7fff0242
1196 dc.l $80009280,$04810000,$60000241,$7fff8242
1197 dc.l $3d41ff84,$f22ed040,$ff84241f,$60b6f23c
1198 dc.l $88000000,$0000f22e,$9000ff5c,$f22e4818
1199 dc.l $ff84f201,$a800f23c,$90000000,$000083ae
1200 dc.l $ff64f200,$0098f23c,$58b80002,$f293ff74
1201 dc.l $6000fe86,$0c010004,$6700fdc6,$0c010005
1202 dc.l $67ffffff,$deb40c01,$000367ff,$ffffdebe
1203 dc.l $f2284818,$00000c01,$00026708,$1d7c0004
1204 dc.l $ff644e75,$1d7c0002,$ff644e75,$4241122e
1205 dc.l $ff4fe709,$822eff4e,$6618f229,$d0800000
1206 dc.l $f2284838,$0000f200,$a800e198,$1d40ff64
1207 dc.l $4e75323b,$120a4efb,$10064afc,$0030ffdc
1208 dc.l $ffdcffdc,$006000f8,$006e0000,$0000ffdc
1209 dc.l $ffdcffdc,$0060007c,$006e0000,$0000ffdc
1210 dc.l $ffdcffdc,$0060007c,$006e0000,$00000060
1211 dc.l $00600060,$00600060,$006e0000,$00000114
1212 dc.l $009c009c,$006000bc,$006e0000,$0000006e
1213 dc.l $006e006e,$006e006e,$006e0000,$000061ff
1214 dc.l $ffffddde,$022e00f7,$ff644e75,$61ffffff
1215 dc.l $ddd0022e,$00f7ff64,$4e753d68,$0000ff84
1216 dc.l $20280004,$08c0001f,$2d40ff88,$2d680008
1217 dc.l $ff8c41ee,$ff846000,$ff422d69,$0000ff84
1218 dc.l $20290004,$08c0001f,$2d40ff88,$2d690008
1219 dc.l $ff8c43ee,$ff846000,$ff223d69,$0000ff90
1220 dc.l $3d680000,$ff842029,$000408c0,$001f2d40
1221 dc.l $ff942028,$000408c0,$001f2d40,$ff882d69
1222 dc.l $0008ff98,$2d680008,$ff8c43ee,$ff9041ee
1223 dc.l $ff846000,$fee61028,$00001229,$0000b101
1224 dc.l $6b00ff78,$4a006b02,$4e751d7c,$0008ff64
1225 dc.l $4e751028,$00001229,$0000b101,$6b00ff7c
1226 dc.l $4a006a02,$4e751d7c,$0008ff64,$4e752d40
1227 dc.l $ff5c4241,$122eff4f,$e709822e,$ff4e6600
1228 dc.l $02a03d69,$0000ff90,$2d690004,$ff942d69
1229 dc.l $0008ff98,$3d680000,$ff842d68,$0004ff88
1230 dc.l $2d680008,$ff8c61ff,$ffffdbf0,$2f0061ff
1231 dc.l $ffffdc94,$d09f0c80,$ffffc001,$670000f8
1232 dc.l $6d000064,$0c800000,$40006700,$01da6e00
1233 dc.l $0122f22e,$d080ff90,$f22e9000,$ff5cf23c
1234 dc.l $88000000,$0000f22e,$4827ff84,$f201a800
1235 dc.l $f23c9000,$00000000,$83aeff64,$f22ef080
1236 dc.l $ff842f02,$322eff84,$24010281,$00007fff
1237 dc.l $02428000,$92808242,$3d41ff84,$241ff22e
1238 dc.l $d080ff84,$4e75f22e,$d080ff90,$f22e9000
1239 dc.l $ff5cf23c,$88000000,$0000f22e,$4827ff84
1240 dc.l $f201a800,$f23c9000,$00000000,$83aeff64
1241 dc.l $00ae0000,$1048ff64,$122eff62,$02010013
1242 dc.l $6620082e,$0003ff64,$56c1202e,$ff5c0200
1243 dc.l $003061ff,$ffffe2a8,$812eff64,$f210d080
1244 dc.l $4e75f22e,$f080ff84,$2f02322e,$ff842401
1245 dc.l $02810000,$7fff9280,$04810000,$60000241
1246 dc.l $7fff0242,$80008242,$3d41ff84,$241ff22e
1247 dc.l $d040ff84,$60acf22e,$d080ff90,$f22e9000
1248 dc.l $ff5cf23c,$88000000,$0000f22e,$4827ff84
1249 dc.l $f201a800,$f23c9000,$00000000,$83aeff64
1250 dc.l $f2000098,$f23c58b8,$0002f293,$ff646000
1251 dc.l $ff0c08ee,$0003ff66,$f22ed080,$ff90f23c
1252 dc.l $90000000,$0010f23c,$88000000,$0000f22e
1253 dc.l $4827ff84,$f201a800,$f23c9000,$00000000
1254 dc.l $83aeff64,$122eff62,$0201000b,$6620f22e
1255 dc.l $f080ff84,$41eeff84,$222eff5c,$61ffffff
1256 dc.l $e166812e,$ff64f22e,$d080ff84,$4e75f22e
1257 dc.l $d040ff90,$f22e9000,$ff5cf23c,$88000000
1258 dc.l $0000f22e,$48a7ff84,$f23c9000,$00000000
1259 dc.l $f22ef040,$ff842f02,$322eff84,$24010281
1260 dc.l $00007fff,$02428000,$92800681,$00006000
1261 dc.l $02417fff,$82423d41,$ff84241f,$f22ed040
1262 dc.l $ff846000,$ff8af22e,$d080ff90,$f22e9000
1263 dc.l $ff5cf23c,$88000000,$0000f22e,$4827ff84
1264 dc.l $f201a800,$f23c9000,$00000000,$83aeff64
1265 dc.l $f2000098,$f23c58b8,$0002f292,$fe20f294
1266 dc.l $ff12f22e,$d040ff90,$222eff5c,$020100c0
1267 dc.l $00010010,$f2019000,$f23c8800,$00000000
1268 dc.l $f22e48a7,$ff84f23c,$90000000,$0000f200
1269 dc.l $0498f23c,$58b80002,$f293fde2,$6000fed4
1270 dc.l $323b120a,$4efb1006,$4afc0030,$fd560072
1271 dc.l $0078006c,$fd560066,$00000000,$00720072
1272 dc.l $0060006c,$00720066,$00000000,$007e0060
1273 dc.l $007e006c,$007e0066,$00000000,$006c006c
1274 dc.l $006c006c,$006c0066,$00000000,$fd560072
1275 dc.l $0078006c,$fd560066,$00000000,$00660066
1276 dc.l $00660066,$00660066,$00000000,$60ffffff
1277 dc.l $da7460ff,$ffffd9ea,$60ffffff,$d9e460ff
1278 dc.l $ffffed0e,$60ffffff,$ed6260ff,$ffffed2e
1279 dc.l $2d40ff5c,$4241122e,$ff4fe709,$822eff4e
1280 dc.l $6600027c,$3d690000,$ff902d69,$0004ff94
1281 dc.l $2d690008,$ff983d68,$0000ff84,$2d680004
1282 dc.l $ff882d68,$0008ff8c,$61ffffff,$d8ae2f00
1283 dc.l $61ffffff,$d9524497,$d197322e,$ff5eec09
1284 dc.l $201f0c80,$ffffc001,$6f000064,$0c800000
1285 dc.l $3fff6700,$01b66e00,$0100f22e,$d080ff90
1286 dc.l $f22e9000,$ff5cf23c,$88000000,$0000f22e
1287 dc.l $4824ff84,$f201a800,$f23c9000,$00000000
1288 dc.l $83aeff64,$f22ef080,$ff842f02,$322eff84
1289 dc.l $24010281,$00007fff,$02428000,$92808242
1290 dc.l $3d41ff84,$241ff22e,$d080ff84,$4e75f22e
1291 dc.l $d080ff90,$f22e9000,$ff5cf23c,$88000000
1292 dc.l $0000f22e,$4824ff84,$f201a800,$f23c9000
1293 dc.l $00000000,$83aeff64,$f227e001,$3217dffc
1294 dc.l $0000000c,$02810000,$7fff9280,$0c810000
1295 dc.l $7fff6d90,$006e1048,$ff66122e,$ff620201
1296 dc.l $00136620,$082e0003,$ff6456c1,$202eff5c
1297 dc.l $02000030,$61ffffff,$df46812e,$ff64f210
1298 dc.l $d0804e75,$f22ef080,$ff842f02,$322eff84
1299 dc.l $24010281,$00007fff,$02428000,$92800481
1300 dc.l $00006000,$02417fff,$82423d41,$ff84241f
1301 dc.l $f22ed040,$ff8460ac,$08ee0003,$ff66f22e
1302 dc.l $d080ff90,$f23c9000,$00000010,$f23c8800
1303 dc.l $00000000,$f22e4824,$ff84f201,$a800f23c
1304 dc.l $90000000,$000083ae,$ff64122e,$ff620201
1305 dc.l $000b6620,$f22ef080,$ff8441ee,$ff84222e
1306 dc.l $ff5c61ff,$ffffde40,$812eff64,$f22ed080
1307 dc.l $ff844e75,$f22ed040,$ff90f22e,$9000ff5c
1308 dc.l $f23c8800,$00000000,$f22e48a4,$ff84f23c
1309 dc.l $90000000,$0000f22e,$f040ff84,$2f02322e
1310 dc.l $ff842401,$02810000,$7fff0242,$80009280
1311 dc.l $06810000,$60000241,$7fff8242,$3d41ff84
1312 dc.l $241ff22e,$d040ff84,$608af22e,$d080ff90
1313 dc.l $f22e9000,$ff5cf23c,$88000000,$0000f22e
1314 dc.l $4824ff84,$f201a800,$f23c9000,$00000000
1315 dc.l $83aeff64,$f2000098,$f23c58b8,$0001f292
1316 dc.l $fe44f294,$ff14f22e,$d040ff90,$42810001
1317 dc.l $0010f201,$9000f23c,$88000000,$0000f22e
1318 dc.l $48a4ff84,$f23c9000,$00000000,$f2000498
1319 dc.l $f23c58b8,$0001f293,$fe0c6000,$fedc323b
1320 dc.l $120a4efb,$10064afc,$0030fd7a,$00720078
1321 dc.l $0060fd7a,$00660000,$00000078,$006c0078
1322 dc.l $00600078,$00660000,$0000007e,$007e006c
1323 dc.l $0060007e,$00660000,$00000060,$00600060
1324 dc.l $00600060,$00660000,$0000fd7a,$00720078
1325 dc.l $0060fd7a,$00660000,$00000066,$00660066
1326 dc.l $00660066,$00660000,$000060ff,$ffffd6d2
1327 dc.l $60ffffff,$d6cc60ff,$ffffd74a,$60ffffff
1328 dc.l $f0ce60ff,$fffff09c,$60ffffff,$f0f40200
1329 dc.l $00300000,$00406008,$02000030,$00000080
1330 dc.l $2d40ff5c,$4241122e,$ff4fe709,$822eff4e
1331 dc.l $6600024c,$61ffffff,$d4b2f22e,$d080ff90
1332 dc.l $f23c8800,$00000000,$f22e9000,$ff5cf22e
1333 dc.l $4822ff84,$f23c9000,$00000000,$f201a800
1334 dc.l $83aeff64,$f281003c,$2f02f227,$e001322e
1335 dc.l $ff5eec09,$34170282,$00007fff,$9480b4bb
1336 dc.l $14246c38,$b4bb142a,$6d0000b8,$67000184
1337 dc.l $32170241,$80008242,$3e81f21f,$d080241f
1338 dc.l $4e754e75,$00007fff,$0000407f,$000043ff
1339 dc.l $00000000,$00003f81,$00003c01,$00ae0000
1340 dc.l $1048ff64,$122eff62,$02010013,$6624dffc
1341 dc.l $0000000c,$082e0003,$ff6456c1,$202eff5c
1342 dc.l $61ffffff,$dc7a812e,$ff64f210,$d080241f
1343 dc.l $4e75122e,$ff5c0201,$00c0661a,$32170241
1344 dc.l $80000482,$00006000,$02427fff,$82423e81
1345 dc.l $f21fd040,$60bef22e,$d080ff90,$222eff5c
1346 dc.l $02010030,$f2019000,$f22e4822,$ff84f23c
1347 dc.l $90000000,$0000dffc,$0000000c,$f227e001
1348 dc.l $60ba08ee,$0003ff66,$dffc0000,$000cf22e
1349 dc.l $d080ff90,$f23c9000,$00000010,$f23c8800
1350 dc.l $00000000,$f22e4822,$ff84f23c,$90000000
1351 dc.l $0000f201,$a80083ae,$ff64122e,$ff620201
1352 dc.l $000b6622,$f22ef080,$ff8441ee,$ff84222e
1353 dc.l $ff5c61ff,$ffffdaca,$812eff64,$f22ed080
1354 dc.l $ff84241f,$4e75f22e,$d040ff90,$222eff5c
1355 dc.l $020100c0,$664ef22e,$9000ff5c,$f23c8800
1356 dc.l $00000000,$f22e48a2,$ff84f23c,$90000000
1357 dc.l $0000f22e,$f040ff84,$322eff84,$24010281
1358 dc.l $00007fff,$02428000,$92800681,$00006000
1359 dc.l $02417fff,$82423d41,$ff84f22e,$d040ff84
1360 dc.l $6000ff82,$222eff5c,$02010030,$f2019000
1361 dc.l $60aa222e,$ff5c0201,$00c06700,$fe74222f
1362 dc.l $00040c81,$80000000,$6600fe66,$4aaf0008
1363 dc.l $6600fe5e,$082e0001,$ff666700,$fe54f22e
1364 dc.l $d040ff90,$222eff5c,$020100c0,$00010010
1365 dc.l $f2019000,$f23c8800,$00000000,$f22e48a2
1366 dc.l $ff84f23c,$90000000,$0000f200,$0018f200
1367 dc.l $0498f200,$0438f292,$feca6000,$fe14323b
1368 dc.l $120a4efb,$10064afc,$0030fdaa,$00e4011c
1369 dc.l $0060fdaa,$00660000,$000000bc,$006c011c
1370 dc.l $006000bc,$00660000,$00000130,$0130010c
1371 dc.l $00600130,$00660000,$00000060,$00600060
1372 dc.l $00600060,$00660000,$0000fdaa,$00e4011c
1373 dc.l $0060fdaa,$00660000,$00000066,$00660066
1374 dc.l $00660066,$00660000,$000060ff,$ffffd3d2
1375 dc.l $60ffffff,$d3cc1028,$00001229,$0000b101
1376 dc.l $6b000016,$4a006b2e,$f23c4400,$00000000
1377 dc.l $1d7c0004,$ff644e75,$122eff5f,$02010030
1378 dc.l $0c010020,$6710f23c,$44000000,$00001d7c
1379 dc.l $0004ff64,$4e75f23c,$44008000,$00001d7c
1380 dc.l $000cff64,$4e753d68,$0000ff84,$2d680004
1381 dc.l $ff882d68,$0008ff8c,$61ffffff,$d27e426e
1382 dc.l $ff9042ae,$ff9442ae,$ff986000,$fcce3d69
1383 dc.l $0000ff90,$2d690004,$ff942d69,$0008ff98
1384 dc.l $61ffffff,$d302426e,$ff8442ae,$ff8842ae
1385 dc.l $ff8c6000,$fca61028,$00001229,$0000b300
1386 dc.l $6bffffff,$d3a0f228,$d0800000,$4a280000
1387 dc.l $6a1c1d7c,$000aff64,$4e75f229,$d0800000
1388 dc.l $4a290000,$6a081d7c,$000aff64,$4e751d7c
1389 dc.l $0002ff64,$4e750200,$00300000,$00406008
1390 dc.l $02000030,$00000080,$2d40ff5c,$4241122e
1391 dc.l $ff4fe709,$822eff4e,$6600024c,$61ffffff
1392 dc.l $d0eaf22e,$d080ff90,$f23c8800,$00000000
1393 dc.l $f22e9000,$ff5cf22e,$4828ff84,$f23c9000
1394 dc.l $00000000,$f201a800,$83aeff64,$f281003c
1395 dc.l $2f02f227,$e001322e,$ff5eec09,$34170282
1396 dc.l $00007fff,$9480b4bb,$14246c38,$b4bb142a
1397 dc.l $6d0000b8,$67000184,$32170241,$80008242
1398 dc.l $3e81f21f,$d080241f,$4e754e75,$00007fff
1399 dc.l $0000407f,$000043ff,$00000000,$00003f81
1400 dc.l $00003c01,$00ae0000,$1048ff64,$122eff62
1401 dc.l $02010013,$6624dffc,$0000000c,$082e0003
1402 dc.l $ff6456c1,$202eff5c,$61ffffff,$d8b2812e
1403 dc.l $ff64f210,$d080241f,$4e75122e,$ff5c0201
1404 dc.l $00c0661a,$32170241,$80000482,$00006000
1405 dc.l $02427fff,$82423e81,$f21fd040,$60bef22e
1406 dc.l $d080ff90,$222eff5c,$02010030,$f2019000
1407 dc.l $f22e4828,$ff84f23c,$90000000,$0000dffc
1408 dc.l $0000000c,$f227e001,$60ba08ee,$0003ff66
1409 dc.l $dffc0000,$000cf22e,$d080ff90,$f23c9000
1410 dc.l $00000010,$f23c8800,$00000000,$f22e4828
1411 dc.l $ff84f23c,$90000000,$0000f201,$a80083ae
1412 dc.l $ff64122e,$ff620201,$000b6622,$f22ef080
1413 dc.l $ff8441ee,$ff84222e,$ff5c61ff,$ffffd702
1414 dc.l $812eff64,$f22ed080,$ff84241f,$4e75f22e
1415 dc.l $d040ff90,$222eff5c,$020100c0,$664ef22e
1416 dc.l $9000ff5c,$f23c8800,$00000000,$f22e48a8
1417 dc.l $ff84f23c,$90000000,$0000f22e,$f040ff84
1418 dc.l $322eff84,$24010281,$00007fff,$02428000
1419 dc.l $92800681,$00006000,$02417fff,$82423d41
1420 dc.l $ff84f22e,$d040ff84,$6000ff82,$222eff5c
1421 dc.l $02010030,$f2019000,$60aa222e,$ff5c0201
1422 dc.l $00c06700,$fe74222f,$00040c81,$80000000
1423 dc.l $6600fe66,$4aaf0008,$6600fe5e,$082e0001
1424 dc.l $ff666700,$fe54f22e,$d040ff90,$222eff5c
1425 dc.l $020100c0,$00010010,$f2019000,$f23c8800
1426 dc.l $00000000,$f22e48a8,$ff84f23c,$90000000
1427 dc.l $0000f200,$0018f200,$0498f200,$0438f292
1428 dc.l $feca6000,$fe14323b,$120a4efb,$10064afc
1429 dc.l $0030fdaa,$00e2011a,$0060fdaa,$00660000
1430 dc.l $000000ba,$006c011a,$006000ba,$00660000
1431 dc.l $00000130,$0130010a,$00600130,$00660000
1432 dc.l $00000060,$00600060,$00600060,$00660000
1433 dc.l $0000fdaa,$00e2011a,$0060fdaa,$00660000
1434 dc.l $00000066,$00660066,$00660066,$00660000
1435 dc.l $000060ff,$ffffd00a,$60ffffff,$d0041028
1436 dc.l $00001229,$0000b300,$6a144a00,$6b2ef23c
1437 dc.l $44000000,$00001d7c,$0004ff64,$4e75122e
1438 dc.l $ff5f0201,$00300c01,$00206710,$f23c4400
1439 dc.l $00000000,$1d7c0004,$ff644e75,$f23c4400
1440 dc.l $80000000,$1d7c000c,$ff644e75,$3d680000
1441 dc.l $ff842d68,$0004ff88,$2d680008,$ff8c61ff
1442 dc.l $ffffceb8,$426eff90,$42aeff94,$42aeff98
1443 dc.l $6000fcd0,$3d690000,$ff902d69,$0004ff94
1444 dc.l $2d690008,$ff9861ff,$ffffcf3c,$426eff84
1445 dc.l $42aeff88,$42aeff8c,$6000fca8,$10280000
1446 dc.l $12290000,$b3006aff,$ffffcfda,$f228d080
1447 dc.l $0000f200,$001af293,$001e1d7c,$000aff64
1448 dc.l $4e75f229,$d0800000,$4a290000,$6a081d7c
1449 dc.l $000aff64,$4e751d7c,$0002ff64,$4e750200
1450 dc.l $00300000,$00406008,$02000030,$00000080
1451 dc.l $2d40ff5c,$4241122e,$ff4e6600,$02744a28
1452 dc.l $00006bff,$ffffcf7e,$020000c0,$6648f22e
1453 dc.l $9000ff5c,$f23c8800,$00000000,$f2104804
1454 dc.l $f201a800,$83aeff64,$4e754a28,$00006bff
1455 dc.l $ffffcf52,$020000c0,$661c3d68,$0000ff84
1456 dc.l $2d680004,$ff882d68,$0008ff8c,$61ffffff
1457 dc.l $ce046000,$003e0c00,$00406600,$00843d68
1458 dc.l $0000ff84,$2d680004,$ff882d68,$0008ff8c
1459 dc.l $61ffffff,$cde00c80,$0000007e,$67000098
1460 dc.l $6e00009e,$0c80ffff,$ff806700,$01a46d00
1461 dc.l $0120f23c,$88000000,$0000f22e,$9000ff5c
1462 dc.l $f22e4804,$ff84f201,$a800f23c,$90000000
1463 dc.l $000083ae,$ff642f02,$f22ef080,$ff84322e
1464 dc.l $ff842401,$02810000,$7fff9280,$02428000
1465 dc.l $84413d42,$ff84241f,$f22ed080,$ff844e75
1466 dc.l $3d680000,$ff842d68,$0004ff88,$2d680008
1467 dc.l $ff8c61ff,$ffffcd5e,$0c800000,$03fe6700
1468 dc.l $00166e1c,$0c80ffff,$fc006700,$01246d00
1469 dc.l $00a06000,$ff7e082e,$0000ff85,$6600ff74
1470 dc.l $08ee0003,$ff66f23c,$90000000,$0010f23c
1471 dc.l $88000000,$0000f22e,$4804ff84,$f201a800
1472 dc.l $f23c9000,$00000000,$83aeff64,$122eff62
1473 dc.l $0201000b,$6620f22e,$f080ff84,$41eeff84
1474 dc.l $222eff5c,$61ffffff,$d338812e,$ff64f22e
1475 dc.l $d080ff84,$4e752d6e,$ff88ff94,$2d6eff8c
1476 dc.l $ff98322e,$ff842f02,$24010281,$00007fff
1477 dc.l $02428000,$92800681,$00006000,$02417fff
1478 dc.l $82423d41,$ff90f22e,$d040ff90,$241f60a6
1479 dc.l $f23c8800,$00000000,$f22e9000,$ff5cf22e
1480 dc.l $4804ff84,$f23c9000,$00000000,$f201a800
1481 dc.l $83aeff64,$00ae0000,$1048ff64,$122eff62
1482 dc.l $02010013,$661c082e,$0003ff64,$56c1202e
1483 dc.l $ff5c61ff,$ffffd3a8,$812eff64,$f210d080
1484 dc.l $4e752f02,$322eff84,$24010281,$00007fff
1485 dc.l $02428000,$92800481,$00006000,$02417fff
1486 dc.l $82423d41,$ff84f22e,$d040ff84,$241f60b6
1487 dc.l $082e0000,$ff856600,$ff78f23c,$88000000
1488 dc.l $0000f22e,$9000ff5c,$f22e4804,$ff84f201
1489 dc.l $a800f23c,$90000000,$000083ae,$ff64f200
1490 dc.l $0080f23c,$58b80001,$f293ff6a,$6000fe48
1491 dc.l $0c010004,$6700fdb4,$0c010001,$67160c01
1492 dc.l $00026736,$0c010005,$67ffffff,$cc8c60ff
1493 dc.l $ffffcc9a,$4a280000,$6b10f23c,$44000000
1494 dc.l $00001d7c,$0004ff64,$4e75f23c,$44008000
1495 dc.l $00001d7c,$000cff64,$4e754a28,$00006bff
1496 dc.l $ffffccc2,$f228d080,$00001d7c,$0002ff64
1497 dc.l $4e75303b,$12064efb,$00020020,$0026002c
1498 dc.l $00300034,$0038003c,$00400044,$004a0050
1499 dc.l $00540058,$005c0060,$0064202e,$ff9c4e75
1500 dc.l $202effa0,$4e752002,$4e752003,$4e752004
1501 dc.l $4e752005,$4e752006,$4e752007,$4e75202e
1502 dc.l $ffa44e75,$202effa8,$4e75200a,$4e75200b
1503 dc.l $4e75200c,$4e75200d,$4e752016,$4e75202e
1504 dc.l $ffd84e75,$323b1206,$4efb1002,$00100016
1505 dc.l $001c0020,$00240028,$002c0030,$2d40ff9c
1506 dc.l $4e752d40,$ffa04e75,$24004e75,$26004e75
1507 dc.l $28004e75,$2a004e75,$2c004e75,$2e004e75
1508 dc.l $323b1206,$4efb1002,$00100016,$001c0020
1509 dc.l $00240028,$002c0030,$3d40ff9e,$4e753d40
1510 dc.l $ffa24e75,$34004e75,$36004e75,$38004e75
1511 dc.l $3a004e75,$3c004e75,$3e004e75,$323b1206
1512 dc.l $4efb1002,$00100016,$001c0020,$00240028
1513 dc.l $002c0030,$1d40ff9f,$4e751d40,$ffa34e75
1514 dc.l $14004e75,$16004e75,$18004e75,$1a004e75
1515 dc.l $1c004e75,$1e004e75,$323b1206,$4efb1002
1516 dc.l $00100016,$001c0020,$00240028,$002c0030
1517 dc.l $d1aeffa4,$4e75d1ae,$ffa84e75,$d5c04e75
1518 dc.l $d7c04e75,$d9c04e75,$dbc04e75,$d1964e75
1519 dc.l $1d7c0004,$ff4a0c00,$00016706,$d1aeffd8
1520 dc.l $4e7554ae,$ffd84e75,$323b1206,$4efb1002
1521 dc.l $00100016,$001c0020,$00240028,$002c0030
1522 dc.l $91aeffa4,$4e7591ae,$ffa84e75,$95c04e75
1523 dc.l $97c04e75,$99c04e75,$9bc04e75,$91964e75
1524 dc.l $1d7c0008,$ff4a0c00,$00016706,$91aeffd8
1525 dc.l $4e7555ae,$ffd84e75,$303b0206,$4efb0002
1526 dc.l $00100028,$0040004c,$00580064,$0070007c
1527 dc.l $2d6effdc,$ff6c2d6e,$ffe0ff70,$2d6effe4
1528 dc.l $ff7441ee,$ff6c4e75,$2d6effe8,$ff6c2d6e
1529 dc.l $ffecff70,$2d6efff0,$ff7441ee,$ff6c4e75
1530 dc.l $f22ef020,$ff6c41ee,$ff6c4e75,$f22ef010
1531 dc.l $ff6c41ee,$ff6c4e75,$f22ef008,$ff6c41ee
1532 dc.l $ff6c4e75,$f22ef004,$ff6c41ee,$ff6c4e75
1533 dc.l $f22ef002,$ff6c41ee,$ff6c4e75,$f22ef001
1534 dc.l $ff6c41ee,$ff6c4e75,$303b0206,$4efb0002
1535 dc.l $00100028,$0040004c,$00580064,$0070007c
1536 dc.l $2d6effdc,$ff782d6e,$ffe0ff7c,$2d6effe4
1537 dc.l $ff8041ee,$ff784e75,$2d6effe8,$ff782d6e
1538 dc.l $ffecff7c,$2d6efff0,$ff8041ee,$ff784e75
1539 dc.l $f22ef020,$ff7841ee,$ff784e75,$f22ef010
1540 dc.l $ff7841ee,$ff784e75,$f22ef008,$ff7841ee
1541 dc.l $ff784e75,$f22ef004,$ff7841ee,$ff784e75
1542 dc.l $f22ef002,$ff7841ee,$ff784e75,$f22ef001
1543 dc.l $ff7841ee,$ff784e75,$303b0206,$4efb0002
1544 dc.l $00100018,$0020002a,$0034003e,$00480052
1545 dc.l $f22ef080,$ffdc4e75,$f22ef080,$ffe84e75
1546 dc.l $f227e001,$f21fd020,$4e75f227,$e001f21f
1547 dc.l $d0104e75,$f227e001,$f21fd008,$4e75f227
1548 dc.l $e001f21f,$d0044e75,$f227e001,$f21fd002
1549 dc.l $4e75f227,$e001f21f,$d0014e75,$700c61ff
1550 dc.l $ffffbace,$43eeff6c,$700c61ff,$ffffa0d8
1551 dc.l $4a8166ff,$00000a14,$e9ee004f,$ff6c0c40
1552 dc.l $7fff6602,$4e75102e,$ff6f0200,$000f660e
1553 dc.l $4aaeff70,$66084aae,$ff746602,$4e7541ee
1554 dc.l $ff6c61ff,$0000001c,$f22ef080,$ff6c4e75
1555 dc.l $00000000,$02030203,$02030302,$03020203
1556 dc.l $2d680000,$ff842d68,$0004ff88,$2d680008
1557 dc.l $ff8c41ee,$ff8448e7,$3c00f227,$e0017402
1558 dc.l $76042810,$42814c3c,$10010000,$000ae9c4
1559 dc.l $08c4d280,$580351ca,$ffee0804,$001e6702
1560 dc.l $44810481,$00000010,$6c0e4481,$00844000
1561 dc.l $00000090,$40000000,$2f017201,$f23c4400
1562 dc.l $00000000,$e9d00704,$f2005822,$28301c00
1563 dc.l $76007407,$f23c4423,$41200000,$e9c408c4
1564 dc.l $f2005822,$580351ca,$ffec5281,$0c810000
1565 dc.l $00026fd8,$0810001f,$6704f200,$001a2217
1566 dc.l $0c810000,$001b6f00,$00e40810,$001e6674
1567 dc.l $42812810,$e9c40704,$66245281,$7a012830
1568 dc.l $5c006608,$50815285,$28305c00,$42837407
1569 dc.l $e9c408c4,$66085883,$528151ca,$fff42001
1570 dc.l $22179280,$6c104481,$28100084,$40000000
1571 dc.l $00904000,$000043fb,$01700000,$06664283
1572 dc.l $f23c4480,$3f800000,$7403e280,$6406f231
1573 dc.l $48a33800,$06830000,$000c4a80,$66ecf200
1574 dc.l $04236068,$42817a02,$28305c00,$66085385
1575 dc.l $50812830,$5c00761c,$7407e9c4,$08c46608
1576 dc.l $59835281,$51cafff4,$20012217,$92806e10
1577 dc.l $44812810,$0284bfff,$ffff0290,$bfffffff
1578 dc.l $43fb0170,$000005fc,$4283f23c,$44803f80
1579 dc.l $00007403,$e2806406,$f23148a3,$38000683
1580 dc.l $0000000c,$4a8066ec,$f2000420,$262eff60
1581 dc.l $e9c32682,$2810e582,$e9c40002,$d48043fa
1582 dc.l $fe501031,$28004283,$efc30682,$f2039000
1583 dc.l $e280640a,$43fb0170,$00000644,$6016e280
1584 dc.l $640a43fb,$01700000,$06d26008,$43fb0170
1585 dc.l $00000590,$20016a08,$44800090,$40000000
1586 dc.l $4283f23c,$44803f80,$0000e280,$6406f231
1587 dc.l $48a33800,$06830000,$000c4a80,$66ec0810
1588 dc.l $001e6706,$f2000420,$6004f200,$0423f200
1589 dc.l $a8000880,$00096706,$006e0108,$ff66588f
1590 dc.l $f21fd040,$4cdf003c,$f23c9000,$00000000
1591 dc.l $f23c8800,$00000000,$4e753ffd,$00009a20
1592 dc.l $9a84fbcf,$f7980000,$00003ffd,$00009a20
1593 dc.l $9a84fbcf,$f7990000,$00003f80,$00000000
1594 dc.l $00000000,$00000000,$00004000,$00000000
1595 dc.l $00000000,$00000000,$00004120,$00000000
1596 dc.l $00000000,$00000000,$0000459a,$28000000
1597 dc.l $00000000,$00000000,$00000000,$00000303
1598 dc.l $02020302,$02030203,$030248e7,$3f20f227
1599 dc.l $e007f23c,$90000000,$00202d50,$ff582e00
1600 dc.l $422eff50,$0c2e0004,$ff4e6600,$00303010
1601 dc.l $02407fff,$22280004,$24280008,$5340e38a
1602 dc.l $e3914a81,$6cf64a40,$6e0450ee,$ff500240
1603 dc.l $7fff3080,$21410004,$21420008,$2d50ff90
1604 dc.l $2d680004,$ff942d68,$0008ff98,$02ae7fff
1605 dc.l $ffffff90,$4a2eff50,$67082c3c,$ffffecbb
1606 dc.l $6038302e,$ff903d7c,$3fffff90,$f22e4800
1607 dc.l $ff900440,$3ffff200,$5022f23a,$4428ff1c
1608 dc.l $f293000e,$f23a4823,$ff02f206,$6000600a
1609 dc.l $f23a4823,$fee6f206,$6000f23c,$88000000
1610 dc.l $00004245,$4a876f04,$28076006,$28069887
1611 dc.l $52844a84,$6f180c84,$00000011,$6f127811
1612 dc.l $4a876f0c,$00ae0000,$2080ff64,$60027801
1613 dc.l $4a876e06,$be866d02,$2c072006,$52809084
1614 dc.l $48454245,$42424a80,$6c145245,$0c80ffff
1615 dc.l $ecd46e08,$06800000,$00187418,$4480f23a
1616 dc.l $4480fe98,$e9ee1682,$ff60e349,$d245e349
1617 dc.l $4aaeff58,$6c025281,$45fafec0,$16321800
1618 dc.l $e98bf203,$9000e88b,$4a03660a,$43fb0170
1619 dc.l $00000370,$6016e20b,$640a43fb,$01700000
1620 dc.l $03fe6008,$43fb0170,$00000490,$4283e288
1621 dc.l $6406f231,$48a33800,$06830000,$000c4a80
1622 dc.l $66ecf23c,$88000000,$0000f23c,$90000000
1623 dc.l $0010f210,$4800f200,$00184a45,$6608f200
1624 dc.l $04206000,$008e4a2e,$ff506700,$0072f227
1625 dc.l $e0023617,$02437fff,$00508000,$d6500443
1626 dc.l $3fffd669,$00240443,$3fffd669,$00300443
1627 dc.l $3fff6b00,$00480257,$80008757,$02507fff
1628 dc.l $2f280008,$2f280004,$2f3c3fff,$0000f21f
1629 dc.l $d080f21f,$48232f29,$002c2f29,$00282f3c
1630 dc.l $3fff0000,$2f290038,$2f290034,$2f3c3fff
1631 dc.l $0000f21f,$4823f21f,$48236016,$60fe4a42
1632 dc.l $670cf229,$48230024,$f2294823,$0030f200
1633 dc.l $0423f200,$a800f22e,$6800ff90,$45eeff90
1634 dc.l $08000009,$670e00aa,$00000001,$0008f22e
1635 dc.l $4800ff90,$2d6eff60,$ff5402ae,$00000030
1636 dc.l $ff6048e7,$c0c02f2e,$ff542f2e,$ff5841ee
1637 dc.l $ff90f210,$68004aae,$ff586c06,$00908000
1638 dc.l $00002f2e,$ff64f22e,$9000ff60,$f23c8800
1639 dc.l $00000000,$f22e4801,$ff90f200,$a800816e
1640 dc.l $ff661d57,$ff64588f,$2d5fff58,$2d5fff54
1641 dc.l $4cdf0303,$2d6eff58,$ff902d6e,$ff54ff60
1642 dc.l $48454a45,$66ff0000,$0086f23a,$4500fcec
1643 dc.l $20045380,$4283e288,$6406f231,$49233800
1644 dc.l $06830000,$000c4a80,$66ec4a2e,$ff50670a
1645 dc.l $f2000018,$60ff0000,$0028f200,$0018f200
1646 dc.l $0838f293,$001a5386,$3a3c0001,$f23c9000
1647 dc.l $00000020,$f23a4523,$fcc26000,$fda8f23a
1648 dc.l $4523fcb8,$f2000838,$f294005c,$f292000c
1649 dc.l $f23a4420,$fca65286,$604c5286,$3a3c0001
1650 dc.l $f23c9000,$00000020,$6000fd7a,$f23a4500
1651 dc.l $fc6a2004,$4283e288,$6406f231,$49233800
1652 dc.l $06830000,$000c4a80,$66ecf200,$0018f200
1653 dc.l $0838f28e,$0012f23a,$4420fc60,$52865284
1654 dc.l $f23a4523,$fc56f23c,$90000000,$0010f200
1655 dc.l $082041ee,$ff84f210,$68002428,$00042628
1656 dc.l $000842a8,$000442a8,$00082010,$48406714
1657 dc.l $04800000,$3ffd4a80,$6e0a4480,$e28ae293
1658 dc.l $51c8fffa,$4a826604,$4a836710,$42810683
1659 dc.l $00000080,$d5810283,$ffffff80,$20045688
1660 dc.l $61ff0000,$02b04a2e,$ff506728,$f200003a
1661 dc.l $f281000c,$f2064000,$f2000018,$602e4a87
1662 dc.l $6d08f23a,$4400fbe4,$6022f206,$4000f200
1663 dc.l $00186018,$f200003a,$f28e000a,$f23a4400
1664 dc.l $fb9a6008,$f2064000,$f2000018,$f2294820
1665 dc.l $0018f22e,$6800ff90,$242a0004,$262a0008
1666 dc.l $3012670e,$04403ffd,$4440e28a,$e29351c8
1667 dc.l $fffa4281,$06830000,$0080d581,$0283ffff
1668 dc.l $ff807004,$41eeff54,$61ff0000,$0228202e
1669 dc.l $ff54720c,$e2a8efee,$010cff84,$e2a8efee
1670 dc.l $0404ff84,$4a006708,$00ae0000,$2080ff64
1671 dc.l $4280022e,$000fff84,$4aaeff58,$6c027002
1672 dc.l $4a866c02,$5280efee,$0002ff84,$f23c8800
1673 dc.l $00000000,$f21fd0e0,$4cdf04fc,$4e754002
1674 dc.l $0000a000,$00000000,$00004005,$0000c800
1675 dc.l $00000000,$0000400c,$00009c40,$00000000
1676 dc.l $00004019,$0000bebc,$20000000,$00004034
1677 dc.l $00008e1b,$c9bf0400,$00004069,$00009dc5
1678 dc.l $ada82b70,$b59e40d3,$0000c278,$1f49ffcf
1679 dc.l $a6d541a8,$000093ba,$47c980e9,$8ce04351
1680 dc.l $0000aa7e,$ebfb9df9,$de8e46a3,$0000e319
1681 dc.l $a0aea60e,$91c74d48,$0000c976,$75868175
1682 dc.l $0c175a92,$00009e8b,$3b5dc53d,$5de57525
1683 dc.l $0000c460,$52028a20,$979b4002,$0000a000
1684 dc.l $00000000,$00004005,$0000c800,$00000000
1685 dc.l $0000400c,$00009c40,$00000000,$00004019
1686 dc.l $0000bebc,$20000000,$00004034,$00008e1b
1687 dc.l $c9bf0400,$00004069,$00009dc5,$ada82b70
1688 dc.l $b59e40d3,$0000c278,$1f49ffcf,$a6d641a8
1689 dc.l $000093ba,$47c980e9,$8ce04351,$0000aa7e
1690 dc.l $ebfb9df9,$de8e46a3,$0000e319,$a0aea60e
1691 dc.l $91c74d48,$0000c976,$75868175,$0c185a92
1692 dc.l $00009e8b,$3b5dc53d,$5de57525,$0000c460
1693 dc.l $52028a20,$979b4002,$0000a000,$00000000
1694 dc.l $00004005,$0000c800,$00000000,$0000400c
1695 dc.l $00009c40,$00000000,$00004019,$0000bebc
1696 dc.l $20000000,$00004034,$00008e1b,$c9bf0400
1697 dc.l $00004069,$00009dc5,$ada82b70,$b59d40d3
1698 dc.l $0000c278,$1f49ffcf,$a6d541a8,$000093ba
1699 dc.l $47c980e9,$8cdf4351,$0000aa7e,$ebfb9df9
1700 dc.l $de8d46a3,$0000e319,$a0aea60e,$91c64d48
1701 dc.l $0000c976,$75868175,$0c175a92,$00009e8b
1702 dc.l $3b5dc53d,$5de47525,$0000c460,$52028a20
1703 dc.l $979a48e7,$ff007e01,$53802802,$2a03e9c2
1704 dc.l $1003e782,$e9c36003,$e7838486,$e385e394
1705 dc.l $4846d346,$d6854e71,$d5844e71,$d3464846
1706 dc.l $4a476712,$4847e947,$de4110c7,$48474247
1707 dc.l $51c8ffc8,$60124847,$3e014847,$524751c8
1708 dc.l $ffba4847,$e94f10c7,$4cdf00ff,$4e757001
1709 dc.l $610000d6,$3d7c0121,$000a6000,$007e7002
1710 dc.l $610000c6,$3d7c0141,$000a606e,$70046100
1711 dc.l $00b83d7c,$0101000a,$60607008,$610000aa
1712 dc.l $3d7c0161,$000a6052,$700c6100,$009c3d7c
1713 dc.l $0161000a,$60447001,$6100008e,$3d7c00a1
1714 dc.l $000a6036,$70026100,$00803d7c,$00c1000a
1715 dc.l $60287004,$61000072,$3d7c0081,$000a601a
1716 dc.l $70086100,$00643d7c,$00e1000a,$600c700c
1717 dc.l $61000056,$3d7c00e1,$000a2d6e,$ff680006
1718 dc.l $f22ed0c0,$ffdcf22e,$9c00ff60,$4cee0303
1719 dc.l $ff9c4e5e,$2f172f6f,$00080004,$2f6f000c
1720 dc.l $00082f7c,$00000001,$000c3f6f,$0006000c
1721 dc.l $3f7c4008,$00060817,$00056706,$08ef0002
1722 dc.l $000d60ff,$ffff95f4,$122eff41,$02010038
1723 dc.l $0c010018,$6700000c,$0c010020,$67000060
1724 dc.l $4e75122e,$ff410241,$0007323b,$12064efb
1725 dc.l $10020010,$0016001c,$00200024,$0028002c
1726 dc.l $003091ae,$ffa44e75,$91aeffa8,$4e7595c0
1727 dc.l $4e7597c0,$4e7599c0,$4e759bc0,$4e759196
1728 dc.l $4e750c2e,$0030000a,$6612082e,$00050004
1729 dc.l $660a4e7a,$880091c0,$4e7b8800,$4e754480
1730 dc.l $60a051fc,$00000000,$00000000,$00000000
diff --git a/arch/m68k/ifpsp060/src/README-SRC b/arch/m68k/ifpsp060/src/README-SRC
new file mode 100644
index 000000000000..6be5cff2a6a5
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/README-SRC
@@ -0,0 +1,12 @@
1This is the original source code from Motorola for the 68060 processor
2support code, providing emulation for rarely used m68k instructions
3not implemented in the 68060 silicon.
4
5The code provided here will not assemble out of the box using the GNU
6assembler, however it is being included in order to comply with the
7GNU General Public License.
8
9You don't need to actually assemble these files in order to compile a
10workin m68k kernel, the precompiled .sa files in arch/m68k/ifpsp060
11are sufficient and were generated from these source files by
12Motorola.
diff --git a/arch/m68k/ifpsp060/src/fplsp.S b/arch/m68k/ifpsp060/src/fplsp.S
new file mode 100644
index 000000000000..fdb79b927ef1
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/fplsp.S
@@ -0,0 +1,10980 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29#
30# lfptop.s:
31# This file is appended to the top of the 060ILSP package
32# and contains the entry points into the package. The user, in
33# effect, branches to one of the branch table entries located here.
34#
35
36 bra.l _facoss_
37 short 0x0000
38 bra.l _facosd_
39 short 0x0000
40 bra.l _facosx_
41 short 0x0000
42
43 bra.l _fasins_
44 short 0x0000
45 bra.l _fasind_
46 short 0x0000
47 bra.l _fasinx_
48 short 0x0000
49
50 bra.l _fatans_
51 short 0x0000
52 bra.l _fatand_
53 short 0x0000
54 bra.l _fatanx_
55 short 0x0000
56
57 bra.l _fatanhs_
58 short 0x0000
59 bra.l _fatanhd_
60 short 0x0000
61 bra.l _fatanhx_
62 short 0x0000
63
64 bra.l _fcoss_
65 short 0x0000
66 bra.l _fcosd_
67 short 0x0000
68 bra.l _fcosx_
69 short 0x0000
70
71 bra.l _fcoshs_
72 short 0x0000
73 bra.l _fcoshd_
74 short 0x0000
75 bra.l _fcoshx_
76 short 0x0000
77
78 bra.l _fetoxs_
79 short 0x0000
80 bra.l _fetoxd_
81 short 0x0000
82 bra.l _fetoxx_
83 short 0x0000
84
85 bra.l _fetoxm1s_
86 short 0x0000
87 bra.l _fetoxm1d_
88 short 0x0000
89 bra.l _fetoxm1x_
90 short 0x0000
91
92 bra.l _fgetexps_
93 short 0x0000
94 bra.l _fgetexpd_
95 short 0x0000
96 bra.l _fgetexpx_
97 short 0x0000
98
99 bra.l _fgetmans_
100 short 0x0000
101 bra.l _fgetmand_
102 short 0x0000
103 bra.l _fgetmanx_
104 short 0x0000
105
106 bra.l _flog10s_
107 short 0x0000
108 bra.l _flog10d_
109 short 0x0000
110 bra.l _flog10x_
111 short 0x0000
112
113 bra.l _flog2s_
114 short 0x0000
115 bra.l _flog2d_
116 short 0x0000
117 bra.l _flog2x_
118 short 0x0000
119
120 bra.l _flogns_
121 short 0x0000
122 bra.l _flognd_
123 short 0x0000
124 bra.l _flognx_
125 short 0x0000
126
127 bra.l _flognp1s_
128 short 0x0000
129 bra.l _flognp1d_
130 short 0x0000
131 bra.l _flognp1x_
132 short 0x0000
133
134 bra.l _fmods_
135 short 0x0000
136 bra.l _fmodd_
137 short 0x0000
138 bra.l _fmodx_
139 short 0x0000
140
141 bra.l _frems_
142 short 0x0000
143 bra.l _fremd_
144 short 0x0000
145 bra.l _fremx_
146 short 0x0000
147
148 bra.l _fscales_
149 short 0x0000
150 bra.l _fscaled_
151 short 0x0000
152 bra.l _fscalex_
153 short 0x0000
154
155 bra.l _fsins_
156 short 0x0000
157 bra.l _fsind_
158 short 0x0000
159 bra.l _fsinx_
160 short 0x0000
161
162 bra.l _fsincoss_
163 short 0x0000
164 bra.l _fsincosd_
165 short 0x0000
166 bra.l _fsincosx_
167 short 0x0000
168
169 bra.l _fsinhs_
170 short 0x0000
171 bra.l _fsinhd_
172 short 0x0000
173 bra.l _fsinhx_
174 short 0x0000
175
176 bra.l _ftans_
177 short 0x0000
178 bra.l _ftand_
179 short 0x0000
180 bra.l _ftanx_
181 short 0x0000
182
183 bra.l _ftanhs_
184 short 0x0000
185 bra.l _ftanhd_
186 short 0x0000
187 bra.l _ftanhx_
188 short 0x0000
189
190 bra.l _ftentoxs_
191 short 0x0000
192 bra.l _ftentoxd_
193 short 0x0000
194 bra.l _ftentoxx_
195 short 0x0000
196
197 bra.l _ftwotoxs_
198 short 0x0000
199 bra.l _ftwotoxd_
200 short 0x0000
201 bra.l _ftwotoxx_
202 short 0x0000
203
204 bra.l _fabss_
205 short 0x0000
206 bra.l _fabsd_
207 short 0x0000
208 bra.l _fabsx_
209 short 0x0000
210
211 bra.l _fadds_
212 short 0x0000
213 bra.l _faddd_
214 short 0x0000
215 bra.l _faddx_
216 short 0x0000
217
218 bra.l _fdivs_
219 short 0x0000
220 bra.l _fdivd_
221 short 0x0000
222 bra.l _fdivx_
223 short 0x0000
224
225 bra.l _fints_
226 short 0x0000
227 bra.l _fintd_
228 short 0x0000
229 bra.l _fintx_
230 short 0x0000
231
232 bra.l _fintrzs_
233 short 0x0000
234 bra.l _fintrzd_
235 short 0x0000
236 bra.l _fintrzx_
237 short 0x0000
238
239 bra.l _fmuls_
240 short 0x0000
241 bra.l _fmuld_
242 short 0x0000
243 bra.l _fmulx_
244 short 0x0000
245
246 bra.l _fnegs_
247 short 0x0000
248 bra.l _fnegd_
249 short 0x0000
250 bra.l _fnegx_
251 short 0x0000
252
253 bra.l _fsqrts_
254 short 0x0000
255 bra.l _fsqrtd_
256 short 0x0000
257 bra.l _fsqrtx_
258 short 0x0000
259
260 bra.l _fsubs_
261 short 0x0000
262 bra.l _fsubd_
263 short 0x0000
264 bra.l _fsubx_
265 short 0x0000
266
267# leave room for future possible additions
268 align 0x400
269
270#
271# This file contains a set of define statements for constants
272# in order to promote readability within the corecode itself.
273#
274
275set LOCAL_SIZE, 192 # stack frame size(bytes)
276set LV, -LOCAL_SIZE # stack offset
277
278set EXC_SR, 0x4 # stack status register
279set EXC_PC, 0x6 # stack pc
280set EXC_VOFF, 0xa # stacked vector offset
281set EXC_EA, 0xc # stacked <ea>
282
283set EXC_FP, 0x0 # frame pointer
284
285set EXC_AREGS, -68 # offset of all address regs
286set EXC_DREGS, -100 # offset of all data regs
287set EXC_FPREGS, -36 # offset of all fp regs
288
289set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
290set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
291set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
292set EXC_A5, EXC_AREGS+(5*4)
293set EXC_A4, EXC_AREGS+(4*4)
294set EXC_A3, EXC_AREGS+(3*4)
295set EXC_A2, EXC_AREGS+(2*4)
296set EXC_A1, EXC_AREGS+(1*4)
297set EXC_A0, EXC_AREGS+(0*4)
298set EXC_D7, EXC_DREGS+(7*4)
299set EXC_D6, EXC_DREGS+(6*4)
300set EXC_D5, EXC_DREGS+(5*4)
301set EXC_D4, EXC_DREGS+(4*4)
302set EXC_D3, EXC_DREGS+(3*4)
303set EXC_D2, EXC_DREGS+(2*4)
304set EXC_D1, EXC_DREGS+(1*4)
305set EXC_D0, EXC_DREGS+(0*4)
306
307set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
308set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
309set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
310
311set FP_SCR1, LV+80 # fp scratch 1
312set FP_SCR1_EX, FP_SCR1+0
313set FP_SCR1_SGN, FP_SCR1+2
314set FP_SCR1_HI, FP_SCR1+4
315set FP_SCR1_LO, FP_SCR1+8
316
317set FP_SCR0, LV+68 # fp scratch 0
318set FP_SCR0_EX, FP_SCR0+0
319set FP_SCR0_SGN, FP_SCR0+2
320set FP_SCR0_HI, FP_SCR0+4
321set FP_SCR0_LO, FP_SCR0+8
322
323set FP_DST, LV+56 # fp destination operand
324set FP_DST_EX, FP_DST+0
325set FP_DST_SGN, FP_DST+2
326set FP_DST_HI, FP_DST+4
327set FP_DST_LO, FP_DST+8
328
329set FP_SRC, LV+44 # fp source operand
330set FP_SRC_EX, FP_SRC+0
331set FP_SRC_SGN, FP_SRC+2
332set FP_SRC_HI, FP_SRC+4
333set FP_SRC_LO, FP_SRC+8
334
335set USER_FPIAR, LV+40 # FP instr address register
336
337set USER_FPSR, LV+36 # FP status register
338set FPSR_CC, USER_FPSR+0 # FPSR condition codes
339set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
340set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
341set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
342
343set USER_FPCR, LV+32 # FP control register
344set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
345set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
346
347set L_SCR3, LV+28 # integer scratch 3
348set L_SCR2, LV+24 # integer scratch 2
349set L_SCR1, LV+20 # integer scratch 1
350
351set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
352
353set EXC_TEMP2, LV+24 # temporary space
354set EXC_TEMP, LV+16 # temporary space
355
356set DTAG, LV+15 # destination operand type
357set STAG, LV+14 # source operand type
358
359set SPCOND_FLG, LV+10 # flag: special case (see below)
360
361set EXC_CC, LV+8 # saved condition codes
362set EXC_EXTWPTR, LV+4 # saved current PC (active)
363set EXC_EXTWORD, LV+2 # saved extension word
364set EXC_CMDREG, LV+2 # saved extension word
365set EXC_OPWORD, LV+0 # saved operation word
366
367################################
368
369# Helpful macros
370
371set FTEMP, 0 # offsets within an
372set FTEMP_EX, 0 # extended precision
373set FTEMP_SGN, 2 # value saved in memory.
374set FTEMP_HI, 4
375set FTEMP_LO, 8
376set FTEMP_GRS, 12
377
378set LOCAL, 0 # offsets within an
379set LOCAL_EX, 0 # extended precision
380set LOCAL_SGN, 2 # value saved in memory.
381set LOCAL_HI, 4
382set LOCAL_LO, 8
383set LOCAL_GRS, 12
384
385set DST, 0 # offsets within an
386set DST_EX, 0 # extended precision
387set DST_HI, 4 # value saved in memory.
388set DST_LO, 8
389
390set SRC, 0 # offsets within an
391set SRC_EX, 0 # extended precision
392set SRC_HI, 4 # value saved in memory.
393set SRC_LO, 8
394
395set SGL_LO, 0x3f81 # min sgl prec exponent
396set SGL_HI, 0x407e # max sgl prec exponent
397set DBL_LO, 0x3c01 # min dbl prec exponent
398set DBL_HI, 0x43fe # max dbl prec exponent
399set EXT_LO, 0x0 # min ext prec exponent
400set EXT_HI, 0x7ffe # max ext prec exponent
401
402set EXT_BIAS, 0x3fff # extended precision bias
403set SGL_BIAS, 0x007f # single precision bias
404set DBL_BIAS, 0x03ff # double precision bias
405
406set NORM, 0x00 # operand type for STAG/DTAG
407set ZERO, 0x01 # operand type for STAG/DTAG
408set INF, 0x02 # operand type for STAG/DTAG
409set QNAN, 0x03 # operand type for STAG/DTAG
410set DENORM, 0x04 # operand type for STAG/DTAG
411set SNAN, 0x05 # operand type for STAG/DTAG
412set UNNORM, 0x06 # operand type for STAG/DTAG
413
414##################
415# FPSR/FPCR bits #
416##################
417set neg_bit, 0x3 # negative result
418set z_bit, 0x2 # zero result
419set inf_bit, 0x1 # infinite result
420set nan_bit, 0x0 # NAN result
421
422set q_sn_bit, 0x7 # sign bit of quotient byte
423
424set bsun_bit, 7 # branch on unordered
425set snan_bit, 6 # signalling NAN
426set operr_bit, 5 # operand error
427set ovfl_bit, 4 # overflow
428set unfl_bit, 3 # underflow
429set dz_bit, 2 # divide by zero
430set inex2_bit, 1 # inexact result 2
431set inex1_bit, 0 # inexact result 1
432
433set aiop_bit, 7 # accrued inexact operation bit
434set aovfl_bit, 6 # accrued overflow bit
435set aunfl_bit, 5 # accrued underflow bit
436set adz_bit, 4 # accrued dz bit
437set ainex_bit, 3 # accrued inexact bit
438
439#############################
440# FPSR individual bit masks #
441#############################
442set neg_mask, 0x08000000 # negative bit mask (lw)
443set inf_mask, 0x02000000 # infinity bit mask (lw)
444set z_mask, 0x04000000 # zero bit mask (lw)
445set nan_mask, 0x01000000 # nan bit mask (lw)
446
447set neg_bmask, 0x08 # negative bit mask (byte)
448set inf_bmask, 0x02 # infinity bit mask (byte)
449set z_bmask, 0x04 # zero bit mask (byte)
450set nan_bmask, 0x01 # nan bit mask (byte)
451
452set bsun_mask, 0x00008000 # bsun exception mask
453set snan_mask, 0x00004000 # snan exception mask
454set operr_mask, 0x00002000 # operr exception mask
455set ovfl_mask, 0x00001000 # overflow exception mask
456set unfl_mask, 0x00000800 # underflow exception mask
457set dz_mask, 0x00000400 # dz exception mask
458set inex2_mask, 0x00000200 # inex2 exception mask
459set inex1_mask, 0x00000100 # inex1 exception mask
460
461set aiop_mask, 0x00000080 # accrued illegal operation
462set aovfl_mask, 0x00000040 # accrued overflow
463set aunfl_mask, 0x00000020 # accrued underflow
464set adz_mask, 0x00000010 # accrued divide by zero
465set ainex_mask, 0x00000008 # accrued inexact
466
467######################################
468# FPSR combinations used in the FPSP #
469######################################
470set dzinf_mask, inf_mask+dz_mask+adz_mask
471set opnan_mask, nan_mask+operr_mask+aiop_mask
472set nzi_mask, 0x01ffffff #clears N, Z, and I
473set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
474set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
475set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
476set inx1a_mask, inex1_mask+ainex_mask
477set inx2a_mask, inex2_mask+ainex_mask
478set snaniop_mask, nan_mask+snan_mask+aiop_mask
479set snaniop2_mask, snan_mask+aiop_mask
480set naniop_mask, nan_mask+aiop_mask
481set neginf_mask, neg_mask+inf_mask
482set infaiop_mask, inf_mask+aiop_mask
483set negz_mask, neg_mask+z_mask
484set opaop_mask, operr_mask+aiop_mask
485set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
486set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
487
488#########
489# misc. #
490#########
491set rnd_stky_bit, 29 # stky bit pos in longword
492
493set sign_bit, 0x7 # sign bit
494set signan_bit, 0x6 # signalling nan bit
495
496set sgl_thresh, 0x3f81 # minimum sgl exponent
497set dbl_thresh, 0x3c01 # minimum dbl exponent
498
499set x_mode, 0x0 # extended precision
500set s_mode, 0x4 # single precision
501set d_mode, 0x8 # double precision
502
503set rn_mode, 0x0 # round-to-nearest
504set rz_mode, 0x1 # round-to-zero
505set rm_mode, 0x2 # round-tp-minus-infinity
506set rp_mode, 0x3 # round-to-plus-infinity
507
508set mantissalen, 64 # length of mantissa in bits
509
510set BYTE, 1 # len(byte) == 1 byte
511set WORD, 2 # len(word) == 2 bytes
512set LONG, 4 # len(longword) == 2 bytes
513
514set BSUN_VEC, 0xc0 # bsun vector offset
515set INEX_VEC, 0xc4 # inexact vector offset
516set DZ_VEC, 0xc8 # dz vector offset
517set UNFL_VEC, 0xcc # unfl vector offset
518set OPERR_VEC, 0xd0 # operr vector offset
519set OVFL_VEC, 0xd4 # ovfl vector offset
520set SNAN_VEC, 0xd8 # snan vector offset
521
522###########################
523# SPecial CONDition FLaGs #
524###########################
525set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
526set fbsun_flg, 0x02 # flag bit: bsun exception
527set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
528set mda7_flg, 0x08 # flag bit: -(a7) <ea>
529set fmovm_flg, 0x40 # flag bit: fmovm instruction
530set immed_flg, 0x80 # flag bit: &<data> <ea>
531
532set ftrapcc_bit, 0x0
533set fbsun_bit, 0x1
534set mia7_bit, 0x2
535set mda7_bit, 0x3
536set immed_bit, 0x7
537
538##################################
539# TRANSCENDENTAL "LAST-OP" FLAGS #
540##################################
541set FMUL_OP, 0x0 # fmul instr performed last
542set FDIV_OP, 0x1 # fdiv performed last
543set FADD_OP, 0x2 # fadd performed last
544set FMOV_OP, 0x3 # fmov performed last
545
546#############
547# CONSTANTS #
548#############
549T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
550T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
551
552PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
553PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
554
555TWOBYPI:
556 long 0x3FE45F30,0x6DC9C883
557
558#########################################################################
559# MONADIC TEMPLATE #
560#########################################################################
561 global _fsins_
562_fsins_:
563 link %a6,&-LOCAL_SIZE
564
565 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
566 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
567 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
568
569 fmov.l &0x0,%fpcr # zero FPCR
570
571#
572# copy, convert, and tag input argument
573#
574 fmov.s 0x8(%a6),%fp0 # load sgl input
575 fmov.x %fp0,FP_SRC(%a6)
576 lea FP_SRC(%a6),%a0
577 bsr.l tag # fetch operand type
578 mov.b %d0,STAG(%a6)
579 mov.b %d0,%d1
580
581 andi.l &0x00ff00ff,USER_FPSR(%a6)
582
583 clr.l %d0
584 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
585
586 tst.b %d1
587 bne.b _L0_2s
588 bsr.l ssin # operand is a NORM
589 bra.b _L0_6s
590_L0_2s:
591 cmpi.b %d1,&ZERO # is operand a ZERO?
592 bne.b _L0_3s # no
593 bsr.l src_zero # yes
594 bra.b _L0_6s
595_L0_3s:
596 cmpi.b %d1,&INF # is operand an INF?
597 bne.b _L0_4s # no
598 bsr.l t_operr # yes
599 bra.b _L0_6s
600_L0_4s:
601 cmpi.b %d1,&QNAN # is operand a QNAN?
602 bne.b _L0_5s # no
603 bsr.l src_qnan # yes
604 bra.b _L0_6s
605_L0_5s:
606 bsr.l ssind # operand is a DENORM
607_L0_6s:
608
609#
610# Result is now in FP0
611#
612 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
613 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
614 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
615 unlk %a6
616 rts
617
618 global _fsind_
619_fsind_:
620 link %a6,&-LOCAL_SIZE
621
622 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
623 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
624 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
625
626 fmov.l &0x0,%fpcr # zero FPCR
627
628#
629# copy, convert, and tag input argument
630#
631 fmov.d 0x8(%a6),%fp0 # load dbl input
632 fmov.x %fp0,FP_SRC(%a6)
633 lea FP_SRC(%a6),%a0
634 bsr.l tag # fetch operand type
635 mov.b %d0,STAG(%a6)
636 mov.b %d0,%d1
637
638 andi.l &0x00ff00ff,USER_FPSR(%a6)
639
640 clr.l %d0
641 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
642
643 mov.b %d1,STAG(%a6)
644 tst.b %d1
645 bne.b _L0_2d
646 bsr.l ssin # operand is a NORM
647 bra.b _L0_6d
648_L0_2d:
649 cmpi.b %d1,&ZERO # is operand a ZERO?
650 bne.b _L0_3d # no
651 bsr.l src_zero # yes
652 bra.b _L0_6d
653_L0_3d:
654 cmpi.b %d1,&INF # is operand an INF?
655 bne.b _L0_4d # no
656 bsr.l t_operr # yes
657 bra.b _L0_6d
658_L0_4d:
659 cmpi.b %d1,&QNAN # is operand a QNAN?
660 bne.b _L0_5d # no
661 bsr.l src_qnan # yes
662 bra.b _L0_6d
663_L0_5d:
664 bsr.l ssind # operand is a DENORM
665_L0_6d:
666
667#
668# Result is now in FP0
669#
670 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
671 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
672 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
673 unlk %a6
674 rts
675
676 global _fsinx_
677_fsinx_:
678 link %a6,&-LOCAL_SIZE
679
680 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
681 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
682 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
683
684 fmov.l &0x0,%fpcr # zero FPCR
685
686#
687# copy, convert, and tag input argument
688#
689 lea FP_SRC(%a6),%a0
690 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
691 mov.l 0x8+0x4(%a6),0x4(%a0)
692 mov.l 0x8+0x8(%a6),0x8(%a0)
693 bsr.l tag # fetch operand type
694 mov.b %d0,STAG(%a6)
695 mov.b %d0,%d1
696
697 andi.l &0x00ff00ff,USER_FPSR(%a6)
698
699 clr.l %d0
700 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
701
702 tst.b %d1
703 bne.b _L0_2x
704 bsr.l ssin # operand is a NORM
705 bra.b _L0_6x
706_L0_2x:
707 cmpi.b %d1,&ZERO # is operand a ZERO?
708 bne.b _L0_3x # no
709 bsr.l src_zero # yes
710 bra.b _L0_6x
711_L0_3x:
712 cmpi.b %d1,&INF # is operand an INF?
713 bne.b _L0_4x # no
714 bsr.l t_operr # yes
715 bra.b _L0_6x
716_L0_4x:
717 cmpi.b %d1,&QNAN # is operand a QNAN?
718 bne.b _L0_5x # no
719 bsr.l src_qnan # yes
720 bra.b _L0_6x
721_L0_5x:
722 bsr.l ssind # operand is a DENORM
723_L0_6x:
724
725#
726# Result is now in FP0
727#
728 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
729 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
730 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
731 unlk %a6
732 rts
733
734
735#########################################################################
736# MONADIC TEMPLATE #
737#########################################################################
738 global _fcoss_
739_fcoss_:
740 link %a6,&-LOCAL_SIZE
741
742 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
743 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
744 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
745
746 fmov.l &0x0,%fpcr # zero FPCR
747
748#
749# copy, convert, and tag input argument
750#
751 fmov.s 0x8(%a6),%fp0 # load sgl input
752 fmov.x %fp0,FP_SRC(%a6)
753 lea FP_SRC(%a6),%a0
754 bsr.l tag # fetch operand type
755 mov.b %d0,STAG(%a6)
756 mov.b %d0,%d1
757
758 andi.l &0x00ff00ff,USER_FPSR(%a6)
759
760 clr.l %d0
761 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
762
763 tst.b %d1
764 bne.b _L1_2s
765 bsr.l scos # operand is a NORM
766 bra.b _L1_6s
767_L1_2s:
768 cmpi.b %d1,&ZERO # is operand a ZERO?
769 bne.b _L1_3s # no
770 bsr.l ld_pone # yes
771 bra.b _L1_6s
772_L1_3s:
773 cmpi.b %d1,&INF # is operand an INF?
774 bne.b _L1_4s # no
775 bsr.l t_operr # yes
776 bra.b _L1_6s
777_L1_4s:
778 cmpi.b %d1,&QNAN # is operand a QNAN?
779 bne.b _L1_5s # no
780 bsr.l src_qnan # yes
781 bra.b _L1_6s
782_L1_5s:
783 bsr.l scosd # operand is a DENORM
784_L1_6s:
785
786#
787# Result is now in FP0
788#
789 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
790 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
791 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
792 unlk %a6
793 rts
794
795 global _fcosd_
796_fcosd_:
797 link %a6,&-LOCAL_SIZE
798
799 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
800 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
801 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
802
803 fmov.l &0x0,%fpcr # zero FPCR
804
805#
806# copy, convert, and tag input argument
807#
808 fmov.d 0x8(%a6),%fp0 # load dbl input
809 fmov.x %fp0,FP_SRC(%a6)
810 lea FP_SRC(%a6),%a0
811 bsr.l tag # fetch operand type
812 mov.b %d0,STAG(%a6)
813 mov.b %d0,%d1
814
815 andi.l &0x00ff00ff,USER_FPSR(%a6)
816
817 clr.l %d0
818 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
819
820 mov.b %d1,STAG(%a6)
821 tst.b %d1
822 bne.b _L1_2d
823 bsr.l scos # operand is a NORM
824 bra.b _L1_6d
825_L1_2d:
826 cmpi.b %d1,&ZERO # is operand a ZERO?
827 bne.b _L1_3d # no
828 bsr.l ld_pone # yes
829 bra.b _L1_6d
830_L1_3d:
831 cmpi.b %d1,&INF # is operand an INF?
832 bne.b _L1_4d # no
833 bsr.l t_operr # yes
834 bra.b _L1_6d
835_L1_4d:
836 cmpi.b %d1,&QNAN # is operand a QNAN?
837 bne.b _L1_5d # no
838 bsr.l src_qnan # yes
839 bra.b _L1_6d
840_L1_5d:
841 bsr.l scosd # operand is a DENORM
842_L1_6d:
843
844#
845# Result is now in FP0
846#
847 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
848 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
849 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
850 unlk %a6
851 rts
852
853 global _fcosx_
854_fcosx_:
855 link %a6,&-LOCAL_SIZE
856
857 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
858 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
859 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
860
861 fmov.l &0x0,%fpcr # zero FPCR
862
863#
864# copy, convert, and tag input argument
865#
866 lea FP_SRC(%a6),%a0
867 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
868 mov.l 0x8+0x4(%a6),0x4(%a0)
869 mov.l 0x8+0x8(%a6),0x8(%a0)
870 bsr.l tag # fetch operand type
871 mov.b %d0,STAG(%a6)
872 mov.b %d0,%d1
873
874 andi.l &0x00ff00ff,USER_FPSR(%a6)
875
876 clr.l %d0
877 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
878
879 tst.b %d1
880 bne.b _L1_2x
881 bsr.l scos # operand is a NORM
882 bra.b _L1_6x
883_L1_2x:
884 cmpi.b %d1,&ZERO # is operand a ZERO?
885 bne.b _L1_3x # no
886 bsr.l ld_pone # yes
887 bra.b _L1_6x
888_L1_3x:
889 cmpi.b %d1,&INF # is operand an INF?
890 bne.b _L1_4x # no
891 bsr.l t_operr # yes
892 bra.b _L1_6x
893_L1_4x:
894 cmpi.b %d1,&QNAN # is operand a QNAN?
895 bne.b _L1_5x # no
896 bsr.l src_qnan # yes
897 bra.b _L1_6x
898_L1_5x:
899 bsr.l scosd # operand is a DENORM
900_L1_6x:
901
902#
903# Result is now in FP0
904#
905 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
906 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
907 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
908 unlk %a6
909 rts
910
911
912#########################################################################
913# MONADIC TEMPLATE #
914#########################################################################
915 global _fsinhs_
916_fsinhs_:
917 link %a6,&-LOCAL_SIZE
918
919 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
920 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
921 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
922
923 fmov.l &0x0,%fpcr # zero FPCR
924
925#
926# copy, convert, and tag input argument
927#
928 fmov.s 0x8(%a6),%fp0 # load sgl input
929 fmov.x %fp0,FP_SRC(%a6)
930 lea FP_SRC(%a6),%a0
931 bsr.l tag # fetch operand type
932 mov.b %d0,STAG(%a6)
933 mov.b %d0,%d1
934
935 andi.l &0x00ff00ff,USER_FPSR(%a6)
936
937 clr.l %d0
938 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
939
940 tst.b %d1
941 bne.b _L2_2s
942 bsr.l ssinh # operand is a NORM
943 bra.b _L2_6s
944_L2_2s:
945 cmpi.b %d1,&ZERO # is operand a ZERO?
946 bne.b _L2_3s # no
947 bsr.l src_zero # yes
948 bra.b _L2_6s
949_L2_3s:
950 cmpi.b %d1,&INF # is operand an INF?
951 bne.b _L2_4s # no
952 bsr.l src_inf # yes
953 bra.b _L2_6s
954_L2_4s:
955 cmpi.b %d1,&QNAN # is operand a QNAN?
956 bne.b _L2_5s # no
957 bsr.l src_qnan # yes
958 bra.b _L2_6s
959_L2_5s:
960 bsr.l ssinhd # operand is a DENORM
961_L2_6s:
962
963#
964# Result is now in FP0
965#
966 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
967 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
968 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
969 unlk %a6
970 rts
971
972 global _fsinhd_
973_fsinhd_:
974 link %a6,&-LOCAL_SIZE
975
976 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
977 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
978 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
979
980 fmov.l &0x0,%fpcr # zero FPCR
981
982#
983# copy, convert, and tag input argument
984#
985 fmov.d 0x8(%a6),%fp0 # load dbl input
986 fmov.x %fp0,FP_SRC(%a6)
987 lea FP_SRC(%a6),%a0
988 bsr.l tag # fetch operand type
989 mov.b %d0,STAG(%a6)
990 mov.b %d0,%d1
991
992 andi.l &0x00ff00ff,USER_FPSR(%a6)
993
994 clr.l %d0
995 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
996
997 mov.b %d1,STAG(%a6)
998 tst.b %d1
999 bne.b _L2_2d
1000 bsr.l ssinh # operand is a NORM
1001 bra.b _L2_6d
1002_L2_2d:
1003 cmpi.b %d1,&ZERO # is operand a ZERO?
1004 bne.b _L2_3d # no
1005 bsr.l src_zero # yes
1006 bra.b _L2_6d
1007_L2_3d:
1008 cmpi.b %d1,&INF # is operand an INF?
1009 bne.b _L2_4d # no
1010 bsr.l src_inf # yes
1011 bra.b _L2_6d
1012_L2_4d:
1013 cmpi.b %d1,&QNAN # is operand a QNAN?
1014 bne.b _L2_5d # no
1015 bsr.l src_qnan # yes
1016 bra.b _L2_6d
1017_L2_5d:
1018 bsr.l ssinhd # operand is a DENORM
1019_L2_6d:
1020
1021#
1022# Result is now in FP0
1023#
1024 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1025 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1026 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1027 unlk %a6
1028 rts
1029
1030 global _fsinhx_
1031_fsinhx_:
1032 link %a6,&-LOCAL_SIZE
1033
1034 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1035 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1036 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1037
1038 fmov.l &0x0,%fpcr # zero FPCR
1039
1040#
1041# copy, convert, and tag input argument
1042#
1043 lea FP_SRC(%a6),%a0
1044 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1045 mov.l 0x8+0x4(%a6),0x4(%a0)
1046 mov.l 0x8+0x8(%a6),0x8(%a0)
1047 bsr.l tag # fetch operand type
1048 mov.b %d0,STAG(%a6)
1049 mov.b %d0,%d1
1050
1051 andi.l &0x00ff00ff,USER_FPSR(%a6)
1052
1053 clr.l %d0
1054 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1055
1056 tst.b %d1
1057 bne.b _L2_2x
1058 bsr.l ssinh # operand is a NORM
1059 bra.b _L2_6x
1060_L2_2x:
1061 cmpi.b %d1,&ZERO # is operand a ZERO?
1062 bne.b _L2_3x # no
1063 bsr.l src_zero # yes
1064 bra.b _L2_6x
1065_L2_3x:
1066 cmpi.b %d1,&INF # is operand an INF?
1067 bne.b _L2_4x # no
1068 bsr.l src_inf # yes
1069 bra.b _L2_6x
1070_L2_4x:
1071 cmpi.b %d1,&QNAN # is operand a QNAN?
1072 bne.b _L2_5x # no
1073 bsr.l src_qnan # yes
1074 bra.b _L2_6x
1075_L2_5x:
1076 bsr.l ssinhd # operand is a DENORM
1077_L2_6x:
1078
1079#
1080# Result is now in FP0
1081#
1082 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1083 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1084 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1085 unlk %a6
1086 rts
1087
1088
1089#########################################################################
1090# MONADIC TEMPLATE #
1091#########################################################################
1092 global _flognp1s_
1093_flognp1s_:
1094 link %a6,&-LOCAL_SIZE
1095
1096 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1097 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1098 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1099
1100 fmov.l &0x0,%fpcr # zero FPCR
1101
1102#
1103# copy, convert, and tag input argument
1104#
1105 fmov.s 0x8(%a6),%fp0 # load sgl input
1106 fmov.x %fp0,FP_SRC(%a6)
1107 lea FP_SRC(%a6),%a0
1108 bsr.l tag # fetch operand type
1109 mov.b %d0,STAG(%a6)
1110 mov.b %d0,%d1
1111
1112 andi.l &0x00ff00ff,USER_FPSR(%a6)
1113
1114 clr.l %d0
1115 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1116
1117 tst.b %d1
1118 bne.b _L3_2s
1119 bsr.l slognp1 # operand is a NORM
1120 bra.b _L3_6s
1121_L3_2s:
1122 cmpi.b %d1,&ZERO # is operand a ZERO?
1123 bne.b _L3_3s # no
1124 bsr.l src_zero # yes
1125 bra.b _L3_6s
1126_L3_3s:
1127 cmpi.b %d1,&INF # is operand an INF?
1128 bne.b _L3_4s # no
1129 bsr.l sopr_inf # yes
1130 bra.b _L3_6s
1131_L3_4s:
1132 cmpi.b %d1,&QNAN # is operand a QNAN?
1133 bne.b _L3_5s # no
1134 bsr.l src_qnan # yes
1135 bra.b _L3_6s
1136_L3_5s:
1137 bsr.l slognp1d # operand is a DENORM
1138_L3_6s:
1139
1140#
1141# Result is now in FP0
1142#
1143 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1144 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1145 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1146 unlk %a6
1147 rts
1148
1149 global _flognp1d_
1150_flognp1d_:
1151 link %a6,&-LOCAL_SIZE
1152
1153 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1154 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1155 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1156
1157 fmov.l &0x0,%fpcr # zero FPCR
1158
1159#
1160# copy, convert, and tag input argument
1161#
1162 fmov.d 0x8(%a6),%fp0 # load dbl input
1163 fmov.x %fp0,FP_SRC(%a6)
1164 lea FP_SRC(%a6),%a0
1165 bsr.l tag # fetch operand type
1166 mov.b %d0,STAG(%a6)
1167 mov.b %d0,%d1
1168
1169 andi.l &0x00ff00ff,USER_FPSR(%a6)
1170
1171 clr.l %d0
1172 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1173
1174 mov.b %d1,STAG(%a6)
1175 tst.b %d1
1176 bne.b _L3_2d
1177 bsr.l slognp1 # operand is a NORM
1178 bra.b _L3_6d
1179_L3_2d:
1180 cmpi.b %d1,&ZERO # is operand a ZERO?
1181 bne.b _L3_3d # no
1182 bsr.l src_zero # yes
1183 bra.b _L3_6d
1184_L3_3d:
1185 cmpi.b %d1,&INF # is operand an INF?
1186 bne.b _L3_4d # no
1187 bsr.l sopr_inf # yes
1188 bra.b _L3_6d
1189_L3_4d:
1190 cmpi.b %d1,&QNAN # is operand a QNAN?
1191 bne.b _L3_5d # no
1192 bsr.l src_qnan # yes
1193 bra.b _L3_6d
1194_L3_5d:
1195 bsr.l slognp1d # operand is a DENORM
1196_L3_6d:
1197
1198#
1199# Result is now in FP0
1200#
1201 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1202 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1203 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1204 unlk %a6
1205 rts
1206
1207 global _flognp1x_
1208_flognp1x_:
1209 link %a6,&-LOCAL_SIZE
1210
1211 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1212 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1213 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1214
1215 fmov.l &0x0,%fpcr # zero FPCR
1216
1217#
1218# copy, convert, and tag input argument
1219#
1220 lea FP_SRC(%a6),%a0
1221 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1222 mov.l 0x8+0x4(%a6),0x4(%a0)
1223 mov.l 0x8+0x8(%a6),0x8(%a0)
1224 bsr.l tag # fetch operand type
1225 mov.b %d0,STAG(%a6)
1226 mov.b %d0,%d1
1227
1228 andi.l &0x00ff00ff,USER_FPSR(%a6)
1229
1230 clr.l %d0
1231 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1232
1233 tst.b %d1
1234 bne.b _L3_2x
1235 bsr.l slognp1 # operand is a NORM
1236 bra.b _L3_6x
1237_L3_2x:
1238 cmpi.b %d1,&ZERO # is operand a ZERO?
1239 bne.b _L3_3x # no
1240 bsr.l src_zero # yes
1241 bra.b _L3_6x
1242_L3_3x:
1243 cmpi.b %d1,&INF # is operand an INF?
1244 bne.b _L3_4x # no
1245 bsr.l sopr_inf # yes
1246 bra.b _L3_6x
1247_L3_4x:
1248 cmpi.b %d1,&QNAN # is operand a QNAN?
1249 bne.b _L3_5x # no
1250 bsr.l src_qnan # yes
1251 bra.b _L3_6x
1252_L3_5x:
1253 bsr.l slognp1d # operand is a DENORM
1254_L3_6x:
1255
1256#
1257# Result is now in FP0
1258#
1259 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1260 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1261 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1262 unlk %a6
1263 rts
1264
1265
1266#########################################################################
1267# MONADIC TEMPLATE #
1268#########################################################################
1269 global _fetoxm1s_
1270_fetoxm1s_:
1271 link %a6,&-LOCAL_SIZE
1272
1273 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1274 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1275 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1276
1277 fmov.l &0x0,%fpcr # zero FPCR
1278
1279#
1280# copy, convert, and tag input argument
1281#
1282 fmov.s 0x8(%a6),%fp0 # load sgl input
1283 fmov.x %fp0,FP_SRC(%a6)
1284 lea FP_SRC(%a6),%a0
1285 bsr.l tag # fetch operand type
1286 mov.b %d0,STAG(%a6)
1287 mov.b %d0,%d1
1288
1289 andi.l &0x00ff00ff,USER_FPSR(%a6)
1290
1291 clr.l %d0
1292 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1293
1294 tst.b %d1
1295 bne.b _L4_2s
1296 bsr.l setoxm1 # operand is a NORM
1297 bra.b _L4_6s
1298_L4_2s:
1299 cmpi.b %d1,&ZERO # is operand a ZERO?
1300 bne.b _L4_3s # no
1301 bsr.l src_zero # yes
1302 bra.b _L4_6s
1303_L4_3s:
1304 cmpi.b %d1,&INF # is operand an INF?
1305 bne.b _L4_4s # no
1306 bsr.l setoxm1i # yes
1307 bra.b _L4_6s
1308_L4_4s:
1309 cmpi.b %d1,&QNAN # is operand a QNAN?
1310 bne.b _L4_5s # no
1311 bsr.l src_qnan # yes
1312 bra.b _L4_6s
1313_L4_5s:
1314 bsr.l setoxm1d # operand is a DENORM
1315_L4_6s:
1316
1317#
1318# Result is now in FP0
1319#
1320 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1321 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1322 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1323 unlk %a6
1324 rts
1325
1326 global _fetoxm1d_
1327_fetoxm1d_:
1328 link %a6,&-LOCAL_SIZE
1329
1330 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1331 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1332 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1333
1334 fmov.l &0x0,%fpcr # zero FPCR
1335
1336#
1337# copy, convert, and tag input argument
1338#
1339 fmov.d 0x8(%a6),%fp0 # load dbl input
1340 fmov.x %fp0,FP_SRC(%a6)
1341 lea FP_SRC(%a6),%a0
1342 bsr.l tag # fetch operand type
1343 mov.b %d0,STAG(%a6)
1344 mov.b %d0,%d1
1345
1346 andi.l &0x00ff00ff,USER_FPSR(%a6)
1347
1348 clr.l %d0
1349 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1350
1351 mov.b %d1,STAG(%a6)
1352 tst.b %d1
1353 bne.b _L4_2d
1354 bsr.l setoxm1 # operand is a NORM
1355 bra.b _L4_6d
1356_L4_2d:
1357 cmpi.b %d1,&ZERO # is operand a ZERO?
1358 bne.b _L4_3d # no
1359 bsr.l src_zero # yes
1360 bra.b _L4_6d
1361_L4_3d:
1362 cmpi.b %d1,&INF # is operand an INF?
1363 bne.b _L4_4d # no
1364 bsr.l setoxm1i # yes
1365 bra.b _L4_6d
1366_L4_4d:
1367 cmpi.b %d1,&QNAN # is operand a QNAN?
1368 bne.b _L4_5d # no
1369 bsr.l src_qnan # yes
1370 bra.b _L4_6d
1371_L4_5d:
1372 bsr.l setoxm1d # operand is a DENORM
1373_L4_6d:
1374
1375#
1376# Result is now in FP0
1377#
1378 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1379 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1380 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1381 unlk %a6
1382 rts
1383
1384 global _fetoxm1x_
1385_fetoxm1x_:
1386 link %a6,&-LOCAL_SIZE
1387
1388 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1389 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1390 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1391
1392 fmov.l &0x0,%fpcr # zero FPCR
1393
1394#
1395# copy, convert, and tag input argument
1396#
1397 lea FP_SRC(%a6),%a0
1398 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1399 mov.l 0x8+0x4(%a6),0x4(%a0)
1400 mov.l 0x8+0x8(%a6),0x8(%a0)
1401 bsr.l tag # fetch operand type
1402 mov.b %d0,STAG(%a6)
1403 mov.b %d0,%d1
1404
1405 andi.l &0x00ff00ff,USER_FPSR(%a6)
1406
1407 clr.l %d0
1408 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1409
1410 tst.b %d1
1411 bne.b _L4_2x
1412 bsr.l setoxm1 # operand is a NORM
1413 bra.b _L4_6x
1414_L4_2x:
1415 cmpi.b %d1,&ZERO # is operand a ZERO?
1416 bne.b _L4_3x # no
1417 bsr.l src_zero # yes
1418 bra.b _L4_6x
1419_L4_3x:
1420 cmpi.b %d1,&INF # is operand an INF?
1421 bne.b _L4_4x # no
1422 bsr.l setoxm1i # yes
1423 bra.b _L4_6x
1424_L4_4x:
1425 cmpi.b %d1,&QNAN # is operand a QNAN?
1426 bne.b _L4_5x # no
1427 bsr.l src_qnan # yes
1428 bra.b _L4_6x
1429_L4_5x:
1430 bsr.l setoxm1d # operand is a DENORM
1431_L4_6x:
1432
1433#
1434# Result is now in FP0
1435#
1436 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1437 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1438 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1439 unlk %a6
1440 rts
1441
1442
1443#########################################################################
1444# MONADIC TEMPLATE #
1445#########################################################################
1446 global _ftanhs_
1447_ftanhs_:
1448 link %a6,&-LOCAL_SIZE
1449
1450 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1451 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1452 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1453
1454 fmov.l &0x0,%fpcr # zero FPCR
1455
1456#
1457# copy, convert, and tag input argument
1458#
1459 fmov.s 0x8(%a6),%fp0 # load sgl input
1460 fmov.x %fp0,FP_SRC(%a6)
1461 lea FP_SRC(%a6),%a0
1462 bsr.l tag # fetch operand type
1463 mov.b %d0,STAG(%a6)
1464 mov.b %d0,%d1
1465
1466 andi.l &0x00ff00ff,USER_FPSR(%a6)
1467
1468 clr.l %d0
1469 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1470
1471 tst.b %d1
1472 bne.b _L5_2s
1473 bsr.l stanh # operand is a NORM
1474 bra.b _L5_6s
1475_L5_2s:
1476 cmpi.b %d1,&ZERO # is operand a ZERO?
1477 bne.b _L5_3s # no
1478 bsr.l src_zero # yes
1479 bra.b _L5_6s
1480_L5_3s:
1481 cmpi.b %d1,&INF # is operand an INF?
1482 bne.b _L5_4s # no
1483 bsr.l src_one # yes
1484 bra.b _L5_6s
1485_L5_4s:
1486 cmpi.b %d1,&QNAN # is operand a QNAN?
1487 bne.b _L5_5s # no
1488 bsr.l src_qnan # yes
1489 bra.b _L5_6s
1490_L5_5s:
1491 bsr.l stanhd # operand is a DENORM
1492_L5_6s:
1493
1494#
1495# Result is now in FP0
1496#
1497 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1498 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1499 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1500 unlk %a6
1501 rts
1502
1503 global _ftanhd_
1504_ftanhd_:
1505 link %a6,&-LOCAL_SIZE
1506
1507 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1508 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1509 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1510
1511 fmov.l &0x0,%fpcr # zero FPCR
1512
1513#
1514# copy, convert, and tag input argument
1515#
1516 fmov.d 0x8(%a6),%fp0 # load dbl input
1517 fmov.x %fp0,FP_SRC(%a6)
1518 lea FP_SRC(%a6),%a0
1519 bsr.l tag # fetch operand type
1520 mov.b %d0,STAG(%a6)
1521 mov.b %d0,%d1
1522
1523 andi.l &0x00ff00ff,USER_FPSR(%a6)
1524
1525 clr.l %d0
1526 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1527
1528 mov.b %d1,STAG(%a6)
1529 tst.b %d1
1530 bne.b _L5_2d
1531 bsr.l stanh # operand is a NORM
1532 bra.b _L5_6d
1533_L5_2d:
1534 cmpi.b %d1,&ZERO # is operand a ZERO?
1535 bne.b _L5_3d # no
1536 bsr.l src_zero # yes
1537 bra.b _L5_6d
1538_L5_3d:
1539 cmpi.b %d1,&INF # is operand an INF?
1540 bne.b _L5_4d # no
1541 bsr.l src_one # yes
1542 bra.b _L5_6d
1543_L5_4d:
1544 cmpi.b %d1,&QNAN # is operand a QNAN?
1545 bne.b _L5_5d # no
1546 bsr.l src_qnan # yes
1547 bra.b _L5_6d
1548_L5_5d:
1549 bsr.l stanhd # operand is a DENORM
1550_L5_6d:
1551
1552#
1553# Result is now in FP0
1554#
1555 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1556 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1557 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1558 unlk %a6
1559 rts
1560
1561 global _ftanhx_
1562_ftanhx_:
1563 link %a6,&-LOCAL_SIZE
1564
1565 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1566 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1567 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1568
1569 fmov.l &0x0,%fpcr # zero FPCR
1570
1571#
1572# copy, convert, and tag input argument
1573#
1574 lea FP_SRC(%a6),%a0
1575 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1576 mov.l 0x8+0x4(%a6),0x4(%a0)
1577 mov.l 0x8+0x8(%a6),0x8(%a0)
1578 bsr.l tag # fetch operand type
1579 mov.b %d0,STAG(%a6)
1580 mov.b %d0,%d1
1581
1582 andi.l &0x00ff00ff,USER_FPSR(%a6)
1583
1584 clr.l %d0
1585 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1586
1587 tst.b %d1
1588 bne.b _L5_2x
1589 bsr.l stanh # operand is a NORM
1590 bra.b _L5_6x
1591_L5_2x:
1592 cmpi.b %d1,&ZERO # is operand a ZERO?
1593 bne.b _L5_3x # no
1594 bsr.l src_zero # yes
1595 bra.b _L5_6x
1596_L5_3x:
1597 cmpi.b %d1,&INF # is operand an INF?
1598 bne.b _L5_4x # no
1599 bsr.l src_one # yes
1600 bra.b _L5_6x
1601_L5_4x:
1602 cmpi.b %d1,&QNAN # is operand a QNAN?
1603 bne.b _L5_5x # no
1604 bsr.l src_qnan # yes
1605 bra.b _L5_6x
1606_L5_5x:
1607 bsr.l stanhd # operand is a DENORM
1608_L5_6x:
1609
1610#
1611# Result is now in FP0
1612#
1613 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1614 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1615 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1616 unlk %a6
1617 rts
1618
1619
1620#########################################################################
1621# MONADIC TEMPLATE #
1622#########################################################################
1623 global _fatans_
1624_fatans_:
1625 link %a6,&-LOCAL_SIZE
1626
1627 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1628 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1629 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1630
1631 fmov.l &0x0,%fpcr # zero FPCR
1632
1633#
1634# copy, convert, and tag input argument
1635#
1636 fmov.s 0x8(%a6),%fp0 # load sgl input
1637 fmov.x %fp0,FP_SRC(%a6)
1638 lea FP_SRC(%a6),%a0
1639 bsr.l tag # fetch operand type
1640 mov.b %d0,STAG(%a6)
1641 mov.b %d0,%d1
1642
1643 andi.l &0x00ff00ff,USER_FPSR(%a6)
1644
1645 clr.l %d0
1646 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1647
1648 tst.b %d1
1649 bne.b _L6_2s
1650 bsr.l satan # operand is a NORM
1651 bra.b _L6_6s
1652_L6_2s:
1653 cmpi.b %d1,&ZERO # is operand a ZERO?
1654 bne.b _L6_3s # no
1655 bsr.l src_zero # yes
1656 bra.b _L6_6s
1657_L6_3s:
1658 cmpi.b %d1,&INF # is operand an INF?
1659 bne.b _L6_4s # no
1660 bsr.l spi_2 # yes
1661 bra.b _L6_6s
1662_L6_4s:
1663 cmpi.b %d1,&QNAN # is operand a QNAN?
1664 bne.b _L6_5s # no
1665 bsr.l src_qnan # yes
1666 bra.b _L6_6s
1667_L6_5s:
1668 bsr.l satand # operand is a DENORM
1669_L6_6s:
1670
1671#
1672# Result is now in FP0
1673#
1674 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1675 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1676 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1677 unlk %a6
1678 rts
1679
1680 global _fatand_
1681_fatand_:
1682 link %a6,&-LOCAL_SIZE
1683
1684 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1685 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1686 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1687
1688 fmov.l &0x0,%fpcr # zero FPCR
1689
1690#
1691# copy, convert, and tag input argument
1692#
1693 fmov.d 0x8(%a6),%fp0 # load dbl input
1694 fmov.x %fp0,FP_SRC(%a6)
1695 lea FP_SRC(%a6),%a0
1696 bsr.l tag # fetch operand type
1697 mov.b %d0,STAG(%a6)
1698 mov.b %d0,%d1
1699
1700 andi.l &0x00ff00ff,USER_FPSR(%a6)
1701
1702 clr.l %d0
1703 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1704
1705 mov.b %d1,STAG(%a6)
1706 tst.b %d1
1707 bne.b _L6_2d
1708 bsr.l satan # operand is a NORM
1709 bra.b _L6_6d
1710_L6_2d:
1711 cmpi.b %d1,&ZERO # is operand a ZERO?
1712 bne.b _L6_3d # no
1713 bsr.l src_zero # yes
1714 bra.b _L6_6d
1715_L6_3d:
1716 cmpi.b %d1,&INF # is operand an INF?
1717 bne.b _L6_4d # no
1718 bsr.l spi_2 # yes
1719 bra.b _L6_6d
1720_L6_4d:
1721 cmpi.b %d1,&QNAN # is operand a QNAN?
1722 bne.b _L6_5d # no
1723 bsr.l src_qnan # yes
1724 bra.b _L6_6d
1725_L6_5d:
1726 bsr.l satand # operand is a DENORM
1727_L6_6d:
1728
1729#
1730# Result is now in FP0
1731#
1732 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1733 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1734 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1735 unlk %a6
1736 rts
1737
1738 global _fatanx_
1739_fatanx_:
1740 link %a6,&-LOCAL_SIZE
1741
1742 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1743 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1744 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1745
1746 fmov.l &0x0,%fpcr # zero FPCR
1747
1748#
1749# copy, convert, and tag input argument
1750#
1751 lea FP_SRC(%a6),%a0
1752 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1753 mov.l 0x8+0x4(%a6),0x4(%a0)
1754 mov.l 0x8+0x8(%a6),0x8(%a0)
1755 bsr.l tag # fetch operand type
1756 mov.b %d0,STAG(%a6)
1757 mov.b %d0,%d1
1758
1759 andi.l &0x00ff00ff,USER_FPSR(%a6)
1760
1761 clr.l %d0
1762 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1763
1764 tst.b %d1
1765 bne.b _L6_2x
1766 bsr.l satan # operand is a NORM
1767 bra.b _L6_6x
1768_L6_2x:
1769 cmpi.b %d1,&ZERO # is operand a ZERO?
1770 bne.b _L6_3x # no
1771 bsr.l src_zero # yes
1772 bra.b _L6_6x
1773_L6_3x:
1774 cmpi.b %d1,&INF # is operand an INF?
1775 bne.b _L6_4x # no
1776 bsr.l spi_2 # yes
1777 bra.b _L6_6x
1778_L6_4x:
1779 cmpi.b %d1,&QNAN # is operand a QNAN?
1780 bne.b _L6_5x # no
1781 bsr.l src_qnan # yes
1782 bra.b _L6_6x
1783_L6_5x:
1784 bsr.l satand # operand is a DENORM
1785_L6_6x:
1786
1787#
1788# Result is now in FP0
1789#
1790 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1791 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1792 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1793 unlk %a6
1794 rts
1795
1796
1797#########################################################################
1798# MONADIC TEMPLATE #
1799#########################################################################
1800 global _fasins_
1801_fasins_:
1802 link %a6,&-LOCAL_SIZE
1803
1804 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1805 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1806 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1807
1808 fmov.l &0x0,%fpcr # zero FPCR
1809
1810#
1811# copy, convert, and tag input argument
1812#
1813 fmov.s 0x8(%a6),%fp0 # load sgl input
1814 fmov.x %fp0,FP_SRC(%a6)
1815 lea FP_SRC(%a6),%a0
1816 bsr.l tag # fetch operand type
1817 mov.b %d0,STAG(%a6)
1818 mov.b %d0,%d1
1819
1820 andi.l &0x00ff00ff,USER_FPSR(%a6)
1821
1822 clr.l %d0
1823 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1824
1825 tst.b %d1
1826 bne.b _L7_2s
1827 bsr.l sasin # operand is a NORM
1828 bra.b _L7_6s
1829_L7_2s:
1830 cmpi.b %d1,&ZERO # is operand a ZERO?
1831 bne.b _L7_3s # no
1832 bsr.l src_zero # yes
1833 bra.b _L7_6s
1834_L7_3s:
1835 cmpi.b %d1,&INF # is operand an INF?
1836 bne.b _L7_4s # no
1837 bsr.l t_operr # yes
1838 bra.b _L7_6s
1839_L7_4s:
1840 cmpi.b %d1,&QNAN # is operand a QNAN?
1841 bne.b _L7_5s # no
1842 bsr.l src_qnan # yes
1843 bra.b _L7_6s
1844_L7_5s:
1845 bsr.l sasind # operand is a DENORM
1846_L7_6s:
1847
1848#
1849# Result is now in FP0
1850#
1851 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1852 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1853 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1854 unlk %a6
1855 rts
1856
1857 global _fasind_
1858_fasind_:
1859 link %a6,&-LOCAL_SIZE
1860
1861 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1862 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1863 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1864
1865 fmov.l &0x0,%fpcr # zero FPCR
1866
1867#
1868# copy, convert, and tag input argument
1869#
1870 fmov.d 0x8(%a6),%fp0 # load dbl input
1871 fmov.x %fp0,FP_SRC(%a6)
1872 lea FP_SRC(%a6),%a0
1873 bsr.l tag # fetch operand type
1874 mov.b %d0,STAG(%a6)
1875 mov.b %d0,%d1
1876
1877 andi.l &0x00ff00ff,USER_FPSR(%a6)
1878
1879 clr.l %d0
1880 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1881
1882 mov.b %d1,STAG(%a6)
1883 tst.b %d1
1884 bne.b _L7_2d
1885 bsr.l sasin # operand is a NORM
1886 bra.b _L7_6d
1887_L7_2d:
1888 cmpi.b %d1,&ZERO # is operand a ZERO?
1889 bne.b _L7_3d # no
1890 bsr.l src_zero # yes
1891 bra.b _L7_6d
1892_L7_3d:
1893 cmpi.b %d1,&INF # is operand an INF?
1894 bne.b _L7_4d # no
1895 bsr.l t_operr # yes
1896 bra.b _L7_6d
1897_L7_4d:
1898 cmpi.b %d1,&QNAN # is operand a QNAN?
1899 bne.b _L7_5d # no
1900 bsr.l src_qnan # yes
1901 bra.b _L7_6d
1902_L7_5d:
1903 bsr.l sasind # operand is a DENORM
1904_L7_6d:
1905
1906#
1907# Result is now in FP0
1908#
1909 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1910 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1911 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1912 unlk %a6
1913 rts
1914
1915 global _fasinx_
1916_fasinx_:
1917 link %a6,&-LOCAL_SIZE
1918
1919 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1920 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1921 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1922
1923 fmov.l &0x0,%fpcr # zero FPCR
1924
1925#
1926# copy, convert, and tag input argument
1927#
1928 lea FP_SRC(%a6),%a0
1929 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1930 mov.l 0x8+0x4(%a6),0x4(%a0)
1931 mov.l 0x8+0x8(%a6),0x8(%a0)
1932 bsr.l tag # fetch operand type
1933 mov.b %d0,STAG(%a6)
1934 mov.b %d0,%d1
1935
1936 andi.l &0x00ff00ff,USER_FPSR(%a6)
1937
1938 clr.l %d0
1939 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1940
1941 tst.b %d1
1942 bne.b _L7_2x
1943 bsr.l sasin # operand is a NORM
1944 bra.b _L7_6x
1945_L7_2x:
1946 cmpi.b %d1,&ZERO # is operand a ZERO?
1947 bne.b _L7_3x # no
1948 bsr.l src_zero # yes
1949 bra.b _L7_6x
1950_L7_3x:
1951 cmpi.b %d1,&INF # is operand an INF?
1952 bne.b _L7_4x # no
1953 bsr.l t_operr # yes
1954 bra.b _L7_6x
1955_L7_4x:
1956 cmpi.b %d1,&QNAN # is operand a QNAN?
1957 bne.b _L7_5x # no
1958 bsr.l src_qnan # yes
1959 bra.b _L7_6x
1960_L7_5x:
1961 bsr.l sasind # operand is a DENORM
1962_L7_6x:
1963
1964#
1965# Result is now in FP0
1966#
1967 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1968 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1969 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1970 unlk %a6
1971 rts
1972
1973
1974#########################################################################
1975# MONADIC TEMPLATE #
1976#########################################################################
1977 global _fatanhs_
1978_fatanhs_:
1979 link %a6,&-LOCAL_SIZE
1980
1981 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1982 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1983 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1984
1985 fmov.l &0x0,%fpcr # zero FPCR
1986
1987#
1988# copy, convert, and tag input argument
1989#
1990 fmov.s 0x8(%a6),%fp0 # load sgl input
1991 fmov.x %fp0,FP_SRC(%a6)
1992 lea FP_SRC(%a6),%a0
1993 bsr.l tag # fetch operand type
1994 mov.b %d0,STAG(%a6)
1995 mov.b %d0,%d1
1996
1997 andi.l &0x00ff00ff,USER_FPSR(%a6)
1998
1999 clr.l %d0
2000 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2001
2002 tst.b %d1
2003 bne.b _L8_2s
2004 bsr.l satanh # operand is a NORM
2005 bra.b _L8_6s
2006_L8_2s:
2007 cmpi.b %d1,&ZERO # is operand a ZERO?
2008 bne.b _L8_3s # no
2009 bsr.l src_zero # yes
2010 bra.b _L8_6s
2011_L8_3s:
2012 cmpi.b %d1,&INF # is operand an INF?
2013 bne.b _L8_4s # no
2014 bsr.l t_operr # yes
2015 bra.b _L8_6s
2016_L8_4s:
2017 cmpi.b %d1,&QNAN # is operand a QNAN?
2018 bne.b _L8_5s # no
2019 bsr.l src_qnan # yes
2020 bra.b _L8_6s
2021_L8_5s:
2022 bsr.l satanhd # operand is a DENORM
2023_L8_6s:
2024
2025#
2026# Result is now in FP0
2027#
2028 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2029 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2030 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2031 unlk %a6
2032 rts
2033
2034 global _fatanhd_
2035_fatanhd_:
2036 link %a6,&-LOCAL_SIZE
2037
2038 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2039 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2040 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2041
2042 fmov.l &0x0,%fpcr # zero FPCR
2043
2044#
2045# copy, convert, and tag input argument
2046#
2047 fmov.d 0x8(%a6),%fp0 # load dbl input
2048 fmov.x %fp0,FP_SRC(%a6)
2049 lea FP_SRC(%a6),%a0
2050 bsr.l tag # fetch operand type
2051 mov.b %d0,STAG(%a6)
2052 mov.b %d0,%d1
2053
2054 andi.l &0x00ff00ff,USER_FPSR(%a6)
2055
2056 clr.l %d0
2057 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2058
2059 mov.b %d1,STAG(%a6)
2060 tst.b %d1
2061 bne.b _L8_2d
2062 bsr.l satanh # operand is a NORM
2063 bra.b _L8_6d
2064_L8_2d:
2065 cmpi.b %d1,&ZERO # is operand a ZERO?
2066 bne.b _L8_3d # no
2067 bsr.l src_zero # yes
2068 bra.b _L8_6d
2069_L8_3d:
2070 cmpi.b %d1,&INF # is operand an INF?
2071 bne.b _L8_4d # no
2072 bsr.l t_operr # yes
2073 bra.b _L8_6d
2074_L8_4d:
2075 cmpi.b %d1,&QNAN # is operand a QNAN?
2076 bne.b _L8_5d # no
2077 bsr.l src_qnan # yes
2078 bra.b _L8_6d
2079_L8_5d:
2080 bsr.l satanhd # operand is a DENORM
2081_L8_6d:
2082
2083#
2084# Result is now in FP0
2085#
2086 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2087 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2088 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2089 unlk %a6
2090 rts
2091
2092 global _fatanhx_
2093_fatanhx_:
2094 link %a6,&-LOCAL_SIZE
2095
2096 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2097 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2098 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2099
2100 fmov.l &0x0,%fpcr # zero FPCR
2101
2102#
2103# copy, convert, and tag input argument
2104#
2105 lea FP_SRC(%a6),%a0
2106 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2107 mov.l 0x8+0x4(%a6),0x4(%a0)
2108 mov.l 0x8+0x8(%a6),0x8(%a0)
2109 bsr.l tag # fetch operand type
2110 mov.b %d0,STAG(%a6)
2111 mov.b %d0,%d1
2112
2113 andi.l &0x00ff00ff,USER_FPSR(%a6)
2114
2115 clr.l %d0
2116 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2117
2118 tst.b %d1
2119 bne.b _L8_2x
2120 bsr.l satanh # operand is a NORM
2121 bra.b _L8_6x
2122_L8_2x:
2123 cmpi.b %d1,&ZERO # is operand a ZERO?
2124 bne.b _L8_3x # no
2125 bsr.l src_zero # yes
2126 bra.b _L8_6x
2127_L8_3x:
2128 cmpi.b %d1,&INF # is operand an INF?
2129 bne.b _L8_4x # no
2130 bsr.l t_operr # yes
2131 bra.b _L8_6x
2132_L8_4x:
2133 cmpi.b %d1,&QNAN # is operand a QNAN?
2134 bne.b _L8_5x # no
2135 bsr.l src_qnan # yes
2136 bra.b _L8_6x
2137_L8_5x:
2138 bsr.l satanhd # operand is a DENORM
2139_L8_6x:
2140
2141#
2142# Result is now in FP0
2143#
2144 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2145 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2146 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2147 unlk %a6
2148 rts
2149
2150
2151#########################################################################
2152# MONADIC TEMPLATE #
2153#########################################################################
2154 global _ftans_
2155_ftans_:
2156 link %a6,&-LOCAL_SIZE
2157
2158 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2159 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2160 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2161
2162 fmov.l &0x0,%fpcr # zero FPCR
2163
2164#
2165# copy, convert, and tag input argument
2166#
2167 fmov.s 0x8(%a6),%fp0 # load sgl input
2168 fmov.x %fp0,FP_SRC(%a6)
2169 lea FP_SRC(%a6),%a0
2170 bsr.l tag # fetch operand type
2171 mov.b %d0,STAG(%a6)
2172 mov.b %d0,%d1
2173
2174 andi.l &0x00ff00ff,USER_FPSR(%a6)
2175
2176 clr.l %d0
2177 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2178
2179 tst.b %d1
2180 bne.b _L9_2s
2181 bsr.l stan # operand is a NORM
2182 bra.b _L9_6s
2183_L9_2s:
2184 cmpi.b %d1,&ZERO # is operand a ZERO?
2185 bne.b _L9_3s # no
2186 bsr.l src_zero # yes
2187 bra.b _L9_6s
2188_L9_3s:
2189 cmpi.b %d1,&INF # is operand an INF?
2190 bne.b _L9_4s # no
2191 bsr.l t_operr # yes
2192 bra.b _L9_6s
2193_L9_4s:
2194 cmpi.b %d1,&QNAN # is operand a QNAN?
2195 bne.b _L9_5s # no
2196 bsr.l src_qnan # yes
2197 bra.b _L9_6s
2198_L9_5s:
2199 bsr.l stand # operand is a DENORM
2200_L9_6s:
2201
2202#
2203# Result is now in FP0
2204#
2205 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2206 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2207 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2208 unlk %a6
2209 rts
2210
2211 global _ftand_
2212_ftand_:
2213 link %a6,&-LOCAL_SIZE
2214
2215 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2216 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2217 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2218
2219 fmov.l &0x0,%fpcr # zero FPCR
2220
2221#
2222# copy, convert, and tag input argument
2223#
2224 fmov.d 0x8(%a6),%fp0 # load dbl input
2225 fmov.x %fp0,FP_SRC(%a6)
2226 lea FP_SRC(%a6),%a0
2227 bsr.l tag # fetch operand type
2228 mov.b %d0,STAG(%a6)
2229 mov.b %d0,%d1
2230
2231 andi.l &0x00ff00ff,USER_FPSR(%a6)
2232
2233 clr.l %d0
2234 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2235
2236 mov.b %d1,STAG(%a6)
2237 tst.b %d1
2238 bne.b _L9_2d
2239 bsr.l stan # operand is a NORM
2240 bra.b _L9_6d
2241_L9_2d:
2242 cmpi.b %d1,&ZERO # is operand a ZERO?
2243 bne.b _L9_3d # no
2244 bsr.l src_zero # yes
2245 bra.b _L9_6d
2246_L9_3d:
2247 cmpi.b %d1,&INF # is operand an INF?
2248 bne.b _L9_4d # no
2249 bsr.l t_operr # yes
2250 bra.b _L9_6d
2251_L9_4d:
2252 cmpi.b %d1,&QNAN # is operand a QNAN?
2253 bne.b _L9_5d # no
2254 bsr.l src_qnan # yes
2255 bra.b _L9_6d
2256_L9_5d:
2257 bsr.l stand # operand is a DENORM
2258_L9_6d:
2259
2260#
2261# Result is now in FP0
2262#
2263 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2264 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2265 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2266 unlk %a6
2267 rts
2268
2269 global _ftanx_
2270_ftanx_:
2271 link %a6,&-LOCAL_SIZE
2272
2273 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2274 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2275 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2276
2277 fmov.l &0x0,%fpcr # zero FPCR
2278
2279#
2280# copy, convert, and tag input argument
2281#
2282 lea FP_SRC(%a6),%a0
2283 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2284 mov.l 0x8+0x4(%a6),0x4(%a0)
2285 mov.l 0x8+0x8(%a6),0x8(%a0)
2286 bsr.l tag # fetch operand type
2287 mov.b %d0,STAG(%a6)
2288 mov.b %d0,%d1
2289
2290 andi.l &0x00ff00ff,USER_FPSR(%a6)
2291
2292 clr.l %d0
2293 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2294
2295 tst.b %d1
2296 bne.b _L9_2x
2297 bsr.l stan # operand is a NORM
2298 bra.b _L9_6x
2299_L9_2x:
2300 cmpi.b %d1,&ZERO # is operand a ZERO?
2301 bne.b _L9_3x # no
2302 bsr.l src_zero # yes
2303 bra.b _L9_6x
2304_L9_3x:
2305 cmpi.b %d1,&INF # is operand an INF?
2306 bne.b _L9_4x # no
2307 bsr.l t_operr # yes
2308 bra.b _L9_6x
2309_L9_4x:
2310 cmpi.b %d1,&QNAN # is operand a QNAN?
2311 bne.b _L9_5x # no
2312 bsr.l src_qnan # yes
2313 bra.b _L9_6x
2314_L9_5x:
2315 bsr.l stand # operand is a DENORM
2316_L9_6x:
2317
2318#
2319# Result is now in FP0
2320#
2321 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2322 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2323 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2324 unlk %a6
2325 rts
2326
2327
2328#########################################################################
2329# MONADIC TEMPLATE #
2330#########################################################################
2331 global _fetoxs_
2332_fetoxs_:
2333 link %a6,&-LOCAL_SIZE
2334
2335 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2336 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2337 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2338
2339 fmov.l &0x0,%fpcr # zero FPCR
2340
2341#
2342# copy, convert, and tag input argument
2343#
2344 fmov.s 0x8(%a6),%fp0 # load sgl input
2345 fmov.x %fp0,FP_SRC(%a6)
2346 lea FP_SRC(%a6),%a0
2347 bsr.l tag # fetch operand type
2348 mov.b %d0,STAG(%a6)
2349 mov.b %d0,%d1
2350
2351 andi.l &0x00ff00ff,USER_FPSR(%a6)
2352
2353 clr.l %d0
2354 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2355
2356 tst.b %d1
2357 bne.b _L10_2s
2358 bsr.l setox # operand is a NORM
2359 bra.b _L10_6s
2360_L10_2s:
2361 cmpi.b %d1,&ZERO # is operand a ZERO?
2362 bne.b _L10_3s # no
2363 bsr.l ld_pone # yes
2364 bra.b _L10_6s
2365_L10_3s:
2366 cmpi.b %d1,&INF # is operand an INF?
2367 bne.b _L10_4s # no
2368 bsr.l szr_inf # yes
2369 bra.b _L10_6s
2370_L10_4s:
2371 cmpi.b %d1,&QNAN # is operand a QNAN?
2372 bne.b _L10_5s # no
2373 bsr.l src_qnan # yes
2374 bra.b _L10_6s
2375_L10_5s:
2376 bsr.l setoxd # operand is a DENORM
2377_L10_6s:
2378
2379#
2380# Result is now in FP0
2381#
2382 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2383 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2384 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2385 unlk %a6
2386 rts
2387
2388 global _fetoxd_
2389_fetoxd_:
2390 link %a6,&-LOCAL_SIZE
2391
2392 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2393 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2394 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2395
2396 fmov.l &0x0,%fpcr # zero FPCR
2397
2398#
2399# copy, convert, and tag input argument
2400#
2401 fmov.d 0x8(%a6),%fp0 # load dbl input
2402 fmov.x %fp0,FP_SRC(%a6)
2403 lea FP_SRC(%a6),%a0
2404 bsr.l tag # fetch operand type
2405 mov.b %d0,STAG(%a6)
2406 mov.b %d0,%d1
2407
2408 andi.l &0x00ff00ff,USER_FPSR(%a6)
2409
2410 clr.l %d0
2411 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2412
2413 mov.b %d1,STAG(%a6)
2414 tst.b %d1
2415 bne.b _L10_2d
2416 bsr.l setox # operand is a NORM
2417 bra.b _L10_6d
2418_L10_2d:
2419 cmpi.b %d1,&ZERO # is operand a ZERO?
2420 bne.b _L10_3d # no
2421 bsr.l ld_pone # yes
2422 bra.b _L10_6d
2423_L10_3d:
2424 cmpi.b %d1,&INF # is operand an INF?
2425 bne.b _L10_4d # no
2426 bsr.l szr_inf # yes
2427 bra.b _L10_6d
2428_L10_4d:
2429 cmpi.b %d1,&QNAN # is operand a QNAN?
2430 bne.b _L10_5d # no
2431 bsr.l src_qnan # yes
2432 bra.b _L10_6d
2433_L10_5d:
2434 bsr.l setoxd # operand is a DENORM
2435_L10_6d:
2436
2437#
2438# Result is now in FP0
2439#
2440 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2441 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2442 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2443 unlk %a6
2444 rts
2445
2446 global _fetoxx_
2447_fetoxx_:
2448 link %a6,&-LOCAL_SIZE
2449
2450 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2451 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2452 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2453
2454 fmov.l &0x0,%fpcr # zero FPCR
2455
2456#
2457# copy, convert, and tag input argument
2458#
2459 lea FP_SRC(%a6),%a0
2460 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2461 mov.l 0x8+0x4(%a6),0x4(%a0)
2462 mov.l 0x8+0x8(%a6),0x8(%a0)
2463 bsr.l tag # fetch operand type
2464 mov.b %d0,STAG(%a6)
2465 mov.b %d0,%d1
2466
2467 andi.l &0x00ff00ff,USER_FPSR(%a6)
2468
2469 clr.l %d0
2470 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2471
2472 tst.b %d1
2473 bne.b _L10_2x
2474 bsr.l setox # operand is a NORM
2475 bra.b _L10_6x
2476_L10_2x:
2477 cmpi.b %d1,&ZERO # is operand a ZERO?
2478 bne.b _L10_3x # no
2479 bsr.l ld_pone # yes
2480 bra.b _L10_6x
2481_L10_3x:
2482 cmpi.b %d1,&INF # is operand an INF?
2483 bne.b _L10_4x # no
2484 bsr.l szr_inf # yes
2485 bra.b _L10_6x
2486_L10_4x:
2487 cmpi.b %d1,&QNAN # is operand a QNAN?
2488 bne.b _L10_5x # no
2489 bsr.l src_qnan # yes
2490 bra.b _L10_6x
2491_L10_5x:
2492 bsr.l setoxd # operand is a DENORM
2493_L10_6x:
2494
2495#
2496# Result is now in FP0
2497#
2498 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2499 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2500 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2501 unlk %a6
2502 rts
2503
2504
2505#########################################################################
2506# MONADIC TEMPLATE #
2507#########################################################################
2508 global _ftwotoxs_
2509_ftwotoxs_:
2510 link %a6,&-LOCAL_SIZE
2511
2512 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2513 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2514 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2515
2516 fmov.l &0x0,%fpcr # zero FPCR
2517
2518#
2519# copy, convert, and tag input argument
2520#
2521 fmov.s 0x8(%a6),%fp0 # load sgl input
2522 fmov.x %fp0,FP_SRC(%a6)
2523 lea FP_SRC(%a6),%a0
2524 bsr.l tag # fetch operand type
2525 mov.b %d0,STAG(%a6)
2526 mov.b %d0,%d1
2527
2528 andi.l &0x00ff00ff,USER_FPSR(%a6)
2529
2530 clr.l %d0
2531 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2532
2533 tst.b %d1
2534 bne.b _L11_2s
2535 bsr.l stwotox # operand is a NORM
2536 bra.b _L11_6s
2537_L11_2s:
2538 cmpi.b %d1,&ZERO # is operand a ZERO?
2539 bne.b _L11_3s # no
2540 bsr.l ld_pone # yes
2541 bra.b _L11_6s
2542_L11_3s:
2543 cmpi.b %d1,&INF # is operand an INF?
2544 bne.b _L11_4s # no
2545 bsr.l szr_inf # yes
2546 bra.b _L11_6s
2547_L11_4s:
2548 cmpi.b %d1,&QNAN # is operand a QNAN?
2549 bne.b _L11_5s # no
2550 bsr.l src_qnan # yes
2551 bra.b _L11_6s
2552_L11_5s:
2553 bsr.l stwotoxd # operand is a DENORM
2554_L11_6s:
2555
2556#
2557# Result is now in FP0
2558#
2559 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2560 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2561 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2562 unlk %a6
2563 rts
2564
2565 global _ftwotoxd_
2566_ftwotoxd_:
2567 link %a6,&-LOCAL_SIZE
2568
2569 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2570 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2571 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2572
2573 fmov.l &0x0,%fpcr # zero FPCR
2574
2575#
2576# copy, convert, and tag input argument
2577#
2578 fmov.d 0x8(%a6),%fp0 # load dbl input
2579 fmov.x %fp0,FP_SRC(%a6)
2580 lea FP_SRC(%a6),%a0
2581 bsr.l tag # fetch operand type
2582 mov.b %d0,STAG(%a6)
2583 mov.b %d0,%d1
2584
2585 andi.l &0x00ff00ff,USER_FPSR(%a6)
2586
2587 clr.l %d0
2588 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2589
2590 mov.b %d1,STAG(%a6)
2591 tst.b %d1
2592 bne.b _L11_2d
2593 bsr.l stwotox # operand is a NORM
2594 bra.b _L11_6d
2595_L11_2d:
2596 cmpi.b %d1,&ZERO # is operand a ZERO?
2597 bne.b _L11_3d # no
2598 bsr.l ld_pone # yes
2599 bra.b _L11_6d
2600_L11_3d:
2601 cmpi.b %d1,&INF # is operand an INF?
2602 bne.b _L11_4d # no
2603 bsr.l szr_inf # yes
2604 bra.b _L11_6d
2605_L11_4d:
2606 cmpi.b %d1,&QNAN # is operand a QNAN?
2607 bne.b _L11_5d # no
2608 bsr.l src_qnan # yes
2609 bra.b _L11_6d
2610_L11_5d:
2611 bsr.l stwotoxd # operand is a DENORM
2612_L11_6d:
2613
2614#
2615# Result is now in FP0
2616#
2617 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2618 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2619 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2620 unlk %a6
2621 rts
2622
2623 global _ftwotoxx_
2624_ftwotoxx_:
2625 link %a6,&-LOCAL_SIZE
2626
2627 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2628 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2629 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2630
2631 fmov.l &0x0,%fpcr # zero FPCR
2632
2633#
2634# copy, convert, and tag input argument
2635#
2636 lea FP_SRC(%a6),%a0
2637 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2638 mov.l 0x8+0x4(%a6),0x4(%a0)
2639 mov.l 0x8+0x8(%a6),0x8(%a0)
2640 bsr.l tag # fetch operand type
2641 mov.b %d0,STAG(%a6)
2642 mov.b %d0,%d1
2643
2644 andi.l &0x00ff00ff,USER_FPSR(%a6)
2645
2646 clr.l %d0
2647 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2648
2649 tst.b %d1
2650 bne.b _L11_2x
2651 bsr.l stwotox # operand is a NORM
2652 bra.b _L11_6x
2653_L11_2x:
2654 cmpi.b %d1,&ZERO # is operand a ZERO?
2655 bne.b _L11_3x # no
2656 bsr.l ld_pone # yes
2657 bra.b _L11_6x
2658_L11_3x:
2659 cmpi.b %d1,&INF # is operand an INF?
2660 bne.b _L11_4x # no
2661 bsr.l szr_inf # yes
2662 bra.b _L11_6x
2663_L11_4x:
2664 cmpi.b %d1,&QNAN # is operand a QNAN?
2665 bne.b _L11_5x # no
2666 bsr.l src_qnan # yes
2667 bra.b _L11_6x
2668_L11_5x:
2669 bsr.l stwotoxd # operand is a DENORM
2670_L11_6x:
2671
2672#
2673# Result is now in FP0
2674#
2675 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2676 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2677 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2678 unlk %a6
2679 rts
2680
2681
2682#########################################################################
2683# MONADIC TEMPLATE #
2684#########################################################################
2685 global _ftentoxs_
2686_ftentoxs_:
2687 link %a6,&-LOCAL_SIZE
2688
2689 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2690 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2691 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2692
2693 fmov.l &0x0,%fpcr # zero FPCR
2694
2695#
2696# copy, convert, and tag input argument
2697#
2698 fmov.s 0x8(%a6),%fp0 # load sgl input
2699 fmov.x %fp0,FP_SRC(%a6)
2700 lea FP_SRC(%a6),%a0
2701 bsr.l tag # fetch operand type
2702 mov.b %d0,STAG(%a6)
2703 mov.b %d0,%d1
2704
2705 andi.l &0x00ff00ff,USER_FPSR(%a6)
2706
2707 clr.l %d0
2708 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2709
2710 tst.b %d1
2711 bne.b _L12_2s
2712 bsr.l stentox # operand is a NORM
2713 bra.b _L12_6s
2714_L12_2s:
2715 cmpi.b %d1,&ZERO # is operand a ZERO?
2716 bne.b _L12_3s # no
2717 bsr.l ld_pone # yes
2718 bra.b _L12_6s
2719_L12_3s:
2720 cmpi.b %d1,&INF # is operand an INF?
2721 bne.b _L12_4s # no
2722 bsr.l szr_inf # yes
2723 bra.b _L12_6s
2724_L12_4s:
2725 cmpi.b %d1,&QNAN # is operand a QNAN?
2726 bne.b _L12_5s # no
2727 bsr.l src_qnan # yes
2728 bra.b _L12_6s
2729_L12_5s:
2730 bsr.l stentoxd # operand is a DENORM
2731_L12_6s:
2732
2733#
2734# Result is now in FP0
2735#
2736 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2737 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2738 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2739 unlk %a6
2740 rts
2741
2742 global _ftentoxd_
2743_ftentoxd_:
2744 link %a6,&-LOCAL_SIZE
2745
2746 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2747 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2748 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2749
2750 fmov.l &0x0,%fpcr # zero FPCR
2751
2752#
2753# copy, convert, and tag input argument
2754#
2755 fmov.d 0x8(%a6),%fp0 # load dbl input
2756 fmov.x %fp0,FP_SRC(%a6)
2757 lea FP_SRC(%a6),%a0
2758 bsr.l tag # fetch operand type
2759 mov.b %d0,STAG(%a6)
2760 mov.b %d0,%d1
2761
2762 andi.l &0x00ff00ff,USER_FPSR(%a6)
2763
2764 clr.l %d0
2765 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2766
2767 mov.b %d1,STAG(%a6)
2768 tst.b %d1
2769 bne.b _L12_2d
2770 bsr.l stentox # operand is a NORM
2771 bra.b _L12_6d
2772_L12_2d:
2773 cmpi.b %d1,&ZERO # is operand a ZERO?
2774 bne.b _L12_3d # no
2775 bsr.l ld_pone # yes
2776 bra.b _L12_6d
2777_L12_3d:
2778 cmpi.b %d1,&INF # is operand an INF?
2779 bne.b _L12_4d # no
2780 bsr.l szr_inf # yes
2781 bra.b _L12_6d
2782_L12_4d:
2783 cmpi.b %d1,&QNAN # is operand a QNAN?
2784 bne.b _L12_5d # no
2785 bsr.l src_qnan # yes
2786 bra.b _L12_6d
2787_L12_5d:
2788 bsr.l stentoxd # operand is a DENORM
2789_L12_6d:
2790
2791#
2792# Result is now in FP0
2793#
2794 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2795 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2796 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2797 unlk %a6
2798 rts
2799
2800 global _ftentoxx_
2801_ftentoxx_:
2802 link %a6,&-LOCAL_SIZE
2803
2804 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2805 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2806 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2807
2808 fmov.l &0x0,%fpcr # zero FPCR
2809
2810#
2811# copy, convert, and tag input argument
2812#
2813 lea FP_SRC(%a6),%a0
2814 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2815 mov.l 0x8+0x4(%a6),0x4(%a0)
2816 mov.l 0x8+0x8(%a6),0x8(%a0)
2817 bsr.l tag # fetch operand type
2818 mov.b %d0,STAG(%a6)
2819 mov.b %d0,%d1
2820
2821 andi.l &0x00ff00ff,USER_FPSR(%a6)
2822
2823 clr.l %d0
2824 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2825
2826 tst.b %d1
2827 bne.b _L12_2x
2828 bsr.l stentox # operand is a NORM
2829 bra.b _L12_6x
2830_L12_2x:
2831 cmpi.b %d1,&ZERO # is operand a ZERO?
2832 bne.b _L12_3x # no
2833 bsr.l ld_pone # yes
2834 bra.b _L12_6x
2835_L12_3x:
2836 cmpi.b %d1,&INF # is operand an INF?
2837 bne.b _L12_4x # no
2838 bsr.l szr_inf # yes
2839 bra.b _L12_6x
2840_L12_4x:
2841 cmpi.b %d1,&QNAN # is operand a QNAN?
2842 bne.b _L12_5x # no
2843 bsr.l src_qnan # yes
2844 bra.b _L12_6x
2845_L12_5x:
2846 bsr.l stentoxd # operand is a DENORM
2847_L12_6x:
2848
2849#
2850# Result is now in FP0
2851#
2852 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2853 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2854 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2855 unlk %a6
2856 rts
2857
2858
2859#########################################################################
2860# MONADIC TEMPLATE #
2861#########################################################################
2862 global _flogns_
2863_flogns_:
2864 link %a6,&-LOCAL_SIZE
2865
2866 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2867 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2868 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2869
2870 fmov.l &0x0,%fpcr # zero FPCR
2871
2872#
2873# copy, convert, and tag input argument
2874#
2875 fmov.s 0x8(%a6),%fp0 # load sgl input
2876 fmov.x %fp0,FP_SRC(%a6)
2877 lea FP_SRC(%a6),%a0
2878 bsr.l tag # fetch operand type
2879 mov.b %d0,STAG(%a6)
2880 mov.b %d0,%d1
2881
2882 andi.l &0x00ff00ff,USER_FPSR(%a6)
2883
2884 clr.l %d0
2885 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2886
2887 tst.b %d1
2888 bne.b _L13_2s
2889 bsr.l slogn # operand is a NORM
2890 bra.b _L13_6s
2891_L13_2s:
2892 cmpi.b %d1,&ZERO # is operand a ZERO?
2893 bne.b _L13_3s # no
2894 bsr.l t_dz2 # yes
2895 bra.b _L13_6s
2896_L13_3s:
2897 cmpi.b %d1,&INF # is operand an INF?
2898 bne.b _L13_4s # no
2899 bsr.l sopr_inf # yes
2900 bra.b _L13_6s
2901_L13_4s:
2902 cmpi.b %d1,&QNAN # is operand a QNAN?
2903 bne.b _L13_5s # no
2904 bsr.l src_qnan # yes
2905 bra.b _L13_6s
2906_L13_5s:
2907 bsr.l slognd # operand is a DENORM
2908_L13_6s:
2909
2910#
2911# Result is now in FP0
2912#
2913 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2914 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2915 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2916 unlk %a6
2917 rts
2918
2919 global _flognd_
2920_flognd_:
2921 link %a6,&-LOCAL_SIZE
2922
2923 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2924 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2925 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2926
2927 fmov.l &0x0,%fpcr # zero FPCR
2928
2929#
2930# copy, convert, and tag input argument
2931#
2932 fmov.d 0x8(%a6),%fp0 # load dbl input
2933 fmov.x %fp0,FP_SRC(%a6)
2934 lea FP_SRC(%a6),%a0
2935 bsr.l tag # fetch operand type
2936 mov.b %d0,STAG(%a6)
2937 mov.b %d0,%d1
2938
2939 andi.l &0x00ff00ff,USER_FPSR(%a6)
2940
2941 clr.l %d0
2942 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2943
2944 mov.b %d1,STAG(%a6)
2945 tst.b %d1
2946 bne.b _L13_2d
2947 bsr.l slogn # operand is a NORM
2948 bra.b _L13_6d
2949_L13_2d:
2950 cmpi.b %d1,&ZERO # is operand a ZERO?
2951 bne.b _L13_3d # no
2952 bsr.l t_dz2 # yes
2953 bra.b _L13_6d
2954_L13_3d:
2955 cmpi.b %d1,&INF # is operand an INF?
2956 bne.b _L13_4d # no
2957 bsr.l sopr_inf # yes
2958 bra.b _L13_6d
2959_L13_4d:
2960 cmpi.b %d1,&QNAN # is operand a QNAN?
2961 bne.b _L13_5d # no
2962 bsr.l src_qnan # yes
2963 bra.b _L13_6d
2964_L13_5d:
2965 bsr.l slognd # operand is a DENORM
2966_L13_6d:
2967
2968#
2969# Result is now in FP0
2970#
2971 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2972 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2973 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2974 unlk %a6
2975 rts
2976
2977 global _flognx_
2978_flognx_:
2979 link %a6,&-LOCAL_SIZE
2980
2981 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2982 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2983 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2984
2985 fmov.l &0x0,%fpcr # zero FPCR
2986
2987#
2988# copy, convert, and tag input argument
2989#
2990 lea FP_SRC(%a6),%a0
2991 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2992 mov.l 0x8+0x4(%a6),0x4(%a0)
2993 mov.l 0x8+0x8(%a6),0x8(%a0)
2994 bsr.l tag # fetch operand type
2995 mov.b %d0,STAG(%a6)
2996 mov.b %d0,%d1
2997
2998 andi.l &0x00ff00ff,USER_FPSR(%a6)
2999
3000 clr.l %d0
3001 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3002
3003 tst.b %d1
3004 bne.b _L13_2x
3005 bsr.l slogn # operand is a NORM
3006 bra.b _L13_6x
3007_L13_2x:
3008 cmpi.b %d1,&ZERO # is operand a ZERO?
3009 bne.b _L13_3x # no
3010 bsr.l t_dz2 # yes
3011 bra.b _L13_6x
3012_L13_3x:
3013 cmpi.b %d1,&INF # is operand an INF?
3014 bne.b _L13_4x # no
3015 bsr.l sopr_inf # yes
3016 bra.b _L13_6x
3017_L13_4x:
3018 cmpi.b %d1,&QNAN # is operand a QNAN?
3019 bne.b _L13_5x # no
3020 bsr.l src_qnan # yes
3021 bra.b _L13_6x
3022_L13_5x:
3023 bsr.l slognd # operand is a DENORM
3024_L13_6x:
3025
3026#
3027# Result is now in FP0
3028#
3029 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3030 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3031 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3032 unlk %a6
3033 rts
3034
3035
3036#########################################################################
3037# MONADIC TEMPLATE #
3038#########################################################################
3039 global _flog10s_
3040_flog10s_:
3041 link %a6,&-LOCAL_SIZE
3042
3043 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3044 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3045 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3046
3047 fmov.l &0x0,%fpcr # zero FPCR
3048
3049#
3050# copy, convert, and tag input argument
3051#
3052 fmov.s 0x8(%a6),%fp0 # load sgl input
3053 fmov.x %fp0,FP_SRC(%a6)
3054 lea FP_SRC(%a6),%a0
3055 bsr.l tag # fetch operand type
3056 mov.b %d0,STAG(%a6)
3057 mov.b %d0,%d1
3058
3059 andi.l &0x00ff00ff,USER_FPSR(%a6)
3060
3061 clr.l %d0
3062 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3063
3064 tst.b %d1
3065 bne.b _L14_2s
3066 bsr.l slog10 # operand is a NORM
3067 bra.b _L14_6s
3068_L14_2s:
3069 cmpi.b %d1,&ZERO # is operand a ZERO?
3070 bne.b _L14_3s # no
3071 bsr.l t_dz2 # yes
3072 bra.b _L14_6s
3073_L14_3s:
3074 cmpi.b %d1,&INF # is operand an INF?
3075 bne.b _L14_4s # no
3076 bsr.l sopr_inf # yes
3077 bra.b _L14_6s
3078_L14_4s:
3079 cmpi.b %d1,&QNAN # is operand a QNAN?
3080 bne.b _L14_5s # no
3081 bsr.l src_qnan # yes
3082 bra.b _L14_6s
3083_L14_5s:
3084 bsr.l slog10d # operand is a DENORM
3085_L14_6s:
3086
3087#
3088# Result is now in FP0
3089#
3090 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3091 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3092 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3093 unlk %a6
3094 rts
3095
3096 global _flog10d_
3097_flog10d_:
3098 link %a6,&-LOCAL_SIZE
3099
3100 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3101 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3102 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3103
3104 fmov.l &0x0,%fpcr # zero FPCR
3105
3106#
3107# copy, convert, and tag input argument
3108#
3109 fmov.d 0x8(%a6),%fp0 # load dbl input
3110 fmov.x %fp0,FP_SRC(%a6)
3111 lea FP_SRC(%a6),%a0
3112 bsr.l tag # fetch operand type
3113 mov.b %d0,STAG(%a6)
3114 mov.b %d0,%d1
3115
3116 andi.l &0x00ff00ff,USER_FPSR(%a6)
3117
3118 clr.l %d0
3119 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3120
3121 mov.b %d1,STAG(%a6)
3122 tst.b %d1
3123 bne.b _L14_2d
3124 bsr.l slog10 # operand is a NORM
3125 bra.b _L14_6d
3126_L14_2d:
3127 cmpi.b %d1,&ZERO # is operand a ZERO?
3128 bne.b _L14_3d # no
3129 bsr.l t_dz2 # yes
3130 bra.b _L14_6d
3131_L14_3d:
3132 cmpi.b %d1,&INF # is operand an INF?
3133 bne.b _L14_4d # no
3134 bsr.l sopr_inf # yes
3135 bra.b _L14_6d
3136_L14_4d:
3137 cmpi.b %d1,&QNAN # is operand a QNAN?
3138 bne.b _L14_5d # no
3139 bsr.l src_qnan # yes
3140 bra.b _L14_6d
3141_L14_5d:
3142 bsr.l slog10d # operand is a DENORM
3143_L14_6d:
3144
3145#
3146# Result is now in FP0
3147#
3148 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3149 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3150 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3151 unlk %a6
3152 rts
3153
3154 global _flog10x_
3155_flog10x_:
3156 link %a6,&-LOCAL_SIZE
3157
3158 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3159 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3160 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3161
3162 fmov.l &0x0,%fpcr # zero FPCR
3163
3164#
3165# copy, convert, and tag input argument
3166#
3167 lea FP_SRC(%a6),%a0
3168 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3169 mov.l 0x8+0x4(%a6),0x4(%a0)
3170 mov.l 0x8+0x8(%a6),0x8(%a0)
3171 bsr.l tag # fetch operand type
3172 mov.b %d0,STAG(%a6)
3173 mov.b %d0,%d1
3174
3175 andi.l &0x00ff00ff,USER_FPSR(%a6)
3176
3177 clr.l %d0
3178 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3179
3180 tst.b %d1
3181 bne.b _L14_2x
3182 bsr.l slog10 # operand is a NORM
3183 bra.b _L14_6x
3184_L14_2x:
3185 cmpi.b %d1,&ZERO # is operand a ZERO?
3186 bne.b _L14_3x # no
3187 bsr.l t_dz2 # yes
3188 bra.b _L14_6x
3189_L14_3x:
3190 cmpi.b %d1,&INF # is operand an INF?
3191 bne.b _L14_4x # no
3192 bsr.l sopr_inf # yes
3193 bra.b _L14_6x
3194_L14_4x:
3195 cmpi.b %d1,&QNAN # is operand a QNAN?
3196 bne.b _L14_5x # no
3197 bsr.l src_qnan # yes
3198 bra.b _L14_6x
3199_L14_5x:
3200 bsr.l slog10d # operand is a DENORM
3201_L14_6x:
3202
3203#
3204# Result is now in FP0
3205#
3206 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3207 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3208 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3209 unlk %a6
3210 rts
3211
3212
3213#########################################################################
3214# MONADIC TEMPLATE #
3215#########################################################################
3216 global _flog2s_
3217_flog2s_:
3218 link %a6,&-LOCAL_SIZE
3219
3220 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3221 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3222 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3223
3224 fmov.l &0x0,%fpcr # zero FPCR
3225
3226#
3227# copy, convert, and tag input argument
3228#
3229 fmov.s 0x8(%a6),%fp0 # load sgl input
3230 fmov.x %fp0,FP_SRC(%a6)
3231 lea FP_SRC(%a6),%a0
3232 bsr.l tag # fetch operand type
3233 mov.b %d0,STAG(%a6)
3234 mov.b %d0,%d1
3235
3236 andi.l &0x00ff00ff,USER_FPSR(%a6)
3237
3238 clr.l %d0
3239 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3240
3241 tst.b %d1
3242 bne.b _L15_2s
3243 bsr.l slog2 # operand is a NORM
3244 bra.b _L15_6s
3245_L15_2s:
3246 cmpi.b %d1,&ZERO # is operand a ZERO?
3247 bne.b _L15_3s # no
3248 bsr.l t_dz2 # yes
3249 bra.b _L15_6s
3250_L15_3s:
3251 cmpi.b %d1,&INF # is operand an INF?
3252 bne.b _L15_4s # no
3253 bsr.l sopr_inf # yes
3254 bra.b _L15_6s
3255_L15_4s:
3256 cmpi.b %d1,&QNAN # is operand a QNAN?
3257 bne.b _L15_5s # no
3258 bsr.l src_qnan # yes
3259 bra.b _L15_6s
3260_L15_5s:
3261 bsr.l slog2d # operand is a DENORM
3262_L15_6s:
3263
3264#
3265# Result is now in FP0
3266#
3267 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3268 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3269 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3270 unlk %a6
3271 rts
3272
3273 global _flog2d_
3274_flog2d_:
3275 link %a6,&-LOCAL_SIZE
3276
3277 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3278 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3279 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3280
3281 fmov.l &0x0,%fpcr # zero FPCR
3282
3283#
3284# copy, convert, and tag input argument
3285#
3286 fmov.d 0x8(%a6),%fp0 # load dbl input
3287 fmov.x %fp0,FP_SRC(%a6)
3288 lea FP_SRC(%a6),%a0
3289 bsr.l tag # fetch operand type
3290 mov.b %d0,STAG(%a6)
3291 mov.b %d0,%d1
3292
3293 andi.l &0x00ff00ff,USER_FPSR(%a6)
3294
3295 clr.l %d0
3296 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3297
3298 mov.b %d1,STAG(%a6)
3299 tst.b %d1
3300 bne.b _L15_2d
3301 bsr.l slog2 # operand is a NORM
3302 bra.b _L15_6d
3303_L15_2d:
3304 cmpi.b %d1,&ZERO # is operand a ZERO?
3305 bne.b _L15_3d # no
3306 bsr.l t_dz2 # yes
3307 bra.b _L15_6d
3308_L15_3d:
3309 cmpi.b %d1,&INF # is operand an INF?
3310 bne.b _L15_4d # no
3311 bsr.l sopr_inf # yes
3312 bra.b _L15_6d
3313_L15_4d:
3314 cmpi.b %d1,&QNAN # is operand a QNAN?
3315 bne.b _L15_5d # no
3316 bsr.l src_qnan # yes
3317 bra.b _L15_6d
3318_L15_5d:
3319 bsr.l slog2d # operand is a DENORM
3320_L15_6d:
3321
3322#
3323# Result is now in FP0
3324#
3325 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3326 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3327 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3328 unlk %a6
3329 rts
3330
3331 global _flog2x_
3332_flog2x_:
3333 link %a6,&-LOCAL_SIZE
3334
3335 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3336 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3337 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3338
3339 fmov.l &0x0,%fpcr # zero FPCR
3340
3341#
3342# copy, convert, and tag input argument
3343#
3344 lea FP_SRC(%a6),%a0
3345 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3346 mov.l 0x8+0x4(%a6),0x4(%a0)
3347 mov.l 0x8+0x8(%a6),0x8(%a0)
3348 bsr.l tag # fetch operand type
3349 mov.b %d0,STAG(%a6)
3350 mov.b %d0,%d1
3351
3352 andi.l &0x00ff00ff,USER_FPSR(%a6)
3353
3354 clr.l %d0
3355 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3356
3357 tst.b %d1
3358 bne.b _L15_2x
3359 bsr.l slog2 # operand is a NORM
3360 bra.b _L15_6x
3361_L15_2x:
3362 cmpi.b %d1,&ZERO # is operand a ZERO?
3363 bne.b _L15_3x # no
3364 bsr.l t_dz2 # yes
3365 bra.b _L15_6x
3366_L15_3x:
3367 cmpi.b %d1,&INF # is operand an INF?
3368 bne.b _L15_4x # no
3369 bsr.l sopr_inf # yes
3370 bra.b _L15_6x
3371_L15_4x:
3372 cmpi.b %d1,&QNAN # is operand a QNAN?
3373 bne.b _L15_5x # no
3374 bsr.l src_qnan # yes
3375 bra.b _L15_6x
3376_L15_5x:
3377 bsr.l slog2d # operand is a DENORM
3378_L15_6x:
3379
3380#
3381# Result is now in FP0
3382#
3383 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3384 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3385 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3386 unlk %a6
3387 rts
3388
3389
3390#########################################################################
3391# MONADIC TEMPLATE #
3392#########################################################################
3393 global _fcoshs_
3394_fcoshs_:
3395 link %a6,&-LOCAL_SIZE
3396
3397 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3398 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3399 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3400
3401 fmov.l &0x0,%fpcr # zero FPCR
3402
3403#
3404# copy, convert, and tag input argument
3405#
3406 fmov.s 0x8(%a6),%fp0 # load sgl input
3407 fmov.x %fp0,FP_SRC(%a6)
3408 lea FP_SRC(%a6),%a0
3409 bsr.l tag # fetch operand type
3410 mov.b %d0,STAG(%a6)
3411 mov.b %d0,%d1
3412
3413 andi.l &0x00ff00ff,USER_FPSR(%a6)
3414
3415 clr.l %d0
3416 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3417
3418 tst.b %d1
3419 bne.b _L16_2s
3420 bsr.l scosh # operand is a NORM
3421 bra.b _L16_6s
3422_L16_2s:
3423 cmpi.b %d1,&ZERO # is operand a ZERO?
3424 bne.b _L16_3s # no
3425 bsr.l ld_pone # yes
3426 bra.b _L16_6s
3427_L16_3s:
3428 cmpi.b %d1,&INF # is operand an INF?
3429 bne.b _L16_4s # no
3430 bsr.l ld_pinf # yes
3431 bra.b _L16_6s
3432_L16_4s:
3433 cmpi.b %d1,&QNAN # is operand a QNAN?
3434 bne.b _L16_5s # no
3435 bsr.l src_qnan # yes
3436 bra.b _L16_6s
3437_L16_5s:
3438 bsr.l scoshd # operand is a DENORM
3439_L16_6s:
3440
3441#
3442# Result is now in FP0
3443#
3444 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3445 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3446 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3447 unlk %a6
3448 rts
3449
3450 global _fcoshd_
3451_fcoshd_:
3452 link %a6,&-LOCAL_SIZE
3453
3454 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3455 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3456 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3457
3458 fmov.l &0x0,%fpcr # zero FPCR
3459
3460#
3461# copy, convert, and tag input argument
3462#
3463 fmov.d 0x8(%a6),%fp0 # load dbl input
3464 fmov.x %fp0,FP_SRC(%a6)
3465 lea FP_SRC(%a6),%a0
3466 bsr.l tag # fetch operand type
3467 mov.b %d0,STAG(%a6)
3468 mov.b %d0,%d1
3469
3470 andi.l &0x00ff00ff,USER_FPSR(%a6)
3471
3472 clr.l %d0
3473 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3474
3475 mov.b %d1,STAG(%a6)
3476 tst.b %d1
3477 bne.b _L16_2d
3478 bsr.l scosh # operand is a NORM
3479 bra.b _L16_6d
3480_L16_2d:
3481 cmpi.b %d1,&ZERO # is operand a ZERO?
3482 bne.b _L16_3d # no
3483 bsr.l ld_pone # yes
3484 bra.b _L16_6d
3485_L16_3d:
3486 cmpi.b %d1,&INF # is operand an INF?
3487 bne.b _L16_4d # no
3488 bsr.l ld_pinf # yes
3489 bra.b _L16_6d
3490_L16_4d:
3491 cmpi.b %d1,&QNAN # is operand a QNAN?
3492 bne.b _L16_5d # no
3493 bsr.l src_qnan # yes
3494 bra.b _L16_6d
3495_L16_5d:
3496 bsr.l scoshd # operand is a DENORM
3497_L16_6d:
3498
3499#
3500# Result is now in FP0
3501#
3502 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3503 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3504 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3505 unlk %a6
3506 rts
3507
3508 global _fcoshx_
3509_fcoshx_:
3510 link %a6,&-LOCAL_SIZE
3511
3512 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3513 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3514 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3515
3516 fmov.l &0x0,%fpcr # zero FPCR
3517
3518#
3519# copy, convert, and tag input argument
3520#
3521 lea FP_SRC(%a6),%a0
3522 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3523 mov.l 0x8+0x4(%a6),0x4(%a0)
3524 mov.l 0x8+0x8(%a6),0x8(%a0)
3525 bsr.l tag # fetch operand type
3526 mov.b %d0,STAG(%a6)
3527 mov.b %d0,%d1
3528
3529 andi.l &0x00ff00ff,USER_FPSR(%a6)
3530
3531 clr.l %d0
3532 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3533
3534 tst.b %d1
3535 bne.b _L16_2x
3536 bsr.l scosh # operand is a NORM
3537 bra.b _L16_6x
3538_L16_2x:
3539 cmpi.b %d1,&ZERO # is operand a ZERO?
3540 bne.b _L16_3x # no
3541 bsr.l ld_pone # yes
3542 bra.b _L16_6x
3543_L16_3x:
3544 cmpi.b %d1,&INF # is operand an INF?
3545 bne.b _L16_4x # no
3546 bsr.l ld_pinf # yes
3547 bra.b _L16_6x
3548_L16_4x:
3549 cmpi.b %d1,&QNAN # is operand a QNAN?
3550 bne.b _L16_5x # no
3551 bsr.l src_qnan # yes
3552 bra.b _L16_6x
3553_L16_5x:
3554 bsr.l scoshd # operand is a DENORM
3555_L16_6x:
3556
3557#
3558# Result is now in FP0
3559#
3560 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3561 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3562 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3563 unlk %a6
3564 rts
3565
3566
3567#########################################################################
3568# MONADIC TEMPLATE #
3569#########################################################################
3570 global _facoss_
3571_facoss_:
3572 link %a6,&-LOCAL_SIZE
3573
3574 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3575 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3576 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3577
3578 fmov.l &0x0,%fpcr # zero FPCR
3579
3580#
3581# copy, convert, and tag input argument
3582#
3583 fmov.s 0x8(%a6),%fp0 # load sgl input
3584 fmov.x %fp0,FP_SRC(%a6)
3585 lea FP_SRC(%a6),%a0
3586 bsr.l tag # fetch operand type
3587 mov.b %d0,STAG(%a6)
3588 mov.b %d0,%d1
3589
3590 andi.l &0x00ff00ff,USER_FPSR(%a6)
3591
3592 clr.l %d0
3593 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3594
3595 tst.b %d1
3596 bne.b _L17_2s
3597 bsr.l sacos # operand is a NORM
3598 bra.b _L17_6s
3599_L17_2s:
3600 cmpi.b %d1,&ZERO # is operand a ZERO?
3601 bne.b _L17_3s # no
3602 bsr.l ld_ppi2 # yes
3603 bra.b _L17_6s
3604_L17_3s:
3605 cmpi.b %d1,&INF # is operand an INF?
3606 bne.b _L17_4s # no
3607 bsr.l t_operr # yes
3608 bra.b _L17_6s
3609_L17_4s:
3610 cmpi.b %d1,&QNAN # is operand a QNAN?
3611 bne.b _L17_5s # no
3612 bsr.l src_qnan # yes
3613 bra.b _L17_6s
3614_L17_5s:
3615 bsr.l sacosd # operand is a DENORM
3616_L17_6s:
3617
3618#
3619# Result is now in FP0
3620#
3621 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3622 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3623 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3624 unlk %a6
3625 rts
3626
3627 global _facosd_
3628_facosd_:
3629 link %a6,&-LOCAL_SIZE
3630
3631 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3632 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3633 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3634
3635 fmov.l &0x0,%fpcr # zero FPCR
3636
3637#
3638# copy, convert, and tag input argument
3639#
3640 fmov.d 0x8(%a6),%fp0 # load dbl input
3641 fmov.x %fp0,FP_SRC(%a6)
3642 lea FP_SRC(%a6),%a0
3643 bsr.l tag # fetch operand type
3644 mov.b %d0,STAG(%a6)
3645 mov.b %d0,%d1
3646
3647 andi.l &0x00ff00ff,USER_FPSR(%a6)
3648
3649 clr.l %d0
3650 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3651
3652 mov.b %d1,STAG(%a6)
3653 tst.b %d1
3654 bne.b _L17_2d
3655 bsr.l sacos # operand is a NORM
3656 bra.b _L17_6d
3657_L17_2d:
3658 cmpi.b %d1,&ZERO # is operand a ZERO?
3659 bne.b _L17_3d # no
3660 bsr.l ld_ppi2 # yes
3661 bra.b _L17_6d
3662_L17_3d:
3663 cmpi.b %d1,&INF # is operand an INF?
3664 bne.b _L17_4d # no
3665 bsr.l t_operr # yes
3666 bra.b _L17_6d
3667_L17_4d:
3668 cmpi.b %d1,&QNAN # is operand a QNAN?
3669 bne.b _L17_5d # no
3670 bsr.l src_qnan # yes
3671 bra.b _L17_6d
3672_L17_5d:
3673 bsr.l sacosd # operand is a DENORM
3674_L17_6d:
3675
3676#
3677# Result is now in FP0
3678#
3679 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3680 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3681 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3682 unlk %a6
3683 rts
3684
3685 global _facosx_
3686_facosx_:
3687 link %a6,&-LOCAL_SIZE
3688
3689 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3690 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3691 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3692
3693 fmov.l &0x0,%fpcr # zero FPCR
3694
3695#
3696# copy, convert, and tag input argument
3697#
3698 lea FP_SRC(%a6),%a0
3699 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3700 mov.l 0x8+0x4(%a6),0x4(%a0)
3701 mov.l 0x8+0x8(%a6),0x8(%a0)
3702 bsr.l tag # fetch operand type
3703 mov.b %d0,STAG(%a6)
3704 mov.b %d0,%d1
3705
3706 andi.l &0x00ff00ff,USER_FPSR(%a6)
3707
3708 clr.l %d0
3709 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3710
3711 tst.b %d1
3712 bne.b _L17_2x
3713 bsr.l sacos # operand is a NORM
3714 bra.b _L17_6x
3715_L17_2x:
3716 cmpi.b %d1,&ZERO # is operand a ZERO?
3717 bne.b _L17_3x # no
3718 bsr.l ld_ppi2 # yes
3719 bra.b _L17_6x
3720_L17_3x:
3721 cmpi.b %d1,&INF # is operand an INF?
3722 bne.b _L17_4x # no
3723 bsr.l t_operr # yes
3724 bra.b _L17_6x
3725_L17_4x:
3726 cmpi.b %d1,&QNAN # is operand a QNAN?
3727 bne.b _L17_5x # no
3728 bsr.l src_qnan # yes
3729 bra.b _L17_6x
3730_L17_5x:
3731 bsr.l sacosd # operand is a DENORM
3732_L17_6x:
3733
3734#
3735# Result is now in FP0
3736#
3737 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3738 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3739 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3740 unlk %a6
3741 rts
3742
3743
3744#########################################################################
3745# MONADIC TEMPLATE #
3746#########################################################################
3747 global _fgetexps_
3748_fgetexps_:
3749 link %a6,&-LOCAL_SIZE
3750
3751 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3752 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3753 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3754
3755 fmov.l &0x0,%fpcr # zero FPCR
3756
3757#
3758# copy, convert, and tag input argument
3759#
3760 fmov.s 0x8(%a6),%fp0 # load sgl input
3761 fmov.x %fp0,FP_SRC(%a6)
3762 lea FP_SRC(%a6),%a0
3763 bsr.l tag # fetch operand type
3764 mov.b %d0,STAG(%a6)
3765 mov.b %d0,%d1
3766
3767 andi.l &0x00ff00ff,USER_FPSR(%a6)
3768
3769 clr.l %d0
3770 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3771
3772 tst.b %d1
3773 bne.b _L18_2s
3774 bsr.l sgetexp # operand is a NORM
3775 bra.b _L18_6s
3776_L18_2s:
3777 cmpi.b %d1,&ZERO # is operand a ZERO?
3778 bne.b _L18_3s # no
3779 bsr.l src_zero # yes
3780 bra.b _L18_6s
3781_L18_3s:
3782 cmpi.b %d1,&INF # is operand an INF?
3783 bne.b _L18_4s # no
3784 bsr.l t_operr # yes
3785 bra.b _L18_6s
3786_L18_4s:
3787 cmpi.b %d1,&QNAN # is operand a QNAN?
3788 bne.b _L18_5s # no
3789 bsr.l src_qnan # yes
3790 bra.b _L18_6s
3791_L18_5s:
3792 bsr.l sgetexpd # operand is a DENORM
3793_L18_6s:
3794
3795#
3796# Result is now in FP0
3797#
3798 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3799 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3800 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3801 unlk %a6
3802 rts
3803
3804 global _fgetexpd_
3805_fgetexpd_:
3806 link %a6,&-LOCAL_SIZE
3807
3808 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3809 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3810 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3811
3812 fmov.l &0x0,%fpcr # zero FPCR
3813
3814#
3815# copy, convert, and tag input argument
3816#
3817 fmov.d 0x8(%a6),%fp0 # load dbl input
3818 fmov.x %fp0,FP_SRC(%a6)
3819 lea FP_SRC(%a6),%a0
3820 bsr.l tag # fetch operand type
3821 mov.b %d0,STAG(%a6)
3822 mov.b %d0,%d1
3823
3824 andi.l &0x00ff00ff,USER_FPSR(%a6)
3825
3826 clr.l %d0
3827 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3828
3829 mov.b %d1,STAG(%a6)
3830 tst.b %d1
3831 bne.b _L18_2d
3832 bsr.l sgetexp # operand is a NORM
3833 bra.b _L18_6d
3834_L18_2d:
3835 cmpi.b %d1,&ZERO # is operand a ZERO?
3836 bne.b _L18_3d # no
3837 bsr.l src_zero # yes
3838 bra.b _L18_6d
3839_L18_3d:
3840 cmpi.b %d1,&INF # is operand an INF?
3841 bne.b _L18_4d # no
3842 bsr.l t_operr # yes
3843 bra.b _L18_6d
3844_L18_4d:
3845 cmpi.b %d1,&QNAN # is operand a QNAN?
3846 bne.b _L18_5d # no
3847 bsr.l src_qnan # yes
3848 bra.b _L18_6d
3849_L18_5d:
3850 bsr.l sgetexpd # operand is a DENORM
3851_L18_6d:
3852
3853#
3854# Result is now in FP0
3855#
3856 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3857 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3858 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3859 unlk %a6
3860 rts
3861
3862 global _fgetexpx_
3863_fgetexpx_:
3864 link %a6,&-LOCAL_SIZE
3865
3866 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3867 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3868 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3869
3870 fmov.l &0x0,%fpcr # zero FPCR
3871
3872#
3873# copy, convert, and tag input argument
3874#
3875 lea FP_SRC(%a6),%a0
3876 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3877 mov.l 0x8+0x4(%a6),0x4(%a0)
3878 mov.l 0x8+0x8(%a6),0x8(%a0)
3879 bsr.l tag # fetch operand type
3880 mov.b %d0,STAG(%a6)
3881 mov.b %d0,%d1
3882
3883 andi.l &0x00ff00ff,USER_FPSR(%a6)
3884
3885 clr.l %d0
3886 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3887
3888 tst.b %d1
3889 bne.b _L18_2x
3890 bsr.l sgetexp # operand is a NORM
3891 bra.b _L18_6x
3892_L18_2x:
3893 cmpi.b %d1,&ZERO # is operand a ZERO?
3894 bne.b _L18_3x # no
3895 bsr.l src_zero # yes
3896 bra.b _L18_6x
3897_L18_3x:
3898 cmpi.b %d1,&INF # is operand an INF?
3899 bne.b _L18_4x # no
3900 bsr.l t_operr # yes
3901 bra.b _L18_6x
3902_L18_4x:
3903 cmpi.b %d1,&QNAN # is operand a QNAN?
3904 bne.b _L18_5x # no
3905 bsr.l src_qnan # yes
3906 bra.b _L18_6x
3907_L18_5x:
3908 bsr.l sgetexpd # operand is a DENORM
3909_L18_6x:
3910
3911#
3912# Result is now in FP0
3913#
3914 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3915 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3916 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3917 unlk %a6
3918 rts
3919
3920
3921#########################################################################
3922# MONADIC TEMPLATE #
3923#########################################################################
3924 global _fgetmans_
3925_fgetmans_:
3926 link %a6,&-LOCAL_SIZE
3927
3928 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3929 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3930 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3931
3932 fmov.l &0x0,%fpcr # zero FPCR
3933
3934#
3935# copy, convert, and tag input argument
3936#
3937 fmov.s 0x8(%a6),%fp0 # load sgl input
3938 fmov.x %fp0,FP_SRC(%a6)
3939 lea FP_SRC(%a6),%a0
3940 bsr.l tag # fetch operand type
3941 mov.b %d0,STAG(%a6)
3942 mov.b %d0,%d1
3943
3944 andi.l &0x00ff00ff,USER_FPSR(%a6)
3945
3946 clr.l %d0
3947 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3948
3949 tst.b %d1
3950 bne.b _L19_2s
3951 bsr.l sgetman # operand is a NORM
3952 bra.b _L19_6s
3953_L19_2s:
3954 cmpi.b %d1,&ZERO # is operand a ZERO?
3955 bne.b _L19_3s # no
3956 bsr.l src_zero # yes
3957 bra.b _L19_6s
3958_L19_3s:
3959 cmpi.b %d1,&INF # is operand an INF?
3960 bne.b _L19_4s # no
3961 bsr.l t_operr # yes
3962 bra.b _L19_6s
3963_L19_4s:
3964 cmpi.b %d1,&QNAN # is operand a QNAN?
3965 bne.b _L19_5s # no
3966 bsr.l src_qnan # yes
3967 bra.b _L19_6s
3968_L19_5s:
3969 bsr.l sgetmand # operand is a DENORM
3970_L19_6s:
3971
3972#
3973# Result is now in FP0
3974#
3975 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3976 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3977 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3978 unlk %a6
3979 rts
3980
3981 global _fgetmand_
3982_fgetmand_:
3983 link %a6,&-LOCAL_SIZE
3984
3985 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3986 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3987 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3988
3989 fmov.l &0x0,%fpcr # zero FPCR
3990
3991#
3992# copy, convert, and tag input argument
3993#
3994 fmov.d 0x8(%a6),%fp0 # load dbl input
3995 fmov.x %fp0,FP_SRC(%a6)
3996 lea FP_SRC(%a6),%a0
3997 bsr.l tag # fetch operand type
3998 mov.b %d0,STAG(%a6)
3999 mov.b %d0,%d1
4000
4001 andi.l &0x00ff00ff,USER_FPSR(%a6)
4002
4003 clr.l %d0
4004 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4005
4006 mov.b %d1,STAG(%a6)
4007 tst.b %d1
4008 bne.b _L19_2d
4009 bsr.l sgetman # operand is a NORM
4010 bra.b _L19_6d
4011_L19_2d:
4012 cmpi.b %d1,&ZERO # is operand a ZERO?
4013 bne.b _L19_3d # no
4014 bsr.l src_zero # yes
4015 bra.b _L19_6d
4016_L19_3d:
4017 cmpi.b %d1,&INF # is operand an INF?
4018 bne.b _L19_4d # no
4019 bsr.l t_operr # yes
4020 bra.b _L19_6d
4021_L19_4d:
4022 cmpi.b %d1,&QNAN # is operand a QNAN?
4023 bne.b _L19_5d # no
4024 bsr.l src_qnan # yes
4025 bra.b _L19_6d
4026_L19_5d:
4027 bsr.l sgetmand # operand is a DENORM
4028_L19_6d:
4029
4030#
4031# Result is now in FP0
4032#
4033 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4034 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4035 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4036 unlk %a6
4037 rts
4038
4039 global _fgetmanx_
4040_fgetmanx_:
4041 link %a6,&-LOCAL_SIZE
4042
4043 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4044 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4045 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4046
4047 fmov.l &0x0,%fpcr # zero FPCR
4048
4049#
4050# copy, convert, and tag input argument
4051#
4052 lea FP_SRC(%a6),%a0
4053 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
4054 mov.l 0x8+0x4(%a6),0x4(%a0)
4055 mov.l 0x8+0x8(%a6),0x8(%a0)
4056 bsr.l tag # fetch operand type
4057 mov.b %d0,STAG(%a6)
4058 mov.b %d0,%d1
4059
4060 andi.l &0x00ff00ff,USER_FPSR(%a6)
4061
4062 clr.l %d0
4063 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4064
4065 tst.b %d1
4066 bne.b _L19_2x
4067 bsr.l sgetman # operand is a NORM
4068 bra.b _L19_6x
4069_L19_2x:
4070 cmpi.b %d1,&ZERO # is operand a ZERO?
4071 bne.b _L19_3x # no
4072 bsr.l src_zero # yes
4073 bra.b _L19_6x
4074_L19_3x:
4075 cmpi.b %d1,&INF # is operand an INF?
4076 bne.b _L19_4x # no
4077 bsr.l t_operr # yes
4078 bra.b _L19_6x
4079_L19_4x:
4080 cmpi.b %d1,&QNAN # is operand a QNAN?
4081 bne.b _L19_5x # no
4082 bsr.l src_qnan # yes
4083 bra.b _L19_6x
4084_L19_5x:
4085 bsr.l sgetmand # operand is a DENORM
4086_L19_6x:
4087
4088#
4089# Result is now in FP0
4090#
4091 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4092 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4093 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4094 unlk %a6
4095 rts
4096
4097
4098#########################################################################
4099# MONADIC TEMPLATE #
4100#########################################################################
4101 global _fsincoss_
4102_fsincoss_:
4103 link %a6,&-LOCAL_SIZE
4104
4105 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4106 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4107 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4108
4109 fmov.l &0x0,%fpcr # zero FPCR
4110
4111#
4112# copy, convert, and tag input argument
4113#
4114 fmov.s 0x8(%a6),%fp0 # load sgl input
4115 fmov.x %fp0,FP_SRC(%a6)
4116 lea FP_SRC(%a6),%a0
4117 bsr.l tag # fetch operand type
4118 mov.b %d0,STAG(%a6)
4119 mov.b %d0,%d1
4120
4121 andi.l &0x00ff00ff,USER_FPSR(%a6)
4122
4123 clr.l %d0
4124 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4125
4126 tst.b %d1
4127 bne.b _L20_2s
4128 bsr.l ssincos # operand is a NORM
4129 bra.b _L20_6s
4130_L20_2s:
4131 cmpi.b %d1,&ZERO # is operand a ZERO?
4132 bne.b _L20_3s # no
4133 bsr.l ssincosz # yes
4134 bra.b _L20_6s
4135_L20_3s:
4136 cmpi.b %d1,&INF # is operand an INF?
4137 bne.b _L20_4s # no
4138 bsr.l ssincosi # yes
4139 bra.b _L20_6s
4140_L20_4s:
4141 cmpi.b %d1,&QNAN # is operand a QNAN?
4142 bne.b _L20_5s # no
4143 bsr.l ssincosqnan # yes
4144 bra.b _L20_6s
4145_L20_5s:
4146 bsr.l ssincosd # operand is a DENORM
4147_L20_6s:
4148
4149#
4150# Result is now in FP0
4151#
4152 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4153 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4154 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4155 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4156 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4157 unlk %a6
4158 rts
4159
4160 global _fsincosd_
4161_fsincosd_:
4162 link %a6,&-LOCAL_SIZE
4163
4164 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4165 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4166 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4167
4168 fmov.l &0x0,%fpcr # zero FPCR
4169
4170#
4171# copy, convert, and tag input argument
4172#
4173 fmov.d 0x8(%a6),%fp0 # load dbl input
4174 fmov.x %fp0,FP_SRC(%a6)
4175 lea FP_SRC(%a6),%a0
4176 bsr.l tag # fetch operand type
4177 mov.b %d0,STAG(%a6)
4178 mov.b %d0,%d1
4179
4180 andi.l &0x00ff00ff,USER_FPSR(%a6)
4181
4182 clr.l %d0
4183 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4184
4185 mov.b %d1,STAG(%a6)
4186 tst.b %d1
4187 bne.b _L20_2d
4188 bsr.l ssincos # operand is a NORM
4189 bra.b _L20_6d
4190_L20_2d:
4191 cmpi.b %d1,&ZERO # is operand a ZERO?
4192 bne.b _L20_3d # no
4193 bsr.l ssincosz # yes
4194 bra.b _L20_6d
4195_L20_3d:
4196 cmpi.b %d1,&INF # is operand an INF?
4197 bne.b _L20_4d # no
4198 bsr.l ssincosi # yes
4199 bra.b _L20_6d
4200_L20_4d:
4201 cmpi.b %d1,&QNAN # is operand a QNAN?
4202 bne.b _L20_5d # no
4203 bsr.l ssincosqnan # yes
4204 bra.b _L20_6d
4205_L20_5d:
4206 bsr.l ssincosd # operand is a DENORM
4207_L20_6d:
4208
4209#
4210# Result is now in FP0
4211#
4212 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4213 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4214 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4215 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4216 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4217 unlk %a6
4218 rts
4219
4220 global _fsincosx_
4221_fsincosx_:
4222 link %a6,&-LOCAL_SIZE
4223
4224 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4225 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4226 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4227
4228 fmov.l &0x0,%fpcr # zero FPCR
4229
4230#
4231# copy, convert, and tag input argument
4232#
4233 lea FP_SRC(%a6),%a0
4234 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
4235 mov.l 0x8+0x4(%a6),0x4(%a0)
4236 mov.l 0x8+0x8(%a6),0x8(%a0)
4237 bsr.l tag # fetch operand type
4238 mov.b %d0,STAG(%a6)
4239 mov.b %d0,%d1
4240
4241 andi.l &0x00ff00ff,USER_FPSR(%a6)
4242
4243 clr.l %d0
4244 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4245
4246 tst.b %d1
4247 bne.b _L20_2x
4248 bsr.l ssincos # operand is a NORM
4249 bra.b _L20_6x
4250_L20_2x:
4251 cmpi.b %d1,&ZERO # is operand a ZERO?
4252 bne.b _L20_3x # no
4253 bsr.l ssincosz # yes
4254 bra.b _L20_6x
4255_L20_3x:
4256 cmpi.b %d1,&INF # is operand an INF?
4257 bne.b _L20_4x # no
4258 bsr.l ssincosi # yes
4259 bra.b _L20_6x
4260_L20_4x:
4261 cmpi.b %d1,&QNAN # is operand a QNAN?
4262 bne.b _L20_5x # no
4263 bsr.l ssincosqnan # yes
4264 bra.b _L20_6x
4265_L20_5x:
4266 bsr.l ssincosd # operand is a DENORM
4267_L20_6x:
4268
4269#
4270# Result is now in FP0
4271#
4272 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4273 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4274 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4275 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4276 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4277 unlk %a6
4278 rts
4279
4280
4281#########################################################################
4282# DYADIC TEMPLATE #
4283#########################################################################
4284 global _frems_
4285_frems_:
4286 link %a6,&-LOCAL_SIZE
4287
4288 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4289 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4290 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4291
4292 fmov.l &0x0,%fpcr # zero FPCR
4293
4294#
4295# copy, convert, and tag input argument
4296#
4297 fmov.s 0x8(%a6),%fp0 # load sgl dst
4298 fmov.x %fp0,FP_DST(%a6)
4299 lea FP_DST(%a6),%a0
4300 bsr.l tag # fetch operand type
4301 mov.b %d0,DTAG(%a6)
4302
4303 fmov.s 0xc(%a6),%fp0 # load sgl src
4304 fmov.x %fp0,FP_SRC(%a6)
4305 lea FP_SRC(%a6),%a0
4306 bsr.l tag # fetch operand type
4307 mov.b %d0,STAG(%a6)
4308 mov.l %d0,%d1
4309
4310 andi.l &0x00ff00ff,USER_FPSR(%a6)
4311
4312 clr.l %d0
4313 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4314
4315 lea FP_SRC(%a6),%a0 # pass ptr to src
4316 lea FP_DST(%a6),%a1 # pass ptr to dst
4317
4318 tst.b %d1
4319 bne.b _L21_2s
4320 bsr.l srem_snorm # operand is a NORM
4321 bra.b _L21_6s
4322_L21_2s:
4323 cmpi.b %d1,&ZERO # is operand a ZERO?
4324 bne.b _L21_3s # no
4325 bsr.l srem_szero # yes
4326 bra.b _L21_6s
4327_L21_3s:
4328 cmpi.b %d1,&INF # is operand an INF?
4329 bne.b _L21_4s # no
4330 bsr.l srem_sinf # yes
4331 bra.b _L21_6s
4332_L21_4s:
4333 cmpi.b %d1,&QNAN # is operand a QNAN?
4334 bne.b _L21_5s # no
4335 bsr.l sop_sqnan # yes
4336 bra.b _L21_6s
4337_L21_5s:
4338 bsr.l srem_sdnrm # operand is a DENORM
4339_L21_6s:
4340
4341#
4342# Result is now in FP0
4343#
4344 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4345 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4346 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4347 unlk %a6
4348 rts
4349
4350 global _fremd_
4351_fremd_:
4352 link %a6,&-LOCAL_SIZE
4353
4354 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4355 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4356 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4357
4358 fmov.l &0x0,%fpcr # zero FPCR
4359
4360#
4361# copy, convert, and tag input argument
4362#
4363 fmov.d 0x8(%a6),%fp0 # load dbl dst
4364 fmov.x %fp0,FP_DST(%a6)
4365 lea FP_DST(%a6),%a0
4366 bsr.l tag # fetch operand type
4367 mov.b %d0,DTAG(%a6)
4368
4369 fmov.d 0x10(%a6),%fp0 # load dbl src
4370 fmov.x %fp0,FP_SRC(%a6)
4371 lea FP_SRC(%a6),%a0
4372 bsr.l tag # fetch operand type
4373 mov.b %d0,STAG(%a6)
4374 mov.l %d0,%d1
4375
4376 andi.l &0x00ff00ff,USER_FPSR(%a6)
4377
4378 clr.l %d0
4379 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4380
4381 lea FP_SRC(%a6),%a0 # pass ptr to src
4382 lea FP_DST(%a6),%a1 # pass ptr to dst
4383
4384 tst.b %d1
4385 bne.b _L21_2d
4386 bsr.l srem_snorm # operand is a NORM
4387 bra.b _L21_6d
4388_L21_2d:
4389 cmpi.b %d1,&ZERO # is operand a ZERO?
4390 bne.b _L21_3d # no
4391 bsr.l srem_szero # yes
4392 bra.b _L21_6d
4393_L21_3d:
4394 cmpi.b %d1,&INF # is operand an INF?
4395 bne.b _L21_4d # no
4396 bsr.l srem_sinf # yes
4397 bra.b _L21_6d
4398_L21_4d:
4399 cmpi.b %d1,&QNAN # is operand a QNAN?
4400 bne.b _L21_5d # no
4401 bsr.l sop_sqnan # yes
4402 bra.b _L21_6d
4403_L21_5d:
4404 bsr.l srem_sdnrm # operand is a DENORM
4405_L21_6d:
4406
4407#
4408# Result is now in FP0
4409#
4410 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4411 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4412 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4413 unlk %a6
4414 rts
4415
4416 global _fremx_
4417_fremx_:
4418 link %a6,&-LOCAL_SIZE
4419
4420 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4421 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4422 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4423
4424 fmov.l &0x0,%fpcr # zero FPCR
4425
4426#
4427# copy, convert, and tag input argument
4428#
4429 lea FP_DST(%a6),%a0
4430 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4431 mov.l 0x8+0x4(%a6),0x4(%a0)
4432 mov.l 0x8+0x8(%a6),0x8(%a0)
4433 bsr.l tag # fetch operand type
4434 mov.b %d0,DTAG(%a6)
4435
4436 lea FP_SRC(%a6),%a0
4437 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4438 mov.l 0x14+0x4(%a6),0x4(%a0)
4439 mov.l 0x14+0x8(%a6),0x8(%a0)
4440 bsr.l tag # fetch operand type
4441 mov.b %d0,STAG(%a6)
4442 mov.l %d0,%d1
4443
4444 andi.l &0x00ff00ff,USER_FPSR(%a6)
4445
4446 clr.l %d0
4447 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4448
4449 lea FP_SRC(%a6),%a0 # pass ptr to src
4450 lea FP_DST(%a6),%a1 # pass ptr to dst
4451
4452 tst.b %d1
4453 bne.b _L21_2x
4454 bsr.l srem_snorm # operand is a NORM
4455 bra.b _L21_6x
4456_L21_2x:
4457 cmpi.b %d1,&ZERO # is operand a ZERO?
4458 bne.b _L21_3x # no
4459 bsr.l srem_szero # yes
4460 bra.b _L21_6x
4461_L21_3x:
4462 cmpi.b %d1,&INF # is operand an INF?
4463 bne.b _L21_4x # no
4464 bsr.l srem_sinf # yes
4465 bra.b _L21_6x
4466_L21_4x:
4467 cmpi.b %d1,&QNAN # is operand a QNAN?
4468 bne.b _L21_5x # no
4469 bsr.l sop_sqnan # yes
4470 bra.b _L21_6x
4471_L21_5x:
4472 bsr.l srem_sdnrm # operand is a DENORM
4473_L21_6x:
4474
4475#
4476# Result is now in FP0
4477#
4478 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4479 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4480 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4481 unlk %a6
4482 rts
4483
4484
4485#########################################################################
4486# DYADIC TEMPLATE #
4487#########################################################################
4488 global _fmods_
4489_fmods_:
4490 link %a6,&-LOCAL_SIZE
4491
4492 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4493 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4494 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4495
4496 fmov.l &0x0,%fpcr # zero FPCR
4497
4498#
4499# copy, convert, and tag input argument
4500#
4501 fmov.s 0x8(%a6),%fp0 # load sgl dst
4502 fmov.x %fp0,FP_DST(%a6)
4503 lea FP_DST(%a6),%a0
4504 bsr.l tag # fetch operand type
4505 mov.b %d0,DTAG(%a6)
4506
4507 fmov.s 0xc(%a6),%fp0 # load sgl src
4508 fmov.x %fp0,FP_SRC(%a6)
4509 lea FP_SRC(%a6),%a0
4510 bsr.l tag # fetch operand type
4511 mov.b %d0,STAG(%a6)
4512 mov.l %d0,%d1
4513
4514 andi.l &0x00ff00ff,USER_FPSR(%a6)
4515
4516 clr.l %d0
4517 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4518
4519 lea FP_SRC(%a6),%a0 # pass ptr to src
4520 lea FP_DST(%a6),%a1 # pass ptr to dst
4521
4522 tst.b %d1
4523 bne.b _L22_2s
4524 bsr.l smod_snorm # operand is a NORM
4525 bra.b _L22_6s
4526_L22_2s:
4527 cmpi.b %d1,&ZERO # is operand a ZERO?
4528 bne.b _L22_3s # no
4529 bsr.l smod_szero # yes
4530 bra.b _L22_6s
4531_L22_3s:
4532 cmpi.b %d1,&INF # is operand an INF?
4533 bne.b _L22_4s # no
4534 bsr.l smod_sinf # yes
4535 bra.b _L22_6s
4536_L22_4s:
4537 cmpi.b %d1,&QNAN # is operand a QNAN?
4538 bne.b _L22_5s # no
4539 bsr.l sop_sqnan # yes
4540 bra.b _L22_6s
4541_L22_5s:
4542 bsr.l smod_sdnrm # operand is a DENORM
4543_L22_6s:
4544
4545#
4546# Result is now in FP0
4547#
4548 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4549 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4550 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4551 unlk %a6
4552 rts
4553
4554 global _fmodd_
4555_fmodd_:
4556 link %a6,&-LOCAL_SIZE
4557
4558 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4559 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4560 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4561
4562 fmov.l &0x0,%fpcr # zero FPCR
4563
4564#
4565# copy, convert, and tag input argument
4566#
4567 fmov.d 0x8(%a6),%fp0 # load dbl dst
4568 fmov.x %fp0,FP_DST(%a6)
4569 lea FP_DST(%a6),%a0
4570 bsr.l tag # fetch operand type
4571 mov.b %d0,DTAG(%a6)
4572
4573 fmov.d 0x10(%a6),%fp0 # load dbl src
4574 fmov.x %fp0,FP_SRC(%a6)
4575 lea FP_SRC(%a6),%a0
4576 bsr.l tag # fetch operand type
4577 mov.b %d0,STAG(%a6)
4578 mov.l %d0,%d1
4579
4580 andi.l &0x00ff00ff,USER_FPSR(%a6)
4581
4582 clr.l %d0
4583 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4584
4585 lea FP_SRC(%a6),%a0 # pass ptr to src
4586 lea FP_DST(%a6),%a1 # pass ptr to dst
4587
4588 tst.b %d1
4589 bne.b _L22_2d
4590 bsr.l smod_snorm # operand is a NORM
4591 bra.b _L22_6d
4592_L22_2d:
4593 cmpi.b %d1,&ZERO # is operand a ZERO?
4594 bne.b _L22_3d # no
4595 bsr.l smod_szero # yes
4596 bra.b _L22_6d
4597_L22_3d:
4598 cmpi.b %d1,&INF # is operand an INF?
4599 bne.b _L22_4d # no
4600 bsr.l smod_sinf # yes
4601 bra.b _L22_6d
4602_L22_4d:
4603 cmpi.b %d1,&QNAN # is operand a QNAN?
4604 bne.b _L22_5d # no
4605 bsr.l sop_sqnan # yes
4606 bra.b _L22_6d
4607_L22_5d:
4608 bsr.l smod_sdnrm # operand is a DENORM
4609_L22_6d:
4610
4611#
4612# Result is now in FP0
4613#
4614 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4615 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4616 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4617 unlk %a6
4618 rts
4619
4620 global _fmodx_
4621_fmodx_:
4622 link %a6,&-LOCAL_SIZE
4623
4624 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4625 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4626 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4627
4628 fmov.l &0x0,%fpcr # zero FPCR
4629
4630#
4631# copy, convert, and tag input argument
4632#
4633 lea FP_DST(%a6),%a0
4634 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4635 mov.l 0x8+0x4(%a6),0x4(%a0)
4636 mov.l 0x8+0x8(%a6),0x8(%a0)
4637 bsr.l tag # fetch operand type
4638 mov.b %d0,DTAG(%a6)
4639
4640 lea FP_SRC(%a6),%a0
4641 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4642 mov.l 0x14+0x4(%a6),0x4(%a0)
4643 mov.l 0x14+0x8(%a6),0x8(%a0)
4644 bsr.l tag # fetch operand type
4645 mov.b %d0,STAG(%a6)
4646 mov.l %d0,%d1
4647
4648 andi.l &0x00ff00ff,USER_FPSR(%a6)
4649
4650 clr.l %d0
4651 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4652
4653 lea FP_SRC(%a6),%a0 # pass ptr to src
4654 lea FP_DST(%a6),%a1 # pass ptr to dst
4655
4656 tst.b %d1
4657 bne.b _L22_2x
4658 bsr.l smod_snorm # operand is a NORM
4659 bra.b _L22_6x
4660_L22_2x:
4661 cmpi.b %d1,&ZERO # is operand a ZERO?
4662 bne.b _L22_3x # no
4663 bsr.l smod_szero # yes
4664 bra.b _L22_6x
4665_L22_3x:
4666 cmpi.b %d1,&INF # is operand an INF?
4667 bne.b _L22_4x # no
4668 bsr.l smod_sinf # yes
4669 bra.b _L22_6x
4670_L22_4x:
4671 cmpi.b %d1,&QNAN # is operand a QNAN?
4672 bne.b _L22_5x # no
4673 bsr.l sop_sqnan # yes
4674 bra.b _L22_6x
4675_L22_5x:
4676 bsr.l smod_sdnrm # operand is a DENORM
4677_L22_6x:
4678
4679#
4680# Result is now in FP0
4681#
4682 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4683 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4684 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4685 unlk %a6
4686 rts
4687
4688
4689#########################################################################
4690# DYADIC TEMPLATE #
4691#########################################################################
4692 global _fscales_
4693_fscales_:
4694 link %a6,&-LOCAL_SIZE
4695
4696 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4697 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4698 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4699
4700 fmov.l &0x0,%fpcr # zero FPCR
4701
4702#
4703# copy, convert, and tag input argument
4704#
4705 fmov.s 0x8(%a6),%fp0 # load sgl dst
4706 fmov.x %fp0,FP_DST(%a6)
4707 lea FP_DST(%a6),%a0
4708 bsr.l tag # fetch operand type
4709 mov.b %d0,DTAG(%a6)
4710
4711 fmov.s 0xc(%a6),%fp0 # load sgl src
4712 fmov.x %fp0,FP_SRC(%a6)
4713 lea FP_SRC(%a6),%a0
4714 bsr.l tag # fetch operand type
4715 mov.b %d0,STAG(%a6)
4716 mov.l %d0,%d1
4717
4718 andi.l &0x00ff00ff,USER_FPSR(%a6)
4719
4720 clr.l %d0
4721 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4722
4723 lea FP_SRC(%a6),%a0 # pass ptr to src
4724 lea FP_DST(%a6),%a1 # pass ptr to dst
4725
4726 tst.b %d1
4727 bne.b _L23_2s
4728 bsr.l sscale_snorm # operand is a NORM
4729 bra.b _L23_6s
4730_L23_2s:
4731 cmpi.b %d1,&ZERO # is operand a ZERO?
4732 bne.b _L23_3s # no
4733 bsr.l sscale_szero # yes
4734 bra.b _L23_6s
4735_L23_3s:
4736 cmpi.b %d1,&INF # is operand an INF?
4737 bne.b _L23_4s # no
4738 bsr.l sscale_sinf # yes
4739 bra.b _L23_6s
4740_L23_4s:
4741 cmpi.b %d1,&QNAN # is operand a QNAN?
4742 bne.b _L23_5s # no
4743 bsr.l sop_sqnan # yes
4744 bra.b _L23_6s
4745_L23_5s:
4746 bsr.l sscale_sdnrm # operand is a DENORM
4747_L23_6s:
4748
4749#
4750# Result is now in FP0
4751#
4752 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4753 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4754 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4755 unlk %a6
4756 rts
4757
4758 global _fscaled_
4759_fscaled_:
4760 link %a6,&-LOCAL_SIZE
4761
4762 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4763 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4764 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4765
4766 fmov.l &0x0,%fpcr # zero FPCR
4767
4768#
4769# copy, convert, and tag input argument
4770#
4771 fmov.d 0x8(%a6),%fp0 # load dbl dst
4772 fmov.x %fp0,FP_DST(%a6)
4773 lea FP_DST(%a6),%a0
4774 bsr.l tag # fetch operand type
4775 mov.b %d0,DTAG(%a6)
4776
4777 fmov.d 0x10(%a6),%fp0 # load dbl src
4778 fmov.x %fp0,FP_SRC(%a6)
4779 lea FP_SRC(%a6),%a0
4780 bsr.l tag # fetch operand type
4781 mov.b %d0,STAG(%a6)
4782 mov.l %d0,%d1
4783
4784 andi.l &0x00ff00ff,USER_FPSR(%a6)
4785
4786 clr.l %d0
4787 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4788
4789 lea FP_SRC(%a6),%a0 # pass ptr to src
4790 lea FP_DST(%a6),%a1 # pass ptr to dst
4791
4792 tst.b %d1
4793 bne.b _L23_2d
4794 bsr.l sscale_snorm # operand is a NORM
4795 bra.b _L23_6d
4796_L23_2d:
4797 cmpi.b %d1,&ZERO # is operand a ZERO?
4798 bne.b _L23_3d # no
4799 bsr.l sscale_szero # yes
4800 bra.b _L23_6d
4801_L23_3d:
4802 cmpi.b %d1,&INF # is operand an INF?
4803 bne.b _L23_4d # no
4804 bsr.l sscale_sinf # yes
4805 bra.b _L23_6d
4806_L23_4d:
4807 cmpi.b %d1,&QNAN # is operand a QNAN?
4808 bne.b _L23_5d # no
4809 bsr.l sop_sqnan # yes
4810 bra.b _L23_6d
4811_L23_5d:
4812 bsr.l sscale_sdnrm # operand is a DENORM
4813_L23_6d:
4814
4815#
4816# Result is now in FP0
4817#
4818 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4819 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4820 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4821 unlk %a6
4822 rts
4823
4824 global _fscalex_
4825_fscalex_:
4826 link %a6,&-LOCAL_SIZE
4827
4828 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4829 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4830 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4831
4832 fmov.l &0x0,%fpcr # zero FPCR
4833
4834#
4835# copy, convert, and tag input argument
4836#
4837 lea FP_DST(%a6),%a0
4838 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4839 mov.l 0x8+0x4(%a6),0x4(%a0)
4840 mov.l 0x8+0x8(%a6),0x8(%a0)
4841 bsr.l tag # fetch operand type
4842 mov.b %d0,DTAG(%a6)
4843
4844 lea FP_SRC(%a6),%a0
4845 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4846 mov.l 0x14+0x4(%a6),0x4(%a0)
4847 mov.l 0x14+0x8(%a6),0x8(%a0)
4848 bsr.l tag # fetch operand type
4849 mov.b %d0,STAG(%a6)
4850 mov.l %d0,%d1
4851
4852 andi.l &0x00ff00ff,USER_FPSR(%a6)
4853
4854 clr.l %d0
4855 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4856
4857 lea FP_SRC(%a6),%a0 # pass ptr to src
4858 lea FP_DST(%a6),%a1 # pass ptr to dst
4859
4860 tst.b %d1
4861 bne.b _L23_2x
4862 bsr.l sscale_snorm # operand is a NORM
4863 bra.b _L23_6x
4864_L23_2x:
4865 cmpi.b %d1,&ZERO # is operand a ZERO?
4866 bne.b _L23_3x # no
4867 bsr.l sscale_szero # yes
4868 bra.b _L23_6x
4869_L23_3x:
4870 cmpi.b %d1,&INF # is operand an INF?
4871 bne.b _L23_4x # no
4872 bsr.l sscale_sinf # yes
4873 bra.b _L23_6x
4874_L23_4x:
4875 cmpi.b %d1,&QNAN # is operand a QNAN?
4876 bne.b _L23_5x # no
4877 bsr.l sop_sqnan # yes
4878 bra.b _L23_6x
4879_L23_5x:
4880 bsr.l sscale_sdnrm # operand is a DENORM
4881_L23_6x:
4882
4883#
4884# Result is now in FP0
4885#
4886 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4887 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4888 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4889 unlk %a6
4890 rts
4891
4892
4893#########################################################################
4894# ssin(): computes the sine of a normalized input #
4895# ssind(): computes the sine of a denormalized input #
4896# scos(): computes the cosine of a normalized input #
4897# scosd(): computes the cosine of a denormalized input #
4898# ssincos(): computes the sine and cosine of a normalized input #
4899# ssincosd(): computes the sine and cosine of a denormalized input #
4900# #
4901# INPUT *************************************************************** #
4902# a0 = pointer to extended precision input #
4903# d0 = round precision,mode #
4904# #
4905# OUTPUT ************************************************************** #
4906# fp0 = sin(X) or cos(X) #
4907# #
4908# For ssincos(X): #
4909# fp0 = sin(X) #
4910# fp1 = cos(X) #
4911# #
4912# ACCURACY and MONOTONICITY ******************************************* #
4913# The returned result is within 1 ulp in 64 significant bit, i.e. #
4914# within 0.5001 ulp to 53 bits if the result is subsequently #
4915# rounded to double precision. The result is provably monotonic #
4916# in double precision. #
4917# #
4918# ALGORITHM *********************************************************** #
4919# #
4920# SIN and COS: #
4921# 1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1. #
4922# #
4923# 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7. #
4924# #
4925# 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
4926# k = N mod 4, so in particular, k = 0,1,2,or 3. #
4927# Overwrite k by k := k + AdjN. #
4928# #
4929# 4. If k is even, go to 6. #
4930# #
4931# 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. #
4932# Return sgn*cos(r) where cos(r) is approximated by an #
4933# even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)), #
4934# s = r*r. #
4935# Exit. #
4936# #
4937# 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r) #
4938# where sin(r) is approximated by an odd polynomial in r #
4939# r + r*s*(A1+s*(A2+ ... + s*A7)), s = r*r. #
4940# Exit. #
4941# #
4942# 7. If |X| > 1, go to 9. #
4943# #
4944# 8. (|X|<2**(-40)) If SIN is invoked, return X; #
4945# otherwise return 1. #
4946# #
4947# 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
4948# go back to 3. #
4949# #
4950# SINCOS: #
4951# 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
4952# #
4953# 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
4954# k = N mod 4, so in particular, k = 0,1,2,or 3. #
4955# #
4956# 3. If k is even, go to 5. #
4957# #
4958# 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie. #
4959# j1 exclusive or with the l.s.b. of k. #
4960# sgn1 := (-1)**j1, sgn2 := (-1)**j2. #
4961# SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where #
4962# sin(r) and cos(r) are computed as odd and even #
4963# polynomials in r, respectively. Exit #
4964# #
4965# 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1. #
4966# SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where #
4967# sin(r) and cos(r) are computed as odd and even #
4968# polynomials in r, respectively. Exit #
4969# #
4970# 6. If |X| > 1, go to 8. #
4971# #
4972# 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit. #
4973# #
4974# 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
4975# go back to 2. #
4976# #
4977#########################################################################
4978
4979SINA7: long 0xBD6AAA77,0xCCC994F5
4980SINA6: long 0x3DE61209,0x7AAE8DA1
4981SINA5: long 0xBE5AE645,0x2A118AE4
4982SINA4: long 0x3EC71DE3,0xA5341531
4983SINA3: long 0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
4984SINA2: long 0x3FF80000,0x88888888,0x888859AF,0x00000000
4985SINA1: long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
4986
4987COSB8: long 0x3D2AC4D0,0xD6011EE3
4988COSB7: long 0xBDA9396F,0x9F45AC19
4989COSB6: long 0x3E21EED9,0x0612C972
4990COSB5: long 0xBE927E4F,0xB79D9FCF
4991COSB4: long 0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
4992COSB3: long 0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
4993COSB2: long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
4994COSB1: long 0xBF000000
4995
4996 set INARG,FP_SCR0
4997
4998 set X,FP_SCR0
4999# set XDCARE,X+2
5000 set XFRAC,X+4
5001
5002 set RPRIME,FP_SCR0
5003 set SPRIME,FP_SCR1
5004
5005 set POSNEG1,L_SCR1
5006 set TWOTO63,L_SCR1
5007
5008 set ENDFLAG,L_SCR2
5009 set INT,L_SCR2
5010
5011 set ADJN,L_SCR3
5012
5013############################################
5014 global ssin
5015ssin:
5016 mov.l &0,ADJN(%a6) # yes; SET ADJN TO 0
5017 bra.b SINBGN
5018
5019############################################
5020 global scos
5021scos:
5022 mov.l &1,ADJN(%a6) # yes; SET ADJN TO 1
5023
5024############################################
5025SINBGN:
5026#--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
5027
5028 fmov.x (%a0),%fp0 # LOAD INPUT
5029 fmov.x %fp0,X(%a6) # save input at X
5030
5031# "COMPACTIFY" X
5032 mov.l (%a0),%d1 # put exp in hi word
5033 mov.w 4(%a0),%d1 # fetch hi(man)
5034 and.l &0x7FFFFFFF,%d1 # strip sign
5035
5036 cmpi.l %d1,&0x3FD78000 # is |X| >= 2**(-40)?
5037 bge.b SOK1 # no
5038 bra.w SINSM # yes; input is very small
5039
5040SOK1:
5041 cmp.l %d1,&0x4004BC7E # is |X| < 15 PI?
5042 blt.b SINMAIN # no
5043 bra.w SREDUCEX # yes; input is very large
5044
5045#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5046#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5047SINMAIN:
5048 fmov.x %fp0,%fp1
5049 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5050
5051 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5052
5053 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
5054
5055 mov.l INT(%a6),%d1 # make a copy of N
5056 asl.l &4,%d1 # N *= 16
5057 add.l %d1,%a1 # tbl_addr = a1 + (N*16)
5058
5059# A1 IS THE ADDRESS OF N*PIBY2
5060# ...WHICH IS IN TWO PIECES Y1 & Y2
5061 fsub.x (%a1)+,%fp0 # X-Y1
5062 fsub.s (%a1),%fp0 # fp0 = R = (X-Y1)-Y2
5063
5064SINCONT:
5065#--continuation from REDUCEX
5066
5067#--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
5068 mov.l INT(%a6),%d1
5069 add.l ADJN(%a6),%d1 # SEE IF D0 IS ODD OR EVEN
5070 ror.l &1,%d1 # D0 WAS ODD IFF D0 IS NEGATIVE
5071 cmp.l %d1,&0
5072 blt.w COSPOLY
5073
5074#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5075#--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
5076#--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
5077#--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
5078#--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
5079#--WHERE T=S*S.
5080#--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
5081#--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
5082SINPOLY:
5083 fmovm.x &0x0c,-(%sp) # save fp2/fp3
5084
5085 fmov.x %fp0,X(%a6) # X IS R
5086 fmul.x %fp0,%fp0 # FP0 IS S
5087
5088 fmov.d SINA7(%pc),%fp3
5089 fmov.d SINA6(%pc),%fp2
5090
5091 fmov.x %fp0,%fp1
5092 fmul.x %fp1,%fp1 # FP1 IS T
5093
5094 ror.l &1,%d1
5095 and.l &0x80000000,%d1
5096# ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5097 eor.l %d1,X(%a6) # X IS NOW R'= SGN*R
5098
5099 fmul.x %fp1,%fp3 # TA7
5100 fmul.x %fp1,%fp2 # TA6
5101
5102 fadd.d SINA5(%pc),%fp3 # A5+TA7
5103 fadd.d SINA4(%pc),%fp2 # A4+TA6
5104
5105 fmul.x %fp1,%fp3 # T(A5+TA7)
5106 fmul.x %fp1,%fp2 # T(A4+TA6)
5107
5108 fadd.d SINA3(%pc),%fp3 # A3+T(A5+TA7)
5109 fadd.x SINA2(%pc),%fp2 # A2+T(A4+TA6)
5110
5111 fmul.x %fp3,%fp1 # T(A3+T(A5+TA7))
5112
5113 fmul.x %fp0,%fp2 # S(A2+T(A4+TA6))
5114 fadd.x SINA1(%pc),%fp1 # A1+T(A3+T(A5+TA7))
5115 fmul.x X(%a6),%fp0 # R'*S
5116
5117 fadd.x %fp2,%fp1 # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
5118
5119 fmul.x %fp1,%fp0 # SIN(R')-R'
5120
5121 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
5122
5123 fmov.l %d0,%fpcr # restore users round mode,prec
5124 fadd.x X(%a6),%fp0 # last inst - possible exception set
5125 bra t_inx2
5126
5127#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5128#--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY
5129#--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
5130#--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
5131#--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
5132#--WHERE T=S*S.
5133#--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
5134#--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
5135#--AND IS THEREFORE STORED AS SINGLE PRECISION.
5136COSPOLY:
5137 fmovm.x &0x0c,-(%sp) # save fp2/fp3
5138
5139 fmul.x %fp0,%fp0 # FP0 IS S
5140
5141 fmov.d COSB8(%pc),%fp2
5142 fmov.d COSB7(%pc),%fp3
5143
5144 fmov.x %fp0,%fp1
5145 fmul.x %fp1,%fp1 # FP1 IS T
5146
5147 fmov.x %fp0,X(%a6) # X IS S
5148 ror.l &1,%d1
5149 and.l &0x80000000,%d1
5150# ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5151
5152 fmul.x %fp1,%fp2 # TB8
5153
5154 eor.l %d1,X(%a6) # X IS NOW S'= SGN*S
5155 and.l &0x80000000,%d1
5156
5157 fmul.x %fp1,%fp3 # TB7
5158
5159 or.l &0x3F800000,%d1 # D0 IS SGN IN SINGLE
5160 mov.l %d1,POSNEG1(%a6)
5161
5162 fadd.d COSB6(%pc),%fp2 # B6+TB8
5163 fadd.d COSB5(%pc),%fp3 # B5+TB7
5164
5165 fmul.x %fp1,%fp2 # T(B6+TB8)
5166 fmul.x %fp1,%fp3 # T(B5+TB7)
5167
5168 fadd.d COSB4(%pc),%fp2 # B4+T(B6+TB8)
5169 fadd.x COSB3(%pc),%fp3 # B3+T(B5+TB7)
5170
5171 fmul.x %fp1,%fp2 # T(B4+T(B6+TB8))
5172 fmul.x %fp3,%fp1 # T(B3+T(B5+TB7))
5173
5174 fadd.x COSB2(%pc),%fp2 # B2+T(B4+T(B6+TB8))
5175 fadd.s COSB1(%pc),%fp1 # B1+T(B3+T(B5+TB7))
5176
5177 fmul.x %fp2,%fp0 # S(B2+T(B4+T(B6+TB8)))
5178
5179 fadd.x %fp1,%fp0
5180
5181 fmul.x X(%a6),%fp0
5182
5183 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
5184
5185 fmov.l %d0,%fpcr # restore users round mode,prec
5186 fadd.s POSNEG1(%a6),%fp0 # last inst - possible exception set
5187 bra t_inx2
5188
5189##############################################
5190
5191# SINe: Big OR Small?
5192#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5193#--IF |X| < 2**(-40), RETURN X OR 1.
5194SINBORS:
5195 cmp.l %d1,&0x3FFF8000
5196 bgt.l SREDUCEX
5197
5198SINSM:
5199 mov.l ADJN(%a6),%d1
5200 cmp.l %d1,&0
5201 bgt.b COSTINY
5202
5203# here, the operation may underflow iff the precision is sgl or dbl.
5204# extended denorms are handled through another entry point.
5205SINTINY:
5206# mov.w &0x0000,XDCARE(%a6) # JUST IN CASE
5207
5208 fmov.l %d0,%fpcr # restore users round mode,prec
5209 mov.b &FMOV_OP,%d1 # last inst is MOVE
5210 fmov.x X(%a6),%fp0 # last inst - possible exception set
5211 bra t_catch
5212
5213COSTINY:
5214 fmov.s &0x3F800000,%fp0 # fp0 = 1.0
5215 fmov.l %d0,%fpcr # restore users round mode,prec
5216 fadd.s &0x80800000,%fp0 # last inst - possible exception set
5217 bra t_pinx2
5218
5219################################################
5220 global ssind
5221#--SIN(X) = X FOR DENORMALIZED X
5222ssind:
5223 bra t_extdnrm
5224
5225############################################
5226 global scosd
5227#--COS(X) = 1 FOR DENORMALIZED X
5228scosd:
5229 fmov.s &0x3F800000,%fp0 # fp0 = 1.0
5230 bra t_pinx2
5231
5232##################################################
5233
5234 global ssincos
5235ssincos:
5236#--SET ADJN TO 4
5237 mov.l &4,ADJN(%a6)
5238
5239 fmov.x (%a0),%fp0 # LOAD INPUT
5240 fmov.x %fp0,X(%a6)
5241
5242 mov.l (%a0),%d1
5243 mov.w 4(%a0),%d1
5244 and.l &0x7FFFFFFF,%d1 # COMPACTIFY X
5245
5246 cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
5247 bge.b SCOK1
5248 bra.w SCSM
5249
5250SCOK1:
5251 cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
5252 blt.b SCMAIN
5253 bra.w SREDUCEX
5254
5255
5256#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5257#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5258SCMAIN:
5259 fmov.x %fp0,%fp1
5260
5261 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5262
5263 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5264
5265 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
5266
5267 mov.l INT(%a6),%d1
5268 asl.l &4,%d1
5269 add.l %d1,%a1 # ADDRESS OF N*PIBY2, IN Y1, Y2
5270
5271 fsub.x (%a1)+,%fp0 # X-Y1
5272 fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
5273
5274SCCONT:
5275#--continuation point from REDUCEX
5276
5277 mov.l INT(%a6),%d1
5278 ror.l &1,%d1
5279 cmp.l %d1,&0 # D0 < 0 IFF N IS ODD
5280 bge.w NEVEN
5281
5282SNODD:
5283#--REGISTERS SAVED SO FAR: D0, A0, FP2.
5284 fmovm.x &0x04,-(%sp) # save fp2
5285
5286 fmov.x %fp0,RPRIME(%a6)
5287 fmul.x %fp0,%fp0 # FP0 IS S = R*R
5288 fmov.d SINA7(%pc),%fp1 # A7
5289 fmov.d COSB8(%pc),%fp2 # B8
5290 fmul.x %fp0,%fp1 # SA7
5291 fmul.x %fp0,%fp2 # SB8
5292
5293 mov.l %d2,-(%sp)
5294 mov.l %d1,%d2
5295 ror.l &1,%d2
5296 and.l &0x80000000,%d2
5297 eor.l %d1,%d2
5298 and.l &0x80000000,%d2
5299
5300 fadd.d SINA6(%pc),%fp1 # A6+SA7
5301 fadd.d COSB7(%pc),%fp2 # B7+SB8
5302
5303 fmul.x %fp0,%fp1 # S(A6+SA7)
5304 eor.l %d2,RPRIME(%a6)
5305 mov.l (%sp)+,%d2
5306 fmul.x %fp0,%fp2 # S(B7+SB8)
5307 ror.l &1,%d1
5308 and.l &0x80000000,%d1
5309 mov.l &0x3F800000,POSNEG1(%a6)
5310 eor.l %d1,POSNEG1(%a6)
5311
5312 fadd.d SINA5(%pc),%fp1 # A5+S(A6+SA7)
5313 fadd.d COSB6(%pc),%fp2 # B6+S(B7+SB8)
5314
5315 fmul.x %fp0,%fp1 # S(A5+S(A6+SA7))
5316 fmul.x %fp0,%fp2 # S(B6+S(B7+SB8))
5317 fmov.x %fp0,SPRIME(%a6)
5318
5319 fadd.d SINA4(%pc),%fp1 # A4+S(A5+S(A6+SA7))
5320 eor.l %d1,SPRIME(%a6)
5321 fadd.d COSB5(%pc),%fp2 # B5+S(B6+S(B7+SB8))
5322
5323 fmul.x %fp0,%fp1 # S(A4+...)
5324 fmul.x %fp0,%fp2 # S(B5+...)
5325
5326 fadd.d SINA3(%pc),%fp1 # A3+S(A4+...)
5327 fadd.d COSB4(%pc),%fp2 # B4+S(B5+...)
5328
5329 fmul.x %fp0,%fp1 # S(A3+...)
5330 fmul.x %fp0,%fp2 # S(B4+...)
5331
5332 fadd.x SINA2(%pc),%fp1 # A2+S(A3+...)
5333 fadd.x COSB3(%pc),%fp2 # B3+S(B4+...)
5334
5335 fmul.x %fp0,%fp1 # S(A2+...)
5336 fmul.x %fp0,%fp2 # S(B3+...)
5337
5338 fadd.x SINA1(%pc),%fp1 # A1+S(A2+...)
5339 fadd.x COSB2(%pc),%fp2 # B2+S(B3+...)
5340
5341 fmul.x %fp0,%fp1 # S(A1+...)
5342 fmul.x %fp2,%fp0 # S(B2+...)
5343
5344 fmul.x RPRIME(%a6),%fp1 # R'S(A1+...)
5345 fadd.s COSB1(%pc),%fp0 # B1+S(B2...)
5346 fmul.x SPRIME(%a6),%fp0 # S'(B1+S(B2+...))
5347
5348 fmovm.x (%sp)+,&0x20 # restore fp2
5349
5350 fmov.l %d0,%fpcr
5351 fadd.x RPRIME(%a6),%fp1 # COS(X)
5352 bsr sto_cos # store cosine result
5353 fadd.s POSNEG1(%a6),%fp0 # SIN(X)
5354 bra t_inx2
5355
5356NEVEN:
5357#--REGISTERS SAVED SO FAR: FP2.
5358 fmovm.x &0x04,-(%sp) # save fp2
5359
5360 fmov.x %fp0,RPRIME(%a6)
5361 fmul.x %fp0,%fp0 # FP0 IS S = R*R
5362
5363 fmov.d COSB8(%pc),%fp1 # B8
5364 fmov.d SINA7(%pc),%fp2 # A7
5365
5366 fmul.x %fp0,%fp1 # SB8
5367 fmov.x %fp0,SPRIME(%a6)
5368 fmul.x %fp0,%fp2 # SA7
5369
5370 ror.l &1,%d1
5371 and.l &0x80000000,%d1
5372
5373 fadd.d COSB7(%pc),%fp1 # B7+SB8
5374 fadd.d SINA6(%pc),%fp2 # A6+SA7
5375
5376 eor.l %d1,RPRIME(%a6)
5377 eor.l %d1,SPRIME(%a6)
5378
5379 fmul.x %fp0,%fp1 # S(B7+SB8)
5380
5381 or.l &0x3F800000,%d1
5382 mov.l %d1,POSNEG1(%a6)
5383
5384 fmul.x %fp0,%fp2 # S(A6+SA7)
5385
5386 fadd.d COSB6(%pc),%fp1 # B6+S(B7+SB8)
5387 fadd.d SINA5(%pc),%fp2 # A5+S(A6+SA7)
5388
5389 fmul.x %fp0,%fp1 # S(B6+S(B7+SB8))
5390 fmul.x %fp0,%fp2 # S(A5+S(A6+SA7))
5391
5392 fadd.d COSB5(%pc),%fp1 # B5+S(B6+S(B7+SB8))
5393 fadd.d SINA4(%pc),%fp2 # A4+S(A5+S(A6+SA7))
5394
5395 fmul.x %fp0,%fp1 # S(B5+...)
5396 fmul.x %fp0,%fp2 # S(A4+...)
5397
5398 fadd.d COSB4(%pc),%fp1 # B4+S(B5+...)
5399 fadd.d SINA3(%pc),%fp2 # A3+S(A4+...)
5400
5401 fmul.x %fp0,%fp1 # S(B4+...)
5402 fmul.x %fp0,%fp2 # S(A3+...)
5403
5404 fadd.x COSB3(%pc),%fp1 # B3+S(B4+...)
5405 fadd.x SINA2(%pc),%fp2 # A2+S(A3+...)
5406
5407 fmul.x %fp0,%fp1 # S(B3+...)
5408 fmul.x %fp0,%fp2 # S(A2+...)
5409
5410 fadd.x COSB2(%pc),%fp1 # B2+S(B3+...)
5411 fadd.x SINA1(%pc),%fp2 # A1+S(A2+...)
5412
5413 fmul.x %fp0,%fp1 # S(B2+...)
5414 fmul.x %fp2,%fp0 # s(a1+...)
5415
5416
5417 fadd.s COSB1(%pc),%fp1 # B1+S(B2...)
5418 fmul.x RPRIME(%a6),%fp0 # R'S(A1+...)
5419 fmul.x SPRIME(%a6),%fp1 # S'(B1+S(B2+...))
5420
5421 fmovm.x (%sp)+,&0x20 # restore fp2
5422
5423 fmov.l %d0,%fpcr
5424 fadd.s POSNEG1(%a6),%fp1 # COS(X)
5425 bsr sto_cos # store cosine result
5426 fadd.x RPRIME(%a6),%fp0 # SIN(X)
5427 bra t_inx2
5428
5429################################################
5430
5431SCBORS:
5432 cmp.l %d1,&0x3FFF8000
5433 bgt.w SREDUCEX
5434
5435################################################
5436
5437SCSM:
5438# mov.w &0x0000,XDCARE(%a6)
5439 fmov.s &0x3F800000,%fp1
5440
5441 fmov.l %d0,%fpcr
5442 fsub.s &0x00800000,%fp1
5443 bsr sto_cos # store cosine result
5444 fmov.l %fpcr,%d0 # d0 must have fpcr,too
5445 mov.b &FMOV_OP,%d1 # last inst is MOVE
5446 fmov.x X(%a6),%fp0
5447 bra t_catch
5448
5449##############################################
5450
5451 global ssincosd
5452#--SIN AND COS OF X FOR DENORMALIZED X
5453ssincosd:
5454 mov.l %d0,-(%sp) # save d0
5455 fmov.s &0x3F800000,%fp1
5456 bsr sto_cos # store cosine result
5457 mov.l (%sp)+,%d0 # restore d0
5458 bra t_extdnrm
5459
5460############################################
5461
5462#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5463#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5464#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5465SREDUCEX:
5466 fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
5467 mov.l %d2,-(%sp) # save d2
5468 fmov.s &0x00000000,%fp1 # fp1 = 0
5469
5470#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5471#--there is a danger of unwanted overflow in first LOOP iteration. In this
5472#--case, reduce argument by one remainder step to make subsequent reduction
5473#--safe.
5474 cmp.l %d1,&0x7ffeffff # is arg dangerously large?
5475 bne.b SLOOP # no
5476
5477# yes; create 2**16383*PI/2
5478 mov.w &0x7ffe,FP_SCR0_EX(%a6)
5479 mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
5480 clr.l FP_SCR0_LO(%a6)
5481
5482# create low half of 2**16383*PI/2 at FP_SCR1
5483 mov.w &0x7fdc,FP_SCR1_EX(%a6)
5484 mov.l &0x85a308d3,FP_SCR1_HI(%a6)
5485 clr.l FP_SCR1_LO(%a6)
5486
5487 ftest.x %fp0 # test sign of argument
5488 fblt.w sred_neg
5489
5490 or.b &0x80,FP_SCR0_EX(%a6) # positive arg
5491 or.b &0x80,FP_SCR1_EX(%a6)
5492sred_neg:
5493 fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
5494 fmov.x %fp0,%fp1 # save high result in fp1
5495 fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
5496 fsub.x %fp0,%fp1 # determine low component of result
5497 fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
5498
5499#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5500#--integer quotient will be stored in N
5501#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5502SLOOP:
5503 fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
5504 mov.w INARG(%a6),%d1
5505 mov.l %d1,%a1 # save a copy of D0
5506 and.l &0x00007FFF,%d1
5507 sub.l &0x00003FFF,%d1 # d0 = K
5508 cmp.l %d1,&28
5509 ble.b SLASTLOOP
5510SCONTLOOP:
5511 sub.l &27,%d1 # d0 = L := K-27
5512 mov.b &0,ENDFLAG(%a6)
5513 bra.b SWORK
5514SLASTLOOP:
5515 clr.l %d1 # d0 = L := 0
5516 mov.b &1,ENDFLAG(%a6)
5517
5518SWORK:
5519#--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
5520#--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5521
5522#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5523#--2**L * (PIby2_1), 2**L * (PIby2_2)
5524
5525 mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
5526 sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
5527
5528 mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
5529 mov.l &0x4E44152A,FP_SCR0_LO(%a6)
5530 mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
5531
5532 fmov.x %fp0,%fp2
5533 fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
5534
5535#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5536#--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
5537#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5538#--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
5539#--US THE DESIRED VALUE IN FLOATING POINT.
5540 mov.l %a1,%d2
5541 swap %d2
5542 and.l &0x80000000,%d2
5543 or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
5544 mov.l %d2,TWOTO63(%a6)
5545 fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
5546 fsub.s TWOTO63(%a6),%fp2 # fp2 = N
5547# fint.x %fp2
5548
5549#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5550 mov.l %d1,%d2 # d2 = L
5551
5552 add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
5553 mov.w %d2,FP_SCR0_EX(%a6)
5554 mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
5555 clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
5556
5557 add.l &0x00003FDD,%d1
5558 mov.w %d1,FP_SCR1_EX(%a6)
5559 mov.l &0x85A308D3,FP_SCR1_HI(%a6)
5560 clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
5561
5562 mov.b ENDFLAG(%a6),%d1
5563
5564#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5565#--P2 = 2**(L) * Piby2_2
5566 fmov.x %fp2,%fp4 # fp4 = N
5567 fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
5568 fmov.x %fp2,%fp5 # fp5 = N
5569 fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
5570 fmov.x %fp4,%fp3 # fp3 = W = N*P1
5571
5572#--we want P+p = W+w but |p| <= half ulp of P
5573#--Then, we need to compute A := R-P and a := r-p
5574 fadd.x %fp5,%fp3 # fp3 = P
5575 fsub.x %fp3,%fp4 # fp4 = W-P
5576
5577 fsub.x %fp3,%fp0 # fp0 = A := R - P
5578 fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
5579
5580 fmov.x %fp0,%fp3 # fp3 = A
5581 fsub.x %fp4,%fp1 # fp1 = a := r - p
5582
5583#--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
5584#--|r| <= half ulp of R.
5585 fadd.x %fp1,%fp0 # fp0 = R := A+a
5586#--No need to calculate r if this is the last loop
5587 cmp.b %d1,&0
5588 bgt.w SRESTORE
5589
5590#--Need to calculate r
5591 fsub.x %fp0,%fp3 # fp3 = A-R
5592 fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
5593 bra.w SLOOP
5594
5595SRESTORE:
5596 fmov.l %fp2,INT(%a6)
5597 mov.l (%sp)+,%d2 # restore d2
5598 fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
5599
5600 mov.l ADJN(%a6),%d1
5601 cmp.l %d1,&4
5602
5603 blt.w SINCONT
5604 bra.w SCCONT
5605
5606#########################################################################
5607# stan(): computes the tangent of a normalized input #
5608# stand(): computes the tangent of a denormalized input #
5609# #
5610# INPUT *************************************************************** #
5611# a0 = pointer to extended precision input #
5612# d0 = round precision,mode #
5613# #
5614# OUTPUT ************************************************************** #
5615# fp0 = tan(X) #
5616# #
5617# ACCURACY and MONOTONICITY ******************************************* #
5618# The returned result is within 3 ulp in 64 significant bit, i.e. #
5619# within 0.5001 ulp to 53 bits if the result is subsequently #
5620# rounded to double precision. The result is provably monotonic #
5621# in double precision. #
5622# #
5623# ALGORITHM *********************************************************** #
5624# #
5625# 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
5626# #
5627# 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
5628# k = N mod 2, so in particular, k = 0 or 1. #
5629# #
5630# 3. If k is odd, go to 5. #
5631# #
5632# 4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a #
5633# rational function U/V where #
5634# U = r + r*s*(P1 + s*(P2 + s*P3)), and #
5635# V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r. #
5636# Exit. #
5637# #
5638# 4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
5639# a rational function U/V where #
5640# U = r + r*s*(P1 + s*(P2 + s*P3)), and #
5641# V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r, #
5642# -Cot(r) = -V/U. Exit. #
5643# #
5644# 6. If |X| > 1, go to 8. #
5645# #
5646# 7. (|X|<2**(-40)) Tan(X) = X. Exit. #
5647# #
5648# 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back #
5649# to 2. #
5650# #
5651#########################################################################
5652
5653TANQ4:
5654 long 0x3EA0B759,0xF50F8688
5655TANP3:
5656 long 0xBEF2BAA5,0xA8924F04
5657
5658TANQ3:
5659 long 0xBF346F59,0xB39BA65F,0x00000000,0x00000000
5660
5661TANP2:
5662 long 0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
5663
5664TANQ2:
5665 long 0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
5666
5667TANP1:
5668 long 0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
5669
5670TANQ1:
5671 long 0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
5672
5673INVTWOPI:
5674 long 0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
5675
5676TWOPI1:
5677 long 0x40010000,0xC90FDAA2,0x00000000,0x00000000
5678TWOPI2:
5679 long 0x3FDF0000,0x85A308D4,0x00000000,0x00000000
5680
5681#--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
5682#--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
5683#--MOST 69 BITS LONG.
5684# global PITBL
5685PITBL:
5686 long 0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
5687 long 0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
5688 long 0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
5689 long 0xC0040000,0xB6365E22,0xEE46F000,0x21480000
5690 long 0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
5691 long 0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
5692 long 0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
5693 long 0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
5694 long 0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
5695 long 0xC0040000,0x90836524,0x88034B96,0x20B00000
5696 long 0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
5697 long 0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
5698 long 0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
5699 long 0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
5700 long 0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
5701 long 0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
5702 long 0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
5703 long 0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
5704 long 0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
5705 long 0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
5706 long 0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
5707 long 0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
5708 long 0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
5709 long 0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
5710 long 0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
5711 long 0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
5712 long 0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
5713 long 0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
5714 long 0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
5715 long 0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
5716 long 0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
5717 long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
5718 long 0x00000000,0x00000000,0x00000000,0x00000000
5719 long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
5720 long 0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
5721 long 0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
5722 long 0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
5723 long 0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
5724 long 0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
5725 long 0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
5726 long 0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
5727 long 0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
5728 long 0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
5729 long 0x40030000,0x8A3AE64F,0x76F80584,0x21080000
5730 long 0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
5731 long 0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
5732 long 0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
5733 long 0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
5734 long 0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
5735 long 0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
5736 long 0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
5737 long 0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
5738 long 0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
5739 long 0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
5740 long 0x40040000,0x8A3AE64F,0x76F80584,0x21880000
5741 long 0x40040000,0x90836524,0x88034B96,0xA0B00000
5742 long 0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
5743 long 0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
5744 long 0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
5745 long 0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
5746 long 0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
5747 long 0x40040000,0xB6365E22,0xEE46F000,0xA1480000
5748 long 0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
5749 long 0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
5750 long 0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
5751
5752 set INARG,FP_SCR0
5753
5754 set TWOTO63,L_SCR1
5755 set INT,L_SCR1
5756 set ENDFLAG,L_SCR2
5757
5758 global stan
5759stan:
5760 fmov.x (%a0),%fp0 # LOAD INPUT
5761
5762 mov.l (%a0),%d1
5763 mov.w 4(%a0),%d1
5764 and.l &0x7FFFFFFF,%d1
5765
5766 cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
5767 bge.b TANOK1
5768 bra.w TANSM
5769TANOK1:
5770 cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
5771 blt.b TANMAIN
5772 bra.w REDUCEX
5773
5774TANMAIN:
5775#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5776#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5777 fmov.x %fp0,%fp1
5778 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5779
5780 lea.l PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5781
5782 fmov.l %fp1,%d1 # CONVERT TO INTEGER
5783
5784 asl.l &4,%d1
5785 add.l %d1,%a1 # ADDRESS N*PIBY2 IN Y1, Y2
5786
5787 fsub.x (%a1)+,%fp0 # X-Y1
5788
5789 fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
5790
5791 ror.l &5,%d1
5792 and.l &0x80000000,%d1 # D0 WAS ODD IFF D0 < 0
5793
5794TANCONT:
5795 fmovm.x &0x0c,-(%sp) # save fp2,fp3
5796
5797 cmp.l %d1,&0
5798 blt.w NODD
5799
5800 fmov.x %fp0,%fp1
5801 fmul.x %fp1,%fp1 # S = R*R
5802
5803 fmov.d TANQ4(%pc),%fp3
5804 fmov.d TANP3(%pc),%fp2
5805
5806 fmul.x %fp1,%fp3 # SQ4
5807 fmul.x %fp1,%fp2 # SP3
5808
5809 fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
5810 fadd.x TANP2(%pc),%fp2 # P2+SP3
5811
5812 fmul.x %fp1,%fp3 # S(Q3+SQ4)
5813 fmul.x %fp1,%fp2 # S(P2+SP3)
5814
5815 fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
5816 fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
5817
5818 fmul.x %fp1,%fp3 # S(Q2+S(Q3+SQ4))
5819 fmul.x %fp1,%fp2 # S(P1+S(P2+SP3))
5820
5821 fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
5822 fmul.x %fp0,%fp2 # RS(P1+S(P2+SP3))
5823
5824 fmul.x %fp3,%fp1 # S(Q1+S(Q2+S(Q3+SQ4)))
5825
5826 fadd.x %fp2,%fp0 # R+RS(P1+S(P2+SP3))
5827
5828 fadd.s &0x3F800000,%fp1 # 1+S(Q1+...)
5829
5830 fmovm.x (%sp)+,&0x30 # restore fp2,fp3
5831
5832 fmov.l %d0,%fpcr # restore users round mode,prec
5833 fdiv.x %fp1,%fp0 # last inst - possible exception set
5834 bra t_inx2
5835
5836NODD:
5837 fmov.x %fp0,%fp1
5838 fmul.x %fp0,%fp0 # S = R*R
5839
5840 fmov.d TANQ4(%pc),%fp3
5841 fmov.d TANP3(%pc),%fp2
5842
5843 fmul.x %fp0,%fp3 # SQ4
5844 fmul.x %fp0,%fp2 # SP3
5845
5846 fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
5847 fadd.x TANP2(%pc),%fp2 # P2+SP3
5848
5849 fmul.x %fp0,%fp3 # S(Q3+SQ4)
5850 fmul.x %fp0,%fp2 # S(P2+SP3)
5851
5852 fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
5853 fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
5854
5855 fmul.x %fp0,%fp3 # S(Q2+S(Q3+SQ4))
5856 fmul.x %fp0,%fp2 # S(P1+S(P2+SP3))
5857
5858 fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
5859 fmul.x %fp1,%fp2 # RS(P1+S(P2+SP3))
5860
5861 fmul.x %fp3,%fp0 # S(Q1+S(Q2+S(Q3+SQ4)))
5862
5863 fadd.x %fp2,%fp1 # R+RS(P1+S(P2+SP3))
5864 fadd.s &0x3F800000,%fp0 # 1+S(Q1+...)
5865
5866 fmovm.x (%sp)+,&0x30 # restore fp2,fp3
5867
5868 fmov.x %fp1,-(%sp)
5869 eor.l &0x80000000,(%sp)
5870
5871 fmov.l %d0,%fpcr # restore users round mode,prec
5872 fdiv.x (%sp)+,%fp0 # last inst - possible exception set
5873 bra t_inx2
5874
5875TANBORS:
5876#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5877#--IF |X| < 2**(-40), RETURN X OR 1.
5878 cmp.l %d1,&0x3FFF8000
5879 bgt.b REDUCEX
5880
5881TANSM:
5882 fmov.x %fp0,-(%sp)
5883 fmov.l %d0,%fpcr # restore users round mode,prec
5884 mov.b &FMOV_OP,%d1 # last inst is MOVE
5885 fmov.x (%sp)+,%fp0 # last inst - posibble exception set
5886 bra t_catch
5887
5888 global stand
5889#--TAN(X) = X FOR DENORMALIZED X
5890stand:
5891 bra t_extdnrm
5892
5893#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5894#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5895#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5896REDUCEX:
5897 fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
5898 mov.l %d2,-(%sp) # save d2
5899 fmov.s &0x00000000,%fp1 # fp1 = 0
5900
5901#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5902#--there is a danger of unwanted overflow in first LOOP iteration. In this
5903#--case, reduce argument by one remainder step to make subsequent reduction
5904#--safe.
5905 cmp.l %d1,&0x7ffeffff # is arg dangerously large?
5906 bne.b LOOP # no
5907
5908# yes; create 2**16383*PI/2
5909 mov.w &0x7ffe,FP_SCR0_EX(%a6)
5910 mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
5911 clr.l FP_SCR0_LO(%a6)
5912
5913# create low half of 2**16383*PI/2 at FP_SCR1
5914 mov.w &0x7fdc,FP_SCR1_EX(%a6)
5915 mov.l &0x85a308d3,FP_SCR1_HI(%a6)
5916 clr.l FP_SCR1_LO(%a6)
5917
5918 ftest.x %fp0 # test sign of argument
5919 fblt.w red_neg
5920
5921 or.b &0x80,FP_SCR0_EX(%a6) # positive arg
5922 or.b &0x80,FP_SCR1_EX(%a6)
5923red_neg:
5924 fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
5925 fmov.x %fp0,%fp1 # save high result in fp1
5926 fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
5927 fsub.x %fp0,%fp1 # determine low component of result
5928 fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
5929
5930#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5931#--integer quotient will be stored in N
5932#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5933LOOP:
5934 fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
5935 mov.w INARG(%a6),%d1
5936 mov.l %d1,%a1 # save a copy of D0
5937 and.l &0x00007FFF,%d1
5938 sub.l &0x00003FFF,%d1 # d0 = K
5939 cmp.l %d1,&28
5940 ble.b LASTLOOP
5941CONTLOOP:
5942 sub.l &27,%d1 # d0 = L := K-27
5943 mov.b &0,ENDFLAG(%a6)
5944 bra.b WORK
5945LASTLOOP:
5946 clr.l %d1 # d0 = L := 0
5947 mov.b &1,ENDFLAG(%a6)
5948
5949WORK:
5950#--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
5951#--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5952
5953#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5954#--2**L * (PIby2_1), 2**L * (PIby2_2)
5955
5956 mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
5957 sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
5958
5959 mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
5960 mov.l &0x4E44152A,FP_SCR0_LO(%a6)
5961 mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
5962
5963 fmov.x %fp0,%fp2
5964 fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
5965
5966#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5967#--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
5968#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5969#--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
5970#--US THE DESIRED VALUE IN FLOATING POINT.
5971 mov.l %a1,%d2
5972 swap %d2
5973 and.l &0x80000000,%d2
5974 or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
5975 mov.l %d2,TWOTO63(%a6)
5976 fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
5977 fsub.s TWOTO63(%a6),%fp2 # fp2 = N
5978# fintrz.x %fp2,%fp2
5979
5980#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5981 mov.l %d1,%d2 # d2 = L
5982
5983 add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
5984 mov.w %d2,FP_SCR0_EX(%a6)
5985 mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
5986 clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
5987
5988 add.l &0x00003FDD,%d1
5989 mov.w %d1,FP_SCR1_EX(%a6)
5990 mov.l &0x85A308D3,FP_SCR1_HI(%a6)
5991 clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
5992
5993 mov.b ENDFLAG(%a6),%d1
5994
5995#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5996#--P2 = 2**(L) * Piby2_2
5997 fmov.x %fp2,%fp4 # fp4 = N
5998 fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
5999 fmov.x %fp2,%fp5 # fp5 = N
6000 fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
6001 fmov.x %fp4,%fp3 # fp3 = W = N*P1
6002
6003#--we want P+p = W+w but |p| <= half ulp of P
6004#--Then, we need to compute A := R-P and a := r-p
6005 fadd.x %fp5,%fp3 # fp3 = P
6006 fsub.x %fp3,%fp4 # fp4 = W-P
6007
6008 fsub.x %fp3,%fp0 # fp0 = A := R - P
6009 fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
6010
6011 fmov.x %fp0,%fp3 # fp3 = A
6012 fsub.x %fp4,%fp1 # fp1 = a := r - p
6013
6014#--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
6015#--|r| <= half ulp of R.
6016 fadd.x %fp1,%fp0 # fp0 = R := A+a
6017#--No need to calculate r if this is the last loop
6018 cmp.b %d1,&0
6019 bgt.w RESTORE
6020
6021#--Need to calculate r
6022 fsub.x %fp0,%fp3 # fp3 = A-R
6023 fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
6024 bra.w LOOP
6025
6026RESTORE:
6027 fmov.l %fp2,INT(%a6)
6028 mov.l (%sp)+,%d2 # restore d2
6029 fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
6030
6031 mov.l INT(%a6),%d1
6032 ror.l &1,%d1
6033
6034 bra.w TANCONT
6035
6036#########################################################################
6037# satan(): computes the arctangent of a normalized number #
6038# satand(): computes the arctangent of a denormalized number #
6039# #
6040# INPUT *************************************************************** #
6041# a0 = pointer to extended precision input #
6042# d0 = round precision,mode #
6043# #
6044# OUTPUT ************************************************************** #
6045# fp0 = arctan(X) #
6046# #
6047# ACCURACY and MONOTONICITY ******************************************* #
6048# The returned result is within 2 ulps in 64 significant bit, #
6049# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6050# rounded to double precision. The result is provably monotonic #
6051# in double precision. #
6052# #
6053# ALGORITHM *********************************************************** #
6054# Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5. #
6055# #
6056# Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x. #
6057# Note that k = -4, -3,..., or 3. #
6058# Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5 #
6059# significant bits of X with a bit-1 attached at the 6-th #
6060# bit position. Define u to be u = (X-F) / (1 + X*F). #
6061# #
6062# Step 3. Approximate arctan(u) by a polynomial poly. #
6063# #
6064# Step 4. Return arctan(F) + poly, arctan(F) is fetched from a #
6065# table of values calculated beforehand. Exit. #
6066# #
6067# Step 5. If |X| >= 16, go to Step 7. #
6068# #
6069# Step 6. Approximate arctan(X) by an odd polynomial in X. Exit. #
6070# #
6071# Step 7. Define X' = -1/X. Approximate arctan(X') by an odd #
6072# polynomial in X'. #
6073# Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit. #
6074# #
6075#########################################################################
6076
6077ATANA3: long 0xBFF6687E,0x314987D8
6078ATANA2: long 0x4002AC69,0x34A26DB3
6079ATANA1: long 0xBFC2476F,0x4E1DA28E
6080
6081ATANB6: long 0x3FB34444,0x7F876989
6082ATANB5: long 0xBFB744EE,0x7FAF45DB
6083ATANB4: long 0x3FBC71C6,0x46940220
6084ATANB3: long 0xBFC24924,0x921872F9
6085ATANB2: long 0x3FC99999,0x99998FA9
6086ATANB1: long 0xBFD55555,0x55555555
6087
6088ATANC5: long 0xBFB70BF3,0x98539E6A
6089ATANC4: long 0x3FBC7187,0x962D1D7D
6090ATANC3: long 0xBFC24924,0x827107B8
6091ATANC2: long 0x3FC99999,0x9996263E
6092ATANC1: long 0xBFD55555,0x55555536
6093
6094PPIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
6095NPIBY2: long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
6096
6097PTINY: long 0x00010000,0x80000000,0x00000000,0x00000000
6098NTINY: long 0x80010000,0x80000000,0x00000000,0x00000000
6099
6100ATANTBL:
6101 long 0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
6102 long 0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
6103 long 0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
6104 long 0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
6105 long 0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
6106 long 0x3FFB0000,0xAB98E943,0x62765619,0x00000000
6107 long 0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
6108 long 0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
6109 long 0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
6110 long 0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
6111 long 0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
6112 long 0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
6113 long 0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
6114 long 0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
6115 long 0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
6116 long 0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
6117 long 0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
6118 long 0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
6119 long 0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
6120 long 0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
6121 long 0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
6122 long 0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
6123 long 0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
6124 long 0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
6125 long 0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
6126 long 0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
6127 long 0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
6128 long 0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
6129 long 0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
6130 long 0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
6131 long 0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
6132 long 0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
6133 long 0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
6134 long 0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
6135 long 0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
6136 long 0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
6137 long 0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
6138 long 0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
6139 long 0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
6140 long 0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
6141 long 0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
6142 long 0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
6143 long 0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
6144 long 0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
6145 long 0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
6146 long 0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
6147 long 0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
6148 long 0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
6149 long 0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
6150 long 0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
6151 long 0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
6152 long 0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
6153 long 0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
6154 long 0x3FFE0000,0x97731420,0x365E538C,0x00000000
6155 long 0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
6156 long 0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
6157 long 0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
6158 long 0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
6159 long 0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
6160 long 0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
6161 long 0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
6162 long 0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
6163 long 0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
6164 long 0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
6165 long 0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
6166 long 0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
6167 long 0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
6168 long 0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
6169 long 0x3FFE0000,0xE8771129,0xC4353259,0x00000000
6170 long 0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
6171 long 0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
6172 long 0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
6173 long 0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
6174 long 0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
6175 long 0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
6176 long 0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
6177 long 0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
6178 long 0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
6179 long 0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
6180 long 0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
6181 long 0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
6182 long 0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
6183 long 0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
6184 long 0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
6185 long 0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
6186 long 0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
6187 long 0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
6188 long 0x3FFF0000,0x9F100575,0x006CC571,0x00000000
6189 long 0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
6190 long 0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
6191 long 0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
6192 long 0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
6193 long 0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
6194 long 0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
6195 long 0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
6196 long 0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
6197 long 0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
6198 long 0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
6199 long 0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
6200 long 0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
6201 long 0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
6202 long 0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
6203 long 0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
6204 long 0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
6205 long 0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
6206 long 0x3FFF0000,0xB525529D,0x562246BD,0x00000000
6207 long 0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
6208 long 0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
6209 long 0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
6210 long 0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
6211 long 0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
6212 long 0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
6213 long 0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
6214 long 0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
6215 long 0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
6216 long 0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
6217 long 0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
6218 long 0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
6219 long 0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
6220 long 0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
6221 long 0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
6222 long 0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
6223 long 0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
6224 long 0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
6225 long 0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
6226 long 0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
6227 long 0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
6228 long 0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
6229
6230 set X,FP_SCR0
6231 set XDCARE,X+2
6232 set XFRAC,X+4
6233 set XFRACLO,X+8
6234
6235 set ATANF,FP_SCR1
6236 set ATANFHI,ATANF+4
6237 set ATANFLO,ATANF+8
6238
6239 global satan
6240#--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
6241satan:
6242 fmov.x (%a0),%fp0 # LOAD INPUT
6243
6244 mov.l (%a0),%d1
6245 mov.w 4(%a0),%d1
6246 fmov.x %fp0,X(%a6)
6247 and.l &0x7FFFFFFF,%d1
6248
6249 cmp.l %d1,&0x3FFB8000 # |X| >= 1/16?
6250 bge.b ATANOK1
6251 bra.w ATANSM
6252
6253ATANOK1:
6254 cmp.l %d1,&0x4002FFFF # |X| < 16 ?
6255 ble.b ATANMAIN
6256 bra.w ATANBIG
6257
6258#--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
6259#--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
6260#--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
6261#--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
6262#--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
6263#--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
6264#--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
6265#--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
6266#--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
6267#--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
6268#--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
6269#--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
6270#--WILL INVOLVE A VERY LONG POLYNOMIAL.
6271
6272#--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
6273#--WE CHOSE F TO BE +-2^K * 1.BBBB1
6274#--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
6275#--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
6276#--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
6277#-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
6278
6279ATANMAIN:
6280
6281 and.l &0xF8000000,XFRAC(%a6) # FIRST 5 BITS
6282 or.l &0x04000000,XFRAC(%a6) # SET 6-TH BIT TO 1
6283 mov.l &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
6284
6285 fmov.x %fp0,%fp1 # FP1 IS X
6286 fmul.x X(%a6),%fp1 # FP1 IS X*F, NOTE THAT X*F > 0
6287 fsub.x X(%a6),%fp0 # FP0 IS X-F
6288 fadd.s &0x3F800000,%fp1 # FP1 IS 1 + X*F
6289 fdiv.x %fp1,%fp0 # FP0 IS U = (X-F)/(1+X*F)
6290
6291#--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
6292#--CREATE ATAN(F) AND STORE IT IN ATANF, AND
6293#--SAVE REGISTERS FP2.
6294
6295 mov.l %d2,-(%sp) # SAVE d2 TEMPORARILY
6296 mov.l %d1,%d2 # THE EXP AND 16 BITS OF X
6297 and.l &0x00007800,%d1 # 4 VARYING BITS OF F'S FRACTION
6298 and.l &0x7FFF0000,%d2 # EXPONENT OF F
6299 sub.l &0x3FFB0000,%d2 # K+4
6300 asr.l &1,%d2
6301 add.l %d2,%d1 # THE 7 BITS IDENTIFYING F
6302 asr.l &7,%d1 # INDEX INTO TBL OF ATAN(|F|)
6303 lea ATANTBL(%pc),%a1
6304 add.l %d1,%a1 # ADDRESS OF ATAN(|F|)
6305 mov.l (%a1)+,ATANF(%a6)
6306 mov.l (%a1)+,ATANFHI(%a6)
6307 mov.l (%a1)+,ATANFLO(%a6) # ATANF IS NOW ATAN(|F|)
6308 mov.l X(%a6),%d1 # LOAD SIGN AND EXPO. AGAIN
6309 and.l &0x80000000,%d1 # SIGN(F)
6310 or.l %d1,ATANF(%a6) # ATANF IS NOW SIGN(F)*ATAN(|F|)
6311 mov.l (%sp)+,%d2 # RESTORE d2
6312
6313#--THAT'S ALL I HAVE TO DO FOR NOW,
6314#--BUT ALAS, THE DIVIDE IS STILL CRANKING!
6315
6316#--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
6317#--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
6318#--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
6319#--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
6320#--WHAT WE HAVE HERE IS MERELY A1 = A3, A2 = A1/A3, A3 = A2/A3.
6321#--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
6322#--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
6323
6324 fmovm.x &0x04,-(%sp) # save fp2
6325
6326 fmov.x %fp0,%fp1
6327 fmul.x %fp1,%fp1
6328 fmov.d ATANA3(%pc),%fp2
6329 fadd.x %fp1,%fp2 # A3+V
6330 fmul.x %fp1,%fp2 # V*(A3+V)
6331 fmul.x %fp0,%fp1 # U*V
6332 fadd.d ATANA2(%pc),%fp2 # A2+V*(A3+V)
6333 fmul.d ATANA1(%pc),%fp1 # A1*U*V
6334 fmul.x %fp2,%fp1 # A1*U*V*(A2+V*(A3+V))
6335 fadd.x %fp1,%fp0 # ATAN(U), FP1 RELEASED
6336
6337 fmovm.x (%sp)+,&0x20 # restore fp2
6338
6339 fmov.l %d0,%fpcr # restore users rnd mode,prec
6340 fadd.x ATANF(%a6),%fp0 # ATAN(X)
6341 bra t_inx2
6342
6343ATANBORS:
6344#--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
6345#--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
6346 cmp.l %d1,&0x3FFF8000
6347 bgt.w ATANBIG # I.E. |X| >= 16
6348
6349ATANSM:
6350#--|X| <= 1/16
6351#--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
6352#--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
6353#--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
6354#--WHERE Y = X*X, AND Z = Y*Y.
6355
6356 cmp.l %d1,&0x3FD78000
6357 blt.w ATANTINY
6358
6359#--COMPUTE POLYNOMIAL
6360 fmovm.x &0x0c,-(%sp) # save fp2/fp3
6361
6362 fmul.x %fp0,%fp0 # FPO IS Y = X*X
6363
6364 fmov.x %fp0,%fp1
6365 fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
6366
6367 fmov.d ATANB6(%pc),%fp2
6368 fmov.d ATANB5(%pc),%fp3
6369
6370 fmul.x %fp1,%fp2 # Z*B6
6371 fmul.x %fp1,%fp3 # Z*B5
6372
6373 fadd.d ATANB4(%pc),%fp2 # B4+Z*B6
6374 fadd.d ATANB3(%pc),%fp3 # B3+Z*B5
6375
6376 fmul.x %fp1,%fp2 # Z*(B4+Z*B6)
6377 fmul.x %fp3,%fp1 # Z*(B3+Z*B5)
6378
6379 fadd.d ATANB2(%pc),%fp2 # B2+Z*(B4+Z*B6)
6380 fadd.d ATANB1(%pc),%fp1 # B1+Z*(B3+Z*B5)
6381
6382 fmul.x %fp0,%fp2 # Y*(B2+Z*(B4+Z*B6))
6383 fmul.x X(%a6),%fp0 # X*Y
6384
6385 fadd.x %fp2,%fp1 # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
6386
6387 fmul.x %fp1,%fp0 # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
6388
6389 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
6390
6391 fmov.l %d0,%fpcr # restore users rnd mode,prec
6392 fadd.x X(%a6),%fp0
6393 bra t_inx2
6394
6395ATANTINY:
6396#--|X| < 2^(-40), ATAN(X) = X
6397
6398 fmov.l %d0,%fpcr # restore users rnd mode,prec
6399 mov.b &FMOV_OP,%d1 # last inst is MOVE
6400 fmov.x X(%a6),%fp0 # last inst - possible exception set
6401
6402 bra t_catch
6403
6404ATANBIG:
6405#--IF |X| > 2^(100), RETURN SIGN(X)*(PI/2 - TINY). OTHERWISE,
6406#--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
6407 cmp.l %d1,&0x40638000
6408 bgt.w ATANHUGE
6409
6410#--APPROXIMATE ATAN(-1/X) BY
6411#--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
6412#--THIS CAN BE RE-WRITTEN AS
6413#--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
6414
6415 fmovm.x &0x0c,-(%sp) # save fp2/fp3
6416
6417 fmov.s &0xBF800000,%fp1 # LOAD -1
6418 fdiv.x %fp0,%fp1 # FP1 IS -1/X
6419
6420#--DIVIDE IS STILL CRANKING
6421
6422 fmov.x %fp1,%fp0 # FP0 IS X'
6423 fmul.x %fp0,%fp0 # FP0 IS Y = X'*X'
6424 fmov.x %fp1,X(%a6) # X IS REALLY X'
6425
6426 fmov.x %fp0,%fp1
6427 fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
6428
6429 fmov.d ATANC5(%pc),%fp3
6430 fmov.d ATANC4(%pc),%fp2
6431
6432 fmul.x %fp1,%fp3 # Z*C5
6433 fmul.x %fp1,%fp2 # Z*B4
6434
6435 fadd.d ATANC3(%pc),%fp3 # C3+Z*C5
6436 fadd.d ATANC2(%pc),%fp2 # C2+Z*C4
6437
6438 fmul.x %fp3,%fp1 # Z*(C3+Z*C5), FP3 RELEASED
6439 fmul.x %fp0,%fp2 # Y*(C2+Z*C4)
6440
6441 fadd.d ATANC1(%pc),%fp1 # C1+Z*(C3+Z*C5)
6442 fmul.x X(%a6),%fp0 # X'*Y
6443
6444 fadd.x %fp2,%fp1 # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
6445
6446 fmul.x %fp1,%fp0 # X'*Y*([B1+Z*(B3+Z*B5)]
6447# ... +[Y*(B2+Z*(B4+Z*B6))])
6448 fadd.x X(%a6),%fp0
6449
6450 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
6451
6452 fmov.l %d0,%fpcr # restore users rnd mode,prec
6453 tst.b (%a0)
6454 bpl.b pos_big
6455
6456neg_big:
6457 fadd.x NPIBY2(%pc),%fp0
6458 bra t_minx2
6459
6460pos_big:
6461 fadd.x PPIBY2(%pc),%fp0
6462 bra t_pinx2
6463
6464ATANHUGE:
6465#--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
6466 tst.b (%a0)
6467 bpl.b pos_huge
6468
6469neg_huge:
6470 fmov.x NPIBY2(%pc),%fp0
6471 fmov.l %d0,%fpcr
6472 fadd.x PTINY(%pc),%fp0
6473 bra t_minx2
6474
6475pos_huge:
6476 fmov.x PPIBY2(%pc),%fp0
6477 fmov.l %d0,%fpcr
6478 fadd.x NTINY(%pc),%fp0
6479 bra t_pinx2
6480
6481 global satand
6482#--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
6483satand:
6484 bra t_extdnrm
6485
6486#########################################################################
6487# sasin(): computes the inverse sine of a normalized input #
6488# sasind(): computes the inverse sine of a denormalized input #
6489# #
6490# INPUT *************************************************************** #
6491# a0 = pointer to extended precision input #
6492# d0 = round precision,mode #
6493# #
6494# OUTPUT ************************************************************** #
6495# fp0 = arcsin(X) #
6496# #
6497# ACCURACY and MONOTONICITY ******************************************* #
6498# The returned result is within 3 ulps in 64 significant bit, #
6499# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6500# rounded to double precision. The result is provably monotonic #
6501# in double precision. #
6502# #
6503# ALGORITHM *********************************************************** #
6504# #
6505# ASIN #
6506# 1. If |X| >= 1, go to 3. #
6507# #
6508# 2. (|X| < 1) Calculate asin(X) by #
6509# z := sqrt( [1-X][1+X] ) #
6510# asin(X) = atan( x / z ). #
6511# Exit. #
6512# #
6513# 3. If |X| > 1, go to 5. #
6514# #
6515# 4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
6516# #
6517# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
6518# Exit. #
6519# #
6520#########################################################################
6521
6522 global sasin
6523sasin:
6524 fmov.x (%a0),%fp0 # LOAD INPUT
6525
6526 mov.l (%a0),%d1
6527 mov.w 4(%a0),%d1
6528 and.l &0x7FFFFFFF,%d1
6529 cmp.l %d1,&0x3FFF8000
6530 bge.b ASINBIG
6531
6532# This catch is added here for the '060 QSP. Originally, the call to
6533# satan() would handle this case by causing the exception which would
6534# not be caught until gen_except(). Now, with the exceptions being
6535# detected inside of satan(), the exception would have been handled there
6536# instead of inside sasin() as expected.
6537 cmp.l %d1,&0x3FD78000
6538 blt.w ASINTINY
6539
6540#--THIS IS THE USUAL CASE, |X| < 1
6541#--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
6542
6543ASINMAIN:
6544 fmov.s &0x3F800000,%fp1
6545 fsub.x %fp0,%fp1 # 1-X
6546 fmovm.x &0x4,-(%sp) # {fp2}
6547 fmov.s &0x3F800000,%fp2
6548 fadd.x %fp0,%fp2 # 1+X
6549 fmul.x %fp2,%fp1 # (1+X)(1-X)
6550 fmovm.x (%sp)+,&0x20 # {fp2}
6551 fsqrt.x %fp1 # SQRT([1-X][1+X])
6552 fdiv.x %fp1,%fp0 # X/SQRT([1-X][1+X])
6553 fmovm.x &0x01,-(%sp) # save X/SQRT(...)
6554 lea (%sp),%a0 # pass ptr to X/SQRT(...)
6555 bsr satan
6556 add.l &0xc,%sp # clear X/SQRT(...) from stack
6557 bra t_inx2
6558
6559ASINBIG:
6560 fabs.x %fp0 # |X|
6561 fcmp.s %fp0,&0x3F800000
6562 fbgt t_operr # cause an operr exception
6563
6564#--|X| = 1, ASIN(X) = +- PI/2.
6565ASINONE:
6566 fmov.x PIBY2(%pc),%fp0
6567 mov.l (%a0),%d1
6568 and.l &0x80000000,%d1 # SIGN BIT OF X
6569 or.l &0x3F800000,%d1 # +-1 IN SGL FORMAT
6570 mov.l %d1,-(%sp) # push SIGN(X) IN SGL-FMT
6571 fmov.l %d0,%fpcr
6572 fmul.s (%sp)+,%fp0
6573 bra t_inx2
6574
6575#--|X| < 2^(-40), ATAN(X) = X
6576ASINTINY:
6577 fmov.l %d0,%fpcr # restore users rnd mode,prec
6578 mov.b &FMOV_OP,%d1 # last inst is MOVE
6579 fmov.x (%a0),%fp0 # last inst - possible exception
6580 bra t_catch
6581
6582 global sasind
6583#--ASIN(X) = X FOR DENORMALIZED X
6584sasind:
6585 bra t_extdnrm
6586
6587#########################################################################
6588# sacos(): computes the inverse cosine of a normalized input #
6589# sacosd(): computes the inverse cosine of a denormalized input #
6590# #
6591# INPUT *************************************************************** #
6592# a0 = pointer to extended precision input #
6593# d0 = round precision,mode #
6594# #
6595# OUTPUT ************************************************************** #
6596# fp0 = arccos(X) #
6597# #
6598# ACCURACY and MONOTONICITY ******************************************* #
6599# The returned result is within 3 ulps in 64 significant bit, #
6600# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6601# rounded to double precision. The result is provably monotonic #
6602# in double precision. #
6603# #
6604# ALGORITHM *********************************************************** #
6605# #
6606# ACOS #
6607# 1. If |X| >= 1, go to 3. #
6608# #
6609# 2. (|X| < 1) Calculate acos(X) by #
6610# z := (1-X) / (1+X) #
6611# acos(X) = 2 * atan( sqrt(z) ). #
6612# Exit. #
6613# #
6614# 3. If |X| > 1, go to 5. #
6615# #
6616# 4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit. #
6617# #
6618# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
6619# Exit. #
6620# #
6621#########################################################################
6622
6623 global sacos
6624sacos:
6625 fmov.x (%a0),%fp0 # LOAD INPUT
6626
6627 mov.l (%a0),%d1 # pack exp w/ upper 16 fraction
6628 mov.w 4(%a0),%d1
6629 and.l &0x7FFFFFFF,%d1
6630 cmp.l %d1,&0x3FFF8000
6631 bge.b ACOSBIG
6632
6633#--THIS IS THE USUAL CASE, |X| < 1
6634#--ACOS(X) = 2 * ATAN( SQRT( (1-X)/(1+X) ) )
6635
6636ACOSMAIN:
6637 fmov.s &0x3F800000,%fp1
6638 fadd.x %fp0,%fp1 # 1+X
6639 fneg.x %fp0 # -X
6640 fadd.s &0x3F800000,%fp0 # 1-X
6641 fdiv.x %fp1,%fp0 # (1-X)/(1+X)
6642 fsqrt.x %fp0 # SQRT((1-X)/(1+X))
6643 mov.l %d0,-(%sp) # save original users fpcr
6644 clr.l %d0
6645 fmovm.x &0x01,-(%sp) # save SQRT(...) to stack
6646 lea (%sp),%a0 # pass ptr to sqrt
6647 bsr satan # ATAN(SQRT([1-X]/[1+X]))
6648 add.l &0xc,%sp # clear SQRT(...) from stack
6649
6650 fmov.l (%sp)+,%fpcr # restore users round prec,mode
6651 fadd.x %fp0,%fp0 # 2 * ATAN( STUFF )
6652 bra t_pinx2
6653
6654ACOSBIG:
6655 fabs.x %fp0
6656 fcmp.s %fp0,&0x3F800000
6657 fbgt t_operr # cause an operr exception
6658
6659#--|X| = 1, ACOS(X) = 0 OR PI
6660 tst.b (%a0) # is X positive or negative?
6661 bpl.b ACOSP1
6662
6663#--X = -1
6664#Returns PI and inexact exception
6665ACOSM1:
6666 fmov.x PI(%pc),%fp0 # load PI
6667 fmov.l %d0,%fpcr # load round mode,prec
6668 fadd.s &0x00800000,%fp0 # add a small value
6669 bra t_pinx2
6670
6671ACOSP1:
6672 bra ld_pzero # answer is positive zero
6673
6674 global sacosd
6675#--ACOS(X) = PI/2 FOR DENORMALIZED X
6676sacosd:
6677 fmov.l %d0,%fpcr # load user's rnd mode/prec
6678 fmov.x PIBY2(%pc),%fp0
6679 bra t_pinx2
6680
6681#########################################################################
6682# setox(): computes the exponential for a normalized input #
6683# setoxd(): computes the exponential for a denormalized input #
6684# setoxm1(): computes the exponential minus 1 for a normalized input #
6685# setoxm1d(): computes the exponential minus 1 for a denormalized input #
6686# #
6687# INPUT *************************************************************** #
6688# a0 = pointer to extended precision input #
6689# d0 = round precision,mode #
6690# #
6691# OUTPUT ************************************************************** #
6692# fp0 = exp(X) or exp(X)-1 #
6693# #
6694# ACCURACY and MONOTONICITY ******************************************* #
6695# The returned result is within 0.85 ulps in 64 significant bit, #
6696# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6697# rounded to double precision. The result is provably monotonic #
6698# in double precision. #
6699# #
6700# ALGORITHM and IMPLEMENTATION **************************************** #
6701# #
6702# setoxd #
6703# ------ #
6704# Step 1. Set ans := 1.0 #
6705# #
6706# Step 2. Return ans := ans + sign(X)*2^(-126). Exit. #
6707# Notes: This will always generate one exception -- inexact. #
6708# #
6709# #
6710# setox #
6711# ----- #
6712# #
6713# Step 1. Filter out extreme cases of input argument. #
6714# 1.1 If |X| >= 2^(-65), go to Step 1.3. #
6715# 1.2 Go to Step 7. #
6716# 1.3 If |X| < 16380 log(2), go to Step 2. #
6717# 1.4 Go to Step 8. #
6718# Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
6719# To avoid the use of floating-point comparisons, a #
6720# compact representation of |X| is used. This format is a #
6721# 32-bit integer, the upper (more significant) 16 bits #
6722# are the sign and biased exponent field of |X|; the #
6723# lower 16 bits are the 16 most significant fraction #
6724# (including the explicit bit) bits of |X|. Consequently, #
6725# the comparisons in Steps 1.1 and 1.3 can be performed #
6726# by integer comparison. Note also that the constant #
6727# 16380 log(2) used in Step 1.3 is also in the compact #
6728# form. Thus taking the branch to Step 2 guarantees #
6729# |X| < 16380 log(2). There is no harm to have a small #
6730# number of cases where |X| is less than, but close to, #
6731# 16380 log(2) and the branch to Step 9 is taken. #
6732# #
6733# Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
6734# 2.1 Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
6735# was taken) #
6736# 2.2 N := round-to-nearest-integer( X * 64/log2 ). #
6737# 2.3 Calculate J = N mod 64; so J = 0,1,2,..., #
6738# or 63. #
6739# 2.4 Calculate M = (N - J)/64; so N = 64M + J. #
6740# 2.5 Calculate the address of the stored value of #
6741# 2^(J/64). #
6742# 2.6 Create the value Scale = 2^M. #
6743# Notes: The calculation in 2.2 is really performed by #
6744# Z := X * constant #
6745# N := round-to-nearest-integer(Z) #
6746# where #
6747# constant := single-precision( 64/log 2 ). #
6748# #
6749# Using a single-precision constant avoids memory #
6750# access. Another effect of using a single-precision #
6751# "constant" is that the calculated value Z is #
6752# #
6753# Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24). #
6754# #
6755# This error has to be considered later in Steps 3 and 4. #
6756# #
6757# Step 3. Calculate X - N*log2/64. #
6758# 3.1 R := X + N*L1, #
6759# where L1 := single-precision(-log2/64). #
6760# 3.2 R := R + N*L2, #
6761# L2 := extended-precision(-log2/64 - L1).#
6762# Notes: a) The way L1 and L2 are chosen ensures L1+L2 #
6763# approximate the value -log2/64 to 88 bits of accuracy. #
6764# b) N*L1 is exact because N is no longer than 22 bits #
6765# and L1 is no longer than 24 bits. #
6766# c) The calculation X+N*L1 is also exact due to #
6767# cancellation. Thus, R is practically X+N(L1+L2) to full #
6768# 64 bits. #
6769# d) It is important to estimate how large can |R| be #
6770# after Step 3.2. #
6771# #
6772# N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24) #
6773# X*64/log2 (1+eps) = N + f, |f| <= 0.5 #
6774# X*64/log2 - N = f - eps*X 64/log2 #
6775# X - N*log2/64 = f*log2/64 - eps*X #
6776# #
6777# #
6778# Now |X| <= 16446 log2, thus #
6779# #
6780# |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #
6781# <= 0.57 log2/64. #
6782# This bound will be used in Step 4. #
6783# #
6784# Step 4. Approximate exp(R)-1 by a polynomial #
6785# p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5)))) #
6786# Notes: a) In order to reduce memory access, the coefficients #
6787# are made as "short" as possible: A1 (which is 1/2), A4 #
6788# and A5 are single precision; A2 and A3 are double #
6789# precision. #
6790# b) Even with the restrictions above, #
6791# |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062. #
6792# Note that 0.0062 is slightly bigger than 0.57 log2/64. #
6793# c) To fully utilize the pipeline, p is separated into #
6794# two independent pieces of roughly equal complexities #
6795# p = [ R + R*S*(A2 + S*A4) ] + #
6796# [ S*(A1 + S*(A3 + S*A5)) ] #
6797# where S = R*R. #
6798# #
6799# Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by #
6800# ans := T + ( T*p + t) #
6801# where T and t are the stored values for 2^(J/64). #
6802# Notes: 2^(J/64) is stored as T and t where T+t approximates #
6803# 2^(J/64) to roughly 85 bits; T is in extended precision #
6804# and t is in single precision. Note also that T is #
6805# rounded to 62 bits so that the last two bits of T are #
6806# zero. The reason for such a special form is that T-1, #
6807# T-2, and T-8 will all be exact --- a property that will #
6808# give much more accurate computation of the function #
6809# EXPM1. #
6810# #
6811# Step 6. Reconstruction of exp(X) #
6812# exp(X) = 2^M * 2^(J/64) * exp(R). #
6813# 6.1 If AdjFlag = 0, go to 6.3 #
6814# 6.2 ans := ans * AdjScale #
6815# 6.3 Restore the user FPCR #
6816# 6.4 Return ans := ans * Scale. Exit. #
6817# Notes: If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R, #
6818# |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will #
6819# neither overflow nor underflow. If AdjFlag = 1, that #
6820# means that #
6821# X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #
6822# Hence, exp(X) may overflow or underflow or neither. #
6823# When that is the case, AdjScale = 2^(M1) where M1 is #
6824# approximately M. Thus 6.2 will never cause #
6825# over/underflow. Possible exception in 6.4 is overflow #
6826# or underflow. The inexact exception is not generated in #
6827# 6.4. Although one can argue that the inexact flag #
6828# should always be raised, to simulate that exception #
6829# cost to much than the flag is worth in practical uses. #
6830# #
6831# Step 7. Return 1 + X. #
6832# 7.1 ans := X #
6833# 7.2 Restore user FPCR. #
6834# 7.3 Return ans := 1 + ans. Exit #
6835# Notes: For non-zero X, the inexact exception will always be #
6836# raised by 7.3. That is the only exception raised by 7.3.#
6837# Note also that we use the FMOVEM instruction to move X #
6838# in Step 7.1 to avoid unnecessary trapping. (Although #
6839# the FMOVEM may not seem relevant since X is normalized, #
6840# the precaution will be useful in the library version of #
6841# this code where the separate entry for denormalized #
6842# inputs will be done away with.) #
6843# #
6844# Step 8. Handle exp(X) where |X| >= 16380log2. #
6845# 8.1 If |X| > 16480 log2, go to Step 9. #
6846# (mimic 2.2 - 2.6) #
6847# 8.2 N := round-to-integer( X * 64/log2 ) #
6848# 8.3 Calculate J = N mod 64, J = 0,1,...,63 #
6849# 8.4 K := (N-J)/64, M1 := truncate(K/2), M = K-M1, #
6850# AdjFlag := 1. #
6851# 8.5 Calculate the address of the stored value #
6852# 2^(J/64). #
6853# 8.6 Create the values Scale = 2^M, AdjScale = 2^M1. #
6854# 8.7 Go to Step 3. #
6855# Notes: Refer to notes for 2.2 - 2.6. #
6856# #
6857# Step 9. Handle exp(X), |X| > 16480 log2. #
6858# 9.1 If X < 0, go to 9.3 #
6859# 9.2 ans := Huge, go to 9.4 #
6860# 9.3 ans := Tiny. #
6861# 9.4 Restore user FPCR. #
6862# 9.5 Return ans := ans * ans. Exit. #
6863# Notes: Exp(X) will surely overflow or underflow, depending on #
6864# X's sign. "Huge" and "Tiny" are respectively large/tiny #
6865# extended-precision numbers whose square over/underflow #
6866# with an inexact result. Thus, 9.5 always raises the #
6867# inexact together with either overflow or underflow. #
6868# #
6869# setoxm1d #
6870# -------- #
6871# #
6872# Step 1. Set ans := 0 #
6873# #
6874# Step 2. Return ans := X + ans. Exit. #
6875# Notes: This will return X with the appropriate rounding #
6876# precision prescribed by the user FPCR. #
6877# #
6878# setoxm1 #
6879# ------- #
6880# #
6881# Step 1. Check |X| #
6882# 1.1 If |X| >= 1/4, go to Step 1.3. #
6883# 1.2 Go to Step 7. #
6884# 1.3 If |X| < 70 log(2), go to Step 2. #
6885# 1.4 Go to Step 10. #
6886# Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
6887# However, it is conceivable |X| can be small very often #
6888# because EXPM1 is intended to evaluate exp(X)-1 #
6889# accurately when |X| is small. For further details on #
6890# the comparisons, see the notes on Step 1 of setox. #
6891# #
6892# Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
6893# 2.1 N := round-to-nearest-integer( X * 64/log2 ). #
6894# 2.2 Calculate J = N mod 64; so J = 0,1,2,..., #
6895# or 63. #
6896# 2.3 Calculate M = (N - J)/64; so N = 64M + J. #
6897# 2.4 Calculate the address of the stored value of #
6898# 2^(J/64). #
6899# 2.5 Create the values Sc = 2^M and #
6900# OnebySc := -2^(-M). #
6901# Notes: See the notes on Step 2 of setox. #
6902# #
6903# Step 3. Calculate X - N*log2/64. #
6904# 3.1 R := X + N*L1, #
6905# where L1 := single-precision(-log2/64). #
6906# 3.2 R := R + N*L2, #
6907# L2 := extended-precision(-log2/64 - L1).#
6908# Notes: Applying the analysis of Step 3 of setox in this case #
6909# shows that |R| <= 0.0055 (note that |X| <= 70 log2 in #
6910# this case). #
6911# #
6912# Step 4. Approximate exp(R)-1 by a polynomial #
6913# p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #
6914# Notes: a) In order to reduce memory access, the coefficients #
6915# are made as "short" as possible: A1 (which is 1/2), A5 #
6916# and A6 are single precision; A2, A3 and A4 are double #
6917# precision. #
6918# b) Even with the restriction above, #
6919# |p - (exp(R)-1)| < |R| * 2^(-72.7) #
6920# for all |R| <= 0.0055. #
6921# c) To fully utilize the pipeline, p is separated into #
6922# two independent pieces of roughly equal complexity #
6923# p = [ R*S*(A2 + S*(A4 + S*A6)) ] + #
6924# [ R + S*(A1 + S*(A3 + S*A5)) ] #
6925# where S = R*R. #
6926# #
6927# Step 5. Compute 2^(J/64)*p by #
6928# p := T*p #
6929# where T and t are the stored values for 2^(J/64). #
6930# Notes: 2^(J/64) is stored as T and t where T+t approximates #
6931# 2^(J/64) to roughly 85 bits; T is in extended precision #
6932# and t is in single precision. Note also that T is #
6933# rounded to 62 bits so that the last two bits of T are #
6934# zero. The reason for such a special form is that T-1, #
6935# T-2, and T-8 will all be exact --- a property that will #
6936# be exploited in Step 6 below. The total relative error #
6937# in p is no bigger than 2^(-67.7) compared to the final #
6938# result. #
6939# #
6940# Step 6. Reconstruction of exp(X)-1 #
6941# exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ). #
6942# 6.1 If M <= 63, go to Step 6.3. #
6943# 6.2 ans := T + (p + (t + OnebySc)). Go to 6.6 #
6944# 6.3 If M >= -3, go to 6.5. #
6945# 6.4 ans := (T + (p + t)) + OnebySc. Go to 6.6 #
6946# 6.5 ans := (T + OnebySc) + (p + t). #
6947# 6.6 Restore user FPCR. #
6948# 6.7 Return ans := Sc * ans. Exit. #
6949# Notes: The various arrangements of the expressions give #
6950# accurate evaluations. #
6951# #
6952# Step 7. exp(X)-1 for |X| < 1/4. #
6953# 7.1 If |X| >= 2^(-65), go to Step 9. #
6954# 7.2 Go to Step 8. #
6955# #
6956# Step 8. Calculate exp(X)-1, |X| < 2^(-65). #
6957# 8.1 If |X| < 2^(-16312), goto 8.3 #
6958# 8.2 Restore FPCR; return ans := X - 2^(-16382). #
6959# Exit. #
6960# 8.3 X := X * 2^(140). #
6961# 8.4 Restore FPCR; ans := ans - 2^(-16382). #
6962# Return ans := ans*2^(140). Exit #
6963# Notes: The idea is to return "X - tiny" under the user #
6964# precision and rounding modes. To avoid unnecessary #
6965# inefficiency, we stay away from denormalized numbers #
6966# the best we can. For |X| >= 2^(-16312), the #
6967# straightforward 8.2 generates the inexact exception as #
6968# the case warrants. #
6969# #
6970# Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial #
6971# p = X + X*X*(B1 + X*(B2 + ... + X*B12)) #
6972# Notes: a) In order to reduce memory access, the coefficients #
6973# are made as "short" as possible: B1 (which is 1/2), B9 #
6974# to B12 are single precision; B3 to B8 are double #
6975# precision; and B2 is double extended. #
6976# b) Even with the restriction above, #
6977# |p - (exp(X)-1)| < |X| 2^(-70.6) #
6978# for all |X| <= 0.251. #
6979# Note that 0.251 is slightly bigger than 1/4. #
6980# c) To fully preserve accuracy, the polynomial is #
6981# computed as #
6982# X + ( S*B1 + Q ) where S = X*X and #
6983# Q = X*S*(B2 + X*(B3 + ... + X*B12)) #
6984# d) To fully utilize the pipeline, Q is separated into #
6985# two independent pieces of roughly equal complexity #
6986# Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] + #
6987# [ S*S*(B3 + S*(B5 + ... + S*B11)) ] #
6988# #
6989# Step 10. Calculate exp(X)-1 for |X| >= 70 log 2. #
6990# 10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all #
6991# practical purposes. Therefore, go to Step 1 of setox. #
6992# 10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #
6993# purposes. #
6994# ans := -1 #
6995# Restore user FPCR #
6996# Return ans := ans + 2^(-126). Exit. #
6997# Notes: 10.2 will always create an inexact and return -1 + tiny #
6998# in the user rounding precision and mode. #
6999# #
7000#########################################################################
7001
7002L2: long 0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
7003
7004EEXPA3: long 0x3FA55555,0x55554CC1
7005EEXPA2: long 0x3FC55555,0x55554A54
7006
7007EM1A4: long 0x3F811111,0x11174385
7008EM1A3: long 0x3FA55555,0x55554F5A
7009
7010EM1A2: long 0x3FC55555,0x55555555,0x00000000,0x00000000
7011
7012EM1B8: long 0x3EC71DE3,0xA5774682
7013EM1B7: long 0x3EFA01A0,0x19D7CB68
7014
7015EM1B6: long 0x3F2A01A0,0x1A019DF3
7016EM1B5: long 0x3F56C16C,0x16C170E2
7017
7018EM1B4: long 0x3F811111,0x11111111
7019EM1B3: long 0x3FA55555,0x55555555
7020
7021EM1B2: long 0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
7022 long 0x00000000
7023
7024TWO140: long 0x48B00000,0x00000000
7025TWON140:
7026 long 0x37300000,0x00000000
7027
7028EEXPTBL:
7029 long 0x3FFF0000,0x80000000,0x00000000,0x00000000
7030 long 0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
7031 long 0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
7032 long 0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
7033 long 0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
7034 long 0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
7035 long 0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
7036 long 0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
7037 long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
7038 long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
7039 long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
7040 long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
7041 long 0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
7042 long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
7043 long 0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
7044 long 0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
7045 long 0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
7046 long 0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
7047 long 0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
7048 long 0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
7049 long 0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
7050 long 0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
7051 long 0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
7052 long 0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
7053 long 0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
7054 long 0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
7055 long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
7056 long 0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
7057 long 0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
7058 long 0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
7059 long 0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
7060 long 0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
7061 long 0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
7062 long 0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
7063 long 0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
7064 long 0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
7065 long 0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
7066 long 0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
7067 long 0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
7068 long 0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
7069 long 0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
7070 long 0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
7071 long 0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
7072 long 0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
7073 long 0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
7074 long 0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
7075 long 0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
7076 long 0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
7077 long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
7078 long 0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
7079 long 0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
7080 long 0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
7081 long 0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
7082 long 0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
7083 long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
7084 long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
7085 long 0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
7086 long 0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
7087 long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
7088 long 0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
7089 long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
7090 long 0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
7091 long 0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
7092 long 0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
7093
7094 set ADJFLAG,L_SCR2
7095 set SCALE,FP_SCR0
7096 set ADJSCALE,FP_SCR1
7097 set SC,FP_SCR0
7098 set ONEBYSC,FP_SCR1
7099
7100 global setox
7101setox:
7102#--entry point for EXP(X), here X is finite, non-zero, and not NaN's
7103
7104#--Step 1.
7105 mov.l (%a0),%d1 # load part of input X
7106 and.l &0x7FFF0000,%d1 # biased expo. of X
7107 cmp.l %d1,&0x3FBE0000 # 2^(-65)
7108 bge.b EXPC1 # normal case
7109 bra EXPSM
7110
7111EXPC1:
7112#--The case |X| >= 2^(-65)
7113 mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
7114 cmp.l %d1,&0x400CB167 # 16380 log2 trunc. 16 bits
7115 blt.b EXPMAIN # normal case
7116 bra EEXPBIG
7117
7118EXPMAIN:
7119#--Step 2.
7120#--This is the normal branch: 2^(-65) <= |X| < 16380 log2.
7121 fmov.x (%a0),%fp0 # load input from (a0)
7122
7123 fmov.x %fp0,%fp1
7124 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7125 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7126 mov.l &0,ADJFLAG(%a6)
7127 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7128 lea EEXPTBL(%pc),%a1
7129 fmov.l %d1,%fp0 # convert to floating-format
7130
7131 mov.l %d1,L_SCR1(%a6) # save N temporarily
7132 and.l &0x3F,%d1 # D0 is J = N mod 64
7133 lsl.l &4,%d1
7134 add.l %d1,%a1 # address of 2^(J/64)
7135 mov.l L_SCR1(%a6),%d1
7136 asr.l &6,%d1 # D0 is M
7137 add.w &0x3FFF,%d1 # biased expo. of 2^(M)
7138 mov.w L2(%pc),L_SCR1(%a6) # prefetch L2, no need in CB
7139
7140EXPCONT1:
7141#--Step 3.
7142#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7143#--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
7144 fmov.x %fp0,%fp2
7145 fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
7146 fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
7147 fadd.x %fp1,%fp0 # X + N*L1
7148 fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
7149
7150#--Step 4.
7151#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7152#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
7153#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7154#--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
7155
7156 fmov.x %fp0,%fp1
7157 fmul.x %fp1,%fp1 # fp1 IS S = R*R
7158
7159 fmov.s &0x3AB60B70,%fp2 # fp2 IS A5
7160
7161 fmul.x %fp1,%fp2 # fp2 IS S*A5
7162 fmov.x %fp1,%fp3
7163 fmul.s &0x3C088895,%fp3 # fp3 IS S*A4
7164
7165 fadd.d EEXPA3(%pc),%fp2 # fp2 IS A3+S*A5
7166 fadd.d EEXPA2(%pc),%fp3 # fp3 IS A2+S*A4
7167
7168 fmul.x %fp1,%fp2 # fp2 IS S*(A3+S*A5)
7169 mov.w %d1,SCALE(%a6) # SCALE is 2^(M) in extended
7170 mov.l &0x80000000,SCALE+4(%a6)
7171 clr.l SCALE+8(%a6)
7172
7173 fmul.x %fp1,%fp3 # fp3 IS S*(A2+S*A4)
7174
7175 fadd.s &0x3F000000,%fp2 # fp2 IS A1+S*(A3+S*A5)
7176 fmul.x %fp0,%fp3 # fp3 IS R*S*(A2+S*A4)
7177
7178 fmul.x %fp1,%fp2 # fp2 IS S*(A1+S*(A3+S*A5))
7179 fadd.x %fp3,%fp0 # fp0 IS R+R*S*(A2+S*A4),
7180
7181 fmov.x (%a1)+,%fp1 # fp1 is lead. pt. of 2^(J/64)
7182 fadd.x %fp2,%fp0 # fp0 is EXP(R) - 1
7183
7184#--Step 5
7185#--final reconstruction process
7186#--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
7187
7188 fmul.x %fp1,%fp0 # 2^(J/64)*(Exp(R)-1)
7189 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7190 fadd.s (%a1),%fp0 # accurate 2^(J/64)
7191
7192 fadd.x %fp1,%fp0 # 2^(J/64) + 2^(J/64)*...
7193 mov.l ADJFLAG(%a6),%d1
7194
7195#--Step 6
7196 tst.l %d1
7197 beq.b NORMAL
7198ADJUST:
7199 fmul.x ADJSCALE(%a6),%fp0
7200NORMAL:
7201 fmov.l %d0,%fpcr # restore user FPCR
7202 mov.b &FMUL_OP,%d1 # last inst is MUL
7203 fmul.x SCALE(%a6),%fp0 # multiply 2^(M)
7204 bra t_catch
7205
7206EXPSM:
7207#--Step 7
7208 fmovm.x (%a0),&0x80 # load X
7209 fmov.l %d0,%fpcr
7210 fadd.s &0x3F800000,%fp0 # 1+X in user mode
7211 bra t_pinx2
7212
7213EEXPBIG:
7214#--Step 8
7215 cmp.l %d1,&0x400CB27C # 16480 log2
7216 bgt.b EXP2BIG
7217#--Steps 8.2 -- 8.6
7218 fmov.x (%a0),%fp0 # load input from (a0)
7219
7220 fmov.x %fp0,%fp1
7221 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7222 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7223 mov.l &1,ADJFLAG(%a6)
7224 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7225 lea EEXPTBL(%pc),%a1
7226 fmov.l %d1,%fp0 # convert to floating-format
7227 mov.l %d1,L_SCR1(%a6) # save N temporarily
7228 and.l &0x3F,%d1 # D0 is J = N mod 64
7229 lsl.l &4,%d1
7230 add.l %d1,%a1 # address of 2^(J/64)
7231 mov.l L_SCR1(%a6),%d1
7232 asr.l &6,%d1 # D0 is K
7233 mov.l %d1,L_SCR1(%a6) # save K temporarily
7234 asr.l &1,%d1 # D0 is M1
7235 sub.l %d1,L_SCR1(%a6) # a1 is M
7236 add.w &0x3FFF,%d1 # biased expo. of 2^(M1)
7237 mov.w %d1,ADJSCALE(%a6) # ADJSCALE := 2^(M1)
7238 mov.l &0x80000000,ADJSCALE+4(%a6)
7239 clr.l ADJSCALE+8(%a6)
7240 mov.l L_SCR1(%a6),%d1 # D0 is M
7241 add.w &0x3FFF,%d1 # biased expo. of 2^(M)
7242 bra.w EXPCONT1 # go back to Step 3
7243
7244EXP2BIG:
7245#--Step 9
7246 tst.b (%a0) # is X positive or negative?
7247 bmi t_unfl2
7248 bra t_ovfl2
7249
7250 global setoxd
7251setoxd:
7252#--entry point for EXP(X), X is denormalized
7253 mov.l (%a0),-(%sp)
7254 andi.l &0x80000000,(%sp)
7255 ori.l &0x00800000,(%sp) # sign(X)*2^(-126)
7256
7257 fmov.s &0x3F800000,%fp0
7258
7259 fmov.l %d0,%fpcr
7260 fadd.s (%sp)+,%fp0
7261 bra t_pinx2
7262
7263 global setoxm1
7264setoxm1:
7265#--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
7266
7267#--Step 1.
7268#--Step 1.1
7269 mov.l (%a0),%d1 # load part of input X
7270 and.l &0x7FFF0000,%d1 # biased expo. of X
7271 cmp.l %d1,&0x3FFD0000 # 1/4
7272 bge.b EM1CON1 # |X| >= 1/4
7273 bra EM1SM
7274
7275EM1CON1:
7276#--Step 1.3
7277#--The case |X| >= 1/4
7278 mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
7279 cmp.l %d1,&0x4004C215 # 70log2 rounded up to 16 bits
7280 ble.b EM1MAIN # 1/4 <= |X| <= 70log2
7281 bra EM1BIG
7282
7283EM1MAIN:
7284#--Step 2.
7285#--This is the case: 1/4 <= |X| <= 70 log2.
7286 fmov.x (%a0),%fp0 # load input from (a0)
7287
7288 fmov.x %fp0,%fp1
7289 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7290 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7291 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7292 lea EEXPTBL(%pc),%a1
7293 fmov.l %d1,%fp0 # convert to floating-format
7294
7295 mov.l %d1,L_SCR1(%a6) # save N temporarily
7296 and.l &0x3F,%d1 # D0 is J = N mod 64
7297 lsl.l &4,%d1
7298 add.l %d1,%a1 # address of 2^(J/64)
7299 mov.l L_SCR1(%a6),%d1
7300 asr.l &6,%d1 # D0 is M
7301 mov.l %d1,L_SCR1(%a6) # save a copy of M
7302
7303#--Step 3.
7304#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7305#--a0 points to 2^(J/64), D0 and a1 both contain M
7306 fmov.x %fp0,%fp2
7307 fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
7308 fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
7309 fadd.x %fp1,%fp0 # X + N*L1
7310 fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
7311 add.w &0x3FFF,%d1 # D0 is biased expo. of 2^M
7312
7313#--Step 4.
7314#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7315#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
7316#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7317#--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
7318
7319 fmov.x %fp0,%fp1
7320 fmul.x %fp1,%fp1 # fp1 IS S = R*R
7321
7322 fmov.s &0x3950097B,%fp2 # fp2 IS a6
7323
7324 fmul.x %fp1,%fp2 # fp2 IS S*A6
7325 fmov.x %fp1,%fp3
7326 fmul.s &0x3AB60B6A,%fp3 # fp3 IS S*A5
7327
7328 fadd.d EM1A4(%pc),%fp2 # fp2 IS A4+S*A6
7329 fadd.d EM1A3(%pc),%fp3 # fp3 IS A3+S*A5
7330 mov.w %d1,SC(%a6) # SC is 2^(M) in extended
7331 mov.l &0x80000000,SC+4(%a6)
7332 clr.l SC+8(%a6)
7333
7334 fmul.x %fp1,%fp2 # fp2 IS S*(A4+S*A6)
7335 mov.l L_SCR1(%a6),%d1 # D0 is M
7336 neg.w %d1 # D0 is -M
7337 fmul.x %fp1,%fp3 # fp3 IS S*(A3+S*A5)
7338 add.w &0x3FFF,%d1 # biased expo. of 2^(-M)
7339 fadd.d EM1A2(%pc),%fp2 # fp2 IS A2+S*(A4+S*A6)
7340 fadd.s &0x3F000000,%fp3 # fp3 IS A1+S*(A3+S*A5)
7341
7342 fmul.x %fp1,%fp2 # fp2 IS S*(A2+S*(A4+S*A6))
7343 or.w &0x8000,%d1 # signed/expo. of -2^(-M)
7344 mov.w %d1,ONEBYSC(%a6) # OnebySc is -2^(-M)
7345 mov.l &0x80000000,ONEBYSC+4(%a6)
7346 clr.l ONEBYSC+8(%a6)
7347 fmul.x %fp3,%fp1 # fp1 IS S*(A1+S*(A3+S*A5))
7348
7349 fmul.x %fp0,%fp2 # fp2 IS R*S*(A2+S*(A4+S*A6))
7350 fadd.x %fp1,%fp0 # fp0 IS R+S*(A1+S*(A3+S*A5))
7351
7352 fadd.x %fp2,%fp0 # fp0 IS EXP(R)-1
7353
7354 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7355
7356#--Step 5
7357#--Compute 2^(J/64)*p
7358
7359 fmul.x (%a1),%fp0 # 2^(J/64)*(Exp(R)-1)
7360
7361#--Step 6
7362#--Step 6.1
7363 mov.l L_SCR1(%a6),%d1 # retrieve M
7364 cmp.l %d1,&63
7365 ble.b MLE63
7366#--Step 6.2 M >= 64
7367 fmov.s 12(%a1),%fp1 # fp1 is t
7368 fadd.x ONEBYSC(%a6),%fp1 # fp1 is t+OnebySc
7369 fadd.x %fp1,%fp0 # p+(t+OnebySc), fp1 released
7370 fadd.x (%a1),%fp0 # T+(p+(t+OnebySc))
7371 bra EM1SCALE
7372MLE63:
7373#--Step 6.3 M <= 63
7374 cmp.l %d1,&-3
7375 bge.b MGEN3
7376MLTN3:
7377#--Step 6.4 M <= -4
7378 fadd.s 12(%a1),%fp0 # p+t
7379 fadd.x (%a1),%fp0 # T+(p+t)
7380 fadd.x ONEBYSC(%a6),%fp0 # OnebySc + (T+(p+t))
7381 bra EM1SCALE
7382MGEN3:
7383#--Step 6.5 -3 <= M <= 63
7384 fmov.x (%a1)+,%fp1 # fp1 is T
7385 fadd.s (%a1),%fp0 # fp0 is p+t
7386 fadd.x ONEBYSC(%a6),%fp1 # fp1 is T+OnebySc
7387 fadd.x %fp1,%fp0 # (T+OnebySc)+(p+t)
7388
7389EM1SCALE:
7390#--Step 6.6
7391 fmov.l %d0,%fpcr
7392 fmul.x SC(%a6),%fp0
7393 bra t_inx2
7394
7395EM1SM:
7396#--Step 7 |X| < 1/4.
7397 cmp.l %d1,&0x3FBE0000 # 2^(-65)
7398 bge.b EM1POLY
7399
7400EM1TINY:
7401#--Step 8 |X| < 2^(-65)
7402 cmp.l %d1,&0x00330000 # 2^(-16312)
7403 blt.b EM12TINY
7404#--Step 8.2
7405 mov.l &0x80010000,SC(%a6) # SC is -2^(-16382)
7406 mov.l &0x80000000,SC+4(%a6)
7407 clr.l SC+8(%a6)
7408 fmov.x (%a0),%fp0
7409 fmov.l %d0,%fpcr
7410 mov.b &FADD_OP,%d1 # last inst is ADD
7411 fadd.x SC(%a6),%fp0
7412 bra t_catch
7413
7414EM12TINY:
7415#--Step 8.3
7416 fmov.x (%a0),%fp0
7417 fmul.d TWO140(%pc),%fp0
7418 mov.l &0x80010000,SC(%a6)
7419 mov.l &0x80000000,SC+4(%a6)
7420 clr.l SC+8(%a6)
7421 fadd.x SC(%a6),%fp0
7422 fmov.l %d0,%fpcr
7423 mov.b &FMUL_OP,%d1 # last inst is MUL
7424 fmul.d TWON140(%pc),%fp0
7425 bra t_catch
7426
7427EM1POLY:
7428#--Step 9 exp(X)-1 by a simple polynomial
7429 fmov.x (%a0),%fp0 # fp0 is X
7430 fmul.x %fp0,%fp0 # fp0 is S := X*X
7431 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7432 fmov.s &0x2F30CAA8,%fp1 # fp1 is B12
7433 fmul.x %fp0,%fp1 # fp1 is S*B12
7434 fmov.s &0x310F8290,%fp2 # fp2 is B11
7435 fadd.s &0x32D73220,%fp1 # fp1 is B10+S*B12
7436
7437 fmul.x %fp0,%fp2 # fp2 is S*B11
7438 fmul.x %fp0,%fp1 # fp1 is S*(B10 + ...
7439
7440 fadd.s &0x3493F281,%fp2 # fp2 is B9+S*...
7441 fadd.d EM1B8(%pc),%fp1 # fp1 is B8+S*...
7442
7443 fmul.x %fp0,%fp2 # fp2 is S*(B9+...
7444 fmul.x %fp0,%fp1 # fp1 is S*(B8+...
7445
7446 fadd.d EM1B7(%pc),%fp2 # fp2 is B7+S*...
7447 fadd.d EM1B6(%pc),%fp1 # fp1 is B6+S*...
7448
7449 fmul.x %fp0,%fp2 # fp2 is S*(B7+...
7450 fmul.x %fp0,%fp1 # fp1 is S*(B6+...
7451
7452 fadd.d EM1B5(%pc),%fp2 # fp2 is B5+S*...
7453 fadd.d EM1B4(%pc),%fp1 # fp1 is B4+S*...
7454
7455 fmul.x %fp0,%fp2 # fp2 is S*(B5+...
7456 fmul.x %fp0,%fp1 # fp1 is S*(B4+...
7457
7458 fadd.d EM1B3(%pc),%fp2 # fp2 is B3+S*...
7459 fadd.x EM1B2(%pc),%fp1 # fp1 is B2+S*...
7460
7461 fmul.x %fp0,%fp2 # fp2 is S*(B3+...
7462 fmul.x %fp0,%fp1 # fp1 is S*(B2+...
7463
7464 fmul.x %fp0,%fp2 # fp2 is S*S*(B3+...)
7465 fmul.x (%a0),%fp1 # fp1 is X*S*(B2...
7466
7467 fmul.s &0x3F000000,%fp0 # fp0 is S*B1
7468 fadd.x %fp2,%fp1 # fp1 is Q
7469
7470 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7471
7472 fadd.x %fp1,%fp0 # fp0 is S*B1+Q
7473
7474 fmov.l %d0,%fpcr
7475 fadd.x (%a0),%fp0
7476 bra t_inx2
7477
7478EM1BIG:
7479#--Step 10 |X| > 70 log2
7480 mov.l (%a0),%d1
7481 cmp.l %d1,&0
7482 bgt.w EXPC1
7483#--Step 10.2
7484 fmov.s &0xBF800000,%fp0 # fp0 is -1
7485 fmov.l %d0,%fpcr
7486 fadd.s &0x00800000,%fp0 # -1 + 2^(-126)
7487 bra t_minx2
7488
7489 global setoxm1d
7490setoxm1d:
7491#--entry point for EXPM1(X), here X is denormalized
7492#--Step 0.
7493 bra t_extdnrm
7494
7495#########################################################################
7496# sgetexp(): returns the exponent portion of the input argument. #
7497# The exponent bias is removed and the exponent value is #
7498# returned as an extended precision number in fp0. #
7499# sgetexpd(): handles denormalized numbers. #
7500# #
7501# sgetman(): extracts the mantissa of the input argument. The #
7502# mantissa is converted to an extended precision number w/ #
7503# an exponent of $3fff and is returned in fp0. The range of #
7504# the result is [1.0 - 2.0). #
7505# sgetmand(): handles denormalized numbers. #
7506# #
7507# INPUT *************************************************************** #
7508# a0 = pointer to extended precision input #
7509# #
7510# OUTPUT ************************************************************** #
7511# fp0 = exponent(X) or mantissa(X) #
7512# #
7513#########################################################################
7514
7515 global sgetexp
7516sgetexp:
7517 mov.w SRC_EX(%a0),%d0 # get the exponent
7518 bclr &0xf,%d0 # clear the sign bit
7519 subi.w &0x3fff,%d0 # subtract off the bias
7520 fmov.w %d0,%fp0 # return exp in fp0
7521 blt.b sgetexpn # it's negative
7522 rts
7523
7524sgetexpn:
7525 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7526 rts
7527
7528 global sgetexpd
7529sgetexpd:
7530 bsr.l norm # normalize
7531 neg.w %d0 # new exp = -(shft amt)
7532 subi.w &0x3fff,%d0 # subtract off the bias
7533 fmov.w %d0,%fp0 # return exp in fp0
7534 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7535 rts
7536
7537 global sgetman
7538sgetman:
7539 mov.w SRC_EX(%a0),%d0 # get the exp
7540 ori.w &0x7fff,%d0 # clear old exp
7541 bclr &0xe,%d0 # make it the new exp +-3fff
7542
7543# here, we build the result in a tmp location so as not to disturb the input
7544 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
7545 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
7546 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
7547 fmov.x FP_SCR0(%a6),%fp0 # put new value back in fp0
7548 bmi.b sgetmann # it's negative
7549 rts
7550
7551sgetmann:
7552 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7553 rts
7554
7555#
7556# For denormalized numbers, shift the mantissa until the j-bit = 1,
7557# then load the exponent with +/1 $3fff.
7558#
7559 global sgetmand
7560sgetmand:
7561 bsr.l norm # normalize exponent
7562 bra.b sgetman
7563
7564#########################################################################
7565# scosh(): computes the hyperbolic cosine of a normalized input #
7566# scoshd(): computes the hyperbolic cosine of a denormalized input #
7567# #
7568# INPUT *************************************************************** #
7569# a0 = pointer to extended precision input #
7570# d0 = round precision,mode #
7571# #
7572# OUTPUT ************************************************************** #
7573# fp0 = cosh(X) #
7574# #
7575# ACCURACY and MONOTONICITY ******************************************* #
7576# The returned result is within 3 ulps in 64 significant bit, #
7577# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7578# rounded to double precision. The result is provably monotonic #
7579# in double precision. #
7580# #
7581# ALGORITHM *********************************************************** #
7582# #
7583# COSH #
7584# 1. If |X| > 16380 log2, go to 3. #
7585# #
7586# 2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae #
7587# y = |X|, z = exp(Y), and #
7588# cosh(X) = (1/2)*( z + 1/z ). #
7589# Exit. #
7590# #
7591# 3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5. #
7592# #
7593# 4. (16380 log2 < |X| <= 16480 log2) #
7594# cosh(X) = sign(X) * exp(|X|)/2. #
7595# However, invoking exp(|X|) may cause premature #
7596# overflow. Thus, we calculate sinh(X) as follows: #
7597# Y := |X| #
7598# Fact := 2**(16380) #
7599# Y' := Y - 16381 log2 #
7600# cosh(X) := Fact * exp(Y'). #
7601# Exit. #
7602# #
7603# 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
7604# Huge*Huge to generate overflow and an infinity with #
7605# the appropriate sign. Huge is the largest finite number #
7606# in extended format. Exit. #
7607# #
7608#########################################################################
7609
7610TWO16380:
7611 long 0x7FFB0000,0x80000000,0x00000000,0x00000000
7612
7613 global scosh
7614scosh:
7615 fmov.x (%a0),%fp0 # LOAD INPUT
7616
7617 mov.l (%a0),%d1
7618 mov.w 4(%a0),%d1
7619 and.l &0x7FFFFFFF,%d1
7620 cmp.l %d1,&0x400CB167
7621 bgt.b COSHBIG
7622
7623#--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7624#--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
7625
7626 fabs.x %fp0 # |X|
7627
7628 mov.l %d0,-(%sp)
7629 clr.l %d0
7630 fmovm.x &0x01,-(%sp) # save |X| to stack
7631 lea (%sp),%a0 # pass ptr to |X|
7632 bsr setox # FP0 IS EXP(|X|)
7633 add.l &0xc,%sp # erase |X| from stack
7634 fmul.s &0x3F000000,%fp0 # (1/2)EXP(|X|)
7635 mov.l (%sp)+,%d0
7636
7637 fmov.s &0x3E800000,%fp1 # (1/4)
7638 fdiv.x %fp0,%fp1 # 1/(2 EXP(|X|))
7639
7640 fmov.l %d0,%fpcr
7641 mov.b &FADD_OP,%d1 # last inst is ADD
7642 fadd.x %fp1,%fp0
7643 bra t_catch
7644
7645COSHBIG:
7646 cmp.l %d1,&0x400CB2B3
7647 bgt.b COSHHUGE
7648
7649 fabs.x %fp0
7650 fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
7651 fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
7652
7653 mov.l %d0,-(%sp)
7654 clr.l %d0
7655 fmovm.x &0x01,-(%sp) # save fp0 to stack
7656 lea (%sp),%a0 # pass ptr to fp0
7657 bsr setox
7658 add.l &0xc,%sp # clear fp0 from stack
7659 mov.l (%sp)+,%d0
7660
7661 fmov.l %d0,%fpcr
7662 mov.b &FMUL_OP,%d1 # last inst is MUL
7663 fmul.x TWO16380(%pc),%fp0
7664 bra t_catch
7665
7666COSHHUGE:
7667 bra t_ovfl2
7668
7669 global scoshd
7670#--COSH(X) = 1 FOR DENORMALIZED X
7671scoshd:
7672 fmov.s &0x3F800000,%fp0
7673
7674 fmov.l %d0,%fpcr
7675 fadd.s &0x00800000,%fp0
7676 bra t_pinx2
7677
7678#########################################################################
7679# ssinh(): computes the hyperbolic sine of a normalized input #
7680# ssinhd(): computes the hyperbolic sine of a denormalized input #
7681# #
7682# INPUT *************************************************************** #
7683# a0 = pointer to extended precision input #
7684# d0 = round precision,mode #
7685# #
7686# OUTPUT ************************************************************** #
7687# fp0 = sinh(X) #
7688# #
7689# ACCURACY and MONOTONICITY ******************************************* #
7690# The returned result is within 3 ulps in 64 significant bit, #
7691# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7692# rounded to double precision. The result is provably monotonic #
7693# in double precision. #
7694# #
7695# ALGORITHM *********************************************************** #
7696# #
7697# SINH #
7698# 1. If |X| > 16380 log2, go to 3. #
7699# #
7700# 2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula #
7701# y = |X|, sgn = sign(X), and z = expm1(Y), #
7702# sinh(X) = sgn*(1/2)*( z + z/(1+z) ). #
7703# Exit. #
7704# #
7705# 3. If |X| > 16480 log2, go to 5. #
7706# #
7707# 4. (16380 log2 < |X| <= 16480 log2) #
7708# sinh(X) = sign(X) * exp(|X|)/2. #
7709# However, invoking exp(|X|) may cause premature overflow. #
7710# Thus, we calculate sinh(X) as follows: #
7711# Y := |X| #
7712# sgn := sign(X) #
7713# sgnFact := sgn * 2**(16380) #
7714# Y' := Y - 16381 log2 #
7715# sinh(X) := sgnFact * exp(Y'). #
7716# Exit. #
7717# #
7718# 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
7719# sign(X)*Huge*Huge to generate overflow and an infinity with #
7720# the appropriate sign. Huge is the largest finite number in #
7721# extended format. Exit. #
7722# #
7723#########################################################################
7724
7725 global ssinh
7726ssinh:
7727 fmov.x (%a0),%fp0 # LOAD INPUT
7728
7729 mov.l (%a0),%d1
7730 mov.w 4(%a0),%d1
7731 mov.l %d1,%a1 # save (compacted) operand
7732 and.l &0x7FFFFFFF,%d1
7733 cmp.l %d1,&0x400CB167
7734 bgt.b SINHBIG
7735
7736#--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7737#--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
7738
7739 fabs.x %fp0 # Y = |X|
7740
7741 movm.l &0x8040,-(%sp) # {a1/d0}
7742 fmovm.x &0x01,-(%sp) # save Y on stack
7743 lea (%sp),%a0 # pass ptr to Y
7744 clr.l %d0
7745 bsr setoxm1 # FP0 IS Z = EXPM1(Y)
7746 add.l &0xc,%sp # clear Y from stack
7747 fmov.l &0,%fpcr
7748 movm.l (%sp)+,&0x0201 # {a1/d0}
7749
7750 fmov.x %fp0,%fp1
7751 fadd.s &0x3F800000,%fp1 # 1+Z
7752 fmov.x %fp0,-(%sp)
7753 fdiv.x %fp1,%fp0 # Z/(1+Z)
7754 mov.l %a1,%d1
7755 and.l &0x80000000,%d1
7756 or.l &0x3F000000,%d1
7757 fadd.x (%sp)+,%fp0
7758 mov.l %d1,-(%sp)
7759
7760 fmov.l %d0,%fpcr
7761 mov.b &FMUL_OP,%d1 # last inst is MUL
7762 fmul.s (%sp)+,%fp0 # last fp inst - possible exceptions set
7763 bra t_catch
7764
7765SINHBIG:
7766 cmp.l %d1,&0x400CB2B3
7767 bgt t_ovfl
7768 fabs.x %fp0
7769 fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
7770 mov.l &0,-(%sp)
7771 mov.l &0x80000000,-(%sp)
7772 mov.l %a1,%d1
7773 and.l &0x80000000,%d1
7774 or.l &0x7FFB0000,%d1
7775 mov.l %d1,-(%sp) # EXTENDED FMT
7776 fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
7777
7778 mov.l %d0,-(%sp)
7779 clr.l %d0
7780 fmovm.x &0x01,-(%sp) # save fp0 on stack
7781 lea (%sp),%a0 # pass ptr to fp0
7782 bsr setox
7783 add.l &0xc,%sp # clear fp0 from stack
7784
7785 mov.l (%sp)+,%d0
7786 fmov.l %d0,%fpcr
7787 mov.b &FMUL_OP,%d1 # last inst is MUL
7788 fmul.x (%sp)+,%fp0 # possible exception
7789 bra t_catch
7790
7791 global ssinhd
7792#--SINH(X) = X FOR DENORMALIZED X
7793ssinhd:
7794 bra t_extdnrm
7795
7796#########################################################################
7797# stanh(): computes the hyperbolic tangent of a normalized input #
7798# stanhd(): computes the hyperbolic tangent of a denormalized input #
7799# #
7800# INPUT *************************************************************** #
7801# a0 = pointer to extended precision input #
7802# d0 = round precision,mode #
7803# #
7804# OUTPUT ************************************************************** #
7805# fp0 = tanh(X) #
7806# #
7807# ACCURACY and MONOTONICITY ******************************************* #
7808# The returned result is within 3 ulps in 64 significant bit, #
7809# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7810# rounded to double precision. The result is provably monotonic #
7811# in double precision. #
7812# #
7813# ALGORITHM *********************************************************** #
7814# #
7815# TANH #
7816# 1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3. #
7817# #
7818# 2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by #
7819# sgn := sign(X), y := 2|X|, z := expm1(Y), and #
7820# tanh(X) = sgn*( z/(2+z) ). #
7821# Exit. #
7822# #
7823# 3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1, #
7824# go to 7. #
7825# #
7826# 4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6. #
7827# #
7828# 5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by #
7829# sgn := sign(X), y := 2|X|, z := exp(Y), #
7830# tanh(X) = sgn - [ sgn*2/(1+z) ]. #
7831# Exit. #
7832# #
7833# 6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we #
7834# calculate Tanh(X) by #
7835# sgn := sign(X), Tiny := 2**(-126), #
7836# tanh(X) := sgn - sgn*Tiny. #
7837# Exit. #
7838# #
7839# 7. (|X| < 2**(-40)). Tanh(X) = X. Exit. #
7840# #
7841#########################################################################
7842
7843 set X,FP_SCR0
7844 set XFRAC,X+4
7845
7846 set SGN,L_SCR3
7847
7848 set V,FP_SCR0
7849
7850 global stanh
7851stanh:
7852 fmov.x (%a0),%fp0 # LOAD INPUT
7853
7854 fmov.x %fp0,X(%a6)
7855 mov.l (%a0),%d1
7856 mov.w 4(%a0),%d1
7857 mov.l %d1,X(%a6)
7858 and.l &0x7FFFFFFF,%d1
7859 cmp.l %d1, &0x3fd78000 # is |X| < 2^(-40)?
7860 blt.w TANHBORS # yes
7861 cmp.l %d1, &0x3fffddce # is |X| > (5/2)LOG2?
7862 bgt.w TANHBORS # yes
7863
7864#--THIS IS THE USUAL CASE
7865#--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
7866
7867 mov.l X(%a6),%d1
7868 mov.l %d1,SGN(%a6)
7869 and.l &0x7FFF0000,%d1
7870 add.l &0x00010000,%d1 # EXPONENT OF 2|X|
7871 mov.l %d1,X(%a6)
7872 and.l &0x80000000,SGN(%a6)
7873 fmov.x X(%a6),%fp0 # FP0 IS Y = 2|X|
7874
7875 mov.l %d0,-(%sp)
7876 clr.l %d0
7877 fmovm.x &0x1,-(%sp) # save Y on stack
7878 lea (%sp),%a0 # pass ptr to Y
7879 bsr setoxm1 # FP0 IS Z = EXPM1(Y)
7880 add.l &0xc,%sp # clear Y from stack
7881 mov.l (%sp)+,%d0
7882
7883 fmov.x %fp0,%fp1
7884 fadd.s &0x40000000,%fp1 # Z+2
7885 mov.l SGN(%a6),%d1
7886 fmov.x %fp1,V(%a6)
7887 eor.l %d1,V(%a6)
7888
7889 fmov.l %d0,%fpcr # restore users round prec,mode
7890 fdiv.x V(%a6),%fp0
7891 bra t_inx2
7892
7893TANHBORS:
7894 cmp.l %d1,&0x3FFF8000
7895 blt.w TANHSM
7896
7897 cmp.l %d1,&0x40048AA1
7898 bgt.w TANHHUGE
7899
7900#-- (5/2) LOG2 < |X| < 50 LOG2,
7901#--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
7902#--TANH(X) = SGN - SGN*2/[EXP(Y)+1].
7903
7904 mov.l X(%a6),%d1
7905 mov.l %d1,SGN(%a6)
7906 and.l &0x7FFF0000,%d1
7907 add.l &0x00010000,%d1 # EXPO OF 2|X|
7908 mov.l %d1,X(%a6) # Y = 2|X|
7909 and.l &0x80000000,SGN(%a6)
7910 mov.l SGN(%a6),%d1
7911 fmov.x X(%a6),%fp0 # Y = 2|X|
7912
7913 mov.l %d0,-(%sp)
7914 clr.l %d0
7915 fmovm.x &0x01,-(%sp) # save Y on stack
7916 lea (%sp),%a0 # pass ptr to Y
7917 bsr setox # FP0 IS EXP(Y)
7918 add.l &0xc,%sp # clear Y from stack
7919 mov.l (%sp)+,%d0
7920 mov.l SGN(%a6),%d1
7921 fadd.s &0x3F800000,%fp0 # EXP(Y)+1
7922
7923 eor.l &0xC0000000,%d1 # -SIGN(X)*2
7924 fmov.s %d1,%fp1 # -SIGN(X)*2 IN SGL FMT
7925 fdiv.x %fp0,%fp1 # -SIGN(X)2 / [EXP(Y)+1 ]
7926
7927 mov.l SGN(%a6),%d1
7928 or.l &0x3F800000,%d1 # SGN
7929 fmov.s %d1,%fp0 # SGN IN SGL FMT
7930
7931 fmov.l %d0,%fpcr # restore users round prec,mode
7932 mov.b &FADD_OP,%d1 # last inst is ADD
7933 fadd.x %fp1,%fp0
7934 bra t_inx2
7935
7936TANHSM:
7937 fmov.l %d0,%fpcr # restore users round prec,mode
7938 mov.b &FMOV_OP,%d1 # last inst is MOVE
7939 fmov.x X(%a6),%fp0 # last inst - possible exception set
7940 bra t_catch
7941
7942#---RETURN SGN(X) - SGN(X)EPS
7943TANHHUGE:
7944 mov.l X(%a6),%d1
7945 and.l &0x80000000,%d1
7946 or.l &0x3F800000,%d1
7947 fmov.s %d1,%fp0
7948 and.l &0x80000000,%d1
7949 eor.l &0x80800000,%d1 # -SIGN(X)*EPS
7950
7951 fmov.l %d0,%fpcr # restore users round prec,mode
7952 fadd.s %d1,%fp0
7953 bra t_inx2
7954
7955 global stanhd
7956#--TANH(X) = X FOR DENORMALIZED X
7957stanhd:
7958 bra t_extdnrm
7959
7960#########################################################################
7961# slogn(): computes the natural logarithm of a normalized input #
7962# slognd(): computes the natural logarithm of a denormalized input #
7963# slognp1(): computes the log(1+X) of a normalized input #
7964# slognp1d(): computes the log(1+X) of a denormalized input #
7965# #
7966# INPUT *************************************************************** #
7967# a0 = pointer to extended precision input #
7968# d0 = round precision,mode #
7969# #
7970# OUTPUT ************************************************************** #
7971# fp0 = log(X) or log(1+X) #
7972# #
7973# ACCURACY and MONOTONICITY ******************************************* #
7974# The returned result is within 2 ulps in 64 significant bit, #
7975# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7976# rounded to double precision. The result is provably monotonic #
7977# in double precision. #
7978# #
7979# ALGORITHM *********************************************************** #
7980# LOGN: #
7981# Step 1. If |X-1| < 1/16, approximate log(X) by an odd #
7982# polynomial in u, where u = 2(X-1)/(X+1). Otherwise, #
7983# move on to Step 2. #
7984# #
7985# Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #
7986# seven significant bits of Y plus 2**(-7), i.e. #
7987# F = 1.xxxxxx1 in base 2 where the six "x" match those #
7988# of Y. Note that |Y-F| <= 2**(-7). #
7989# #
7990# Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a #
7991# polynomial in u, log(1+u) = poly. #
7992# #
7993# Step 4. Reconstruct #
7994# log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #
7995# by k*log(2) + (log(F) + poly). The values of log(F) are #
7996# calculated beforehand and stored in the program. #
7997# #
7998# lognp1: #
7999# Step 1: If |X| < 1/16, approximate log(1+X) by an odd #
8000# polynomial in u where u = 2X/(2+X). Otherwise, move on #
8001# to Step 2. #
8002# #
8003# Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done #
8004# in Step 2 of the algorithm for LOGN and compute #
8005# log(1+X) as k*log(2) + log(F) + poly where poly #
8006# approximates log(1+u), u = (Y-F)/F. #
8007# #
8008# Implementation Notes: #
8009# Note 1. There are 64 different possible values for F, thus 64 #
8010# log(F)'s need to be tabulated. Moreover, the values of #
8011# 1/F are also tabulated so that the division in (Y-F)/F #
8012# can be performed by a multiplication. #
8013# #
8014# Note 2. In Step 2 of lognp1, in order to preserved accuracy, #
8015# the value Y-F has to be calculated carefully when #
8016# 1/2 <= X < 3/2. #
8017# #
8018# Note 3. To fully exploit the pipeline, polynomials are usually #
8019# separated into two parts evaluated independently before #
8020# being added up. #
8021# #
8022#########################################################################
8023LOGOF2:
8024 long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8025
8026one:
8027 long 0x3F800000
8028zero:
8029 long 0x00000000
8030infty:
8031 long 0x7F800000
8032negone:
8033 long 0xBF800000
8034
8035LOGA6:
8036 long 0x3FC2499A,0xB5E4040B
8037LOGA5:
8038 long 0xBFC555B5,0x848CB7DB
8039
8040LOGA4:
8041 long 0x3FC99999,0x987D8730
8042LOGA3:
8043 long 0xBFCFFFFF,0xFF6F7E97
8044
8045LOGA2:
8046 long 0x3FD55555,0x555555A4
8047LOGA1:
8048 long 0xBFE00000,0x00000008
8049
8050LOGB5:
8051 long 0x3F175496,0xADD7DAD6
8052LOGB4:
8053 long 0x3F3C71C2,0xFE80C7E0
8054
8055LOGB3:
8056 long 0x3F624924,0x928BCCFF
8057LOGB2:
8058 long 0x3F899999,0x999995EC
8059
8060LOGB1:
8061 long 0x3FB55555,0x55555555
8062TWO:
8063 long 0x40000000,0x00000000
8064
8065LTHOLD:
8066 long 0x3f990000,0x80000000,0x00000000,0x00000000
8067
8068LOGTBL:
8069 long 0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
8070 long 0x3FF70000,0xFF015358,0x833C47E2,0x00000000
8071 long 0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
8072 long 0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
8073 long 0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
8074 long 0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
8075 long 0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
8076 long 0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
8077 long 0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
8078 long 0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
8079 long 0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
8080 long 0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
8081 long 0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
8082 long 0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
8083 long 0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
8084 long 0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
8085 long 0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
8086 long 0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
8087 long 0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
8088 long 0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
8089 long 0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
8090 long 0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
8091 long 0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
8092 long 0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
8093 long 0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
8094 long 0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
8095 long 0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
8096 long 0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
8097 long 0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
8098 long 0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
8099 long 0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
8100 long 0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
8101 long 0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
8102 long 0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
8103 long 0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
8104 long 0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
8105 long 0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
8106 long 0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
8107 long 0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
8108 long 0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
8109 long 0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
8110 long 0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
8111 long 0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
8112 long 0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
8113 long 0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
8114 long 0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
8115 long 0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
8116 long 0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
8117 long 0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
8118 long 0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
8119 long 0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
8120 long 0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
8121 long 0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
8122 long 0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
8123 long 0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
8124 long 0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
8125 long 0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
8126 long 0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
8127 long 0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
8128 long 0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
8129 long 0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
8130 long 0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
8131 long 0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
8132 long 0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
8133 long 0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
8134 long 0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
8135 long 0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
8136 long 0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
8137 long 0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
8138 long 0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
8139 long 0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
8140 long 0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
8141 long 0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
8142 long 0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
8143 long 0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
8144 long 0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
8145 long 0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
8146 long 0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
8147 long 0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
8148 long 0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
8149 long 0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
8150 long 0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
8151 long 0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
8152 long 0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
8153 long 0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
8154 long 0x3FFE0000,0x825EFCED,0x49369330,0x00000000
8155 long 0x3FFE0000,0x9868C809,0x868C8098,0x00000000
8156 long 0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
8157 long 0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
8158 long 0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
8159 long 0x3FFE0000,0x95A02568,0x095A0257,0x00000000
8160 long 0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
8161 long 0x3FFE0000,0x94458094,0x45809446,0x00000000
8162 long 0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
8163 long 0x3FFE0000,0x92F11384,0x0497889C,0x00000000
8164 long 0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
8165 long 0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
8166 long 0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
8167 long 0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
8168 long 0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
8169 long 0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
8170 long 0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
8171 long 0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
8172 long 0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
8173 long 0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
8174 long 0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
8175 long 0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
8176 long 0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
8177 long 0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
8178 long 0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
8179 long 0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
8180 long 0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
8181 long 0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
8182 long 0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
8183 long 0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
8184 long 0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
8185 long 0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
8186 long 0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
8187 long 0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
8188 long 0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
8189 long 0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
8190 long 0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
8191 long 0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
8192 long 0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
8193 long 0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
8194 long 0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
8195 long 0x3FFE0000,0x80808080,0x80808081,0x00000000
8196 long 0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
8197
8198 set ADJK,L_SCR1
8199
8200 set X,FP_SCR0
8201 set XDCARE,X+2
8202 set XFRAC,X+4
8203
8204 set F,FP_SCR1
8205 set FFRAC,F+4
8206
8207 set KLOG2,FP_SCR0
8208
8209 set SAVEU,FP_SCR0
8210
8211 global slogn
8212#--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
8213slogn:
8214 fmov.x (%a0),%fp0 # LOAD INPUT
8215 mov.l &0x00000000,ADJK(%a6)
8216
8217LOGBGN:
8218#--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
8219#--A FINITE, NON-ZERO, NORMALIZED NUMBER.
8220
8221 mov.l (%a0),%d1
8222 mov.w 4(%a0),%d1
8223
8224 mov.l (%a0),X(%a6)
8225 mov.l 4(%a0),X+4(%a6)
8226 mov.l 8(%a0),X+8(%a6)
8227
8228 cmp.l %d1,&0 # CHECK IF X IS NEGATIVE
8229 blt.w LOGNEG # LOG OF NEGATIVE ARGUMENT IS INVALID
8230# X IS POSITIVE, CHECK IF X IS NEAR 1
8231 cmp.l %d1,&0x3ffef07d # IS X < 15/16?
8232 blt.b LOGMAIN # YES
8233 cmp.l %d1,&0x3fff8841 # IS X > 17/16?
8234 ble.w LOGNEAR1 # NO
8235
8236LOGMAIN:
8237#--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
8238
8239#--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
8240#--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
8241#--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
8242#-- = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
8243#--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
8244#--LOG(1+U) CAN BE VERY EFFICIENT.
8245#--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
8246#--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
8247
8248#--GET K, Y, F, AND ADDRESS OF 1/F.
8249 asr.l &8,%d1
8250 asr.l &8,%d1 # SHIFTED 16 BITS, BIASED EXPO. OF X
8251 sub.l &0x3FFF,%d1 # THIS IS K
8252 add.l ADJK(%a6),%d1 # ADJUST K, ORIGINAL INPUT MAY BE DENORM.
8253 lea LOGTBL(%pc),%a0 # BASE ADDRESS OF 1/F AND LOG(F)
8254 fmov.l %d1,%fp1 # CONVERT K TO FLOATING-POINT FORMAT
8255
8256#--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
8257 mov.l &0x3FFF0000,X(%a6) # X IS NOW Y, I.E. 2^(-K)*X
8258 mov.l XFRAC(%a6),FFRAC(%a6)
8259 and.l &0xFE000000,FFRAC(%a6) # FIRST 7 BITS OF Y
8260 or.l &0x01000000,FFRAC(%a6) # GET F: ATTACH A 1 AT THE EIGHTH BIT
8261 mov.l FFRAC(%a6),%d1 # READY TO GET ADDRESS OF 1/F
8262 and.l &0x7E000000,%d1
8263 asr.l &8,%d1
8264 asr.l &8,%d1
8265 asr.l &4,%d1 # SHIFTED 20, D0 IS THE DISPLACEMENT
8266 add.l %d1,%a0 # A0 IS THE ADDRESS FOR 1/F
8267
8268 fmov.x X(%a6),%fp0
8269 mov.l &0x3fff0000,F(%a6)
8270 clr.l F+8(%a6)
8271 fsub.x F(%a6),%fp0 # Y-F
8272 fmovm.x &0xc,-(%sp) # SAVE FP2-3 WHILE FP0 IS NOT READY
8273#--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
8274#--REGISTERS SAVED: FPCR, FP1, FP2
8275
8276LP1CONT1:
8277#--AN RE-ENTRY POINT FOR LOGNP1
8278 fmul.x (%a0),%fp0 # FP0 IS U = (Y-F)/F
8279 fmul.x LOGOF2(%pc),%fp1 # GET K*LOG2 WHILE FP0 IS NOT READY
8280 fmov.x %fp0,%fp2
8281 fmul.x %fp2,%fp2 # FP2 IS V=U*U
8282 fmov.x %fp1,KLOG2(%a6) # PUT K*LOG2 IN MEMEORY, FREE FP1
8283
8284#--LOG(1+U) IS APPROXIMATED BY
8285#--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
8286#--[U + V*(A1+V*(A3+V*A5))] + [U*V*(A2+V*(A4+V*A6))]
8287
8288 fmov.x %fp2,%fp3
8289 fmov.x %fp2,%fp1
8290
8291 fmul.d LOGA6(%pc),%fp1 # V*A6
8292 fmul.d LOGA5(%pc),%fp2 # V*A5
8293
8294 fadd.d LOGA4(%pc),%fp1 # A4+V*A6
8295 fadd.d LOGA3(%pc),%fp2 # A3+V*A5
8296
8297 fmul.x %fp3,%fp1 # V*(A4+V*A6)
8298 fmul.x %fp3,%fp2 # V*(A3+V*A5)
8299
8300 fadd.d LOGA2(%pc),%fp1 # A2+V*(A4+V*A6)
8301 fadd.d LOGA1(%pc),%fp2 # A1+V*(A3+V*A5)
8302
8303 fmul.x %fp3,%fp1 # V*(A2+V*(A4+V*A6))
8304 add.l &16,%a0 # ADDRESS OF LOG(F)
8305 fmul.x %fp3,%fp2 # V*(A1+V*(A3+V*A5))
8306
8307 fmul.x %fp0,%fp1 # U*V*(A2+V*(A4+V*A6))
8308 fadd.x %fp2,%fp0 # U+V*(A1+V*(A3+V*A5))
8309
8310 fadd.x (%a0),%fp1 # LOG(F)+U*V*(A2+V*(A4+V*A6))
8311 fmovm.x (%sp)+,&0x30 # RESTORE FP2-3
8312 fadd.x %fp1,%fp0 # FP0 IS LOG(F) + LOG(1+U)
8313
8314 fmov.l %d0,%fpcr
8315 fadd.x KLOG2(%a6),%fp0 # FINAL ADD
8316 bra t_inx2
8317
8318
8319LOGNEAR1:
8320
8321# if the input is exactly equal to one, then exit through ld_pzero.
8322# if these 2 lines weren't here, the correct answer would be returned
8323# but the INEX2 bit would be set.
8324 fcmp.b %fp0,&0x1 # is it equal to one?
8325 fbeq.l ld_pzero # yes
8326
8327#--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
8328 fmov.x %fp0,%fp1
8329 fsub.s one(%pc),%fp1 # FP1 IS X-1
8330 fadd.s one(%pc),%fp0 # FP0 IS X+1
8331 fadd.x %fp1,%fp1 # FP1 IS 2(X-1)
8332#--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
8333#--IN U, U = 2(X-1)/(X+1) = FP1/FP0
8334
8335LP1CONT2:
8336#--THIS IS AN RE-ENTRY POINT FOR LOGNP1
8337 fdiv.x %fp0,%fp1 # FP1 IS U
8338 fmovm.x &0xc,-(%sp) # SAVE FP2-3
8339#--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
8340#--LET V=U*U, W=V*V, CALCULATE
8341#--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
8342#--U + U*V*( [B1 + W*(B3 + W*B5)] + [V*(B2 + W*B4)] )
8343 fmov.x %fp1,%fp0
8344 fmul.x %fp0,%fp0 # FP0 IS V
8345 fmov.x %fp1,SAVEU(%a6) # STORE U IN MEMORY, FREE FP1
8346 fmov.x %fp0,%fp1
8347 fmul.x %fp1,%fp1 # FP1 IS W
8348
8349 fmov.d LOGB5(%pc),%fp3
8350 fmov.d LOGB4(%pc),%fp2
8351
8352 fmul.x %fp1,%fp3 # W*B5
8353 fmul.x %fp1,%fp2 # W*B4
8354
8355 fadd.d LOGB3(%pc),%fp3 # B3+W*B5
8356 fadd.d LOGB2(%pc),%fp2 # B2+W*B4
8357
8358 fmul.x %fp3,%fp1 # W*(B3+W*B5), FP3 RELEASED
8359
8360 fmul.x %fp0,%fp2 # V*(B2+W*B4)
8361
8362 fadd.d LOGB1(%pc),%fp1 # B1+W*(B3+W*B5)
8363 fmul.x SAVEU(%a6),%fp0 # FP0 IS U*V
8364
8365 fadd.x %fp2,%fp1 # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
8366 fmovm.x (%sp)+,&0x30 # FP2-3 RESTORED
8367
8368 fmul.x %fp1,%fp0 # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
8369
8370 fmov.l %d0,%fpcr
8371 fadd.x SAVEU(%a6),%fp0
8372 bra t_inx2
8373
8374#--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
8375LOGNEG:
8376 bra t_operr
8377
8378 global slognd
8379slognd:
8380#--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
8381
8382 mov.l &-100,ADJK(%a6) # INPUT = 2^(ADJK) * FP0
8383
8384#----normalize the input value by left shifting k bits (k to be determined
8385#----below), adjusting exponent and storing -k to ADJK
8386#----the value TWOTO100 is no longer needed.
8387#----Note that this code assumes the denormalized input is NON-ZERO.
8388
8389 movm.l &0x3f00,-(%sp) # save some registers {d2-d7}
8390 mov.l (%a0),%d3 # D3 is exponent of smallest norm. #
8391 mov.l 4(%a0),%d4
8392 mov.l 8(%a0),%d5 # (D4,D5) is (Hi_X,Lo_X)
8393 clr.l %d2 # D2 used for holding K
8394
8395 tst.l %d4
8396 bne.b Hi_not0
8397
8398Hi_0:
8399 mov.l %d5,%d4
8400 clr.l %d5
8401 mov.l &32,%d2
8402 clr.l %d6
8403 bfffo %d4{&0:&32},%d6
8404 lsl.l %d6,%d4
8405 add.l %d6,%d2 # (D3,D4,D5) is normalized
8406
8407 mov.l %d3,X(%a6)
8408 mov.l %d4,XFRAC(%a6)
8409 mov.l %d5,XFRAC+4(%a6)
8410 neg.l %d2
8411 mov.l %d2,ADJK(%a6)
8412 fmov.x X(%a6),%fp0
8413 movm.l (%sp)+,&0xfc # restore registers {d2-d7}
8414 lea X(%a6),%a0
8415 bra.w LOGBGN # begin regular log(X)
8416
8417Hi_not0:
8418 clr.l %d6
8419 bfffo %d4{&0:&32},%d6 # find first 1
8420 mov.l %d6,%d2 # get k
8421 lsl.l %d6,%d4
8422 mov.l %d5,%d7 # a copy of D5
8423 lsl.l %d6,%d5
8424 neg.l %d6
8425 add.l &32,%d6
8426 lsr.l %d6,%d7
8427 or.l %d7,%d4 # (D3,D4,D5) normalized
8428
8429 mov.l %d3,X(%a6)
8430 mov.l %d4,XFRAC(%a6)
8431 mov.l %d5,XFRAC+4(%a6)
8432 neg.l %d2
8433 mov.l %d2,ADJK(%a6)
8434 fmov.x X(%a6),%fp0
8435 movm.l (%sp)+,&0xfc # restore registers {d2-d7}
8436 lea X(%a6),%a0
8437 bra.w LOGBGN # begin regular log(X)
8438
8439 global slognp1
8440#--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
8441slognp1:
8442 fmov.x (%a0),%fp0 # LOAD INPUT
8443 fabs.x %fp0 # test magnitude
8444 fcmp.x %fp0,LTHOLD(%pc) # compare with min threshold
8445 fbgt.w LP1REAL # if greater, continue
8446 fmov.l %d0,%fpcr
8447 mov.b &FMOV_OP,%d1 # last inst is MOVE
8448 fmov.x (%a0),%fp0 # return signed argument
8449 bra t_catch
8450
8451LP1REAL:
8452 fmov.x (%a0),%fp0 # LOAD INPUT
8453 mov.l &0x00000000,ADJK(%a6)
8454 fmov.x %fp0,%fp1 # FP1 IS INPUT Z
8455 fadd.s one(%pc),%fp0 # X := ROUND(1+Z)
8456 fmov.x %fp0,X(%a6)
8457 mov.w XFRAC(%a6),XDCARE(%a6)
8458 mov.l X(%a6),%d1
8459 cmp.l %d1,&0
8460 ble.w LP1NEG0 # LOG OF ZERO OR -VE
8461 cmp.l %d1,&0x3ffe8000 # IS BOUNDS [1/2,3/2]?
8462 blt.w LOGMAIN
8463 cmp.l %d1,&0x3fffc000
8464 bgt.w LOGMAIN
8465#--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
8466#--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
8467#--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
8468
8469LP1NEAR1:
8470#--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
8471 cmp.l %d1,&0x3ffef07d
8472 blt.w LP1CARE
8473 cmp.l %d1,&0x3fff8841
8474 bgt.w LP1CARE
8475
8476LP1ONE16:
8477#--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
8478#--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
8479 fadd.x %fp1,%fp1 # FP1 IS 2Z
8480 fadd.s one(%pc),%fp0 # FP0 IS 1+X
8481#--U = FP1/FP0
8482 bra.w LP1CONT2
8483
8484LP1CARE:
8485#--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
8486#--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
8487#--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
8488#--THERE ARE ONLY TWO CASES.
8489#--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
8490#--CASE 2: 1+Z > 1, THEN K = 0 AND Y-F = (1-F) + Z
8491#--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
8492#--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
8493
8494 mov.l XFRAC(%a6),FFRAC(%a6)
8495 and.l &0xFE000000,FFRAC(%a6)
8496 or.l &0x01000000,FFRAC(%a6) # F OBTAINED
8497 cmp.l %d1,&0x3FFF8000 # SEE IF 1+Z > 1
8498 bge.b KISZERO
8499
8500KISNEG1:
8501 fmov.s TWO(%pc),%fp0
8502 mov.l &0x3fff0000,F(%a6)
8503 clr.l F+8(%a6)
8504 fsub.x F(%a6),%fp0 # 2-F
8505 mov.l FFRAC(%a6),%d1
8506 and.l &0x7E000000,%d1
8507 asr.l &8,%d1
8508 asr.l &8,%d1
8509 asr.l &4,%d1 # D0 CONTAINS DISPLACEMENT FOR 1/F
8510 fadd.x %fp1,%fp1 # GET 2Z
8511 fmovm.x &0xc,-(%sp) # SAVE FP2 {%fp2/%fp3}
8512 fadd.x %fp1,%fp0 # FP0 IS Y-F = (2-F)+2Z
8513 lea LOGTBL(%pc),%a0 # A0 IS ADDRESS OF 1/F
8514 add.l %d1,%a0
8515 fmov.s negone(%pc),%fp1 # FP1 IS K = -1
8516 bra.w LP1CONT1
8517
8518KISZERO:
8519 fmov.s one(%pc),%fp0
8520 mov.l &0x3fff0000,F(%a6)
8521 clr.l F+8(%a6)
8522 fsub.x F(%a6),%fp0 # 1-F
8523 mov.l FFRAC(%a6),%d1
8524 and.l &0x7E000000,%d1
8525 asr.l &8,%d1
8526 asr.l &8,%d1
8527 asr.l &4,%d1
8528 fadd.x %fp1,%fp0 # FP0 IS Y-F
8529 fmovm.x &0xc,-(%sp) # FP2 SAVED {%fp2/%fp3}
8530 lea LOGTBL(%pc),%a0
8531 add.l %d1,%a0 # A0 IS ADDRESS OF 1/F
8532 fmov.s zero(%pc),%fp1 # FP1 IS K = 0
8533 bra.w LP1CONT1
8534
8535LP1NEG0:
8536#--FPCR SAVED. D0 IS X IN COMPACT FORM.
8537 cmp.l %d1,&0
8538 blt.b LP1NEG
8539LP1ZERO:
8540 fmov.s negone(%pc),%fp0
8541
8542 fmov.l %d0,%fpcr
8543 bra t_dz
8544
8545LP1NEG:
8546 fmov.s zero(%pc),%fp0
8547
8548 fmov.l %d0,%fpcr
8549 bra t_operr
8550
8551 global slognp1d
8552#--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
8553# Simply return the denorm
8554slognp1d:
8555 bra t_extdnrm
8556
8557#########################################################################
8558# satanh(): computes the inverse hyperbolic tangent of a norm input #
8559# satanhd(): computes the inverse hyperbolic tangent of a denorm input #
8560# #
8561# INPUT *************************************************************** #
8562# a0 = pointer to extended precision input #
8563# d0 = round precision,mode #
8564# #
8565# OUTPUT ************************************************************** #
8566# fp0 = arctanh(X) #
8567# #
8568# ACCURACY and MONOTONICITY ******************************************* #
8569# The returned result is within 3 ulps in 64 significant bit, #
8570# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8571# rounded to double precision. The result is provably monotonic #
8572# in double precision. #
8573# #
8574# ALGORITHM *********************************************************** #
8575# #
8576# ATANH #
8577# 1. If |X| >= 1, go to 3. #
8578# #
8579# 2. (|X| < 1) Calculate atanh(X) by #
8580# sgn := sign(X) #
8581# y := |X| #
8582# z := 2y/(1-y) #
8583# atanh(X) := sgn * (1/2) * logp1(z) #
8584# Exit. #
8585# #
8586# 3. If |X| > 1, go to 5. #
8587# #
8588# 4. (|X| = 1) Generate infinity with an appropriate sign and #
8589# divide-by-zero by #
8590# sgn := sign(X) #
8591# atan(X) := sgn / (+0). #
8592# Exit. #
8593# #
8594# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
8595# Exit. #
8596# #
8597#########################################################################
8598
8599 global satanh
8600satanh:
8601 mov.l (%a0),%d1
8602 mov.w 4(%a0),%d1
8603 and.l &0x7FFFFFFF,%d1
8604 cmp.l %d1,&0x3FFF8000
8605 bge.b ATANHBIG
8606
8607#--THIS IS THE USUAL CASE, |X| < 1
8608#--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
8609
8610 fabs.x (%a0),%fp0 # Y = |X|
8611 fmov.x %fp0,%fp1
8612 fneg.x %fp1 # -Y
8613 fadd.x %fp0,%fp0 # 2Y
8614 fadd.s &0x3F800000,%fp1 # 1-Y
8615 fdiv.x %fp1,%fp0 # 2Y/(1-Y)
8616 mov.l (%a0),%d1
8617 and.l &0x80000000,%d1
8618 or.l &0x3F000000,%d1 # SIGN(X)*HALF
8619 mov.l %d1,-(%sp)
8620
8621 mov.l %d0,-(%sp) # save rnd prec,mode
8622 clr.l %d0 # pass ext prec,RN
8623 fmovm.x &0x01,-(%sp) # save Z on stack
8624 lea (%sp),%a0 # pass ptr to Z
8625 bsr slognp1 # LOG1P(Z)
8626 add.l &0xc,%sp # clear Z from stack
8627
8628 mov.l (%sp)+,%d0 # fetch old prec,mode
8629 fmov.l %d0,%fpcr # load it
8630 mov.b &FMUL_OP,%d1 # last inst is MUL
8631 fmul.s (%sp)+,%fp0
8632 bra t_catch
8633
8634ATANHBIG:
8635 fabs.x (%a0),%fp0 # |X|
8636 fcmp.s %fp0,&0x3F800000
8637 fbgt t_operr
8638 bra t_dz
8639
8640 global satanhd
8641#--ATANH(X) = X FOR DENORMALIZED X
8642satanhd:
8643 bra t_extdnrm
8644
8645#########################################################################
8646# slog10(): computes the base-10 logarithm of a normalized input #
8647# slog10d(): computes the base-10 logarithm of a denormalized input #
8648# slog2(): computes the base-2 logarithm of a normalized input #
8649# slog2d(): computes the base-2 logarithm of a denormalized input #
8650# #
8651# INPUT *************************************************************** #
8652# a0 = pointer to extended precision input #
8653# d0 = round precision,mode #
8654# #
8655# OUTPUT ************************************************************** #
8656# fp0 = log_10(X) or log_2(X) #
8657# #
8658# ACCURACY and MONOTONICITY ******************************************* #
8659# The returned result is within 1.7 ulps in 64 significant bit, #
8660# i.e. within 0.5003 ulp to 53 bits if the result is subsequently #
8661# rounded to double precision. The result is provably monotonic #
8662# in double precision. #
8663# #
8664# ALGORITHM *********************************************************** #
8665# #
8666# slog10d: #
8667# #
8668# Step 0. If X < 0, create a NaN and raise the invalid operation #
8669# flag. Otherwise, save FPCR in D1; set FpCR to default. #
8670# Notes: Default means round-to-nearest mode, no floating-point #
8671# traps, and precision control = double extended. #
8672# #
8673# Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8674# Notes: Even if X is denormalized, log(X) is always normalized. #
8675# #
8676# Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
8677# 2.1 Restore the user FPCR #
8678# 2.2 Return ans := Y * INV_L10. #
8679# #
8680# slog10: #
8681# #
8682# Step 0. If X < 0, create a NaN and raise the invalid operation #
8683# flag. Otherwise, save FPCR in D1; set FpCR to default. #
8684# Notes: Default means round-to-nearest mode, no floating-point #
8685# traps, and precision control = double extended. #
8686# #
8687# Step 1. Call sLogN to obtain Y = log(X), the natural log of X. #
8688# #
8689# Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
8690# 2.1 Restore the user FPCR #
8691# 2.2 Return ans := Y * INV_L10. #
8692# #
8693# sLog2d: #
8694# #
8695# Step 0. If X < 0, create a NaN and raise the invalid operation #
8696# flag. Otherwise, save FPCR in D1; set FpCR to default. #
8697# Notes: Default means round-to-nearest mode, no floating-point #
8698# traps, and precision control = double extended. #
8699# #
8700# Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8701# Notes: Even if X is denormalized, log(X) is always normalized. #
8702# #
8703# Step 2. Compute log_10(X) = log(X) * (1/log(2)). #
8704# 2.1 Restore the user FPCR #
8705# 2.2 Return ans := Y * INV_L2. #
8706# #
8707# sLog2: #
8708# #
8709# Step 0. If X < 0, create a NaN and raise the invalid operation #
8710# flag. Otherwise, save FPCR in D1; set FpCR to default. #
8711# Notes: Default means round-to-nearest mode, no floating-point #
8712# traps, and precision control = double extended. #
8713# #
8714# Step 1. If X is not an integer power of two, i.e., X != 2^k, #
8715# go to Step 3. #
8716# #
8717# Step 2. Return k. #
8718# 2.1 Get integer k, X = 2^k. #
8719# 2.2 Restore the user FPCR. #
8720# 2.3 Return ans := convert-to-double-extended(k). #
8721# #
8722# Step 3. Call sLogN to obtain Y = log(X), the natural log of X. #
8723# #
8724# Step 4. Compute log_2(X) = log(X) * (1/log(2)). #
8725# 4.1 Restore the user FPCR #
8726# 4.2 Return ans := Y * INV_L2. #
8727# #
8728#########################################################################
8729
8730INV_L10:
8731 long 0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
8732
8733INV_L2:
8734 long 0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
8735
8736 global slog10
8737#--entry point for Log10(X), X is normalized
8738slog10:
8739 fmov.b &0x1,%fp0
8740 fcmp.x %fp0,(%a0) # if operand == 1,
8741 fbeq.l ld_pzero # return an EXACT zero
8742
8743 mov.l (%a0),%d1
8744 blt.w invalid
8745 mov.l %d0,-(%sp)
8746 clr.l %d0
8747 bsr slogn # log(X), X normal.
8748 fmov.l (%sp)+,%fpcr
8749 fmul.x INV_L10(%pc),%fp0
8750 bra t_inx2
8751
8752 global slog10d
8753#--entry point for Log10(X), X is denormalized
8754slog10d:
8755 mov.l (%a0),%d1
8756 blt.w invalid
8757 mov.l %d0,-(%sp)
8758 clr.l %d0
8759 bsr slognd # log(X), X denorm.
8760 fmov.l (%sp)+,%fpcr
8761 fmul.x INV_L10(%pc),%fp0
8762 bra t_minx2
8763
8764 global slog2
8765#--entry point for Log2(X), X is normalized
8766slog2:
8767 mov.l (%a0),%d1
8768 blt.w invalid
8769
8770 mov.l 8(%a0),%d1
8771 bne.b continue # X is not 2^k
8772
8773 mov.l 4(%a0),%d1
8774 and.l &0x7FFFFFFF,%d1
8775 bne.b continue
8776
8777#--X = 2^k.
8778 mov.w (%a0),%d1
8779 and.l &0x00007FFF,%d1
8780 sub.l &0x3FFF,%d1
8781 beq.l ld_pzero
8782 fmov.l %d0,%fpcr
8783 fmov.l %d1,%fp0
8784 bra t_inx2
8785
8786continue:
8787 mov.l %d0,-(%sp)
8788 clr.l %d0
8789 bsr slogn # log(X), X normal.
8790 fmov.l (%sp)+,%fpcr
8791 fmul.x INV_L2(%pc),%fp0
8792 bra t_inx2
8793
8794invalid:
8795 bra t_operr
8796
8797 global slog2d
8798#--entry point for Log2(X), X is denormalized
8799slog2d:
8800 mov.l (%a0),%d1
8801 blt.w invalid
8802 mov.l %d0,-(%sp)
8803 clr.l %d0
8804 bsr slognd # log(X), X denorm.
8805 fmov.l (%sp)+,%fpcr
8806 fmul.x INV_L2(%pc),%fp0
8807 bra t_minx2
8808
8809#########################################################################
8810# stwotox(): computes 2**X for a normalized input #
8811# stwotoxd(): computes 2**X for a denormalized input #
8812# stentox(): computes 10**X for a normalized input #
8813# stentoxd(): computes 10**X for a denormalized input #
8814# #
8815# INPUT *************************************************************** #
8816# a0 = pointer to extended precision input #
8817# d0 = round precision,mode #
8818# #
8819# OUTPUT ************************************************************** #
8820# fp0 = 2**X or 10**X #
8821# #
8822# ACCURACY and MONOTONICITY ******************************************* #
8823# The returned result is within 2 ulps in 64 significant bit, #
8824# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8825# rounded to double precision. The result is provably monotonic #
8826# in double precision. #
8827# #
8828# ALGORITHM *********************************************************** #
8829# #
8830# twotox #
8831# 1. If |X| > 16480, go to ExpBig. #
8832# #
8833# 2. If |X| < 2**(-70), go to ExpSm. #
8834# #
8835# 3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore #
8836# decompose N as #
8837# N = 64(M + M') + j, j = 0,1,2,...,63. #
8838# #
8839# 4. Overwrite r := r * log2. Then #
8840# 2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
8841# Go to expr to compute that expression. #
8842# #
8843# tentox #
8844# 1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig. #
8845# #
8846# 2. If |X| < 2**(-70), go to ExpSm. #
8847# #
8848# 3. Set y := X*log_2(10)*64 (base 2 log of 10). Set #
8849# N := round-to-int(y). Decompose N as #
8850# N = 64(M + M') + j, j = 0,1,2,...,63. #
8851# #
8852# 4. Define r as #
8853# r := ((X - N*L1)-N*L2) * L10 #
8854# where L1, L2 are the leading and trailing parts of #
8855# log_10(2)/64 and L10 is the natural log of 10. Then #
8856# 10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
8857# Go to expr to compute that expression. #
8858# #
8859# expr #
8860# 1. Fetch 2**(j/64) from table as Fact1 and Fact2. #
8861# #
8862# 2. Overwrite Fact1 and Fact2 by #
8863# Fact1 := 2**(M) * Fact1 #
8864# Fact2 := 2**(M) * Fact2 #
8865# Thus Fact1 + Fact2 = 2**(M) * 2**(j/64). #
8866# #
8867# 3. Calculate P where 1 + P approximates exp(r): #
8868# P = r + r*r*(A1+r*(A2+...+r*A5)). #
8869# #
8870# 4. Let AdjFact := 2**(M'). Return #
8871# AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ). #
8872# Exit. #
8873# #
8874# ExpBig #
8875# 1. Generate overflow by Huge * Huge if X > 0; otherwise, #
8876# generate underflow by Tiny * Tiny. #
8877# #
8878# ExpSm #
8879# 1. Return 1 + X. #
8880# #
8881#########################################################################
8882
8883L2TEN64:
8884 long 0x406A934F,0x0979A371 # 64LOG10/LOG2
8885L10TWO1:
8886 long 0x3F734413,0x509F8000 # LOG2/64LOG10
8887
8888L10TWO2:
8889 long 0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
8890
8891LOG10: long 0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
8892
8893LOG2: long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8894
8895EXPA5: long 0x3F56C16D,0x6F7BD0B2
8896EXPA4: long 0x3F811112,0x302C712C
8897EXPA3: long 0x3FA55555,0x55554CC1
8898EXPA2: long 0x3FC55555,0x55554A54
8899EXPA1: long 0x3FE00000,0x00000000,0x00000000,0x00000000
8900
8901TEXPTBL:
8902 long 0x3FFF0000,0x80000000,0x00000000,0x3F738000
8903 long 0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
8904 long 0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
8905 long 0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
8906 long 0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
8907 long 0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
8908 long 0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
8909 long 0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
8910 long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
8911 long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
8912 long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
8913 long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
8914 long 0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
8915 long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
8916 long 0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
8917 long 0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
8918 long 0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
8919 long 0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
8920 long 0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
8921 long 0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
8922 long 0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
8923 long 0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
8924 long 0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
8925 long 0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
8926 long 0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
8927 long 0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
8928 long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
8929 long 0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
8930 long 0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
8931 long 0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
8932 long 0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
8933 long 0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
8934 long 0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
8935 long 0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
8936 long 0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
8937 long 0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
8938 long 0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
8939 long 0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
8940 long 0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
8941 long 0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
8942 long 0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
8943 long 0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
8944 long 0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
8945 long 0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
8946 long 0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
8947 long 0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
8948 long 0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
8949 long 0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
8950 long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
8951 long 0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
8952 long 0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
8953 long 0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
8954 long 0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
8955 long 0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
8956 long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
8957 long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
8958 long 0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
8959 long 0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
8960 long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
8961 long 0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
8962 long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
8963 long 0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
8964 long 0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
8965 long 0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
8966
8967 set INT,L_SCR1
8968
8969 set X,FP_SCR0
8970 set XDCARE,X+2
8971 set XFRAC,X+4
8972
8973 set ADJFACT,FP_SCR0
8974
8975 set FACT1,FP_SCR0
8976 set FACT1HI,FACT1+4
8977 set FACT1LOW,FACT1+8
8978
8979 set FACT2,FP_SCR1
8980 set FACT2HI,FACT2+4
8981 set FACT2LOW,FACT2+8
8982
8983 global stwotox
8984#--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
8985stwotox:
8986 fmovm.x (%a0),&0x80 # LOAD INPUT
8987
8988 mov.l (%a0),%d1
8989 mov.w 4(%a0),%d1
8990 fmov.x %fp0,X(%a6)
8991 and.l &0x7FFFFFFF,%d1
8992
8993 cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
8994 bge.b TWOOK1
8995 bra.w EXPBORS
8996
8997TWOOK1:
8998 cmp.l %d1,&0x400D80C0 # |X| > 16480?
8999 ble.b TWOMAIN
9000 bra.w EXPBORS
9001
9002TWOMAIN:
9003#--USUAL CASE, 2^(-70) <= |X| <= 16480
9004
9005 fmov.x %fp0,%fp1
9006 fmul.s &0x42800000,%fp1 # 64 * X
9007 fmov.l %fp1,INT(%a6) # N = ROUND-TO-INT(64 X)
9008 mov.l %d2,-(%sp)
9009 lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
9010 fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
9011 mov.l INT(%a6),%d1
9012 mov.l %d1,%d2
9013 and.l &0x3F,%d1 # D0 IS J
9014 asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
9015 add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
9016 asr.l &6,%d2 # d2 IS L, N = 64L + J
9017 mov.l %d2,%d1
9018 asr.l &1,%d1 # D0 IS M
9019 sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
9020 add.l &0x3FFF,%d2
9021
9022#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9023#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9024#--ADJFACT = 2^(M').
9025#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9026
9027 fmovm.x &0x0c,-(%sp) # save fp2/fp3
9028
9029 fmul.s &0x3C800000,%fp1 # (1/64)*N
9030 mov.l (%a1)+,FACT1(%a6)
9031 mov.l (%a1)+,FACT1HI(%a6)
9032 mov.l (%a1)+,FACT1LOW(%a6)
9033 mov.w (%a1)+,FACT2(%a6)
9034
9035 fsub.x %fp1,%fp0 # X - (1/64)*INT(64 X)
9036
9037 mov.w (%a1)+,FACT2HI(%a6)
9038 clr.w FACT2HI+2(%a6)
9039 clr.l FACT2LOW(%a6)
9040 add.w %d1,FACT1(%a6)
9041 fmul.x LOG2(%pc),%fp0 # FP0 IS R
9042 add.w %d1,FACT2(%a6)
9043
9044 bra.w expr
9045
9046EXPBORS:
9047#--FPCR, D0 SAVED
9048 cmp.l %d1,&0x3FFF8000
9049 bgt.b TEXPBIG
9050
9051#--|X| IS SMALL, RETURN 1 + X
9052
9053 fmov.l %d0,%fpcr # restore users round prec,mode
9054 fadd.s &0x3F800000,%fp0 # RETURN 1 + X
9055 bra t_pinx2
9056
9057TEXPBIG:
9058#--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
9059#--REGISTERS SAVE SO FAR ARE FPCR AND D0
9060 mov.l X(%a6),%d1
9061 cmp.l %d1,&0
9062 blt.b EXPNEG
9063
9064 bra t_ovfl2 # t_ovfl expects positive value
9065
9066EXPNEG:
9067 bra t_unfl2 # t_unfl expects positive value
9068
9069 global stwotoxd
9070stwotoxd:
9071#--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
9072
9073 fmov.l %d0,%fpcr # set user's rounding mode/precision
9074 fmov.s &0x3F800000,%fp0 # RETURN 1 + X
9075 mov.l (%a0),%d1
9076 or.l &0x00800001,%d1
9077 fadd.s %d1,%fp0
9078 bra t_pinx2
9079
9080 global stentox
9081#--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
9082stentox:
9083 fmovm.x (%a0),&0x80 # LOAD INPUT
9084
9085 mov.l (%a0),%d1
9086 mov.w 4(%a0),%d1
9087 fmov.x %fp0,X(%a6)
9088 and.l &0x7FFFFFFF,%d1
9089
9090 cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
9091 bge.b TENOK1
9092 bra.w EXPBORS
9093
9094TENOK1:
9095 cmp.l %d1,&0x400B9B07 # |X| <= 16480*log2/log10 ?
9096 ble.b TENMAIN
9097 bra.w EXPBORS
9098
9099TENMAIN:
9100#--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
9101
9102 fmov.x %fp0,%fp1
9103 fmul.d L2TEN64(%pc),%fp1 # X*64*LOG10/LOG2
9104 fmov.l %fp1,INT(%a6) # N=INT(X*64*LOG10/LOG2)
9105 mov.l %d2,-(%sp)
9106 lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
9107 fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
9108 mov.l INT(%a6),%d1
9109 mov.l %d1,%d2
9110 and.l &0x3F,%d1 # D0 IS J
9111 asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
9112 add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
9113 asr.l &6,%d2 # d2 IS L, N = 64L + J
9114 mov.l %d2,%d1
9115 asr.l &1,%d1 # D0 IS M
9116 sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
9117 add.l &0x3FFF,%d2
9118
9119#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9120#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9121#--ADJFACT = 2^(M').
9122#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9123 fmovm.x &0x0c,-(%sp) # save fp2/fp3
9124
9125 fmov.x %fp1,%fp2
9126
9127 fmul.d L10TWO1(%pc),%fp1 # N*(LOG2/64LOG10)_LEAD
9128 mov.l (%a1)+,FACT1(%a6)
9129
9130 fmul.x L10TWO2(%pc),%fp2 # N*(LOG2/64LOG10)_TRAIL
9131
9132 mov.l (%a1)+,FACT1HI(%a6)
9133 mov.l (%a1)+,FACT1LOW(%a6)
9134 fsub.x %fp1,%fp0 # X - N L_LEAD
9135 mov.w (%a1)+,FACT2(%a6)
9136
9137 fsub.x %fp2,%fp0 # X - N L_TRAIL
9138
9139 mov.w (%a1)+,FACT2HI(%a6)
9140 clr.w FACT2HI+2(%a6)
9141 clr.l FACT2LOW(%a6)
9142
9143 fmul.x LOG10(%pc),%fp0 # FP0 IS R
9144 add.w %d1,FACT1(%a6)
9145 add.w %d1,FACT2(%a6)
9146
9147expr:
9148#--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
9149#--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
9150#--FP0 IS R. THE FOLLOWING CODE COMPUTES
9151#-- 2**(M'+M) * 2**(J/64) * EXP(R)
9152
9153 fmov.x %fp0,%fp1
9154 fmul.x %fp1,%fp1 # FP1 IS S = R*R
9155
9156 fmov.d EXPA5(%pc),%fp2 # FP2 IS A5
9157 fmov.d EXPA4(%pc),%fp3 # FP3 IS A4
9158
9159 fmul.x %fp1,%fp2 # FP2 IS S*A5
9160 fmul.x %fp1,%fp3 # FP3 IS S*A4
9161
9162 fadd.d EXPA3(%pc),%fp2 # FP2 IS A3+S*A5
9163 fadd.d EXPA2(%pc),%fp3 # FP3 IS A2+S*A4
9164
9165 fmul.x %fp1,%fp2 # FP2 IS S*(A3+S*A5)
9166 fmul.x %fp1,%fp3 # FP3 IS S*(A2+S*A4)
9167
9168 fadd.d EXPA1(%pc),%fp2 # FP2 IS A1+S*(A3+S*A5)
9169 fmul.x %fp0,%fp3 # FP3 IS R*S*(A2+S*A4)
9170
9171 fmul.x %fp1,%fp2 # FP2 IS S*(A1+S*(A3+S*A5))
9172 fadd.x %fp3,%fp0 # FP0 IS R+R*S*(A2+S*A4)
9173 fadd.x %fp2,%fp0 # FP0 IS EXP(R) - 1
9174
9175 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
9176
9177#--FINAL RECONSTRUCTION PROCESS
9178#--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1) - (1 OR 0)
9179
9180 fmul.x FACT1(%a6),%fp0
9181 fadd.x FACT2(%a6),%fp0
9182 fadd.x FACT1(%a6),%fp0
9183
9184 fmov.l %d0,%fpcr # restore users round prec,mode
9185 mov.w %d2,ADJFACT(%a6) # INSERT EXPONENT
9186 mov.l (%sp)+,%d2
9187 mov.l &0x80000000,ADJFACT+4(%a6)
9188 clr.l ADJFACT+8(%a6)
9189 mov.b &FMUL_OP,%d1 # last inst is MUL
9190 fmul.x ADJFACT(%a6),%fp0 # FINAL ADJUSTMENT
9191 bra t_catch
9192
9193 global stentoxd
9194stentoxd:
9195#--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
9196
9197 fmov.l %d0,%fpcr # set user's rounding mode/precision
9198 fmov.s &0x3F800000,%fp0 # RETURN 1 + X
9199 mov.l (%a0),%d1
9200 or.l &0x00800001,%d1
9201 fadd.s %d1,%fp0
9202 bra t_pinx2
9203
9204#########################################################################
9205# sscale(): computes the destination operand scaled by the source #
9206# operand. If the absoulute value of the source operand is #
9207# >= 2^14, an overflow or underflow is returned. #
9208# #
9209# INPUT *************************************************************** #
9210# a0 = pointer to double-extended source operand X #
9211# a1 = pointer to double-extended destination operand Y #
9212# #
9213# OUTPUT ************************************************************** #
9214# fp0 = scale(X,Y) #
9215# #
9216#########################################################################
9217
9218set SIGN, L_SCR1
9219
9220 global sscale
9221sscale:
9222 mov.l %d0,-(%sp) # store off ctrl bits for now
9223
9224 mov.w DST_EX(%a1),%d1 # get dst exponent
9225 smi.b SIGN(%a6) # use SIGN to hold dst sign
9226 andi.l &0x00007fff,%d1 # strip sign from dst exp
9227
9228 mov.w SRC_EX(%a0),%d0 # check src bounds
9229 andi.w &0x7fff,%d0 # clr src sign bit
9230 cmpi.w %d0,&0x3fff # is src ~ ZERO?
9231 blt.w src_small # yes
9232 cmpi.w %d0,&0x400c # no; is src too big?
9233 bgt.w src_out # yes
9234
9235#
9236# Source is within 2^14 range.
9237#
9238src_ok:
9239 fintrz.x SRC(%a0),%fp0 # calc int of src
9240 fmov.l %fp0,%d0 # int src to d0
9241# don't want any accrued bits from the fintrz showing up later since
9242# we may need to read the fpsr for the last fp op in t_catch2().
9243 fmov.l &0x0,%fpsr
9244
9245 tst.b DST_HI(%a1) # is dst denormalized?
9246 bmi.b sok_norm
9247
9248# the dst is a DENORM. normalize the DENORM and add the adjustment to
9249# the src value. then, jump to the norm part of the routine.
9250sok_dnrm:
9251 mov.l %d0,-(%sp) # save src for now
9252
9253 mov.w DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
9254 mov.l DST_HI(%a1),FP_SCR0_HI(%a6)
9255 mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
9256
9257 lea FP_SCR0(%a6),%a0 # pass ptr to DENORM
9258 bsr.l norm # normalize the DENORM
9259 neg.l %d0
9260 add.l (%sp)+,%d0 # add adjustment to src
9261
9262 fmovm.x FP_SCR0(%a6),&0x80 # load normalized DENORM
9263
9264 cmpi.w %d0,&-0x3fff # is the shft amt really low?
9265 bge.b sok_norm2 # thank goodness no
9266
9267# the multiply factor that we're trying to create should be a denorm
9268# for the multiply to work. therefore, we're going to actually do a
9269# multiply with a denorm which will cause an unimplemented data type
9270# exception to be put into the machine which will be caught and corrected
9271# later. we don't do this with the DENORMs above because this method
9272# is slower. but, don't fret, I don't see it being used much either.
9273 fmov.l (%sp)+,%fpcr # restore user fpcr
9274 mov.l &0x80000000,%d1 # load normalized mantissa
9275 subi.l &-0x3fff,%d0 # how many should we shift?
9276 neg.l %d0 # make it positive
9277 cmpi.b %d0,&0x20 # is it > 32?
9278 bge.b sok_dnrm_32 # yes
9279 lsr.l %d0,%d1 # no; bit stays in upper lw
9280 clr.l -(%sp) # insert zero low mantissa
9281 mov.l %d1,-(%sp) # insert new high mantissa
9282 clr.l -(%sp) # make zero exponent
9283 bra.b sok_norm_cont
9284sok_dnrm_32:
9285 subi.b &0x20,%d0 # get shift count
9286 lsr.l %d0,%d1 # make low mantissa longword
9287 mov.l %d1,-(%sp) # insert new low mantissa
9288 clr.l -(%sp) # insert zero high mantissa
9289 clr.l -(%sp) # make zero exponent
9290 bra.b sok_norm_cont
9291
9292# the src will force the dst to a DENORM value or worse. so, let's
9293# create an fp multiply that will create the result.
9294sok_norm:
9295 fmovm.x DST(%a1),&0x80 # load fp0 with normalized src
9296sok_norm2:
9297 fmov.l (%sp)+,%fpcr # restore user fpcr
9298
9299 addi.w &0x3fff,%d0 # turn src amt into exp value
9300 swap %d0 # put exponent in high word
9301 clr.l -(%sp) # insert new exponent
9302 mov.l &0x80000000,-(%sp) # insert new high mantissa
9303 mov.l %d0,-(%sp) # insert new lo mantissa
9304
9305sok_norm_cont:
9306 fmov.l %fpcr,%d0 # d0 needs fpcr for t_catch2
9307 mov.b &FMUL_OP,%d1 # last inst is MUL
9308 fmul.x (%sp)+,%fp0 # do the multiply
9309 bra t_catch2 # catch any exceptions
9310
9311#
9312# Source is outside of 2^14 range. Test the sign and branch
9313# to the appropriate exception handler.
9314#
9315src_out:
9316 mov.l (%sp)+,%d0 # restore ctrl bits
9317 exg %a0,%a1 # swap src,dst ptrs
9318 tst.b SRC_EX(%a1) # is src negative?
9319 bmi t_unfl # yes; underflow
9320 bra t_ovfl_sc # no; overflow
9321
9322#
9323# The source input is below 1, so we check for denormalized numbers
9324# and set unfl.
9325#
9326src_small:
9327 tst.b DST_HI(%a1) # is dst denormalized?
9328 bpl.b ssmall_done # yes
9329
9330 mov.l (%sp)+,%d0
9331 fmov.l %d0,%fpcr # no; load control bits
9332 mov.b &FMOV_OP,%d1 # last inst is MOVE
9333 fmov.x DST(%a1),%fp0 # simply return dest
9334 bra t_catch2
9335ssmall_done:
9336 mov.l (%sp)+,%d0 # load control bits into d1
9337 mov.l %a1,%a0 # pass ptr to dst
9338 bra t_resdnrm
9339
9340#########################################################################
9341# smod(): computes the fp MOD of the input values X,Y. #
9342# srem(): computes the fp (IEEE) REM of the input values X,Y. #
9343# #
9344# INPUT *************************************************************** #
9345# a0 = pointer to extended precision input X #
9346# a1 = pointer to extended precision input Y #
9347# d0 = round precision,mode #
9348# #
9349# The input operands X and Y can be either normalized or #
9350# denormalized. #
9351# #
9352# OUTPUT ************************************************************** #
9353# fp0 = FREM(X,Y) or FMOD(X,Y) #
9354# #
9355# ALGORITHM *********************************************************** #
9356# #
9357# Step 1. Save and strip signs of X and Y: signX := sign(X), #
9358# signY := sign(Y), X := |X|, Y := |Y|, #
9359# signQ := signX EOR signY. Record whether MOD or REM #
9360# is requested. #
9361# #
9362# Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0. #
9363# If (L < 0) then #
9364# R := X, go to Step 4. #
9365# else #
9366# R := 2^(-L)X, j := L. #
9367# endif #
9368# #
9369# Step 3. Perform MOD(X,Y) #
9370# 3.1 If R = Y, go to Step 9. #
9371# 3.2 If R > Y, then { R := R - Y, Q := Q + 1} #
9372# 3.3 If j = 0, go to Step 4. #
9373# 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to #
9374# Step 3.1. #
9375# #
9376# Step 4. At this point, R = X - QY = MOD(X,Y). Set #
9377# Last_Subtract := false (used in Step 7 below). If #
9378# MOD is requested, go to Step 6. #
9379# #
9380# Step 5. R = MOD(X,Y), but REM(X,Y) is requested. #
9381# 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to #
9382# Step 6. #
9383# 5.2 If R > Y/2, then { set Last_Subtract := true, #
9384# Q := Q + 1, Y := signY*Y }. Go to Step 6. #
9385# 5.3 This is the tricky case of R = Y/2. If Q is odd, #
9386# then { Q := Q + 1, signX := -signX }. #
9387# #
9388# Step 6. R := signX*R. #
9389# #
9390# Step 7. If Last_Subtract = true, R := R - Y. #
9391# #
9392# Step 8. Return signQ, last 7 bits of Q, and R as required. #
9393# #
9394# Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus, #
9395# X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1), #
9396# R := 0. Return signQ, last 7 bits of Q, and R. #
9397# #
9398#########################################################################
9399
9400 set Mod_Flag,L_SCR3
9401 set Sc_Flag,L_SCR3+1
9402
9403 set SignY,L_SCR2
9404 set SignX,L_SCR2+2
9405 set SignQ,L_SCR3+2
9406
9407 set Y,FP_SCR0
9408 set Y_Hi,Y+4
9409 set Y_Lo,Y+8
9410
9411 set R,FP_SCR1
9412 set R_Hi,R+4
9413 set R_Lo,R+8
9414
9415Scale:
9416 long 0x00010000,0x80000000,0x00000000,0x00000000
9417
9418 global smod
9419smod:
9420 clr.b FPSR_QBYTE(%a6)
9421 mov.l %d0,-(%sp) # save ctrl bits
9422 clr.b Mod_Flag(%a6)
9423 bra.b Mod_Rem
9424
9425 global srem
9426srem:
9427 clr.b FPSR_QBYTE(%a6)
9428 mov.l %d0,-(%sp) # save ctrl bits
9429 mov.b &0x1,Mod_Flag(%a6)
9430
9431Mod_Rem:
9432#..Save sign of X and Y
9433 movm.l &0x3f00,-(%sp) # save data registers
9434 mov.w SRC_EX(%a0),%d3
9435 mov.w %d3,SignY(%a6)
9436 and.l &0x00007FFF,%d3 # Y := |Y|
9437
9438#
9439 mov.l SRC_HI(%a0),%d4
9440 mov.l SRC_LO(%a0),%d5 # (D3,D4,D5) is |Y|
9441
9442 tst.l %d3
9443 bne.b Y_Normal
9444
9445 mov.l &0x00003FFE,%d3 # $3FFD + 1
9446 tst.l %d4
9447 bne.b HiY_not0
9448
9449HiY_0:
9450 mov.l %d5,%d4
9451 clr.l %d5
9452 sub.l &32,%d3
9453 clr.l %d6
9454 bfffo %d4{&0:&32},%d6
9455 lsl.l %d6,%d4
9456 sub.l %d6,%d3 # (D3,D4,D5) is normalized
9457# ...with bias $7FFD
9458 bra.b Chk_X
9459
9460HiY_not0:
9461 clr.l %d6
9462 bfffo %d4{&0:&32},%d6
9463 sub.l %d6,%d3
9464 lsl.l %d6,%d4
9465 mov.l %d5,%d7 # a copy of D5
9466 lsl.l %d6,%d5
9467 neg.l %d6
9468 add.l &32,%d6
9469 lsr.l %d6,%d7
9470 or.l %d7,%d4 # (D3,D4,D5) normalized
9471# ...with bias $7FFD
9472 bra.b Chk_X
9473
9474Y_Normal:
9475 add.l &0x00003FFE,%d3 # (D3,D4,D5) normalized
9476# ...with bias $7FFD
9477
9478Chk_X:
9479 mov.w DST_EX(%a1),%d0
9480 mov.w %d0,SignX(%a6)
9481 mov.w SignY(%a6),%d1
9482 eor.l %d0,%d1
9483 and.l &0x00008000,%d1
9484 mov.w %d1,SignQ(%a6) # sign(Q) obtained
9485 and.l &0x00007FFF,%d0
9486 mov.l DST_HI(%a1),%d1
9487 mov.l DST_LO(%a1),%d2 # (D0,D1,D2) is |X|
9488 tst.l %d0
9489 bne.b X_Normal
9490 mov.l &0x00003FFE,%d0
9491 tst.l %d1
9492 bne.b HiX_not0
9493
9494HiX_0:
9495 mov.l %d2,%d1
9496 clr.l %d2
9497 sub.l &32,%d0
9498 clr.l %d6
9499 bfffo %d1{&0:&32},%d6
9500 lsl.l %d6,%d1
9501 sub.l %d6,%d0 # (D0,D1,D2) is normalized
9502# ...with bias $7FFD
9503 bra.b Init
9504
9505HiX_not0:
9506 clr.l %d6
9507 bfffo %d1{&0:&32},%d6
9508 sub.l %d6,%d0
9509 lsl.l %d6,%d1
9510 mov.l %d2,%d7 # a copy of D2
9511 lsl.l %d6,%d2
9512 neg.l %d6
9513 add.l &32,%d6
9514 lsr.l %d6,%d7
9515 or.l %d7,%d1 # (D0,D1,D2) normalized
9516# ...with bias $7FFD
9517 bra.b Init
9518
9519X_Normal:
9520 add.l &0x00003FFE,%d0 # (D0,D1,D2) normalized
9521# ...with bias $7FFD
9522
9523Init:
9524#
9525 mov.l %d3,L_SCR1(%a6) # save biased exp(Y)
9526 mov.l %d0,-(%sp) # save biased exp(X)
9527 sub.l %d3,%d0 # L := expo(X)-expo(Y)
9528
9529 clr.l %d6 # D6 := carry <- 0
9530 clr.l %d3 # D3 is Q
9531 mov.l &0,%a1 # A1 is k; j+k=L, Q=0
9532
9533#..(Carry,D1,D2) is R
9534 tst.l %d0
9535 bge.b Mod_Loop_pre
9536
9537#..expo(X) < expo(Y). Thus X = mod(X,Y)
9538#
9539 mov.l (%sp)+,%d0 # restore d0
9540 bra.w Get_Mod
9541
9542Mod_Loop_pre:
9543 addq.l &0x4,%sp # erase exp(X)
9544#..At this point R = 2^(-L)X; Q = 0; k = 0; and k+j = L
9545Mod_Loop:
9546 tst.l %d6 # test carry bit
9547 bgt.b R_GT_Y
9548
9549#..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
9550 cmp.l %d1,%d4 # compare hi(R) and hi(Y)
9551 bne.b R_NE_Y
9552 cmp.l %d2,%d5 # compare lo(R) and lo(Y)
9553 bne.b R_NE_Y
9554
9555#..At this point, R = Y
9556 bra.w Rem_is_0
9557
9558R_NE_Y:
9559#..use the borrow of the previous compare
9560 bcs.b R_LT_Y # borrow is set iff R < Y
9561
9562R_GT_Y:
9563#..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
9564#..and Y < (D1,D2) < 2Y. Either way, perform R - Y
9565 sub.l %d5,%d2 # lo(R) - lo(Y)
9566 subx.l %d4,%d1 # hi(R) - hi(Y)
9567 clr.l %d6 # clear carry
9568 addq.l &1,%d3 # Q := Q + 1
9569
9570R_LT_Y:
9571#..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
9572 tst.l %d0 # see if j = 0.
9573 beq.b PostLoop
9574
9575 add.l %d3,%d3 # Q := 2Q
9576 add.l %d2,%d2 # lo(R) = 2lo(R)
9577 roxl.l &1,%d1 # hi(R) = 2hi(R) + carry
9578 scs %d6 # set Carry if 2(R) overflows
9579 addq.l &1,%a1 # k := k+1
9580 subq.l &1,%d0 # j := j - 1
9581#..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
9582
9583 bra.b Mod_Loop
9584
9585PostLoop:
9586#..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
9587
9588#..normalize R.
9589 mov.l L_SCR1(%a6),%d0 # new biased expo of R
9590 tst.l %d1
9591 bne.b HiR_not0
9592
9593HiR_0:
9594 mov.l %d2,%d1
9595 clr.l %d2
9596 sub.l &32,%d0
9597 clr.l %d6
9598 bfffo %d1{&0:&32},%d6
9599 lsl.l %d6,%d1
9600 sub.l %d6,%d0 # (D0,D1,D2) is normalized
9601# ...with bias $7FFD
9602 bra.b Get_Mod
9603
9604HiR_not0:
9605 clr.l %d6
9606 bfffo %d1{&0:&32},%d6
9607 bmi.b Get_Mod # already normalized
9608 sub.l %d6,%d0
9609 lsl.l %d6,%d1
9610 mov.l %d2,%d7 # a copy of D2
9611 lsl.l %d6,%d2
9612 neg.l %d6
9613 add.l &32,%d6
9614 lsr.l %d6,%d7
9615 or.l %d7,%d1 # (D0,D1,D2) normalized
9616
9617#
9618Get_Mod:
9619 cmp.l %d0,&0x000041FE
9620 bge.b No_Scale
9621Do_Scale:
9622 mov.w %d0,R(%a6)
9623 mov.l %d1,R_Hi(%a6)
9624 mov.l %d2,R_Lo(%a6)
9625 mov.l L_SCR1(%a6),%d6
9626 mov.w %d6,Y(%a6)
9627 mov.l %d4,Y_Hi(%a6)
9628 mov.l %d5,Y_Lo(%a6)
9629 fmov.x R(%a6),%fp0 # no exception
9630 mov.b &1,Sc_Flag(%a6)
9631 bra.b ModOrRem
9632No_Scale:
9633 mov.l %d1,R_Hi(%a6)
9634 mov.l %d2,R_Lo(%a6)
9635 sub.l &0x3FFE,%d0
9636 mov.w %d0,R(%a6)
9637 mov.l L_SCR1(%a6),%d6
9638 sub.l &0x3FFE,%d6
9639 mov.l %d6,L_SCR1(%a6)
9640 fmov.x R(%a6),%fp0
9641 mov.w %d6,Y(%a6)
9642 mov.l %d4,Y_Hi(%a6)
9643 mov.l %d5,Y_Lo(%a6)
9644 clr.b Sc_Flag(%a6)
9645
9646#
9647ModOrRem:
9648 tst.b Mod_Flag(%a6)
9649 beq.b Fix_Sign
9650
9651 mov.l L_SCR1(%a6),%d6 # new biased expo(Y)
9652 subq.l &1,%d6 # biased expo(Y/2)
9653 cmp.l %d0,%d6
9654 blt.b Fix_Sign
9655 bgt.b Last_Sub
9656
9657 cmp.l %d1,%d4
9658 bne.b Not_EQ
9659 cmp.l %d2,%d5
9660 bne.b Not_EQ
9661 bra.w Tie_Case
9662
9663Not_EQ:
9664 bcs.b Fix_Sign
9665
9666Last_Sub:
9667#
9668 fsub.x Y(%a6),%fp0 # no exceptions
9669 addq.l &1,%d3 # Q := Q + 1
9670
9671#
9672Fix_Sign:
9673#..Get sign of X
9674 mov.w SignX(%a6),%d6
9675 bge.b Get_Q
9676 fneg.x %fp0
9677
9678#..Get Q
9679#
9680Get_Q:
9681 clr.l %d6
9682 mov.w SignQ(%a6),%d6 # D6 is sign(Q)
9683 mov.l &8,%d7
9684 lsr.l %d7,%d6
9685 and.l &0x0000007F,%d3 # 7 bits of Q
9686 or.l %d6,%d3 # sign and bits of Q
9687# swap %d3
9688# fmov.l %fpsr,%d6
9689# and.l &0xFF00FFFF,%d6
9690# or.l %d3,%d6
9691# fmov.l %d6,%fpsr # put Q in fpsr
9692 mov.b %d3,FPSR_QBYTE(%a6) # put Q in fpsr
9693
9694#
9695Restore:
9696 movm.l (%sp)+,&0xfc # {%d2-%d7}
9697 mov.l (%sp)+,%d0
9698 fmov.l %d0,%fpcr
9699 tst.b Sc_Flag(%a6)
9700 beq.b Finish
9701 mov.b &FMUL_OP,%d1 # last inst is MUL
9702 fmul.x Scale(%pc),%fp0 # may cause underflow
9703 bra t_catch2
9704# the '040 package did this apparently to see if the dst operand for the
9705# preceding fmul was a denorm. but, it better not have been since the
9706# algorithm just got done playing with fp0 and expected no exceptions
9707# as a result. trust me...
9708# bra t_avoid_unsupp # check for denorm as a
9709# ;result of the scaling
9710
9711Finish:
9712 mov.b &FMOV_OP,%d1 # last inst is MOVE
9713 fmov.x %fp0,%fp0 # capture exceptions & round
9714 bra t_catch2
9715
9716Rem_is_0:
9717#..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
9718 addq.l &1,%d3
9719 cmp.l %d0,&8 # D0 is j
9720 bge.b Q_Big
9721
9722 lsl.l %d0,%d3
9723 bra.b Set_R_0
9724
9725Q_Big:
9726 clr.l %d3
9727
9728Set_R_0:
9729 fmov.s &0x00000000,%fp0
9730 clr.b Sc_Flag(%a6)
9731 bra.w Fix_Sign
9732
9733Tie_Case:
9734#..Check parity of Q
9735 mov.l %d3,%d6
9736 and.l &0x00000001,%d6
9737 tst.l %d6
9738 beq.w Fix_Sign # Q is even
9739
9740#..Q is odd, Q := Q + 1, signX := -signX
9741 addq.l &1,%d3
9742 mov.w SignX(%a6),%d6
9743 eor.l &0x00008000,%d6
9744 mov.w %d6,SignX(%a6)
9745 bra.w Fix_Sign
9746
9747#########################################################################
9748# XDEF **************************************************************** #
9749# tag(): return the optype of the input ext fp number #
9750# #
9751# This routine is used by the 060FPLSP. #
9752# #
9753# XREF **************************************************************** #
9754# None #
9755# #
9756# INPUT *************************************************************** #
9757# a0 = pointer to extended precision operand #
9758# #
9759# OUTPUT ************************************************************** #
9760# d0 = value of type tag #
9761# one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
9762# #
9763# ALGORITHM *********************************************************** #
9764# Simply test the exponent, j-bit, and mantissa values to #
9765# determine the type of operand. #
9766# If it's an unnormalized zero, alter the operand and force it #
9767# to be a normal zero. #
9768# #
9769#########################################################################
9770
9771 global tag
9772tag:
9773 mov.w FTEMP_EX(%a0), %d0 # extract exponent
9774 andi.w &0x7fff, %d0 # strip off sign
9775 cmpi.w %d0, &0x7fff # is (EXP == MAX)?
9776 beq.b inf_or_nan_x
9777not_inf_or_nan_x:
9778 btst &0x7,FTEMP_HI(%a0)
9779 beq.b not_norm_x
9780is_norm_x:
9781 mov.b &NORM, %d0
9782 rts
9783not_norm_x:
9784 tst.w %d0 # is exponent = 0?
9785 bne.b is_unnorm_x
9786not_unnorm_x:
9787 tst.l FTEMP_HI(%a0)
9788 bne.b is_denorm_x
9789 tst.l FTEMP_LO(%a0)
9790 bne.b is_denorm_x
9791is_zero_x:
9792 mov.b &ZERO, %d0
9793 rts
9794is_denorm_x:
9795 mov.b &DENORM, %d0
9796 rts
9797is_unnorm_x:
9798 bsr.l unnorm_fix # convert to norm,denorm,or zero
9799 rts
9800is_unnorm_reg_x:
9801 mov.b &UNNORM, %d0
9802 rts
9803inf_or_nan_x:
9804 tst.l FTEMP_LO(%a0)
9805 bne.b is_nan_x
9806 mov.l FTEMP_HI(%a0), %d0
9807 and.l &0x7fffffff, %d0 # msb is a don't care!
9808 bne.b is_nan_x
9809is_inf_x:
9810 mov.b &INF, %d0
9811 rts
9812is_nan_x:
9813 mov.b &QNAN, %d0
9814 rts
9815
9816#############################################################
9817
9818qnan: long 0x7fff0000, 0xffffffff, 0xffffffff
9819
9820#########################################################################
9821# XDEF **************************************************************** #
9822# t_dz(): Handle 060FPLSP dz exception for "flogn" emulation. #
9823# t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation. #
9824# #
9825# These rouitnes are used by the 060FPLSP package. #
9826# #
9827# XREF **************************************************************** #
9828# None #
9829# #
9830# INPUT *************************************************************** #
9831# a0 = pointer to extended precision source operand. #
9832# #
9833# OUTPUT ************************************************************** #
9834# fp0 = default DZ result. #
9835# #
9836# ALGORITHM *********************************************************** #
9837# Transcendental emulation for the 060FPLSP has detected that #
9838# a DZ exception should occur for the instruction. If DZ is disabled, #
9839# return the default result. #
9840# If DZ is enabled, the dst operand should be returned unscathed #
9841# in fp0 while fp1 is used to create a DZ exception so that the #
9842# operating system can log that such an event occurred. #
9843# #
9844#########################################################################
9845
9846 global t_dz
9847t_dz:
9848 tst.b SRC_EX(%a0) # check sign for neg or pos
9849 bpl.b dz_pinf # branch if pos sign
9850
9851 global t_dz2
9852t_dz2:
9853 ori.l &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
9854
9855 btst &dz_bit,FPCR_ENABLE(%a6)
9856 bne.b dz_minf_ena
9857
9858# dz is disabled. return a -INF.
9859 fmov.s &0xff800000,%fp0 # return -INF
9860 rts
9861
9862# dz is enabled. create a dz exception so the user can record it
9863# but use fp1 instead. return the dst operand unscathed in fp0.
9864dz_minf_ena:
9865 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9866 fmov.l USER_FPCR(%a6),%fpcr
9867 fmov.s &0xbf800000,%fp1 # load -1
9868 fdiv.s &0x00000000,%fp1 # -1 / 0
9869 rts
9870
9871dz_pinf:
9872 ori.l &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
9873
9874 btst &dz_bit,FPCR_ENABLE(%a6)
9875 bne.b dz_pinf_ena
9876
9877# dz is disabled. return a +INF.
9878 fmov.s &0x7f800000,%fp0 # return +INF
9879 rts
9880
9881# dz is enabled. create a dz exception so the user can record it
9882# but use fp1 instead. return the dst operand unscathed in fp0.
9883dz_pinf_ena:
9884 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9885 fmov.l USER_FPCR(%a6),%fpcr
9886 fmov.s &0x3f800000,%fp1 # load +1
9887 fdiv.s &0x00000000,%fp1 # +1 / 0
9888 rts
9889
9890#########################################################################
9891# XDEF **************************************************************** #
9892# t_operr(): Handle 060FPLSP OPERR exception during emulation. #
9893# #
9894# This routine is used by the 060FPLSP package. #
9895# #
9896# XREF **************************************************************** #
9897# None. #
9898# #
9899# INPUT *************************************************************** #
9900# fp1 = source operand #
9901# #
9902# OUTPUT ************************************************************** #
9903# fp0 = default result #
9904# fp1 = unchanged #
9905# #
9906# ALGORITHM *********************************************************** #
9907# An operand error should occur as the result of transcendental #
9908# emulation in the 060FPLSP. If OPERR is disabled, just return a NAN #
9909# in fp0. If OPERR is enabled, return the dst operand unscathed in fp0 #
9910# and the source operand in fp1. Use fp2 to create an OPERR exception #
9911# so that the operating system can log the event. #
9912# #
9913#########################################################################
9914
9915 global t_operr
9916t_operr:
9917 ori.l &opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP
9918
9919 btst &operr_bit,FPCR_ENABLE(%a6)
9920 bne.b operr_ena
9921
9922# operr is disabled. return a QNAN in fp0
9923 fmovm.x qnan(%pc),&0x80 # return QNAN
9924 rts
9925
9926# operr is enabled. create an operr exception so the user can record it
9927# but use fp2 instead. return the dst operand unscathed in fp0.
9928operr_ena:
9929 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9930 fmov.l USER_FPCR(%a6),%fpcr
9931 fmovm.x &0x04,-(%sp) # save fp2
9932 fmov.s &0x7f800000,%fp2 # load +INF
9933 fmul.s &0x00000000,%fp2 # +INF x 0
9934 fmovm.x (%sp)+,&0x20 # restore fp2
9935 rts
9936
9937pls_huge:
9938 long 0x7ffe0000,0xffffffff,0xffffffff
9939mns_huge:
9940 long 0xfffe0000,0xffffffff,0xffffffff
9941pls_tiny:
9942 long 0x00000000,0x80000000,0x00000000
9943mns_tiny:
9944 long 0x80000000,0x80000000,0x00000000
9945
9946#########################################################################
9947# XDEF **************************************************************** #
9948# t_unfl(): Handle 060FPLSP underflow exception during emulation. #
9949# t_unfl2(): Handle 060FPLSP underflow exception during #
9950# emulation. result always positive. #
9951# #
9952# This routine is used by the 060FPLSP package. #
9953# #
9954# XREF **************************************************************** #
9955# None. #
9956# #
9957# INPUT *************************************************************** #
9958# a0 = pointer to extended precision source operand #
9959# #
9960# OUTPUT ************************************************************** #
9961# fp0 = default underflow result #
9962# #
9963# ALGORITHM *********************************************************** #
9964# An underflow should occur as the result of transcendental #
9965# emulation in the 060FPLSP. Create an underflow by using "fmul" #
9966# and two very small numbers of appropriate sign so the operating #
9967# system can log the event. #
9968# #
9969#########################################################################
9970
9971 global t_unfl
9972t_unfl:
9973 tst.b SRC_EX(%a0)
9974 bpl.b unf_pos
9975
9976 global t_unfl2
9977t_unfl2:
9978 ori.l &unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX
9979
9980 fmov.l USER_FPCR(%a6),%fpcr
9981 fmovm.x mns_tiny(%pc),&0x80
9982 fmul.x pls_tiny(%pc),%fp0
9983
9984 fmov.l %fpsr,%d0
9985 rol.l &0x8,%d0
9986 mov.b %d0,FPSR_CC(%a6)
9987 rts
9988unf_pos:
9989 ori.w &unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX
9990
9991 fmov.l USER_FPCR(%a6),%fpcr
9992 fmovm.x pls_tiny(%pc),&0x80
9993 fmul.x %fp0,%fp0
9994
9995 fmov.l %fpsr,%d0
9996 rol.l &0x8,%d0
9997 mov.b %d0,FPSR_CC(%a6)
9998 rts
9999
10000#########################################################################
10001# XDEF **************************************************************** #
10002# t_ovfl(): Handle 060FPLSP overflow exception during emulation. #
10003# (monadic) #
10004# t_ovfl2(): Handle 060FPLSP overflow exception during #
10005# emulation. result always positive. (dyadic) #
10006# t_ovfl_sc(): Handle 060FPLSP overflow exception during #
10007# emulation for "fscale". #
10008# #
10009# This routine is used by the 060FPLSP package. #
10010# #
10011# XREF **************************************************************** #
10012# None. #
10013# #
10014# INPUT *************************************************************** #
10015# a0 = pointer to extended precision source operand #
10016# #
10017# OUTPUT ************************************************************** #
10018# fp0 = default underflow result #
10019# #
10020# ALGORITHM *********************************************************** #
10021# An overflow should occur as the result of transcendental #
10022# emulation in the 060FPLSP. Create an overflow by using "fmul" #
10023# and two very lareg numbers of appropriate sign so the operating #
10024# system can log the event. #
10025# For t_ovfl_sc() we take special care not to lose the INEX2 bit. #
10026# #
10027#########################################################################
10028
10029 global t_ovfl_sc
10030t_ovfl_sc:
10031 ori.l &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
10032
10033 mov.b %d0,%d1 # fetch rnd prec,mode
10034 andi.b &0xc0,%d1 # extract prec
10035 beq.w ovfl_work
10036
10037# dst op is a DENORM. we have to normalize the mantissa to see if the
10038# result would be inexact for the given precision. make a copy of the
10039# dst so we don't screw up the version passed to us.
10040 mov.w LOCAL_EX(%a0),FP_SCR0_EX(%a6)
10041 mov.l LOCAL_HI(%a0),FP_SCR0_HI(%a6)
10042 mov.l LOCAL_LO(%a0),FP_SCR0_LO(%a6)
10043 lea FP_SCR0(%a6),%a0 # pass ptr to FP_SCR0
10044 movm.l &0xc080,-(%sp) # save d0-d1/a0
10045 bsr.l norm # normalize mantissa
10046 movm.l (%sp)+,&0x0103 # restore d0-d1/a0
10047
10048 cmpi.b %d1,&0x40 # is precision sgl?
10049 bne.b ovfl_sc_dbl # no; dbl
10050ovfl_sc_sgl:
10051 tst.l LOCAL_LO(%a0) # is lo lw of sgl set?
10052 bne.b ovfl_sc_inx # yes
10053 tst.b 3+LOCAL_HI(%a0) # is lo byte of hi lw set?
10054 bne.b ovfl_sc_inx # yes
10055 bra.w ovfl_work # don't set INEX2
10056ovfl_sc_dbl:
10057 mov.l LOCAL_LO(%a0),%d1 # are any of lo 11 bits of
10058 andi.l &0x7ff,%d1 # dbl mantissa set?
10059 beq.w ovfl_work # no; don't set INEX2
10060ovfl_sc_inx:
10061 ori.l &inex2_mask,USER_FPSR(%a6) # set INEX2
10062 bra.b ovfl_work # continue
10063
10064 global t_ovfl
10065t_ovfl:
10066 ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10067ovfl_work:
10068 tst.b SRC_EX(%a0)
10069 bpl.b ovfl_p
10070ovfl_m:
10071 fmov.l USER_FPCR(%a6),%fpcr
10072 fmovm.x mns_huge(%pc),&0x80
10073 fmul.x pls_huge(%pc),%fp0
10074
10075 fmov.l %fpsr,%d0
10076 rol.l &0x8,%d0
10077 ori.b &neg_mask,%d0
10078 mov.b %d0,FPSR_CC(%a6)
10079 rts
10080ovfl_p:
10081 fmov.l USER_FPCR(%a6),%fpcr
10082 fmovm.x pls_huge(%pc),&0x80
10083 fmul.x pls_huge(%pc),%fp0
10084
10085 fmov.l %fpsr,%d0
10086 rol.l &0x8,%d0
10087 mov.b %d0,FPSR_CC(%a6)
10088 rts
10089
10090 global t_ovfl2
10091t_ovfl2:
10092 ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10093 fmov.l USER_FPCR(%a6),%fpcr
10094 fmovm.x pls_huge(%pc),&0x80
10095 fmul.x pls_huge(%pc),%fp0
10096
10097 fmov.l %fpsr,%d0
10098 rol.l &0x8,%d0
10099 mov.b %d0,FPSR_CC(%a6)
10100 rts
10101
10102#########################################################################
10103# XDEF **************************************************************** #
10104# t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
10105# emulation. #
10106# t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
10107# emulation. #
10108# #
10109# These routines are used by the 060FPLSP package. #
10110# #
10111# XREF **************************************************************** #
10112# None. #
10113# #
10114# INPUT *************************************************************** #
10115# fp0 = default underflow or overflow result #
10116# #
10117# OUTPUT ************************************************************** #
10118# fp0 = default result #
10119# #
10120# ALGORITHM *********************************************************** #
10121# If an overflow or underflow occurred during the last #
10122# instruction of transcendental 060FPLSP emulation, then it has already #
10123# occurred and has been logged. Now we need to see if an inexact #
10124# exception should occur. #
10125# #
10126#########################################################################
10127
10128 global t_catch2
10129t_catch2:
10130 fmov.l %fpsr,%d0
10131 or.l %d0,USER_FPSR(%a6)
10132 bra.b inx2_work
10133
10134 global t_catch
10135t_catch:
10136 fmov.l %fpsr,%d0
10137 or.l %d0,USER_FPSR(%a6)
10138
10139#########################################################################
10140# XDEF **************************************************************** #
10141# t_inx2(): Handle inexact 060FPLSP exception during emulation. #
10142# t_pinx2(): Handle inexact 060FPLSP exception for "+" results. #
10143# t_minx2(): Handle inexact 060FPLSP exception for "-" results. #
10144# #
10145# XREF **************************************************************** #
10146# None. #
10147# #
10148# INPUT *************************************************************** #
10149# fp0 = default result #
10150# #
10151# OUTPUT ************************************************************** #
10152# fp0 = default result #
10153# #
10154# ALGORITHM *********************************************************** #
10155# The last instruction of transcendental emulation for the #
10156# 060FPLSP should be inexact. So, if inexact is enabled, then we create #
10157# the event here by adding a large and very small number together #
10158# so that the operating system can log the event. #
10159# Must check, too, if the result was zero, in which case we just #
10160# set the FPSR bits and return. #
10161# #
10162#########################################################################
10163
10164 global t_inx2
10165t_inx2:
10166 fblt.w t_minx2
10167 fbeq.w inx2_zero
10168
10169 global t_pinx2
10170t_pinx2:
10171 ori.w &inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX
10172 bra.b inx2_work
10173
10174 global t_minx2
10175t_minx2:
10176 ori.l &inx2a_mask+neg_mask,USER_FPSR(%a6)
10177
10178inx2_work:
10179 btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
10180 bne.b inx2_work_ena # yes
10181 rts
10182inx2_work_ena:
10183 fmov.l USER_FPCR(%a6),%fpcr # insert user's exceptions
10184 fmov.s &0x3f800000,%fp1 # load +1
10185 fadd.x pls_tiny(%pc),%fp1 # cause exception
10186 rts
10187
10188inx2_zero:
10189 mov.b &z_bmask,FPSR_CC(%a6)
10190 ori.w &inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX
10191 rts
10192
10193#########################################################################
10194# XDEF **************************************************************** #
10195# t_extdnrm(): Handle DENORM inputs in 060FPLSP. #
10196# t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale". #
10197# #
10198# This routine is used by the 060FPLSP package. #
10199# #
10200# XREF **************************************************************** #
10201# None. #
10202# #
10203# INPUT *************************************************************** #
10204# a0 = pointer to extended precision input operand #
10205# #
10206# OUTPUT ************************************************************** #
10207# fp0 = default result #
10208# #
10209# ALGORITHM *********************************************************** #
10210# For all functions that have a denormalized input and that #
10211# f(x)=x, this is the entry point. #
10212# DENORM value is moved using "fmove" which triggers an exception #
10213# if enabled so the operating system can log the event. #
10214# #
10215#########################################################################
10216
10217 global t_extdnrm
10218t_extdnrm:
10219 fmov.l USER_FPCR(%a6),%fpcr
10220 fmov.x SRC_EX(%a0),%fp0
10221 fmov.l %fpsr,%d0
10222 ori.l &unfinx_mask,%d0
10223 or.l %d0,USER_FPSR(%a6)
10224 rts
10225
10226 global t_resdnrm
10227t_resdnrm:
10228 fmov.l USER_FPCR(%a6),%fpcr
10229 fmov.x SRC_EX(%a0),%fp0
10230 fmov.l %fpsr,%d0
10231 or.l %d0,USER_FPSR(%a6)
10232 rts
10233
10234##########################################
10235
10236#
10237# sto_cos:
10238# This is used by fsincos library emulation. The correct
10239# values are already in fp0 and fp1 so we do nothing here.
10240#
10241 global sto_cos
10242sto_cos:
10243 rts
10244
10245##########################################
10246
10247#
10248# dst_qnan --- force result when destination is a NaN
10249#
10250 global dst_qnan
10251dst_qnan:
10252 fmov.x DST(%a1),%fp0
10253 tst.b DST_EX(%a1)
10254 bmi.b dst_qnan_m
10255dst_qnan_p:
10256 mov.b &nan_bmask,FPSR_CC(%a6)
10257 rts
10258dst_qnan_m:
10259 mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)
10260 rts
10261
10262#
10263# src_qnan --- force result when source is a NaN
10264#
10265 global src_qnan
10266src_qnan:
10267 fmov.x SRC(%a0),%fp0
10268 tst.b SRC_EX(%a0)
10269 bmi.b src_qnan_m
10270src_qnan_p:
10271 mov.b &nan_bmask,FPSR_CC(%a6)
10272 rts
10273src_qnan_m:
10274 mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)
10275 rts
10276
10277##########################################
10278
10279#
10280# Native instruction support
10281#
10282# Some systems may need entry points even for 68060 native
10283# instructions. These routines are provided for
10284# convenience.
10285#
10286 global _fadds_
10287_fadds_:
10288 fmov.l %fpcr,-(%sp) # save fpcr
10289 fmov.l &0x00000000,%fpcr # clear fpcr for load
10290 fmov.s 0x8(%sp),%fp0 # load sgl dst
10291 fmov.l (%sp)+,%fpcr # restore fpcr
10292 fadd.s 0x8(%sp),%fp0 # fadd w/ sgl src
10293 rts
10294
10295 global _faddd_
10296_faddd_:
10297 fmov.l %fpcr,-(%sp) # save fpcr
10298 fmov.l &0x00000000,%fpcr # clear fpcr for load
10299 fmov.d 0x8(%sp),%fp0 # load dbl dst
10300 fmov.l (%sp)+,%fpcr # restore fpcr
10301 fadd.d 0xc(%sp),%fp0 # fadd w/ dbl src
10302 rts
10303
10304 global _faddx_
10305_faddx_:
10306 fmovm.x 0x4(%sp),&0x80 # load ext dst
10307 fadd.x 0x10(%sp),%fp0 # fadd w/ ext src
10308 rts
10309
10310 global _fsubs_
10311_fsubs_:
10312 fmov.l %fpcr,-(%sp) # save fpcr
10313 fmov.l &0x00000000,%fpcr # clear fpcr for load
10314 fmov.s 0x8(%sp),%fp0 # load sgl dst
10315 fmov.l (%sp)+,%fpcr # restore fpcr
10316 fsub.s 0x8(%sp),%fp0 # fsub w/ sgl src
10317 rts
10318
10319 global _fsubd_
10320_fsubd_:
10321 fmov.l %fpcr,-(%sp) # save fpcr
10322 fmov.l &0x00000000,%fpcr # clear fpcr for load
10323 fmov.d 0x8(%sp),%fp0 # load dbl dst
10324 fmov.l (%sp)+,%fpcr # restore fpcr
10325 fsub.d 0xc(%sp),%fp0 # fsub w/ dbl src
10326 rts
10327
10328 global _fsubx_
10329_fsubx_:
10330 fmovm.x 0x4(%sp),&0x80 # load ext dst
10331 fsub.x 0x10(%sp),%fp0 # fsub w/ ext src
10332 rts
10333
10334 global _fmuls_
10335_fmuls_:
10336 fmov.l %fpcr,-(%sp) # save fpcr
10337 fmov.l &0x00000000,%fpcr # clear fpcr for load
10338 fmov.s 0x8(%sp),%fp0 # load sgl dst
10339 fmov.l (%sp)+,%fpcr # restore fpcr
10340 fmul.s 0x8(%sp),%fp0 # fmul w/ sgl src
10341 rts
10342
10343 global _fmuld_
10344_fmuld_:
10345 fmov.l %fpcr,-(%sp) # save fpcr
10346 fmov.l &0x00000000,%fpcr # clear fpcr for load
10347 fmov.d 0x8(%sp),%fp0 # load dbl dst
10348 fmov.l (%sp)+,%fpcr # restore fpcr
10349 fmul.d 0xc(%sp),%fp0 # fmul w/ dbl src
10350 rts
10351
10352 global _fmulx_
10353_fmulx_:
10354 fmovm.x 0x4(%sp),&0x80 # load ext dst
10355 fmul.x 0x10(%sp),%fp0 # fmul w/ ext src
10356 rts
10357
10358 global _fdivs_
10359_fdivs_:
10360 fmov.l %fpcr,-(%sp) # save fpcr
10361 fmov.l &0x00000000,%fpcr # clear fpcr for load
10362 fmov.s 0x8(%sp),%fp0 # load sgl dst
10363 fmov.l (%sp)+,%fpcr # restore fpcr
10364 fdiv.s 0x8(%sp),%fp0 # fdiv w/ sgl src
10365 rts
10366
10367 global _fdivd_
10368_fdivd_:
10369 fmov.l %fpcr,-(%sp) # save fpcr
10370 fmov.l &0x00000000,%fpcr # clear fpcr for load
10371 fmov.d 0x8(%sp),%fp0 # load dbl dst
10372 fmov.l (%sp)+,%fpcr # restore fpcr
10373 fdiv.d 0xc(%sp),%fp0 # fdiv w/ dbl src
10374 rts
10375
10376 global _fdivx_
10377_fdivx_:
10378 fmovm.x 0x4(%sp),&0x80 # load ext dst
10379 fdiv.x 0x10(%sp),%fp0 # fdiv w/ ext src
10380 rts
10381
10382 global _fabss_
10383_fabss_:
10384 fabs.s 0x4(%sp),%fp0 # fabs w/ sgl src
10385 rts
10386
10387 global _fabsd_
10388_fabsd_:
10389 fabs.d 0x4(%sp),%fp0 # fabs w/ dbl src
10390 rts
10391
10392 global _fabsx_
10393_fabsx_:
10394 fabs.x 0x4(%sp),%fp0 # fabs w/ ext src
10395 rts
10396
10397 global _fnegs_
10398_fnegs_:
10399 fneg.s 0x4(%sp),%fp0 # fneg w/ sgl src
10400 rts
10401
10402 global _fnegd_
10403_fnegd_:
10404 fneg.d 0x4(%sp),%fp0 # fneg w/ dbl src
10405 rts
10406
10407 global _fnegx_
10408_fnegx_:
10409 fneg.x 0x4(%sp),%fp0 # fneg w/ ext src
10410 rts
10411
10412 global _fsqrts_
10413_fsqrts_:
10414 fsqrt.s 0x4(%sp),%fp0 # fsqrt w/ sgl src
10415 rts
10416
10417 global _fsqrtd_
10418_fsqrtd_:
10419 fsqrt.d 0x4(%sp),%fp0 # fsqrt w/ dbl src
10420 rts
10421
10422 global _fsqrtx_
10423_fsqrtx_:
10424 fsqrt.x 0x4(%sp),%fp0 # fsqrt w/ ext src
10425 rts
10426
10427 global _fints_
10428_fints_:
10429 fint.s 0x4(%sp),%fp0 # fint w/ sgl src
10430 rts
10431
10432 global _fintd_
10433_fintd_:
10434 fint.d 0x4(%sp),%fp0 # fint w/ dbl src
10435 rts
10436
10437 global _fintx_
10438_fintx_:
10439 fint.x 0x4(%sp),%fp0 # fint w/ ext src
10440 rts
10441
10442 global _fintrzs_
10443_fintrzs_:
10444 fintrz.s 0x4(%sp),%fp0 # fintrz w/ sgl src
10445 rts
10446
10447 global _fintrzd_
10448_fintrzd_:
10449 fintrz.d 0x4(%sp),%fp0 # fintrx w/ dbl src
10450 rts
10451
10452 global _fintrzx_
10453_fintrzx_:
10454 fintrz.x 0x4(%sp),%fp0 # fintrz w/ ext src
10455 rts
10456
10457########################################################################
10458
10459#########################################################################
10460# src_zero(): Return signed zero according to sign of src operand. #
10461#########################################################################
10462 global src_zero
10463src_zero:
10464 tst.b SRC_EX(%a0) # get sign of src operand
10465 bmi.b ld_mzero # if neg, load neg zero
10466
10467#
10468# ld_pzero(): return a positive zero.
10469#
10470 global ld_pzero
10471ld_pzero:
10472 fmov.s &0x00000000,%fp0 # load +0
10473 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10474 rts
10475
10476# ld_mzero(): return a negative zero.
10477 global ld_mzero
10478ld_mzero:
10479 fmov.s &0x80000000,%fp0 # load -0
10480 mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
10481 rts
10482
10483#########################################################################
10484# dst_zero(): Return signed zero according to sign of dst operand. #
10485#########################################################################
10486 global dst_zero
10487dst_zero:
10488 tst.b DST_EX(%a1) # get sign of dst operand
10489 bmi.b ld_mzero # if neg, load neg zero
10490 bra.b ld_pzero # load positive zero
10491
10492#########################################################################
10493# src_inf(): Return signed inf according to sign of src operand. #
10494#########################################################################
10495 global src_inf
10496src_inf:
10497 tst.b SRC_EX(%a0) # get sign of src operand
10498 bmi.b ld_minf # if negative branch
10499
10500#
10501# ld_pinf(): return a positive infinity.
10502#
10503 global ld_pinf
10504ld_pinf:
10505 fmov.s &0x7f800000,%fp0 # load +INF
10506 mov.b &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit
10507 rts
10508
10509#
10510# ld_minf():return a negative infinity.
10511#
10512 global ld_minf
10513ld_minf:
10514 fmov.s &0xff800000,%fp0 # load -INF
10515 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
10516 rts
10517
10518#########################################################################
10519# dst_inf(): Return signed inf according to sign of dst operand. #
10520#########################################################################
10521 global dst_inf
10522dst_inf:
10523 tst.b DST_EX(%a1) # get sign of dst operand
10524 bmi.b ld_minf # if negative branch
10525 bra.b ld_pinf
10526
10527 global szr_inf
10528#################################################################
10529# szr_inf(): Return +ZERO for a negative src operand or #
10530# +INF for a positive src operand. #
10531# Routine used for fetox, ftwotox, and ftentox. #
10532#################################################################
10533szr_inf:
10534 tst.b SRC_EX(%a0) # check sign of source
10535 bmi.b ld_pzero
10536 bra.b ld_pinf
10537
10538#########################################################################
10539# sopr_inf(): Return +INF for a positive src operand or #
10540# jump to operand error routine for a negative src operand. #
10541# Routine used for flogn, flognp1, flog10, and flog2. #
10542#########################################################################
10543 global sopr_inf
10544sopr_inf:
10545 tst.b SRC_EX(%a0) # check sign of source
10546 bmi.w t_operr
10547 bra.b ld_pinf
10548
10549#################################################################
10550# setoxm1i(): Return minus one for a negative src operand or #
10551# positive infinity for a positive src operand. #
10552# Routine used for fetoxm1. #
10553#################################################################
10554 global setoxm1i
10555setoxm1i:
10556 tst.b SRC_EX(%a0) # check sign of source
10557 bmi.b ld_mone
10558 bra.b ld_pinf
10559
10560#########################################################################
10561# src_one(): Return signed one according to sign of src operand. #
10562#########################################################################
10563 global src_one
10564src_one:
10565 tst.b SRC_EX(%a0) # check sign of source
10566 bmi.b ld_mone
10567
10568#
10569# ld_pone(): return positive one.
10570#
10571 global ld_pone
10572ld_pone:
10573 fmov.s &0x3f800000,%fp0 # load +1
10574 clr.b FPSR_CC(%a6)
10575 rts
10576
10577#
10578# ld_mone(): return negative one.
10579#
10580 global ld_mone
10581ld_mone:
10582 fmov.s &0xbf800000,%fp0 # load -1
10583 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
10584 rts
10585
10586ppiby2: long 0x3fff0000, 0xc90fdaa2, 0x2168c235
10587mpiby2: long 0xbfff0000, 0xc90fdaa2, 0x2168c235
10588
10589#################################################################
10590# spi_2(): Return signed PI/2 according to sign of src operand. #
10591#################################################################
10592 global spi_2
10593spi_2:
10594 tst.b SRC_EX(%a0) # check sign of source
10595 bmi.b ld_mpi2
10596
10597#
10598# ld_ppi2(): return positive PI/2.
10599#
10600 global ld_ppi2
10601ld_ppi2:
10602 fmov.l %d0,%fpcr
10603 fmov.x ppiby2(%pc),%fp0 # load +pi/2
10604 bra.w t_pinx2 # set INEX2
10605
10606#
10607# ld_mpi2(): return negative PI/2.
10608#
10609 global ld_mpi2
10610ld_mpi2:
10611 fmov.l %d0,%fpcr
10612 fmov.x mpiby2(%pc),%fp0 # load -pi/2
10613 bra.w t_minx2 # set INEX2
10614
10615####################################################
10616# The following routines give support for fsincos. #
10617####################################################
10618
10619#
10620# ssincosz(): When the src operand is ZERO, store a one in the
10621# cosine register and return a ZERO in fp0 w/ the same sign
10622# as the src operand.
10623#
10624 global ssincosz
10625ssincosz:
10626 fmov.s &0x3f800000,%fp1
10627 tst.b SRC_EX(%a0) # test sign
10628 bpl.b sincoszp
10629 fmov.s &0x80000000,%fp0 # return sin result in fp0
10630 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6)
10631 rts
10632sincoszp:
10633 fmov.s &0x00000000,%fp0 # return sin result in fp0
10634 mov.b &z_bmask,FPSR_CC(%a6)
10635 rts
10636
10637#
10638# ssincosi(): When the src operand is INF, store a QNAN in the cosine
10639# register and jump to the operand error routine for negative
10640# src operands.
10641#
10642 global ssincosi
10643ssincosi:
10644 fmov.x qnan(%pc),%fp1 # load NAN
10645 bra.w t_operr
10646
10647#
10648# ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
10649# register and branch to the src QNAN routine.
10650#
10651 global ssincosqnan
10652ssincosqnan:
10653 fmov.x LOCAL_EX(%a0),%fp1
10654 bra.w src_qnan
10655
10656########################################################################
10657
10658 global smod_sdnrm
10659 global smod_snorm
10660smod_sdnrm:
10661smod_snorm:
10662 mov.b DTAG(%a6),%d1
10663 beq.l smod
10664 cmpi.b %d1,&ZERO
10665 beq.w smod_zro
10666 cmpi.b %d1,&INF
10667 beq.l t_operr
10668 cmpi.b %d1,&DENORM
10669 beq.l smod
10670 bra.l dst_qnan
10671
10672 global smod_szero
10673smod_szero:
10674 mov.b DTAG(%a6),%d1
10675 beq.l t_operr
10676 cmpi.b %d1,&ZERO
10677 beq.l t_operr
10678 cmpi.b %d1,&INF
10679 beq.l t_operr
10680 cmpi.b %d1,&DENORM
10681 beq.l t_operr
10682 bra.l dst_qnan
10683
10684 global smod_sinf
10685smod_sinf:
10686 mov.b DTAG(%a6),%d1
10687 beq.l smod_fpn
10688 cmpi.b %d1,&ZERO
10689 beq.l smod_zro
10690 cmpi.b %d1,&INF
10691 beq.l t_operr
10692 cmpi.b %d1,&DENORM
10693 beq.l smod_fpn
10694 bra.l dst_qnan
10695
10696smod_zro:
10697srem_zro:
10698 mov.b SRC_EX(%a0),%d1 # get src sign
10699 mov.b DST_EX(%a1),%d0 # get dst sign
10700 eor.b %d0,%d1 # get qbyte sign
10701 andi.b &0x80,%d1
10702 mov.b %d1,FPSR_QBYTE(%a6)
10703 tst.b %d0
10704 bpl.w ld_pzero
10705 bra.w ld_mzero
10706
10707smod_fpn:
10708srem_fpn:
10709 clr.b FPSR_QBYTE(%a6)
10710 mov.l %d0,-(%sp)
10711 mov.b SRC_EX(%a0),%d1 # get src sign
10712 mov.b DST_EX(%a1),%d0 # get dst sign
10713 eor.b %d0,%d1 # get qbyte sign
10714 andi.b &0x80,%d1
10715 mov.b %d1,FPSR_QBYTE(%a6)
10716 cmpi.b DTAG(%a6),&DENORM
10717 bne.b smod_nrm
10718 lea DST(%a1),%a0
10719 mov.l (%sp)+,%d0
10720 bra t_resdnrm
10721smod_nrm:
10722 fmov.l (%sp)+,%fpcr
10723 fmov.x DST(%a1),%fp0
10724 tst.b DST_EX(%a1)
10725 bmi.b smod_nrm_neg
10726 rts
10727
10728smod_nrm_neg:
10729 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' code
10730 rts
10731
10732#########################################################################
10733 global srem_snorm
10734 global srem_sdnrm
10735srem_sdnrm:
10736srem_snorm:
10737 mov.b DTAG(%a6),%d1
10738 beq.l srem
10739 cmpi.b %d1,&ZERO
10740 beq.w srem_zro
10741 cmpi.b %d1,&INF
10742 beq.l t_operr
10743 cmpi.b %d1,&DENORM
10744 beq.l srem
10745 bra.l dst_qnan
10746
10747 global srem_szero
10748srem_szero:
10749 mov.b DTAG(%a6),%d1
10750 beq.l t_operr
10751 cmpi.b %d1,&ZERO
10752 beq.l t_operr
10753 cmpi.b %d1,&INF
10754 beq.l t_operr
10755 cmpi.b %d1,&DENORM
10756 beq.l t_operr
10757 bra.l dst_qnan
10758
10759 global srem_sinf
10760srem_sinf:
10761 mov.b DTAG(%a6),%d1
10762 beq.w srem_fpn
10763 cmpi.b %d1,&ZERO
10764 beq.w srem_zro
10765 cmpi.b %d1,&INF
10766 beq.l t_operr
10767 cmpi.b %d1,&DENORM
10768 beq.l srem_fpn
10769 bra.l dst_qnan
10770
10771#########################################################################
10772
10773 global sscale_snorm
10774 global sscale_sdnrm
10775sscale_snorm:
10776sscale_sdnrm:
10777 mov.b DTAG(%a6),%d1
10778 beq.l sscale
10779 cmpi.b %d1,&ZERO
10780 beq.l dst_zero
10781 cmpi.b %d1,&INF
10782 beq.l dst_inf
10783 cmpi.b %d1,&DENORM
10784 beq.l sscale
10785 bra.l dst_qnan
10786
10787 global sscale_szero
10788sscale_szero:
10789 mov.b DTAG(%a6),%d1
10790 beq.l sscale
10791 cmpi.b %d1,&ZERO
10792 beq.l dst_zero
10793 cmpi.b %d1,&INF
10794 beq.l dst_inf
10795 cmpi.b %d1,&DENORM
10796 beq.l sscale
10797 bra.l dst_qnan
10798
10799 global sscale_sinf
10800sscale_sinf:
10801 mov.b DTAG(%a6),%d1
10802 beq.l t_operr
10803 cmpi.b %d1,&QNAN
10804 beq.l dst_qnan
10805 bra.l t_operr
10806
10807########################################################################
10808
10809 global sop_sqnan
10810sop_sqnan:
10811 mov.b DTAG(%a6),%d1
10812 cmpi.b %d1,&QNAN
10813 beq.l dst_qnan
10814 bra.l src_qnan
10815
10816#########################################################################
10817# norm(): normalize the mantissa of an extended precision input. the #
10818# input operand should not be normalized already. #
10819# #
10820# XDEF **************************************************************** #
10821# norm() #
10822# #
10823# XREF **************************************************************** #
10824# none #
10825# #
10826# INPUT *************************************************************** #
10827# a0 = pointer fp extended precision operand to normalize #
10828# #
10829# OUTPUT ************************************************************** #
10830# d0 = number of bit positions the mantissa was shifted #
10831# a0 = the input operand's mantissa is normalized; the exponent #
10832# is unchanged. #
10833# #
10834#########################################################################
10835 global norm
10836norm:
10837 mov.l %d2, -(%sp) # create some temp regs
10838 mov.l %d3, -(%sp)
10839
10840 mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)
10841 mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)
10842
10843 bfffo %d0{&0:&32}, %d2 # how many places to shift?
10844 beq.b norm_lo # hi(man) is all zeroes!
10845
10846norm_hi:
10847 lsl.l %d2, %d0 # left shift hi(man)
10848 bfextu %d1{&0:%d2}, %d3 # extract lo bits
10849
10850 or.l %d3, %d0 # create hi(man)
10851 lsl.l %d2, %d1 # create lo(man)
10852
10853 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
10854 mov.l %d1, FTEMP_LO(%a0) # store new lo(man)
10855
10856 mov.l %d2, %d0 # return shift amount
10857
10858 mov.l (%sp)+, %d3 # restore temp regs
10859 mov.l (%sp)+, %d2
10860
10861 rts
10862
10863norm_lo:
10864 bfffo %d1{&0:&32}, %d2 # how many places to shift?
10865 lsl.l %d2, %d1 # shift lo(man)
10866 add.l &32, %d2 # add 32 to shft amount
10867
10868 mov.l %d1, FTEMP_HI(%a0) # store hi(man)
10869 clr.l FTEMP_LO(%a0) # lo(man) is now zero
10870
10871 mov.l %d2, %d0 # return shift amount
10872
10873 mov.l (%sp)+, %d3 # restore temp regs
10874 mov.l (%sp)+, %d2
10875
10876 rts
10877
10878#########################################################################
10879# unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #
10880# - returns corresponding optype tag #
10881# #
10882# XDEF **************************************************************** #
10883# unnorm_fix() #
10884# #
10885# XREF **************************************************************** #
10886# norm() - normalize the mantissa #
10887# #
10888# INPUT *************************************************************** #
10889# a0 = pointer to unnormalized extended precision number #
10890# #
10891# OUTPUT ************************************************************** #
10892# d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #
10893# a0 = input operand has been converted to a norm, denorm, or #
10894# zero; both the exponent and mantissa are changed. #
10895# #
10896#########################################################################
10897
10898 global unnorm_fix
10899unnorm_fix:
10900 bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
10901 bne.b unnorm_shift # hi(man) is not all zeroes
10902
10903#
10904# hi(man) is all zeroes so see if any bits in lo(man) are set
10905#
10906unnorm_chk_lo:
10907 bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
10908 beq.w unnorm_zero # yes
10909
10910 add.w &32, %d0 # no; fix shift distance
10911
10912#
10913# d0 = # shifts needed for complete normalization
10914#
10915unnorm_shift:
10916 clr.l %d1 # clear top word
10917 mov.w FTEMP_EX(%a0), %d1 # extract exponent
10918 and.w &0x7fff, %d1 # strip off sgn
10919
10920 cmp.w %d0, %d1 # will denorm push exp < 0?
10921 bgt.b unnorm_nrm_zero # yes; denorm only until exp = 0
10922
10923#
10924# exponent would not go < 0. therefore, number stays normalized
10925#
10926 sub.w %d0, %d1 # shift exponent value
10927 mov.w FTEMP_EX(%a0), %d0 # load old exponent
10928 and.w &0x8000, %d0 # save old sign
10929 or.w %d0, %d1 # {sgn,new exp}
10930 mov.w %d1, FTEMP_EX(%a0) # insert new exponent
10931
10932 bsr.l norm # normalize UNNORM
10933
10934 mov.b &NORM, %d0 # return new optype tag
10935 rts
10936
10937#
10938# exponent would go < 0, so only denormalize until exp = 0
10939#
10940unnorm_nrm_zero:
10941 cmp.b %d1, &32 # is exp <= 32?
10942 bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent
10943
10944 bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
10945 mov.l %d0, FTEMP_HI(%a0) # save new hi(man)
10946
10947 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
10948 lsl.l %d1, %d0 # extract new lo(man)
10949 mov.l %d0, FTEMP_LO(%a0) # save new lo(man)
10950
10951 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
10952
10953 mov.b &DENORM, %d0 # return new optype tag
10954 rts
10955
10956#
10957# only mantissa bits set are in lo(man)
10958#
10959unnorm_nrm_zero_lrg:
10960 sub.w &32, %d1 # adjust shft amt by 32
10961
10962 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
10963 lsl.l %d1, %d0 # left shift lo(man)
10964
10965 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
10966 clr.l FTEMP_LO(%a0) # lo(man) = 0
10967
10968 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
10969
10970 mov.b &DENORM, %d0 # return new optype tag
10971 rts
10972
10973#
10974# whole mantissa is zero so this UNNORM is actually a zero
10975#
10976unnorm_zero:
10977 and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero
10978
10979 mov.b &ZERO, %d0 # fix optype tag
10980 rts
diff --git a/arch/m68k/ifpsp060/src/fpsp.S b/arch/m68k/ifpsp060/src/fpsp.S
new file mode 100644
index 000000000000..3b597a9bbf43
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/fpsp.S
@@ -0,0 +1,24785 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29#
30# freal.s:
31# This file is appended to the top of the 060FPSP package
32# and contains the entry points into the package. The user, in
33# effect, branches to one of the branch table entries located
34# after _060FPSP_TABLE.
35# Also, subroutine stubs exist in this file (_fpsp_done for
36# example) that are referenced by the FPSP package itself in order
37# to call a given routine. The stub routine actually performs the
38# callout. The FPSP code does a "bsr" to the stub routine. This
39# extra layer of hierarchy adds a slight performance penalty but
40# it makes the FPSP code easier to read and more mainatinable.
41#
42
43set _off_bsun, 0x00
44set _off_snan, 0x04
45set _off_operr, 0x08
46set _off_ovfl, 0x0c
47set _off_unfl, 0x10
48set _off_dz, 0x14
49set _off_inex, 0x18
50set _off_fline, 0x1c
51set _off_fpu_dis, 0x20
52set _off_trap, 0x24
53set _off_trace, 0x28
54set _off_access, 0x2c
55set _off_done, 0x30
56
57set _off_imr, 0x40
58set _off_dmr, 0x44
59set _off_dmw, 0x48
60set _off_irw, 0x4c
61set _off_irl, 0x50
62set _off_drb, 0x54
63set _off_drw, 0x58
64set _off_drl, 0x5c
65set _off_dwb, 0x60
66set _off_dww, 0x64
67set _off_dwl, 0x68
68
69_060FPSP_TABLE:
70
71###############################################################
72
73# Here's the table of ENTRY POINTS for those linking the package.
74 bra.l _fpsp_snan
75 short 0x0000
76 bra.l _fpsp_operr
77 short 0x0000
78 bra.l _fpsp_ovfl
79 short 0x0000
80 bra.l _fpsp_unfl
81 short 0x0000
82 bra.l _fpsp_dz
83 short 0x0000
84 bra.l _fpsp_inex
85 short 0x0000
86 bra.l _fpsp_fline
87 short 0x0000
88 bra.l _fpsp_unsupp
89 short 0x0000
90 bra.l _fpsp_effadd
91 short 0x0000
92
93 space 56
94
95###############################################################
96 global _fpsp_done
97_fpsp_done:
98 mov.l %d0,-(%sp)
99 mov.l (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
100 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
101 mov.l 0x4(%sp),%d0
102 rtd &0x4
103
104 global _real_ovfl
105_real_ovfl:
106 mov.l %d0,-(%sp)
107 mov.l (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
108 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
109 mov.l 0x4(%sp),%d0
110 rtd &0x4
111
112 global _real_unfl
113_real_unfl:
114 mov.l %d0,-(%sp)
115 mov.l (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
116 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
117 mov.l 0x4(%sp),%d0
118 rtd &0x4
119
120 global _real_inex
121_real_inex:
122 mov.l %d0,-(%sp)
123 mov.l (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
124 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
125 mov.l 0x4(%sp),%d0
126 rtd &0x4
127
128 global _real_bsun
129_real_bsun:
130 mov.l %d0,-(%sp)
131 mov.l (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
132 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
133 mov.l 0x4(%sp),%d0
134 rtd &0x4
135
136 global _real_operr
137_real_operr:
138 mov.l %d0,-(%sp)
139 mov.l (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
140 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
141 mov.l 0x4(%sp),%d0
142 rtd &0x4
143
144 global _real_snan
145_real_snan:
146 mov.l %d0,-(%sp)
147 mov.l (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
148 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
149 mov.l 0x4(%sp),%d0
150 rtd &0x4
151
152 global _real_dz
153_real_dz:
154 mov.l %d0,-(%sp)
155 mov.l (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
156 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
157 mov.l 0x4(%sp),%d0
158 rtd &0x4
159
160 global _real_fline
161_real_fline:
162 mov.l %d0,-(%sp)
163 mov.l (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
164 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
165 mov.l 0x4(%sp),%d0
166 rtd &0x4
167
168 global _real_fpu_disabled
169_real_fpu_disabled:
170 mov.l %d0,-(%sp)
171 mov.l (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
172 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
173 mov.l 0x4(%sp),%d0
174 rtd &0x4
175
176 global _real_trap
177_real_trap:
178 mov.l %d0,-(%sp)
179 mov.l (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
180 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
181 mov.l 0x4(%sp),%d0
182 rtd &0x4
183
184 global _real_trace
185_real_trace:
186 mov.l %d0,-(%sp)
187 mov.l (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
188 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
189 mov.l 0x4(%sp),%d0
190 rtd &0x4
191
192 global _real_access
193_real_access:
194 mov.l %d0,-(%sp)
195 mov.l (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
196 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
197 mov.l 0x4(%sp),%d0
198 rtd &0x4
199
200#######################################
201
202 global _imem_read
203_imem_read:
204 mov.l %d0,-(%sp)
205 mov.l (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
206 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
207 mov.l 0x4(%sp),%d0
208 rtd &0x4
209
210 global _dmem_read
211_dmem_read:
212 mov.l %d0,-(%sp)
213 mov.l (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
214 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
215 mov.l 0x4(%sp),%d0
216 rtd &0x4
217
218 global _dmem_write
219_dmem_write:
220 mov.l %d0,-(%sp)
221 mov.l (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
222 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
223 mov.l 0x4(%sp),%d0
224 rtd &0x4
225
226 global _imem_read_word
227_imem_read_word:
228 mov.l %d0,-(%sp)
229 mov.l (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
230 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
231 mov.l 0x4(%sp),%d0
232 rtd &0x4
233
234 global _imem_read_long
235_imem_read_long:
236 mov.l %d0,-(%sp)
237 mov.l (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
238 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
239 mov.l 0x4(%sp),%d0
240 rtd &0x4
241
242 global _dmem_read_byte
243_dmem_read_byte:
244 mov.l %d0,-(%sp)
245 mov.l (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
246 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
247 mov.l 0x4(%sp),%d0
248 rtd &0x4
249
250 global _dmem_read_word
251_dmem_read_word:
252 mov.l %d0,-(%sp)
253 mov.l (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
254 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
255 mov.l 0x4(%sp),%d0
256 rtd &0x4
257
258 global _dmem_read_long
259_dmem_read_long:
260 mov.l %d0,-(%sp)
261 mov.l (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
262 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
263 mov.l 0x4(%sp),%d0
264 rtd &0x4
265
266 global _dmem_write_byte
267_dmem_write_byte:
268 mov.l %d0,-(%sp)
269 mov.l (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
270 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
271 mov.l 0x4(%sp),%d0
272 rtd &0x4
273
274 global _dmem_write_word
275_dmem_write_word:
276 mov.l %d0,-(%sp)
277 mov.l (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
278 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
279 mov.l 0x4(%sp),%d0
280 rtd &0x4
281
282 global _dmem_write_long
283_dmem_write_long:
284 mov.l %d0,-(%sp)
285 mov.l (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
286 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
287 mov.l 0x4(%sp),%d0
288 rtd &0x4
289
290#
291# This file contains a set of define statements for constants
292# in order to promote readability within the corecode itself.
293#
294
295set LOCAL_SIZE, 192 # stack frame size(bytes)
296set LV, -LOCAL_SIZE # stack offset
297
298set EXC_SR, 0x4 # stack status register
299set EXC_PC, 0x6 # stack pc
300set EXC_VOFF, 0xa # stacked vector offset
301set EXC_EA, 0xc # stacked <ea>
302
303set EXC_FP, 0x0 # frame pointer
304
305set EXC_AREGS, -68 # offset of all address regs
306set EXC_DREGS, -100 # offset of all data regs
307set EXC_FPREGS, -36 # offset of all fp regs
308
309set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
310set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
311set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
312set EXC_A5, EXC_AREGS+(5*4)
313set EXC_A4, EXC_AREGS+(4*4)
314set EXC_A3, EXC_AREGS+(3*4)
315set EXC_A2, EXC_AREGS+(2*4)
316set EXC_A1, EXC_AREGS+(1*4)
317set EXC_A0, EXC_AREGS+(0*4)
318set EXC_D7, EXC_DREGS+(7*4)
319set EXC_D6, EXC_DREGS+(6*4)
320set EXC_D5, EXC_DREGS+(5*4)
321set EXC_D4, EXC_DREGS+(4*4)
322set EXC_D3, EXC_DREGS+(3*4)
323set EXC_D2, EXC_DREGS+(2*4)
324set EXC_D1, EXC_DREGS+(1*4)
325set EXC_D0, EXC_DREGS+(0*4)
326
327set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
328set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
329set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
330
331set FP_SCR1, LV+80 # fp scratch 1
332set FP_SCR1_EX, FP_SCR1+0
333set FP_SCR1_SGN, FP_SCR1+2
334set FP_SCR1_HI, FP_SCR1+4
335set FP_SCR1_LO, FP_SCR1+8
336
337set FP_SCR0, LV+68 # fp scratch 0
338set FP_SCR0_EX, FP_SCR0+0
339set FP_SCR0_SGN, FP_SCR0+2
340set FP_SCR0_HI, FP_SCR0+4
341set FP_SCR0_LO, FP_SCR0+8
342
343set FP_DST, LV+56 # fp destination operand
344set FP_DST_EX, FP_DST+0
345set FP_DST_SGN, FP_DST+2
346set FP_DST_HI, FP_DST+4
347set FP_DST_LO, FP_DST+8
348
349set FP_SRC, LV+44 # fp source operand
350set FP_SRC_EX, FP_SRC+0
351set FP_SRC_SGN, FP_SRC+2
352set FP_SRC_HI, FP_SRC+4
353set FP_SRC_LO, FP_SRC+8
354
355set USER_FPIAR, LV+40 # FP instr address register
356
357set USER_FPSR, LV+36 # FP status register
358set FPSR_CC, USER_FPSR+0 # FPSR condition codes
359set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
360set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
361set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
362
363set USER_FPCR, LV+32 # FP control register
364set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
365set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
366
367set L_SCR3, LV+28 # integer scratch 3
368set L_SCR2, LV+24 # integer scratch 2
369set L_SCR1, LV+20 # integer scratch 1
370
371set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
372
373set EXC_TEMP2, LV+24 # temporary space
374set EXC_TEMP, LV+16 # temporary space
375
376set DTAG, LV+15 # destination operand type
377set STAG, LV+14 # source operand type
378
379set SPCOND_FLG, LV+10 # flag: special case (see below)
380
381set EXC_CC, LV+8 # saved condition codes
382set EXC_EXTWPTR, LV+4 # saved current PC (active)
383set EXC_EXTWORD, LV+2 # saved extension word
384set EXC_CMDREG, LV+2 # saved extension word
385set EXC_OPWORD, LV+0 # saved operation word
386
387################################
388
389# Helpful macros
390
391set FTEMP, 0 # offsets within an
392set FTEMP_EX, 0 # extended precision
393set FTEMP_SGN, 2 # value saved in memory.
394set FTEMP_HI, 4
395set FTEMP_LO, 8
396set FTEMP_GRS, 12
397
398set LOCAL, 0 # offsets within an
399set LOCAL_EX, 0 # extended precision
400set LOCAL_SGN, 2 # value saved in memory.
401set LOCAL_HI, 4
402set LOCAL_LO, 8
403set LOCAL_GRS, 12
404
405set DST, 0 # offsets within an
406set DST_EX, 0 # extended precision
407set DST_HI, 4 # value saved in memory.
408set DST_LO, 8
409
410set SRC, 0 # offsets within an
411set SRC_EX, 0 # extended precision
412set SRC_HI, 4 # value saved in memory.
413set SRC_LO, 8
414
415set SGL_LO, 0x3f81 # min sgl prec exponent
416set SGL_HI, 0x407e # max sgl prec exponent
417set DBL_LO, 0x3c01 # min dbl prec exponent
418set DBL_HI, 0x43fe # max dbl prec exponent
419set EXT_LO, 0x0 # min ext prec exponent
420set EXT_HI, 0x7ffe # max ext prec exponent
421
422set EXT_BIAS, 0x3fff # extended precision bias
423set SGL_BIAS, 0x007f # single precision bias
424set DBL_BIAS, 0x03ff # double precision bias
425
426set NORM, 0x00 # operand type for STAG/DTAG
427set ZERO, 0x01 # operand type for STAG/DTAG
428set INF, 0x02 # operand type for STAG/DTAG
429set QNAN, 0x03 # operand type for STAG/DTAG
430set DENORM, 0x04 # operand type for STAG/DTAG
431set SNAN, 0x05 # operand type for STAG/DTAG
432set UNNORM, 0x06 # operand type for STAG/DTAG
433
434##################
435# FPSR/FPCR bits #
436##################
437set neg_bit, 0x3 # negative result
438set z_bit, 0x2 # zero result
439set inf_bit, 0x1 # infinite result
440set nan_bit, 0x0 # NAN result
441
442set q_sn_bit, 0x7 # sign bit of quotient byte
443
444set bsun_bit, 7 # branch on unordered
445set snan_bit, 6 # signalling NAN
446set operr_bit, 5 # operand error
447set ovfl_bit, 4 # overflow
448set unfl_bit, 3 # underflow
449set dz_bit, 2 # divide by zero
450set inex2_bit, 1 # inexact result 2
451set inex1_bit, 0 # inexact result 1
452
453set aiop_bit, 7 # accrued inexact operation bit
454set aovfl_bit, 6 # accrued overflow bit
455set aunfl_bit, 5 # accrued underflow bit
456set adz_bit, 4 # accrued dz bit
457set ainex_bit, 3 # accrued inexact bit
458
459#############################
460# FPSR individual bit masks #
461#############################
462set neg_mask, 0x08000000 # negative bit mask (lw)
463set inf_mask, 0x02000000 # infinity bit mask (lw)
464set z_mask, 0x04000000 # zero bit mask (lw)
465set nan_mask, 0x01000000 # nan bit mask (lw)
466
467set neg_bmask, 0x08 # negative bit mask (byte)
468set inf_bmask, 0x02 # infinity bit mask (byte)
469set z_bmask, 0x04 # zero bit mask (byte)
470set nan_bmask, 0x01 # nan bit mask (byte)
471
472set bsun_mask, 0x00008000 # bsun exception mask
473set snan_mask, 0x00004000 # snan exception mask
474set operr_mask, 0x00002000 # operr exception mask
475set ovfl_mask, 0x00001000 # overflow exception mask
476set unfl_mask, 0x00000800 # underflow exception mask
477set dz_mask, 0x00000400 # dz exception mask
478set inex2_mask, 0x00000200 # inex2 exception mask
479set inex1_mask, 0x00000100 # inex1 exception mask
480
481set aiop_mask, 0x00000080 # accrued illegal operation
482set aovfl_mask, 0x00000040 # accrued overflow
483set aunfl_mask, 0x00000020 # accrued underflow
484set adz_mask, 0x00000010 # accrued divide by zero
485set ainex_mask, 0x00000008 # accrued inexact
486
487######################################
488# FPSR combinations used in the FPSP #
489######################################
490set dzinf_mask, inf_mask+dz_mask+adz_mask
491set opnan_mask, nan_mask+operr_mask+aiop_mask
492set nzi_mask, 0x01ffffff #clears N, Z, and I
493set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
494set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
495set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
496set inx1a_mask, inex1_mask+ainex_mask
497set inx2a_mask, inex2_mask+ainex_mask
498set snaniop_mask, nan_mask+snan_mask+aiop_mask
499set snaniop2_mask, snan_mask+aiop_mask
500set naniop_mask, nan_mask+aiop_mask
501set neginf_mask, neg_mask+inf_mask
502set infaiop_mask, inf_mask+aiop_mask
503set negz_mask, neg_mask+z_mask
504set opaop_mask, operr_mask+aiop_mask
505set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
506set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
507
508#########
509# misc. #
510#########
511set rnd_stky_bit, 29 # stky bit pos in longword
512
513set sign_bit, 0x7 # sign bit
514set signan_bit, 0x6 # signalling nan bit
515
516set sgl_thresh, 0x3f81 # minimum sgl exponent
517set dbl_thresh, 0x3c01 # minimum dbl exponent
518
519set x_mode, 0x0 # extended precision
520set s_mode, 0x4 # single precision
521set d_mode, 0x8 # double precision
522
523set rn_mode, 0x0 # round-to-nearest
524set rz_mode, 0x1 # round-to-zero
525set rm_mode, 0x2 # round-tp-minus-infinity
526set rp_mode, 0x3 # round-to-plus-infinity
527
528set mantissalen, 64 # length of mantissa in bits
529
530set BYTE, 1 # len(byte) == 1 byte
531set WORD, 2 # len(word) == 2 bytes
532set LONG, 4 # len(longword) == 2 bytes
533
534set BSUN_VEC, 0xc0 # bsun vector offset
535set INEX_VEC, 0xc4 # inexact vector offset
536set DZ_VEC, 0xc8 # dz vector offset
537set UNFL_VEC, 0xcc # unfl vector offset
538set OPERR_VEC, 0xd0 # operr vector offset
539set OVFL_VEC, 0xd4 # ovfl vector offset
540set SNAN_VEC, 0xd8 # snan vector offset
541
542###########################
543# SPecial CONDition FLaGs #
544###########################
545set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
546set fbsun_flg, 0x02 # flag bit: bsun exception
547set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
548set mda7_flg, 0x08 # flag bit: -(a7) <ea>
549set fmovm_flg, 0x40 # flag bit: fmovm instruction
550set immed_flg, 0x80 # flag bit: &<data> <ea>
551
552set ftrapcc_bit, 0x0
553set fbsun_bit, 0x1
554set mia7_bit, 0x2
555set mda7_bit, 0x3
556set immed_bit, 0x7
557
558##################################
559# TRANSCENDENTAL "LAST-OP" FLAGS #
560##################################
561set FMUL_OP, 0x0 # fmul instr performed last
562set FDIV_OP, 0x1 # fdiv performed last
563set FADD_OP, 0x2 # fadd performed last
564set FMOV_OP, 0x3 # fmov performed last
565
566#############
567# CONSTANTS #
568#############
569T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
570T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
571
572PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
573PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
574
575TWOBYPI:
576 long 0x3FE45F30,0x6DC9C883
577
578#########################################################################
579# XDEF **************************************************************** #
580# _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception. #
581# #
582# This handler should be the first code executed upon taking the #
583# FP Overflow exception in an operating system. #
584# #
585# XREF **************************************************************** #
586# _imem_read_long() - read instruction longword #
587# fix_skewed_ops() - adjust src operand in fsave frame #
588# set_tag_x() - determine optype of src/dst operands #
589# store_fpreg() - store opclass 0 or 2 result to FP regfile #
590# unnorm_fix() - change UNNORM operands to NORM or ZERO #
591# load_fpn2() - load dst operand from FP regfile #
592# fout() - emulate an opclass 3 instruction #
593# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
594# _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
595# _real_ovfl() - "callout" for Overflow exception enabled code #
596# _real_inex() - "callout" for Inexact exception enabled code #
597# _real_trace() - "callout" for Trace exception code #
598# #
599# INPUT *************************************************************** #
600# - The system stack contains the FP Ovfl exception stack frame #
601# - The fsave frame contains the source operand #
602# #
603# OUTPUT ************************************************************** #
604# Overflow Exception enabled: #
605# - The system stack is unchanged #
606# - The fsave frame contains the adjusted src op for opclass 0,2 #
607# Overflow Exception disabled: #
608# - The system stack is unchanged #
609# - The "exception present" flag in the fsave frame is cleared #
610# #
611# ALGORITHM *********************************************************** #
612# On the 060, if an FP overflow is present as the result of any #
613# instruction, the 060 will take an overflow exception whether the #
614# exception is enabled or disabled in the FPCR. For the disabled case, #
615# This handler emulates the instruction to determine what the correct #
616# default result should be for the operation. This default result is #
617# then stored in either the FP regfile, data regfile, or memory. #
618# Finally, the handler exits through the "callout" _fpsp_done() #
619# denoting that no exceptional conditions exist within the machine. #
620# If the exception is enabled, then this handler must create the #
621# exceptional operand and plave it in the fsave state frame, and store #
622# the default result (only if the instruction is opclass 3). For #
623# exceptions enabled, this handler must exit through the "callout" #
624# _real_ovfl() so that the operating system enabled overflow handler #
625# can handle this case. #
626# Two other conditions exist. First, if overflow was disabled #
627# but the inexact exception was enabled, this handler must exit #
628# through the "callout" _real_inex() regardless of whether the result #
629# was inexact. #
630# Also, in the case of an opclass three instruction where #
631# overflow was disabled and the trace exception was enabled, this #
632# handler must exit through the "callout" _real_trace(). #
633# #
634#########################################################################
635
636 global _fpsp_ovfl
637_fpsp_ovfl:
638
639#$# sub.l &24,%sp # make room for src/dst
640
641 link.w %a6,&-LOCAL_SIZE # init stack frame
642
643 fsave FP_SRC(%a6) # grab the "busy" frame
644
645 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
646 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
647 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
648
649# the FPIAR holds the "current PC" of the faulting instruction
650 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
651 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
652 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
653 bsr.l _imem_read_long # fetch the instruction words
654 mov.l %d0,EXC_OPWORD(%a6)
655
656##############################################################################
657
658 btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
659 bne.w fovfl_out
660
661
662 lea FP_SRC(%a6),%a0 # pass: ptr to src op
663 bsr.l fix_skewed_ops # fix src op
664
665# since, I believe, only NORMs and DENORMs can come through here,
666# maybe we can avoid the subroutine call.
667 lea FP_SRC(%a6),%a0 # pass: ptr to src op
668 bsr.l set_tag_x # tag the operand type
669 mov.b %d0,STAG(%a6) # maybe NORM,DENORM
670
671# bit five of the fp extension word separates the monadic and dyadic operations
672# that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
673# will never take this exception.
674 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
675 beq.b fovfl_extract # monadic
676
677 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
678 bsr.l load_fpn2 # load dst into FP_DST
679
680 lea FP_DST(%a6),%a0 # pass: ptr to dst op
681 bsr.l set_tag_x # tag the operand type
682 cmpi.b %d0,&UNNORM # is operand an UNNORM?
683 bne.b fovfl_op2_done # no
684 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
685fovfl_op2_done:
686 mov.b %d0,DTAG(%a6) # save dst optype tag
687
688fovfl_extract:
689
690#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
691#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
692#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
693#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
694#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
695#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
696
697 clr.l %d0
698 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
699
700 mov.b 1+EXC_CMDREG(%a6),%d1
701 andi.w &0x007f,%d1 # extract extension
702
703 andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
704
705 fmov.l &0x0,%fpcr # zero current control regs
706 fmov.l &0x0,%fpsr
707
708 lea FP_SRC(%a6),%a0
709 lea FP_DST(%a6),%a1
710
711# maybe we can make these entry points ONLY the OVFL entry points of each routine.
712 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
713 jsr (tbl_unsupp.l,%pc,%d1.l*1)
714
715# the operation has been emulated. the result is in fp0.
716# the EXOP, if an exception occurred, is in fp1.
717# we must save the default result regardless of whether
718# traps are enabled or disabled.
719 bfextu EXC_CMDREG(%a6){&6:&3},%d0
720 bsr.l store_fpreg
721
722# the exceptional possibilities we have left ourselves with are ONLY overflow
723# and inexact. and, the inexact is such that overflow occurred and was disabled
724# but inexact was enabled.
725 btst &ovfl_bit,FPCR_ENABLE(%a6)
726 bne.b fovfl_ovfl_on
727
728 btst &inex2_bit,FPCR_ENABLE(%a6)
729 bne.b fovfl_inex_on
730
731 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
732 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
733 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
734
735 unlk %a6
736#$# add.l &24,%sp
737 bra.l _fpsp_done
738
739# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
740# in fp1. now, simply jump to _real_ovfl()!
741fovfl_ovfl_on:
742 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
743
744 mov.w &0xe005,2+FP_SRC(%a6) # save exc status
745
746 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
747 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
748 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
749
750 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
751
752 unlk %a6
753
754 bra.l _real_ovfl
755
756# overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
757# we must jump to real_inex().
758fovfl_inex_on:
759
760 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
761
762 mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
763 mov.w &0xe001,2+FP_SRC(%a6) # save exc status
764
765 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
766 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
767 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
768
769 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
770
771 unlk %a6
772
773 bra.l _real_inex
774
775########################################################################
776fovfl_out:
777
778
779#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
780#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
781#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
782
783# the src operand is definitely a NORM(!), so tag it as such
784 mov.b &NORM,STAG(%a6) # set src optype tag
785
786 clr.l %d0
787 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
788
789 and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
790
791 fmov.l &0x0,%fpcr # zero current control regs
792 fmov.l &0x0,%fpsr
793
794 lea FP_SRC(%a6),%a0 # pass ptr to src operand
795
796 bsr.l fout
797
798 btst &ovfl_bit,FPCR_ENABLE(%a6)
799 bne.w fovfl_ovfl_on
800
801 btst &inex2_bit,FPCR_ENABLE(%a6)
802 bne.w fovfl_inex_on
803
804 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
805 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
806 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
807
808 unlk %a6
809#$# add.l &24,%sp
810
811 btst &0x7,(%sp) # is trace on?
812 beq.l _fpsp_done # no
813
814 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
815 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
816 bra.l _real_trace
817
818#########################################################################
819# XDEF **************************************************************** #
820# _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. #
821# #
822# This handler should be the first code executed upon taking the #
823# FP Underflow exception in an operating system. #
824# #
825# XREF **************************************************************** #
826# _imem_read_long() - read instruction longword #
827# fix_skewed_ops() - adjust src operand in fsave frame #
828# set_tag_x() - determine optype of src/dst operands #
829# store_fpreg() - store opclass 0 or 2 result to FP regfile #
830# unnorm_fix() - change UNNORM operands to NORM or ZERO #
831# load_fpn2() - load dst operand from FP regfile #
832# fout() - emulate an opclass 3 instruction #
833# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
834# _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
835# _real_ovfl() - "callout" for Overflow exception enabled code #
836# _real_inex() - "callout" for Inexact exception enabled code #
837# _real_trace() - "callout" for Trace exception code #
838# #
839# INPUT *************************************************************** #
840# - The system stack contains the FP Unfl exception stack frame #
841# - The fsave frame contains the source operand #
842# #
843# OUTPUT ************************************************************** #
844# Underflow Exception enabled: #
845# - The system stack is unchanged #
846# - The fsave frame contains the adjusted src op for opclass 0,2 #
847# Underflow Exception disabled: #
848# - The system stack is unchanged #
849# - The "exception present" flag in the fsave frame is cleared #
850# #
851# ALGORITHM *********************************************************** #
852# On the 060, if an FP underflow is present as the result of any #
853# instruction, the 060 will take an underflow exception whether the #
854# exception is enabled or disabled in the FPCR. For the disabled case, #
855# This handler emulates the instruction to determine what the correct #
856# default result should be for the operation. This default result is #
857# then stored in either the FP regfile, data regfile, or memory. #
858# Finally, the handler exits through the "callout" _fpsp_done() #
859# denoting that no exceptional conditions exist within the machine. #
860# If the exception is enabled, then this handler must create the #
861# exceptional operand and plave it in the fsave state frame, and store #
862# the default result (only if the instruction is opclass 3). For #
863# exceptions enabled, this handler must exit through the "callout" #
864# _real_unfl() so that the operating system enabled overflow handler #
865# can handle this case. #
866# Two other conditions exist. First, if underflow was disabled #
867# but the inexact exception was enabled and the result was inexact, #
868# this handler must exit through the "callout" _real_inex(). #
869# was inexact. #
870# Also, in the case of an opclass three instruction where #
871# underflow was disabled and the trace exception was enabled, this #
872# handler must exit through the "callout" _real_trace(). #
873# #
874#########################################################################
875
876 global _fpsp_unfl
877_fpsp_unfl:
878
879#$# sub.l &24,%sp # make room for src/dst
880
881 link.w %a6,&-LOCAL_SIZE # init stack frame
882
883 fsave FP_SRC(%a6) # grab the "busy" frame
884
885 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
886 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
887 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
888
889# the FPIAR holds the "current PC" of the faulting instruction
890 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
891 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
892 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
893 bsr.l _imem_read_long # fetch the instruction words
894 mov.l %d0,EXC_OPWORD(%a6)
895
896##############################################################################
897
898 btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
899 bne.w funfl_out
900
901
902 lea FP_SRC(%a6),%a0 # pass: ptr to src op
903 bsr.l fix_skewed_ops # fix src op
904
905 lea FP_SRC(%a6),%a0 # pass: ptr to src op
906 bsr.l set_tag_x # tag the operand type
907 mov.b %d0,STAG(%a6) # maybe NORM,DENORM
908
909# bit five of the fp ext word separates the monadic and dyadic operations
910# that can pass through fpsp_unfl(). remember that fcmp, and ftst
911# will never take this exception.
912 btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic?
913 beq.b funfl_extract # monadic
914
915# now, what's left that's not dyadic is fsincos. we can distinguish it
916# from all dyadics by the '0110xxx pattern
917 btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos?
918 bne.b funfl_extract # yes
919
920 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
921 bsr.l load_fpn2 # load dst into FP_DST
922
923 lea FP_DST(%a6),%a0 # pass: ptr to dst op
924 bsr.l set_tag_x # tag the operand type
925 cmpi.b %d0,&UNNORM # is operand an UNNORM?
926 bne.b funfl_op2_done # no
927 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
928funfl_op2_done:
929 mov.b %d0,DTAG(%a6) # save dst optype tag
930
931funfl_extract:
932
933#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
934#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
935#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
936#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
937#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
938#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
939
940 clr.l %d0
941 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
942
943 mov.b 1+EXC_CMDREG(%a6),%d1
944 andi.w &0x007f,%d1 # extract extension
945
946 andi.l &0x00ff01ff,USER_FPSR(%a6)
947
948 fmov.l &0x0,%fpcr # zero current control regs
949 fmov.l &0x0,%fpsr
950
951 lea FP_SRC(%a6),%a0
952 lea FP_DST(%a6),%a1
953
954# maybe we can make these entry points ONLY the OVFL entry points of each routine.
955 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
956 jsr (tbl_unsupp.l,%pc,%d1.l*1)
957
958 bfextu EXC_CMDREG(%a6){&6:&3},%d0
959 bsr.l store_fpreg
960
961# The `060 FPU multiplier hardware is such that if the result of a
962# multiply operation is the smallest possible normalized number
963# (0x00000000_80000000_00000000), then the machine will take an
964# underflow exception. Since this is incorrect, we need to check
965# if our emulation, after re-doing the operation, decided that
966# no underflow was called for. We do these checks only in
967# funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
968# special case will simply exit gracefully with the correct result.
969
970# the exceptional possibilities we have left ourselves with are ONLY overflow
971# and inexact. and, the inexact is such that overflow occurred and was disabled
972# but inexact was enabled.
973 btst &unfl_bit,FPCR_ENABLE(%a6)
974 bne.b funfl_unfl_on
975
976funfl_chkinex:
977 btst &inex2_bit,FPCR_ENABLE(%a6)
978 bne.b funfl_inex_on
979
980funfl_exit:
981 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
982 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
983 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
984
985 unlk %a6
986#$# add.l &24,%sp
987 bra.l _fpsp_done
988
989# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
990# in fp1 (don't forget to save fp0). what to do now?
991# well, we simply have to get to go to _real_unfl()!
992funfl_unfl_on:
993
994# The `060 FPU multiplier hardware is such that if the result of a
995# multiply operation is the smallest possible normalized number
996# (0x00000000_80000000_00000000), then the machine will take an
997# underflow exception. Since this is incorrect, we check here to see
998# if our emulation, after re-doing the operation, decided that
999# no underflow was called for.
1000 btst &unfl_bit,FPSR_EXCEPT(%a6)
1001 beq.w funfl_chkinex
1002
1003funfl_unfl_on2:
1004 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
1005
1006 mov.w &0xe003,2+FP_SRC(%a6) # save exc status
1007
1008 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1009 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1010 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1011
1012 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
1013
1014 unlk %a6
1015
1016 bra.l _real_unfl
1017
1018# undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
1019# we must jump to real_inex().
1020funfl_inex_on:
1021
1022# The `060 FPU multiplier hardware is such that if the result of a
1023# multiply operation is the smallest possible normalized number
1024# (0x00000000_80000000_00000000), then the machine will take an
1025# underflow exception.
1026# But, whether bogus or not, if inexact is enabled AND it occurred,
1027# then we have to branch to real_inex.
1028
1029 btst &inex2_bit,FPSR_EXCEPT(%a6)
1030 beq.w funfl_exit
1031
1032funfl_inex_on2:
1033
1034 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to stack
1035
1036 mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
1037 mov.w &0xe001,2+FP_SRC(%a6) # save exc status
1038
1039 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1040 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1041 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1042
1043 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
1044
1045 unlk %a6
1046
1047 bra.l _real_inex
1048
1049#######################################################################
1050funfl_out:
1051
1052
1053#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
1054#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
1055#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
1056
1057# the src operand is definitely a NORM(!), so tag it as such
1058 mov.b &NORM,STAG(%a6) # set src optype tag
1059
1060 clr.l %d0
1061 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
1062
1063 and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
1064
1065 fmov.l &0x0,%fpcr # zero current control regs
1066 fmov.l &0x0,%fpsr
1067
1068 lea FP_SRC(%a6),%a0 # pass ptr to src operand
1069
1070 bsr.l fout
1071
1072 btst &unfl_bit,FPCR_ENABLE(%a6)
1073 bne.w funfl_unfl_on2
1074
1075 btst &inex2_bit,FPCR_ENABLE(%a6)
1076 bne.w funfl_inex_on2
1077
1078 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1079 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1080 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1081
1082 unlk %a6
1083#$# add.l &24,%sp
1084
1085 btst &0x7,(%sp) # is trace on?
1086 beq.l _fpsp_done # no
1087
1088 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
1089 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
1090 bra.l _real_trace
1091
1092#########################################################################
1093# XDEF **************************************************************** #
1094# _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented #
1095# Data Type" exception. #
1096# #
1097# This handler should be the first code executed upon taking the #
1098# FP Unimplemented Data Type exception in an operating system. #
1099# #
1100# XREF **************************************************************** #
1101# _imem_read_{word,long}() - read instruction word/longword #
1102# fix_skewed_ops() - adjust src operand in fsave frame #
1103# set_tag_x() - determine optype of src/dst operands #
1104# store_fpreg() - store opclass 0 or 2 result to FP regfile #
1105# unnorm_fix() - change UNNORM operands to NORM or ZERO #
1106# load_fpn2() - load dst operand from FP regfile #
1107# load_fpn1() - load src operand from FP regfile #
1108# fout() - emulate an opclass 3 instruction #
1109# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
1110# _real_inex() - "callout" to operating system inexact handler #
1111# _fpsp_done() - "callout" for exit; work all done #
1112# _real_trace() - "callout" for Trace enabled exception #
1113# funimp_skew() - adjust fsave src ops to "incorrect" value #
1114# _real_snan() - "callout" for SNAN exception #
1115# _real_operr() - "callout" for OPERR exception #
1116# _real_ovfl() - "callout" for OVFL exception #
1117# _real_unfl() - "callout" for UNFL exception #
1118# get_packed() - fetch packed operand from memory #
1119# #
1120# INPUT *************************************************************** #
1121# - The system stack contains the "Unimp Data Type" stk frame #
1122# - The fsave frame contains the ssrc op (for UNNORM/DENORM) #
1123# #
1124# OUTPUT ************************************************************** #
1125# If Inexact exception (opclass 3): #
1126# - The system stack is changed to an Inexact exception stk frame #
1127# If SNAN exception (opclass 3): #
1128# - The system stack is changed to an SNAN exception stk frame #
1129# If OPERR exception (opclass 3): #
1130# - The system stack is changed to an OPERR exception stk frame #
1131# If OVFL exception (opclass 3): #
1132# - The system stack is changed to an OVFL exception stk frame #
1133# If UNFL exception (opclass 3): #
1134# - The system stack is changed to an UNFL exception stack frame #
1135# If Trace exception enabled: #
1136# - The system stack is changed to a Trace exception stack frame #
1137# Else: (normal case) #
1138# - Correct result has been stored as appropriate #
1139# #
1140# ALGORITHM *********************************************************** #
1141# Two main instruction types can enter here: (1) DENORM or UNNORM #
1142# unimplemented data types. These can be either opclass 0,2 or 3 #
1143# instructions, and (2) PACKED unimplemented data format instructions #
1144# also of opclasses 0,2, or 3. #
1145# For UNNORM/DENORM opclass 0 and 2, the handler fetches the src #
1146# operand from the fsave state frame and the dst operand (if dyadic) #
1147# from the FP register file. The instruction is then emulated by #
1148# choosing an emulation routine from a table of routines indexed by #
1149# instruction type. Once the instruction has been emulated and result #
1150# saved, then we check to see if any enabled exceptions resulted from #
1151# instruction emulation. If none, then we exit through the "callout" #
1152# _fpsp_done(). If there is an enabled FP exception, then we insert #
1153# this exception into the FPU in the fsave state frame and then exit #
1154# through _fpsp_done(). #
1155# PACKED opclass 0 and 2 is similar in how the instruction is #
1156# emulated and exceptions handled. The differences occur in how the #
1157# handler loads the packed op (by calling get_packed() routine) and #
1158# by the fact that a Trace exception could be pending for PACKED ops. #
1159# If a Trace exception is pending, then the current exception stack #
1160# frame is changed to a Trace exception stack frame and an exit is #
1161# made through _real_trace(). #
1162# For UNNORM/DENORM opclass 3, the actual move out to memory is #
1163# performed by calling the routine fout(). If no exception should occur #
1164# as the result of emulation, then an exit either occurs through #
1165# _fpsp_done() or through _real_trace() if a Trace exception is pending #
1166# (a Trace stack frame must be created here, too). If an FP exception #
1167# should occur, then we must create an exception stack frame of that #
1168# type and jump to either _real_snan(), _real_operr(), _real_inex(), #
1169# _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3 #
1170# emulation is performed in a similar manner. #
1171# #
1172#########################################################################
1173
1174#
1175# (1) DENORM and UNNORM (unimplemented) data types:
1176#
1177# post-instruction
1178# *****************
1179# * EA *
1180# pre-instruction * *
1181# ***************** *****************
1182# * 0x0 * 0x0dc * * 0x3 * 0x0dc *
1183# ***************** *****************
1184# * Next * * Next *
1185# * PC * * PC *
1186# ***************** *****************
1187# * SR * * SR *
1188# ***************** *****************
1189#
1190# (2) PACKED format (unsupported) opclasses two and three:
1191# *****************
1192# * EA *
1193# * *
1194# *****************
1195# * 0x2 * 0x0dc *
1196# *****************
1197# * Next *
1198# * PC *
1199# *****************
1200# * SR *
1201# *****************
1202#
1203 global _fpsp_unsupp
1204_fpsp_unsupp:
1205
1206 link.w %a6,&-LOCAL_SIZE # init stack frame
1207
1208 fsave FP_SRC(%a6) # save fp state
1209
1210 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1211 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
1212 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
1213
1214 btst &0x5,EXC_SR(%a6) # user or supervisor mode?
1215 bne.b fu_s
1216fu_u:
1217 mov.l %usp,%a0 # fetch user stack pointer
1218 mov.l %a0,EXC_A7(%a6) # save on stack
1219 bra.b fu_cont
1220# if the exception is an opclass zero or two unimplemented data type
1221# exception, then the a7' calculated here is wrong since it doesn't
1222# stack an ea. however, we don't need an a7' for this case anyways.
1223fu_s:
1224 lea 0x4+EXC_EA(%a6),%a0 # load old a7'
1225 mov.l %a0,EXC_A7(%a6) # save on stack
1226
1227fu_cont:
1228
1229# the FPIAR holds the "current PC" of the faulting instruction
1230# the FPIAR should be set correctly for ALL exceptions passing through
1231# this point.
1232 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
1233 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1234 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1235 bsr.l _imem_read_long # fetch the instruction words
1236 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
1237
1238############################
1239
1240 clr.b SPCOND_FLG(%a6) # clear special condition flag
1241
1242# Separate opclass three (fpn-to-mem) ops since they have a different
1243# stack frame and protocol.
1244 btst &0x5,EXC_CMDREG(%a6) # is it an fmove out?
1245 bne.w fu_out # yes
1246
1247# Separate packed opclass two instructions.
1248 bfextu EXC_CMDREG(%a6){&0:&6},%d0
1249 cmpi.b %d0,&0x13
1250 beq.w fu_in_pack
1251
1252
1253# I'm not sure at this point what FPSR bits are valid for this instruction.
1254# so, since the emulation routines re-create them anyways, zero exception field
1255 andi.l &0x00ff00ff,USER_FPSR(%a6) # zero exception field
1256
1257 fmov.l &0x0,%fpcr # zero current control regs
1258 fmov.l &0x0,%fpsr
1259
1260# Opclass two w/ memory-to-fpn operation will have an incorrect extended
1261# precision format if the src format was single or double and the
1262# source data type was an INF, NAN, DENORM, or UNNORM
1263 lea FP_SRC(%a6),%a0 # pass ptr to input
1264 bsr.l fix_skewed_ops
1265
1266# we don't know whether the src operand or the dst operand (or both) is the
1267# UNNORM or DENORM. call the function that tags the operand type. if the
1268# input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
1269 lea FP_SRC(%a6),%a0 # pass: ptr to src op
1270 bsr.l set_tag_x # tag the operand type
1271 cmpi.b %d0,&UNNORM # is operand an UNNORM?
1272 bne.b fu_op2 # no
1273 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1274
1275fu_op2:
1276 mov.b %d0,STAG(%a6) # save src optype tag
1277
1278 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1279
1280# bit five of the fp extension word separates the monadic and dyadic operations
1281# at this point
1282 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
1283 beq.b fu_extract # monadic
1284 cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
1285 beq.b fu_extract # yes, so it's monadic, too
1286
1287 bsr.l load_fpn2 # load dst into FP_DST
1288
1289 lea FP_DST(%a6),%a0 # pass: ptr to dst op
1290 bsr.l set_tag_x # tag the operand type
1291 cmpi.b %d0,&UNNORM # is operand an UNNORM?
1292 bne.b fu_op2_done # no
1293 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1294fu_op2_done:
1295 mov.b %d0,DTAG(%a6) # save dst optype tag
1296
1297fu_extract:
1298 clr.l %d0
1299 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1300
1301 bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1302
1303 lea FP_SRC(%a6),%a0
1304 lea FP_DST(%a6),%a1
1305
1306 mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1307 jsr (tbl_unsupp.l,%pc,%d1.l*1)
1308
1309#
1310# Exceptions in order of precedence:
1311# BSUN : none
1312# SNAN : all dyadic ops
1313# OPERR : fsqrt(-NORM)
1314# OVFL : all except ftst,fcmp
1315# UNFL : all except ftst,fcmp
1316# DZ : fdiv
1317# INEX2 : all except ftst,fcmp
1318# INEX1 : none (packed doesn't go through here)
1319#
1320
1321# we determine the highest priority exception(if any) set by the
1322# emulation routine that has also been enabled by the user.
1323 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions set
1324 bne.b fu_in_ena # some are enabled
1325
1326fu_in_cont:
1327# fcmp and ftst do not store any result.
1328 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
1329 andi.b &0x38,%d0 # extract bits 3-5
1330 cmpi.b %d0,&0x38 # is instr fcmp or ftst?
1331 beq.b fu_in_exit # yes
1332
1333 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1334 bsr.l store_fpreg # store the result
1335
1336fu_in_exit:
1337
1338 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1339 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1340 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1341
1342 unlk %a6
1343
1344 bra.l _fpsp_done
1345
1346fu_in_ena:
1347 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
1348 bfffo %d0{&24:&8},%d0 # find highest priority exception
1349 bne.b fu_in_exc # there is at least one set
1350
1351#
1352# No exceptions occurred that were also enabled. Now:
1353#
1354# if (OVFL && ovfl_disabled && inexact_enabled) {
1355# branch to _real_inex() (even if the result was exact!);
1356# } else {
1357# save the result in the proper fp reg (unless the op is fcmp or ftst);
1358# return;
1359# }
1360#
1361 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1362 beq.b fu_in_cont # no
1363
1364fu_in_ovflchk:
1365 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1366 beq.b fu_in_cont # no
1367 bra.w fu_in_exc_ovfl # go insert overflow frame
1368
1369#
1370# An exception occurred and that exception was enabled:
1371#
1372# shift enabled exception field into lo byte of d0;
1373# if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1374# ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1375# /*
1376# * this is the case where we must call _real_inex() now or else
1377# * there will be no other way to pass it the exceptional operand
1378# */
1379# call _real_inex();
1380# } else {
1381# restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1382# }
1383#
1384fu_in_exc:
1385 subi.l &24,%d0 # fix offset to be 0-8
1386 cmpi.b %d0,&0x6 # is exception INEX? (6)
1387 bne.b fu_in_exc_exit # no
1388
1389# the enabled exception was inexact
1390 btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1391 bne.w fu_in_exc_unfl # yes
1392 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1393 bne.w fu_in_exc_ovfl # yes
1394
1395# here, we insert the correct fsave status value into the fsave frame for the
1396# corresponding exception. the operand in the fsave frame should be the original
1397# src operand.
1398fu_in_exc_exit:
1399 mov.l %d0,-(%sp) # save d0
1400 bsr.l funimp_skew # skew sgl or dbl inputs
1401 mov.l (%sp)+,%d0 # restore d0
1402
1403 mov.w (tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
1404
1405 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1406 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1407 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1408
1409 frestore FP_SRC(%a6) # restore src op
1410
1411 unlk %a6
1412
1413 bra.l _fpsp_done
1414
1415tbl_except:
1416 short 0xe000,0xe006,0xe004,0xe005
1417 short 0xe003,0xe002,0xe001,0xe001
1418
1419fu_in_exc_unfl:
1420 mov.w &0x4,%d0
1421 bra.b fu_in_exc_exit
1422fu_in_exc_ovfl:
1423 mov.w &0x03,%d0
1424 bra.b fu_in_exc_exit
1425
1426# If the input operand to this operation was opclass two and a single
1427# or double precision denorm, inf, or nan, the operand needs to be
1428# "corrected" in order to have the proper equivalent extended precision
1429# number.
1430 global fix_skewed_ops
1431fix_skewed_ops:
1432 bfextu EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
1433 cmpi.b %d0,&0x11 # is class = 2 & fmt = sgl?
1434 beq.b fso_sgl # yes
1435 cmpi.b %d0,&0x15 # is class = 2 & fmt = dbl?
1436 beq.b fso_dbl # yes
1437 rts # no
1438
1439fso_sgl:
1440 mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
1441 andi.w &0x7fff,%d0 # strip sign
1442 cmpi.w %d0,&0x3f80 # is |exp| == $3f80?
1443 beq.b fso_sgl_dnrm_zero # yes
1444 cmpi.w %d0,&0x407f # no; is |exp| == $407f?
1445 beq.b fso_infnan # yes
1446 rts # no
1447
1448fso_sgl_dnrm_zero:
1449 andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1450 beq.b fso_zero # it's a skewed zero
1451fso_sgl_dnrm:
1452# here, we count on norm not to alter a0...
1453 bsr.l norm # normalize mantissa
1454 neg.w %d0 # -shft amt
1455 addi.w &0x3f81,%d0 # adjust new exponent
1456 andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
1457 or.w %d0,LOCAL_EX(%a0) # insert new exponent
1458 rts
1459
1460fso_zero:
1461 andi.w &0x8000,LOCAL_EX(%a0) # clear bogus exponent
1462 rts
1463
1464fso_infnan:
1465 andi.b &0x7f,LOCAL_HI(%a0) # clear j-bit
1466 ori.w &0x7fff,LOCAL_EX(%a0) # make exponent = $7fff
1467 rts
1468
1469fso_dbl:
1470 mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
1471 andi.w &0x7fff,%d0 # strip sign
1472 cmpi.w %d0,&0x3c00 # is |exp| == $3c00?
1473 beq.b fso_dbl_dnrm_zero # yes
1474 cmpi.w %d0,&0x43ff # no; is |exp| == $43ff?
1475 beq.b fso_infnan # yes
1476 rts # no
1477
1478fso_dbl_dnrm_zero:
1479 andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1480 bne.b fso_dbl_dnrm # it's a skewed denorm
1481 tst.l LOCAL_LO(%a0) # is it a zero?
1482 beq.b fso_zero # yes
1483fso_dbl_dnrm:
1484# here, we count on norm not to alter a0...
1485 bsr.l norm # normalize mantissa
1486 neg.w %d0 # -shft amt
1487 addi.w &0x3c01,%d0 # adjust new exponent
1488 andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
1489 or.w %d0,LOCAL_EX(%a0) # insert new exponent
1490 rts
1491
1492#################################################################
1493
1494# fmove out took an unimplemented data type exception.
1495# the src operand is in FP_SRC. Call _fout() to write out the result and
1496# to determine which exceptions, if any, to take.
1497fu_out:
1498
1499# Separate packed move outs from the UNNORM and DENORM move outs.
1500 bfextu EXC_CMDREG(%a6){&3:&3},%d0
1501 cmpi.b %d0,&0x3
1502 beq.w fu_out_pack
1503 cmpi.b %d0,&0x7
1504 beq.w fu_out_pack
1505
1506
1507# I'm not sure at this point what FPSR bits are valid for this instruction.
1508# so, since the emulation routines re-create them anyways, zero exception field.
1509# fmove out doesn't affect ccodes.
1510 and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
1511
1512 fmov.l &0x0,%fpcr # zero current control regs
1513 fmov.l &0x0,%fpsr
1514
1515# the src can ONLY be a DENORM or an UNNORM! so, don't make any big subroutine
1516# call here. just figure out what it is...
1517 mov.w FP_SRC_EX(%a6),%d0 # get exponent
1518 andi.w &0x7fff,%d0 # strip sign
1519 beq.b fu_out_denorm # it's a DENORM
1520
1521 lea FP_SRC(%a6),%a0
1522 bsr.l unnorm_fix # yes; fix it
1523
1524 mov.b %d0,STAG(%a6)
1525
1526 bra.b fu_out_cont
1527fu_out_denorm:
1528 mov.b &DENORM,STAG(%a6)
1529fu_out_cont:
1530
1531 clr.l %d0
1532 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1533
1534 lea FP_SRC(%a6),%a0 # pass ptr to src operand
1535
1536 mov.l (%a6),EXC_A6(%a6) # in case a6 changes
1537 bsr.l fout # call fmove out routine
1538
1539# Exceptions in order of precedence:
1540# BSUN : none
1541# SNAN : none
1542# OPERR : fmove.{b,w,l} out of large UNNORM
1543# OVFL : fmove.{s,d}
1544# UNFL : fmove.{s,d,x}
1545# DZ : none
1546# INEX2 : all
1547# INEX1 : none (packed doesn't travel through here)
1548
1549# determine the highest priority exception(if any) set by the
1550# emulation routine that has also been enabled by the user.
1551 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
1552 bne.w fu_out_ena # some are enabled
1553
1554fu_out_done:
1555
1556 mov.l EXC_A6(%a6),(%a6) # in case a6 changed
1557
1558# on extended precision opclass three instructions using pre-decrement or
1559# post-increment addressing mode, the address register is not updated. is the
1560# address register was the stack pointer used from user mode, then let's update
1561# it here. if it was used from supervisor mode, then we have to handle this
1562# as a special case.
1563 btst &0x5,EXC_SR(%a6)
1564 bne.b fu_out_done_s
1565
1566 mov.l EXC_A7(%a6),%a0 # restore a7
1567 mov.l %a0,%usp
1568
1569fu_out_done_cont:
1570 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1571 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1572 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1573
1574 unlk %a6
1575
1576 btst &0x7,(%sp) # is trace on?
1577 bne.b fu_out_trace # yes
1578
1579 bra.l _fpsp_done
1580
1581# is the ea mode pre-decrement of the stack pointer from supervisor mode?
1582# ("fmov.x fpm,-(a7)") if so,
1583fu_out_done_s:
1584 cmpi.b SPCOND_FLG(%a6),&mda7_flg
1585 bne.b fu_out_done_cont
1586
1587# the extended precision result is still in fp0. but, we need to save it
1588# somewhere on the stack until we can copy it to its final resting place.
1589# here, we're counting on the top of the stack to be the old place-holders
1590# for fp0/fp1 which have already been restored. that way, we can write
1591# over those destinations with the shifted stack frame.
1592 fmovm.x &0x80,FP_SRC(%a6) # put answer on stack
1593
1594 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1595 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1596 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1597
1598 mov.l (%a6),%a6 # restore frame pointer
1599
1600 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
1601 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
1602
1603# now, copy the result to the proper place on the stack
1604 mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
1605 mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
1606 mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
1607
1608 add.l &LOCAL_SIZE-0x8,%sp
1609
1610 btst &0x7,(%sp)
1611 bne.b fu_out_trace
1612
1613 bra.l _fpsp_done
1614
1615fu_out_ena:
1616 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
1617 bfffo %d0{&24:&8},%d0 # find highest priority exception
1618 bne.b fu_out_exc # there is at least one set
1619
1620# no exceptions were set.
1621# if a disabled overflow occurred and inexact was enabled but the result
1622# was exact, then a branch to _real_inex() is made.
1623 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1624 beq.w fu_out_done # no
1625
1626fu_out_ovflchk:
1627 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1628 beq.w fu_out_done # no
1629 bra.w fu_inex # yes
1630
1631#
1632# The fp move out that took the "Unimplemented Data Type" exception was
1633# being traced. Since the stack frames are similar, get the "current" PC
1634# from FPIAR and put it in the trace stack frame then jump to _real_trace().
1635#
1636# UNSUPP FRAME TRACE FRAME
1637# ***************** *****************
1638# * EA * * Current *
1639# * * * PC *
1640# ***************** *****************
1641# * 0x3 * 0x0dc * * 0x2 * 0x024 *
1642# ***************** *****************
1643# * Next * * Next *
1644# * PC * * PC *
1645# ***************** *****************
1646# * SR * * SR *
1647# ***************** *****************
1648#
1649fu_out_trace:
1650 mov.w &0x2024,0x6(%sp)
1651 fmov.l %fpiar,0x8(%sp)
1652 bra.l _real_trace
1653
1654# an exception occurred and that exception was enabled.
1655fu_out_exc:
1656 subi.l &24,%d0 # fix offset to be 0-8
1657
1658# we don't mess with the existing fsave frame. just re-insert it and
1659# jump to the "_real_{}()" handler...
1660 mov.w (tbl_fu_out.b,%pc,%d0.w*2),%d0
1661 jmp (tbl_fu_out.b,%pc,%d0.w*1)
1662
1663 swbeg &0x8
1664tbl_fu_out:
1665 short tbl_fu_out - tbl_fu_out # BSUN can't happen
1666 short tbl_fu_out - tbl_fu_out # SNAN can't happen
1667 short fu_operr - tbl_fu_out # OPERR
1668 short fu_ovfl - tbl_fu_out # OVFL
1669 short fu_unfl - tbl_fu_out # UNFL
1670 short tbl_fu_out - tbl_fu_out # DZ can't happen
1671 short fu_inex - tbl_fu_out # INEX2
1672 short tbl_fu_out - tbl_fu_out # INEX1 won't make it here
1673
1674# for snan,operr,ovfl,unfl, src op is still in FP_SRC so just
1675# frestore it.
1676fu_snan:
1677 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1678 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1679 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1680
1681 mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd8
1682 mov.w &0xe006,2+FP_SRC(%a6)
1683
1684 frestore FP_SRC(%a6)
1685
1686 unlk %a6
1687
1688
1689 bra.l _real_snan
1690
1691fu_operr:
1692 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1693 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1694 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1695
1696 mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0
1697 mov.w &0xe004,2+FP_SRC(%a6)
1698
1699 frestore FP_SRC(%a6)
1700
1701 unlk %a6
1702
1703
1704 bra.l _real_operr
1705
1706fu_ovfl:
1707 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1708
1709 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1710 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1711 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1712
1713 mov.w &0x30d4,EXC_VOFF(%a6) # vector offset = 0xd4
1714 mov.w &0xe005,2+FP_SRC(%a6)
1715
1716 frestore FP_SRC(%a6) # restore EXOP
1717
1718 unlk %a6
1719
1720 bra.l _real_ovfl
1721
1722# underflow can happen for extended precision. extended precision opclass
1723# three instruction exceptions don't update the stack pointer. so, if the
1724# exception occurred from user mode, then simply update a7 and exit normally.
1725# if the exception occurred from supervisor mode, check if
1726fu_unfl:
1727 mov.l EXC_A6(%a6),(%a6) # restore a6
1728
1729 btst &0x5,EXC_SR(%a6)
1730 bne.w fu_unfl_s
1731
1732 mov.l EXC_A7(%a6),%a0 # restore a7 whether we need
1733 mov.l %a0,%usp # to or not...
1734
1735fu_unfl_cont:
1736 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1737
1738 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1739 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1740 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1741
1742 mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc
1743 mov.w &0xe003,2+FP_SRC(%a6)
1744
1745 frestore FP_SRC(%a6) # restore EXOP
1746
1747 unlk %a6
1748
1749 bra.l _real_unfl
1750
1751fu_unfl_s:
1752 cmpi.b SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)?
1753 bne.b fu_unfl_cont
1754
1755# the extended precision result is still in fp0. but, we need to save it
1756# somewhere on the stack until we can copy it to its final resting place
1757# (where the exc frame is currently). make sure it's not at the top of the
1758# frame or it will get overwritten when the exc stack frame is shifted "down".
1759 fmovm.x &0x80,FP_SRC(%a6) # put answer on stack
1760 fmovm.x &0x40,FP_DST(%a6) # put EXOP on stack
1761
1762 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1763 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1764 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1765
1766 mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc
1767 mov.w &0xe003,2+FP_DST(%a6)
1768
1769 frestore FP_DST(%a6) # restore EXOP
1770
1771 mov.l (%a6),%a6 # restore frame pointer
1772
1773 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
1774 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
1775 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
1776
1777# now, copy the result to the proper place on the stack
1778 mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
1779 mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
1780 mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
1781
1782 add.l &LOCAL_SIZE-0x8,%sp
1783
1784 bra.l _real_unfl
1785
1786# fmove in and out enter here.
1787fu_inex:
1788 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1789
1790 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1791 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1792 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1793
1794 mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4
1795 mov.w &0xe001,2+FP_SRC(%a6)
1796
1797 frestore FP_SRC(%a6) # restore EXOP
1798
1799 unlk %a6
1800
1801
1802 bra.l _real_inex
1803
1804#########################################################################
1805#########################################################################
1806fu_in_pack:
1807
1808
1809# I'm not sure at this point what FPSR bits are valid for this instruction.
1810# so, since the emulation routines re-create them anyways, zero exception field
1811 andi.l &0x0ff00ff,USER_FPSR(%a6) # zero exception field
1812
1813 fmov.l &0x0,%fpcr # zero current control regs
1814 fmov.l &0x0,%fpsr
1815
1816 bsr.l get_packed # fetch packed src operand
1817
1818 lea FP_SRC(%a6),%a0 # pass ptr to src
1819 bsr.l set_tag_x # set src optype tag
1820
1821 mov.b %d0,STAG(%a6) # save src optype tag
1822
1823 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1824
1825# bit five of the fp extension word separates the monadic and dyadic operations
1826# at this point
1827 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
1828 beq.b fu_extract_p # monadic
1829 cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
1830 beq.b fu_extract_p # yes, so it's monadic, too
1831
1832 bsr.l load_fpn2 # load dst into FP_DST
1833
1834 lea FP_DST(%a6),%a0 # pass: ptr to dst op
1835 bsr.l set_tag_x # tag the operand type
1836 cmpi.b %d0,&UNNORM # is operand an UNNORM?
1837 bne.b fu_op2_done_p # no
1838 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1839fu_op2_done_p:
1840 mov.b %d0,DTAG(%a6) # save dst optype tag
1841
1842fu_extract_p:
1843 clr.l %d0
1844 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1845
1846 bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1847
1848 lea FP_SRC(%a6),%a0
1849 lea FP_DST(%a6),%a1
1850
1851 mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1852 jsr (tbl_unsupp.l,%pc,%d1.l*1)
1853
1854#
1855# Exceptions in order of precedence:
1856# BSUN : none
1857# SNAN : all dyadic ops
1858# OPERR : fsqrt(-NORM)
1859# OVFL : all except ftst,fcmp
1860# UNFL : all except ftst,fcmp
1861# DZ : fdiv
1862# INEX2 : all except ftst,fcmp
1863# INEX1 : all
1864#
1865
1866# we determine the highest priority exception(if any) set by the
1867# emulation routine that has also been enabled by the user.
1868 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
1869 bne.w fu_in_ena_p # some are enabled
1870
1871fu_in_cont_p:
1872# fcmp and ftst do not store any result.
1873 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
1874 andi.b &0x38,%d0 # extract bits 3-5
1875 cmpi.b %d0,&0x38 # is instr fcmp or ftst?
1876 beq.b fu_in_exit_p # yes
1877
1878 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1879 bsr.l store_fpreg # store the result
1880
1881fu_in_exit_p:
1882
1883 btst &0x5,EXC_SR(%a6) # user or supervisor?
1884 bne.w fu_in_exit_s_p # supervisor
1885
1886 mov.l EXC_A7(%a6),%a0 # update user a7
1887 mov.l %a0,%usp
1888
1889fu_in_exit_cont_p:
1890 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1891 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1892 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1893
1894 unlk %a6 # unravel stack frame
1895
1896 btst &0x7,(%sp) # is trace on?
1897 bne.w fu_trace_p # yes
1898
1899 bra.l _fpsp_done # exit to os
1900
1901# the exception occurred in supervisor mode. check to see if the
1902# addressing mode was (a7)+. if so, we'll need to shift the
1903# stack frame "up".
1904fu_in_exit_s_p:
1905 btst &mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+
1906 beq.b fu_in_exit_cont_p # no
1907
1908 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1909 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1910 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1911
1912 unlk %a6 # unravel stack frame
1913
1914# shift the stack frame "up". we don't really care about the <ea> field.
1915 mov.l 0x4(%sp),0x10(%sp)
1916 mov.l 0x0(%sp),0xc(%sp)
1917 add.l &0xc,%sp
1918
1919 btst &0x7,(%sp) # is trace on?
1920 bne.w fu_trace_p # yes
1921
1922 bra.l _fpsp_done # exit to os
1923
1924fu_in_ena_p:
1925 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled & set
1926 bfffo %d0{&24:&8},%d0 # find highest priority exception
1927 bne.b fu_in_exc_p # at least one was set
1928
1929#
1930# No exceptions occurred that were also enabled. Now:
1931#
1932# if (OVFL && ovfl_disabled && inexact_enabled) {
1933# branch to _real_inex() (even if the result was exact!);
1934# } else {
1935# save the result in the proper fp reg (unless the op is fcmp or ftst);
1936# return;
1937# }
1938#
1939 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1940 beq.w fu_in_cont_p # no
1941
1942fu_in_ovflchk_p:
1943 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1944 beq.w fu_in_cont_p # no
1945 bra.w fu_in_exc_ovfl_p # do _real_inex() now
1946
1947#
1948# An exception occurred and that exception was enabled:
1949#
1950# shift enabled exception field into lo byte of d0;
1951# if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1952# ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1953# /*
1954# * this is the case where we must call _real_inex() now or else
1955# * there will be no other way to pass it the exceptional operand
1956# */
1957# call _real_inex();
1958# } else {
1959# restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1960# }
1961#
1962fu_in_exc_p:
1963 subi.l &24,%d0 # fix offset to be 0-8
1964 cmpi.b %d0,&0x6 # is exception INEX? (6 or 7)
1965 blt.b fu_in_exc_exit_p # no
1966
1967# the enabled exception was inexact
1968 btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1969 bne.w fu_in_exc_unfl_p # yes
1970 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1971 bne.w fu_in_exc_ovfl_p # yes
1972
1973# here, we insert the correct fsave status value into the fsave frame for the
1974# corresponding exception. the operand in the fsave frame should be the original
1975# src operand.
1976# as a reminder for future predicted pain and agony, we are passing in fsave the
1977# "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs.
1978# this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!!
1979fu_in_exc_exit_p:
1980 btst &0x5,EXC_SR(%a6) # user or supervisor?
1981 bne.w fu_in_exc_exit_s_p # supervisor
1982
1983 mov.l EXC_A7(%a6),%a0 # update user a7
1984 mov.l %a0,%usp
1985
1986fu_in_exc_exit_cont_p:
1987 mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
1988
1989 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1990 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1991 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1992
1993 frestore FP_SRC(%a6) # restore src op
1994
1995 unlk %a6
1996
1997 btst &0x7,(%sp) # is trace enabled?
1998 bne.w fu_trace_p # yes
1999
2000 bra.l _fpsp_done
2001
2002tbl_except_p:
2003 short 0xe000,0xe006,0xe004,0xe005
2004 short 0xe003,0xe002,0xe001,0xe001
2005
2006fu_in_exc_ovfl_p:
2007 mov.w &0x3,%d0
2008 bra.w fu_in_exc_exit_p
2009
2010fu_in_exc_unfl_p:
2011 mov.w &0x4,%d0
2012 bra.w fu_in_exc_exit_p
2013
2014fu_in_exc_exit_s_p:
2015 btst &mia7_bit,SPCOND_FLG(%a6)
2016 beq.b fu_in_exc_exit_cont_p
2017
2018 mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
2019
2020 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2021 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2022 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2023
2024 frestore FP_SRC(%a6) # restore src op
2025
2026 unlk %a6 # unravel stack frame
2027
2028# shift stack frame "up". who cares about <ea> field.
2029 mov.l 0x4(%sp),0x10(%sp)
2030 mov.l 0x0(%sp),0xc(%sp)
2031 add.l &0xc,%sp
2032
2033 btst &0x7,(%sp) # is trace on?
2034 bne.b fu_trace_p # yes
2035
2036 bra.l _fpsp_done # exit to os
2037
2038#
2039# The opclass two PACKED instruction that took an "Unimplemented Data Type"
2040# exception was being traced. Make the "current" PC the FPIAR and put it in the
2041# trace stack frame then jump to _real_trace().
2042#
2043# UNSUPP FRAME TRACE FRAME
2044# ***************** *****************
2045# * EA * * Current *
2046# * * * PC *
2047# ***************** *****************
2048# * 0x2 * 0x0dc * * 0x2 * 0x024 *
2049# ***************** *****************
2050# * Next * * Next *
2051# * PC * * PC *
2052# ***************** *****************
2053# * SR * * SR *
2054# ***************** *****************
2055fu_trace_p:
2056 mov.w &0x2024,0x6(%sp)
2057 fmov.l %fpiar,0x8(%sp)
2058
2059 bra.l _real_trace
2060
2061#########################################################
2062#########################################################
2063fu_out_pack:
2064
2065
2066# I'm not sure at this point what FPSR bits are valid for this instruction.
2067# so, since the emulation routines re-create them anyways, zero exception field.
2068# fmove out doesn't affect ccodes.
2069 and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
2070
2071 fmov.l &0x0,%fpcr # zero current control regs
2072 fmov.l &0x0,%fpsr
2073
2074 bfextu EXC_CMDREG(%a6){&6:&3},%d0
2075 bsr.l load_fpn1
2076
2077# unlike other opclass 3, unimplemented data type exceptions, packed must be
2078# able to detect all operand types.
2079 lea FP_SRC(%a6),%a0
2080 bsr.l set_tag_x # tag the operand type
2081 cmpi.b %d0,&UNNORM # is operand an UNNORM?
2082 bne.b fu_op2_p # no
2083 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
2084
2085fu_op2_p:
2086 mov.b %d0,STAG(%a6) # save src optype tag
2087
2088 clr.l %d0
2089 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
2090
2091 lea FP_SRC(%a6),%a0 # pass ptr to src operand
2092
2093 mov.l (%a6),EXC_A6(%a6) # in case a6 changes
2094 bsr.l fout # call fmove out routine
2095
2096# Exceptions in order of precedence:
2097# BSUN : no
2098# SNAN : yes
2099# OPERR : if ((k_factor > +17) || (dec. exp exceeds 3 digits))
2100# OVFL : no
2101# UNFL : no
2102# DZ : no
2103# INEX2 : yes
2104# INEX1 : no
2105
2106# determine the highest priority exception(if any) set by the
2107# emulation routine that has also been enabled by the user.
2108 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
2109 bne.w fu_out_ena_p # some are enabled
2110
2111fu_out_exit_p:
2112 mov.l EXC_A6(%a6),(%a6) # restore a6
2113
2114 btst &0x5,EXC_SR(%a6) # user or supervisor?
2115 bne.b fu_out_exit_s_p # supervisor
2116
2117 mov.l EXC_A7(%a6),%a0 # update user a7
2118 mov.l %a0,%usp
2119
2120fu_out_exit_cont_p:
2121 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2122 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2123 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2124
2125 unlk %a6 # unravel stack frame
2126
2127 btst &0x7,(%sp) # is trace on?
2128 bne.w fu_trace_p # yes
2129
2130 bra.l _fpsp_done # exit to os
2131
2132# the exception occurred in supervisor mode. check to see if the
2133# addressing mode was -(a7). if so, we'll need to shift the
2134# stack frame "down".
2135fu_out_exit_s_p:
2136 btst &mda7_bit,SPCOND_FLG(%a6) # was ea mode -(a7)
2137 beq.b fu_out_exit_cont_p # no
2138
2139 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2140 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2141 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2142
2143 mov.l (%a6),%a6 # restore frame pointer
2144
2145 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2146 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2147
2148# now, copy the result to the proper place on the stack
2149 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
2150 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
2151 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
2152
2153 add.l &LOCAL_SIZE-0x8,%sp
2154
2155 btst &0x7,(%sp)
2156 bne.w fu_trace_p
2157
2158 bra.l _fpsp_done
2159
2160fu_out_ena_p:
2161 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
2162 bfffo %d0{&24:&8},%d0 # find highest priority exception
2163 beq.w fu_out_exit_p
2164
2165 mov.l EXC_A6(%a6),(%a6) # restore a6
2166
2167# an exception occurred and that exception was enabled.
2168# the only exception possible on packed move out are INEX, OPERR, and SNAN.
2169fu_out_exc_p:
2170 cmpi.b %d0,&0x1a
2171 bgt.w fu_inex_p2
2172 beq.w fu_operr_p
2173
2174fu_snan_p:
2175 btst &0x5,EXC_SR(%a6)
2176 bne.b fu_snan_s_p
2177
2178 mov.l EXC_A7(%a6),%a0
2179 mov.l %a0,%usp
2180 bra.w fu_snan
2181
2182fu_snan_s_p:
2183 cmpi.b SPCOND_FLG(%a6),&mda7_flg
2184 bne.w fu_snan
2185
2186# the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2187# the strategy is to move the exception frame "down" 12 bytes. then, we
2188# can store the default result where the exception frame was.
2189 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2190 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2191 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2192
2193 mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd0
2194 mov.w &0xe006,2+FP_SRC(%a6) # set fsave status
2195
2196 frestore FP_SRC(%a6) # restore src operand
2197
2198 mov.l (%a6),%a6 # restore frame pointer
2199
2200 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2201 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2202 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2203
2204# now, we copy the default result to its proper location
2205 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2206 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2207 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2208
2209 add.l &LOCAL_SIZE-0x8,%sp
2210
2211
2212 bra.l _real_snan
2213
2214fu_operr_p:
2215 btst &0x5,EXC_SR(%a6)
2216 bne.w fu_operr_p_s
2217
2218 mov.l EXC_A7(%a6),%a0
2219 mov.l %a0,%usp
2220 bra.w fu_operr
2221
2222fu_operr_p_s:
2223 cmpi.b SPCOND_FLG(%a6),&mda7_flg
2224 bne.w fu_operr
2225
2226# the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2227# the strategy is to move the exception frame "down" 12 bytes. then, we
2228# can store the default result where the exception frame was.
2229 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2230 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2231 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2232
2233 mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0
2234 mov.w &0xe004,2+FP_SRC(%a6) # set fsave status
2235
2236 frestore FP_SRC(%a6) # restore src operand
2237
2238 mov.l (%a6),%a6 # restore frame pointer
2239
2240 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2241 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2242 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2243
2244# now, we copy the default result to its proper location
2245 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2246 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2247 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2248
2249 add.l &LOCAL_SIZE-0x8,%sp
2250
2251
2252 bra.l _real_operr
2253
2254fu_inex_p2:
2255 btst &0x5,EXC_SR(%a6)
2256 bne.w fu_inex_s_p2
2257
2258 mov.l EXC_A7(%a6),%a0
2259 mov.l %a0,%usp
2260 bra.w fu_inex
2261
2262fu_inex_s_p2:
2263 cmpi.b SPCOND_FLG(%a6),&mda7_flg
2264 bne.w fu_inex
2265
2266# the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2267# the strategy is to move the exception frame "down" 12 bytes. then, we
2268# can store the default result where the exception frame was.
2269 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2270 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2271 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2272
2273 mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4
2274 mov.w &0xe001,2+FP_SRC(%a6) # set fsave status
2275
2276 frestore FP_SRC(%a6) # restore src operand
2277
2278 mov.l (%a6),%a6 # restore frame pointer
2279
2280 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2281 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2282 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2283
2284# now, we copy the default result to its proper location
2285 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2286 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2287 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2288
2289 add.l &LOCAL_SIZE-0x8,%sp
2290
2291
2292 bra.l _real_inex
2293
2294#########################################################################
2295
2296#
2297# if we're stuffing a source operand back into an fsave frame then we
2298# have to make sure that for single or double source operands that the
2299# format stuffed is as weird as the hardware usually makes it.
2300#
2301 global funimp_skew
2302funimp_skew:
2303 bfextu EXC_EXTWORD(%a6){&3:&3},%d0 # extract src specifier
2304 cmpi.b %d0,&0x1 # was src sgl?
2305 beq.b funimp_skew_sgl # yes
2306 cmpi.b %d0,&0x5 # was src dbl?
2307 beq.b funimp_skew_dbl # yes
2308 rts
2309
2310funimp_skew_sgl:
2311 mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent
2312 andi.w &0x7fff,%d0 # strip sign
2313 beq.b funimp_skew_sgl_not
2314 cmpi.w %d0,&0x3f80
2315 bgt.b funimp_skew_sgl_not
2316 neg.w %d0 # make exponent negative
2317 addi.w &0x3f81,%d0 # find amt to shift
2318 mov.l FP_SRC_HI(%a6),%d1 # fetch DENORM hi(man)
2319 lsr.l %d0,%d1 # shift it
2320 bset &31,%d1 # set j-bit
2321 mov.l %d1,FP_SRC_HI(%a6) # insert new hi(man)
2322 andi.w &0x8000,FP_SRC_EX(%a6) # clear old exponent
2323 ori.w &0x3f80,FP_SRC_EX(%a6) # insert new "skewed" exponent
2324funimp_skew_sgl_not:
2325 rts
2326
2327funimp_skew_dbl:
2328 mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent
2329 andi.w &0x7fff,%d0 # strip sign
2330 beq.b funimp_skew_dbl_not
2331 cmpi.w %d0,&0x3c00
2332 bgt.b funimp_skew_dbl_not
2333
2334 tst.b FP_SRC_EX(%a6) # make "internal format"
2335 smi.b 0x2+FP_SRC(%a6)
2336 mov.w %d0,FP_SRC_EX(%a6) # insert exponent with cleared sign
2337 clr.l %d0 # clear g,r,s
2338 lea FP_SRC(%a6),%a0 # pass ptr to src op
2339 mov.w &0x3c01,%d1 # pass denorm threshold
2340 bsr.l dnrm_lp # denorm it
2341 mov.w &0x3c00,%d0 # new exponent
2342 tst.b 0x2+FP_SRC(%a6) # is sign set?
2343 beq.b fss_dbl_denorm_done # no
2344 bset &15,%d0 # set sign
2345fss_dbl_denorm_done:
2346 bset &0x7,FP_SRC_HI(%a6) # set j-bit
2347 mov.w %d0,FP_SRC_EX(%a6) # insert new exponent
2348funimp_skew_dbl_not:
2349 rts
2350
2351#########################################################################
2352 global _mem_write2
2353_mem_write2:
2354 btst &0x5,EXC_SR(%a6)
2355 beq.l _dmem_write
2356 mov.l 0x0(%a0),FP_DST_EX(%a6)
2357 mov.l 0x4(%a0),FP_DST_HI(%a6)
2358 mov.l 0x8(%a0),FP_DST_LO(%a6)
2359 clr.l %d1
2360 rts
2361
2362#########################################################################
2363# XDEF **************************************************************** #
2364# _fpsp_effadd(): 060FPSP entry point for FP "Unimplemented #
2365# effective address" exception. #
2366# #
2367# This handler should be the first code executed upon taking the #
2368# FP Unimplemented Effective Address exception in an operating #
2369# system. #
2370# #
2371# XREF **************************************************************** #
2372# _imem_read_long() - read instruction longword #
2373# fix_skewed_ops() - adjust src operand in fsave frame #
2374# set_tag_x() - determine optype of src/dst operands #
2375# store_fpreg() - store opclass 0 or 2 result to FP regfile #
2376# unnorm_fix() - change UNNORM operands to NORM or ZERO #
2377# load_fpn2() - load dst operand from FP regfile #
2378# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
2379# decbin() - convert packed data to FP binary data #
2380# _real_fpu_disabled() - "callout" for "FPU disabled" exception #
2381# _real_access() - "callout" for access error exception #
2382# _mem_read() - read extended immediate operand from memory #
2383# _fpsp_done() - "callout" for exit; work all done #
2384# _real_trace() - "callout" for Trace enabled exception #
2385# fmovm_dynamic() - emulate dynamic fmovm instruction #
2386# fmovm_ctrl() - emulate fmovm control instruction #
2387# #
2388# INPUT *************************************************************** #
2389# - The system stack contains the "Unimplemented <ea>" stk frame #
2390# #
2391# OUTPUT ************************************************************** #
2392# If access error: #
2393# - The system stack is changed to an access error stack frame #
2394# If FPU disabled: #
2395# - The system stack is changed to an FPU disabled stack frame #
2396# If Trace exception enabled: #
2397# - The system stack is changed to a Trace exception stack frame #
2398# Else: (normal case) #
2399# - None (correct result has been stored as appropriate) #
2400# #
2401# ALGORITHM *********************************************************** #
2402# This exception handles 3 types of operations: #
2403# (1) FP Instructions using extended precision or packed immediate #
2404# addressing mode. #
2405# (2) The "fmovm.x" instruction w/ dynamic register specification. #
2406# (3) The "fmovm.l" instruction w/ 2 or 3 control registers. #
2407# #
2408# For immediate data operations, the data is read in w/ a #
2409# _mem_read() "callout", converted to FP binary (if packed), and used #
2410# as the source operand to the instruction specified by the instruction #
2411# word. If no FP exception should be reported ads a result of the #
2412# emulation, then the result is stored to the destination register and #
2413# the handler exits through _fpsp_done(). If an enabled exc has been #
2414# signalled as a result of emulation, then an fsave state frame #
2415# corresponding to the FP exception type must be entered into the 060 #
2416# FPU before exiting. In either the enabled or disabled cases, we #
2417# must also check if a Trace exception is pending, in which case, we #
2418# must create a Trace exception stack frame from the current exception #
2419# stack frame. If no Trace is pending, we simply exit through #
2420# _fpsp_done(). #
2421# For "fmovm.x", call the routine fmovm_dynamic() which will #
2422# decode and emulate the instruction. No FP exceptions can be pending #
2423# as a result of this operation emulation. A Trace exception can be #
2424# pending, though, which means the current stack frame must be changed #
2425# to a Trace stack frame and an exit made through _real_trace(). #
2426# For the case of "fmovm.x Dn,-(a7)", where the offending instruction #
2427# was executed from supervisor mode, this handler must store the FP #
2428# register file values to the system stack by itself since #
2429# fmovm_dynamic() can't handle this. A normal exit is made through #
2430# fpsp_done(). #
2431# For "fmovm.l", fmovm_ctrl() is used to emulate the instruction. #
2432# Again, a Trace exception may be pending and an exit made through #
2433# _real_trace(). Else, a normal exit is made through _fpsp_done(). #
2434# #
2435# Before any of the above is attempted, it must be checked to #
2436# see if the FPU is disabled. Since the "Unimp <ea>" exception is taken #
2437# before the "FPU disabled" exception, but the "FPU disabled" exception #
2438# has higher priority, we check the disabled bit in the PCR. If set, #
2439# then we must create an 8 word "FPU disabled" exception stack frame #
2440# from the current 4 word exception stack frame. This includes #
2441# reproducing the effective address of the instruction to put on the #
2442# new stack frame. #
2443# #
2444# In the process of all emulation work, if a _mem_read() #
2445# "callout" returns a failing result indicating an access error, then #
2446# we must create an access error stack frame from the current stack #
2447# frame. This information includes a faulting address and a fault- #
2448# status-longword. These are created within this handler. #
2449# #
2450#########################################################################
2451
2452 global _fpsp_effadd
2453_fpsp_effadd:
2454
2455# This exception type takes priority over the "Line F Emulator"
2456# exception. Therefore, the FPU could be disabled when entering here.
2457# So, we must check to see if it's disabled and handle that case separately.
2458 mov.l %d0,-(%sp) # save d0
2459 movc %pcr,%d0 # load proc cr
2460 btst &0x1,%d0 # is FPU disabled?
2461 bne.w iea_disabled # yes
2462 mov.l (%sp)+,%d0 # restore d0
2463
2464 link %a6,&-LOCAL_SIZE # init stack frame
2465
2466 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2467 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
2468 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
2469
2470# PC of instruction that took the exception is the PC in the frame
2471 mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
2472
2473 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
2474 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
2475 bsr.l _imem_read_long # fetch the instruction words
2476 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
2477
2478#########################################################################
2479
2480 tst.w %d0 # is operation fmovem?
2481 bmi.w iea_fmovm # yes
2482
2483#
2484# here, we will have:
2485# fabs fdabs fsabs facos fmod
2486# fadd fdadd fsadd fasin frem
2487# fcmp fatan fscale
2488# fdiv fddiv fsdiv fatanh fsin
2489# fint fcos fsincos
2490# fintrz fcosh fsinh
2491# fmove fdmove fsmove fetox ftan
2492# fmul fdmul fsmul fetoxm1 ftanh
2493# fneg fdneg fsneg fgetexp ftentox
2494# fsgldiv fgetman ftwotox
2495# fsglmul flog10
2496# fsqrt flog2
2497# fsub fdsub fssub flogn
2498# ftst flognp1
2499# which can all use f<op>.{x,p}
2500# so, now it's immediate data extended precision AND PACKED FORMAT!
2501#
2502iea_op:
2503 andi.l &0x00ff00ff,USER_FPSR(%a6)
2504
2505 btst &0xa,%d0 # is src fmt x or p?
2506 bne.b iea_op_pack # packed
2507
2508
2509 mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data>
2510 lea FP_SRC(%a6),%a1 # pass: ptr to super addr
2511 mov.l &0xc,%d0 # pass: 12 bytes
2512 bsr.l _imem_read # read extended immediate
2513
2514 tst.l %d1 # did ifetch fail?
2515 bne.w iea_iacc # yes
2516
2517 bra.b iea_op_setsrc
2518
2519iea_op_pack:
2520
2521 mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data>
2522 lea FP_SRC(%a6),%a1 # pass: ptr to super dst
2523 mov.l &0xc,%d0 # pass: 12 bytes
2524 bsr.l _imem_read # read packed operand
2525
2526 tst.l %d1 # did ifetch fail?
2527 bne.w iea_iacc # yes
2528
2529# The packed operand is an INF or a NAN if the exponent field is all ones.
2530 bfextu FP_SRC(%a6){&1:&15},%d0 # get exp
2531 cmpi.w %d0,&0x7fff # INF or NAN?
2532 beq.b iea_op_setsrc # operand is an INF or NAN
2533
2534# The packed operand is a zero if the mantissa is all zero, else it's
2535# a normal packed op.
2536 mov.b 3+FP_SRC(%a6),%d0 # get byte 4
2537 andi.b &0x0f,%d0 # clear all but last nybble
2538 bne.b iea_op_gp_not_spec # not a zero
2539 tst.l FP_SRC_HI(%a6) # is lw 2 zero?
2540 bne.b iea_op_gp_not_spec # not a zero
2541 tst.l FP_SRC_LO(%a6) # is lw 3 zero?
2542 beq.b iea_op_setsrc # operand is a ZERO
2543iea_op_gp_not_spec:
2544 lea FP_SRC(%a6),%a0 # pass: ptr to packed op
2545 bsr.l decbin # convert to extended
2546 fmovm.x &0x80,FP_SRC(%a6) # make this the srcop
2547
2548iea_op_setsrc:
2549 addi.l &0xc,EXC_EXTWPTR(%a6) # update extension word pointer
2550
2551# FP_SRC now holds the src operand.
2552 lea FP_SRC(%a6),%a0 # pass: ptr to src op
2553 bsr.l set_tag_x # tag the operand type
2554 mov.b %d0,STAG(%a6) # could be ANYTHING!!!
2555 cmpi.b %d0,&UNNORM # is operand an UNNORM?
2556 bne.b iea_op_getdst # no
2557 bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO
2558 mov.b %d0,STAG(%a6) # set new optype tag
2559iea_op_getdst:
2560 clr.b STORE_FLG(%a6) # clear "store result" boolean
2561
2562 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
2563 beq.b iea_op_extract # monadic
2564 btst &0x4,1+EXC_CMDREG(%a6) # is operation fsincos,ftst,fcmp?
2565 bne.b iea_op_spec # yes
2566
2567iea_op_loaddst:
2568 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
2569 bsr.l load_fpn2 # load dst operand
2570
2571 lea FP_DST(%a6),%a0 # pass: ptr to dst op
2572 bsr.l set_tag_x # tag the operand type
2573 mov.b %d0,DTAG(%a6) # could be ANYTHING!!!
2574 cmpi.b %d0,&UNNORM # is operand an UNNORM?
2575 bne.b iea_op_extract # no
2576 bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO
2577 mov.b %d0,DTAG(%a6) # set new optype tag
2578 bra.b iea_op_extract
2579
2580# the operation is fsincos, ftst, or fcmp. only fcmp is dyadic
2581iea_op_spec:
2582 btst &0x3,1+EXC_CMDREG(%a6) # is operation fsincos?
2583 beq.b iea_op_extract # yes
2584# now, we're left with ftst and fcmp. so, first let's tag them so that they don't
2585# store a result. then, only fcmp will branch back and pick up a dst operand.
2586 st STORE_FLG(%a6) # don't store a final result
2587 btst &0x1,1+EXC_CMDREG(%a6) # is operation fcmp?
2588 beq.b iea_op_loaddst # yes
2589
2590iea_op_extract:
2591 clr.l %d0
2592 mov.b FPCR_MODE(%a6),%d0 # pass: rnd mode,prec
2593
2594 mov.b 1+EXC_CMDREG(%a6),%d1
2595 andi.w &0x007f,%d1 # extract extension
2596
2597 fmov.l &0x0,%fpcr
2598 fmov.l &0x0,%fpsr
2599
2600 lea FP_SRC(%a6),%a0
2601 lea FP_DST(%a6),%a1
2602
2603 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
2604 jsr (tbl_unsupp.l,%pc,%d1.l*1)
2605
2606#
2607# Exceptions in order of precedence:
2608# BSUN : none
2609# SNAN : all operations
2610# OPERR : all reg-reg or mem-reg operations that can normally operr
2611# OVFL : same as OPERR
2612# UNFL : same as OPERR
2613# DZ : same as OPERR
2614# INEX2 : same as OPERR
2615# INEX1 : all packed immediate operations
2616#
2617
2618# we determine the highest priority exception(if any) set by the
2619# emulation routine that has also been enabled by the user.
2620 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
2621 bne.b iea_op_ena # some are enabled
2622
2623# now, we save the result, unless, of course, the operation was ftst or fcmp.
2624# these don't save results.
2625iea_op_save:
2626 tst.b STORE_FLG(%a6) # does this op store a result?
2627 bne.b iea_op_exit1 # exit with no frestore
2628
2629iea_op_store:
2630 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
2631 bsr.l store_fpreg # store the result
2632
2633iea_op_exit1:
2634 mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
2635 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
2636
2637 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2638 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2639 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2640
2641 unlk %a6 # unravel the frame
2642
2643 btst &0x7,(%sp) # is trace on?
2644 bne.w iea_op_trace # yes
2645
2646 bra.l _fpsp_done # exit to os
2647
2648iea_op_ena:
2649 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enable and set
2650 bfffo %d0{&24:&8},%d0 # find highest priority exception
2651 bne.b iea_op_exc # at least one was set
2652
2653# no exception occurred. now, did a disabled, exact overflow occur with inexact
2654# enabled? if so, then we have to stuff an overflow frame into the FPU.
2655 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
2656 beq.b iea_op_save
2657
2658iea_op_ovfl:
2659 btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
2660 beq.b iea_op_store # no
2661 bra.b iea_op_exc_ovfl # yes
2662
2663# an enabled exception occurred. we have to insert the exception type back into
2664# the machine.
2665iea_op_exc:
2666 subi.l &24,%d0 # fix offset to be 0-8
2667 cmpi.b %d0,&0x6 # is exception INEX?
2668 bne.b iea_op_exc_force # no
2669
2670# the enabled exception was inexact. so, if it occurs with an overflow
2671# or underflow that was disabled, then we have to force an overflow or
2672# underflow frame.
2673 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
2674 bne.b iea_op_exc_ovfl # yes
2675 btst &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
2676 bne.b iea_op_exc_unfl # yes
2677
2678iea_op_exc_force:
2679 mov.w (tbl_iea_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
2680 bra.b iea_op_exit2 # exit with frestore
2681
2682tbl_iea_except:
2683 short 0xe002, 0xe006, 0xe004, 0xe005
2684 short 0xe003, 0xe002, 0xe001, 0xe001
2685
2686iea_op_exc_ovfl:
2687 mov.w &0xe005,2+FP_SRC(%a6)
2688 bra.b iea_op_exit2
2689
2690iea_op_exc_unfl:
2691 mov.w &0xe003,2+FP_SRC(%a6)
2692
2693iea_op_exit2:
2694 mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
2695 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
2696
2697 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2698 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2699 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2700
2701 frestore FP_SRC(%a6) # restore exceptional state
2702
2703 unlk %a6 # unravel the frame
2704
2705 btst &0x7,(%sp) # is trace on?
2706 bne.b iea_op_trace # yes
2707
2708 bra.l _fpsp_done # exit to os
2709
2710#
2711# The opclass two instruction that took an "Unimplemented Effective Address"
2712# exception was being traced. Make the "current" PC the FPIAR and put it in
2713# the trace stack frame then jump to _real_trace().
2714#
2715# UNIMP EA FRAME TRACE FRAME
2716# ***************** *****************
2717# * 0x0 * 0x0f0 * * Current *
2718# ***************** * PC *
2719# * Current * *****************
2720# * PC * * 0x2 * 0x024 *
2721# ***************** *****************
2722# * SR * * Next *
2723# ***************** * PC *
2724# *****************
2725# * SR *
2726# *****************
2727iea_op_trace:
2728 mov.l (%sp),-(%sp) # shift stack frame "down"
2729 mov.w 0x8(%sp),0x4(%sp)
2730 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
2731 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
2732
2733 bra.l _real_trace
2734
2735#########################################################################
2736iea_fmovm:
2737 btst &14,%d0 # ctrl or data reg
2738 beq.w iea_fmovm_ctrl
2739
2740iea_fmovm_data:
2741
2742 btst &0x5,EXC_SR(%a6) # user or supervisor mode
2743 bne.b iea_fmovm_data_s
2744
2745iea_fmovm_data_u:
2746 mov.l %usp,%a0
2747 mov.l %a0,EXC_A7(%a6) # store current a7
2748 bsr.l fmovm_dynamic # do dynamic fmovm
2749 mov.l EXC_A7(%a6),%a0 # load possibly new a7
2750 mov.l %a0,%usp # update usp
2751 bra.w iea_fmovm_exit
2752
2753iea_fmovm_data_s:
2754 clr.b SPCOND_FLG(%a6)
2755 lea 0x2+EXC_VOFF(%a6),%a0
2756 mov.l %a0,EXC_A7(%a6)
2757 bsr.l fmovm_dynamic # do dynamic fmovm
2758
2759 cmpi.b SPCOND_FLG(%a6),&mda7_flg
2760 beq.w iea_fmovm_data_predec
2761 cmpi.b SPCOND_FLG(%a6),&mia7_flg
2762 bne.w iea_fmovm_exit
2763
2764# right now, d0 = the size.
2765# the data has been fetched from the supervisor stack, but we have not
2766# incremented the stack pointer by the appropriate number of bytes.
2767# do it here.
2768iea_fmovm_data_postinc:
2769 btst &0x7,EXC_SR(%a6)
2770 bne.b iea_fmovm_data_pi_trace
2771
2772 mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0)
2773 mov.l EXC_EXTWPTR(%a6),(EXC_PC,%a6,%d0)
2774 mov.w &0x00f0,(EXC_VOFF,%a6,%d0)
2775
2776 lea (EXC_SR,%a6,%d0),%a0
2777 mov.l %a0,EXC_SR(%a6)
2778
2779 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2780 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2781 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2782
2783 unlk %a6
2784 mov.l (%sp)+,%sp
2785 bra.l _fpsp_done
2786
2787iea_fmovm_data_pi_trace:
2788 mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
2789 mov.l EXC_EXTWPTR(%a6),(EXC_PC-0x4,%a6,%d0)
2790 mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0)
2791 mov.l EXC_PC(%a6),(EXC_VOFF+0x2-0x4,%a6,%d0)
2792
2793 lea (EXC_SR-0x4,%a6,%d0),%a0
2794 mov.l %a0,EXC_SR(%a6)
2795
2796 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2797 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2798 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2799
2800 unlk %a6
2801 mov.l (%sp)+,%sp
2802 bra.l _real_trace
2803
2804# right now, d1 = size and d0 = the strg.
2805iea_fmovm_data_predec:
2806 mov.b %d1,EXC_VOFF(%a6) # store strg
2807 mov.b %d0,0x1+EXC_VOFF(%a6) # store size
2808
2809 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2810 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2811 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2812
2813 mov.l (%a6),-(%sp) # make a copy of a6
2814 mov.l %d0,-(%sp) # save d0
2815 mov.l %d1,-(%sp) # save d1
2816 mov.l EXC_EXTWPTR(%a6),-(%sp) # make a copy of Next PC
2817
2818 clr.l %d0
2819 mov.b 0x1+EXC_VOFF(%a6),%d0 # fetch size
2820 neg.l %d0 # get negative of size
2821
2822 btst &0x7,EXC_SR(%a6) # is trace enabled?
2823 beq.b iea_fmovm_data_p2
2824
2825 mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
2826 mov.l EXC_PC(%a6),(EXC_VOFF-0x2,%a6,%d0)
2827 mov.l (%sp)+,(EXC_PC-0x4,%a6,%d0)
2828 mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0)
2829
2830 pea (%a6,%d0) # create final sp
2831 bra.b iea_fmovm_data_p3
2832
2833iea_fmovm_data_p2:
2834 mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0)
2835 mov.l (%sp)+,(EXC_PC,%a6,%d0)
2836 mov.w &0x00f0,(EXC_VOFF,%a6,%d0)
2837
2838 pea (0x4,%a6,%d0) # create final sp
2839
2840iea_fmovm_data_p3:
2841 clr.l %d1
2842 mov.b EXC_VOFF(%a6),%d1 # fetch strg
2843
2844 tst.b %d1
2845 bpl.b fm_1
2846 fmovm.x &0x80,(0x4+0x8,%a6,%d0)
2847 addi.l &0xc,%d0
2848fm_1:
2849 lsl.b &0x1,%d1
2850 bpl.b fm_2
2851 fmovm.x &0x40,(0x4+0x8,%a6,%d0)
2852 addi.l &0xc,%d0
2853fm_2:
2854 lsl.b &0x1,%d1
2855 bpl.b fm_3
2856 fmovm.x &0x20,(0x4+0x8,%a6,%d0)
2857 addi.l &0xc,%d0
2858fm_3:
2859 lsl.b &0x1,%d1
2860 bpl.b fm_4
2861 fmovm.x &0x10,(0x4+0x8,%a6,%d0)
2862 addi.l &0xc,%d0
2863fm_4:
2864 lsl.b &0x1,%d1
2865 bpl.b fm_5
2866 fmovm.x &0x08,(0x4+0x8,%a6,%d0)
2867 addi.l &0xc,%d0
2868fm_5:
2869 lsl.b &0x1,%d1
2870 bpl.b fm_6
2871 fmovm.x &0x04,(0x4+0x8,%a6,%d0)
2872 addi.l &0xc,%d0
2873fm_6:
2874 lsl.b &0x1,%d1
2875 bpl.b fm_7
2876 fmovm.x &0x02,(0x4+0x8,%a6,%d0)
2877 addi.l &0xc,%d0
2878fm_7:
2879 lsl.b &0x1,%d1
2880 bpl.b fm_end
2881 fmovm.x &0x01,(0x4+0x8,%a6,%d0)
2882fm_end:
2883 mov.l 0x4(%sp),%d1
2884 mov.l 0x8(%sp),%d0
2885 mov.l 0xc(%sp),%a6
2886 mov.l (%sp)+,%sp
2887
2888 btst &0x7,(%sp) # is trace enabled?
2889 beq.l _fpsp_done
2890 bra.l _real_trace
2891
2892#########################################################################
2893iea_fmovm_ctrl:
2894
2895 bsr.l fmovm_ctrl # load ctrl regs
2896
2897iea_fmovm_exit:
2898 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2899 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2900 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2901
2902 btst &0x7,EXC_SR(%a6) # is trace on?
2903 bne.b iea_fmovm_trace # yes
2904
2905 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set Next PC
2906
2907 unlk %a6 # unravel the frame
2908
2909 bra.l _fpsp_done # exit to os
2910
2911#
2912# The control reg instruction that took an "Unimplemented Effective Address"
2913# exception was being traced. The "Current PC" for the trace frame is the
2914# PC stacked for Unimp EA. The "Next PC" is in EXC_EXTWPTR.
2915# After fixing the stack frame, jump to _real_trace().
2916#
2917# UNIMP EA FRAME TRACE FRAME
2918# ***************** *****************
2919# * 0x0 * 0x0f0 * * Current *
2920# ***************** * PC *
2921# * Current * *****************
2922# * PC * * 0x2 * 0x024 *
2923# ***************** *****************
2924# * SR * * Next *
2925# ***************** * PC *
2926# *****************
2927# * SR *
2928# *****************
2929# this ain't a pretty solution, but it works:
2930# -restore a6 (not with unlk)
2931# -shift stack frame down over where old a6 used to be
2932# -add LOCAL_SIZE to stack pointer
2933iea_fmovm_trace:
2934 mov.l (%a6),%a6 # restore frame pointer
2935 mov.w EXC_SR+LOCAL_SIZE(%sp),0x0+LOCAL_SIZE(%sp)
2936 mov.l EXC_PC+LOCAL_SIZE(%sp),0x8+LOCAL_SIZE(%sp)
2937 mov.l EXC_EXTWPTR+LOCAL_SIZE(%sp),0x2+LOCAL_SIZE(%sp)
2938 mov.w &0x2024,0x6+LOCAL_SIZE(%sp) # stk fmt = 0x2; voff = 0x024
2939 add.l &LOCAL_SIZE,%sp # clear stack frame
2940
2941 bra.l _real_trace
2942
2943#########################################################################
2944# The FPU is disabled and so we should really have taken the "Line
2945# F Emulator" exception. So, here we create an 8-word stack frame
2946# from our 4-word stack frame. This means we must calculate the length
2947# the faulting instruction to get the "next PC". This is trivial for
2948# immediate operands but requires some extra work for fmovm dynamic
2949# which can use most addressing modes.
2950iea_disabled:
2951 mov.l (%sp)+,%d0 # restore d0
2952
2953 link %a6,&-LOCAL_SIZE # init stack frame
2954
2955 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2956
2957# PC of instruction that took the exception is the PC in the frame
2958 mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
2959 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
2960 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
2961 bsr.l _imem_read_long # fetch the instruction words
2962 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
2963
2964 tst.w %d0 # is instr fmovm?
2965 bmi.b iea_dis_fmovm # yes
2966# instruction is using an extended precision immediate operand. therefore,
2967# the total instruction length is 16 bytes.
2968iea_dis_immed:
2969 mov.l &0x10,%d0 # 16 bytes of instruction
2970 bra.b iea_dis_cont
2971iea_dis_fmovm:
2972 btst &0xe,%d0 # is instr fmovm ctrl
2973 bne.b iea_dis_fmovm_data # no
2974# the instruction is a fmovm.l with 2 or 3 registers.
2975 bfextu %d0{&19:&3},%d1
2976 mov.l &0xc,%d0
2977 cmpi.b %d1,&0x7 # move all regs?
2978 bne.b iea_dis_cont
2979 addq.l &0x4,%d0
2980 bra.b iea_dis_cont
2981# the instruction is an fmovm.x dynamic which can use many addressing
2982# modes and thus can have several different total instruction lengths.
2983# call fmovm_calc_ea which will go through the ea calc process and,
2984# as a by-product, will tell us how long the instruction is.
2985iea_dis_fmovm_data:
2986 clr.l %d0
2987 bsr.l fmovm_calc_ea
2988 mov.l EXC_EXTWPTR(%a6),%d0
2989 sub.l EXC_PC(%a6),%d0
2990iea_dis_cont:
2991 mov.w %d0,EXC_VOFF(%a6) # store stack shift value
2992
2993 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2994
2995 unlk %a6
2996
2997# here, we actually create the 8-word frame from the 4-word frame,
2998# with the "next PC" as additional info.
2999# the <ea> field is let as undefined.
3000 subq.l &0x8,%sp # make room for new stack
3001 mov.l %d0,-(%sp) # save d0
3002 mov.w 0xc(%sp),0x4(%sp) # move SR
3003 mov.l 0xe(%sp),0x6(%sp) # move Current PC
3004 clr.l %d0
3005 mov.w 0x12(%sp),%d0
3006 mov.l 0x6(%sp),0x10(%sp) # move Current PC
3007 add.l %d0,0x6(%sp) # make Next PC
3008 mov.w &0x402c,0xa(%sp) # insert offset,frame format
3009 mov.l (%sp)+,%d0 # restore d0
3010
3011 bra.l _real_fpu_disabled
3012
3013##########
3014
3015iea_iacc:
3016 movc %pcr,%d0
3017 btst &0x1,%d0
3018 bne.b iea_iacc_cont
3019 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3020 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack
3021iea_iacc_cont:
3022 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3023
3024 unlk %a6
3025
3026 subq.w &0x8,%sp # make stack frame bigger
3027 mov.l 0x8(%sp),(%sp) # store SR,hi(PC)
3028 mov.w 0xc(%sp),0x4(%sp) # store lo(PC)
3029 mov.w &0x4008,0x6(%sp) # store voff
3030 mov.l 0x2(%sp),0x8(%sp) # store ea
3031 mov.l &0x09428001,0xc(%sp) # store fslw
3032
3033iea_acc_done:
3034 btst &0x5,(%sp) # user or supervisor mode?
3035 beq.b iea_acc_done2 # user
3036 bset &0x2,0xd(%sp) # set supervisor TM bit
3037
3038iea_acc_done2:
3039 bra.l _real_access
3040
3041iea_dacc:
3042 lea -LOCAL_SIZE(%a6),%sp
3043
3044 movc %pcr,%d1
3045 btst &0x1,%d1
3046 bne.b iea_dacc_cont
3047 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack
3048 fmovm.l LOCAL_SIZE+USER_FPCR(%sp),%fpcr,%fpsr,%fpiar # restore ctrl regs
3049iea_dacc_cont:
3050 mov.l (%a6),%a6
3051
3052 mov.l 0x4+LOCAL_SIZE(%sp),-0x8+0x4+LOCAL_SIZE(%sp)
3053 mov.w 0x8+LOCAL_SIZE(%sp),-0x8+0x8+LOCAL_SIZE(%sp)
3054 mov.w &0x4008,-0x8+0xa+LOCAL_SIZE(%sp)
3055 mov.l %a0,-0x8+0xc+LOCAL_SIZE(%sp)
3056 mov.w %d0,-0x8+0x10+LOCAL_SIZE(%sp)
3057 mov.w &0x0001,-0x8+0x12+LOCAL_SIZE(%sp)
3058
3059 movm.l LOCAL_SIZE+EXC_DREGS(%sp),&0x0303 # restore d0-d1/a0-a1
3060 add.w &LOCAL_SIZE-0x4,%sp
3061
3062 bra.b iea_acc_done
3063
3064#########################################################################
3065# XDEF **************************************************************** #
3066# _fpsp_operr(): 060FPSP entry point for FP Operr exception. #
3067# #
3068# This handler should be the first code executed upon taking the #
3069# FP Operand Error exception in an operating system. #
3070# #
3071# XREF **************************************************************** #
3072# _imem_read_long() - read instruction longword #
3073# fix_skewed_ops() - adjust src operand in fsave frame #
3074# _real_operr() - "callout" to operating system operr handler #
3075# _dmem_write_{byte,word,long}() - store data to mem (opclass 3) #
3076# store_dreg_{b,w,l}() - store data to data regfile (opclass 3) #
3077# facc_out_{b,w,l}() - store to memory took access error (opcl 3) #
3078# #
3079# INPUT *************************************************************** #
3080# - The system stack contains the FP Operr exception frame #
3081# - The fsave frame contains the source operand #
3082# #
3083# OUTPUT ************************************************************** #
3084# No access error: #
3085# - The system stack is unchanged #
3086# - The fsave frame contains the adjusted src op for opclass 0,2 #
3087# #
3088# ALGORITHM *********************************************************** #
3089# In a system where the FP Operr exception is enabled, the goal #
3090# is to get to the handler specified at _real_operr(). But, on the 060, #
3091# for opclass zero and two instruction taking this exception, the #
3092# input operand in the fsave frame may be incorrect for some cases #
3093# and needs to be corrected. This handler calls fix_skewed_ops() to #
3094# do just this and then exits through _real_operr(). #
3095# For opclass 3 instructions, the 060 doesn't store the default #
3096# operr result out to memory or data register file as it should. #
3097# This code must emulate the move out before finally exiting through #
3098# _real_inex(). The move out, if to memory, is performed using #
3099# _mem_write() "callout" routines that may return a failing result. #
3100# In this special case, the handler must exit through facc_out() #
3101# which creates an access error stack frame from the current operr #
3102# stack frame. #
3103# #
3104#########################################################################
3105
3106 global _fpsp_operr
3107_fpsp_operr:
3108
3109 link.w %a6,&-LOCAL_SIZE # init stack frame
3110
3111 fsave FP_SRC(%a6) # grab the "busy" frame
3112
3113 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3114 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3115 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3116
3117# the FPIAR holds the "current PC" of the faulting instruction
3118 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3119
3120 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3121 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3122 bsr.l _imem_read_long # fetch the instruction words
3123 mov.l %d0,EXC_OPWORD(%a6)
3124
3125##############################################################################
3126
3127 btst &13,%d0 # is instr an fmove out?
3128 bne.b foperr_out # fmove out
3129
3130
3131# here, we simply see if the operand in the fsave frame needs to be "unskewed".
3132# this would be the case for opclass two operations with a source infinity or
3133# denorm operand in the sgl or dbl format. NANs also become skewed, but can't
3134# cause an operr so we don't need to check for them here.
3135 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3136 bsr.l fix_skewed_ops # fix src op
3137
3138foperr_exit:
3139 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3140 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3141 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3142
3143 frestore FP_SRC(%a6)
3144
3145 unlk %a6
3146 bra.l _real_operr
3147
3148########################################################################
3149
3150#
3151# the hardware does not save the default result to memory on enabled
3152# operand error exceptions. we do this here before passing control to
3153# the user operand error handler.
3154#
3155# byte, word, and long destination format operations can pass
3156# through here. we simply need to test the sign of the src
3157# operand and save the appropriate minimum or maximum integer value
3158# to the effective address as pointed to by the stacked effective address.
3159#
3160# although packed opclass three operations can take operand error
3161# exceptions, they won't pass through here since they are caught
3162# first by the unsupported data format exception handler. that handler
3163# sends them directly to _real_operr() if necessary.
3164#
3165foperr_out:
3166
3167 mov.w FP_SRC_EX(%a6),%d1 # fetch exponent
3168 andi.w &0x7fff,%d1
3169 cmpi.w %d1,&0x7fff
3170 bne.b foperr_out_not_qnan
3171# the operand is either an infinity or a QNAN.
3172 tst.l FP_SRC_LO(%a6)
3173 bne.b foperr_out_qnan
3174 mov.l FP_SRC_HI(%a6),%d1
3175 andi.l &0x7fffffff,%d1
3176 beq.b foperr_out_not_qnan
3177foperr_out_qnan:
3178 mov.l FP_SRC_HI(%a6),L_SCR1(%a6)
3179 bra.b foperr_out_jmp
3180
3181foperr_out_not_qnan:
3182 mov.l &0x7fffffff,%d1
3183 tst.b FP_SRC_EX(%a6)
3184 bpl.b foperr_out_not_qnan2
3185 addq.l &0x1,%d1
3186foperr_out_not_qnan2:
3187 mov.l %d1,L_SCR1(%a6)
3188
3189foperr_out_jmp:
3190 bfextu %d0{&19:&3},%d0 # extract dst format field
3191 mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg
3192 mov.w (tbl_operr.b,%pc,%d0.w*2),%a0
3193 jmp (tbl_operr.b,%pc,%a0)
3194
3195tbl_operr:
3196 short foperr_out_l - tbl_operr # long word integer
3197 short tbl_operr - tbl_operr # sgl prec shouldn't happen
3198 short tbl_operr - tbl_operr # ext prec shouldn't happen
3199 short foperr_exit - tbl_operr # packed won't enter here
3200 short foperr_out_w - tbl_operr # word integer
3201 short tbl_operr - tbl_operr # dbl prec shouldn't happen
3202 short foperr_out_b - tbl_operr # byte integer
3203 short tbl_operr - tbl_operr # packed won't enter here
3204
3205foperr_out_b:
3206 mov.b L_SCR1(%a6),%d0 # load positive default result
3207 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3208 ble.b foperr_out_b_save_dn # yes
3209 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3210 bsr.l _dmem_write_byte # write the default result
3211
3212 tst.l %d1 # did dstore fail?
3213 bne.l facc_out_b # yes
3214
3215 bra.w foperr_exit
3216foperr_out_b_save_dn:
3217 andi.w &0x0007,%d1
3218 bsr.l store_dreg_b # store result to regfile
3219 bra.w foperr_exit
3220
3221foperr_out_w:
3222 mov.w L_SCR1(%a6),%d0 # load positive default result
3223 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3224 ble.b foperr_out_w_save_dn # yes
3225 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3226 bsr.l _dmem_write_word # write the default result
3227
3228 tst.l %d1 # did dstore fail?
3229 bne.l facc_out_w # yes
3230
3231 bra.w foperr_exit
3232foperr_out_w_save_dn:
3233 andi.w &0x0007,%d1
3234 bsr.l store_dreg_w # store result to regfile
3235 bra.w foperr_exit
3236
3237foperr_out_l:
3238 mov.l L_SCR1(%a6),%d0 # load positive default result
3239 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3240 ble.b foperr_out_l_save_dn # yes
3241 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3242 bsr.l _dmem_write_long # write the default result
3243
3244 tst.l %d1 # did dstore fail?
3245 bne.l facc_out_l # yes
3246
3247 bra.w foperr_exit
3248foperr_out_l_save_dn:
3249 andi.w &0x0007,%d1
3250 bsr.l store_dreg_l # store result to regfile
3251 bra.w foperr_exit
3252
3253#########################################################################
3254# XDEF **************************************************************** #
3255# _fpsp_snan(): 060FPSP entry point for FP SNAN exception. #
3256# #
3257# This handler should be the first code executed upon taking the #
3258# FP Signalling NAN exception in an operating system. #
3259# #
3260# XREF **************************************************************** #
3261# _imem_read_long() - read instruction longword #
3262# fix_skewed_ops() - adjust src operand in fsave frame #
3263# _real_snan() - "callout" to operating system SNAN handler #
3264# _dmem_write_{byte,word,long}() - store data to mem (opclass 3) #
3265# store_dreg_{b,w,l}() - store data to data regfile (opclass 3) #
3266# facc_out_{b,w,l,d,x}() - store to mem took acc error (opcl 3) #
3267# _calc_ea_fout() - fix An if <ea> is -() or ()+; also get <ea> #
3268# #
3269# INPUT *************************************************************** #
3270# - The system stack contains the FP SNAN exception frame #
3271# - The fsave frame contains the source operand #
3272# #
3273# OUTPUT ************************************************************** #
3274# No access error: #
3275# - The system stack is unchanged #
3276# - The fsave frame contains the adjusted src op for opclass 0,2 #
3277# #
3278# ALGORITHM *********************************************************** #
3279# In a system where the FP SNAN exception is enabled, the goal #
3280# is to get to the handler specified at _real_snan(). But, on the 060, #
3281# for opclass zero and two instructions taking this exception, the #
3282# input operand in the fsave frame may be incorrect for some cases #
3283# and needs to be corrected. This handler calls fix_skewed_ops() to #
3284# do just this and then exits through _real_snan(). #
3285# For opclass 3 instructions, the 060 doesn't store the default #
3286# SNAN result out to memory or data register file as it should. #
3287# This code must emulate the move out before finally exiting through #
3288# _real_snan(). The move out, if to memory, is performed using #
3289# _mem_write() "callout" routines that may return a failing result. #
3290# In this special case, the handler must exit through facc_out() #
3291# which creates an access error stack frame from the current SNAN #
3292# stack frame. #
3293# For the case of an extended precision opclass 3 instruction, #
3294# if the effective addressing mode was -() or ()+, then the address #
3295# register must get updated by calling _calc_ea_fout(). If the <ea> #
3296# was -(a7) from supervisor mode, then the exception frame currently #
3297# on the system stack must be carefully moved "down" to make room #
3298# for the operand being moved. #
3299# #
3300#########################################################################
3301
3302 global _fpsp_snan
3303_fpsp_snan:
3304
3305 link.w %a6,&-LOCAL_SIZE # init stack frame
3306
3307 fsave FP_SRC(%a6) # grab the "busy" frame
3308
3309 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3310 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3311 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3312
3313# the FPIAR holds the "current PC" of the faulting instruction
3314 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3315
3316 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3317 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3318 bsr.l _imem_read_long # fetch the instruction words
3319 mov.l %d0,EXC_OPWORD(%a6)
3320
3321##############################################################################
3322
3323 btst &13,%d0 # is instr an fmove out?
3324 bne.w fsnan_out # fmove out
3325
3326
3327# here, we simply see if the operand in the fsave frame needs to be "unskewed".
3328# this would be the case for opclass two operations with a source infinity or
3329# denorm operand in the sgl or dbl format. NANs also become skewed and must be
3330# fixed here.
3331 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3332 bsr.l fix_skewed_ops # fix src op
3333
3334fsnan_exit:
3335 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3336 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3337 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3338
3339 frestore FP_SRC(%a6)
3340
3341 unlk %a6
3342 bra.l _real_snan
3343
3344########################################################################
3345
3346#
3347# the hardware does not save the default result to memory on enabled
3348# snan exceptions. we do this here before passing control to
3349# the user snan handler.
3350#
3351# byte, word, long, and packed destination format operations can pass
3352# through here. since packed format operations already were handled by
3353# fpsp_unsupp(), then we need to do nothing else for them here.
3354# for byte, word, and long, we simply need to test the sign of the src
3355# operand and save the appropriate minimum or maximum integer value
3356# to the effective address as pointed to by the stacked effective address.
3357#
3358fsnan_out:
3359
3360 bfextu %d0{&19:&3},%d0 # extract dst format field
3361 mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg
3362 mov.w (tbl_snan.b,%pc,%d0.w*2),%a0
3363 jmp (tbl_snan.b,%pc,%a0)
3364
3365tbl_snan:
3366 short fsnan_out_l - tbl_snan # long word integer
3367 short fsnan_out_s - tbl_snan # sgl prec shouldn't happen
3368 short fsnan_out_x - tbl_snan # ext prec shouldn't happen
3369 short tbl_snan - tbl_snan # packed needs no help
3370 short fsnan_out_w - tbl_snan # word integer
3371 short fsnan_out_d - tbl_snan # dbl prec shouldn't happen
3372 short fsnan_out_b - tbl_snan # byte integer
3373 short tbl_snan - tbl_snan # packed needs no help
3374
3375fsnan_out_b:
3376 mov.b FP_SRC_HI(%a6),%d0 # load upper byte of SNAN
3377 bset &6,%d0 # set SNAN bit
3378 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3379 ble.b fsnan_out_b_dn # yes
3380 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3381 bsr.l _dmem_write_byte # write the default result
3382
3383 tst.l %d1 # did dstore fail?
3384 bne.l facc_out_b # yes
3385
3386 bra.w fsnan_exit
3387fsnan_out_b_dn:
3388 andi.w &0x0007,%d1
3389 bsr.l store_dreg_b # store result to regfile
3390 bra.w fsnan_exit
3391
3392fsnan_out_w:
3393 mov.w FP_SRC_HI(%a6),%d0 # load upper word of SNAN
3394 bset &14,%d0 # set SNAN bit
3395 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3396 ble.b fsnan_out_w_dn # yes
3397 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3398 bsr.l _dmem_write_word # write the default result
3399
3400 tst.l %d1 # did dstore fail?
3401 bne.l facc_out_w # yes
3402
3403 bra.w fsnan_exit
3404fsnan_out_w_dn:
3405 andi.w &0x0007,%d1
3406 bsr.l store_dreg_w # store result to regfile
3407 bra.w fsnan_exit
3408
3409fsnan_out_l:
3410 mov.l FP_SRC_HI(%a6),%d0 # load upper longword of SNAN
3411 bset &30,%d0 # set SNAN bit
3412 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3413 ble.b fsnan_out_l_dn # yes
3414 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3415 bsr.l _dmem_write_long # write the default result
3416
3417 tst.l %d1 # did dstore fail?
3418 bne.l facc_out_l # yes
3419
3420 bra.w fsnan_exit
3421fsnan_out_l_dn:
3422 andi.w &0x0007,%d1
3423 bsr.l store_dreg_l # store result to regfile
3424 bra.w fsnan_exit
3425
3426fsnan_out_s:
3427 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3428 ble.b fsnan_out_d_dn # yes
3429 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3430 andi.l &0x80000000,%d0 # keep sign
3431 ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit
3432 mov.l FP_SRC_HI(%a6),%d1 # load mantissa
3433 lsr.l &0x8,%d1 # shift mantissa for sgl
3434 or.l %d1,%d0 # create sgl SNAN
3435 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3436 bsr.l _dmem_write_long # write the default result
3437
3438 tst.l %d1 # did dstore fail?
3439 bne.l facc_out_l # yes
3440
3441 bra.w fsnan_exit
3442fsnan_out_d_dn:
3443 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3444 andi.l &0x80000000,%d0 # keep sign
3445 ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit
3446 mov.l %d1,-(%sp)
3447 mov.l FP_SRC_HI(%a6),%d1 # load mantissa
3448 lsr.l &0x8,%d1 # shift mantissa for sgl
3449 or.l %d1,%d0 # create sgl SNAN
3450 mov.l (%sp)+,%d1
3451 andi.w &0x0007,%d1
3452 bsr.l store_dreg_l # store result to regfile
3453 bra.w fsnan_exit
3454
3455fsnan_out_d:
3456 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3457 andi.l &0x80000000,%d0 # keep sign
3458 ori.l &0x7ff80000,%d0 # insert new exponent,SNAN bit
3459 mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa
3460 mov.l %d0,FP_SCR0_EX(%a6) # store to temp space
3461 mov.l &11,%d0 # load shift amt
3462 lsr.l %d0,%d1
3463 or.l %d1,FP_SCR0_EX(%a6) # create dbl hi
3464 mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa
3465 andi.l &0x000007ff,%d1
3466 ror.l %d0,%d1
3467 mov.l %d1,FP_SCR0_HI(%a6) # store to temp space
3468 mov.l FP_SRC_LO(%a6),%d1 # load lo mantissa
3469 lsr.l %d0,%d1
3470 or.l %d1,FP_SCR0_HI(%a6) # create dbl lo
3471 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
3472 mov.l EXC_EA(%a6),%a1 # pass: dst addr
3473 movq.l &0x8,%d0 # pass: size of 8 bytes
3474 bsr.l _dmem_write # write the default result
3475
3476 tst.l %d1 # did dstore fail?
3477 bne.l facc_out_d # yes
3478
3479 bra.w fsnan_exit
3480
3481# for extended precision, if the addressing mode is pre-decrement or
3482# post-increment, then the address register did not get updated.
3483# in addition, for pre-decrement, the stacked <ea> is incorrect.
3484fsnan_out_x:
3485 clr.b SPCOND_FLG(%a6) # clear special case flag
3486
3487 mov.w FP_SRC_EX(%a6),FP_SCR0_EX(%a6)
3488 clr.w 2+FP_SCR0(%a6)
3489 mov.l FP_SRC_HI(%a6),%d0
3490 bset &30,%d0
3491 mov.l %d0,FP_SCR0_HI(%a6)
3492 mov.l FP_SRC_LO(%a6),FP_SCR0_LO(%a6)
3493
3494 btst &0x5,EXC_SR(%a6) # supervisor mode exception?
3495 bne.b fsnan_out_x_s # yes
3496
3497 mov.l %usp,%a0 # fetch user stack pointer
3498 mov.l %a0,EXC_A7(%a6) # save on stack for calc_ea()
3499 mov.l (%a6),EXC_A6(%a6)
3500
3501 bsr.l _calc_ea_fout # find the correct ea,update An
3502 mov.l %a0,%a1
3503 mov.l %a0,EXC_EA(%a6) # stack correct <ea>
3504
3505 mov.l EXC_A7(%a6),%a0
3506 mov.l %a0,%usp # restore user stack pointer
3507 mov.l EXC_A6(%a6),(%a6)
3508
3509fsnan_out_x_save:
3510 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
3511 movq.l &0xc,%d0 # pass: size of extended
3512 bsr.l _dmem_write # write the default result
3513
3514 tst.l %d1 # did dstore fail?
3515 bne.l facc_out_x # yes
3516
3517 bra.w fsnan_exit
3518
3519fsnan_out_x_s:
3520 mov.l (%a6),EXC_A6(%a6)
3521
3522 bsr.l _calc_ea_fout # find the correct ea,update An
3523 mov.l %a0,%a1
3524 mov.l %a0,EXC_EA(%a6) # stack correct <ea>
3525
3526 mov.l EXC_A6(%a6),(%a6)
3527
3528 cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
3529 bne.b fsnan_out_x_save # no
3530
3531# the operation was "fmove.x SNAN,-(a7)" from supervisor mode.
3532 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3533 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3534 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3535
3536 frestore FP_SRC(%a6)
3537
3538 mov.l EXC_A6(%a6),%a6 # restore frame pointer
3539
3540 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
3541 mov.l LOCAL_SIZE+EXC_PC+0x2(%sp),LOCAL_SIZE+EXC_PC+0x2-0xc(%sp)
3542 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
3543
3544 mov.l LOCAL_SIZE+FP_SCR0_EX(%sp),LOCAL_SIZE+EXC_SR(%sp)
3545 mov.l LOCAL_SIZE+FP_SCR0_HI(%sp),LOCAL_SIZE+EXC_PC+0x2(%sp)
3546 mov.l LOCAL_SIZE+FP_SCR0_LO(%sp),LOCAL_SIZE+EXC_EA(%sp)
3547
3548 add.l &LOCAL_SIZE-0x8,%sp
3549
3550 bra.l _real_snan
3551
3552#########################################################################
3553# XDEF **************************************************************** #
3554# _fpsp_inex(): 060FPSP entry point for FP Inexact exception. #
3555# #
3556# This handler should be the first code executed upon taking the #
3557# FP Inexact exception in an operating system. #
3558# #
3559# XREF **************************************************************** #
3560# _imem_read_long() - read instruction longword #
3561# fix_skewed_ops() - adjust src operand in fsave frame #
3562# set_tag_x() - determine optype of src/dst operands #
3563# store_fpreg() - store opclass 0 or 2 result to FP regfile #
3564# unnorm_fix() - change UNNORM operands to NORM or ZERO #
3565# load_fpn2() - load dst operand from FP regfile #
3566# smovcr() - emulate an "fmovcr" instruction #
3567# fout() - emulate an opclass 3 instruction #
3568# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
3569# _real_inex() - "callout" to operating system inexact handler #
3570# #
3571# INPUT *************************************************************** #
3572# - The system stack contains the FP Inexact exception frame #
3573# - The fsave frame contains the source operand #
3574# #
3575# OUTPUT ************************************************************** #
3576# - The system stack is unchanged #
3577# - The fsave frame contains the adjusted src op for opclass 0,2 #
3578# #
3579# ALGORITHM *********************************************************** #
3580# In a system where the FP Inexact exception is enabled, the goal #
3581# is to get to the handler specified at _real_inex(). But, on the 060, #
3582# for opclass zero and two instruction taking this exception, the #
3583# hardware doesn't store the correct result to the destination FP #
3584# register as did the '040 and '881/2. This handler must emulate the #
3585# instruction in order to get this value and then store it to the #
3586# correct register before calling _real_inex(). #
3587# For opclass 3 instructions, the 060 doesn't store the default #
3588# inexact result out to memory or data register file as it should. #
3589# This code must emulate the move out by calling fout() before finally #
3590# exiting through _real_inex(). #
3591# #
3592#########################################################################
3593
3594 global _fpsp_inex
3595_fpsp_inex:
3596
3597 link.w %a6,&-LOCAL_SIZE # init stack frame
3598
3599 fsave FP_SRC(%a6) # grab the "busy" frame
3600
3601 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3602 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3603 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3604
3605# the FPIAR holds the "current PC" of the faulting instruction
3606 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3607
3608 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3609 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3610 bsr.l _imem_read_long # fetch the instruction words
3611 mov.l %d0,EXC_OPWORD(%a6)
3612
3613##############################################################################
3614
3615 btst &13,%d0 # is instr an fmove out?
3616 bne.w finex_out # fmove out
3617
3618
3619# the hardware, for "fabs" and "fneg" w/ a long source format, puts the
3620# longword integer directly into the upper longword of the mantissa along
3621# w/ an exponent value of 0x401e. we convert this to extended precision here.
3622 bfextu %d0{&19:&3},%d0 # fetch instr size
3623 bne.b finex_cont # instr size is not long
3624 cmpi.w FP_SRC_EX(%a6),&0x401e # is exponent 0x401e?
3625 bne.b finex_cont # no
3626 fmov.l &0x0,%fpcr
3627 fmov.l FP_SRC_HI(%a6),%fp0 # load integer src
3628 fmov.x %fp0,FP_SRC(%a6) # store integer as extended precision
3629 mov.w &0xe001,0x2+FP_SRC(%a6)
3630
3631finex_cont:
3632 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3633 bsr.l fix_skewed_ops # fix src op
3634
3635# Here, we zero the ccode and exception byte field since we're going to
3636# emulate the whole instruction. Notice, though, that we don't kill the
3637# INEX1 bit. This is because a packed op has long since been converted
3638# to extended before arriving here. Therefore, we need to retain the
3639# INEX1 bit from when the operand was first converted.
3640 andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
3641
3642 fmov.l &0x0,%fpcr # zero current control regs
3643 fmov.l &0x0,%fpsr
3644
3645 bfextu EXC_EXTWORD(%a6){&0:&6},%d1 # extract upper 6 of cmdreg
3646 cmpi.b %d1,&0x17 # is op an fmovecr?
3647 beq.w finex_fmovcr # yes
3648
3649 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3650 bsr.l set_tag_x # tag the operand type
3651 mov.b %d0,STAG(%a6) # maybe NORM,DENORM
3652
3653# bits four and five of the fp extension word separate the monadic and dyadic
3654# operations that can pass through fpsp_inex(). remember that fcmp and ftst
3655# will never take this exception, but fsincos will.
3656 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
3657 beq.b finex_extract # monadic
3658
3659 btst &0x4,1+EXC_CMDREG(%a6) # is operation an fsincos?
3660 bne.b finex_extract # yes
3661
3662 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
3663 bsr.l load_fpn2 # load dst into FP_DST
3664
3665 lea FP_DST(%a6),%a0 # pass: ptr to dst op
3666 bsr.l set_tag_x # tag the operand type
3667 cmpi.b %d0,&UNNORM # is operand an UNNORM?
3668 bne.b finex_op2_done # no
3669 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
3670finex_op2_done:
3671 mov.b %d0,DTAG(%a6) # save dst optype tag
3672
3673finex_extract:
3674 clr.l %d0
3675 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
3676
3677 mov.b 1+EXC_CMDREG(%a6),%d1
3678 andi.w &0x007f,%d1 # extract extension
3679
3680 lea FP_SRC(%a6),%a0
3681 lea FP_DST(%a6),%a1
3682
3683 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
3684 jsr (tbl_unsupp.l,%pc,%d1.l*1)
3685
3686# the operation has been emulated. the result is in fp0.
3687finex_save:
3688 bfextu EXC_CMDREG(%a6){&6:&3},%d0
3689 bsr.l store_fpreg
3690
3691finex_exit:
3692 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3693 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3694 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3695
3696 frestore FP_SRC(%a6)
3697
3698 unlk %a6
3699 bra.l _real_inex
3700
3701finex_fmovcr:
3702 clr.l %d0
3703 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode
3704 mov.b 1+EXC_CMDREG(%a6),%d1
3705 andi.l &0x0000007f,%d1 # pass rom offset
3706 bsr.l smovcr
3707 bra.b finex_save
3708
3709########################################################################
3710
3711#
3712# the hardware does not save the default result to memory on enabled
3713# inexact exceptions. we do this here before passing control to
3714# the user inexact handler.
3715#
3716# byte, word, and long destination format operations can pass
3717# through here. so can double and single precision.
3718# although packed opclass three operations can take inexact
3719# exceptions, they won't pass through here since they are caught
3720# first by the unsupported data format exception handler. that handler
3721# sends them directly to _real_inex() if necessary.
3722#
3723finex_out:
3724
3725 mov.b &NORM,STAG(%a6) # src is a NORM
3726
3727 clr.l %d0
3728 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode
3729
3730 andi.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
3731
3732 lea FP_SRC(%a6),%a0 # pass ptr to src operand
3733
3734 bsr.l fout # store the default result
3735
3736 bra.b finex_exit
3737
3738#########################################################################
3739# XDEF **************************************************************** #
3740# _fpsp_dz(): 060FPSP entry point for FP DZ exception. #
3741# #
3742# This handler should be the first code executed upon taking #
3743# the FP DZ exception in an operating system. #
3744# #
3745# XREF **************************************************************** #
3746# _imem_read_long() - read instruction longword from memory #
3747# fix_skewed_ops() - adjust fsave operand #
3748# _real_dz() - "callout" exit point from FP DZ handler #
3749# #
3750# INPUT *************************************************************** #
3751# - The system stack contains the FP DZ exception stack. #
3752# - The fsave frame contains the source operand. #
3753# #
3754# OUTPUT ************************************************************** #
3755# - The system stack contains the FP DZ exception stack. #
3756# - The fsave frame contains the adjusted source operand. #
3757# #
3758# ALGORITHM *********************************************************** #
3759# In a system where the DZ exception is enabled, the goal is to #
3760# get to the handler specified at _real_dz(). But, on the 060, when the #
3761# exception is taken, the input operand in the fsave state frame may #
3762# be incorrect for some cases and need to be adjusted. So, this package #
3763# adjusts the operand using fix_skewed_ops() and then branches to #
3764# _real_dz(). #
3765# #
3766#########################################################################
3767
3768 global _fpsp_dz
3769_fpsp_dz:
3770
3771 link.w %a6,&-LOCAL_SIZE # init stack frame
3772
3773 fsave FP_SRC(%a6) # grab the "busy" frame
3774
3775 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3776 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3777 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3778
3779# the FPIAR holds the "current PC" of the faulting instruction
3780 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3781
3782 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3783 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3784 bsr.l _imem_read_long # fetch the instruction words
3785 mov.l %d0,EXC_OPWORD(%a6)
3786
3787##############################################################################
3788
3789
3790# here, we simply see if the operand in the fsave frame needs to be "unskewed".
3791# this would be the case for opclass two operations with a source zero
3792# in the sgl or dbl format.
3793 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3794 bsr.l fix_skewed_ops # fix src op
3795
3796fdz_exit:
3797 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3798 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3799 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3800
3801 frestore FP_SRC(%a6)
3802
3803 unlk %a6
3804 bra.l _real_dz
3805
3806#########################################################################
3807# XDEF **************************************************************** #
3808# _fpsp_fline(): 060FPSP entry point for "Line F emulator" exc. #
3809# #
3810# This handler should be the first code executed upon taking the #
3811# "Line F Emulator" exception in an operating system. #
3812# #
3813# XREF **************************************************************** #
3814# _fpsp_unimp() - handle "FP Unimplemented" exceptions #
3815# _real_fpu_disabled() - handle "FPU disabled" exceptions #
3816# _real_fline() - handle "FLINE" exceptions #
3817# _imem_read_long() - read instruction longword #
3818# #
3819# INPUT *************************************************************** #
3820# - The system stack contains a "Line F Emulator" exception #
3821# stack frame. #
3822# #
3823# OUTPUT ************************************************************** #
3824# - The system stack is unchanged #
3825# #
3826# ALGORITHM *********************************************************** #
3827# When a "Line F Emulator" exception occurs, there are 3 possible #
3828# exception types, denoted by the exception stack frame format number: #
3829# (1) FPU unimplemented instruction (6 word stack frame) #
3830# (2) FPU disabled (8 word stack frame) #
3831# (3) Line F (4 word stack frame) #
3832# #
3833# This module determines which and forks the flow off to the #
3834# appropriate "callout" (for "disabled" and "Line F") or to the #
3835# correct emulation code (for "FPU unimplemented"). #
3836# This code also must check for "fmovecr" instructions w/ a #
3837# non-zero <ea> field. These may get flagged as "Line F" but should #
3838# really be flagged as "FPU Unimplemented". (This is a "feature" on #
3839# the '060. #
3840# #
3841#########################################################################
3842
3843 global _fpsp_fline
3844_fpsp_fline:
3845
3846# check to see if this exception is a "FP Unimplemented Instruction"
3847# exception. if so, branch directly to that handler's entry point.
3848 cmpi.w 0x6(%sp),&0x202c
3849 beq.l _fpsp_unimp
3850
3851# check to see if the FPU is disabled. if so, jump to the OS entry
3852# point for that condition.
3853 cmpi.w 0x6(%sp),&0x402c
3854 beq.l _real_fpu_disabled
3855
3856# the exception was an "F-Line Illegal" exception. we check to see
3857# if the F-Line instruction is an "fmovecr" w/ a non-zero <ea>. if
3858# so, convert the F-Line exception stack frame to an FP Unimplemented
3859# Instruction exception stack frame else branch to the OS entry
3860# point for the F-Line exception handler.
3861 link.w %a6,&-LOCAL_SIZE # init stack frame
3862
3863 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3864
3865 mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
3866 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3867 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3868 bsr.l _imem_read_long # fetch instruction words
3869
3870 bfextu %d0{&0:&10},%d1 # is it an fmovecr?
3871 cmpi.w %d1,&0x03c8
3872 bne.b fline_fline # no
3873
3874 bfextu %d0{&16:&6},%d1 # is it an fmovecr?
3875 cmpi.b %d1,&0x17
3876 bne.b fline_fline # no
3877
3878# it's an fmovecr w/ a non-zero <ea> that has entered through
3879# the F-Line Illegal exception.
3880# so, we need to convert the F-Line exception stack frame into an
3881# FP Unimplemented Instruction stack frame and jump to that entry
3882# point.
3883#
3884# but, if the FPU is disabled, then we need to jump to the FPU diabled
3885# entry point.
3886 movc %pcr,%d0
3887 btst &0x1,%d0
3888 beq.b fline_fmovcr
3889
3890 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3891
3892 unlk %a6
3893
3894 sub.l &0x8,%sp # make room for "Next PC", <ea>
3895 mov.w 0x8(%sp),(%sp)
3896 mov.l 0xa(%sp),0x2(%sp) # move "Current PC"
3897 mov.w &0x402c,0x6(%sp)
3898 mov.l 0x2(%sp),0xc(%sp)
3899 addq.l &0x4,0x2(%sp) # set "Next PC"
3900
3901 bra.l _real_fpu_disabled
3902
3903fline_fmovcr:
3904 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3905
3906 unlk %a6
3907
3908 fmov.l 0x2(%sp),%fpiar # set current PC
3909 addq.l &0x4,0x2(%sp) # set Next PC
3910
3911 mov.l (%sp),-(%sp)
3912 mov.l 0x8(%sp),0x4(%sp)
3913 mov.b &0x20,0x6(%sp)
3914
3915 bra.l _fpsp_unimp
3916
3917fline_fline:
3918 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3919
3920 unlk %a6
3921
3922 bra.l _real_fline
3923
3924#########################################################################
3925# XDEF **************************************************************** #
3926# _fpsp_unimp(): 060FPSP entry point for FP "Unimplemented #
3927# Instruction" exception. #
3928# #
3929# This handler should be the first code executed upon taking the #
3930# FP Unimplemented Instruction exception in an operating system. #
3931# #
3932# XREF **************************************************************** #
3933# _imem_read_{word,long}() - read instruction word/longword #
3934# load_fop() - load src/dst ops from memory and/or FP regfile #
3935# store_fpreg() - store opclass 0 or 2 result to FP regfile #
3936# tbl_trans - addr of table of emulation routines for trnscndls #
3937# _real_access() - "callout" for access error exception #
3938# _fpsp_done() - "callout" for exit; work all done #
3939# _real_trace() - "callout" for Trace enabled exception #
3940# smovcr() - emulate "fmovecr" instruction #
3941# funimp_skew() - adjust fsave src ops to "incorrect" value #
3942# _ftrapcc() - emulate an "ftrapcc" instruction #
3943# _fdbcc() - emulate an "fdbcc" instruction #
3944# _fscc() - emulate an "fscc" instruction #
3945# _real_trap() - "callout" for Trap exception #
3946# _real_bsun() - "callout" for enabled Bsun exception #
3947# #
3948# INPUT *************************************************************** #
3949# - The system stack contains the "Unimplemented Instr" stk frame #
3950# #
3951# OUTPUT ************************************************************** #
3952# If access error: #
3953# - The system stack is changed to an access error stack frame #
3954# If Trace exception enabled: #
3955# - The system stack is changed to a Trace exception stack frame #
3956# Else: (normal case) #
3957# - Correct result has been stored as appropriate #
3958# #
3959# ALGORITHM *********************************************************** #
3960# There are two main cases of instructions that may enter here to #
3961# be emulated: (1) the FPgen instructions, most of which were also #
3962# unimplemented on the 040, and (2) "ftrapcc", "fscc", and "fdbcc". #
3963# For the first set, this handler calls the routine load_fop() #
3964# to load the source and destination (for dyadic) operands to be used #
3965# for instruction emulation. The correct emulation routine is then #
3966# chosen by decoding the instruction type and indexing into an #
3967# emulation subroutine index table. After emulation returns, this #
3968# handler checks to see if an exception should occur as a result of the #
3969# FP instruction emulation. If so, then an FP exception of the correct #
3970# type is inserted into the FPU state frame using the "frestore" #
3971# instruction before exiting through _fpsp_done(). In either the #
3972# exceptional or non-exceptional cases, we must check to see if the #
3973# Trace exception is enabled. If so, then we must create a Trace #
3974# exception frame from the current exception frame and exit through #
3975# _real_trace(). #
3976# For "fdbcc", "ftrapcc", and "fscc", the emulation subroutines #
3977# _fdbcc(), _ftrapcc(), and _fscc() respectively are used. All three #
3978# may flag that a BSUN exception should be taken. If so, then the #
3979# current exception stack frame is converted into a BSUN exception #
3980# stack frame and an exit is made through _real_bsun(). If the #
3981# instruction was "ftrapcc" and a Trap exception should result, a Trap #
3982# exception stack frame is created from the current frame and an exit #
3983# is made through _real_trap(). If a Trace exception is pending, then #
3984# a Trace exception frame is created from the current frame and a jump #
3985# is made to _real_trace(). Finally, if none of these conditions exist, #
3986# then the handler exits though the callout _fpsp_done(). #
3987# #
3988# In any of the above scenarios, if a _mem_read() or _mem_write() #
3989# "callout" returns a failing value, then an access error stack frame #
3990# is created from the current stack frame and an exit is made through #
3991# _real_access(). #
3992# #
3993#########################################################################
3994
3995#
3996# FP UNIMPLEMENTED INSTRUCTION STACK FRAME:
3997#
3998# *****************
3999# * * => <ea> of fp unimp instr.
4000# - EA -
4001# * *
4002# *****************
4003# * 0x2 * 0x02c * => frame format and vector offset(vector #11)
4004# *****************
4005# * *
4006# - Next PC - => PC of instr to execute after exc handling
4007# * *
4008# *****************
4009# * SR * => SR at the time the exception was taken
4010# *****************
4011#
4012# Note: the !NULL bit does not get set in the fsave frame when the
4013# machine encounters an fp unimp exception. Therefore, it must be set
4014# before leaving this handler.
4015#
4016 global _fpsp_unimp
4017_fpsp_unimp:
4018
4019 link.w %a6,&-LOCAL_SIZE # init stack frame
4020
4021 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4022 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
4023 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1
4024
4025 btst &0x5,EXC_SR(%a6) # user mode exception?
4026 bne.b funimp_s # no; supervisor mode
4027
4028# save the value of the user stack pointer onto the stack frame
4029funimp_u:
4030 mov.l %usp,%a0 # fetch user stack pointer
4031 mov.l %a0,EXC_A7(%a6) # store in stack frame
4032 bra.b funimp_cont
4033
4034# store the value of the supervisor stack pointer BEFORE the exc occurred.
4035# old_sp is address just above stacked effective address.
4036funimp_s:
4037 lea 4+EXC_EA(%a6),%a0 # load old a7'
4038 mov.l %a0,EXC_A7(%a6) # store a7'
4039 mov.l %a0,OLD_A7(%a6) # make a copy
4040
4041funimp_cont:
4042
4043# the FPIAR holds the "current PC" of the faulting instruction.
4044 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
4045
4046 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4047 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
4048 bsr.l _imem_read_long # fetch the instruction words
4049 mov.l %d0,EXC_OPWORD(%a6)
4050
4051############################################################################
4052
4053 fmov.l &0x0,%fpcr # clear FPCR
4054 fmov.l &0x0,%fpsr # clear FPSR
4055
4056 clr.b SPCOND_FLG(%a6) # clear "special case" flag
4057
4058# Divide the fp instructions into 8 types based on the TYPE field in
4059# bits 6-8 of the opword(classes 6,7 are undefined).
4060# (for the '060, only two types can take this exception)
4061# bftst %d0{&7:&3} # test TYPE
4062 btst &22,%d0 # type 0 or 1 ?
4063 bne.w funimp_misc # type 1
4064
4065#########################################
4066# TYPE == 0: General instructions #
4067#########################################
4068funimp_gen:
4069
4070 clr.b STORE_FLG(%a6) # clear "store result" flag
4071
4072# clear the ccode byte and exception status byte
4073 andi.l &0x00ff00ff,USER_FPSR(%a6)
4074
4075 bfextu %d0{&16:&6},%d1 # extract upper 6 of cmdreg
4076 cmpi.b %d1,&0x17 # is op an fmovecr?
4077 beq.w funimp_fmovcr # yes
4078
4079funimp_gen_op:
4080 bsr.l _load_fop # load
4081
4082 clr.l %d0
4083 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode
4084
4085 mov.b 1+EXC_CMDREG(%a6),%d1
4086 andi.w &0x003f,%d1 # extract extension bits
4087 lsl.w &0x3,%d1 # shift right 3 bits
4088 or.b STAG(%a6),%d1 # insert src optag bits
4089
4090 lea FP_DST(%a6),%a1 # pass dst ptr in a1
4091 lea FP_SRC(%a6),%a0 # pass src ptr in a0
4092
4093 mov.w (tbl_trans.w,%pc,%d1.w*2),%d1
4094 jsr (tbl_trans.w,%pc,%d1.w*1) # emulate
4095
4096funimp_fsave:
4097 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
4098 bne.w funimp_ena # some are enabled
4099
4100funimp_store:
4101 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch Dn
4102 bsr.l store_fpreg # store result to fp regfile
4103
4104funimp_gen_exit:
4105 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
4106 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4107 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4108
4109funimp_gen_exit_cmp:
4110 cmpi.b SPCOND_FLG(%a6),&mia7_flg # was the ea mode (sp)+ ?
4111 beq.b funimp_gen_exit_a7 # yes
4112
4113 cmpi.b SPCOND_FLG(%a6),&mda7_flg # was the ea mode -(sp) ?
4114 beq.b funimp_gen_exit_a7 # yes
4115
4116funimp_gen_exit_cont:
4117 unlk %a6
4118
4119funimp_gen_exit_cont2:
4120 btst &0x7,(%sp) # is trace on?
4121 beq.l _fpsp_done # no
4122
4123# this catches a problem with the case where an exception will be re-inserted
4124# into the machine. the frestore has already been executed...so, the fmov.l
4125# alone of the control register would trigger an unwanted exception.
4126# until I feel like fixing this, we'll sidestep the exception.
4127 fsave -(%sp)
4128 fmov.l %fpiar,0x14(%sp) # "Current PC" is in FPIAR
4129 frestore (%sp)+
4130 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x24
4131 bra.l _real_trace
4132
4133funimp_gen_exit_a7:
4134 btst &0x5,EXC_SR(%a6) # supervisor or user mode?
4135 bne.b funimp_gen_exit_a7_s # supervisor
4136
4137 mov.l %a0,-(%sp)
4138 mov.l EXC_A7(%a6),%a0
4139 mov.l %a0,%usp
4140 mov.l (%sp)+,%a0
4141 bra.b funimp_gen_exit_cont
4142
4143# if the instruction was executed from supervisor mode and the addressing
4144# mode was (a7)+, then the stack frame for the rte must be shifted "up"
4145# "n" bytes where "n" is the size of the src operand type.
4146# f<op>.{b,w,l,s,d,x,p}
4147funimp_gen_exit_a7_s:
4148 mov.l %d0,-(%sp) # save d0
4149 mov.l EXC_A7(%a6),%d0 # load new a7'
4150 sub.l OLD_A7(%a6),%d0 # subtract old a7'
4151 mov.l 0x2+EXC_PC(%a6),(0x2+EXC_PC,%a6,%d0) # shift stack frame
4152 mov.l EXC_SR(%a6),(EXC_SR,%a6,%d0) # shift stack frame
4153 mov.w %d0,EXC_SR(%a6) # store incr number
4154 mov.l (%sp)+,%d0 # restore d0
4155
4156 unlk %a6
4157
4158 add.w (%sp),%sp # stack frame shifted
4159 bra.b funimp_gen_exit_cont2
4160
4161######################
4162# fmovecr.x #ccc,fpn #
4163######################
4164funimp_fmovcr:
4165 clr.l %d0
4166 mov.b FPCR_MODE(%a6),%d0
4167 mov.b 1+EXC_CMDREG(%a6),%d1
4168 andi.l &0x0000007f,%d1 # pass rom offset in d1
4169 bsr.l smovcr
4170 bra.w funimp_fsave
4171
4172#########################################################################
4173
4174#
4175# the user has enabled some exceptions. we figure not to see this too
4176# often so that's why it gets lower priority.
4177#
4178funimp_ena:
4179
4180# was an exception set that was also enabled?
4181 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled and set
4182 bfffo %d0{&24:&8},%d0 # find highest priority exception
4183 bne.b funimp_exc # at least one was set
4184
4185# no exception that was enabled was set BUT if we got an exact overflow
4186# and overflow wasn't enabled but inexact was (yech!) then this is
4187# an inexact exception; otherwise, return to normal non-exception flow.
4188 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
4189 beq.w funimp_store # no; return to normal flow
4190
4191# the overflow w/ exact result happened but was inexact set in the FPCR?
4192funimp_ovfl:
4193 btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
4194 beq.w funimp_store # no; return to normal flow
4195 bra.b funimp_exc_ovfl # yes
4196
4197# some exception happened that was actually enabled.
4198# we'll insert this new exception into the FPU and then return.
4199funimp_exc:
4200 subi.l &24,%d0 # fix offset to be 0-8
4201 cmpi.b %d0,&0x6 # is exception INEX?
4202 bne.b funimp_exc_force # no
4203
4204# the enabled exception was inexact. so, if it occurs with an overflow
4205# or underflow that was disabled, then we have to force an overflow or
4206# underflow frame. the eventual overflow or underflow handler will see that
4207# it's actually an inexact and act appropriately. this is the only easy
4208# way to have the EXOP available for the enabled inexact handler when
4209# a disabled overflow or underflow has also happened.
4210 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
4211 bne.b funimp_exc_ovfl # yes
4212 btst &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
4213 bne.b funimp_exc_unfl # yes
4214
4215# force the fsave exception status bits to signal an exception of the
4216# appropriate type. don't forget to "skew" the source operand in case we
4217# "unskewed" the one the hardware initially gave us.
4218funimp_exc_force:
4219 mov.l %d0,-(%sp) # save d0
4220 bsr.l funimp_skew # check for special case
4221 mov.l (%sp)+,%d0 # restore d0
4222 mov.w (tbl_funimp_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
4223 bra.b funimp_gen_exit2 # exit with frestore
4224
4225tbl_funimp_except:
4226 short 0xe002, 0xe006, 0xe004, 0xe005
4227 short 0xe003, 0xe002, 0xe001, 0xe001
4228
4229# insert an overflow frame
4230funimp_exc_ovfl:
4231 bsr.l funimp_skew # check for special case
4232 mov.w &0xe005,2+FP_SRC(%a6)
4233 bra.b funimp_gen_exit2
4234
4235# insert an underflow frame
4236funimp_exc_unfl:
4237 bsr.l funimp_skew # check for special case
4238 mov.w &0xe003,2+FP_SRC(%a6)
4239
4240# this is the general exit point for an enabled exception that will be
4241# restored into the machine for the instruction just emulated.
4242funimp_gen_exit2:
4243 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
4244 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4245 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4246
4247 frestore FP_SRC(%a6) # insert exceptional status
4248
4249 bra.w funimp_gen_exit_cmp
4250
4251############################################################################
4252
4253#
4254# TYPE == 1: FDB<cc>, FS<cc>, FTRAP<cc>
4255#
4256# These instructions were implemented on the '881/2 and '040 in hardware but
4257# are emulated in software on the '060.
4258#
4259funimp_misc:
4260 bfextu %d0{&10:&3},%d1 # extract mode field
4261 cmpi.b %d1,&0x1 # is it an fdb<cc>?
4262 beq.w funimp_fdbcc # yes
4263 cmpi.b %d1,&0x7 # is it an fs<cc>?
4264 bne.w funimp_fscc # yes
4265 bfextu %d0{&13:&3},%d1
4266 cmpi.b %d1,&0x2 # is it an fs<cc>?
4267 blt.w funimp_fscc # yes
4268
4269#########################
4270# ftrap<cc> #
4271# ftrap<cc>.w #<data> #
4272# ftrap<cc>.l #<data> #
4273#########################
4274funimp_ftrapcc:
4275
4276 bsr.l _ftrapcc # FTRAP<cc>()
4277
4278 cmpi.b SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
4279 beq.w funimp_bsun # yes
4280
4281 cmpi.b SPCOND_FLG(%a6),&ftrapcc_flg # should a trap occur?
4282 bne.w funimp_done # no
4283
4284# FP UNIMP FRAME TRAP FRAME
4285# ***************** *****************
4286# ** <EA> ** ** Current PC **
4287# ***************** *****************
4288# * 0x2 * 0x02c * * 0x2 * 0x01c *
4289# ***************** *****************
4290# ** Next PC ** ** Next PC **
4291# ***************** *****************
4292# * SR * * SR *
4293# ***************** *****************
4294# (6 words) (6 words)
4295#
4296# the ftrapcc instruction should take a trap. so, here we must create a
4297# trap stack frame from an unimplemented fp instruction stack frame and
4298# jump to the user supplied entry point for the trap exception
4299funimp_ftrapcc_tp:
4300 mov.l USER_FPIAR(%a6),EXC_EA(%a6) # Address = Current PC
4301 mov.w &0x201c,EXC_VOFF(%a6) # Vector Offset = 0x01c
4302
4303 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
4304 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4305 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4306
4307 unlk %a6
4308 bra.l _real_trap
4309
4310#########################
4311# fdb<cc> Dn,<label> #
4312#########################
4313funimp_fdbcc:
4314
4315 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4316 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4317 bsr.l _imem_read_word # read displacement
4318
4319 tst.l %d1 # did ifetch fail?
4320 bne.w funimp_iacc # yes
4321
4322 ext.l %d0 # sign extend displacement
4323
4324 bsr.l _fdbcc # FDB<cc>()
4325
4326 cmpi.b SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
4327 beq.w funimp_bsun
4328
4329 bra.w funimp_done # branch to finish
4330
4331#################
4332# fs<cc>.b <ea> #
4333#################
4334funimp_fscc:
4335
4336 bsr.l _fscc # FS<cc>()
4337
4338# I am assuming here that an "fs<cc>.b -(An)" or "fs<cc>.b (An)+" instruction
4339# does not need to update "An" before taking a bsun exception.
4340 cmpi.b SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
4341 beq.w funimp_bsun
4342
4343 btst &0x5,EXC_SR(%a6) # yes; is it a user mode exception?
4344 bne.b funimp_fscc_s # no
4345
4346funimp_fscc_u:
4347 mov.l EXC_A7(%a6),%a0 # yes; set new USP
4348 mov.l %a0,%usp
4349 bra.w funimp_done # branch to finish
4350
4351# remember, I'm assuming that post-increment is bogus...(it IS!!!)
4352# so, the least significant WORD of the stacked effective address got
4353# overwritten by the "fs<cc> -(An)". We must shift the stack frame "down"
4354# so that the rte will work correctly without destroying the result.
4355# even though the operation size is byte, the stack ptr is decr by 2.
4356#
4357# remember, also, this instruction may be traced.
4358funimp_fscc_s:
4359 cmpi.b SPCOND_FLG(%a6),&mda7_flg # was a7 modified?
4360 bne.w funimp_done # no
4361
4362 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
4363 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4364 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4365
4366 unlk %a6
4367
4368 btst &0x7,(%sp) # is trace enabled?
4369 bne.b funimp_fscc_s_trace # yes
4370
4371 subq.l &0x2,%sp
4372 mov.l 0x2(%sp),(%sp) # shift SR,hi(PC) "down"
4373 mov.l 0x6(%sp),0x4(%sp) # shift lo(PC),voff "down"
4374 bra.l _fpsp_done
4375
4376funimp_fscc_s_trace:
4377 subq.l &0x2,%sp
4378 mov.l 0x2(%sp),(%sp) # shift SR,hi(PC) "down"
4379 mov.w 0x6(%sp),0x4(%sp) # shift lo(PC)
4380 mov.w &0x2024,0x6(%sp) # fmt/voff = $2024
4381 fmov.l %fpiar,0x8(%sp) # insert "current PC"
4382
4383 bra.l _real_trace
4384
4385#
4386# The ftrap<cc>, fs<cc>, or fdb<cc> is to take an enabled bsun. we must convert
4387# the fp unimplemented instruction exception stack frame into a bsun stack frame,
4388# restore a bsun exception into the machine, and branch to the user
4389# supplied bsun hook.
4390#
4391# FP UNIMP FRAME BSUN FRAME
4392# ***************** *****************
4393# ** <EA> ** * 0x0 * 0x0c0 *
4394# ***************** *****************
4395# * 0x2 * 0x02c * ** Current PC **
4396# ***************** *****************
4397# ** Next PC ** * SR *
4398# ***************** *****************
4399# * SR * (4 words)
4400# *****************
4401# (6 words)
4402#
4403funimp_bsun:
4404 mov.w &0x00c0,2+EXC_EA(%a6) # Fmt = 0x0; Vector Offset = 0x0c0
4405 mov.l USER_FPIAR(%a6),EXC_VOFF(%a6) # PC = Current PC
4406 mov.w EXC_SR(%a6),2+EXC_PC(%a6) # shift SR "up"
4407
4408 mov.w &0xe000,2+FP_SRC(%a6) # bsun exception enabled
4409
4410 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
4411 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4412 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4413
4414 frestore FP_SRC(%a6) # restore bsun exception
4415
4416 unlk %a6
4417
4418 addq.l &0x4,%sp # erase sludge
4419
4420 bra.l _real_bsun # branch to user bsun hook
4421
4422#
4423# all ftrapcc/fscc/fdbcc processing has been completed. unwind the stack frame
4424# and return.
4425#
4426# as usual, we have to check for trace mode being on here. since instructions
4427# modifying the supervisor stack frame don't pass through here, this is a
4428# relatively easy task.
4429#
4430funimp_done:
4431 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
4432 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4433 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4434
4435 unlk %a6
4436
4437 btst &0x7,(%sp) # is trace enabled?
4438 bne.b funimp_trace # yes
4439
4440 bra.l _fpsp_done
4441
4442# FP UNIMP FRAME TRACE FRAME
4443# ***************** *****************
4444# ** <EA> ** ** Current PC **
4445# ***************** *****************
4446# * 0x2 * 0x02c * * 0x2 * 0x024 *
4447# ***************** *****************
4448# ** Next PC ** ** Next PC **
4449# ***************** *****************
4450# * SR * * SR *
4451# ***************** *****************
4452# (6 words) (6 words)
4453#
4454# the fscc instruction should take a trace trap. so, here we must create a
4455# trace stack frame from an unimplemented fp instruction stack frame and
4456# jump to the user supplied entry point for the trace exception
4457funimp_trace:
4458 fmov.l %fpiar,0x8(%sp) # current PC is in fpiar
4459 mov.b &0x24,0x7(%sp) # vector offset = 0x024
4460
4461 bra.l _real_trace
4462
4463################################################################
4464
4465 global tbl_trans
4466 swbeg &0x1c0
4467tbl_trans:
4468 short tbl_trans - tbl_trans # $00-0 fmovecr all
4469 short tbl_trans - tbl_trans # $00-1 fmovecr all
4470 short tbl_trans - tbl_trans # $00-2 fmovecr all
4471 short tbl_trans - tbl_trans # $00-3 fmovecr all
4472 short tbl_trans - tbl_trans # $00-4 fmovecr all
4473 short tbl_trans - tbl_trans # $00-5 fmovecr all
4474 short tbl_trans - tbl_trans # $00-6 fmovecr all
4475 short tbl_trans - tbl_trans # $00-7 fmovecr all
4476
4477 short tbl_trans - tbl_trans # $01-0 fint norm
4478 short tbl_trans - tbl_trans # $01-1 fint zero
4479 short tbl_trans - tbl_trans # $01-2 fint inf
4480 short tbl_trans - tbl_trans # $01-3 fint qnan
4481 short tbl_trans - tbl_trans # $01-5 fint denorm
4482 short tbl_trans - tbl_trans # $01-4 fint snan
4483 short tbl_trans - tbl_trans # $01-6 fint unnorm
4484 short tbl_trans - tbl_trans # $01-7 ERROR
4485
4486 short ssinh - tbl_trans # $02-0 fsinh norm
4487 short src_zero - tbl_trans # $02-1 fsinh zero
4488 short src_inf - tbl_trans # $02-2 fsinh inf
4489 short src_qnan - tbl_trans # $02-3 fsinh qnan
4490 short ssinhd - tbl_trans # $02-5 fsinh denorm
4491 short src_snan - tbl_trans # $02-4 fsinh snan
4492 short tbl_trans - tbl_trans # $02-6 fsinh unnorm
4493 short tbl_trans - tbl_trans # $02-7 ERROR
4494
4495 short tbl_trans - tbl_trans # $03-0 fintrz norm
4496 short tbl_trans - tbl_trans # $03-1 fintrz zero
4497 short tbl_trans - tbl_trans # $03-2 fintrz inf
4498 short tbl_trans - tbl_trans # $03-3 fintrz qnan
4499 short tbl_trans - tbl_trans # $03-5 fintrz denorm
4500 short tbl_trans - tbl_trans # $03-4 fintrz snan
4501 short tbl_trans - tbl_trans # $03-6 fintrz unnorm
4502 short tbl_trans - tbl_trans # $03-7 ERROR
4503
4504 short tbl_trans - tbl_trans # $04-0 fsqrt norm
4505 short tbl_trans - tbl_trans # $04-1 fsqrt zero
4506 short tbl_trans - tbl_trans # $04-2 fsqrt inf
4507 short tbl_trans - tbl_trans # $04-3 fsqrt qnan
4508 short tbl_trans - tbl_trans # $04-5 fsqrt denorm
4509 short tbl_trans - tbl_trans # $04-4 fsqrt snan
4510 short tbl_trans - tbl_trans # $04-6 fsqrt unnorm
4511 short tbl_trans - tbl_trans # $04-7 ERROR
4512
4513 short tbl_trans - tbl_trans # $05-0 ERROR
4514 short tbl_trans - tbl_trans # $05-1 ERROR
4515 short tbl_trans - tbl_trans # $05-2 ERROR
4516 short tbl_trans - tbl_trans # $05-3 ERROR
4517 short tbl_trans - tbl_trans # $05-4 ERROR
4518 short tbl_trans - tbl_trans # $05-5 ERROR
4519 short tbl_trans - tbl_trans # $05-6 ERROR
4520 short tbl_trans - tbl_trans # $05-7 ERROR
4521
4522 short slognp1 - tbl_trans # $06-0 flognp1 norm
4523 short src_zero - tbl_trans # $06-1 flognp1 zero
4524 short sopr_inf - tbl_trans # $06-2 flognp1 inf
4525 short src_qnan - tbl_trans # $06-3 flognp1 qnan
4526 short slognp1d - tbl_trans # $06-5 flognp1 denorm
4527 short src_snan - tbl_trans # $06-4 flognp1 snan
4528 short tbl_trans - tbl_trans # $06-6 flognp1 unnorm
4529 short tbl_trans - tbl_trans # $06-7 ERROR
4530
4531 short tbl_trans - tbl_trans # $07-0 ERROR
4532 short tbl_trans - tbl_trans # $07-1 ERROR
4533 short tbl_trans - tbl_trans # $07-2 ERROR
4534 short tbl_trans - tbl_trans # $07-3 ERROR
4535 short tbl_trans - tbl_trans # $07-4 ERROR
4536 short tbl_trans - tbl_trans # $07-5 ERROR
4537 short tbl_trans - tbl_trans # $07-6 ERROR
4538 short tbl_trans - tbl_trans # $07-7 ERROR
4539
4540 short setoxm1 - tbl_trans # $08-0 fetoxm1 norm
4541 short src_zero - tbl_trans # $08-1 fetoxm1 zero
4542 short setoxm1i - tbl_trans # $08-2 fetoxm1 inf
4543 short src_qnan - tbl_trans # $08-3 fetoxm1 qnan
4544 short setoxm1d - tbl_trans # $08-5 fetoxm1 denorm
4545 short src_snan - tbl_trans # $08-4 fetoxm1 snan
4546 short tbl_trans - tbl_trans # $08-6 fetoxm1 unnorm
4547 short tbl_trans - tbl_trans # $08-7 ERROR
4548
4549 short stanh - tbl_trans # $09-0 ftanh norm
4550 short src_zero - tbl_trans # $09-1 ftanh zero
4551 short src_one - tbl_trans # $09-2 ftanh inf
4552 short src_qnan - tbl_trans # $09-3 ftanh qnan
4553 short stanhd - tbl_trans # $09-5 ftanh denorm
4554 short src_snan - tbl_trans # $09-4 ftanh snan
4555 short tbl_trans - tbl_trans # $09-6 ftanh unnorm
4556 short tbl_trans - tbl_trans # $09-7 ERROR
4557
4558 short satan - tbl_trans # $0a-0 fatan norm
4559 short src_zero - tbl_trans # $0a-1 fatan zero
4560 short spi_2 - tbl_trans # $0a-2 fatan inf
4561 short src_qnan - tbl_trans # $0a-3 fatan qnan
4562 short satand - tbl_trans # $0a-5 fatan denorm
4563 short src_snan - tbl_trans # $0a-4 fatan snan
4564 short tbl_trans - tbl_trans # $0a-6 fatan unnorm
4565 short tbl_trans - tbl_trans # $0a-7 ERROR
4566
4567 short tbl_trans - tbl_trans # $0b-0 ERROR
4568 short tbl_trans - tbl_trans # $0b-1 ERROR
4569 short tbl_trans - tbl_trans # $0b-2 ERROR
4570 short tbl_trans - tbl_trans # $0b-3 ERROR
4571 short tbl_trans - tbl_trans # $0b-4 ERROR
4572 short tbl_trans - tbl_trans # $0b-5 ERROR
4573 short tbl_trans - tbl_trans # $0b-6 ERROR
4574 short tbl_trans - tbl_trans # $0b-7 ERROR
4575
4576 short sasin - tbl_trans # $0c-0 fasin norm
4577 short src_zero - tbl_trans # $0c-1 fasin zero
4578 short t_operr - tbl_trans # $0c-2 fasin inf
4579 short src_qnan - tbl_trans # $0c-3 fasin qnan
4580 short sasind - tbl_trans # $0c-5 fasin denorm
4581 short src_snan - tbl_trans # $0c-4 fasin snan
4582 short tbl_trans - tbl_trans # $0c-6 fasin unnorm
4583 short tbl_trans - tbl_trans # $0c-7 ERROR
4584
4585 short satanh - tbl_trans # $0d-0 fatanh norm
4586 short src_zero - tbl_trans # $0d-1 fatanh zero
4587 short t_operr - tbl_trans # $0d-2 fatanh inf
4588 short src_qnan - tbl_trans # $0d-3 fatanh qnan
4589 short satanhd - tbl_trans # $0d-5 fatanh denorm
4590 short src_snan - tbl_trans # $0d-4 fatanh snan
4591 short tbl_trans - tbl_trans # $0d-6 fatanh unnorm
4592 short tbl_trans - tbl_trans # $0d-7 ERROR
4593
4594 short ssin - tbl_trans # $0e-0 fsin norm
4595 short src_zero - tbl_trans # $0e-1 fsin zero
4596 short t_operr - tbl_trans # $0e-2 fsin inf
4597 short src_qnan - tbl_trans # $0e-3 fsin qnan
4598 short ssind - tbl_trans # $0e-5 fsin denorm
4599 short src_snan - tbl_trans # $0e-4 fsin snan
4600 short tbl_trans - tbl_trans # $0e-6 fsin unnorm
4601 short tbl_trans - tbl_trans # $0e-7 ERROR
4602
4603 short stan - tbl_trans # $0f-0 ftan norm
4604 short src_zero - tbl_trans # $0f-1 ftan zero
4605 short t_operr - tbl_trans # $0f-2 ftan inf
4606 short src_qnan - tbl_trans # $0f-3 ftan qnan
4607 short stand - tbl_trans # $0f-5 ftan denorm
4608 short src_snan - tbl_trans # $0f-4 ftan snan
4609 short tbl_trans - tbl_trans # $0f-6 ftan unnorm
4610 short tbl_trans - tbl_trans # $0f-7 ERROR
4611
4612 short setox - tbl_trans # $10-0 fetox norm
4613 short ld_pone - tbl_trans # $10-1 fetox zero
4614 short szr_inf - tbl_trans # $10-2 fetox inf
4615 short src_qnan - tbl_trans # $10-3 fetox qnan
4616 short setoxd - tbl_trans # $10-5 fetox denorm
4617 short src_snan - tbl_trans # $10-4 fetox snan
4618 short tbl_trans - tbl_trans # $10-6 fetox unnorm
4619 short tbl_trans - tbl_trans # $10-7 ERROR
4620
4621 short stwotox - tbl_trans # $11-0 ftwotox norm
4622 short ld_pone - tbl_trans # $11-1 ftwotox zero
4623 short szr_inf - tbl_trans # $11-2 ftwotox inf
4624 short src_qnan - tbl_trans # $11-3 ftwotox qnan
4625 short stwotoxd - tbl_trans # $11-5 ftwotox denorm
4626 short src_snan - tbl_trans # $11-4 ftwotox snan
4627 short tbl_trans - tbl_trans # $11-6 ftwotox unnorm
4628 short tbl_trans - tbl_trans # $11-7 ERROR
4629
4630 short stentox - tbl_trans # $12-0 ftentox norm
4631 short ld_pone - tbl_trans # $12-1 ftentox zero
4632 short szr_inf - tbl_trans # $12-2 ftentox inf
4633 short src_qnan - tbl_trans # $12-3 ftentox qnan
4634 short stentoxd - tbl_trans # $12-5 ftentox denorm
4635 short src_snan - tbl_trans # $12-4 ftentox snan
4636 short tbl_trans - tbl_trans # $12-6 ftentox unnorm
4637 short tbl_trans - tbl_trans # $12-7 ERROR
4638
4639 short tbl_trans - tbl_trans # $13-0 ERROR
4640 short tbl_trans - tbl_trans # $13-1 ERROR
4641 short tbl_trans - tbl_trans # $13-2 ERROR
4642 short tbl_trans - tbl_trans # $13-3 ERROR
4643 short tbl_trans - tbl_trans # $13-4 ERROR
4644 short tbl_trans - tbl_trans # $13-5 ERROR
4645 short tbl_trans - tbl_trans # $13-6 ERROR
4646 short tbl_trans - tbl_trans # $13-7 ERROR
4647
4648 short slogn - tbl_trans # $14-0 flogn norm
4649 short t_dz2 - tbl_trans # $14-1 flogn zero
4650 short sopr_inf - tbl_trans # $14-2 flogn inf
4651 short src_qnan - tbl_trans # $14-3 flogn qnan
4652 short slognd - tbl_trans # $14-5 flogn denorm
4653 short src_snan - tbl_trans # $14-4 flogn snan
4654 short tbl_trans - tbl_trans # $14-6 flogn unnorm
4655 short tbl_trans - tbl_trans # $14-7 ERROR
4656
4657 short slog10 - tbl_trans # $15-0 flog10 norm
4658 short t_dz2 - tbl_trans # $15-1 flog10 zero
4659 short sopr_inf - tbl_trans # $15-2 flog10 inf
4660 short src_qnan - tbl_trans # $15-3 flog10 qnan
4661 short slog10d - tbl_trans # $15-5 flog10 denorm
4662 short src_snan - tbl_trans # $15-4 flog10 snan
4663 short tbl_trans - tbl_trans # $15-6 flog10 unnorm
4664 short tbl_trans - tbl_trans # $15-7 ERROR
4665
4666 short slog2 - tbl_trans # $16-0 flog2 norm
4667 short t_dz2 - tbl_trans # $16-1 flog2 zero
4668 short sopr_inf - tbl_trans # $16-2 flog2 inf
4669 short src_qnan - tbl_trans # $16-3 flog2 qnan
4670 short slog2d - tbl_trans # $16-5 flog2 denorm
4671 short src_snan - tbl_trans # $16-4 flog2 snan
4672 short tbl_trans - tbl_trans # $16-6 flog2 unnorm
4673 short tbl_trans - tbl_trans # $16-7 ERROR
4674
4675 short tbl_trans - tbl_trans # $17-0 ERROR
4676 short tbl_trans - tbl_trans # $17-1 ERROR
4677 short tbl_trans - tbl_trans # $17-2 ERROR
4678 short tbl_trans - tbl_trans # $17-3 ERROR
4679 short tbl_trans - tbl_trans # $17-4 ERROR
4680 short tbl_trans - tbl_trans # $17-5 ERROR
4681 short tbl_trans - tbl_trans # $17-6 ERROR
4682 short tbl_trans - tbl_trans # $17-7 ERROR
4683
4684 short tbl_trans - tbl_trans # $18-0 fabs norm
4685 short tbl_trans - tbl_trans # $18-1 fabs zero
4686 short tbl_trans - tbl_trans # $18-2 fabs inf
4687 short tbl_trans - tbl_trans # $18-3 fabs qnan
4688 short tbl_trans - tbl_trans # $18-5 fabs denorm
4689 short tbl_trans - tbl_trans # $18-4 fabs snan
4690 short tbl_trans - tbl_trans # $18-6 fabs unnorm
4691 short tbl_trans - tbl_trans # $18-7 ERROR
4692
4693 short scosh - tbl_trans # $19-0 fcosh norm
4694 short ld_pone - tbl_trans # $19-1 fcosh zero
4695 short ld_pinf - tbl_trans # $19-2 fcosh inf
4696 short src_qnan - tbl_trans # $19-3 fcosh qnan
4697 short scoshd - tbl_trans # $19-5 fcosh denorm
4698 short src_snan - tbl_trans # $19-4 fcosh snan
4699 short tbl_trans - tbl_trans # $19-6 fcosh unnorm
4700 short tbl_trans - tbl_trans # $19-7 ERROR
4701
4702 short tbl_trans - tbl_trans # $1a-0 fneg norm
4703 short tbl_trans - tbl_trans # $1a-1 fneg zero
4704 short tbl_trans - tbl_trans # $1a-2 fneg inf
4705 short tbl_trans - tbl_trans # $1a-3 fneg qnan
4706 short tbl_trans - tbl_trans # $1a-5 fneg denorm
4707 short tbl_trans - tbl_trans # $1a-4 fneg snan
4708 short tbl_trans - tbl_trans # $1a-6 fneg unnorm
4709 short tbl_trans - tbl_trans # $1a-7 ERROR
4710
4711 short tbl_trans - tbl_trans # $1b-0 ERROR
4712 short tbl_trans - tbl_trans # $1b-1 ERROR
4713 short tbl_trans - tbl_trans # $1b-2 ERROR
4714 short tbl_trans - tbl_trans # $1b-3 ERROR
4715 short tbl_trans - tbl_trans # $1b-4 ERROR
4716 short tbl_trans - tbl_trans # $1b-5 ERROR
4717 short tbl_trans - tbl_trans # $1b-6 ERROR
4718 short tbl_trans - tbl_trans # $1b-7 ERROR
4719
4720 short sacos - tbl_trans # $1c-0 facos norm
4721 short ld_ppi2 - tbl_trans # $1c-1 facos zero
4722 short t_operr - tbl_trans # $1c-2 facos inf
4723 short src_qnan - tbl_trans # $1c-3 facos qnan
4724 short sacosd - tbl_trans # $1c-5 facos denorm
4725 short src_snan - tbl_trans # $1c-4 facos snan
4726 short tbl_trans - tbl_trans # $1c-6 facos unnorm
4727 short tbl_trans - tbl_trans # $1c-7 ERROR
4728
4729 short scos - tbl_trans # $1d-0 fcos norm
4730 short ld_pone - tbl_trans # $1d-1 fcos zero
4731 short t_operr - tbl_trans # $1d-2 fcos inf
4732 short src_qnan - tbl_trans # $1d-3 fcos qnan
4733 short scosd - tbl_trans # $1d-5 fcos denorm
4734 short src_snan - tbl_trans # $1d-4 fcos snan
4735 short tbl_trans - tbl_trans # $1d-6 fcos unnorm
4736 short tbl_trans - tbl_trans # $1d-7 ERROR
4737
4738 short sgetexp - tbl_trans # $1e-0 fgetexp norm
4739 short src_zero - tbl_trans # $1e-1 fgetexp zero
4740 short t_operr - tbl_trans # $1e-2 fgetexp inf
4741 short src_qnan - tbl_trans # $1e-3 fgetexp qnan
4742 short sgetexpd - tbl_trans # $1e-5 fgetexp denorm
4743 short src_snan - tbl_trans # $1e-4 fgetexp snan
4744 short tbl_trans - tbl_trans # $1e-6 fgetexp unnorm
4745 short tbl_trans - tbl_trans # $1e-7 ERROR
4746
4747 short sgetman - tbl_trans # $1f-0 fgetman norm
4748 short src_zero - tbl_trans # $1f-1 fgetman zero
4749 short t_operr - tbl_trans # $1f-2 fgetman inf
4750 short src_qnan - tbl_trans # $1f-3 fgetman qnan
4751 short sgetmand - tbl_trans # $1f-5 fgetman denorm
4752 short src_snan - tbl_trans # $1f-4 fgetman snan
4753 short tbl_trans - tbl_trans # $1f-6 fgetman unnorm
4754 short tbl_trans - tbl_trans # $1f-7 ERROR
4755
4756 short tbl_trans - tbl_trans # $20-0 fdiv norm
4757 short tbl_trans - tbl_trans # $20-1 fdiv zero
4758 short tbl_trans - tbl_trans # $20-2 fdiv inf
4759 short tbl_trans - tbl_trans # $20-3 fdiv qnan
4760 short tbl_trans - tbl_trans # $20-5 fdiv denorm
4761 short tbl_trans - tbl_trans # $20-4 fdiv snan
4762 short tbl_trans - tbl_trans # $20-6 fdiv unnorm
4763 short tbl_trans - tbl_trans # $20-7 ERROR
4764
4765 short smod_snorm - tbl_trans # $21-0 fmod norm
4766 short smod_szero - tbl_trans # $21-1 fmod zero
4767 short smod_sinf - tbl_trans # $21-2 fmod inf
4768 short sop_sqnan - tbl_trans # $21-3 fmod qnan
4769 short smod_sdnrm - tbl_trans # $21-5 fmod denorm
4770 short sop_ssnan - tbl_trans # $21-4 fmod snan
4771 short tbl_trans - tbl_trans # $21-6 fmod unnorm
4772 short tbl_trans - tbl_trans # $21-7 ERROR
4773
4774 short tbl_trans - tbl_trans # $22-0 fadd norm
4775 short tbl_trans - tbl_trans # $22-1 fadd zero
4776 short tbl_trans - tbl_trans # $22-2 fadd inf
4777 short tbl_trans - tbl_trans # $22-3 fadd qnan
4778 short tbl_trans - tbl_trans # $22-5 fadd denorm
4779 short tbl_trans - tbl_trans # $22-4 fadd snan
4780 short tbl_trans - tbl_trans # $22-6 fadd unnorm
4781 short tbl_trans - tbl_trans # $22-7 ERROR
4782
4783 short tbl_trans - tbl_trans # $23-0 fmul norm
4784 short tbl_trans - tbl_trans # $23-1 fmul zero
4785 short tbl_trans - tbl_trans # $23-2 fmul inf
4786 short tbl_trans - tbl_trans # $23-3 fmul qnan
4787 short tbl_trans - tbl_trans # $23-5 fmul denorm
4788 short tbl_trans - tbl_trans # $23-4 fmul snan
4789 short tbl_trans - tbl_trans # $23-6 fmul unnorm
4790 short tbl_trans - tbl_trans # $23-7 ERROR
4791
4792 short tbl_trans - tbl_trans # $24-0 fsgldiv norm
4793 short tbl_trans - tbl_trans # $24-1 fsgldiv zero
4794 short tbl_trans - tbl_trans # $24-2 fsgldiv inf
4795 short tbl_trans - tbl_trans # $24-3 fsgldiv qnan
4796 short tbl_trans - tbl_trans # $24-5 fsgldiv denorm
4797 short tbl_trans - tbl_trans # $24-4 fsgldiv snan
4798 short tbl_trans - tbl_trans # $24-6 fsgldiv unnorm
4799 short tbl_trans - tbl_trans # $24-7 ERROR
4800
4801 short srem_snorm - tbl_trans # $25-0 frem norm
4802 short srem_szero - tbl_trans # $25-1 frem zero
4803 short srem_sinf - tbl_trans # $25-2 frem inf
4804 short sop_sqnan - tbl_trans # $25-3 frem qnan
4805 short srem_sdnrm - tbl_trans # $25-5 frem denorm
4806 short sop_ssnan - tbl_trans # $25-4 frem snan
4807 short tbl_trans - tbl_trans # $25-6 frem unnorm
4808 short tbl_trans - tbl_trans # $25-7 ERROR
4809
4810 short sscale_snorm - tbl_trans # $26-0 fscale norm
4811 short sscale_szero - tbl_trans # $26-1 fscale zero
4812 short sscale_sinf - tbl_trans # $26-2 fscale inf
4813 short sop_sqnan - tbl_trans # $26-3 fscale qnan
4814 short sscale_sdnrm - tbl_trans # $26-5 fscale denorm
4815 short sop_ssnan - tbl_trans # $26-4 fscale snan
4816 short tbl_trans - tbl_trans # $26-6 fscale unnorm
4817 short tbl_trans - tbl_trans # $26-7 ERROR
4818
4819 short tbl_trans - tbl_trans # $27-0 fsglmul norm
4820 short tbl_trans - tbl_trans # $27-1 fsglmul zero
4821 short tbl_trans - tbl_trans # $27-2 fsglmul inf
4822 short tbl_trans - tbl_trans # $27-3 fsglmul qnan
4823 short tbl_trans - tbl_trans # $27-5 fsglmul denorm
4824 short tbl_trans - tbl_trans # $27-4 fsglmul snan
4825 short tbl_trans - tbl_trans # $27-6 fsglmul unnorm
4826 short tbl_trans - tbl_trans # $27-7 ERROR
4827
4828 short tbl_trans - tbl_trans # $28-0 fsub norm
4829 short tbl_trans - tbl_trans # $28-1 fsub zero
4830 short tbl_trans - tbl_trans # $28-2 fsub inf
4831 short tbl_trans - tbl_trans # $28-3 fsub qnan
4832 short tbl_trans - tbl_trans # $28-5 fsub denorm
4833 short tbl_trans - tbl_trans # $28-4 fsub snan
4834 short tbl_trans - tbl_trans # $28-6 fsub unnorm
4835 short tbl_trans - tbl_trans # $28-7 ERROR
4836
4837 short tbl_trans - tbl_trans # $29-0 ERROR
4838 short tbl_trans - tbl_trans # $29-1 ERROR
4839 short tbl_trans - tbl_trans # $29-2 ERROR
4840 short tbl_trans - tbl_trans # $29-3 ERROR
4841 short tbl_trans - tbl_trans # $29-4 ERROR
4842 short tbl_trans - tbl_trans # $29-5 ERROR
4843 short tbl_trans - tbl_trans # $29-6 ERROR
4844 short tbl_trans - tbl_trans # $29-7 ERROR
4845
4846 short tbl_trans - tbl_trans # $2a-0 ERROR
4847 short tbl_trans - tbl_trans # $2a-1 ERROR
4848 short tbl_trans - tbl_trans # $2a-2 ERROR
4849 short tbl_trans - tbl_trans # $2a-3 ERROR
4850 short tbl_trans - tbl_trans # $2a-4 ERROR
4851 short tbl_trans - tbl_trans # $2a-5 ERROR
4852 short tbl_trans - tbl_trans # $2a-6 ERROR
4853 short tbl_trans - tbl_trans # $2a-7 ERROR
4854
4855 short tbl_trans - tbl_trans # $2b-0 ERROR
4856 short tbl_trans - tbl_trans # $2b-1 ERROR
4857 short tbl_trans - tbl_trans # $2b-2 ERROR
4858 short tbl_trans - tbl_trans # $2b-3 ERROR
4859 short tbl_trans - tbl_trans # $2b-4 ERROR
4860 short tbl_trans - tbl_trans # $2b-5 ERROR
4861 short tbl_trans - tbl_trans # $2b-6 ERROR
4862 short tbl_trans - tbl_trans # $2b-7 ERROR
4863
4864 short tbl_trans - tbl_trans # $2c-0 ERROR
4865 short tbl_trans - tbl_trans # $2c-1 ERROR
4866 short tbl_trans - tbl_trans # $2c-2 ERROR
4867 short tbl_trans - tbl_trans # $2c-3 ERROR
4868 short tbl_trans - tbl_trans # $2c-4 ERROR
4869 short tbl_trans - tbl_trans # $2c-5 ERROR
4870 short tbl_trans - tbl_trans # $2c-6 ERROR
4871 short tbl_trans - tbl_trans # $2c-7 ERROR
4872
4873 short tbl_trans - tbl_trans # $2d-0 ERROR
4874 short tbl_trans - tbl_trans # $2d-1 ERROR
4875 short tbl_trans - tbl_trans # $2d-2 ERROR
4876 short tbl_trans - tbl_trans # $2d-3 ERROR
4877 short tbl_trans - tbl_trans # $2d-4 ERROR
4878 short tbl_trans - tbl_trans # $2d-5 ERROR
4879 short tbl_trans - tbl_trans # $2d-6 ERROR
4880 short tbl_trans - tbl_trans # $2d-7 ERROR
4881
4882 short tbl_trans - tbl_trans # $2e-0 ERROR
4883 short tbl_trans - tbl_trans # $2e-1 ERROR
4884 short tbl_trans - tbl_trans # $2e-2 ERROR
4885 short tbl_trans - tbl_trans # $2e-3 ERROR
4886 short tbl_trans - tbl_trans # $2e-4 ERROR
4887 short tbl_trans - tbl_trans # $2e-5 ERROR
4888 short tbl_trans - tbl_trans # $2e-6 ERROR
4889 short tbl_trans - tbl_trans # $2e-7 ERROR
4890
4891 short tbl_trans - tbl_trans # $2f-0 ERROR
4892 short tbl_trans - tbl_trans # $2f-1 ERROR
4893 short tbl_trans - tbl_trans # $2f-2 ERROR
4894 short tbl_trans - tbl_trans # $2f-3 ERROR
4895 short tbl_trans - tbl_trans # $2f-4 ERROR
4896 short tbl_trans - tbl_trans # $2f-5 ERROR
4897 short tbl_trans - tbl_trans # $2f-6 ERROR
4898 short tbl_trans - tbl_trans # $2f-7 ERROR
4899
4900 short ssincos - tbl_trans # $30-0 fsincos norm
4901 short ssincosz - tbl_trans # $30-1 fsincos zero
4902 short ssincosi - tbl_trans # $30-2 fsincos inf
4903 short ssincosqnan - tbl_trans # $30-3 fsincos qnan
4904 short ssincosd - tbl_trans # $30-5 fsincos denorm
4905 short ssincossnan - tbl_trans # $30-4 fsincos snan
4906 short tbl_trans - tbl_trans # $30-6 fsincos unnorm
4907 short tbl_trans - tbl_trans # $30-7 ERROR
4908
4909 short ssincos - tbl_trans # $31-0 fsincos norm
4910 short ssincosz - tbl_trans # $31-1 fsincos zero
4911 short ssincosi - tbl_trans # $31-2 fsincos inf
4912 short ssincosqnan - tbl_trans # $31-3 fsincos qnan
4913 short ssincosd - tbl_trans # $31-5 fsincos denorm
4914 short ssincossnan - tbl_trans # $31-4 fsincos snan
4915 short tbl_trans - tbl_trans # $31-6 fsincos unnorm
4916 short tbl_trans - tbl_trans # $31-7 ERROR
4917
4918 short ssincos - tbl_trans # $32-0 fsincos norm
4919 short ssincosz - tbl_trans # $32-1 fsincos zero
4920 short ssincosi - tbl_trans # $32-2 fsincos inf
4921 short ssincosqnan - tbl_trans # $32-3 fsincos qnan
4922 short ssincosd - tbl_trans # $32-5 fsincos denorm
4923 short ssincossnan - tbl_trans # $32-4 fsincos snan
4924 short tbl_trans - tbl_trans # $32-6 fsincos unnorm
4925 short tbl_trans - tbl_trans # $32-7 ERROR
4926
4927 short ssincos - tbl_trans # $33-0 fsincos norm
4928 short ssincosz - tbl_trans # $33-1 fsincos zero
4929 short ssincosi - tbl_trans # $33-2 fsincos inf
4930 short ssincosqnan - tbl_trans # $33-3 fsincos qnan
4931 short ssincosd - tbl_trans # $33-5 fsincos denorm
4932 short ssincossnan - tbl_trans # $33-4 fsincos snan
4933 short tbl_trans - tbl_trans # $33-6 fsincos unnorm
4934 short tbl_trans - tbl_trans # $33-7 ERROR
4935
4936 short ssincos - tbl_trans # $34-0 fsincos norm
4937 short ssincosz - tbl_trans # $34-1 fsincos zero
4938 short ssincosi - tbl_trans # $34-2 fsincos inf
4939 short ssincosqnan - tbl_trans # $34-3 fsincos qnan
4940 short ssincosd - tbl_trans # $34-5 fsincos denorm
4941 short ssincossnan - tbl_trans # $34-4 fsincos snan
4942 short tbl_trans - tbl_trans # $34-6 fsincos unnorm
4943 short tbl_trans - tbl_trans # $34-7 ERROR
4944
4945 short ssincos - tbl_trans # $35-0 fsincos norm
4946 short ssincosz - tbl_trans # $35-1 fsincos zero
4947 short ssincosi - tbl_trans # $35-2 fsincos inf
4948 short ssincosqnan - tbl_trans # $35-3 fsincos qnan
4949 short ssincosd - tbl_trans # $35-5 fsincos denorm
4950 short ssincossnan - tbl_trans # $35-4 fsincos snan
4951 short tbl_trans - tbl_trans # $35-6 fsincos unnorm
4952 short tbl_trans - tbl_trans # $35-7 ERROR
4953
4954 short ssincos - tbl_trans # $36-0 fsincos norm
4955 short ssincosz - tbl_trans # $36-1 fsincos zero
4956 short ssincosi - tbl_trans # $36-2 fsincos inf
4957 short ssincosqnan - tbl_trans # $36-3 fsincos qnan
4958 short ssincosd - tbl_trans # $36-5 fsincos denorm
4959 short ssincossnan - tbl_trans # $36-4 fsincos snan
4960 short tbl_trans - tbl_trans # $36-6 fsincos unnorm
4961 short tbl_trans - tbl_trans # $36-7 ERROR
4962
4963 short ssincos - tbl_trans # $37-0 fsincos norm
4964 short ssincosz - tbl_trans # $37-1 fsincos zero
4965 short ssincosi - tbl_trans # $37-2 fsincos inf
4966 short ssincosqnan - tbl_trans # $37-3 fsincos qnan
4967 short ssincosd - tbl_trans # $37-5 fsincos denorm
4968 short ssincossnan - tbl_trans # $37-4 fsincos snan
4969 short tbl_trans - tbl_trans # $37-6 fsincos unnorm
4970 short tbl_trans - tbl_trans # $37-7 ERROR
4971
4972##########
4973
4974# the instruction fetch access for the displacement word for the
4975# fdbcc emulation failed. here, we create an access error frame
4976# from the current frame and branch to _real_access().
4977funimp_iacc:
4978 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4979 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4980 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
4981
4982 mov.l USER_FPIAR(%a6),EXC_PC(%a6) # store current PC
4983
4984 unlk %a6
4985
4986 mov.l (%sp),-(%sp) # store SR,hi(PC)
4987 mov.w 0x8(%sp),0x4(%sp) # store lo(PC)
4988 mov.w &0x4008,0x6(%sp) # store voff
4989 mov.l 0x2(%sp),0x8(%sp) # store EA
4990 mov.l &0x09428001,0xc(%sp) # store FSLW
4991
4992 btst &0x5,(%sp) # user or supervisor mode?
4993 beq.b funimp_iacc_end # user
4994 bset &0x2,0xd(%sp) # set supervisor TM bit
4995
4996funimp_iacc_end:
4997 bra.l _real_access
4998
4999#########################################################################
5000# ssin(): computes the sine of a normalized input #
5001# ssind(): computes the sine of a denormalized input #
5002# scos(): computes the cosine of a normalized input #
5003# scosd(): computes the cosine of a denormalized input #
5004# ssincos(): computes the sine and cosine of a normalized input #
5005# ssincosd(): computes the sine and cosine of a denormalized input #
5006# #
5007# INPUT *************************************************************** #
5008# a0 = pointer to extended precision input #
5009# d0 = round precision,mode #
5010# #
5011# OUTPUT ************************************************************** #
5012# fp0 = sin(X) or cos(X) #
5013# #
5014# For ssincos(X): #
5015# fp0 = sin(X) #
5016# fp1 = cos(X) #
5017# #
5018# ACCURACY and MONOTONICITY ******************************************* #
5019# The returned result is within 1 ulp in 64 significant bit, i.e. #
5020# within 0.5001 ulp to 53 bits if the result is subsequently #
5021# rounded to double precision. The result is provably monotonic #
5022# in double precision. #
5023# #
5024# ALGORITHM *********************************************************** #
5025# #
5026# SIN and COS: #
5027# 1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1. #
5028# #
5029# 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7. #
5030# #
5031# 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
5032# k = N mod 4, so in particular, k = 0,1,2,or 3. #
5033# Overwrite k by k := k + AdjN. #
5034# #
5035# 4. If k is even, go to 6. #
5036# #
5037# 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. #
5038# Return sgn*cos(r) where cos(r) is approximated by an #
5039# even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)), #
5040# s = r*r. #
5041# Exit. #
5042# #
5043# 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r) #
5044# where sin(r) is approximated by an odd polynomial in r #
5045# r + r*s*(A1+s*(A2+ ... + s*A7)), s = r*r. #
5046# Exit. #
5047# #
5048# 7. If |X| > 1, go to 9. #
5049# #
5050# 8. (|X|<2**(-40)) If SIN is invoked, return X; #
5051# otherwise return 1. #
5052# #
5053# 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
5054# go back to 3. #
5055# #
5056# SINCOS: #
5057# 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
5058# #
5059# 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
5060# k = N mod 4, so in particular, k = 0,1,2,or 3. #
5061# #
5062# 3. If k is even, go to 5. #
5063# #
5064# 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie. #
5065# j1 exclusive or with the l.s.b. of k. #
5066# sgn1 := (-1)**j1, sgn2 := (-1)**j2. #
5067# SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where #
5068# sin(r) and cos(r) are computed as odd and even #
5069# polynomials in r, respectively. Exit #
5070# #
5071# 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1. #
5072# SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where #
5073# sin(r) and cos(r) are computed as odd and even #
5074# polynomials in r, respectively. Exit #
5075# #
5076# 6. If |X| > 1, go to 8. #
5077# #
5078# 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit. #
5079# #
5080# 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
5081# go back to 2. #
5082# #
5083#########################################################################
5084
5085SINA7: long 0xBD6AAA77,0xCCC994F5
5086SINA6: long 0x3DE61209,0x7AAE8DA1
5087SINA5: long 0xBE5AE645,0x2A118AE4
5088SINA4: long 0x3EC71DE3,0xA5341531
5089SINA3: long 0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
5090SINA2: long 0x3FF80000,0x88888888,0x888859AF,0x00000000
5091SINA1: long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
5092
5093COSB8: long 0x3D2AC4D0,0xD6011EE3
5094COSB7: long 0xBDA9396F,0x9F45AC19
5095COSB6: long 0x3E21EED9,0x0612C972
5096COSB5: long 0xBE927E4F,0xB79D9FCF
5097COSB4: long 0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
5098COSB3: long 0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
5099COSB2: long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
5100COSB1: long 0xBF000000
5101
5102 set INARG,FP_SCR0
5103
5104 set X,FP_SCR0
5105# set XDCARE,X+2
5106 set XFRAC,X+4
5107
5108 set RPRIME,FP_SCR0
5109 set SPRIME,FP_SCR1
5110
5111 set POSNEG1,L_SCR1
5112 set TWOTO63,L_SCR1
5113
5114 set ENDFLAG,L_SCR2
5115 set INT,L_SCR2
5116
5117 set ADJN,L_SCR3
5118
5119############################################
5120 global ssin
5121ssin:
5122 mov.l &0,ADJN(%a6) # yes; SET ADJN TO 0
5123 bra.b SINBGN
5124
5125############################################
5126 global scos
5127scos:
5128 mov.l &1,ADJN(%a6) # yes; SET ADJN TO 1
5129
5130############################################
5131SINBGN:
5132#--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
5133
5134 fmov.x (%a0),%fp0 # LOAD INPUT
5135 fmov.x %fp0,X(%a6) # save input at X
5136
5137# "COMPACTIFY" X
5138 mov.l (%a0),%d1 # put exp in hi word
5139 mov.w 4(%a0),%d1 # fetch hi(man)
5140 and.l &0x7FFFFFFF,%d1 # strip sign
5141
5142 cmpi.l %d1,&0x3FD78000 # is |X| >= 2**(-40)?
5143 bge.b SOK1 # no
5144 bra.w SINSM # yes; input is very small
5145
5146SOK1:
5147 cmp.l %d1,&0x4004BC7E # is |X| < 15 PI?
5148 blt.b SINMAIN # no
5149 bra.w SREDUCEX # yes; input is very large
5150
5151#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5152#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5153SINMAIN:
5154 fmov.x %fp0,%fp1
5155 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5156
5157 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5158
5159 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
5160
5161 mov.l INT(%a6),%d1 # make a copy of N
5162 asl.l &4,%d1 # N *= 16
5163 add.l %d1,%a1 # tbl_addr = a1 + (N*16)
5164
5165# A1 IS THE ADDRESS OF N*PIBY2
5166# ...WHICH IS IN TWO PIECES Y1 & Y2
5167 fsub.x (%a1)+,%fp0 # X-Y1
5168 fsub.s (%a1),%fp0 # fp0 = R = (X-Y1)-Y2
5169
5170SINCONT:
5171#--continuation from REDUCEX
5172
5173#--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
5174 mov.l INT(%a6),%d1
5175 add.l ADJN(%a6),%d1 # SEE IF D0 IS ODD OR EVEN
5176 ror.l &1,%d1 # D0 WAS ODD IFF D0 IS NEGATIVE
5177 cmp.l %d1,&0
5178 blt.w COSPOLY
5179
5180#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5181#--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
5182#--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
5183#--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
5184#--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
5185#--WHERE T=S*S.
5186#--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
5187#--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
5188SINPOLY:
5189 fmovm.x &0x0c,-(%sp) # save fp2/fp3
5190
5191 fmov.x %fp0,X(%a6) # X IS R
5192 fmul.x %fp0,%fp0 # FP0 IS S
5193
5194 fmov.d SINA7(%pc),%fp3
5195 fmov.d SINA6(%pc),%fp2
5196
5197 fmov.x %fp0,%fp1
5198 fmul.x %fp1,%fp1 # FP1 IS T
5199
5200 ror.l &1,%d1
5201 and.l &0x80000000,%d1
5202# ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5203 eor.l %d1,X(%a6) # X IS NOW R'= SGN*R
5204
5205 fmul.x %fp1,%fp3 # TA7
5206 fmul.x %fp1,%fp2 # TA6
5207
5208 fadd.d SINA5(%pc),%fp3 # A5+TA7
5209 fadd.d SINA4(%pc),%fp2 # A4+TA6
5210
5211 fmul.x %fp1,%fp3 # T(A5+TA7)
5212 fmul.x %fp1,%fp2 # T(A4+TA6)
5213
5214 fadd.d SINA3(%pc),%fp3 # A3+T(A5+TA7)
5215 fadd.x SINA2(%pc),%fp2 # A2+T(A4+TA6)
5216
5217 fmul.x %fp3,%fp1 # T(A3+T(A5+TA7))
5218
5219 fmul.x %fp0,%fp2 # S(A2+T(A4+TA6))
5220 fadd.x SINA1(%pc),%fp1 # A1+T(A3+T(A5+TA7))
5221 fmul.x X(%a6),%fp0 # R'*S
5222
5223 fadd.x %fp2,%fp1 # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
5224
5225 fmul.x %fp1,%fp0 # SIN(R')-R'
5226
5227 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
5228
5229 fmov.l %d0,%fpcr # restore users round mode,prec
5230 fadd.x X(%a6),%fp0 # last inst - possible exception set
5231 bra t_inx2
5232
5233#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5234#--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY
5235#--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
5236#--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
5237#--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
5238#--WHERE T=S*S.
5239#--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
5240#--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
5241#--AND IS THEREFORE STORED AS SINGLE PRECISION.
5242COSPOLY:
5243 fmovm.x &0x0c,-(%sp) # save fp2/fp3
5244
5245 fmul.x %fp0,%fp0 # FP0 IS S
5246
5247 fmov.d COSB8(%pc),%fp2
5248 fmov.d COSB7(%pc),%fp3
5249
5250 fmov.x %fp0,%fp1
5251 fmul.x %fp1,%fp1 # FP1 IS T
5252
5253 fmov.x %fp0,X(%a6) # X IS S
5254 ror.l &1,%d1
5255 and.l &0x80000000,%d1
5256# ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5257
5258 fmul.x %fp1,%fp2 # TB8
5259
5260 eor.l %d1,X(%a6) # X IS NOW S'= SGN*S
5261 and.l &0x80000000,%d1
5262
5263 fmul.x %fp1,%fp3 # TB7
5264
5265 or.l &0x3F800000,%d1 # D0 IS SGN IN SINGLE
5266 mov.l %d1,POSNEG1(%a6)
5267
5268 fadd.d COSB6(%pc),%fp2 # B6+TB8
5269 fadd.d COSB5(%pc),%fp3 # B5+TB7
5270
5271 fmul.x %fp1,%fp2 # T(B6+TB8)
5272 fmul.x %fp1,%fp3 # T(B5+TB7)
5273
5274 fadd.d COSB4(%pc),%fp2 # B4+T(B6+TB8)
5275 fadd.x COSB3(%pc),%fp3 # B3+T(B5+TB7)
5276
5277 fmul.x %fp1,%fp2 # T(B4+T(B6+TB8))
5278 fmul.x %fp3,%fp1 # T(B3+T(B5+TB7))
5279
5280 fadd.x COSB2(%pc),%fp2 # B2+T(B4+T(B6+TB8))
5281 fadd.s COSB1(%pc),%fp1 # B1+T(B3+T(B5+TB7))
5282
5283 fmul.x %fp2,%fp0 # S(B2+T(B4+T(B6+TB8)))
5284
5285 fadd.x %fp1,%fp0
5286
5287 fmul.x X(%a6),%fp0
5288
5289 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
5290
5291 fmov.l %d0,%fpcr # restore users round mode,prec
5292 fadd.s POSNEG1(%a6),%fp0 # last inst - possible exception set
5293 bra t_inx2
5294
5295##############################################
5296
5297# SINe: Big OR Small?
5298#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5299#--IF |X| < 2**(-40), RETURN X OR 1.
5300SINBORS:
5301 cmp.l %d1,&0x3FFF8000
5302 bgt.l SREDUCEX
5303
5304SINSM:
5305 mov.l ADJN(%a6),%d1
5306 cmp.l %d1,&0
5307 bgt.b COSTINY
5308
5309# here, the operation may underflow iff the precision is sgl or dbl.
5310# extended denorms are handled through another entry point.
5311SINTINY:
5312# mov.w &0x0000,XDCARE(%a6) # JUST IN CASE
5313
5314 fmov.l %d0,%fpcr # restore users round mode,prec
5315 mov.b &FMOV_OP,%d1 # last inst is MOVE
5316 fmov.x X(%a6),%fp0 # last inst - possible exception set
5317 bra t_catch
5318
5319COSTINY:
5320 fmov.s &0x3F800000,%fp0 # fp0 = 1.0
5321 fmov.l %d0,%fpcr # restore users round mode,prec
5322 fadd.s &0x80800000,%fp0 # last inst - possible exception set
5323 bra t_pinx2
5324
5325################################################
5326 global ssind
5327#--SIN(X) = X FOR DENORMALIZED X
5328ssind:
5329 bra t_extdnrm
5330
5331############################################
5332 global scosd
5333#--COS(X) = 1 FOR DENORMALIZED X
5334scosd:
5335 fmov.s &0x3F800000,%fp0 # fp0 = 1.0
5336 bra t_pinx2
5337
5338##################################################
5339
5340 global ssincos
5341ssincos:
5342#--SET ADJN TO 4
5343 mov.l &4,ADJN(%a6)
5344
5345 fmov.x (%a0),%fp0 # LOAD INPUT
5346 fmov.x %fp0,X(%a6)
5347
5348 mov.l (%a0),%d1
5349 mov.w 4(%a0),%d1
5350 and.l &0x7FFFFFFF,%d1 # COMPACTIFY X
5351
5352 cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
5353 bge.b SCOK1
5354 bra.w SCSM
5355
5356SCOK1:
5357 cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
5358 blt.b SCMAIN
5359 bra.w SREDUCEX
5360
5361
5362#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5363#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5364SCMAIN:
5365 fmov.x %fp0,%fp1
5366
5367 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5368
5369 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5370
5371 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
5372
5373 mov.l INT(%a6),%d1
5374 asl.l &4,%d1
5375 add.l %d1,%a1 # ADDRESS OF N*PIBY2, IN Y1, Y2
5376
5377 fsub.x (%a1)+,%fp0 # X-Y1
5378 fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
5379
5380SCCONT:
5381#--continuation point from REDUCEX
5382
5383 mov.l INT(%a6),%d1
5384 ror.l &1,%d1
5385 cmp.l %d1,&0 # D0 < 0 IFF N IS ODD
5386 bge.w NEVEN
5387
5388SNODD:
5389#--REGISTERS SAVED SO FAR: D0, A0, FP2.
5390 fmovm.x &0x04,-(%sp) # save fp2
5391
5392 fmov.x %fp0,RPRIME(%a6)
5393 fmul.x %fp0,%fp0 # FP0 IS S = R*R
5394 fmov.d SINA7(%pc),%fp1 # A7
5395 fmov.d COSB8(%pc),%fp2 # B8
5396 fmul.x %fp0,%fp1 # SA7
5397 fmul.x %fp0,%fp2 # SB8
5398
5399 mov.l %d2,-(%sp)
5400 mov.l %d1,%d2
5401 ror.l &1,%d2
5402 and.l &0x80000000,%d2
5403 eor.l %d1,%d2
5404 and.l &0x80000000,%d2
5405
5406 fadd.d SINA6(%pc),%fp1 # A6+SA7
5407 fadd.d COSB7(%pc),%fp2 # B7+SB8
5408
5409 fmul.x %fp0,%fp1 # S(A6+SA7)
5410 eor.l %d2,RPRIME(%a6)
5411 mov.l (%sp)+,%d2
5412 fmul.x %fp0,%fp2 # S(B7+SB8)
5413 ror.l &1,%d1
5414 and.l &0x80000000,%d1
5415 mov.l &0x3F800000,POSNEG1(%a6)
5416 eor.l %d1,POSNEG1(%a6)
5417
5418 fadd.d SINA5(%pc),%fp1 # A5+S(A6+SA7)
5419 fadd.d COSB6(%pc),%fp2 # B6+S(B7+SB8)
5420
5421 fmul.x %fp0,%fp1 # S(A5+S(A6+SA7))
5422 fmul.x %fp0,%fp2 # S(B6+S(B7+SB8))
5423 fmov.x %fp0,SPRIME(%a6)
5424
5425 fadd.d SINA4(%pc),%fp1 # A4+S(A5+S(A6+SA7))
5426 eor.l %d1,SPRIME(%a6)
5427 fadd.d COSB5(%pc),%fp2 # B5+S(B6+S(B7+SB8))
5428
5429 fmul.x %fp0,%fp1 # S(A4+...)
5430 fmul.x %fp0,%fp2 # S(B5+...)
5431
5432 fadd.d SINA3(%pc),%fp1 # A3+S(A4+...)
5433 fadd.d COSB4(%pc),%fp2 # B4+S(B5+...)
5434
5435 fmul.x %fp0,%fp1 # S(A3+...)
5436 fmul.x %fp0,%fp2 # S(B4+...)
5437
5438 fadd.x SINA2(%pc),%fp1 # A2+S(A3+...)
5439 fadd.x COSB3(%pc),%fp2 # B3+S(B4+...)
5440
5441 fmul.x %fp0,%fp1 # S(A2+...)
5442 fmul.x %fp0,%fp2 # S(B3+...)
5443
5444 fadd.x SINA1(%pc),%fp1 # A1+S(A2+...)
5445 fadd.x COSB2(%pc),%fp2 # B2+S(B3+...)
5446
5447 fmul.x %fp0,%fp1 # S(A1+...)
5448 fmul.x %fp2,%fp0 # S(B2+...)
5449
5450 fmul.x RPRIME(%a6),%fp1 # R'S(A1+...)
5451 fadd.s COSB1(%pc),%fp0 # B1+S(B2...)
5452 fmul.x SPRIME(%a6),%fp0 # S'(B1+S(B2+...))
5453
5454 fmovm.x (%sp)+,&0x20 # restore fp2
5455
5456 fmov.l %d0,%fpcr
5457 fadd.x RPRIME(%a6),%fp1 # COS(X)
5458 bsr sto_cos # store cosine result
5459 fadd.s POSNEG1(%a6),%fp0 # SIN(X)
5460 bra t_inx2
5461
5462NEVEN:
5463#--REGISTERS SAVED SO FAR: FP2.
5464 fmovm.x &0x04,-(%sp) # save fp2
5465
5466 fmov.x %fp0,RPRIME(%a6)
5467 fmul.x %fp0,%fp0 # FP0 IS S = R*R
5468
5469 fmov.d COSB8(%pc),%fp1 # B8
5470 fmov.d SINA7(%pc),%fp2 # A7
5471
5472 fmul.x %fp0,%fp1 # SB8
5473 fmov.x %fp0,SPRIME(%a6)
5474 fmul.x %fp0,%fp2 # SA7
5475
5476 ror.l &1,%d1
5477 and.l &0x80000000,%d1
5478
5479 fadd.d COSB7(%pc),%fp1 # B7+SB8
5480 fadd.d SINA6(%pc),%fp2 # A6+SA7
5481
5482 eor.l %d1,RPRIME(%a6)
5483 eor.l %d1,SPRIME(%a6)
5484
5485 fmul.x %fp0,%fp1 # S(B7+SB8)
5486
5487 or.l &0x3F800000,%d1
5488 mov.l %d1,POSNEG1(%a6)
5489
5490 fmul.x %fp0,%fp2 # S(A6+SA7)
5491
5492 fadd.d COSB6(%pc),%fp1 # B6+S(B7+SB8)
5493 fadd.d SINA5(%pc),%fp2 # A5+S(A6+SA7)
5494
5495 fmul.x %fp0,%fp1 # S(B6+S(B7+SB8))
5496 fmul.x %fp0,%fp2 # S(A5+S(A6+SA7))
5497
5498 fadd.d COSB5(%pc),%fp1 # B5+S(B6+S(B7+SB8))
5499 fadd.d SINA4(%pc),%fp2 # A4+S(A5+S(A6+SA7))
5500
5501 fmul.x %fp0,%fp1 # S(B5+...)
5502 fmul.x %fp0,%fp2 # S(A4+...)
5503
5504 fadd.d COSB4(%pc),%fp1 # B4+S(B5+...)
5505 fadd.d SINA3(%pc),%fp2 # A3+S(A4+...)
5506
5507 fmul.x %fp0,%fp1 # S(B4+...)
5508 fmul.x %fp0,%fp2 # S(A3+...)
5509
5510 fadd.x COSB3(%pc),%fp1 # B3+S(B4+...)
5511 fadd.x SINA2(%pc),%fp2 # A2+S(A3+...)
5512
5513 fmul.x %fp0,%fp1 # S(B3+...)
5514 fmul.x %fp0,%fp2 # S(A2+...)
5515
5516 fadd.x COSB2(%pc),%fp1 # B2+S(B3+...)
5517 fadd.x SINA1(%pc),%fp2 # A1+S(A2+...)
5518
5519 fmul.x %fp0,%fp1 # S(B2+...)
5520 fmul.x %fp2,%fp0 # s(a1+...)
5521
5522
5523 fadd.s COSB1(%pc),%fp1 # B1+S(B2...)
5524 fmul.x RPRIME(%a6),%fp0 # R'S(A1+...)
5525 fmul.x SPRIME(%a6),%fp1 # S'(B1+S(B2+...))
5526
5527 fmovm.x (%sp)+,&0x20 # restore fp2
5528
5529 fmov.l %d0,%fpcr
5530 fadd.s POSNEG1(%a6),%fp1 # COS(X)
5531 bsr sto_cos # store cosine result
5532 fadd.x RPRIME(%a6),%fp0 # SIN(X)
5533 bra t_inx2
5534
5535################################################
5536
5537SCBORS:
5538 cmp.l %d1,&0x3FFF8000
5539 bgt.w SREDUCEX
5540
5541################################################
5542
5543SCSM:
5544# mov.w &0x0000,XDCARE(%a6)
5545 fmov.s &0x3F800000,%fp1
5546
5547 fmov.l %d0,%fpcr
5548 fsub.s &0x00800000,%fp1
5549 bsr sto_cos # store cosine result
5550 fmov.l %fpcr,%d0 # d0 must have fpcr,too
5551 mov.b &FMOV_OP,%d1 # last inst is MOVE
5552 fmov.x X(%a6),%fp0
5553 bra t_catch
5554
5555##############################################
5556
5557 global ssincosd
5558#--SIN AND COS OF X FOR DENORMALIZED X
5559ssincosd:
5560 mov.l %d0,-(%sp) # save d0
5561 fmov.s &0x3F800000,%fp1
5562 bsr sto_cos # store cosine result
5563 mov.l (%sp)+,%d0 # restore d0
5564 bra t_extdnrm
5565
5566############################################
5567
5568#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5569#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5570#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5571SREDUCEX:
5572 fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
5573 mov.l %d2,-(%sp) # save d2
5574 fmov.s &0x00000000,%fp1 # fp1 = 0
5575
5576#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5577#--there is a danger of unwanted overflow in first LOOP iteration. In this
5578#--case, reduce argument by one remainder step to make subsequent reduction
5579#--safe.
5580 cmp.l %d1,&0x7ffeffff # is arg dangerously large?
5581 bne.b SLOOP # no
5582
5583# yes; create 2**16383*PI/2
5584 mov.w &0x7ffe,FP_SCR0_EX(%a6)
5585 mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
5586 clr.l FP_SCR0_LO(%a6)
5587
5588# create low half of 2**16383*PI/2 at FP_SCR1
5589 mov.w &0x7fdc,FP_SCR1_EX(%a6)
5590 mov.l &0x85a308d3,FP_SCR1_HI(%a6)
5591 clr.l FP_SCR1_LO(%a6)
5592
5593 ftest.x %fp0 # test sign of argument
5594 fblt.w sred_neg
5595
5596 or.b &0x80,FP_SCR0_EX(%a6) # positive arg
5597 or.b &0x80,FP_SCR1_EX(%a6)
5598sred_neg:
5599 fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
5600 fmov.x %fp0,%fp1 # save high result in fp1
5601 fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
5602 fsub.x %fp0,%fp1 # determine low component of result
5603 fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
5604
5605#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5606#--integer quotient will be stored in N
5607#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5608SLOOP:
5609 fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
5610 mov.w INARG(%a6),%d1
5611 mov.l %d1,%a1 # save a copy of D0
5612 and.l &0x00007FFF,%d1
5613 sub.l &0x00003FFF,%d1 # d0 = K
5614 cmp.l %d1,&28
5615 ble.b SLASTLOOP
5616SCONTLOOP:
5617 sub.l &27,%d1 # d0 = L := K-27
5618 mov.b &0,ENDFLAG(%a6)
5619 bra.b SWORK
5620SLASTLOOP:
5621 clr.l %d1 # d0 = L := 0
5622 mov.b &1,ENDFLAG(%a6)
5623
5624SWORK:
5625#--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
5626#--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5627
5628#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5629#--2**L * (PIby2_1), 2**L * (PIby2_2)
5630
5631 mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
5632 sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
5633
5634 mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
5635 mov.l &0x4E44152A,FP_SCR0_LO(%a6)
5636 mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
5637
5638 fmov.x %fp0,%fp2
5639 fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
5640
5641#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5642#--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
5643#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5644#--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
5645#--US THE DESIRED VALUE IN FLOATING POINT.
5646 mov.l %a1,%d2
5647 swap %d2
5648 and.l &0x80000000,%d2
5649 or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
5650 mov.l %d2,TWOTO63(%a6)
5651 fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
5652 fsub.s TWOTO63(%a6),%fp2 # fp2 = N
5653# fint.x %fp2
5654
5655#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5656 mov.l %d1,%d2 # d2 = L
5657
5658 add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
5659 mov.w %d2,FP_SCR0_EX(%a6)
5660 mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
5661 clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
5662
5663 add.l &0x00003FDD,%d1
5664 mov.w %d1,FP_SCR1_EX(%a6)
5665 mov.l &0x85A308D3,FP_SCR1_HI(%a6)
5666 clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
5667
5668 mov.b ENDFLAG(%a6),%d1
5669
5670#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5671#--P2 = 2**(L) * Piby2_2
5672 fmov.x %fp2,%fp4 # fp4 = N
5673 fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
5674 fmov.x %fp2,%fp5 # fp5 = N
5675 fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
5676 fmov.x %fp4,%fp3 # fp3 = W = N*P1
5677
5678#--we want P+p = W+w but |p| <= half ulp of P
5679#--Then, we need to compute A := R-P and a := r-p
5680 fadd.x %fp5,%fp3 # fp3 = P
5681 fsub.x %fp3,%fp4 # fp4 = W-P
5682
5683 fsub.x %fp3,%fp0 # fp0 = A := R - P
5684 fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
5685
5686 fmov.x %fp0,%fp3 # fp3 = A
5687 fsub.x %fp4,%fp1 # fp1 = a := r - p
5688
5689#--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
5690#--|r| <= half ulp of R.
5691 fadd.x %fp1,%fp0 # fp0 = R := A+a
5692#--No need to calculate r if this is the last loop
5693 cmp.b %d1,&0
5694 bgt.w SRESTORE
5695
5696#--Need to calculate r
5697 fsub.x %fp0,%fp3 # fp3 = A-R
5698 fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
5699 bra.w SLOOP
5700
5701SRESTORE:
5702 fmov.l %fp2,INT(%a6)
5703 mov.l (%sp)+,%d2 # restore d2
5704 fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
5705
5706 mov.l ADJN(%a6),%d1
5707 cmp.l %d1,&4
5708
5709 blt.w SINCONT
5710 bra.w SCCONT
5711
5712#########################################################################
5713# stan(): computes the tangent of a normalized input #
5714# stand(): computes the tangent of a denormalized input #
5715# #
5716# INPUT *************************************************************** #
5717# a0 = pointer to extended precision input #
5718# d0 = round precision,mode #
5719# #
5720# OUTPUT ************************************************************** #
5721# fp0 = tan(X) #
5722# #
5723# ACCURACY and MONOTONICITY ******************************************* #
5724# The returned result is within 3 ulp in 64 significant bit, i.e. #
5725# within 0.5001 ulp to 53 bits if the result is subsequently #
5726# rounded to double precision. The result is provably monotonic #
5727# in double precision. #
5728# #
5729# ALGORITHM *********************************************************** #
5730# #
5731# 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
5732# #
5733# 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
5734# k = N mod 2, so in particular, k = 0 or 1. #
5735# #
5736# 3. If k is odd, go to 5. #
5737# #
5738# 4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a #
5739# rational function U/V where #
5740# U = r + r*s*(P1 + s*(P2 + s*P3)), and #
5741# V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r. #
5742# Exit. #
5743# #
5744# 4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
5745# a rational function U/V where #
5746# U = r + r*s*(P1 + s*(P2 + s*P3)), and #
5747# V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r, #
5748# -Cot(r) = -V/U. Exit. #
5749# #
5750# 6. If |X| > 1, go to 8. #
5751# #
5752# 7. (|X|<2**(-40)) Tan(X) = X. Exit. #
5753# #
5754# 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back #
5755# to 2. #
5756# #
5757#########################################################################
5758
5759TANQ4:
5760 long 0x3EA0B759,0xF50F8688
5761TANP3:
5762 long 0xBEF2BAA5,0xA8924F04
5763
5764TANQ3:
5765 long 0xBF346F59,0xB39BA65F,0x00000000,0x00000000
5766
5767TANP2:
5768 long 0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
5769
5770TANQ2:
5771 long 0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
5772
5773TANP1:
5774 long 0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
5775
5776TANQ1:
5777 long 0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
5778
5779INVTWOPI:
5780 long 0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
5781
5782TWOPI1:
5783 long 0x40010000,0xC90FDAA2,0x00000000,0x00000000
5784TWOPI2:
5785 long 0x3FDF0000,0x85A308D4,0x00000000,0x00000000
5786
5787#--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
5788#--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
5789#--MOST 69 BITS LONG.
5790# global PITBL
5791PITBL:
5792 long 0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
5793 long 0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
5794 long 0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
5795 long 0xC0040000,0xB6365E22,0xEE46F000,0x21480000
5796 long 0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
5797 long 0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
5798 long 0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
5799 long 0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
5800 long 0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
5801 long 0xC0040000,0x90836524,0x88034B96,0x20B00000
5802 long 0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
5803 long 0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
5804 long 0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
5805 long 0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
5806 long 0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
5807 long 0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
5808 long 0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
5809 long 0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
5810 long 0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
5811 long 0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
5812 long 0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
5813 long 0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
5814 long 0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
5815 long 0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
5816 long 0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
5817 long 0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
5818 long 0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
5819 long 0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
5820 long 0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
5821 long 0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
5822 long 0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
5823 long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
5824 long 0x00000000,0x00000000,0x00000000,0x00000000
5825 long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
5826 long 0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
5827 long 0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
5828 long 0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
5829 long 0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
5830 long 0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
5831 long 0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
5832 long 0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
5833 long 0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
5834 long 0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
5835 long 0x40030000,0x8A3AE64F,0x76F80584,0x21080000
5836 long 0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
5837 long 0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
5838 long 0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
5839 long 0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
5840 long 0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
5841 long 0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
5842 long 0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
5843 long 0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
5844 long 0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
5845 long 0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
5846 long 0x40040000,0x8A3AE64F,0x76F80584,0x21880000
5847 long 0x40040000,0x90836524,0x88034B96,0xA0B00000
5848 long 0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
5849 long 0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
5850 long 0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
5851 long 0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
5852 long 0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
5853 long 0x40040000,0xB6365E22,0xEE46F000,0xA1480000
5854 long 0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
5855 long 0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
5856 long 0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
5857
5858 set INARG,FP_SCR0
5859
5860 set TWOTO63,L_SCR1
5861 set INT,L_SCR1
5862 set ENDFLAG,L_SCR2
5863
5864 global stan
5865stan:
5866 fmov.x (%a0),%fp0 # LOAD INPUT
5867
5868 mov.l (%a0),%d1
5869 mov.w 4(%a0),%d1
5870 and.l &0x7FFFFFFF,%d1
5871
5872 cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
5873 bge.b TANOK1
5874 bra.w TANSM
5875TANOK1:
5876 cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
5877 blt.b TANMAIN
5878 bra.w REDUCEX
5879
5880TANMAIN:
5881#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5882#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5883 fmov.x %fp0,%fp1
5884 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5885
5886 lea.l PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5887
5888 fmov.l %fp1,%d1 # CONVERT TO INTEGER
5889
5890 asl.l &4,%d1
5891 add.l %d1,%a1 # ADDRESS N*PIBY2 IN Y1, Y2
5892
5893 fsub.x (%a1)+,%fp0 # X-Y1
5894
5895 fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
5896
5897 ror.l &5,%d1
5898 and.l &0x80000000,%d1 # D0 WAS ODD IFF D0 < 0
5899
5900TANCONT:
5901 fmovm.x &0x0c,-(%sp) # save fp2,fp3
5902
5903 cmp.l %d1,&0
5904 blt.w NODD
5905
5906 fmov.x %fp0,%fp1
5907 fmul.x %fp1,%fp1 # S = R*R
5908
5909 fmov.d TANQ4(%pc),%fp3
5910 fmov.d TANP3(%pc),%fp2
5911
5912 fmul.x %fp1,%fp3 # SQ4
5913 fmul.x %fp1,%fp2 # SP3
5914
5915 fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
5916 fadd.x TANP2(%pc),%fp2 # P2+SP3
5917
5918 fmul.x %fp1,%fp3 # S(Q3+SQ4)
5919 fmul.x %fp1,%fp2 # S(P2+SP3)
5920
5921 fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
5922 fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
5923
5924 fmul.x %fp1,%fp3 # S(Q2+S(Q3+SQ4))
5925 fmul.x %fp1,%fp2 # S(P1+S(P2+SP3))
5926
5927 fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
5928 fmul.x %fp0,%fp2 # RS(P1+S(P2+SP3))
5929
5930 fmul.x %fp3,%fp1 # S(Q1+S(Q2+S(Q3+SQ4)))
5931
5932 fadd.x %fp2,%fp0 # R+RS(P1+S(P2+SP3))
5933
5934 fadd.s &0x3F800000,%fp1 # 1+S(Q1+...)
5935
5936 fmovm.x (%sp)+,&0x30 # restore fp2,fp3
5937
5938 fmov.l %d0,%fpcr # restore users round mode,prec
5939 fdiv.x %fp1,%fp0 # last inst - possible exception set
5940 bra t_inx2
5941
5942NODD:
5943 fmov.x %fp0,%fp1
5944 fmul.x %fp0,%fp0 # S = R*R
5945
5946 fmov.d TANQ4(%pc),%fp3
5947 fmov.d TANP3(%pc),%fp2
5948
5949 fmul.x %fp0,%fp3 # SQ4
5950 fmul.x %fp0,%fp2 # SP3
5951
5952 fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
5953 fadd.x TANP2(%pc),%fp2 # P2+SP3
5954
5955 fmul.x %fp0,%fp3 # S(Q3+SQ4)
5956 fmul.x %fp0,%fp2 # S(P2+SP3)
5957
5958 fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
5959 fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
5960
5961 fmul.x %fp0,%fp3 # S(Q2+S(Q3+SQ4))
5962 fmul.x %fp0,%fp2 # S(P1+S(P2+SP3))
5963
5964 fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
5965 fmul.x %fp1,%fp2 # RS(P1+S(P2+SP3))
5966
5967 fmul.x %fp3,%fp0 # S(Q1+S(Q2+S(Q3+SQ4)))
5968
5969 fadd.x %fp2,%fp1 # R+RS(P1+S(P2+SP3))
5970 fadd.s &0x3F800000,%fp0 # 1+S(Q1+...)
5971
5972 fmovm.x (%sp)+,&0x30 # restore fp2,fp3
5973
5974 fmov.x %fp1,-(%sp)
5975 eor.l &0x80000000,(%sp)
5976
5977 fmov.l %d0,%fpcr # restore users round mode,prec
5978 fdiv.x (%sp)+,%fp0 # last inst - possible exception set
5979 bra t_inx2
5980
5981TANBORS:
5982#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5983#--IF |X| < 2**(-40), RETURN X OR 1.
5984 cmp.l %d1,&0x3FFF8000
5985 bgt.b REDUCEX
5986
5987TANSM:
5988 fmov.x %fp0,-(%sp)
5989 fmov.l %d0,%fpcr # restore users round mode,prec
5990 mov.b &FMOV_OP,%d1 # last inst is MOVE
5991 fmov.x (%sp)+,%fp0 # last inst - posibble exception set
5992 bra t_catch
5993
5994 global stand
5995#--TAN(X) = X FOR DENORMALIZED X
5996stand:
5997 bra t_extdnrm
5998
5999#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
6000#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
6001#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
6002REDUCEX:
6003 fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
6004 mov.l %d2,-(%sp) # save d2
6005 fmov.s &0x00000000,%fp1 # fp1 = 0
6006
6007#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
6008#--there is a danger of unwanted overflow in first LOOP iteration. In this
6009#--case, reduce argument by one remainder step to make subsequent reduction
6010#--safe.
6011 cmp.l %d1,&0x7ffeffff # is arg dangerously large?
6012 bne.b LOOP # no
6013
6014# yes; create 2**16383*PI/2
6015 mov.w &0x7ffe,FP_SCR0_EX(%a6)
6016 mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
6017 clr.l FP_SCR0_LO(%a6)
6018
6019# create low half of 2**16383*PI/2 at FP_SCR1
6020 mov.w &0x7fdc,FP_SCR1_EX(%a6)
6021 mov.l &0x85a308d3,FP_SCR1_HI(%a6)
6022 clr.l FP_SCR1_LO(%a6)
6023
6024 ftest.x %fp0 # test sign of argument
6025 fblt.w red_neg
6026
6027 or.b &0x80,FP_SCR0_EX(%a6) # positive arg
6028 or.b &0x80,FP_SCR1_EX(%a6)
6029red_neg:
6030 fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
6031 fmov.x %fp0,%fp1 # save high result in fp1
6032 fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
6033 fsub.x %fp0,%fp1 # determine low component of result
6034 fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
6035
6036#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
6037#--integer quotient will be stored in N
6038#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
6039LOOP:
6040 fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
6041 mov.w INARG(%a6),%d1
6042 mov.l %d1,%a1 # save a copy of D0
6043 and.l &0x00007FFF,%d1
6044 sub.l &0x00003FFF,%d1 # d0 = K
6045 cmp.l %d1,&28
6046 ble.b LASTLOOP
6047CONTLOOP:
6048 sub.l &27,%d1 # d0 = L := K-27
6049 mov.b &0,ENDFLAG(%a6)
6050 bra.b WORK
6051LASTLOOP:
6052 clr.l %d1 # d0 = L := 0
6053 mov.b &1,ENDFLAG(%a6)
6054
6055WORK:
6056#--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
6057#--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
6058
6059#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
6060#--2**L * (PIby2_1), 2**L * (PIby2_2)
6061
6062 mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
6063 sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
6064
6065 mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
6066 mov.l &0x4E44152A,FP_SCR0_LO(%a6)
6067 mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
6068
6069 fmov.x %fp0,%fp2
6070 fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
6071
6072#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
6073#--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
6074#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
6075#--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
6076#--US THE DESIRED VALUE IN FLOATING POINT.
6077 mov.l %a1,%d2
6078 swap %d2
6079 and.l &0x80000000,%d2
6080 or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
6081 mov.l %d2,TWOTO63(%a6)
6082 fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
6083 fsub.s TWOTO63(%a6),%fp2 # fp2 = N
6084# fintrz.x %fp2,%fp2
6085
6086#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
6087 mov.l %d1,%d2 # d2 = L
6088
6089 add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
6090 mov.w %d2,FP_SCR0_EX(%a6)
6091 mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
6092 clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
6093
6094 add.l &0x00003FDD,%d1
6095 mov.w %d1,FP_SCR1_EX(%a6)
6096 mov.l &0x85A308D3,FP_SCR1_HI(%a6)
6097 clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
6098
6099 mov.b ENDFLAG(%a6),%d1
6100
6101#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
6102#--P2 = 2**(L) * Piby2_2
6103 fmov.x %fp2,%fp4 # fp4 = N
6104 fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
6105 fmov.x %fp2,%fp5 # fp5 = N
6106 fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
6107 fmov.x %fp4,%fp3 # fp3 = W = N*P1
6108
6109#--we want P+p = W+w but |p| <= half ulp of P
6110#--Then, we need to compute A := R-P and a := r-p
6111 fadd.x %fp5,%fp3 # fp3 = P
6112 fsub.x %fp3,%fp4 # fp4 = W-P
6113
6114 fsub.x %fp3,%fp0 # fp0 = A := R - P
6115 fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
6116
6117 fmov.x %fp0,%fp3 # fp3 = A
6118 fsub.x %fp4,%fp1 # fp1 = a := r - p
6119
6120#--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
6121#--|r| <= half ulp of R.
6122 fadd.x %fp1,%fp0 # fp0 = R := A+a
6123#--No need to calculate r if this is the last loop
6124 cmp.b %d1,&0
6125 bgt.w RESTORE
6126
6127#--Need to calculate r
6128 fsub.x %fp0,%fp3 # fp3 = A-R
6129 fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
6130 bra.w LOOP
6131
6132RESTORE:
6133 fmov.l %fp2,INT(%a6)
6134 mov.l (%sp)+,%d2 # restore d2
6135 fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
6136
6137 mov.l INT(%a6),%d1
6138 ror.l &1,%d1
6139
6140 bra.w TANCONT
6141
6142#########################################################################
6143# satan(): computes the arctangent of a normalized number #
6144# satand(): computes the arctangent of a denormalized number #
6145# #
6146# INPUT *************************************************************** #
6147# a0 = pointer to extended precision input #
6148# d0 = round precision,mode #
6149# #
6150# OUTPUT ************************************************************** #
6151# fp0 = arctan(X) #
6152# #
6153# ACCURACY and MONOTONICITY ******************************************* #
6154# The returned result is within 2 ulps in 64 significant bit, #
6155# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6156# rounded to double precision. The result is provably monotonic #
6157# in double precision. #
6158# #
6159# ALGORITHM *********************************************************** #
6160# Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5. #
6161# #
6162# Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x. #
6163# Note that k = -4, -3,..., or 3. #
6164# Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5 #
6165# significant bits of X with a bit-1 attached at the 6-th #
6166# bit position. Define u to be u = (X-F) / (1 + X*F). #
6167# #
6168# Step 3. Approximate arctan(u) by a polynomial poly. #
6169# #
6170# Step 4. Return arctan(F) + poly, arctan(F) is fetched from a #
6171# table of values calculated beforehand. Exit. #
6172# #
6173# Step 5. If |X| >= 16, go to Step 7. #
6174# #
6175# Step 6. Approximate arctan(X) by an odd polynomial in X. Exit. #
6176# #
6177# Step 7. Define X' = -1/X. Approximate arctan(X') by an odd #
6178# polynomial in X'. #
6179# Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit. #
6180# #
6181#########################################################################
6182
6183ATANA3: long 0xBFF6687E,0x314987D8
6184ATANA2: long 0x4002AC69,0x34A26DB3
6185ATANA1: long 0xBFC2476F,0x4E1DA28E
6186
6187ATANB6: long 0x3FB34444,0x7F876989
6188ATANB5: long 0xBFB744EE,0x7FAF45DB
6189ATANB4: long 0x3FBC71C6,0x46940220
6190ATANB3: long 0xBFC24924,0x921872F9
6191ATANB2: long 0x3FC99999,0x99998FA9
6192ATANB1: long 0xBFD55555,0x55555555
6193
6194ATANC5: long 0xBFB70BF3,0x98539E6A
6195ATANC4: long 0x3FBC7187,0x962D1D7D
6196ATANC3: long 0xBFC24924,0x827107B8
6197ATANC2: long 0x3FC99999,0x9996263E
6198ATANC1: long 0xBFD55555,0x55555536
6199
6200PPIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
6201NPIBY2: long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
6202
6203PTINY: long 0x00010000,0x80000000,0x00000000,0x00000000
6204NTINY: long 0x80010000,0x80000000,0x00000000,0x00000000
6205
6206ATANTBL:
6207 long 0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
6208 long 0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
6209 long 0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
6210 long 0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
6211 long 0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
6212 long 0x3FFB0000,0xAB98E943,0x62765619,0x00000000
6213 long 0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
6214 long 0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
6215 long 0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
6216 long 0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
6217 long 0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
6218 long 0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
6219 long 0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
6220 long 0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
6221 long 0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
6222 long 0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
6223 long 0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
6224 long 0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
6225 long 0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
6226 long 0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
6227 long 0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
6228 long 0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
6229 long 0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
6230 long 0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
6231 long 0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
6232 long 0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
6233 long 0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
6234 long 0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
6235 long 0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
6236 long 0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
6237 long 0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
6238 long 0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
6239 long 0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
6240 long 0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
6241 long 0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
6242 long 0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
6243 long 0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
6244 long 0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
6245 long 0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
6246 long 0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
6247 long 0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
6248 long 0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
6249 long 0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
6250 long 0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
6251 long 0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
6252 long 0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
6253 long 0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
6254 long 0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
6255 long 0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
6256 long 0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
6257 long 0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
6258 long 0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
6259 long 0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
6260 long 0x3FFE0000,0x97731420,0x365E538C,0x00000000
6261 long 0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
6262 long 0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
6263 long 0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
6264 long 0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
6265 long 0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
6266 long 0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
6267 long 0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
6268 long 0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
6269 long 0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
6270 long 0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
6271 long 0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
6272 long 0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
6273 long 0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
6274 long 0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
6275 long 0x3FFE0000,0xE8771129,0xC4353259,0x00000000
6276 long 0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
6277 long 0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
6278 long 0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
6279 long 0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
6280 long 0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
6281 long 0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
6282 long 0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
6283 long 0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
6284 long 0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
6285 long 0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
6286 long 0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
6287 long 0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
6288 long 0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
6289 long 0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
6290 long 0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
6291 long 0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
6292 long 0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
6293 long 0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
6294 long 0x3FFF0000,0x9F100575,0x006CC571,0x00000000
6295 long 0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
6296 long 0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
6297 long 0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
6298 long 0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
6299 long 0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
6300 long 0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
6301 long 0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
6302 long 0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
6303 long 0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
6304 long 0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
6305 long 0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
6306 long 0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
6307 long 0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
6308 long 0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
6309 long 0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
6310 long 0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
6311 long 0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
6312 long 0x3FFF0000,0xB525529D,0x562246BD,0x00000000
6313 long 0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
6314 long 0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
6315 long 0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
6316 long 0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
6317 long 0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
6318 long 0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
6319 long 0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
6320 long 0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
6321 long 0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
6322 long 0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
6323 long 0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
6324 long 0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
6325 long 0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
6326 long 0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
6327 long 0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
6328 long 0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
6329 long 0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
6330 long 0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
6331 long 0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
6332 long 0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
6333 long 0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
6334 long 0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
6335
6336 set X,FP_SCR0
6337 set XDCARE,X+2
6338 set XFRAC,X+4
6339 set XFRACLO,X+8
6340
6341 set ATANF,FP_SCR1
6342 set ATANFHI,ATANF+4
6343 set ATANFLO,ATANF+8
6344
6345 global satan
6346#--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
6347satan:
6348 fmov.x (%a0),%fp0 # LOAD INPUT
6349
6350 mov.l (%a0),%d1
6351 mov.w 4(%a0),%d1
6352 fmov.x %fp0,X(%a6)
6353 and.l &0x7FFFFFFF,%d1
6354
6355 cmp.l %d1,&0x3FFB8000 # |X| >= 1/16?
6356 bge.b ATANOK1
6357 bra.w ATANSM
6358
6359ATANOK1:
6360 cmp.l %d1,&0x4002FFFF # |X| < 16 ?
6361 ble.b ATANMAIN
6362 bra.w ATANBIG
6363
6364#--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
6365#--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
6366#--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
6367#--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
6368#--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
6369#--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
6370#--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
6371#--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
6372#--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
6373#--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
6374#--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
6375#--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
6376#--WILL INVOLVE A VERY LONG POLYNOMIAL.
6377
6378#--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
6379#--WE CHOSE F TO BE +-2^K * 1.BBBB1
6380#--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
6381#--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
6382#--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
6383#-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
6384
6385ATANMAIN:
6386
6387 and.l &0xF8000000,XFRAC(%a6) # FIRST 5 BITS
6388 or.l &0x04000000,XFRAC(%a6) # SET 6-TH BIT TO 1
6389 mov.l &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
6390
6391 fmov.x %fp0,%fp1 # FP1 IS X
6392 fmul.x X(%a6),%fp1 # FP1 IS X*F, NOTE THAT X*F > 0
6393 fsub.x X(%a6),%fp0 # FP0 IS X-F
6394 fadd.s &0x3F800000,%fp1 # FP1 IS 1 + X*F
6395 fdiv.x %fp1,%fp0 # FP0 IS U = (X-F)/(1+X*F)
6396
6397#--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
6398#--CREATE ATAN(F) AND STORE IT IN ATANF, AND
6399#--SAVE REGISTERS FP2.
6400
6401 mov.l %d2,-(%sp) # SAVE d2 TEMPORARILY
6402 mov.l %d1,%d2 # THE EXP AND 16 BITS OF X
6403 and.l &0x00007800,%d1 # 4 VARYING BITS OF F'S FRACTION
6404 and.l &0x7FFF0000,%d2 # EXPONENT OF F
6405 sub.l &0x3FFB0000,%d2 # K+4
6406 asr.l &1,%d2
6407 add.l %d2,%d1 # THE 7 BITS IDENTIFYING F
6408 asr.l &7,%d1 # INDEX INTO TBL OF ATAN(|F|)
6409 lea ATANTBL(%pc),%a1
6410 add.l %d1,%a1 # ADDRESS OF ATAN(|F|)
6411 mov.l (%a1)+,ATANF(%a6)
6412 mov.l (%a1)+,ATANFHI(%a6)
6413 mov.l (%a1)+,ATANFLO(%a6) # ATANF IS NOW ATAN(|F|)
6414 mov.l X(%a6),%d1 # LOAD SIGN AND EXPO. AGAIN
6415 and.l &0x80000000,%d1 # SIGN(F)
6416 or.l %d1,ATANF(%a6) # ATANF IS NOW SIGN(F)*ATAN(|F|)
6417 mov.l (%sp)+,%d2 # RESTORE d2
6418
6419#--THAT'S ALL I HAVE TO DO FOR NOW,
6420#--BUT ALAS, THE DIVIDE IS STILL CRANKING!
6421
6422#--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
6423#--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
6424#--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
6425#--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
6426#--WHAT WE HAVE HERE IS MERELY A1 = A3, A2 = A1/A3, A3 = A2/A3.
6427#--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
6428#--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
6429
6430 fmovm.x &0x04,-(%sp) # save fp2
6431
6432 fmov.x %fp0,%fp1
6433 fmul.x %fp1,%fp1
6434 fmov.d ATANA3(%pc),%fp2
6435 fadd.x %fp1,%fp2 # A3+V
6436 fmul.x %fp1,%fp2 # V*(A3+V)
6437 fmul.x %fp0,%fp1 # U*V
6438 fadd.d ATANA2(%pc),%fp2 # A2+V*(A3+V)
6439 fmul.d ATANA1(%pc),%fp1 # A1*U*V
6440 fmul.x %fp2,%fp1 # A1*U*V*(A2+V*(A3+V))
6441 fadd.x %fp1,%fp0 # ATAN(U), FP1 RELEASED
6442
6443 fmovm.x (%sp)+,&0x20 # restore fp2
6444
6445 fmov.l %d0,%fpcr # restore users rnd mode,prec
6446 fadd.x ATANF(%a6),%fp0 # ATAN(X)
6447 bra t_inx2
6448
6449ATANBORS:
6450#--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
6451#--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
6452 cmp.l %d1,&0x3FFF8000
6453 bgt.w ATANBIG # I.E. |X| >= 16
6454
6455ATANSM:
6456#--|X| <= 1/16
6457#--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
6458#--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
6459#--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
6460#--WHERE Y = X*X, AND Z = Y*Y.
6461
6462 cmp.l %d1,&0x3FD78000
6463 blt.w ATANTINY
6464
6465#--COMPUTE POLYNOMIAL
6466 fmovm.x &0x0c,-(%sp) # save fp2/fp3
6467
6468 fmul.x %fp0,%fp0 # FPO IS Y = X*X
6469
6470 fmov.x %fp0,%fp1
6471 fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
6472
6473 fmov.d ATANB6(%pc),%fp2
6474 fmov.d ATANB5(%pc),%fp3
6475
6476 fmul.x %fp1,%fp2 # Z*B6
6477 fmul.x %fp1,%fp3 # Z*B5
6478
6479 fadd.d ATANB4(%pc),%fp2 # B4+Z*B6
6480 fadd.d ATANB3(%pc),%fp3 # B3+Z*B5
6481
6482 fmul.x %fp1,%fp2 # Z*(B4+Z*B6)
6483 fmul.x %fp3,%fp1 # Z*(B3+Z*B5)
6484
6485 fadd.d ATANB2(%pc),%fp2 # B2+Z*(B4+Z*B6)
6486 fadd.d ATANB1(%pc),%fp1 # B1+Z*(B3+Z*B5)
6487
6488 fmul.x %fp0,%fp2 # Y*(B2+Z*(B4+Z*B6))
6489 fmul.x X(%a6),%fp0 # X*Y
6490
6491 fadd.x %fp2,%fp1 # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
6492
6493 fmul.x %fp1,%fp0 # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
6494
6495 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
6496
6497 fmov.l %d0,%fpcr # restore users rnd mode,prec
6498 fadd.x X(%a6),%fp0
6499 bra t_inx2
6500
6501ATANTINY:
6502#--|X| < 2^(-40), ATAN(X) = X
6503
6504 fmov.l %d0,%fpcr # restore users rnd mode,prec
6505 mov.b &FMOV_OP,%d1 # last inst is MOVE
6506 fmov.x X(%a6),%fp0 # last inst - possible exception set
6507
6508 bra t_catch
6509
6510ATANBIG:
6511#--IF |X| > 2^(100), RETURN SIGN(X)*(PI/2 - TINY). OTHERWISE,
6512#--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
6513 cmp.l %d1,&0x40638000
6514 bgt.w ATANHUGE
6515
6516#--APPROXIMATE ATAN(-1/X) BY
6517#--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
6518#--THIS CAN BE RE-WRITTEN AS
6519#--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
6520
6521 fmovm.x &0x0c,-(%sp) # save fp2/fp3
6522
6523 fmov.s &0xBF800000,%fp1 # LOAD -1
6524 fdiv.x %fp0,%fp1 # FP1 IS -1/X
6525
6526#--DIVIDE IS STILL CRANKING
6527
6528 fmov.x %fp1,%fp0 # FP0 IS X'
6529 fmul.x %fp0,%fp0 # FP0 IS Y = X'*X'
6530 fmov.x %fp1,X(%a6) # X IS REALLY X'
6531
6532 fmov.x %fp0,%fp1
6533 fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
6534
6535 fmov.d ATANC5(%pc),%fp3
6536 fmov.d ATANC4(%pc),%fp2
6537
6538 fmul.x %fp1,%fp3 # Z*C5
6539 fmul.x %fp1,%fp2 # Z*B4
6540
6541 fadd.d ATANC3(%pc),%fp3 # C3+Z*C5
6542 fadd.d ATANC2(%pc),%fp2 # C2+Z*C4
6543
6544 fmul.x %fp3,%fp1 # Z*(C3+Z*C5), FP3 RELEASED
6545 fmul.x %fp0,%fp2 # Y*(C2+Z*C4)
6546
6547 fadd.d ATANC1(%pc),%fp1 # C1+Z*(C3+Z*C5)
6548 fmul.x X(%a6),%fp0 # X'*Y
6549
6550 fadd.x %fp2,%fp1 # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
6551
6552 fmul.x %fp1,%fp0 # X'*Y*([B1+Z*(B3+Z*B5)]
6553# ... +[Y*(B2+Z*(B4+Z*B6))])
6554 fadd.x X(%a6),%fp0
6555
6556 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
6557
6558 fmov.l %d0,%fpcr # restore users rnd mode,prec
6559 tst.b (%a0)
6560 bpl.b pos_big
6561
6562neg_big:
6563 fadd.x NPIBY2(%pc),%fp0
6564 bra t_minx2
6565
6566pos_big:
6567 fadd.x PPIBY2(%pc),%fp0
6568 bra t_pinx2
6569
6570ATANHUGE:
6571#--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
6572 tst.b (%a0)
6573 bpl.b pos_huge
6574
6575neg_huge:
6576 fmov.x NPIBY2(%pc),%fp0
6577 fmov.l %d0,%fpcr
6578 fadd.x PTINY(%pc),%fp0
6579 bra t_minx2
6580
6581pos_huge:
6582 fmov.x PPIBY2(%pc),%fp0
6583 fmov.l %d0,%fpcr
6584 fadd.x NTINY(%pc),%fp0
6585 bra t_pinx2
6586
6587 global satand
6588#--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
6589satand:
6590 bra t_extdnrm
6591
6592#########################################################################
6593# sasin(): computes the inverse sine of a normalized input #
6594# sasind(): computes the inverse sine of a denormalized input #
6595# #
6596# INPUT *************************************************************** #
6597# a0 = pointer to extended precision input #
6598# d0 = round precision,mode #
6599# #
6600# OUTPUT ************************************************************** #
6601# fp0 = arcsin(X) #
6602# #
6603# ACCURACY and MONOTONICITY ******************************************* #
6604# The returned result is within 3 ulps in 64 significant bit, #
6605# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6606# rounded to double precision. The result is provably monotonic #
6607# in double precision. #
6608# #
6609# ALGORITHM *********************************************************** #
6610# #
6611# ASIN #
6612# 1. If |X| >= 1, go to 3. #
6613# #
6614# 2. (|X| < 1) Calculate asin(X) by #
6615# z := sqrt( [1-X][1+X] ) #
6616# asin(X) = atan( x / z ). #
6617# Exit. #
6618# #
6619# 3. If |X| > 1, go to 5. #
6620# #
6621# 4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
6622# #
6623# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
6624# Exit. #
6625# #
6626#########################################################################
6627
6628 global sasin
6629sasin:
6630 fmov.x (%a0),%fp0 # LOAD INPUT
6631
6632 mov.l (%a0),%d1
6633 mov.w 4(%a0),%d1
6634 and.l &0x7FFFFFFF,%d1
6635 cmp.l %d1,&0x3FFF8000
6636 bge.b ASINBIG
6637
6638# This catch is added here for the '060 QSP. Originally, the call to
6639# satan() would handle this case by causing the exception which would
6640# not be caught until gen_except(). Now, with the exceptions being
6641# detected inside of satan(), the exception would have been handled there
6642# instead of inside sasin() as expected.
6643 cmp.l %d1,&0x3FD78000
6644 blt.w ASINTINY
6645
6646#--THIS IS THE USUAL CASE, |X| < 1
6647#--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
6648
6649ASINMAIN:
6650 fmov.s &0x3F800000,%fp1
6651 fsub.x %fp0,%fp1 # 1-X
6652 fmovm.x &0x4,-(%sp) # {fp2}
6653 fmov.s &0x3F800000,%fp2
6654 fadd.x %fp0,%fp2 # 1+X
6655 fmul.x %fp2,%fp1 # (1+X)(1-X)
6656 fmovm.x (%sp)+,&0x20 # {fp2}
6657 fsqrt.x %fp1 # SQRT([1-X][1+X])
6658 fdiv.x %fp1,%fp0 # X/SQRT([1-X][1+X])
6659 fmovm.x &0x01,-(%sp) # save X/SQRT(...)
6660 lea (%sp),%a0 # pass ptr to X/SQRT(...)
6661 bsr satan
6662 add.l &0xc,%sp # clear X/SQRT(...) from stack
6663 bra t_inx2
6664
6665ASINBIG:
6666 fabs.x %fp0 # |X|
6667 fcmp.s %fp0,&0x3F800000
6668 fbgt t_operr # cause an operr exception
6669
6670#--|X| = 1, ASIN(X) = +- PI/2.
6671ASINONE:
6672 fmov.x PIBY2(%pc),%fp0
6673 mov.l (%a0),%d1
6674 and.l &0x80000000,%d1 # SIGN BIT OF X
6675 or.l &0x3F800000,%d1 # +-1 IN SGL FORMAT
6676 mov.l %d1,-(%sp) # push SIGN(X) IN SGL-FMT
6677 fmov.l %d0,%fpcr
6678 fmul.s (%sp)+,%fp0
6679 bra t_inx2
6680
6681#--|X| < 2^(-40), ATAN(X) = X
6682ASINTINY:
6683 fmov.l %d0,%fpcr # restore users rnd mode,prec
6684 mov.b &FMOV_OP,%d1 # last inst is MOVE
6685 fmov.x (%a0),%fp0 # last inst - possible exception
6686 bra t_catch
6687
6688 global sasind
6689#--ASIN(X) = X FOR DENORMALIZED X
6690sasind:
6691 bra t_extdnrm
6692
6693#########################################################################
6694# sacos(): computes the inverse cosine of a normalized input #
6695# sacosd(): computes the inverse cosine of a denormalized input #
6696# #
6697# INPUT *************************************************************** #
6698# a0 = pointer to extended precision input #
6699# d0 = round precision,mode #
6700# #
6701# OUTPUT ************************************************************** #
6702# fp0 = arccos(X) #
6703# #
6704# ACCURACY and MONOTONICITY ******************************************* #
6705# The returned result is within 3 ulps in 64 significant bit, #
6706# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6707# rounded to double precision. The result is provably monotonic #
6708# in double precision. #
6709# #
6710# ALGORITHM *********************************************************** #
6711# #
6712# ACOS #
6713# 1. If |X| >= 1, go to 3. #
6714# #
6715# 2. (|X| < 1) Calculate acos(X) by #
6716# z := (1-X) / (1+X) #
6717# acos(X) = 2 * atan( sqrt(z) ). #
6718# Exit. #
6719# #
6720# 3. If |X| > 1, go to 5. #
6721# #
6722# 4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit. #
6723# #
6724# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
6725# Exit. #
6726# #
6727#########################################################################
6728
6729 global sacos
6730sacos:
6731 fmov.x (%a0),%fp0 # LOAD INPUT
6732
6733 mov.l (%a0),%d1 # pack exp w/ upper 16 fraction
6734 mov.w 4(%a0),%d1
6735 and.l &0x7FFFFFFF,%d1
6736 cmp.l %d1,&0x3FFF8000
6737 bge.b ACOSBIG
6738
6739#--THIS IS THE USUAL CASE, |X| < 1
6740#--ACOS(X) = 2 * ATAN( SQRT( (1-X)/(1+X) ) )
6741
6742ACOSMAIN:
6743 fmov.s &0x3F800000,%fp1
6744 fadd.x %fp0,%fp1 # 1+X
6745 fneg.x %fp0 # -X
6746 fadd.s &0x3F800000,%fp0 # 1-X
6747 fdiv.x %fp1,%fp0 # (1-X)/(1+X)
6748 fsqrt.x %fp0 # SQRT((1-X)/(1+X))
6749 mov.l %d0,-(%sp) # save original users fpcr
6750 clr.l %d0
6751 fmovm.x &0x01,-(%sp) # save SQRT(...) to stack
6752 lea (%sp),%a0 # pass ptr to sqrt
6753 bsr satan # ATAN(SQRT([1-X]/[1+X]))
6754 add.l &0xc,%sp # clear SQRT(...) from stack
6755
6756 fmov.l (%sp)+,%fpcr # restore users round prec,mode
6757 fadd.x %fp0,%fp0 # 2 * ATAN( STUFF )
6758 bra t_pinx2
6759
6760ACOSBIG:
6761 fabs.x %fp0
6762 fcmp.s %fp0,&0x3F800000
6763 fbgt t_operr # cause an operr exception
6764
6765#--|X| = 1, ACOS(X) = 0 OR PI
6766 tst.b (%a0) # is X positive or negative?
6767 bpl.b ACOSP1
6768
6769#--X = -1
6770#Returns PI and inexact exception
6771ACOSM1:
6772 fmov.x PI(%pc),%fp0 # load PI
6773 fmov.l %d0,%fpcr # load round mode,prec
6774 fadd.s &0x00800000,%fp0 # add a small value
6775 bra t_pinx2
6776
6777ACOSP1:
6778 bra ld_pzero # answer is positive zero
6779
6780 global sacosd
6781#--ACOS(X) = PI/2 FOR DENORMALIZED X
6782sacosd:
6783 fmov.l %d0,%fpcr # load user's rnd mode/prec
6784 fmov.x PIBY2(%pc),%fp0
6785 bra t_pinx2
6786
6787#########################################################################
6788# setox(): computes the exponential for a normalized input #
6789# setoxd(): computes the exponential for a denormalized input #
6790# setoxm1(): computes the exponential minus 1 for a normalized input #
6791# setoxm1d(): computes the exponential minus 1 for a denormalized input #
6792# #
6793# INPUT *************************************************************** #
6794# a0 = pointer to extended precision input #
6795# d0 = round precision,mode #
6796# #
6797# OUTPUT ************************************************************** #
6798# fp0 = exp(X) or exp(X)-1 #
6799# #
6800# ACCURACY and MONOTONICITY ******************************************* #
6801# The returned result is within 0.85 ulps in 64 significant bit, #
6802# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6803# rounded to double precision. The result is provably monotonic #
6804# in double precision. #
6805# #
6806# ALGORITHM and IMPLEMENTATION **************************************** #
6807# #
6808# setoxd #
6809# ------ #
6810# Step 1. Set ans := 1.0 #
6811# #
6812# Step 2. Return ans := ans + sign(X)*2^(-126). Exit. #
6813# Notes: This will always generate one exception -- inexact. #
6814# #
6815# #
6816# setox #
6817# ----- #
6818# #
6819# Step 1. Filter out extreme cases of input argument. #
6820# 1.1 If |X| >= 2^(-65), go to Step 1.3. #
6821# 1.2 Go to Step 7. #
6822# 1.3 If |X| < 16380 log(2), go to Step 2. #
6823# 1.4 Go to Step 8. #
6824# Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
6825# To avoid the use of floating-point comparisons, a #
6826# compact representation of |X| is used. This format is a #
6827# 32-bit integer, the upper (more significant) 16 bits #
6828# are the sign and biased exponent field of |X|; the #
6829# lower 16 bits are the 16 most significant fraction #
6830# (including the explicit bit) bits of |X|. Consequently, #
6831# the comparisons in Steps 1.1 and 1.3 can be performed #
6832# by integer comparison. Note also that the constant #
6833# 16380 log(2) used in Step 1.3 is also in the compact #
6834# form. Thus taking the branch to Step 2 guarantees #
6835# |X| < 16380 log(2). There is no harm to have a small #
6836# number of cases where |X| is less than, but close to, #
6837# 16380 log(2) and the branch to Step 9 is taken. #
6838# #
6839# Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
6840# 2.1 Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
6841# was taken) #
6842# 2.2 N := round-to-nearest-integer( X * 64/log2 ). #
6843# 2.3 Calculate J = N mod 64; so J = 0,1,2,..., #
6844# or 63. #
6845# 2.4 Calculate M = (N - J)/64; so N = 64M + J. #
6846# 2.5 Calculate the address of the stored value of #
6847# 2^(J/64). #
6848# 2.6 Create the value Scale = 2^M. #
6849# Notes: The calculation in 2.2 is really performed by #
6850# Z := X * constant #
6851# N := round-to-nearest-integer(Z) #
6852# where #
6853# constant := single-precision( 64/log 2 ). #
6854# #
6855# Using a single-precision constant avoids memory #
6856# access. Another effect of using a single-precision #
6857# "constant" is that the calculated value Z is #
6858# #
6859# Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24). #
6860# #
6861# This error has to be considered later in Steps 3 and 4. #
6862# #
6863# Step 3. Calculate X - N*log2/64. #
6864# 3.1 R := X + N*L1, #
6865# where L1 := single-precision(-log2/64). #
6866# 3.2 R := R + N*L2, #
6867# L2 := extended-precision(-log2/64 - L1).#
6868# Notes: a) The way L1 and L2 are chosen ensures L1+L2 #
6869# approximate the value -log2/64 to 88 bits of accuracy. #
6870# b) N*L1 is exact because N is no longer than 22 bits #
6871# and L1 is no longer than 24 bits. #
6872# c) The calculation X+N*L1 is also exact due to #
6873# cancellation. Thus, R is practically X+N(L1+L2) to full #
6874# 64 bits. #
6875# d) It is important to estimate how large can |R| be #
6876# after Step 3.2. #
6877# #
6878# N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24) #
6879# X*64/log2 (1+eps) = N + f, |f| <= 0.5 #
6880# X*64/log2 - N = f - eps*X 64/log2 #
6881# X - N*log2/64 = f*log2/64 - eps*X #
6882# #
6883# #
6884# Now |X| <= 16446 log2, thus #
6885# #
6886# |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #
6887# <= 0.57 log2/64. #
6888# This bound will be used in Step 4. #
6889# #
6890# Step 4. Approximate exp(R)-1 by a polynomial #
6891# p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5)))) #
6892# Notes: a) In order to reduce memory access, the coefficients #
6893# are made as "short" as possible: A1 (which is 1/2), A4 #
6894# and A5 are single precision; A2 and A3 are double #
6895# precision. #
6896# b) Even with the restrictions above, #
6897# |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062. #
6898# Note that 0.0062 is slightly bigger than 0.57 log2/64. #
6899# c) To fully utilize the pipeline, p is separated into #
6900# two independent pieces of roughly equal complexities #
6901# p = [ R + R*S*(A2 + S*A4) ] + #
6902# [ S*(A1 + S*(A3 + S*A5)) ] #
6903# where S = R*R. #
6904# #
6905# Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by #
6906# ans := T + ( T*p + t) #
6907# where T and t are the stored values for 2^(J/64). #
6908# Notes: 2^(J/64) is stored as T and t where T+t approximates #
6909# 2^(J/64) to roughly 85 bits; T is in extended precision #
6910# and t is in single precision. Note also that T is #
6911# rounded to 62 bits so that the last two bits of T are #
6912# zero. The reason for such a special form is that T-1, #
6913# T-2, and T-8 will all be exact --- a property that will #
6914# give much more accurate computation of the function #
6915# EXPM1. #
6916# #
6917# Step 6. Reconstruction of exp(X) #
6918# exp(X) = 2^M * 2^(J/64) * exp(R). #
6919# 6.1 If AdjFlag = 0, go to 6.3 #
6920# 6.2 ans := ans * AdjScale #
6921# 6.3 Restore the user FPCR #
6922# 6.4 Return ans := ans * Scale. Exit. #
6923# Notes: If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R, #
6924# |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will #
6925# neither overflow nor underflow. If AdjFlag = 1, that #
6926# means that #
6927# X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #
6928# Hence, exp(X) may overflow or underflow or neither. #
6929# When that is the case, AdjScale = 2^(M1) where M1 is #
6930# approximately M. Thus 6.2 will never cause #
6931# over/underflow. Possible exception in 6.4 is overflow #
6932# or underflow. The inexact exception is not generated in #
6933# 6.4. Although one can argue that the inexact flag #
6934# should always be raised, to simulate that exception #
6935# cost to much than the flag is worth in practical uses. #
6936# #
6937# Step 7. Return 1 + X. #
6938# 7.1 ans := X #
6939# 7.2 Restore user FPCR. #
6940# 7.3 Return ans := 1 + ans. Exit #
6941# Notes: For non-zero X, the inexact exception will always be #
6942# raised by 7.3. That is the only exception raised by 7.3.#
6943# Note also that we use the FMOVEM instruction to move X #
6944# in Step 7.1 to avoid unnecessary trapping. (Although #
6945# the FMOVEM may not seem relevant since X is normalized, #
6946# the precaution will be useful in the library version of #
6947# this code where the separate entry for denormalized #
6948# inputs will be done away with.) #
6949# #
6950# Step 8. Handle exp(X) where |X| >= 16380log2. #
6951# 8.1 If |X| > 16480 log2, go to Step 9. #
6952# (mimic 2.2 - 2.6) #
6953# 8.2 N := round-to-integer( X * 64/log2 ) #
6954# 8.3 Calculate J = N mod 64, J = 0,1,...,63 #
6955# 8.4 K := (N-J)/64, M1 := truncate(K/2), M = K-M1, #
6956# AdjFlag := 1. #
6957# 8.5 Calculate the address of the stored value #
6958# 2^(J/64). #
6959# 8.6 Create the values Scale = 2^M, AdjScale = 2^M1. #
6960# 8.7 Go to Step 3. #
6961# Notes: Refer to notes for 2.2 - 2.6. #
6962# #
6963# Step 9. Handle exp(X), |X| > 16480 log2. #
6964# 9.1 If X < 0, go to 9.3 #
6965# 9.2 ans := Huge, go to 9.4 #
6966# 9.3 ans := Tiny. #
6967# 9.4 Restore user FPCR. #
6968# 9.5 Return ans := ans * ans. Exit. #
6969# Notes: Exp(X) will surely overflow or underflow, depending on #
6970# X's sign. "Huge" and "Tiny" are respectively large/tiny #
6971# extended-precision numbers whose square over/underflow #
6972# with an inexact result. Thus, 9.5 always raises the #
6973# inexact together with either overflow or underflow. #
6974# #
6975# setoxm1d #
6976# -------- #
6977# #
6978# Step 1. Set ans := 0 #
6979# #
6980# Step 2. Return ans := X + ans. Exit. #
6981# Notes: This will return X with the appropriate rounding #
6982# precision prescribed by the user FPCR. #
6983# #
6984# setoxm1 #
6985# ------- #
6986# #
6987# Step 1. Check |X| #
6988# 1.1 If |X| >= 1/4, go to Step 1.3. #
6989# 1.2 Go to Step 7. #
6990# 1.3 If |X| < 70 log(2), go to Step 2. #
6991# 1.4 Go to Step 10. #
6992# Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
6993# However, it is conceivable |X| can be small very often #
6994# because EXPM1 is intended to evaluate exp(X)-1 #
6995# accurately when |X| is small. For further details on #
6996# the comparisons, see the notes on Step 1 of setox. #
6997# #
6998# Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
6999# 2.1 N := round-to-nearest-integer( X * 64/log2 ). #
7000# 2.2 Calculate J = N mod 64; so J = 0,1,2,..., #
7001# or 63. #
7002# 2.3 Calculate M = (N - J)/64; so N = 64M + J. #
7003# 2.4 Calculate the address of the stored value of #
7004# 2^(J/64). #
7005# 2.5 Create the values Sc = 2^M and #
7006# OnebySc := -2^(-M). #
7007# Notes: See the notes on Step 2 of setox. #
7008# #
7009# Step 3. Calculate X - N*log2/64. #
7010# 3.1 R := X + N*L1, #
7011# where L1 := single-precision(-log2/64). #
7012# 3.2 R := R + N*L2, #
7013# L2 := extended-precision(-log2/64 - L1).#
7014# Notes: Applying the analysis of Step 3 of setox in this case #
7015# shows that |R| <= 0.0055 (note that |X| <= 70 log2 in #
7016# this case). #
7017# #
7018# Step 4. Approximate exp(R)-1 by a polynomial #
7019# p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #
7020# Notes: a) In order to reduce memory access, the coefficients #
7021# are made as "short" as possible: A1 (which is 1/2), A5 #
7022# and A6 are single precision; A2, A3 and A4 are double #
7023# precision. #
7024# b) Even with the restriction above, #
7025# |p - (exp(R)-1)| < |R| * 2^(-72.7) #
7026# for all |R| <= 0.0055. #
7027# c) To fully utilize the pipeline, p is separated into #
7028# two independent pieces of roughly equal complexity #
7029# p = [ R*S*(A2 + S*(A4 + S*A6)) ] + #
7030# [ R + S*(A1 + S*(A3 + S*A5)) ] #
7031# where S = R*R. #
7032# #
7033# Step 5. Compute 2^(J/64)*p by #
7034# p := T*p #
7035# where T and t are the stored values for 2^(J/64). #
7036# Notes: 2^(J/64) is stored as T and t where T+t approximates #
7037# 2^(J/64) to roughly 85 bits; T is in extended precision #
7038# and t is in single precision. Note also that T is #
7039# rounded to 62 bits so that the last two bits of T are #
7040# zero. The reason for such a special form is that T-1, #
7041# T-2, and T-8 will all be exact --- a property that will #
7042# be exploited in Step 6 below. The total relative error #
7043# in p is no bigger than 2^(-67.7) compared to the final #
7044# result. #
7045# #
7046# Step 6. Reconstruction of exp(X)-1 #
7047# exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ). #
7048# 6.1 If M <= 63, go to Step 6.3. #
7049# 6.2 ans := T + (p + (t + OnebySc)). Go to 6.6 #
7050# 6.3 If M >= -3, go to 6.5. #
7051# 6.4 ans := (T + (p + t)) + OnebySc. Go to 6.6 #
7052# 6.5 ans := (T + OnebySc) + (p + t). #
7053# 6.6 Restore user FPCR. #
7054# 6.7 Return ans := Sc * ans. Exit. #
7055# Notes: The various arrangements of the expressions give #
7056# accurate evaluations. #
7057# #
7058# Step 7. exp(X)-1 for |X| < 1/4. #
7059# 7.1 If |X| >= 2^(-65), go to Step 9. #
7060# 7.2 Go to Step 8. #
7061# #
7062# Step 8. Calculate exp(X)-1, |X| < 2^(-65). #
7063# 8.1 If |X| < 2^(-16312), goto 8.3 #
7064# 8.2 Restore FPCR; return ans := X - 2^(-16382). #
7065# Exit. #
7066# 8.3 X := X * 2^(140). #
7067# 8.4 Restore FPCR; ans := ans - 2^(-16382). #
7068# Return ans := ans*2^(140). Exit #
7069# Notes: The idea is to return "X - tiny" under the user #
7070# precision and rounding modes. To avoid unnecessary #
7071# inefficiency, we stay away from denormalized numbers #
7072# the best we can. For |X| >= 2^(-16312), the #
7073# straightforward 8.2 generates the inexact exception as #
7074# the case warrants. #
7075# #
7076# Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial #
7077# p = X + X*X*(B1 + X*(B2 + ... + X*B12)) #
7078# Notes: a) In order to reduce memory access, the coefficients #
7079# are made as "short" as possible: B1 (which is 1/2), B9 #
7080# to B12 are single precision; B3 to B8 are double #
7081# precision; and B2 is double extended. #
7082# b) Even with the restriction above, #
7083# |p - (exp(X)-1)| < |X| 2^(-70.6) #
7084# for all |X| <= 0.251. #
7085# Note that 0.251 is slightly bigger than 1/4. #
7086# c) To fully preserve accuracy, the polynomial is #
7087# computed as #
7088# X + ( S*B1 + Q ) where S = X*X and #
7089# Q = X*S*(B2 + X*(B3 + ... + X*B12)) #
7090# d) To fully utilize the pipeline, Q is separated into #
7091# two independent pieces of roughly equal complexity #
7092# Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] + #
7093# [ S*S*(B3 + S*(B5 + ... + S*B11)) ] #
7094# #
7095# Step 10. Calculate exp(X)-1 for |X| >= 70 log 2. #
7096# 10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all #
7097# practical purposes. Therefore, go to Step 1 of setox. #
7098# 10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #
7099# purposes. #
7100# ans := -1 #
7101# Restore user FPCR #
7102# Return ans := ans + 2^(-126). Exit. #
7103# Notes: 10.2 will always create an inexact and return -1 + tiny #
7104# in the user rounding precision and mode. #
7105# #
7106#########################################################################
7107
7108L2: long 0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
7109
7110EEXPA3: long 0x3FA55555,0x55554CC1
7111EEXPA2: long 0x3FC55555,0x55554A54
7112
7113EM1A4: long 0x3F811111,0x11174385
7114EM1A3: long 0x3FA55555,0x55554F5A
7115
7116EM1A2: long 0x3FC55555,0x55555555,0x00000000,0x00000000
7117
7118EM1B8: long 0x3EC71DE3,0xA5774682
7119EM1B7: long 0x3EFA01A0,0x19D7CB68
7120
7121EM1B6: long 0x3F2A01A0,0x1A019DF3
7122EM1B5: long 0x3F56C16C,0x16C170E2
7123
7124EM1B4: long 0x3F811111,0x11111111
7125EM1B3: long 0x3FA55555,0x55555555
7126
7127EM1B2: long 0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
7128 long 0x00000000
7129
7130TWO140: long 0x48B00000,0x00000000
7131TWON140:
7132 long 0x37300000,0x00000000
7133
7134EEXPTBL:
7135 long 0x3FFF0000,0x80000000,0x00000000,0x00000000
7136 long 0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
7137 long 0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
7138 long 0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
7139 long 0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
7140 long 0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
7141 long 0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
7142 long 0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
7143 long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
7144 long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
7145 long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
7146 long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
7147 long 0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
7148 long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
7149 long 0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
7150 long 0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
7151 long 0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
7152 long 0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
7153 long 0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
7154 long 0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
7155 long 0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
7156 long 0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
7157 long 0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
7158 long 0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
7159 long 0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
7160 long 0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
7161 long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
7162 long 0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
7163 long 0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
7164 long 0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
7165 long 0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
7166 long 0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
7167 long 0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
7168 long 0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
7169 long 0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
7170 long 0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
7171 long 0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
7172 long 0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
7173 long 0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
7174 long 0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
7175 long 0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
7176 long 0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
7177 long 0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
7178 long 0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
7179 long 0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
7180 long 0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
7181 long 0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
7182 long 0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
7183 long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
7184 long 0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
7185 long 0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
7186 long 0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
7187 long 0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
7188 long 0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
7189 long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
7190 long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
7191 long 0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
7192 long 0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
7193 long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
7194 long 0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
7195 long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
7196 long 0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
7197 long 0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
7198 long 0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
7199
7200 set ADJFLAG,L_SCR2
7201 set SCALE,FP_SCR0
7202 set ADJSCALE,FP_SCR1
7203 set SC,FP_SCR0
7204 set ONEBYSC,FP_SCR1
7205
7206 global setox
7207setox:
7208#--entry point for EXP(X), here X is finite, non-zero, and not NaN's
7209
7210#--Step 1.
7211 mov.l (%a0),%d1 # load part of input X
7212 and.l &0x7FFF0000,%d1 # biased expo. of X
7213 cmp.l %d1,&0x3FBE0000 # 2^(-65)
7214 bge.b EXPC1 # normal case
7215 bra EXPSM
7216
7217EXPC1:
7218#--The case |X| >= 2^(-65)
7219 mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
7220 cmp.l %d1,&0x400CB167 # 16380 log2 trunc. 16 bits
7221 blt.b EXPMAIN # normal case
7222 bra EEXPBIG
7223
7224EXPMAIN:
7225#--Step 2.
7226#--This is the normal branch: 2^(-65) <= |X| < 16380 log2.
7227 fmov.x (%a0),%fp0 # load input from (a0)
7228
7229 fmov.x %fp0,%fp1
7230 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7231 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7232 mov.l &0,ADJFLAG(%a6)
7233 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7234 lea EEXPTBL(%pc),%a1
7235 fmov.l %d1,%fp0 # convert to floating-format
7236
7237 mov.l %d1,L_SCR1(%a6) # save N temporarily
7238 and.l &0x3F,%d1 # D0 is J = N mod 64
7239 lsl.l &4,%d1
7240 add.l %d1,%a1 # address of 2^(J/64)
7241 mov.l L_SCR1(%a6),%d1
7242 asr.l &6,%d1 # D0 is M
7243 add.w &0x3FFF,%d1 # biased expo. of 2^(M)
7244 mov.w L2(%pc),L_SCR1(%a6) # prefetch L2, no need in CB
7245
7246EXPCONT1:
7247#--Step 3.
7248#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7249#--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
7250 fmov.x %fp0,%fp2
7251 fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
7252 fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
7253 fadd.x %fp1,%fp0 # X + N*L1
7254 fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
7255
7256#--Step 4.
7257#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7258#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
7259#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7260#--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
7261
7262 fmov.x %fp0,%fp1
7263 fmul.x %fp1,%fp1 # fp1 IS S = R*R
7264
7265 fmov.s &0x3AB60B70,%fp2 # fp2 IS A5
7266
7267 fmul.x %fp1,%fp2 # fp2 IS S*A5
7268 fmov.x %fp1,%fp3
7269 fmul.s &0x3C088895,%fp3 # fp3 IS S*A4
7270
7271 fadd.d EEXPA3(%pc),%fp2 # fp2 IS A3+S*A5
7272 fadd.d EEXPA2(%pc),%fp3 # fp3 IS A2+S*A4
7273
7274 fmul.x %fp1,%fp2 # fp2 IS S*(A3+S*A5)
7275 mov.w %d1,SCALE(%a6) # SCALE is 2^(M) in extended
7276 mov.l &0x80000000,SCALE+4(%a6)
7277 clr.l SCALE+8(%a6)
7278
7279 fmul.x %fp1,%fp3 # fp3 IS S*(A2+S*A4)
7280
7281 fadd.s &0x3F000000,%fp2 # fp2 IS A1+S*(A3+S*A5)
7282 fmul.x %fp0,%fp3 # fp3 IS R*S*(A2+S*A4)
7283
7284 fmul.x %fp1,%fp2 # fp2 IS S*(A1+S*(A3+S*A5))
7285 fadd.x %fp3,%fp0 # fp0 IS R+R*S*(A2+S*A4),
7286
7287 fmov.x (%a1)+,%fp1 # fp1 is lead. pt. of 2^(J/64)
7288 fadd.x %fp2,%fp0 # fp0 is EXP(R) - 1
7289
7290#--Step 5
7291#--final reconstruction process
7292#--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
7293
7294 fmul.x %fp1,%fp0 # 2^(J/64)*(Exp(R)-1)
7295 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7296 fadd.s (%a1),%fp0 # accurate 2^(J/64)
7297
7298 fadd.x %fp1,%fp0 # 2^(J/64) + 2^(J/64)*...
7299 mov.l ADJFLAG(%a6),%d1
7300
7301#--Step 6
7302 tst.l %d1
7303 beq.b NORMAL
7304ADJUST:
7305 fmul.x ADJSCALE(%a6),%fp0
7306NORMAL:
7307 fmov.l %d0,%fpcr # restore user FPCR
7308 mov.b &FMUL_OP,%d1 # last inst is MUL
7309 fmul.x SCALE(%a6),%fp0 # multiply 2^(M)
7310 bra t_catch
7311
7312EXPSM:
7313#--Step 7
7314 fmovm.x (%a0),&0x80 # load X
7315 fmov.l %d0,%fpcr
7316 fadd.s &0x3F800000,%fp0 # 1+X in user mode
7317 bra t_pinx2
7318
7319EEXPBIG:
7320#--Step 8
7321 cmp.l %d1,&0x400CB27C # 16480 log2
7322 bgt.b EXP2BIG
7323#--Steps 8.2 -- 8.6
7324 fmov.x (%a0),%fp0 # load input from (a0)
7325
7326 fmov.x %fp0,%fp1
7327 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7328 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7329 mov.l &1,ADJFLAG(%a6)
7330 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7331 lea EEXPTBL(%pc),%a1
7332 fmov.l %d1,%fp0 # convert to floating-format
7333 mov.l %d1,L_SCR1(%a6) # save N temporarily
7334 and.l &0x3F,%d1 # D0 is J = N mod 64
7335 lsl.l &4,%d1
7336 add.l %d1,%a1 # address of 2^(J/64)
7337 mov.l L_SCR1(%a6),%d1
7338 asr.l &6,%d1 # D0 is K
7339 mov.l %d1,L_SCR1(%a6) # save K temporarily
7340 asr.l &1,%d1 # D0 is M1
7341 sub.l %d1,L_SCR1(%a6) # a1 is M
7342 add.w &0x3FFF,%d1 # biased expo. of 2^(M1)
7343 mov.w %d1,ADJSCALE(%a6) # ADJSCALE := 2^(M1)
7344 mov.l &0x80000000,ADJSCALE+4(%a6)
7345 clr.l ADJSCALE+8(%a6)
7346 mov.l L_SCR1(%a6),%d1 # D0 is M
7347 add.w &0x3FFF,%d1 # biased expo. of 2^(M)
7348 bra.w EXPCONT1 # go back to Step 3
7349
7350EXP2BIG:
7351#--Step 9
7352 tst.b (%a0) # is X positive or negative?
7353 bmi t_unfl2
7354 bra t_ovfl2
7355
7356 global setoxd
7357setoxd:
7358#--entry point for EXP(X), X is denormalized
7359 mov.l (%a0),-(%sp)
7360 andi.l &0x80000000,(%sp)
7361 ori.l &0x00800000,(%sp) # sign(X)*2^(-126)
7362
7363 fmov.s &0x3F800000,%fp0
7364
7365 fmov.l %d0,%fpcr
7366 fadd.s (%sp)+,%fp0
7367 bra t_pinx2
7368
7369 global setoxm1
7370setoxm1:
7371#--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
7372
7373#--Step 1.
7374#--Step 1.1
7375 mov.l (%a0),%d1 # load part of input X
7376 and.l &0x7FFF0000,%d1 # biased expo. of X
7377 cmp.l %d1,&0x3FFD0000 # 1/4
7378 bge.b EM1CON1 # |X| >= 1/4
7379 bra EM1SM
7380
7381EM1CON1:
7382#--Step 1.3
7383#--The case |X| >= 1/4
7384 mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
7385 cmp.l %d1,&0x4004C215 # 70log2 rounded up to 16 bits
7386 ble.b EM1MAIN # 1/4 <= |X| <= 70log2
7387 bra EM1BIG
7388
7389EM1MAIN:
7390#--Step 2.
7391#--This is the case: 1/4 <= |X| <= 70 log2.
7392 fmov.x (%a0),%fp0 # load input from (a0)
7393
7394 fmov.x %fp0,%fp1
7395 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7396 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7397 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7398 lea EEXPTBL(%pc),%a1
7399 fmov.l %d1,%fp0 # convert to floating-format
7400
7401 mov.l %d1,L_SCR1(%a6) # save N temporarily
7402 and.l &0x3F,%d1 # D0 is J = N mod 64
7403 lsl.l &4,%d1
7404 add.l %d1,%a1 # address of 2^(J/64)
7405 mov.l L_SCR1(%a6),%d1
7406 asr.l &6,%d1 # D0 is M
7407 mov.l %d1,L_SCR1(%a6) # save a copy of M
7408
7409#--Step 3.
7410#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7411#--a0 points to 2^(J/64), D0 and a1 both contain M
7412 fmov.x %fp0,%fp2
7413 fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
7414 fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
7415 fadd.x %fp1,%fp0 # X + N*L1
7416 fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
7417 add.w &0x3FFF,%d1 # D0 is biased expo. of 2^M
7418
7419#--Step 4.
7420#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7421#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
7422#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7423#--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
7424
7425 fmov.x %fp0,%fp1
7426 fmul.x %fp1,%fp1 # fp1 IS S = R*R
7427
7428 fmov.s &0x3950097B,%fp2 # fp2 IS a6
7429
7430 fmul.x %fp1,%fp2 # fp2 IS S*A6
7431 fmov.x %fp1,%fp3
7432 fmul.s &0x3AB60B6A,%fp3 # fp3 IS S*A5
7433
7434 fadd.d EM1A4(%pc),%fp2 # fp2 IS A4+S*A6
7435 fadd.d EM1A3(%pc),%fp3 # fp3 IS A3+S*A5
7436 mov.w %d1,SC(%a6) # SC is 2^(M) in extended
7437 mov.l &0x80000000,SC+4(%a6)
7438 clr.l SC+8(%a6)
7439
7440 fmul.x %fp1,%fp2 # fp2 IS S*(A4+S*A6)
7441 mov.l L_SCR1(%a6),%d1 # D0 is M
7442 neg.w %d1 # D0 is -M
7443 fmul.x %fp1,%fp3 # fp3 IS S*(A3+S*A5)
7444 add.w &0x3FFF,%d1 # biased expo. of 2^(-M)
7445 fadd.d EM1A2(%pc),%fp2 # fp2 IS A2+S*(A4+S*A6)
7446 fadd.s &0x3F000000,%fp3 # fp3 IS A1+S*(A3+S*A5)
7447
7448 fmul.x %fp1,%fp2 # fp2 IS S*(A2+S*(A4+S*A6))
7449 or.w &0x8000,%d1 # signed/expo. of -2^(-M)
7450 mov.w %d1,ONEBYSC(%a6) # OnebySc is -2^(-M)
7451 mov.l &0x80000000,ONEBYSC+4(%a6)
7452 clr.l ONEBYSC+8(%a6)
7453 fmul.x %fp3,%fp1 # fp1 IS S*(A1+S*(A3+S*A5))
7454
7455 fmul.x %fp0,%fp2 # fp2 IS R*S*(A2+S*(A4+S*A6))
7456 fadd.x %fp1,%fp0 # fp0 IS R+S*(A1+S*(A3+S*A5))
7457
7458 fadd.x %fp2,%fp0 # fp0 IS EXP(R)-1
7459
7460 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7461
7462#--Step 5
7463#--Compute 2^(J/64)*p
7464
7465 fmul.x (%a1),%fp0 # 2^(J/64)*(Exp(R)-1)
7466
7467#--Step 6
7468#--Step 6.1
7469 mov.l L_SCR1(%a6),%d1 # retrieve M
7470 cmp.l %d1,&63
7471 ble.b MLE63
7472#--Step 6.2 M >= 64
7473 fmov.s 12(%a1),%fp1 # fp1 is t
7474 fadd.x ONEBYSC(%a6),%fp1 # fp1 is t+OnebySc
7475 fadd.x %fp1,%fp0 # p+(t+OnebySc), fp1 released
7476 fadd.x (%a1),%fp0 # T+(p+(t+OnebySc))
7477 bra EM1SCALE
7478MLE63:
7479#--Step 6.3 M <= 63
7480 cmp.l %d1,&-3
7481 bge.b MGEN3
7482MLTN3:
7483#--Step 6.4 M <= -4
7484 fadd.s 12(%a1),%fp0 # p+t
7485 fadd.x (%a1),%fp0 # T+(p+t)
7486 fadd.x ONEBYSC(%a6),%fp0 # OnebySc + (T+(p+t))
7487 bra EM1SCALE
7488MGEN3:
7489#--Step 6.5 -3 <= M <= 63
7490 fmov.x (%a1)+,%fp1 # fp1 is T
7491 fadd.s (%a1),%fp0 # fp0 is p+t
7492 fadd.x ONEBYSC(%a6),%fp1 # fp1 is T+OnebySc
7493 fadd.x %fp1,%fp0 # (T+OnebySc)+(p+t)
7494
7495EM1SCALE:
7496#--Step 6.6
7497 fmov.l %d0,%fpcr
7498 fmul.x SC(%a6),%fp0
7499 bra t_inx2
7500
7501EM1SM:
7502#--Step 7 |X| < 1/4.
7503 cmp.l %d1,&0x3FBE0000 # 2^(-65)
7504 bge.b EM1POLY
7505
7506EM1TINY:
7507#--Step 8 |X| < 2^(-65)
7508 cmp.l %d1,&0x00330000 # 2^(-16312)
7509 blt.b EM12TINY
7510#--Step 8.2
7511 mov.l &0x80010000,SC(%a6) # SC is -2^(-16382)
7512 mov.l &0x80000000,SC+4(%a6)
7513 clr.l SC+8(%a6)
7514 fmov.x (%a0),%fp0
7515 fmov.l %d0,%fpcr
7516 mov.b &FADD_OP,%d1 # last inst is ADD
7517 fadd.x SC(%a6),%fp0
7518 bra t_catch
7519
7520EM12TINY:
7521#--Step 8.3
7522 fmov.x (%a0),%fp0
7523 fmul.d TWO140(%pc),%fp0
7524 mov.l &0x80010000,SC(%a6)
7525 mov.l &0x80000000,SC+4(%a6)
7526 clr.l SC+8(%a6)
7527 fadd.x SC(%a6),%fp0
7528 fmov.l %d0,%fpcr
7529 mov.b &FMUL_OP,%d1 # last inst is MUL
7530 fmul.d TWON140(%pc),%fp0
7531 bra t_catch
7532
7533EM1POLY:
7534#--Step 9 exp(X)-1 by a simple polynomial
7535 fmov.x (%a0),%fp0 # fp0 is X
7536 fmul.x %fp0,%fp0 # fp0 is S := X*X
7537 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7538 fmov.s &0x2F30CAA8,%fp1 # fp1 is B12
7539 fmul.x %fp0,%fp1 # fp1 is S*B12
7540 fmov.s &0x310F8290,%fp2 # fp2 is B11
7541 fadd.s &0x32D73220,%fp1 # fp1 is B10+S*B12
7542
7543 fmul.x %fp0,%fp2 # fp2 is S*B11
7544 fmul.x %fp0,%fp1 # fp1 is S*(B10 + ...
7545
7546 fadd.s &0x3493F281,%fp2 # fp2 is B9+S*...
7547 fadd.d EM1B8(%pc),%fp1 # fp1 is B8+S*...
7548
7549 fmul.x %fp0,%fp2 # fp2 is S*(B9+...
7550 fmul.x %fp0,%fp1 # fp1 is S*(B8+...
7551
7552 fadd.d EM1B7(%pc),%fp2 # fp2 is B7+S*...
7553 fadd.d EM1B6(%pc),%fp1 # fp1 is B6+S*...
7554
7555 fmul.x %fp0,%fp2 # fp2 is S*(B7+...
7556 fmul.x %fp0,%fp1 # fp1 is S*(B6+...
7557
7558 fadd.d EM1B5(%pc),%fp2 # fp2 is B5+S*...
7559 fadd.d EM1B4(%pc),%fp1 # fp1 is B4+S*...
7560
7561 fmul.x %fp0,%fp2 # fp2 is S*(B5+...
7562 fmul.x %fp0,%fp1 # fp1 is S*(B4+...
7563
7564 fadd.d EM1B3(%pc),%fp2 # fp2 is B3+S*...
7565 fadd.x EM1B2(%pc),%fp1 # fp1 is B2+S*...
7566
7567 fmul.x %fp0,%fp2 # fp2 is S*(B3+...
7568 fmul.x %fp0,%fp1 # fp1 is S*(B2+...
7569
7570 fmul.x %fp0,%fp2 # fp2 is S*S*(B3+...)
7571 fmul.x (%a0),%fp1 # fp1 is X*S*(B2...
7572
7573 fmul.s &0x3F000000,%fp0 # fp0 is S*B1
7574 fadd.x %fp2,%fp1 # fp1 is Q
7575
7576 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7577
7578 fadd.x %fp1,%fp0 # fp0 is S*B1+Q
7579
7580 fmov.l %d0,%fpcr
7581 fadd.x (%a0),%fp0
7582 bra t_inx2
7583
7584EM1BIG:
7585#--Step 10 |X| > 70 log2
7586 mov.l (%a0),%d1
7587 cmp.l %d1,&0
7588 bgt.w EXPC1
7589#--Step 10.2
7590 fmov.s &0xBF800000,%fp0 # fp0 is -1
7591 fmov.l %d0,%fpcr
7592 fadd.s &0x00800000,%fp0 # -1 + 2^(-126)
7593 bra t_minx2
7594
7595 global setoxm1d
7596setoxm1d:
7597#--entry point for EXPM1(X), here X is denormalized
7598#--Step 0.
7599 bra t_extdnrm
7600
7601#########################################################################
7602# sgetexp(): returns the exponent portion of the input argument. #
7603# The exponent bias is removed and the exponent value is #
7604# returned as an extended precision number in fp0. #
7605# sgetexpd(): handles denormalized numbers. #
7606# #
7607# sgetman(): extracts the mantissa of the input argument. The #
7608# mantissa is converted to an extended precision number w/ #
7609# an exponent of $3fff and is returned in fp0. The range of #
7610# the result is [1.0 - 2.0). #
7611# sgetmand(): handles denormalized numbers. #
7612# #
7613# INPUT *************************************************************** #
7614# a0 = pointer to extended precision input #
7615# #
7616# OUTPUT ************************************************************** #
7617# fp0 = exponent(X) or mantissa(X) #
7618# #
7619#########################################################################
7620
7621 global sgetexp
7622sgetexp:
7623 mov.w SRC_EX(%a0),%d0 # get the exponent
7624 bclr &0xf,%d0 # clear the sign bit
7625 subi.w &0x3fff,%d0 # subtract off the bias
7626 fmov.w %d0,%fp0 # return exp in fp0
7627 blt.b sgetexpn # it's negative
7628 rts
7629
7630sgetexpn:
7631 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7632 rts
7633
7634 global sgetexpd
7635sgetexpd:
7636 bsr.l norm # normalize
7637 neg.w %d0 # new exp = -(shft amt)
7638 subi.w &0x3fff,%d0 # subtract off the bias
7639 fmov.w %d0,%fp0 # return exp in fp0
7640 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7641 rts
7642
7643 global sgetman
7644sgetman:
7645 mov.w SRC_EX(%a0),%d0 # get the exp
7646 ori.w &0x7fff,%d0 # clear old exp
7647 bclr &0xe,%d0 # make it the new exp +-3fff
7648
7649# here, we build the result in a tmp location so as not to disturb the input
7650 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
7651 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
7652 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
7653 fmov.x FP_SCR0(%a6),%fp0 # put new value back in fp0
7654 bmi.b sgetmann # it's negative
7655 rts
7656
7657sgetmann:
7658 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7659 rts
7660
7661#
7662# For denormalized numbers, shift the mantissa until the j-bit = 1,
7663# then load the exponent with +/1 $3fff.
7664#
7665 global sgetmand
7666sgetmand:
7667 bsr.l norm # normalize exponent
7668 bra.b sgetman
7669
7670#########################################################################
7671# scosh(): computes the hyperbolic cosine of a normalized input #
7672# scoshd(): computes the hyperbolic cosine of a denormalized input #
7673# #
7674# INPUT *************************************************************** #
7675# a0 = pointer to extended precision input #
7676# d0 = round precision,mode #
7677# #
7678# OUTPUT ************************************************************** #
7679# fp0 = cosh(X) #
7680# #
7681# ACCURACY and MONOTONICITY ******************************************* #
7682# The returned result is within 3 ulps in 64 significant bit, #
7683# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7684# rounded to double precision. The result is provably monotonic #
7685# in double precision. #
7686# #
7687# ALGORITHM *********************************************************** #
7688# #
7689# COSH #
7690# 1. If |X| > 16380 log2, go to 3. #
7691# #
7692# 2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae #
7693# y = |X|, z = exp(Y), and #
7694# cosh(X) = (1/2)*( z + 1/z ). #
7695# Exit. #
7696# #
7697# 3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5. #
7698# #
7699# 4. (16380 log2 < |X| <= 16480 log2) #
7700# cosh(X) = sign(X) * exp(|X|)/2. #
7701# However, invoking exp(|X|) may cause premature #
7702# overflow. Thus, we calculate sinh(X) as follows: #
7703# Y := |X| #
7704# Fact := 2**(16380) #
7705# Y' := Y - 16381 log2 #
7706# cosh(X) := Fact * exp(Y'). #
7707# Exit. #
7708# #
7709# 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
7710# Huge*Huge to generate overflow and an infinity with #
7711# the appropriate sign. Huge is the largest finite number #
7712# in extended format. Exit. #
7713# #
7714#########################################################################
7715
7716TWO16380:
7717 long 0x7FFB0000,0x80000000,0x00000000,0x00000000
7718
7719 global scosh
7720scosh:
7721 fmov.x (%a0),%fp0 # LOAD INPUT
7722
7723 mov.l (%a0),%d1
7724 mov.w 4(%a0),%d1
7725 and.l &0x7FFFFFFF,%d1
7726 cmp.l %d1,&0x400CB167
7727 bgt.b COSHBIG
7728
7729#--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7730#--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
7731
7732 fabs.x %fp0 # |X|
7733
7734 mov.l %d0,-(%sp)
7735 clr.l %d0
7736 fmovm.x &0x01,-(%sp) # save |X| to stack
7737 lea (%sp),%a0 # pass ptr to |X|
7738 bsr setox # FP0 IS EXP(|X|)
7739 add.l &0xc,%sp # erase |X| from stack
7740 fmul.s &0x3F000000,%fp0 # (1/2)EXP(|X|)
7741 mov.l (%sp)+,%d0
7742
7743 fmov.s &0x3E800000,%fp1 # (1/4)
7744 fdiv.x %fp0,%fp1 # 1/(2 EXP(|X|))
7745
7746 fmov.l %d0,%fpcr
7747 mov.b &FADD_OP,%d1 # last inst is ADD
7748 fadd.x %fp1,%fp0
7749 bra t_catch
7750
7751COSHBIG:
7752 cmp.l %d1,&0x400CB2B3
7753 bgt.b COSHHUGE
7754
7755 fabs.x %fp0
7756 fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
7757 fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
7758
7759 mov.l %d0,-(%sp)
7760 clr.l %d0
7761 fmovm.x &0x01,-(%sp) # save fp0 to stack
7762 lea (%sp),%a0 # pass ptr to fp0
7763 bsr setox
7764 add.l &0xc,%sp # clear fp0 from stack
7765 mov.l (%sp)+,%d0
7766
7767 fmov.l %d0,%fpcr
7768 mov.b &FMUL_OP,%d1 # last inst is MUL
7769 fmul.x TWO16380(%pc),%fp0
7770 bra t_catch
7771
7772COSHHUGE:
7773 bra t_ovfl2
7774
7775 global scoshd
7776#--COSH(X) = 1 FOR DENORMALIZED X
7777scoshd:
7778 fmov.s &0x3F800000,%fp0
7779
7780 fmov.l %d0,%fpcr
7781 fadd.s &0x00800000,%fp0
7782 bra t_pinx2
7783
7784#########################################################################
7785# ssinh(): computes the hyperbolic sine of a normalized input #
7786# ssinhd(): computes the hyperbolic sine of a denormalized input #
7787# #
7788# INPUT *************************************************************** #
7789# a0 = pointer to extended precision input #
7790# d0 = round precision,mode #
7791# #
7792# OUTPUT ************************************************************** #
7793# fp0 = sinh(X) #
7794# #
7795# ACCURACY and MONOTONICITY ******************************************* #
7796# The returned result is within 3 ulps in 64 significant bit, #
7797# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7798# rounded to double precision. The result is provably monotonic #
7799# in double precision. #
7800# #
7801# ALGORITHM *********************************************************** #
7802# #
7803# SINH #
7804# 1. If |X| > 16380 log2, go to 3. #
7805# #
7806# 2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula #
7807# y = |X|, sgn = sign(X), and z = expm1(Y), #
7808# sinh(X) = sgn*(1/2)*( z + z/(1+z) ). #
7809# Exit. #
7810# #
7811# 3. If |X| > 16480 log2, go to 5. #
7812# #
7813# 4. (16380 log2 < |X| <= 16480 log2) #
7814# sinh(X) = sign(X) * exp(|X|)/2. #
7815# However, invoking exp(|X|) may cause premature overflow. #
7816# Thus, we calculate sinh(X) as follows: #
7817# Y := |X| #
7818# sgn := sign(X) #
7819# sgnFact := sgn * 2**(16380) #
7820# Y' := Y - 16381 log2 #
7821# sinh(X) := sgnFact * exp(Y'). #
7822# Exit. #
7823# #
7824# 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
7825# sign(X)*Huge*Huge to generate overflow and an infinity with #
7826# the appropriate sign. Huge is the largest finite number in #
7827# extended format. Exit. #
7828# #
7829#########################################################################
7830
7831 global ssinh
7832ssinh:
7833 fmov.x (%a0),%fp0 # LOAD INPUT
7834
7835 mov.l (%a0),%d1
7836 mov.w 4(%a0),%d1
7837 mov.l %d1,%a1 # save (compacted) operand
7838 and.l &0x7FFFFFFF,%d1
7839 cmp.l %d1,&0x400CB167
7840 bgt.b SINHBIG
7841
7842#--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7843#--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
7844
7845 fabs.x %fp0 # Y = |X|
7846
7847 movm.l &0x8040,-(%sp) # {a1/d0}
7848 fmovm.x &0x01,-(%sp) # save Y on stack
7849 lea (%sp),%a0 # pass ptr to Y
7850 clr.l %d0
7851 bsr setoxm1 # FP0 IS Z = EXPM1(Y)
7852 add.l &0xc,%sp # clear Y from stack
7853 fmov.l &0,%fpcr
7854 movm.l (%sp)+,&0x0201 # {a1/d0}
7855
7856 fmov.x %fp0,%fp1
7857 fadd.s &0x3F800000,%fp1 # 1+Z
7858 fmov.x %fp0,-(%sp)
7859 fdiv.x %fp1,%fp0 # Z/(1+Z)
7860 mov.l %a1,%d1
7861 and.l &0x80000000,%d1
7862 or.l &0x3F000000,%d1
7863 fadd.x (%sp)+,%fp0
7864 mov.l %d1,-(%sp)
7865
7866 fmov.l %d0,%fpcr
7867 mov.b &FMUL_OP,%d1 # last inst is MUL
7868 fmul.s (%sp)+,%fp0 # last fp inst - possible exceptions set
7869 bra t_catch
7870
7871SINHBIG:
7872 cmp.l %d1,&0x400CB2B3
7873 bgt t_ovfl
7874 fabs.x %fp0
7875 fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
7876 mov.l &0,-(%sp)
7877 mov.l &0x80000000,-(%sp)
7878 mov.l %a1,%d1
7879 and.l &0x80000000,%d1
7880 or.l &0x7FFB0000,%d1
7881 mov.l %d1,-(%sp) # EXTENDED FMT
7882 fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
7883
7884 mov.l %d0,-(%sp)
7885 clr.l %d0
7886 fmovm.x &0x01,-(%sp) # save fp0 on stack
7887 lea (%sp),%a0 # pass ptr to fp0
7888 bsr setox
7889 add.l &0xc,%sp # clear fp0 from stack
7890
7891 mov.l (%sp)+,%d0
7892 fmov.l %d0,%fpcr
7893 mov.b &FMUL_OP,%d1 # last inst is MUL
7894 fmul.x (%sp)+,%fp0 # possible exception
7895 bra t_catch
7896
7897 global ssinhd
7898#--SINH(X) = X FOR DENORMALIZED X
7899ssinhd:
7900 bra t_extdnrm
7901
7902#########################################################################
7903# stanh(): computes the hyperbolic tangent of a normalized input #
7904# stanhd(): computes the hyperbolic tangent of a denormalized input #
7905# #
7906# INPUT *************************************************************** #
7907# a0 = pointer to extended precision input #
7908# d0 = round precision,mode #
7909# #
7910# OUTPUT ************************************************************** #
7911# fp0 = tanh(X) #
7912# #
7913# ACCURACY and MONOTONICITY ******************************************* #
7914# The returned result is within 3 ulps in 64 significant bit, #
7915# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7916# rounded to double precision. The result is provably monotonic #
7917# in double precision. #
7918# #
7919# ALGORITHM *********************************************************** #
7920# #
7921# TANH #
7922# 1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3. #
7923# #
7924# 2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by #
7925# sgn := sign(X), y := 2|X|, z := expm1(Y), and #
7926# tanh(X) = sgn*( z/(2+z) ). #
7927# Exit. #
7928# #
7929# 3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1, #
7930# go to 7. #
7931# #
7932# 4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6. #
7933# #
7934# 5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by #
7935# sgn := sign(X), y := 2|X|, z := exp(Y), #
7936# tanh(X) = sgn - [ sgn*2/(1+z) ]. #
7937# Exit. #
7938# #
7939# 6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we #
7940# calculate Tanh(X) by #
7941# sgn := sign(X), Tiny := 2**(-126), #
7942# tanh(X) := sgn - sgn*Tiny. #
7943# Exit. #
7944# #
7945# 7. (|X| < 2**(-40)). Tanh(X) = X. Exit. #
7946# #
7947#########################################################################
7948
7949 set X,FP_SCR0
7950 set XFRAC,X+4
7951
7952 set SGN,L_SCR3
7953
7954 set V,FP_SCR0
7955
7956 global stanh
7957stanh:
7958 fmov.x (%a0),%fp0 # LOAD INPUT
7959
7960 fmov.x %fp0,X(%a6)
7961 mov.l (%a0),%d1
7962 mov.w 4(%a0),%d1
7963 mov.l %d1,X(%a6)
7964 and.l &0x7FFFFFFF,%d1
7965 cmp.l %d1, &0x3fd78000 # is |X| < 2^(-40)?
7966 blt.w TANHBORS # yes
7967 cmp.l %d1, &0x3fffddce # is |X| > (5/2)LOG2?
7968 bgt.w TANHBORS # yes
7969
7970#--THIS IS THE USUAL CASE
7971#--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
7972
7973 mov.l X(%a6),%d1
7974 mov.l %d1,SGN(%a6)
7975 and.l &0x7FFF0000,%d1
7976 add.l &0x00010000,%d1 # EXPONENT OF 2|X|
7977 mov.l %d1,X(%a6)
7978 and.l &0x80000000,SGN(%a6)
7979 fmov.x X(%a6),%fp0 # FP0 IS Y = 2|X|
7980
7981 mov.l %d0,-(%sp)
7982 clr.l %d0
7983 fmovm.x &0x1,-(%sp) # save Y on stack
7984 lea (%sp),%a0 # pass ptr to Y
7985 bsr setoxm1 # FP0 IS Z = EXPM1(Y)
7986 add.l &0xc,%sp # clear Y from stack
7987 mov.l (%sp)+,%d0
7988
7989 fmov.x %fp0,%fp1
7990 fadd.s &0x40000000,%fp1 # Z+2
7991 mov.l SGN(%a6),%d1
7992 fmov.x %fp1,V(%a6)
7993 eor.l %d1,V(%a6)
7994
7995 fmov.l %d0,%fpcr # restore users round prec,mode
7996 fdiv.x V(%a6),%fp0
7997 bra t_inx2
7998
7999TANHBORS:
8000 cmp.l %d1,&0x3FFF8000
8001 blt.w TANHSM
8002
8003 cmp.l %d1,&0x40048AA1
8004 bgt.w TANHHUGE
8005
8006#-- (5/2) LOG2 < |X| < 50 LOG2,
8007#--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
8008#--TANH(X) = SGN - SGN*2/[EXP(Y)+1].
8009
8010 mov.l X(%a6),%d1
8011 mov.l %d1,SGN(%a6)
8012 and.l &0x7FFF0000,%d1
8013 add.l &0x00010000,%d1 # EXPO OF 2|X|
8014 mov.l %d1,X(%a6) # Y = 2|X|
8015 and.l &0x80000000,SGN(%a6)
8016 mov.l SGN(%a6),%d1
8017 fmov.x X(%a6),%fp0 # Y = 2|X|
8018
8019 mov.l %d0,-(%sp)
8020 clr.l %d0
8021 fmovm.x &0x01,-(%sp) # save Y on stack
8022 lea (%sp),%a0 # pass ptr to Y
8023 bsr setox # FP0 IS EXP(Y)
8024 add.l &0xc,%sp # clear Y from stack
8025 mov.l (%sp)+,%d0
8026 mov.l SGN(%a6),%d1
8027 fadd.s &0x3F800000,%fp0 # EXP(Y)+1
8028
8029 eor.l &0xC0000000,%d1 # -SIGN(X)*2
8030 fmov.s %d1,%fp1 # -SIGN(X)*2 IN SGL FMT
8031 fdiv.x %fp0,%fp1 # -SIGN(X)2 / [EXP(Y)+1 ]
8032
8033 mov.l SGN(%a6),%d1
8034 or.l &0x3F800000,%d1 # SGN
8035 fmov.s %d1,%fp0 # SGN IN SGL FMT
8036
8037 fmov.l %d0,%fpcr # restore users round prec,mode
8038 mov.b &FADD_OP,%d1 # last inst is ADD
8039 fadd.x %fp1,%fp0
8040 bra t_inx2
8041
8042TANHSM:
8043 fmov.l %d0,%fpcr # restore users round prec,mode
8044 mov.b &FMOV_OP,%d1 # last inst is MOVE
8045 fmov.x X(%a6),%fp0 # last inst - possible exception set
8046 bra t_catch
8047
8048#---RETURN SGN(X) - SGN(X)EPS
8049TANHHUGE:
8050 mov.l X(%a6),%d1
8051 and.l &0x80000000,%d1
8052 or.l &0x3F800000,%d1
8053 fmov.s %d1,%fp0
8054 and.l &0x80000000,%d1
8055 eor.l &0x80800000,%d1 # -SIGN(X)*EPS
8056
8057 fmov.l %d0,%fpcr # restore users round prec,mode
8058 fadd.s %d1,%fp0
8059 bra t_inx2
8060
8061 global stanhd
8062#--TANH(X) = X FOR DENORMALIZED X
8063stanhd:
8064 bra t_extdnrm
8065
8066#########################################################################
8067# slogn(): computes the natural logarithm of a normalized input #
8068# slognd(): computes the natural logarithm of a denormalized input #
8069# slognp1(): computes the log(1+X) of a normalized input #
8070# slognp1d(): computes the log(1+X) of a denormalized input #
8071# #
8072# INPUT *************************************************************** #
8073# a0 = pointer to extended precision input #
8074# d0 = round precision,mode #
8075# #
8076# OUTPUT ************************************************************** #
8077# fp0 = log(X) or log(1+X) #
8078# #
8079# ACCURACY and MONOTONICITY ******************************************* #
8080# The returned result is within 2 ulps in 64 significant bit, #
8081# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8082# rounded to double precision. The result is provably monotonic #
8083# in double precision. #
8084# #
8085# ALGORITHM *********************************************************** #
8086# LOGN: #
8087# Step 1. If |X-1| < 1/16, approximate log(X) by an odd #
8088# polynomial in u, where u = 2(X-1)/(X+1). Otherwise, #
8089# move on to Step 2. #
8090# #
8091# Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #
8092# seven significant bits of Y plus 2**(-7), i.e. #
8093# F = 1.xxxxxx1 in base 2 where the six "x" match those #
8094# of Y. Note that |Y-F| <= 2**(-7). #
8095# #
8096# Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a #
8097# polynomial in u, log(1+u) = poly. #
8098# #
8099# Step 4. Reconstruct #
8100# log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #
8101# by k*log(2) + (log(F) + poly). The values of log(F) are #
8102# calculated beforehand and stored in the program. #
8103# #
8104# lognp1: #
8105# Step 1: If |X| < 1/16, approximate log(1+X) by an odd #
8106# polynomial in u where u = 2X/(2+X). Otherwise, move on #
8107# to Step 2. #
8108# #
8109# Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done #
8110# in Step 2 of the algorithm for LOGN and compute #
8111# log(1+X) as k*log(2) + log(F) + poly where poly #
8112# approximates log(1+u), u = (Y-F)/F. #
8113# #
8114# Implementation Notes: #
8115# Note 1. There are 64 different possible values for F, thus 64 #
8116# log(F)'s need to be tabulated. Moreover, the values of #
8117# 1/F are also tabulated so that the division in (Y-F)/F #
8118# can be performed by a multiplication. #
8119# #
8120# Note 2. In Step 2 of lognp1, in order to preserved accuracy, #
8121# the value Y-F has to be calculated carefully when #
8122# 1/2 <= X < 3/2. #
8123# #
8124# Note 3. To fully exploit the pipeline, polynomials are usually #
8125# separated into two parts evaluated independently before #
8126# being added up. #
8127# #
8128#########################################################################
8129LOGOF2:
8130 long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8131
8132one:
8133 long 0x3F800000
8134zero:
8135 long 0x00000000
8136infty:
8137 long 0x7F800000
8138negone:
8139 long 0xBF800000
8140
8141LOGA6:
8142 long 0x3FC2499A,0xB5E4040B
8143LOGA5:
8144 long 0xBFC555B5,0x848CB7DB
8145
8146LOGA4:
8147 long 0x3FC99999,0x987D8730
8148LOGA3:
8149 long 0xBFCFFFFF,0xFF6F7E97
8150
8151LOGA2:
8152 long 0x3FD55555,0x555555A4
8153LOGA1:
8154 long 0xBFE00000,0x00000008
8155
8156LOGB5:
8157 long 0x3F175496,0xADD7DAD6
8158LOGB4:
8159 long 0x3F3C71C2,0xFE80C7E0
8160
8161LOGB3:
8162 long 0x3F624924,0x928BCCFF
8163LOGB2:
8164 long 0x3F899999,0x999995EC
8165
8166LOGB1:
8167 long 0x3FB55555,0x55555555
8168TWO:
8169 long 0x40000000,0x00000000
8170
8171LTHOLD:
8172 long 0x3f990000,0x80000000,0x00000000,0x00000000
8173
8174LOGTBL:
8175 long 0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
8176 long 0x3FF70000,0xFF015358,0x833C47E2,0x00000000
8177 long 0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
8178 long 0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
8179 long 0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
8180 long 0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
8181 long 0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
8182 long 0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
8183 long 0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
8184 long 0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
8185 long 0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
8186 long 0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
8187 long 0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
8188 long 0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
8189 long 0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
8190 long 0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
8191 long 0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
8192 long 0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
8193 long 0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
8194 long 0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
8195 long 0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
8196 long 0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
8197 long 0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
8198 long 0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
8199 long 0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
8200 long 0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
8201 long 0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
8202 long 0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
8203 long 0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
8204 long 0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
8205 long 0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
8206 long 0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
8207 long 0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
8208 long 0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
8209 long 0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
8210 long 0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
8211 long 0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
8212 long 0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
8213 long 0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
8214 long 0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
8215 long 0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
8216 long 0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
8217 long 0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
8218 long 0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
8219 long 0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
8220 long 0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
8221 long 0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
8222 long 0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
8223 long 0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
8224 long 0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
8225 long 0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
8226 long 0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
8227 long 0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
8228 long 0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
8229 long 0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
8230 long 0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
8231 long 0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
8232 long 0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
8233 long 0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
8234 long 0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
8235 long 0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
8236 long 0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
8237 long 0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
8238 long 0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
8239 long 0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
8240 long 0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
8241 long 0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
8242 long 0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
8243 long 0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
8244 long 0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
8245 long 0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
8246 long 0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
8247 long 0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
8248 long 0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
8249 long 0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
8250 long 0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
8251 long 0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
8252 long 0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
8253 long 0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
8254 long 0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
8255 long 0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
8256 long 0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
8257 long 0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
8258 long 0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
8259 long 0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
8260 long 0x3FFE0000,0x825EFCED,0x49369330,0x00000000
8261 long 0x3FFE0000,0x9868C809,0x868C8098,0x00000000
8262 long 0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
8263 long 0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
8264 long 0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
8265 long 0x3FFE0000,0x95A02568,0x095A0257,0x00000000
8266 long 0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
8267 long 0x3FFE0000,0x94458094,0x45809446,0x00000000
8268 long 0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
8269 long 0x3FFE0000,0x92F11384,0x0497889C,0x00000000
8270 long 0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
8271 long 0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
8272 long 0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
8273 long 0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
8274 long 0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
8275 long 0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
8276 long 0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
8277 long 0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
8278 long 0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
8279 long 0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
8280 long 0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
8281 long 0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
8282 long 0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
8283 long 0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
8284 long 0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
8285 long 0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
8286 long 0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
8287 long 0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
8288 long 0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
8289 long 0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
8290 long 0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
8291 long 0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
8292 long 0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
8293 long 0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
8294 long 0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
8295 long 0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
8296 long 0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
8297 long 0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
8298 long 0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
8299 long 0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
8300 long 0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
8301 long 0x3FFE0000,0x80808080,0x80808081,0x00000000
8302 long 0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
8303
8304 set ADJK,L_SCR1
8305
8306 set X,FP_SCR0
8307 set XDCARE,X+2
8308 set XFRAC,X+4
8309
8310 set F,FP_SCR1
8311 set FFRAC,F+4
8312
8313 set KLOG2,FP_SCR0
8314
8315 set SAVEU,FP_SCR0
8316
8317 global slogn
8318#--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
8319slogn:
8320 fmov.x (%a0),%fp0 # LOAD INPUT
8321 mov.l &0x00000000,ADJK(%a6)
8322
8323LOGBGN:
8324#--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
8325#--A FINITE, NON-ZERO, NORMALIZED NUMBER.
8326
8327 mov.l (%a0),%d1
8328 mov.w 4(%a0),%d1
8329
8330 mov.l (%a0),X(%a6)
8331 mov.l 4(%a0),X+4(%a6)
8332 mov.l 8(%a0),X+8(%a6)
8333
8334 cmp.l %d1,&0 # CHECK IF X IS NEGATIVE
8335 blt.w LOGNEG # LOG OF NEGATIVE ARGUMENT IS INVALID
8336# X IS POSITIVE, CHECK IF X IS NEAR 1
8337 cmp.l %d1,&0x3ffef07d # IS X < 15/16?
8338 blt.b LOGMAIN # YES
8339 cmp.l %d1,&0x3fff8841 # IS X > 17/16?
8340 ble.w LOGNEAR1 # NO
8341
8342LOGMAIN:
8343#--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
8344
8345#--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
8346#--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
8347#--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
8348#-- = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
8349#--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
8350#--LOG(1+U) CAN BE VERY EFFICIENT.
8351#--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
8352#--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
8353
8354#--GET K, Y, F, AND ADDRESS OF 1/F.
8355 asr.l &8,%d1
8356 asr.l &8,%d1 # SHIFTED 16 BITS, BIASED EXPO. OF X
8357 sub.l &0x3FFF,%d1 # THIS IS K
8358 add.l ADJK(%a6),%d1 # ADJUST K, ORIGINAL INPUT MAY BE DENORM.
8359 lea LOGTBL(%pc),%a0 # BASE ADDRESS OF 1/F AND LOG(F)
8360 fmov.l %d1,%fp1 # CONVERT K TO FLOATING-POINT FORMAT
8361
8362#--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
8363 mov.l &0x3FFF0000,X(%a6) # X IS NOW Y, I.E. 2^(-K)*X
8364 mov.l XFRAC(%a6),FFRAC(%a6)
8365 and.l &0xFE000000,FFRAC(%a6) # FIRST 7 BITS OF Y
8366 or.l &0x01000000,FFRAC(%a6) # GET F: ATTACH A 1 AT THE EIGHTH BIT
8367 mov.l FFRAC(%a6),%d1 # READY TO GET ADDRESS OF 1/F
8368 and.l &0x7E000000,%d1
8369 asr.l &8,%d1
8370 asr.l &8,%d1
8371 asr.l &4,%d1 # SHIFTED 20, D0 IS THE DISPLACEMENT
8372 add.l %d1,%a0 # A0 IS THE ADDRESS FOR 1/F
8373
8374 fmov.x X(%a6),%fp0
8375 mov.l &0x3fff0000,F(%a6)
8376 clr.l F+8(%a6)
8377 fsub.x F(%a6),%fp0 # Y-F
8378 fmovm.x &0xc,-(%sp) # SAVE FP2-3 WHILE FP0 IS NOT READY
8379#--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
8380#--REGISTERS SAVED: FPCR, FP1, FP2
8381
8382LP1CONT1:
8383#--AN RE-ENTRY POINT FOR LOGNP1
8384 fmul.x (%a0),%fp0 # FP0 IS U = (Y-F)/F
8385 fmul.x LOGOF2(%pc),%fp1 # GET K*LOG2 WHILE FP0 IS NOT READY
8386 fmov.x %fp0,%fp2
8387 fmul.x %fp2,%fp2 # FP2 IS V=U*U
8388 fmov.x %fp1,KLOG2(%a6) # PUT K*LOG2 IN MEMEORY, FREE FP1
8389
8390#--LOG(1+U) IS APPROXIMATED BY
8391#--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
8392#--[U + V*(A1+V*(A3+V*A5))] + [U*V*(A2+V*(A4+V*A6))]
8393
8394 fmov.x %fp2,%fp3
8395 fmov.x %fp2,%fp1
8396
8397 fmul.d LOGA6(%pc),%fp1 # V*A6
8398 fmul.d LOGA5(%pc),%fp2 # V*A5
8399
8400 fadd.d LOGA4(%pc),%fp1 # A4+V*A6
8401 fadd.d LOGA3(%pc),%fp2 # A3+V*A5
8402
8403 fmul.x %fp3,%fp1 # V*(A4+V*A6)
8404 fmul.x %fp3,%fp2 # V*(A3+V*A5)
8405
8406 fadd.d LOGA2(%pc),%fp1 # A2+V*(A4+V*A6)
8407 fadd.d LOGA1(%pc),%fp2 # A1+V*(A3+V*A5)
8408
8409 fmul.x %fp3,%fp1 # V*(A2+V*(A4+V*A6))
8410 add.l &16,%a0 # ADDRESS OF LOG(F)
8411 fmul.x %fp3,%fp2 # V*(A1+V*(A3+V*A5))
8412
8413 fmul.x %fp0,%fp1 # U*V*(A2+V*(A4+V*A6))
8414 fadd.x %fp2,%fp0 # U+V*(A1+V*(A3+V*A5))
8415
8416 fadd.x (%a0),%fp1 # LOG(F)+U*V*(A2+V*(A4+V*A6))
8417 fmovm.x (%sp)+,&0x30 # RESTORE FP2-3
8418 fadd.x %fp1,%fp0 # FP0 IS LOG(F) + LOG(1+U)
8419
8420 fmov.l %d0,%fpcr
8421 fadd.x KLOG2(%a6),%fp0 # FINAL ADD
8422 bra t_inx2
8423
8424
8425LOGNEAR1:
8426
8427# if the input is exactly equal to one, then exit through ld_pzero.
8428# if these 2 lines weren't here, the correct answer would be returned
8429# but the INEX2 bit would be set.
8430 fcmp.b %fp0,&0x1 # is it equal to one?
8431 fbeq.l ld_pzero # yes
8432
8433#--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
8434 fmov.x %fp0,%fp1
8435 fsub.s one(%pc),%fp1 # FP1 IS X-1
8436 fadd.s one(%pc),%fp0 # FP0 IS X+1
8437 fadd.x %fp1,%fp1 # FP1 IS 2(X-1)
8438#--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
8439#--IN U, U = 2(X-1)/(X+1) = FP1/FP0
8440
8441LP1CONT2:
8442#--THIS IS AN RE-ENTRY POINT FOR LOGNP1
8443 fdiv.x %fp0,%fp1 # FP1 IS U
8444 fmovm.x &0xc,-(%sp) # SAVE FP2-3
8445#--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
8446#--LET V=U*U, W=V*V, CALCULATE
8447#--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
8448#--U + U*V*( [B1 + W*(B3 + W*B5)] + [V*(B2 + W*B4)] )
8449 fmov.x %fp1,%fp0
8450 fmul.x %fp0,%fp0 # FP0 IS V
8451 fmov.x %fp1,SAVEU(%a6) # STORE U IN MEMORY, FREE FP1
8452 fmov.x %fp0,%fp1
8453 fmul.x %fp1,%fp1 # FP1 IS W
8454
8455 fmov.d LOGB5(%pc),%fp3
8456 fmov.d LOGB4(%pc),%fp2
8457
8458 fmul.x %fp1,%fp3 # W*B5
8459 fmul.x %fp1,%fp2 # W*B4
8460
8461 fadd.d LOGB3(%pc),%fp3 # B3+W*B5
8462 fadd.d LOGB2(%pc),%fp2 # B2+W*B4
8463
8464 fmul.x %fp3,%fp1 # W*(B3+W*B5), FP3 RELEASED
8465
8466 fmul.x %fp0,%fp2 # V*(B2+W*B4)
8467
8468 fadd.d LOGB1(%pc),%fp1 # B1+W*(B3+W*B5)
8469 fmul.x SAVEU(%a6),%fp0 # FP0 IS U*V
8470
8471 fadd.x %fp2,%fp1 # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
8472 fmovm.x (%sp)+,&0x30 # FP2-3 RESTORED
8473
8474 fmul.x %fp1,%fp0 # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
8475
8476 fmov.l %d0,%fpcr
8477 fadd.x SAVEU(%a6),%fp0
8478 bra t_inx2
8479
8480#--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
8481LOGNEG:
8482 bra t_operr
8483
8484 global slognd
8485slognd:
8486#--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
8487
8488 mov.l &-100,ADJK(%a6) # INPUT = 2^(ADJK) * FP0
8489
8490#----normalize the input value by left shifting k bits (k to be determined
8491#----below), adjusting exponent and storing -k to ADJK
8492#----the value TWOTO100 is no longer needed.
8493#----Note that this code assumes the denormalized input is NON-ZERO.
8494
8495 movm.l &0x3f00,-(%sp) # save some registers {d2-d7}
8496 mov.l (%a0),%d3 # D3 is exponent of smallest norm. #
8497 mov.l 4(%a0),%d4
8498 mov.l 8(%a0),%d5 # (D4,D5) is (Hi_X,Lo_X)
8499 clr.l %d2 # D2 used for holding K
8500
8501 tst.l %d4
8502 bne.b Hi_not0
8503
8504Hi_0:
8505 mov.l %d5,%d4
8506 clr.l %d5
8507 mov.l &32,%d2
8508 clr.l %d6
8509 bfffo %d4{&0:&32},%d6
8510 lsl.l %d6,%d4
8511 add.l %d6,%d2 # (D3,D4,D5) is normalized
8512
8513 mov.l %d3,X(%a6)
8514 mov.l %d4,XFRAC(%a6)
8515 mov.l %d5,XFRAC+4(%a6)
8516 neg.l %d2
8517 mov.l %d2,ADJK(%a6)
8518 fmov.x X(%a6),%fp0
8519 movm.l (%sp)+,&0xfc # restore registers {d2-d7}
8520 lea X(%a6),%a0
8521 bra.w LOGBGN # begin regular log(X)
8522
8523Hi_not0:
8524 clr.l %d6
8525 bfffo %d4{&0:&32},%d6 # find first 1
8526 mov.l %d6,%d2 # get k
8527 lsl.l %d6,%d4
8528 mov.l %d5,%d7 # a copy of D5
8529 lsl.l %d6,%d5
8530 neg.l %d6
8531 add.l &32,%d6
8532 lsr.l %d6,%d7
8533 or.l %d7,%d4 # (D3,D4,D5) normalized
8534
8535 mov.l %d3,X(%a6)
8536 mov.l %d4,XFRAC(%a6)
8537 mov.l %d5,XFRAC+4(%a6)
8538 neg.l %d2
8539 mov.l %d2,ADJK(%a6)
8540 fmov.x X(%a6),%fp0
8541 movm.l (%sp)+,&0xfc # restore registers {d2-d7}
8542 lea X(%a6),%a0
8543 bra.w LOGBGN # begin regular log(X)
8544
8545 global slognp1
8546#--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
8547slognp1:
8548 fmov.x (%a0),%fp0 # LOAD INPUT
8549 fabs.x %fp0 # test magnitude
8550 fcmp.x %fp0,LTHOLD(%pc) # compare with min threshold
8551 fbgt.w LP1REAL # if greater, continue
8552 fmov.l %d0,%fpcr
8553 mov.b &FMOV_OP,%d1 # last inst is MOVE
8554 fmov.x (%a0),%fp0 # return signed argument
8555 bra t_catch
8556
8557LP1REAL:
8558 fmov.x (%a0),%fp0 # LOAD INPUT
8559 mov.l &0x00000000,ADJK(%a6)
8560 fmov.x %fp0,%fp1 # FP1 IS INPUT Z
8561 fadd.s one(%pc),%fp0 # X := ROUND(1+Z)
8562 fmov.x %fp0,X(%a6)
8563 mov.w XFRAC(%a6),XDCARE(%a6)
8564 mov.l X(%a6),%d1
8565 cmp.l %d1,&0
8566 ble.w LP1NEG0 # LOG OF ZERO OR -VE
8567 cmp.l %d1,&0x3ffe8000 # IS BOUNDS [1/2,3/2]?
8568 blt.w LOGMAIN
8569 cmp.l %d1,&0x3fffc000
8570 bgt.w LOGMAIN
8571#--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
8572#--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
8573#--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
8574
8575LP1NEAR1:
8576#--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
8577 cmp.l %d1,&0x3ffef07d
8578 blt.w LP1CARE
8579 cmp.l %d1,&0x3fff8841
8580 bgt.w LP1CARE
8581
8582LP1ONE16:
8583#--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
8584#--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
8585 fadd.x %fp1,%fp1 # FP1 IS 2Z
8586 fadd.s one(%pc),%fp0 # FP0 IS 1+X
8587#--U = FP1/FP0
8588 bra.w LP1CONT2
8589
8590LP1CARE:
8591#--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
8592#--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
8593#--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
8594#--THERE ARE ONLY TWO CASES.
8595#--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
8596#--CASE 2: 1+Z > 1, THEN K = 0 AND Y-F = (1-F) + Z
8597#--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
8598#--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
8599
8600 mov.l XFRAC(%a6),FFRAC(%a6)
8601 and.l &0xFE000000,FFRAC(%a6)
8602 or.l &0x01000000,FFRAC(%a6) # F OBTAINED
8603 cmp.l %d1,&0x3FFF8000 # SEE IF 1+Z > 1
8604 bge.b KISZERO
8605
8606KISNEG1:
8607 fmov.s TWO(%pc),%fp0
8608 mov.l &0x3fff0000,F(%a6)
8609 clr.l F+8(%a6)
8610 fsub.x F(%a6),%fp0 # 2-F
8611 mov.l FFRAC(%a6),%d1
8612 and.l &0x7E000000,%d1
8613 asr.l &8,%d1
8614 asr.l &8,%d1
8615 asr.l &4,%d1 # D0 CONTAINS DISPLACEMENT FOR 1/F
8616 fadd.x %fp1,%fp1 # GET 2Z
8617 fmovm.x &0xc,-(%sp) # SAVE FP2 {%fp2/%fp3}
8618 fadd.x %fp1,%fp0 # FP0 IS Y-F = (2-F)+2Z
8619 lea LOGTBL(%pc),%a0 # A0 IS ADDRESS OF 1/F
8620 add.l %d1,%a0
8621 fmov.s negone(%pc),%fp1 # FP1 IS K = -1
8622 bra.w LP1CONT1
8623
8624KISZERO:
8625 fmov.s one(%pc),%fp0
8626 mov.l &0x3fff0000,F(%a6)
8627 clr.l F+8(%a6)
8628 fsub.x F(%a6),%fp0 # 1-F
8629 mov.l FFRAC(%a6),%d1
8630 and.l &0x7E000000,%d1
8631 asr.l &8,%d1
8632 asr.l &8,%d1
8633 asr.l &4,%d1
8634 fadd.x %fp1,%fp0 # FP0 IS Y-F
8635 fmovm.x &0xc,-(%sp) # FP2 SAVED {%fp2/%fp3}
8636 lea LOGTBL(%pc),%a0
8637 add.l %d1,%a0 # A0 IS ADDRESS OF 1/F
8638 fmov.s zero(%pc),%fp1 # FP1 IS K = 0
8639 bra.w LP1CONT1
8640
8641LP1NEG0:
8642#--FPCR SAVED. D0 IS X IN COMPACT FORM.
8643 cmp.l %d1,&0
8644 blt.b LP1NEG
8645LP1ZERO:
8646 fmov.s negone(%pc),%fp0
8647
8648 fmov.l %d0,%fpcr
8649 bra t_dz
8650
8651LP1NEG:
8652 fmov.s zero(%pc),%fp0
8653
8654 fmov.l %d0,%fpcr
8655 bra t_operr
8656
8657 global slognp1d
8658#--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
8659# Simply return the denorm
8660slognp1d:
8661 bra t_extdnrm
8662
8663#########################################################################
8664# satanh(): computes the inverse hyperbolic tangent of a norm input #
8665# satanhd(): computes the inverse hyperbolic tangent of a denorm input #
8666# #
8667# INPUT *************************************************************** #
8668# a0 = pointer to extended precision input #
8669# d0 = round precision,mode #
8670# #
8671# OUTPUT ************************************************************** #
8672# fp0 = arctanh(X) #
8673# #
8674# ACCURACY and MONOTONICITY ******************************************* #
8675# The returned result is within 3 ulps in 64 significant bit, #
8676# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8677# rounded to double precision. The result is provably monotonic #
8678# in double precision. #
8679# #
8680# ALGORITHM *********************************************************** #
8681# #
8682# ATANH #
8683# 1. If |X| >= 1, go to 3. #
8684# #
8685# 2. (|X| < 1) Calculate atanh(X) by #
8686# sgn := sign(X) #
8687# y := |X| #
8688# z := 2y/(1-y) #
8689# atanh(X) := sgn * (1/2) * logp1(z) #
8690# Exit. #
8691# #
8692# 3. If |X| > 1, go to 5. #
8693# #
8694# 4. (|X| = 1) Generate infinity with an appropriate sign and #
8695# divide-by-zero by #
8696# sgn := sign(X) #
8697# atan(X) := sgn / (+0). #
8698# Exit. #
8699# #
8700# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
8701# Exit. #
8702# #
8703#########################################################################
8704
8705 global satanh
8706satanh:
8707 mov.l (%a0),%d1
8708 mov.w 4(%a0),%d1
8709 and.l &0x7FFFFFFF,%d1
8710 cmp.l %d1,&0x3FFF8000
8711 bge.b ATANHBIG
8712
8713#--THIS IS THE USUAL CASE, |X| < 1
8714#--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
8715
8716 fabs.x (%a0),%fp0 # Y = |X|
8717 fmov.x %fp0,%fp1
8718 fneg.x %fp1 # -Y
8719 fadd.x %fp0,%fp0 # 2Y
8720 fadd.s &0x3F800000,%fp1 # 1-Y
8721 fdiv.x %fp1,%fp0 # 2Y/(1-Y)
8722 mov.l (%a0),%d1
8723 and.l &0x80000000,%d1
8724 or.l &0x3F000000,%d1 # SIGN(X)*HALF
8725 mov.l %d1,-(%sp)
8726
8727 mov.l %d0,-(%sp) # save rnd prec,mode
8728 clr.l %d0 # pass ext prec,RN
8729 fmovm.x &0x01,-(%sp) # save Z on stack
8730 lea (%sp),%a0 # pass ptr to Z
8731 bsr slognp1 # LOG1P(Z)
8732 add.l &0xc,%sp # clear Z from stack
8733
8734 mov.l (%sp)+,%d0 # fetch old prec,mode
8735 fmov.l %d0,%fpcr # load it
8736 mov.b &FMUL_OP,%d1 # last inst is MUL
8737 fmul.s (%sp)+,%fp0
8738 bra t_catch
8739
8740ATANHBIG:
8741 fabs.x (%a0),%fp0 # |X|
8742 fcmp.s %fp0,&0x3F800000
8743 fbgt t_operr
8744 bra t_dz
8745
8746 global satanhd
8747#--ATANH(X) = X FOR DENORMALIZED X
8748satanhd:
8749 bra t_extdnrm
8750
8751#########################################################################
8752# slog10(): computes the base-10 logarithm of a normalized input #
8753# slog10d(): computes the base-10 logarithm of a denormalized input #
8754# slog2(): computes the base-2 logarithm of a normalized input #
8755# slog2d(): computes the base-2 logarithm of a denormalized input #
8756# #
8757# INPUT *************************************************************** #
8758# a0 = pointer to extended precision input #
8759# d0 = round precision,mode #
8760# #
8761# OUTPUT ************************************************************** #
8762# fp0 = log_10(X) or log_2(X) #
8763# #
8764# ACCURACY and MONOTONICITY ******************************************* #
8765# The returned result is within 1.7 ulps in 64 significant bit, #
8766# i.e. within 0.5003 ulp to 53 bits if the result is subsequently #
8767# rounded to double precision. The result is provably monotonic #
8768# in double precision. #
8769# #
8770# ALGORITHM *********************************************************** #
8771# #
8772# slog10d: #
8773# #
8774# Step 0. If X < 0, create a NaN and raise the invalid operation #
8775# flag. Otherwise, save FPCR in D1; set FpCR to default. #
8776# Notes: Default means round-to-nearest mode, no floating-point #
8777# traps, and precision control = double extended. #
8778# #
8779# Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8780# Notes: Even if X is denormalized, log(X) is always normalized. #
8781# #
8782# Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
8783# 2.1 Restore the user FPCR #
8784# 2.2 Return ans := Y * INV_L10. #
8785# #
8786# slog10: #
8787# #
8788# Step 0. If X < 0, create a NaN and raise the invalid operation #
8789# flag. Otherwise, save FPCR in D1; set FpCR to default. #
8790# Notes: Default means round-to-nearest mode, no floating-point #
8791# traps, and precision control = double extended. #
8792# #
8793# Step 1. Call sLogN to obtain Y = log(X), the natural log of X. #
8794# #
8795# Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
8796# 2.1 Restore the user FPCR #
8797# 2.2 Return ans := Y * INV_L10. #
8798# #
8799# sLog2d: #
8800# #
8801# Step 0. If X < 0, create a NaN and raise the invalid operation #
8802# flag. Otherwise, save FPCR in D1; set FpCR to default. #
8803# Notes: Default means round-to-nearest mode, no floating-point #
8804# traps, and precision control = double extended. #
8805# #
8806# Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8807# Notes: Even if X is denormalized, log(X) is always normalized. #
8808# #
8809# Step 2. Compute log_10(X) = log(X) * (1/log(2)). #
8810# 2.1 Restore the user FPCR #
8811# 2.2 Return ans := Y * INV_L2. #
8812# #
8813# sLog2: #
8814# #
8815# Step 0. If X < 0, create a NaN and raise the invalid operation #
8816# flag. Otherwise, save FPCR in D1; set FpCR to default. #
8817# Notes: Default means round-to-nearest mode, no floating-point #
8818# traps, and precision control = double extended. #
8819# #
8820# Step 1. If X is not an integer power of two, i.e., X != 2^k, #
8821# go to Step 3. #
8822# #
8823# Step 2. Return k. #
8824# 2.1 Get integer k, X = 2^k. #
8825# 2.2 Restore the user FPCR. #
8826# 2.3 Return ans := convert-to-double-extended(k). #
8827# #
8828# Step 3. Call sLogN to obtain Y = log(X), the natural log of X. #
8829# #
8830# Step 4. Compute log_2(X) = log(X) * (1/log(2)). #
8831# 4.1 Restore the user FPCR #
8832# 4.2 Return ans := Y * INV_L2. #
8833# #
8834#########################################################################
8835
8836INV_L10:
8837 long 0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
8838
8839INV_L2:
8840 long 0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
8841
8842 global slog10
8843#--entry point for Log10(X), X is normalized
8844slog10:
8845 fmov.b &0x1,%fp0
8846 fcmp.x %fp0,(%a0) # if operand == 1,
8847 fbeq.l ld_pzero # return an EXACT zero
8848
8849 mov.l (%a0),%d1
8850 blt.w invalid
8851 mov.l %d0,-(%sp)
8852 clr.l %d0
8853 bsr slogn # log(X), X normal.
8854 fmov.l (%sp)+,%fpcr
8855 fmul.x INV_L10(%pc),%fp0
8856 bra t_inx2
8857
8858 global slog10d
8859#--entry point for Log10(X), X is denormalized
8860slog10d:
8861 mov.l (%a0),%d1
8862 blt.w invalid
8863 mov.l %d0,-(%sp)
8864 clr.l %d0
8865 bsr slognd # log(X), X denorm.
8866 fmov.l (%sp)+,%fpcr
8867 fmul.x INV_L10(%pc),%fp0
8868 bra t_minx2
8869
8870 global slog2
8871#--entry point for Log2(X), X is normalized
8872slog2:
8873 mov.l (%a0),%d1
8874 blt.w invalid
8875
8876 mov.l 8(%a0),%d1
8877 bne.b continue # X is not 2^k
8878
8879 mov.l 4(%a0),%d1
8880 and.l &0x7FFFFFFF,%d1
8881 bne.b continue
8882
8883#--X = 2^k.
8884 mov.w (%a0),%d1
8885 and.l &0x00007FFF,%d1
8886 sub.l &0x3FFF,%d1
8887 beq.l ld_pzero
8888 fmov.l %d0,%fpcr
8889 fmov.l %d1,%fp0
8890 bra t_inx2
8891
8892continue:
8893 mov.l %d0,-(%sp)
8894 clr.l %d0
8895 bsr slogn # log(X), X normal.
8896 fmov.l (%sp)+,%fpcr
8897 fmul.x INV_L2(%pc),%fp0
8898 bra t_inx2
8899
8900invalid:
8901 bra t_operr
8902
8903 global slog2d
8904#--entry point for Log2(X), X is denormalized
8905slog2d:
8906 mov.l (%a0),%d1
8907 blt.w invalid
8908 mov.l %d0,-(%sp)
8909 clr.l %d0
8910 bsr slognd # log(X), X denorm.
8911 fmov.l (%sp)+,%fpcr
8912 fmul.x INV_L2(%pc),%fp0
8913 bra t_minx2
8914
8915#########################################################################
8916# stwotox(): computes 2**X for a normalized input #
8917# stwotoxd(): computes 2**X for a denormalized input #
8918# stentox(): computes 10**X for a normalized input #
8919# stentoxd(): computes 10**X for a denormalized input #
8920# #
8921# INPUT *************************************************************** #
8922# a0 = pointer to extended precision input #
8923# d0 = round precision,mode #
8924# #
8925# OUTPUT ************************************************************** #
8926# fp0 = 2**X or 10**X #
8927# #
8928# ACCURACY and MONOTONICITY ******************************************* #
8929# The returned result is within 2 ulps in 64 significant bit, #
8930# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8931# rounded to double precision. The result is provably monotonic #
8932# in double precision. #
8933# #
8934# ALGORITHM *********************************************************** #
8935# #
8936# twotox #
8937# 1. If |X| > 16480, go to ExpBig. #
8938# #
8939# 2. If |X| < 2**(-70), go to ExpSm. #
8940# #
8941# 3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore #
8942# decompose N as #
8943# N = 64(M + M') + j, j = 0,1,2,...,63. #
8944# #
8945# 4. Overwrite r := r * log2. Then #
8946# 2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
8947# Go to expr to compute that expression. #
8948# #
8949# tentox #
8950# 1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig. #
8951# #
8952# 2. If |X| < 2**(-70), go to ExpSm. #
8953# #
8954# 3. Set y := X*log_2(10)*64 (base 2 log of 10). Set #
8955# N := round-to-int(y). Decompose N as #
8956# N = 64(M + M') + j, j = 0,1,2,...,63. #
8957# #
8958# 4. Define r as #
8959# r := ((X - N*L1)-N*L2) * L10 #
8960# where L1, L2 are the leading and trailing parts of #
8961# log_10(2)/64 and L10 is the natural log of 10. Then #
8962# 10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
8963# Go to expr to compute that expression. #
8964# #
8965# expr #
8966# 1. Fetch 2**(j/64) from table as Fact1 and Fact2. #
8967# #
8968# 2. Overwrite Fact1 and Fact2 by #
8969# Fact1 := 2**(M) * Fact1 #
8970# Fact2 := 2**(M) * Fact2 #
8971# Thus Fact1 + Fact2 = 2**(M) * 2**(j/64). #
8972# #
8973# 3. Calculate P where 1 + P approximates exp(r): #
8974# P = r + r*r*(A1+r*(A2+...+r*A5)). #
8975# #
8976# 4. Let AdjFact := 2**(M'). Return #
8977# AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ). #
8978# Exit. #
8979# #
8980# ExpBig #
8981# 1. Generate overflow by Huge * Huge if X > 0; otherwise, #
8982# generate underflow by Tiny * Tiny. #
8983# #
8984# ExpSm #
8985# 1. Return 1 + X. #
8986# #
8987#########################################################################
8988
8989L2TEN64:
8990 long 0x406A934F,0x0979A371 # 64LOG10/LOG2
8991L10TWO1:
8992 long 0x3F734413,0x509F8000 # LOG2/64LOG10
8993
8994L10TWO2:
8995 long 0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
8996
8997LOG10: long 0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
8998
8999LOG2: long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
9000
9001EXPA5: long 0x3F56C16D,0x6F7BD0B2
9002EXPA4: long 0x3F811112,0x302C712C
9003EXPA3: long 0x3FA55555,0x55554CC1
9004EXPA2: long 0x3FC55555,0x55554A54
9005EXPA1: long 0x3FE00000,0x00000000,0x00000000,0x00000000
9006
9007TEXPTBL:
9008 long 0x3FFF0000,0x80000000,0x00000000,0x3F738000
9009 long 0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
9010 long 0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
9011 long 0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
9012 long 0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
9013 long 0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
9014 long 0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
9015 long 0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
9016 long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
9017 long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
9018 long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
9019 long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
9020 long 0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
9021 long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
9022 long 0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
9023 long 0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
9024 long 0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
9025 long 0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
9026 long 0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
9027 long 0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
9028 long 0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
9029 long 0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
9030 long 0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
9031 long 0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
9032 long 0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
9033 long 0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
9034 long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
9035 long 0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
9036 long 0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
9037 long 0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
9038 long 0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
9039 long 0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
9040 long 0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
9041 long 0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
9042 long 0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
9043 long 0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
9044 long 0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
9045 long 0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
9046 long 0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
9047 long 0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
9048 long 0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
9049 long 0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
9050 long 0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
9051 long 0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
9052 long 0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
9053 long 0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
9054 long 0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
9055 long 0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
9056 long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
9057 long 0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
9058 long 0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
9059 long 0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
9060 long 0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
9061 long 0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
9062 long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
9063 long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
9064 long 0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
9065 long 0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
9066 long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
9067 long 0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
9068 long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
9069 long 0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
9070 long 0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
9071 long 0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
9072
9073 set INT,L_SCR1
9074
9075 set X,FP_SCR0
9076 set XDCARE,X+2
9077 set XFRAC,X+4
9078
9079 set ADJFACT,FP_SCR0
9080
9081 set FACT1,FP_SCR0
9082 set FACT1HI,FACT1+4
9083 set FACT1LOW,FACT1+8
9084
9085 set FACT2,FP_SCR1
9086 set FACT2HI,FACT2+4
9087 set FACT2LOW,FACT2+8
9088
9089 global stwotox
9090#--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
9091stwotox:
9092 fmovm.x (%a0),&0x80 # LOAD INPUT
9093
9094 mov.l (%a0),%d1
9095 mov.w 4(%a0),%d1
9096 fmov.x %fp0,X(%a6)
9097 and.l &0x7FFFFFFF,%d1
9098
9099 cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
9100 bge.b TWOOK1
9101 bra.w EXPBORS
9102
9103TWOOK1:
9104 cmp.l %d1,&0x400D80C0 # |X| > 16480?
9105 ble.b TWOMAIN
9106 bra.w EXPBORS
9107
9108TWOMAIN:
9109#--USUAL CASE, 2^(-70) <= |X| <= 16480
9110
9111 fmov.x %fp0,%fp1
9112 fmul.s &0x42800000,%fp1 # 64 * X
9113 fmov.l %fp1,INT(%a6) # N = ROUND-TO-INT(64 X)
9114 mov.l %d2,-(%sp)
9115 lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
9116 fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
9117 mov.l INT(%a6),%d1
9118 mov.l %d1,%d2
9119 and.l &0x3F,%d1 # D0 IS J
9120 asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
9121 add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
9122 asr.l &6,%d2 # d2 IS L, N = 64L + J
9123 mov.l %d2,%d1
9124 asr.l &1,%d1 # D0 IS M
9125 sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
9126 add.l &0x3FFF,%d2
9127
9128#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9129#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9130#--ADJFACT = 2^(M').
9131#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9132
9133 fmovm.x &0x0c,-(%sp) # save fp2/fp3
9134
9135 fmul.s &0x3C800000,%fp1 # (1/64)*N
9136 mov.l (%a1)+,FACT1(%a6)
9137 mov.l (%a1)+,FACT1HI(%a6)
9138 mov.l (%a1)+,FACT1LOW(%a6)
9139 mov.w (%a1)+,FACT2(%a6)
9140
9141 fsub.x %fp1,%fp0 # X - (1/64)*INT(64 X)
9142
9143 mov.w (%a1)+,FACT2HI(%a6)
9144 clr.w FACT2HI+2(%a6)
9145 clr.l FACT2LOW(%a6)
9146 add.w %d1,FACT1(%a6)
9147 fmul.x LOG2(%pc),%fp0 # FP0 IS R
9148 add.w %d1,FACT2(%a6)
9149
9150 bra.w expr
9151
9152EXPBORS:
9153#--FPCR, D0 SAVED
9154 cmp.l %d1,&0x3FFF8000
9155 bgt.b TEXPBIG
9156
9157#--|X| IS SMALL, RETURN 1 + X
9158
9159 fmov.l %d0,%fpcr # restore users round prec,mode
9160 fadd.s &0x3F800000,%fp0 # RETURN 1 + X
9161 bra t_pinx2
9162
9163TEXPBIG:
9164#--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
9165#--REGISTERS SAVE SO FAR ARE FPCR AND D0
9166 mov.l X(%a6),%d1
9167 cmp.l %d1,&0
9168 blt.b EXPNEG
9169
9170 bra t_ovfl2 # t_ovfl expects positive value
9171
9172EXPNEG:
9173 bra t_unfl2 # t_unfl expects positive value
9174
9175 global stwotoxd
9176stwotoxd:
9177#--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
9178
9179 fmov.l %d0,%fpcr # set user's rounding mode/precision
9180 fmov.s &0x3F800000,%fp0 # RETURN 1 + X
9181 mov.l (%a0),%d1
9182 or.l &0x00800001,%d1
9183 fadd.s %d1,%fp0
9184 bra t_pinx2
9185
9186 global stentox
9187#--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
9188stentox:
9189 fmovm.x (%a0),&0x80 # LOAD INPUT
9190
9191 mov.l (%a0),%d1
9192 mov.w 4(%a0),%d1
9193 fmov.x %fp0,X(%a6)
9194 and.l &0x7FFFFFFF,%d1
9195
9196 cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
9197 bge.b TENOK1
9198 bra.w EXPBORS
9199
9200TENOK1:
9201 cmp.l %d1,&0x400B9B07 # |X| <= 16480*log2/log10 ?
9202 ble.b TENMAIN
9203 bra.w EXPBORS
9204
9205TENMAIN:
9206#--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
9207
9208 fmov.x %fp0,%fp1
9209 fmul.d L2TEN64(%pc),%fp1 # X*64*LOG10/LOG2
9210 fmov.l %fp1,INT(%a6) # N=INT(X*64*LOG10/LOG2)
9211 mov.l %d2,-(%sp)
9212 lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
9213 fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
9214 mov.l INT(%a6),%d1
9215 mov.l %d1,%d2
9216 and.l &0x3F,%d1 # D0 IS J
9217 asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
9218 add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
9219 asr.l &6,%d2 # d2 IS L, N = 64L + J
9220 mov.l %d2,%d1
9221 asr.l &1,%d1 # D0 IS M
9222 sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
9223 add.l &0x3FFF,%d2
9224
9225#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9226#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9227#--ADJFACT = 2^(M').
9228#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9229 fmovm.x &0x0c,-(%sp) # save fp2/fp3
9230
9231 fmov.x %fp1,%fp2
9232
9233 fmul.d L10TWO1(%pc),%fp1 # N*(LOG2/64LOG10)_LEAD
9234 mov.l (%a1)+,FACT1(%a6)
9235
9236 fmul.x L10TWO2(%pc),%fp2 # N*(LOG2/64LOG10)_TRAIL
9237
9238 mov.l (%a1)+,FACT1HI(%a6)
9239 mov.l (%a1)+,FACT1LOW(%a6)
9240 fsub.x %fp1,%fp0 # X - N L_LEAD
9241 mov.w (%a1)+,FACT2(%a6)
9242
9243 fsub.x %fp2,%fp0 # X - N L_TRAIL
9244
9245 mov.w (%a1)+,FACT2HI(%a6)
9246 clr.w FACT2HI+2(%a6)
9247 clr.l FACT2LOW(%a6)
9248
9249 fmul.x LOG10(%pc),%fp0 # FP0 IS R
9250 add.w %d1,FACT1(%a6)
9251 add.w %d1,FACT2(%a6)
9252
9253expr:
9254#--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
9255#--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
9256#--FP0 IS R. THE FOLLOWING CODE COMPUTES
9257#-- 2**(M'+M) * 2**(J/64) * EXP(R)
9258
9259 fmov.x %fp0,%fp1
9260 fmul.x %fp1,%fp1 # FP1 IS S = R*R
9261
9262 fmov.d EXPA5(%pc),%fp2 # FP2 IS A5
9263 fmov.d EXPA4(%pc),%fp3 # FP3 IS A4
9264
9265 fmul.x %fp1,%fp2 # FP2 IS S*A5
9266 fmul.x %fp1,%fp3 # FP3 IS S*A4
9267
9268 fadd.d EXPA3(%pc),%fp2 # FP2 IS A3+S*A5
9269 fadd.d EXPA2(%pc),%fp3 # FP3 IS A2+S*A4
9270
9271 fmul.x %fp1,%fp2 # FP2 IS S*(A3+S*A5)
9272 fmul.x %fp1,%fp3 # FP3 IS S*(A2+S*A4)
9273
9274 fadd.d EXPA1(%pc),%fp2 # FP2 IS A1+S*(A3+S*A5)
9275 fmul.x %fp0,%fp3 # FP3 IS R*S*(A2+S*A4)
9276
9277 fmul.x %fp1,%fp2 # FP2 IS S*(A1+S*(A3+S*A5))
9278 fadd.x %fp3,%fp0 # FP0 IS R+R*S*(A2+S*A4)
9279 fadd.x %fp2,%fp0 # FP0 IS EXP(R) - 1
9280
9281 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
9282
9283#--FINAL RECONSTRUCTION PROCESS
9284#--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1) - (1 OR 0)
9285
9286 fmul.x FACT1(%a6),%fp0
9287 fadd.x FACT2(%a6),%fp0
9288 fadd.x FACT1(%a6),%fp0
9289
9290 fmov.l %d0,%fpcr # restore users round prec,mode
9291 mov.w %d2,ADJFACT(%a6) # INSERT EXPONENT
9292 mov.l (%sp)+,%d2
9293 mov.l &0x80000000,ADJFACT+4(%a6)
9294 clr.l ADJFACT+8(%a6)
9295 mov.b &FMUL_OP,%d1 # last inst is MUL
9296 fmul.x ADJFACT(%a6),%fp0 # FINAL ADJUSTMENT
9297 bra t_catch
9298
9299 global stentoxd
9300stentoxd:
9301#--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
9302
9303 fmov.l %d0,%fpcr # set user's rounding mode/precision
9304 fmov.s &0x3F800000,%fp0 # RETURN 1 + X
9305 mov.l (%a0),%d1
9306 or.l &0x00800001,%d1
9307 fadd.s %d1,%fp0
9308 bra t_pinx2
9309
9310#########################################################################
9311# smovcr(): returns the ROM constant at the offset specified in d1 #
9312# rounded to the mode and precision specified in d0. #
9313# #
9314# INPUT *************************************************************** #
9315# d0 = rnd prec,mode #
9316# d1 = ROM offset #
9317# #
9318# OUTPUT ************************************************************** #
9319# fp0 = the ROM constant rounded to the user's rounding mode,prec #
9320# #
9321#########################################################################
9322
9323 global smovcr
9324smovcr:
9325 mov.l %d1,-(%sp) # save rom offset for a sec
9326
9327 lsr.b &0x4,%d0 # shift ctrl bits to lo
9328 mov.l %d0,%d1 # make a copy
9329 andi.w &0x3,%d1 # extract rnd mode
9330 andi.w &0xc,%d0 # extract rnd prec
9331 swap %d0 # put rnd prec in hi
9332 mov.w %d1,%d0 # put rnd mode in lo
9333
9334 mov.l (%sp)+,%d1 # get rom offset
9335
9336#
9337# check range of offset
9338#
9339 tst.b %d1 # if zero, offset is to pi
9340 beq.b pi_tbl # it is pi
9341 cmpi.b %d1,&0x0a # check range $01 - $0a
9342 ble.b z_val # if in this range, return zero
9343 cmpi.b %d1,&0x0e # check range $0b - $0e
9344 ble.b sm_tbl # valid constants in this range
9345 cmpi.b %d1,&0x2f # check range $10 - $2f
9346 ble.b z_val # if in this range, return zero
9347 cmpi.b %d1,&0x3f # check range $30 - $3f
9348 ble.b bg_tbl # valid constants in this range
9349
9350z_val:
9351 bra.l ld_pzero # return a zero
9352
9353#
9354# the answer is PI rounded to the proper precision.
9355#
9356# fetch a pointer to the answer table relating to the proper rounding
9357# precision.
9358#
9359pi_tbl:
9360 tst.b %d0 # is rmode RN?
9361 bne.b pi_not_rn # no
9362pi_rn:
9363 lea.l PIRN(%pc),%a0 # yes; load PI RN table addr
9364 bra.w set_finx
9365pi_not_rn:
9366 cmpi.b %d0,&rp_mode # is rmode RP?
9367 beq.b pi_rp # yes
9368pi_rzrm:
9369 lea.l PIRZRM(%pc),%a0 # no; load PI RZ,RM table addr
9370 bra.b set_finx
9371pi_rp:
9372 lea.l PIRP(%pc),%a0 # load PI RP table addr
9373 bra.b set_finx
9374
9375#
9376# the answer is one of:
9377# $0B log10(2) (inexact)
9378# $0C e (inexact)
9379# $0D log2(e) (inexact)
9380# $0E log10(e) (exact)
9381#
9382# fetch a pointer to the answer table relating to the proper rounding
9383# precision.
9384#
9385sm_tbl:
9386 subi.b &0xb,%d1 # make offset in 0-4 range
9387 tst.b %d0 # is rmode RN?
9388 bne.b sm_not_rn # no
9389sm_rn:
9390 lea.l SMALRN(%pc),%a0 # yes; load RN table addr
9391sm_tbl_cont:
9392 cmpi.b %d1,&0x2 # is result log10(e)?
9393 ble.b set_finx # no; answer is inexact
9394 bra.b no_finx # yes; answer is exact
9395sm_not_rn:
9396 cmpi.b %d0,&rp_mode # is rmode RP?
9397 beq.b sm_rp # yes
9398sm_rzrm:
9399 lea.l SMALRZRM(%pc),%a0 # no; load RZ,RM table addr
9400 bra.b sm_tbl_cont
9401sm_rp:
9402 lea.l SMALRP(%pc),%a0 # load RP table addr
9403 bra.b sm_tbl_cont
9404
9405#
9406# the answer is one of:
9407# $30 ln(2) (inexact)
9408# $31 ln(10) (inexact)
9409# $32 10^0 (exact)
9410# $33 10^1 (exact)
9411# $34 10^2 (exact)
9412# $35 10^4 (exact)
9413# $36 10^8 (exact)
9414# $37 10^16 (exact)
9415# $38 10^32 (inexact)
9416# $39 10^64 (inexact)
9417# $3A 10^128 (inexact)
9418# $3B 10^256 (inexact)
9419# $3C 10^512 (inexact)
9420# $3D 10^1024 (inexact)
9421# $3E 10^2048 (inexact)
9422# $3F 10^4096 (inexact)
9423#
9424# fetch a pointer to the answer table relating to the proper rounding
9425# precision.
9426#
9427bg_tbl:
9428 subi.b &0x30,%d1 # make offset in 0-f range
9429 tst.b %d0 # is rmode RN?
9430 bne.b bg_not_rn # no
9431bg_rn:
9432 lea.l BIGRN(%pc),%a0 # yes; load RN table addr
9433bg_tbl_cont:
9434 cmpi.b %d1,&0x1 # is offset <= $31?
9435 ble.b set_finx # yes; answer is inexact
9436 cmpi.b %d1,&0x7 # is $32 <= offset <= $37?
9437 ble.b no_finx # yes; answer is exact
9438 bra.b set_finx # no; answer is inexact
9439bg_not_rn:
9440 cmpi.b %d0,&rp_mode # is rmode RP?
9441 beq.b bg_rp # yes
9442bg_rzrm:
9443 lea.l BIGRZRM(%pc),%a0 # no; load RZ,RM table addr
9444 bra.b bg_tbl_cont
9445bg_rp:
9446 lea.l BIGRP(%pc),%a0 # load RP table addr
9447 bra.b bg_tbl_cont
9448
9449# answer is inexact, so set INEX2 and AINEX in the user's FPSR.
9450set_finx:
9451 ori.l &inx2a_mask,USER_FPSR(%a6) # set INEX2/AINEX
9452no_finx:
9453 mulu.w &0xc,%d1 # offset points into tables
9454 swap %d0 # put rnd prec in lo word
9455 tst.b %d0 # is precision extended?
9456
9457 bne.b not_ext # if xprec, do not call round
9458
9459# Precision is extended
9460 fmovm.x (%a0,%d1.w),&0x80 # return result in fp0
9461 rts
9462
9463# Precision is single or double
9464not_ext:
9465 swap %d0 # rnd prec in upper word
9466
9467# call round() to round the answer to the proper precision.
9468# exponents out of range for single or double DO NOT cause underflow
9469# or overflow.
9470 mov.w 0x0(%a0,%d1.w),FP_SCR1_EX(%a6) # load first word
9471 mov.l 0x4(%a0,%d1.w),FP_SCR1_HI(%a6) # load second word
9472 mov.l 0x8(%a0,%d1.w),FP_SCR1_LO(%a6) # load third word
9473 mov.l %d0,%d1
9474 clr.l %d0 # clear g,r,s
9475 lea FP_SCR1(%a6),%a0 # pass ptr to answer
9476 clr.w LOCAL_SGN(%a0) # sign always positive
9477 bsr.l _round # round the mantissa
9478
9479 fmovm.x (%a0),&0x80 # return rounded result in fp0
9480 rts
9481
9482 align 0x4
9483
9484PIRN: long 0x40000000,0xc90fdaa2,0x2168c235 # pi
9485PIRZRM: long 0x40000000,0xc90fdaa2,0x2168c234 # pi
9486PIRP: long 0x40000000,0xc90fdaa2,0x2168c235 # pi
9487
9488SMALRN: long 0x3ffd0000,0x9a209a84,0xfbcff798 # log10(2)
9489 long 0x40000000,0xadf85458,0xa2bb4a9a # e
9490 long 0x3fff0000,0xb8aa3b29,0x5c17f0bc # log2(e)
9491 long 0x3ffd0000,0xde5bd8a9,0x37287195 # log10(e)
9492 long 0x00000000,0x00000000,0x00000000 # 0.0
9493
9494SMALRZRM:
9495 long 0x3ffd0000,0x9a209a84,0xfbcff798 # log10(2)
9496 long 0x40000000,0xadf85458,0xa2bb4a9a # e
9497 long 0x3fff0000,0xb8aa3b29,0x5c17f0bb # log2(e)
9498 long 0x3ffd0000,0xde5bd8a9,0x37287195 # log10(e)
9499 long 0x00000000,0x00000000,0x00000000 # 0.0
9500
9501SMALRP: long 0x3ffd0000,0x9a209a84,0xfbcff799 # log10(2)
9502 long 0x40000000,0xadf85458,0xa2bb4a9b # e
9503 long 0x3fff0000,0xb8aa3b29,0x5c17f0bc # log2(e)
9504 long 0x3ffd0000,0xde5bd8a9,0x37287195 # log10(e)
9505 long 0x00000000,0x00000000,0x00000000 # 0.0
9506
9507BIGRN: long 0x3ffe0000,0xb17217f7,0xd1cf79ac # ln(2)
9508 long 0x40000000,0x935d8ddd,0xaaa8ac17 # ln(10)
9509
9510 long 0x3fff0000,0x80000000,0x00000000 # 10 ^ 0
9511 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
9512 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
9513 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
9514 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
9515 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
9516 long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
9517 long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
9518 long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
9519 long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
9520 long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
9521 long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
9522 long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
9523 long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
9524
9525BIGRZRM:
9526 long 0x3ffe0000,0xb17217f7,0xd1cf79ab # ln(2)
9527 long 0x40000000,0x935d8ddd,0xaaa8ac16 # ln(10)
9528
9529 long 0x3fff0000,0x80000000,0x00000000 # 10 ^ 0
9530 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
9531 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
9532 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
9533 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
9534 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
9535 long 0x40690000,0x9DC5ADA8,0x2B70B59D # 10 ^ 32
9536 long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
9537 long 0x41A80000,0x93BA47C9,0x80E98CDF # 10 ^ 128
9538 long 0x43510000,0xAA7EEBFB,0x9DF9DE8D # 10 ^ 256
9539 long 0x46A30000,0xE319A0AE,0xA60E91C6 # 10 ^ 512
9540 long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
9541 long 0x5A920000,0x9E8B3B5D,0xC53D5DE4 # 10 ^ 2048
9542 long 0x75250000,0xC4605202,0x8A20979A # 10 ^ 4096
9543
9544BIGRP:
9545 long 0x3ffe0000,0xb17217f7,0xd1cf79ac # ln(2)
9546 long 0x40000000,0x935d8ddd,0xaaa8ac17 # ln(10)
9547
9548 long 0x3fff0000,0x80000000,0x00000000 # 10 ^ 0
9549 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
9550 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
9551 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
9552 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
9553 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
9554 long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
9555 long 0x40D30000,0xC2781F49,0xFFCFA6D6 # 10 ^ 64
9556 long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
9557 long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
9558 long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
9559 long 0x4D480000,0xC9767586,0x81750C18 # 10 ^ 1024
9560 long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
9561 long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
9562
9563#########################################################################
9564# sscale(): computes the destination operand scaled by the source #
9565# operand. If the absoulute value of the source operand is #
9566# >= 2^14, an overflow or underflow is returned. #
9567# #
9568# INPUT *************************************************************** #
9569# a0 = pointer to double-extended source operand X #
9570# a1 = pointer to double-extended destination operand Y #
9571# #
9572# OUTPUT ************************************************************** #
9573# fp0 = scale(X,Y) #
9574# #
9575#########################################################################
9576
9577set SIGN, L_SCR1
9578
9579 global sscale
9580sscale:
9581 mov.l %d0,-(%sp) # store off ctrl bits for now
9582
9583 mov.w DST_EX(%a1),%d1 # get dst exponent
9584 smi.b SIGN(%a6) # use SIGN to hold dst sign
9585 andi.l &0x00007fff,%d1 # strip sign from dst exp
9586
9587 mov.w SRC_EX(%a0),%d0 # check src bounds
9588 andi.w &0x7fff,%d0 # clr src sign bit
9589 cmpi.w %d0,&0x3fff # is src ~ ZERO?
9590 blt.w src_small # yes
9591 cmpi.w %d0,&0x400c # no; is src too big?
9592 bgt.w src_out # yes
9593
9594#
9595# Source is within 2^14 range.
9596#
9597src_ok:
9598 fintrz.x SRC(%a0),%fp0 # calc int of src
9599 fmov.l %fp0,%d0 # int src to d0
9600# don't want any accrued bits from the fintrz showing up later since
9601# we may need to read the fpsr for the last fp op in t_catch2().
9602 fmov.l &0x0,%fpsr
9603
9604 tst.b DST_HI(%a1) # is dst denormalized?
9605 bmi.b sok_norm
9606
9607# the dst is a DENORM. normalize the DENORM and add the adjustment to
9608# the src value. then, jump to the norm part of the routine.
9609sok_dnrm:
9610 mov.l %d0,-(%sp) # save src for now
9611
9612 mov.w DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
9613 mov.l DST_HI(%a1),FP_SCR0_HI(%a6)
9614 mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
9615
9616 lea FP_SCR0(%a6),%a0 # pass ptr to DENORM
9617 bsr.l norm # normalize the DENORM
9618 neg.l %d0
9619 add.l (%sp)+,%d0 # add adjustment to src
9620
9621 fmovm.x FP_SCR0(%a6),&0x80 # load normalized DENORM
9622
9623 cmpi.w %d0,&-0x3fff # is the shft amt really low?
9624 bge.b sok_norm2 # thank goodness no
9625
9626# the multiply factor that we're trying to create should be a denorm
9627# for the multiply to work. therefore, we're going to actually do a
9628# multiply with a denorm which will cause an unimplemented data type
9629# exception to be put into the machine which will be caught and corrected
9630# later. we don't do this with the DENORMs above because this method
9631# is slower. but, don't fret, I don't see it being used much either.
9632 fmov.l (%sp)+,%fpcr # restore user fpcr
9633 mov.l &0x80000000,%d1 # load normalized mantissa
9634 subi.l &-0x3fff,%d0 # how many should we shift?
9635 neg.l %d0 # make it positive
9636 cmpi.b %d0,&0x20 # is it > 32?
9637 bge.b sok_dnrm_32 # yes
9638 lsr.l %d0,%d1 # no; bit stays in upper lw
9639 clr.l -(%sp) # insert zero low mantissa
9640 mov.l %d1,-(%sp) # insert new high mantissa
9641 clr.l -(%sp) # make zero exponent
9642 bra.b sok_norm_cont
9643sok_dnrm_32:
9644 subi.b &0x20,%d0 # get shift count
9645 lsr.l %d0,%d1 # make low mantissa longword
9646 mov.l %d1,-(%sp) # insert new low mantissa
9647 clr.l -(%sp) # insert zero high mantissa
9648 clr.l -(%sp) # make zero exponent
9649 bra.b sok_norm_cont
9650
9651# the src will force the dst to a DENORM value or worse. so, let's
9652# create an fp multiply that will create the result.
9653sok_norm:
9654 fmovm.x DST(%a1),&0x80 # load fp0 with normalized src
9655sok_norm2:
9656 fmov.l (%sp)+,%fpcr # restore user fpcr
9657
9658 addi.w &0x3fff,%d0 # turn src amt into exp value
9659 swap %d0 # put exponent in high word
9660 clr.l -(%sp) # insert new exponent
9661 mov.l &0x80000000,-(%sp) # insert new high mantissa
9662 mov.l %d0,-(%sp) # insert new lo mantissa
9663
9664sok_norm_cont:
9665 fmov.l %fpcr,%d0 # d0 needs fpcr for t_catch2
9666 mov.b &FMUL_OP,%d1 # last inst is MUL
9667 fmul.x (%sp)+,%fp0 # do the multiply
9668 bra t_catch2 # catch any exceptions
9669
9670#
9671# Source is outside of 2^14 range. Test the sign and branch
9672# to the appropriate exception handler.
9673#
9674src_out:
9675 mov.l (%sp)+,%d0 # restore ctrl bits
9676 exg %a0,%a1 # swap src,dst ptrs
9677 tst.b SRC_EX(%a1) # is src negative?
9678 bmi t_unfl # yes; underflow
9679 bra t_ovfl_sc # no; overflow
9680
9681#
9682# The source input is below 1, so we check for denormalized numbers
9683# and set unfl.
9684#
9685src_small:
9686 tst.b DST_HI(%a1) # is dst denormalized?
9687 bpl.b ssmall_done # yes
9688
9689 mov.l (%sp)+,%d0
9690 fmov.l %d0,%fpcr # no; load control bits
9691 mov.b &FMOV_OP,%d1 # last inst is MOVE
9692 fmov.x DST(%a1),%fp0 # simply return dest
9693 bra t_catch2
9694ssmall_done:
9695 mov.l (%sp)+,%d0 # load control bits into d1
9696 mov.l %a1,%a0 # pass ptr to dst
9697 bra t_resdnrm
9698
9699#########################################################################
9700# smod(): computes the fp MOD of the input values X,Y. #
9701# srem(): computes the fp (IEEE) REM of the input values X,Y. #
9702# #
9703# INPUT *************************************************************** #
9704# a0 = pointer to extended precision input X #
9705# a1 = pointer to extended precision input Y #
9706# d0 = round precision,mode #
9707# #
9708# The input operands X and Y can be either normalized or #
9709# denormalized. #
9710# #
9711# OUTPUT ************************************************************** #
9712# fp0 = FREM(X,Y) or FMOD(X,Y) #
9713# #
9714# ALGORITHM *********************************************************** #
9715# #
9716# Step 1. Save and strip signs of X and Y: signX := sign(X), #
9717# signY := sign(Y), X := |X|, Y := |Y|, #
9718# signQ := signX EOR signY. Record whether MOD or REM #
9719# is requested. #
9720# #
9721# Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0. #
9722# If (L < 0) then #
9723# R := X, go to Step 4. #
9724# else #
9725# R := 2^(-L)X, j := L. #
9726# endif #
9727# #
9728# Step 3. Perform MOD(X,Y) #
9729# 3.1 If R = Y, go to Step 9. #
9730# 3.2 If R > Y, then { R := R - Y, Q := Q + 1} #
9731# 3.3 If j = 0, go to Step 4. #
9732# 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to #
9733# Step 3.1. #
9734# #
9735# Step 4. At this point, R = X - QY = MOD(X,Y). Set #
9736# Last_Subtract := false (used in Step 7 below). If #
9737# MOD is requested, go to Step 6. #
9738# #
9739# Step 5. R = MOD(X,Y), but REM(X,Y) is requested. #
9740# 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to #
9741# Step 6. #
9742# 5.2 If R > Y/2, then { set Last_Subtract := true, #
9743# Q := Q + 1, Y := signY*Y }. Go to Step 6. #
9744# 5.3 This is the tricky case of R = Y/2. If Q is odd, #
9745# then { Q := Q + 1, signX := -signX }. #
9746# #
9747# Step 6. R := signX*R. #
9748# #
9749# Step 7. If Last_Subtract = true, R := R - Y. #
9750# #
9751# Step 8. Return signQ, last 7 bits of Q, and R as required. #
9752# #
9753# Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus, #
9754# X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1), #
9755# R := 0. Return signQ, last 7 bits of Q, and R. #
9756# #
9757#########################################################################
9758
9759 set Mod_Flag,L_SCR3
9760 set Sc_Flag,L_SCR3+1
9761
9762 set SignY,L_SCR2
9763 set SignX,L_SCR2+2
9764 set SignQ,L_SCR3+2
9765
9766 set Y,FP_SCR0
9767 set Y_Hi,Y+4
9768 set Y_Lo,Y+8
9769
9770 set R,FP_SCR1
9771 set R_Hi,R+4
9772 set R_Lo,R+8
9773
9774Scale:
9775 long 0x00010000,0x80000000,0x00000000,0x00000000
9776
9777 global smod
9778smod:
9779 clr.b FPSR_QBYTE(%a6)
9780 mov.l %d0,-(%sp) # save ctrl bits
9781 clr.b Mod_Flag(%a6)
9782 bra.b Mod_Rem
9783
9784 global srem
9785srem:
9786 clr.b FPSR_QBYTE(%a6)
9787 mov.l %d0,-(%sp) # save ctrl bits
9788 mov.b &0x1,Mod_Flag(%a6)
9789
9790Mod_Rem:
9791#..Save sign of X and Y
9792 movm.l &0x3f00,-(%sp) # save data registers
9793 mov.w SRC_EX(%a0),%d3
9794 mov.w %d3,SignY(%a6)
9795 and.l &0x00007FFF,%d3 # Y := |Y|
9796
9797#
9798 mov.l SRC_HI(%a0),%d4
9799 mov.l SRC_LO(%a0),%d5 # (D3,D4,D5) is |Y|
9800
9801 tst.l %d3
9802 bne.b Y_Normal
9803
9804 mov.l &0x00003FFE,%d3 # $3FFD + 1
9805 tst.l %d4
9806 bne.b HiY_not0
9807
9808HiY_0:
9809 mov.l %d5,%d4
9810 clr.l %d5
9811 sub.l &32,%d3
9812 clr.l %d6
9813 bfffo %d4{&0:&32},%d6
9814 lsl.l %d6,%d4
9815 sub.l %d6,%d3 # (D3,D4,D5) is normalized
9816# ...with bias $7FFD
9817 bra.b Chk_X
9818
9819HiY_not0:
9820 clr.l %d6
9821 bfffo %d4{&0:&32},%d6
9822 sub.l %d6,%d3
9823 lsl.l %d6,%d4
9824 mov.l %d5,%d7 # a copy of D5
9825 lsl.l %d6,%d5
9826 neg.l %d6
9827 add.l &32,%d6
9828 lsr.l %d6,%d7
9829 or.l %d7,%d4 # (D3,D4,D5) normalized
9830# ...with bias $7FFD
9831 bra.b Chk_X
9832
9833Y_Normal:
9834 add.l &0x00003FFE,%d3 # (D3,D4,D5) normalized
9835# ...with bias $7FFD
9836
9837Chk_X:
9838 mov.w DST_EX(%a1),%d0
9839 mov.w %d0,SignX(%a6)
9840 mov.w SignY(%a6),%d1
9841 eor.l %d0,%d1
9842 and.l &0x00008000,%d1
9843 mov.w %d1,SignQ(%a6) # sign(Q) obtained
9844 and.l &0x00007FFF,%d0
9845 mov.l DST_HI(%a1),%d1
9846 mov.l DST_LO(%a1),%d2 # (D0,D1,D2) is |X|
9847 tst.l %d0
9848 bne.b X_Normal
9849 mov.l &0x00003FFE,%d0
9850 tst.l %d1
9851 bne.b HiX_not0
9852
9853HiX_0:
9854 mov.l %d2,%d1
9855 clr.l %d2
9856 sub.l &32,%d0
9857 clr.l %d6
9858 bfffo %d1{&0:&32},%d6
9859 lsl.l %d6,%d1
9860 sub.l %d6,%d0 # (D0,D1,D2) is normalized
9861# ...with bias $7FFD
9862 bra.b Init
9863
9864HiX_not0:
9865 clr.l %d6
9866 bfffo %d1{&0:&32},%d6
9867 sub.l %d6,%d0
9868 lsl.l %d6,%d1
9869 mov.l %d2,%d7 # a copy of D2
9870 lsl.l %d6,%d2
9871 neg.l %d6
9872 add.l &32,%d6
9873 lsr.l %d6,%d7
9874 or.l %d7,%d1 # (D0,D1,D2) normalized
9875# ...with bias $7FFD
9876 bra.b Init
9877
9878X_Normal:
9879 add.l &0x00003FFE,%d0 # (D0,D1,D2) normalized
9880# ...with bias $7FFD
9881
9882Init:
9883#
9884 mov.l %d3,L_SCR1(%a6) # save biased exp(Y)
9885 mov.l %d0,-(%sp) # save biased exp(X)
9886 sub.l %d3,%d0 # L := expo(X)-expo(Y)
9887
9888 clr.l %d6 # D6 := carry <- 0
9889 clr.l %d3 # D3 is Q
9890 mov.l &0,%a1 # A1 is k; j+k=L, Q=0
9891
9892#..(Carry,D1,D2) is R
9893 tst.l %d0
9894 bge.b Mod_Loop_pre
9895
9896#..expo(X) < expo(Y). Thus X = mod(X,Y)
9897#
9898 mov.l (%sp)+,%d0 # restore d0
9899 bra.w Get_Mod
9900
9901Mod_Loop_pre:
9902 addq.l &0x4,%sp # erase exp(X)
9903#..At this point R = 2^(-L)X; Q = 0; k = 0; and k+j = L
9904Mod_Loop:
9905 tst.l %d6 # test carry bit
9906 bgt.b R_GT_Y
9907
9908#..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
9909 cmp.l %d1,%d4 # compare hi(R) and hi(Y)
9910 bne.b R_NE_Y
9911 cmp.l %d2,%d5 # compare lo(R) and lo(Y)
9912 bne.b R_NE_Y
9913
9914#..At this point, R = Y
9915 bra.w Rem_is_0
9916
9917R_NE_Y:
9918#..use the borrow of the previous compare
9919 bcs.b R_LT_Y # borrow is set iff R < Y
9920
9921R_GT_Y:
9922#..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
9923#..and Y < (D1,D2) < 2Y. Either way, perform R - Y
9924 sub.l %d5,%d2 # lo(R) - lo(Y)
9925 subx.l %d4,%d1 # hi(R) - hi(Y)
9926 clr.l %d6 # clear carry
9927 addq.l &1,%d3 # Q := Q + 1
9928
9929R_LT_Y:
9930#..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
9931 tst.l %d0 # see if j = 0.
9932 beq.b PostLoop
9933
9934 add.l %d3,%d3 # Q := 2Q
9935 add.l %d2,%d2 # lo(R) = 2lo(R)
9936 roxl.l &1,%d1 # hi(R) = 2hi(R) + carry
9937 scs %d6 # set Carry if 2(R) overflows
9938 addq.l &1,%a1 # k := k+1
9939 subq.l &1,%d0 # j := j - 1
9940#..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
9941
9942 bra.b Mod_Loop
9943
9944PostLoop:
9945#..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
9946
9947#..normalize R.
9948 mov.l L_SCR1(%a6),%d0 # new biased expo of R
9949 tst.l %d1
9950 bne.b HiR_not0
9951
9952HiR_0:
9953 mov.l %d2,%d1
9954 clr.l %d2
9955 sub.l &32,%d0
9956 clr.l %d6
9957 bfffo %d1{&0:&32},%d6
9958 lsl.l %d6,%d1
9959 sub.l %d6,%d0 # (D0,D1,D2) is normalized
9960# ...with bias $7FFD
9961 bra.b Get_Mod
9962
9963HiR_not0:
9964 clr.l %d6
9965 bfffo %d1{&0:&32},%d6
9966 bmi.b Get_Mod # already normalized
9967 sub.l %d6,%d0
9968 lsl.l %d6,%d1
9969 mov.l %d2,%d7 # a copy of D2
9970 lsl.l %d6,%d2
9971 neg.l %d6
9972 add.l &32,%d6
9973 lsr.l %d6,%d7
9974 or.l %d7,%d1 # (D0,D1,D2) normalized
9975
9976#
9977Get_Mod:
9978 cmp.l %d0,&0x000041FE
9979 bge.b No_Scale
9980Do_Scale:
9981 mov.w %d0,R(%a6)
9982 mov.l %d1,R_Hi(%a6)
9983 mov.l %d2,R_Lo(%a6)
9984 mov.l L_SCR1(%a6),%d6
9985 mov.w %d6,Y(%a6)
9986 mov.l %d4,Y_Hi(%a6)
9987 mov.l %d5,Y_Lo(%a6)
9988 fmov.x R(%a6),%fp0 # no exception
9989 mov.b &1,Sc_Flag(%a6)
9990 bra.b ModOrRem
9991No_Scale:
9992 mov.l %d1,R_Hi(%a6)
9993 mov.l %d2,R_Lo(%a6)
9994 sub.l &0x3FFE,%d0
9995 mov.w %d0,R(%a6)
9996 mov.l L_SCR1(%a6),%d6
9997 sub.l &0x3FFE,%d6
9998 mov.l %d6,L_SCR1(%a6)
9999 fmov.x R(%a6),%fp0
10000 mov.w %d6,Y(%a6)
10001 mov.l %d4,Y_Hi(%a6)
10002 mov.l %d5,Y_Lo(%a6)
10003 clr.b Sc_Flag(%a6)
10004
10005#
10006ModOrRem:
10007 tst.b Mod_Flag(%a6)
10008 beq.b Fix_Sign
10009
10010 mov.l L_SCR1(%a6),%d6 # new biased expo(Y)
10011 subq.l &1,%d6 # biased expo(Y/2)
10012 cmp.l %d0,%d6
10013 blt.b Fix_Sign
10014 bgt.b Last_Sub
10015
10016 cmp.l %d1,%d4
10017 bne.b Not_EQ
10018 cmp.l %d2,%d5
10019 bne.b Not_EQ
10020 bra.w Tie_Case
10021
10022Not_EQ:
10023 bcs.b Fix_Sign
10024
10025Last_Sub:
10026#
10027 fsub.x Y(%a6),%fp0 # no exceptions
10028 addq.l &1,%d3 # Q := Q + 1
10029
10030#
10031Fix_Sign:
10032#..Get sign of X
10033 mov.w SignX(%a6),%d6
10034 bge.b Get_Q
10035 fneg.x %fp0
10036
10037#..Get Q
10038#
10039Get_Q:
10040 clr.l %d6
10041 mov.w SignQ(%a6),%d6 # D6 is sign(Q)
10042 mov.l &8,%d7
10043 lsr.l %d7,%d6
10044 and.l &0x0000007F,%d3 # 7 bits of Q
10045 or.l %d6,%d3 # sign and bits of Q
10046# swap %d3
10047# fmov.l %fpsr,%d6
10048# and.l &0xFF00FFFF,%d6
10049# or.l %d3,%d6
10050# fmov.l %d6,%fpsr # put Q in fpsr
10051 mov.b %d3,FPSR_QBYTE(%a6) # put Q in fpsr
10052
10053#
10054Restore:
10055 movm.l (%sp)+,&0xfc # {%d2-%d7}
10056 mov.l (%sp)+,%d0
10057 fmov.l %d0,%fpcr
10058 tst.b Sc_Flag(%a6)
10059 beq.b Finish
10060 mov.b &FMUL_OP,%d1 # last inst is MUL
10061 fmul.x Scale(%pc),%fp0 # may cause underflow
10062 bra t_catch2
10063# the '040 package did this apparently to see if the dst operand for the
10064# preceding fmul was a denorm. but, it better not have been since the
10065# algorithm just got done playing with fp0 and expected no exceptions
10066# as a result. trust me...
10067# bra t_avoid_unsupp # check for denorm as a
10068# ;result of the scaling
10069
10070Finish:
10071 mov.b &FMOV_OP,%d1 # last inst is MOVE
10072 fmov.x %fp0,%fp0 # capture exceptions & round
10073 bra t_catch2
10074
10075Rem_is_0:
10076#..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
10077 addq.l &1,%d3
10078 cmp.l %d0,&8 # D0 is j
10079 bge.b Q_Big
10080
10081 lsl.l %d0,%d3
10082 bra.b Set_R_0
10083
10084Q_Big:
10085 clr.l %d3
10086
10087Set_R_0:
10088 fmov.s &0x00000000,%fp0
10089 clr.b Sc_Flag(%a6)
10090 bra.w Fix_Sign
10091
10092Tie_Case:
10093#..Check parity of Q
10094 mov.l %d3,%d6
10095 and.l &0x00000001,%d6
10096 tst.l %d6
10097 beq.w Fix_Sign # Q is even
10098
10099#..Q is odd, Q := Q + 1, signX := -signX
10100 addq.l &1,%d3
10101 mov.w SignX(%a6),%d6
10102 eor.l &0x00008000,%d6
10103 mov.w %d6,SignX(%a6)
10104 bra.w Fix_Sign
10105
10106qnan: long 0x7fff0000, 0xffffffff, 0xffffffff
10107
10108#########################################################################
10109# XDEF **************************************************************** #
10110# t_dz(): Handle DZ exception during transcendental emulation. #
10111# Sets N bit according to sign of source operand. #
10112# t_dz2(): Handle DZ exception during transcendental emulation. #
10113# Sets N bit always. #
10114# #
10115# XREF **************************************************************** #
10116# None #
10117# #
10118# INPUT *************************************************************** #
10119# a0 = pointer to source operand #
10120# #
10121# OUTPUT ************************************************************** #
10122# fp0 = default result #
10123# #
10124# ALGORITHM *********************************************************** #
10125# - Store properly signed INF into fp0. #
10126# - Set FPSR exception status dz bit, ccode inf bit, and #
10127# accrued dz bit. #
10128# #
10129#########################################################################
10130
10131 global t_dz
10132t_dz:
10133 tst.b SRC_EX(%a0) # no; is src negative?
10134 bmi.b t_dz2 # yes
10135
10136dz_pinf:
10137 fmov.s &0x7f800000,%fp0 # return +INF in fp0
10138 ori.l &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
10139 rts
10140
10141 global t_dz2
10142t_dz2:
10143 fmov.s &0xff800000,%fp0 # return -INF in fp0
10144 ori.l &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
10145 rts
10146
10147#################################################################
10148# OPERR exception: #
10149# - set FPSR exception status operr bit, condition code #
10150# nan bit; Store default NAN into fp0 #
10151#################################################################
10152 global t_operr
10153t_operr:
10154 ori.l &opnan_mask,USER_FPSR(%a6) # set NaN/OPERR/AIOP
10155 fmovm.x qnan(%pc),&0x80 # return default NAN in fp0
10156 rts
10157
10158#################################################################
10159# Extended DENORM: #
10160# - For all functions that have a denormalized input and #
10161# that f(x)=x, this is the entry point. #
10162# - we only return the EXOP here if either underflow or #
10163# inexact is enabled. #
10164#################################################################
10165
10166# Entry point for scale w/ extended denorm. The function does
10167# NOT set INEX2/AUNFL/AINEX.
10168 global t_resdnrm
10169t_resdnrm:
10170 ori.l &unfl_mask,USER_FPSR(%a6) # set UNFL
10171 bra.b xdnrm_con
10172
10173 global t_extdnrm
10174t_extdnrm:
10175 ori.l &unfinx_mask,USER_FPSR(%a6) # set UNFL/INEX2/AUNFL/AINEX
10176
10177xdnrm_con:
10178 mov.l %a0,%a1 # make copy of src ptr
10179 mov.l %d0,%d1 # make copy of rnd prec,mode
10180 andi.b &0xc0,%d1 # extended precision?
10181 bne.b xdnrm_sd # no
10182
10183# result precision is extended.
10184 tst.b LOCAL_EX(%a0) # is denorm negative?
10185 bpl.b xdnrm_exit # no
10186
10187 bset &neg_bit,FPSR_CC(%a6) # yes; set 'N' ccode bit
10188 bra.b xdnrm_exit
10189
10190# result precision is single or double
10191xdnrm_sd:
10192 mov.l %a1,-(%sp)
10193 tst.b LOCAL_EX(%a0) # is denorm pos or neg?
10194 smi.b %d1 # set d0 accodingly
10195 bsr.l unf_sub
10196 mov.l (%sp)+,%a1
10197xdnrm_exit:
10198 fmovm.x (%a0),&0x80 # return default result in fp0
10199
10200 mov.b FPCR_ENABLE(%a6),%d0
10201 andi.b &0x0a,%d0 # is UNFL or INEX enabled?
10202 bne.b xdnrm_ena # yes
10203 rts
10204
10205################
10206# unfl enabled #
10207################
10208# we have a DENORM that needs to be converted into an EXOP.
10209# so, normalize the mantissa, add 0x6000 to the new exponent,
10210# and return the result in fp1.
10211xdnrm_ena:
10212 mov.w LOCAL_EX(%a1),FP_SCR0_EX(%a6)
10213 mov.l LOCAL_HI(%a1),FP_SCR0_HI(%a6)
10214 mov.l LOCAL_LO(%a1),FP_SCR0_LO(%a6)
10215
10216 lea FP_SCR0(%a6),%a0
10217 bsr.l norm # normalize mantissa
10218 addi.l &0x6000,%d0 # add extra bias
10219 andi.w &0x8000,FP_SCR0_EX(%a6) # keep old sign
10220 or.w %d0,FP_SCR0_EX(%a6) # insert new exponent
10221
10222 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10223 rts
10224
10225#################################################################
10226# UNFL exception: #
10227# - This routine is for cases where even an EXOP isn't #
10228# large enough to hold the range of this result. #
10229# In such a case, the EXOP equals zero. #
10230# - Return the default result to the proper precision #
10231# with the sign of this result being the same as that #
10232# of the src operand. #
10233# - t_unfl2() is provided to force the result sign to #
10234# positive which is the desired result for fetox(). #
10235#################################################################
10236 global t_unfl
10237t_unfl:
10238 ori.l &unfinx_mask,USER_FPSR(%a6) # set UNFL/INEX2/AUNFL/AINEX
10239
10240 tst.b (%a0) # is result pos or neg?
10241 smi.b %d1 # set d1 accordingly
10242 bsr.l unf_sub # calc default unfl result
10243 fmovm.x (%a0),&0x80 # return default result in fp0
10244
10245 fmov.s &0x00000000,%fp1 # return EXOP in fp1
10246 rts
10247
10248# t_unfl2 ALWAYS tells unf_sub to create a positive result
10249 global t_unfl2
10250t_unfl2:
10251 ori.l &unfinx_mask,USER_FPSR(%a6) # set UNFL/INEX2/AUNFL/AINEX
10252
10253 sf.b %d1 # set d0 to represent positive
10254 bsr.l unf_sub # calc default unfl result
10255 fmovm.x (%a0),&0x80 # return default result in fp0
10256
10257 fmov.s &0x0000000,%fp1 # return EXOP in fp1
10258 rts
10259
10260#################################################################
10261# OVFL exception: #
10262# - This routine is for cases where even an EXOP isn't #
10263# large enough to hold the range of this result. #
10264# - Return the default result to the proper precision #
10265# with the sign of this result being the same as that #
10266# of the src operand. #
10267# - t_ovfl2() is provided to force the result sign to #
10268# positive which is the desired result for fcosh(). #
10269# - t_ovfl_sc() is provided for scale() which only sets #
10270# the inexact bits if the number is inexact for the #
10271# precision indicated. #
10272#################################################################
10273
10274 global t_ovfl_sc
10275t_ovfl_sc:
10276 ori.l &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
10277
10278 mov.b %d0,%d1 # fetch rnd mode/prec
10279 andi.b &0xc0,%d1 # extract rnd prec
10280 beq.b ovfl_work # prec is extended
10281
10282 tst.b LOCAL_HI(%a0) # is dst a DENORM?
10283 bmi.b ovfl_sc_norm # no
10284
10285# dst op is a DENORM. we have to normalize the mantissa to see if the
10286# result would be inexact for the given precision. make a copy of the
10287# dst so we don't screw up the version passed to us.
10288 mov.w LOCAL_EX(%a0),FP_SCR0_EX(%a6)
10289 mov.l LOCAL_HI(%a0),FP_SCR0_HI(%a6)
10290 mov.l LOCAL_LO(%a0),FP_SCR0_LO(%a6)
10291 lea FP_SCR0(%a6),%a0 # pass ptr to FP_SCR0
10292 movm.l &0xc080,-(%sp) # save d0-d1/a0
10293 bsr.l norm # normalize mantissa
10294 movm.l (%sp)+,&0x0103 # restore d0-d1/a0
10295
10296ovfl_sc_norm:
10297 cmpi.b %d1,&0x40 # is prec dbl?
10298 bne.b ovfl_sc_dbl # no; sgl
10299ovfl_sc_sgl:
10300 tst.l LOCAL_LO(%a0) # is lo lw of sgl set?
10301 bne.b ovfl_sc_inx # yes
10302 tst.b 3+LOCAL_HI(%a0) # is lo byte of hi lw set?
10303 bne.b ovfl_sc_inx # yes
10304 bra.b ovfl_work # don't set INEX2
10305ovfl_sc_dbl:
10306 mov.l LOCAL_LO(%a0),%d1 # are any of lo 11 bits of
10307 andi.l &0x7ff,%d1 # dbl mantissa set?
10308 beq.b ovfl_work # no; don't set INEX2
10309ovfl_sc_inx:
10310 ori.l &inex2_mask,USER_FPSR(%a6) # set INEX2
10311 bra.b ovfl_work # continue
10312
10313 global t_ovfl
10314t_ovfl:
10315 ori.l &ovfinx_mask,USER_FPSR(%a6) # set OVFL/INEX2/AOVFL/AINEX
10316
10317ovfl_work:
10318 tst.b LOCAL_EX(%a0) # what is the sign?
10319 smi.b %d1 # set d1 accordingly
10320 bsr.l ovf_res # calc default ovfl result
10321 mov.b %d0,FPSR_CC(%a6) # insert new ccodes
10322 fmovm.x (%a0),&0x80 # return default result in fp0
10323
10324 fmov.s &0x00000000,%fp1 # return EXOP in fp1
10325 rts
10326
10327# t_ovfl2 ALWAYS tells ovf_res to create a positive result
10328 global t_ovfl2
10329t_ovfl2:
10330 ori.l &ovfinx_mask,USER_FPSR(%a6) # set OVFL/INEX2/AOVFL/AINEX
10331
10332 sf.b %d1 # clear sign flag for positive
10333 bsr.l ovf_res # calc default ovfl result
10334 mov.b %d0,FPSR_CC(%a6) # insert new ccodes
10335 fmovm.x (%a0),&0x80 # return default result in fp0
10336
10337 fmov.s &0x00000000,%fp1 # return EXOP in fp1
10338 rts
10339
10340#################################################################
10341# t_catch(): #
10342# - the last operation of a transcendental emulation #
10343# routine may have caused an underflow or overflow. #
10344# we find out if this occurred by doing an fsave and #
10345# checking the exception bit. if one did occur, then we #
10346# jump to fgen_except() which creates the default #
10347# result and EXOP for us. #
10348#################################################################
10349 global t_catch
10350t_catch:
10351
10352 fsave -(%sp)
10353 tst.b 0x2(%sp)
10354 bmi.b catch
10355 add.l &0xc,%sp
10356
10357#################################################################
10358# INEX2 exception: #
10359# - The inex2 and ainex bits are set. #
10360#################################################################
10361 global t_inx2
10362t_inx2:
10363 fblt.w t_minx2
10364 fbeq.w inx2_zero
10365
10366 global t_pinx2
10367t_pinx2:
10368 ori.w &inx2a_mask,2+USER_FPSR(%a6) # set INEX2/AINEX
10369 rts
10370
10371 global t_minx2
10372t_minx2:
10373 ori.l &inx2a_mask+neg_mask,USER_FPSR(%a6) # set N/INEX2/AINEX
10374 rts
10375
10376inx2_zero:
10377 mov.b &z_bmask,FPSR_CC(%a6)
10378 ori.w &inx2a_mask,2+USER_FPSR(%a6) # set INEX2/AINEX
10379 rts
10380
10381# an underflow or overflow exception occurred.
10382# we must set INEX/AINEX since the fmul/fdiv/fmov emulation may not!
10383catch:
10384 ori.w &inx2a_mask,FPSR_EXCEPT(%a6)
10385catch2:
10386 bsr.l fgen_except
10387 add.l &0xc,%sp
10388 rts
10389
10390 global t_catch2
10391t_catch2:
10392
10393 fsave -(%sp)
10394
10395 tst.b 0x2(%sp)
10396 bmi.b catch2
10397 add.l &0xc,%sp
10398
10399 fmov.l %fpsr,%d0
10400 or.l %d0,USER_FPSR(%a6)
10401
10402 rts
10403
10404#########################################################################
10405
10406#########################################################################
10407# unf_res(): underflow default result calculation for transcendentals #
10408# #
10409# INPUT: #
10410# d0 : rnd mode,precision #
10411# d1.b : sign bit of result ('11111111 = (-) ; '00000000 = (+)) #
10412# OUTPUT: #
10413# a0 : points to result (in instruction memory) #
10414#########################################################################
10415unf_sub:
10416 ori.l &unfinx_mask,USER_FPSR(%a6)
10417
10418 andi.w &0x10,%d1 # keep sign bit in 4th spot
10419
10420 lsr.b &0x4,%d0 # shift rnd prec,mode to lo bits
10421 andi.b &0xf,%d0 # strip hi rnd mode bit
10422 or.b %d1,%d0 # concat {sgn,mode,prec}
10423
10424 mov.l %d0,%d1 # make a copy
10425 lsl.b &0x1,%d1 # mult index 2 by 2
10426
10427 mov.b (tbl_unf_cc.b,%pc,%d0.w*1),FPSR_CC(%a6) # insert ccode bits
10428 lea (tbl_unf_result.b,%pc,%d1.w*8),%a0 # grab result ptr
10429 rts
10430
10431tbl_unf_cc:
10432 byte 0x4, 0x4, 0x4, 0x0
10433 byte 0x4, 0x4, 0x4, 0x0
10434 byte 0x4, 0x4, 0x4, 0x0
10435 byte 0x0, 0x0, 0x0, 0x0
10436 byte 0x8+0x4, 0x8+0x4, 0x8, 0x8+0x4
10437 byte 0x8+0x4, 0x8+0x4, 0x8, 0x8+0x4
10438 byte 0x8+0x4, 0x8+0x4, 0x8, 0x8+0x4
10439
10440tbl_unf_result:
10441 long 0x00000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
10442 long 0x00000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
10443 long 0x00000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
10444 long 0x00000000, 0x00000000, 0x00000001, 0x0 # MIN; ext
10445
10446 long 0x3f810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
10447 long 0x3f810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
10448 long 0x3f810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
10449 long 0x3f810000, 0x00000100, 0x00000000, 0x0 # MIN; sgl
10450
10451 long 0x3c010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
10452 long 0x3c010000, 0x00000000, 0x00000000, 0x0 # ZER0;dbl
10453 long 0x3c010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
10454 long 0x3c010000, 0x00000000, 0x00000800, 0x0 # MIN; dbl
10455
10456 long 0x0,0x0,0x0,0x0
10457 long 0x0,0x0,0x0,0x0
10458 long 0x0,0x0,0x0,0x0
10459 long 0x0,0x0,0x0,0x0
10460
10461 long 0x80000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
10462 long 0x80000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
10463 long 0x80000000, 0x00000000, 0x00000001, 0x0 # MIN; ext
10464 long 0x80000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
10465
10466 long 0xbf810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
10467 long 0xbf810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
10468 long 0xbf810000, 0x00000100, 0x00000000, 0x0 # MIN; sgl
10469 long 0xbf810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
10470
10471 long 0xbc010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
10472 long 0xbc010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
10473 long 0xbc010000, 0x00000000, 0x00000800, 0x0 # MIN; dbl
10474 long 0xbc010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
10475
10476############################################################
10477
10478#########################################################################
10479# src_zero(): Return signed zero according to sign of src operand. #
10480#########################################################################
10481 global src_zero
10482src_zero:
10483 tst.b SRC_EX(%a0) # get sign of src operand
10484 bmi.b ld_mzero # if neg, load neg zero
10485
10486#
10487# ld_pzero(): return a positive zero.
10488#
10489 global ld_pzero
10490ld_pzero:
10491 fmov.s &0x00000000,%fp0 # load +0
10492 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10493 rts
10494
10495# ld_mzero(): return a negative zero.
10496 global ld_mzero
10497ld_mzero:
10498 fmov.s &0x80000000,%fp0 # load -0
10499 mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
10500 rts
10501
10502#########################################################################
10503# dst_zero(): Return signed zero according to sign of dst operand. #
10504#########################################################################
10505 global dst_zero
10506dst_zero:
10507 tst.b DST_EX(%a1) # get sign of dst operand
10508 bmi.b ld_mzero # if neg, load neg zero
10509 bra.b ld_pzero # load positive zero
10510
10511#########################################################################
10512# src_inf(): Return signed inf according to sign of src operand. #
10513#########################################################################
10514 global src_inf
10515src_inf:
10516 tst.b SRC_EX(%a0) # get sign of src operand
10517 bmi.b ld_minf # if negative branch
10518
10519#
10520# ld_pinf(): return a positive infinity.
10521#
10522 global ld_pinf
10523ld_pinf:
10524 fmov.s &0x7f800000,%fp0 # load +INF
10525 mov.b &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit
10526 rts
10527
10528#
10529# ld_minf():return a negative infinity.
10530#
10531 global ld_minf
10532ld_minf:
10533 fmov.s &0xff800000,%fp0 # load -INF
10534 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
10535 rts
10536
10537#########################################################################
10538# dst_inf(): Return signed inf according to sign of dst operand. #
10539#########################################################################
10540 global dst_inf
10541dst_inf:
10542 tst.b DST_EX(%a1) # get sign of dst operand
10543 bmi.b ld_minf # if negative branch
10544 bra.b ld_pinf
10545
10546 global szr_inf
10547#################################################################
10548# szr_inf(): Return +ZERO for a negative src operand or #
10549# +INF for a positive src operand. #
10550# Routine used for fetox, ftwotox, and ftentox. #
10551#################################################################
10552szr_inf:
10553 tst.b SRC_EX(%a0) # check sign of source
10554 bmi.b ld_pzero
10555 bra.b ld_pinf
10556
10557#########################################################################
10558# sopr_inf(): Return +INF for a positive src operand or #
10559# jump to operand error routine for a negative src operand. #
10560# Routine used for flogn, flognp1, flog10, and flog2. #
10561#########################################################################
10562 global sopr_inf
10563sopr_inf:
10564 tst.b SRC_EX(%a0) # check sign of source
10565 bmi.w t_operr
10566 bra.b ld_pinf
10567
10568#################################################################
10569# setoxm1i(): Return minus one for a negative src operand or #
10570# positive infinity for a positive src operand. #
10571# Routine used for fetoxm1. #
10572#################################################################
10573 global setoxm1i
10574setoxm1i:
10575 tst.b SRC_EX(%a0) # check sign of source
10576 bmi.b ld_mone
10577 bra.b ld_pinf
10578
10579#########################################################################
10580# src_one(): Return signed one according to sign of src operand. #
10581#########################################################################
10582 global src_one
10583src_one:
10584 tst.b SRC_EX(%a0) # check sign of source
10585 bmi.b ld_mone
10586
10587#
10588# ld_pone(): return positive one.
10589#
10590 global ld_pone
10591ld_pone:
10592 fmov.s &0x3f800000,%fp0 # load +1
10593 clr.b FPSR_CC(%a6)
10594 rts
10595
10596#
10597# ld_mone(): return negative one.
10598#
10599 global ld_mone
10600ld_mone:
10601 fmov.s &0xbf800000,%fp0 # load -1
10602 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
10603 rts
10604
10605ppiby2: long 0x3fff0000, 0xc90fdaa2, 0x2168c235
10606mpiby2: long 0xbfff0000, 0xc90fdaa2, 0x2168c235
10607
10608#################################################################
10609# spi_2(): Return signed PI/2 according to sign of src operand. #
10610#################################################################
10611 global spi_2
10612spi_2:
10613 tst.b SRC_EX(%a0) # check sign of source
10614 bmi.b ld_mpi2
10615
10616#
10617# ld_ppi2(): return positive PI/2.
10618#
10619 global ld_ppi2
10620ld_ppi2:
10621 fmov.l %d0,%fpcr
10622 fmov.x ppiby2(%pc),%fp0 # load +pi/2
10623 bra.w t_pinx2 # set INEX2
10624
10625#
10626# ld_mpi2(): return negative PI/2.
10627#
10628 global ld_mpi2
10629ld_mpi2:
10630 fmov.l %d0,%fpcr
10631 fmov.x mpiby2(%pc),%fp0 # load -pi/2
10632 bra.w t_minx2 # set INEX2
10633
10634####################################################
10635# The following routines give support for fsincos. #
10636####################################################
10637
10638#
10639# ssincosz(): When the src operand is ZERO, store a one in the
10640# cosine register and return a ZERO in fp0 w/ the same sign
10641# as the src operand.
10642#
10643 global ssincosz
10644ssincosz:
10645 fmov.s &0x3f800000,%fp1
10646 tst.b SRC_EX(%a0) # test sign
10647 bpl.b sincoszp
10648 fmov.s &0x80000000,%fp0 # return sin result in fp0
10649 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6)
10650 bra.b sto_cos # store cosine result
10651sincoszp:
10652 fmov.s &0x00000000,%fp0 # return sin result in fp0
10653 mov.b &z_bmask,FPSR_CC(%a6)
10654 bra.b sto_cos # store cosine result
10655
10656#
10657# ssincosi(): When the src operand is INF, store a QNAN in the cosine
10658# register and jump to the operand error routine for negative
10659# src operands.
10660#
10661 global ssincosi
10662ssincosi:
10663 fmov.x qnan(%pc),%fp1 # load NAN
10664 bsr.l sto_cos # store cosine result
10665 bra.w t_operr
10666
10667#
10668# ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
10669# register and branch to the src QNAN routine.
10670#
10671 global ssincosqnan
10672ssincosqnan:
10673 fmov.x LOCAL_EX(%a0),%fp1
10674 bsr.l sto_cos
10675 bra.w src_qnan
10676
10677#
10678# ssincossnan(): When the src operand is an SNAN, store the SNAN w/ the SNAN bit set
10679# in the cosine register and branch to the src SNAN routine.
10680#
10681 global ssincossnan
10682ssincossnan:
10683 fmov.x LOCAL_EX(%a0),%fp1
10684 bsr.l sto_cos
10685 bra.w src_snan
10686
10687########################################################################
10688
10689#########################################################################
10690# sto_cos(): store fp1 to the fpreg designated by the CMDREG dst field. #
10691# fp1 holds the result of the cosine portion of ssincos(). #
10692# the value in fp1 will not take any exceptions when moved. #
10693# INPUT: #
10694# fp1 : fp value to store #
10695# MODIFIED: #
10696# d0 #
10697#########################################################################
10698 global sto_cos
10699sto_cos:
10700 mov.b 1+EXC_CMDREG(%a6),%d0
10701 andi.w &0x7,%d0
10702 mov.w (tbl_sto_cos.b,%pc,%d0.w*2),%d0
10703 jmp (tbl_sto_cos.b,%pc,%d0.w*1)
10704
10705tbl_sto_cos:
10706 short sto_cos_0 - tbl_sto_cos
10707 short sto_cos_1 - tbl_sto_cos
10708 short sto_cos_2 - tbl_sto_cos
10709 short sto_cos_3 - tbl_sto_cos
10710 short sto_cos_4 - tbl_sto_cos
10711 short sto_cos_5 - tbl_sto_cos
10712 short sto_cos_6 - tbl_sto_cos
10713 short sto_cos_7 - tbl_sto_cos
10714
10715sto_cos_0:
10716 fmovm.x &0x40,EXC_FP0(%a6)
10717 rts
10718sto_cos_1:
10719 fmovm.x &0x40,EXC_FP1(%a6)
10720 rts
10721sto_cos_2:
10722 fmov.x %fp1,%fp2
10723 rts
10724sto_cos_3:
10725 fmov.x %fp1,%fp3
10726 rts
10727sto_cos_4:
10728 fmov.x %fp1,%fp4
10729 rts
10730sto_cos_5:
10731 fmov.x %fp1,%fp5
10732 rts
10733sto_cos_6:
10734 fmov.x %fp1,%fp6
10735 rts
10736sto_cos_7:
10737 fmov.x %fp1,%fp7
10738 rts
10739
10740##################################################################
10741 global smod_sdnrm
10742 global smod_snorm
10743smod_sdnrm:
10744smod_snorm:
10745 mov.b DTAG(%a6),%d1
10746 beq.l smod
10747 cmpi.b %d1,&ZERO
10748 beq.w smod_zro
10749 cmpi.b %d1,&INF
10750 beq.l t_operr
10751 cmpi.b %d1,&DENORM
10752 beq.l smod
10753 cmpi.b %d1,&SNAN
10754 beq.l dst_snan
10755 bra.l dst_qnan
10756
10757 global smod_szero
10758smod_szero:
10759 mov.b DTAG(%a6),%d1
10760 beq.l t_operr
10761 cmpi.b %d1,&ZERO
10762 beq.l t_operr
10763 cmpi.b %d1,&INF
10764 beq.l t_operr
10765 cmpi.b %d1,&DENORM
10766 beq.l t_operr
10767 cmpi.b %d1,&QNAN
10768 beq.l dst_qnan
10769 bra.l dst_snan
10770
10771 global smod_sinf
10772smod_sinf:
10773 mov.b DTAG(%a6),%d1
10774 beq.l smod_fpn
10775 cmpi.b %d1,&ZERO
10776 beq.l smod_zro
10777 cmpi.b %d1,&INF
10778 beq.l t_operr
10779 cmpi.b %d1,&DENORM
10780 beq.l smod_fpn
10781 cmpi.b %d1,&QNAN
10782 beq.l dst_qnan
10783 bra.l dst_snan
10784
10785smod_zro:
10786srem_zro:
10787 mov.b SRC_EX(%a0),%d1 # get src sign
10788 mov.b DST_EX(%a1),%d0 # get dst sign
10789 eor.b %d0,%d1 # get qbyte sign
10790 andi.b &0x80,%d1
10791 mov.b %d1,FPSR_QBYTE(%a6)
10792 tst.b %d0
10793 bpl.w ld_pzero
10794 bra.w ld_mzero
10795
10796smod_fpn:
10797srem_fpn:
10798 clr.b FPSR_QBYTE(%a6)
10799 mov.l %d0,-(%sp)
10800 mov.b SRC_EX(%a0),%d1 # get src sign
10801 mov.b DST_EX(%a1),%d0 # get dst sign
10802 eor.b %d0,%d1 # get qbyte sign
10803 andi.b &0x80,%d1
10804 mov.b %d1,FPSR_QBYTE(%a6)
10805 cmpi.b DTAG(%a6),&DENORM
10806 bne.b smod_nrm
10807 lea DST(%a1),%a0
10808 mov.l (%sp)+,%d0
10809 bra t_resdnrm
10810smod_nrm:
10811 fmov.l (%sp)+,%fpcr
10812 fmov.x DST(%a1),%fp0
10813 tst.b DST_EX(%a1)
10814 bmi.b smod_nrm_neg
10815 rts
10816
10817smod_nrm_neg:
10818 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode
10819 rts
10820
10821#########################################################################
10822 global srem_snorm
10823 global srem_sdnrm
10824srem_sdnrm:
10825srem_snorm:
10826 mov.b DTAG(%a6),%d1
10827 beq.l srem
10828 cmpi.b %d1,&ZERO
10829 beq.w srem_zro
10830 cmpi.b %d1,&INF
10831 beq.l t_operr
10832 cmpi.b %d1,&DENORM
10833 beq.l srem
10834 cmpi.b %d1,&QNAN
10835 beq.l dst_qnan
10836 bra.l dst_snan
10837
10838 global srem_szero
10839srem_szero:
10840 mov.b DTAG(%a6),%d1
10841 beq.l t_operr
10842 cmpi.b %d1,&ZERO
10843 beq.l t_operr
10844 cmpi.b %d1,&INF
10845 beq.l t_operr
10846 cmpi.b %d1,&DENORM
10847 beq.l t_operr
10848 cmpi.b %d1,&QNAN
10849 beq.l dst_qnan
10850 bra.l dst_snan
10851
10852 global srem_sinf
10853srem_sinf:
10854 mov.b DTAG(%a6),%d1
10855 beq.w srem_fpn
10856 cmpi.b %d1,&ZERO
10857 beq.w srem_zro
10858 cmpi.b %d1,&INF
10859 beq.l t_operr
10860 cmpi.b %d1,&DENORM
10861 beq.l srem_fpn
10862 cmpi.b %d1,&QNAN
10863 beq.l dst_qnan
10864 bra.l dst_snan
10865
10866#########################################################################
10867 global sscale_snorm
10868 global sscale_sdnrm
10869sscale_snorm:
10870sscale_sdnrm:
10871 mov.b DTAG(%a6),%d1
10872 beq.l sscale
10873 cmpi.b %d1,&ZERO
10874 beq.l dst_zero
10875 cmpi.b %d1,&INF
10876 beq.l dst_inf
10877 cmpi.b %d1,&DENORM
10878 beq.l sscale
10879 cmpi.b %d1,&QNAN
10880 beq.l dst_qnan
10881 bra.l dst_snan
10882
10883 global sscale_szero
10884sscale_szero:
10885 mov.b DTAG(%a6),%d1
10886 beq.l sscale
10887 cmpi.b %d1,&ZERO
10888 beq.l dst_zero
10889 cmpi.b %d1,&INF
10890 beq.l dst_inf
10891 cmpi.b %d1,&DENORM
10892 beq.l sscale
10893 cmpi.b %d1,&QNAN
10894 beq.l dst_qnan
10895 bra.l dst_snan
10896
10897 global sscale_sinf
10898sscale_sinf:
10899 mov.b DTAG(%a6),%d1
10900 beq.l t_operr
10901 cmpi.b %d1,&QNAN
10902 beq.l dst_qnan
10903 cmpi.b %d1,&SNAN
10904 beq.l dst_snan
10905 bra.l t_operr
10906
10907########################################################################
10908
10909#
10910# sop_sqnan(): The src op for frem/fmod/fscale was a QNAN.
10911#
10912 global sop_sqnan
10913sop_sqnan:
10914 mov.b DTAG(%a6),%d1
10915 cmpi.b %d1,&QNAN
10916 beq.b dst_qnan
10917 cmpi.b %d1,&SNAN
10918 beq.b dst_snan
10919 bra.b src_qnan
10920
10921#
10922# sop_ssnan(): The src op for frem/fmod/fscale was an SNAN.
10923#
10924 global sop_ssnan
10925sop_ssnan:
10926 mov.b DTAG(%a6),%d1
10927 cmpi.b %d1,&QNAN
10928 beq.b dst_qnan_src_snan
10929 cmpi.b %d1,&SNAN
10930 beq.b dst_snan
10931 bra.b src_snan
10932
10933dst_qnan_src_snan:
10934 ori.l &snaniop_mask,USER_FPSR(%a6) # set NAN/SNAN/AIOP
10935 bra.b dst_qnan
10936
10937#
10938# dst_qnan(): Return the dst SNAN w/ the SNAN bit set.
10939#
10940 global dst_snan
10941dst_snan:
10942 fmov.x DST(%a1),%fp0 # the fmove sets the SNAN bit
10943 fmov.l %fpsr,%d0 # catch resulting status
10944 or.l %d0,USER_FPSR(%a6) # store status
10945 rts
10946
10947#
10948# dst_qnan(): Return the dst QNAN.
10949#
10950 global dst_qnan
10951dst_qnan:
10952 fmov.x DST(%a1),%fp0 # return the non-signalling nan
10953 tst.b DST_EX(%a1) # set ccodes according to QNAN sign
10954 bmi.b dst_qnan_m
10955dst_qnan_p:
10956 mov.b &nan_bmask,FPSR_CC(%a6)
10957 rts
10958dst_qnan_m:
10959 mov.b &neg_bmask+nan_bmask,FPSR_CC(%a6)
10960 rts
10961
10962#
10963# src_snan(): Return the src SNAN w/ the SNAN bit set.
10964#
10965 global src_snan
10966src_snan:
10967 fmov.x SRC(%a0),%fp0 # the fmove sets the SNAN bit
10968 fmov.l %fpsr,%d0 # catch resulting status
10969 or.l %d0,USER_FPSR(%a6) # store status
10970 rts
10971
10972#
10973# src_qnan(): Return the src QNAN.
10974#
10975 global src_qnan
10976src_qnan:
10977 fmov.x SRC(%a0),%fp0 # return the non-signalling nan
10978 tst.b SRC_EX(%a0) # set ccodes according to QNAN sign
10979 bmi.b dst_qnan_m
10980src_qnan_p:
10981 mov.b &nan_bmask,FPSR_CC(%a6)
10982 rts
10983src_qnan_m:
10984 mov.b &neg_bmask+nan_bmask,FPSR_CC(%a6)
10985 rts
10986
10987#
10988# fkern2.s:
10989# These entry points are used by the exception handler
10990# routines where an instruction is selected by an index into
10991# a large jump table corresponding to a given instruction which
10992# has been decoded. Flow continues here where we now decode
10993# further accoding to the source operand type.
10994#
10995
10996 global fsinh
10997fsinh:
10998 mov.b STAG(%a6),%d1
10999 beq.l ssinh
11000 cmpi.b %d1,&ZERO
11001 beq.l src_zero
11002 cmpi.b %d1,&INF
11003 beq.l src_inf
11004 cmpi.b %d1,&DENORM
11005 beq.l ssinhd
11006 cmpi.b %d1,&QNAN
11007 beq.l src_qnan
11008 bra.l src_snan
11009
11010 global flognp1
11011flognp1:
11012 mov.b STAG(%a6),%d1
11013 beq.l slognp1
11014 cmpi.b %d1,&ZERO
11015 beq.l src_zero
11016 cmpi.b %d1,&INF
11017 beq.l sopr_inf
11018 cmpi.b %d1,&DENORM
11019 beq.l slognp1d
11020 cmpi.b %d1,&QNAN
11021 beq.l src_qnan
11022 bra.l src_snan
11023
11024 global fetoxm1
11025fetoxm1:
11026 mov.b STAG(%a6),%d1
11027 beq.l setoxm1
11028 cmpi.b %d1,&ZERO
11029 beq.l src_zero
11030 cmpi.b %d1,&INF
11031 beq.l setoxm1i
11032 cmpi.b %d1,&DENORM
11033 beq.l setoxm1d
11034 cmpi.b %d1,&QNAN
11035 beq.l src_qnan
11036 bra.l src_snan
11037
11038 global ftanh
11039ftanh:
11040 mov.b STAG(%a6),%d1
11041 beq.l stanh
11042 cmpi.b %d1,&ZERO
11043 beq.l src_zero
11044 cmpi.b %d1,&INF
11045 beq.l src_one
11046 cmpi.b %d1,&DENORM
11047 beq.l stanhd
11048 cmpi.b %d1,&QNAN
11049 beq.l src_qnan
11050 bra.l src_snan
11051
11052 global fatan
11053fatan:
11054 mov.b STAG(%a6),%d1
11055 beq.l satan
11056 cmpi.b %d1,&ZERO
11057 beq.l src_zero
11058 cmpi.b %d1,&INF
11059 beq.l spi_2
11060 cmpi.b %d1,&DENORM
11061 beq.l satand
11062 cmpi.b %d1,&QNAN
11063 beq.l src_qnan
11064 bra.l src_snan
11065
11066 global fasin
11067fasin:
11068 mov.b STAG(%a6),%d1
11069 beq.l sasin
11070 cmpi.b %d1,&ZERO
11071 beq.l src_zero
11072 cmpi.b %d1,&INF
11073 beq.l t_operr
11074 cmpi.b %d1,&DENORM
11075 beq.l sasind
11076 cmpi.b %d1,&QNAN
11077 beq.l src_qnan
11078 bra.l src_snan
11079
11080 global fatanh
11081fatanh:
11082 mov.b STAG(%a6),%d1
11083 beq.l satanh
11084 cmpi.b %d1,&ZERO
11085 beq.l src_zero
11086 cmpi.b %d1,&INF
11087 beq.l t_operr
11088 cmpi.b %d1,&DENORM
11089 beq.l satanhd
11090 cmpi.b %d1,&QNAN
11091 beq.l src_qnan
11092 bra.l src_snan
11093
11094 global fsine
11095fsine:
11096 mov.b STAG(%a6),%d1
11097 beq.l ssin
11098 cmpi.b %d1,&ZERO
11099 beq.l src_zero
11100 cmpi.b %d1,&INF
11101 beq.l t_operr
11102 cmpi.b %d1,&DENORM
11103 beq.l ssind
11104 cmpi.b %d1,&QNAN
11105 beq.l src_qnan
11106 bra.l src_snan
11107
11108 global ftan
11109ftan:
11110 mov.b STAG(%a6),%d1
11111 beq.l stan
11112 cmpi.b %d1,&ZERO
11113 beq.l src_zero
11114 cmpi.b %d1,&INF
11115 beq.l t_operr
11116 cmpi.b %d1,&DENORM
11117 beq.l stand
11118 cmpi.b %d1,&QNAN
11119 beq.l src_qnan
11120 bra.l src_snan
11121
11122 global fetox
11123fetox:
11124 mov.b STAG(%a6),%d1
11125 beq.l setox
11126 cmpi.b %d1,&ZERO
11127 beq.l ld_pone
11128 cmpi.b %d1,&INF
11129 beq.l szr_inf
11130 cmpi.b %d1,&DENORM
11131 beq.l setoxd
11132 cmpi.b %d1,&QNAN
11133 beq.l src_qnan
11134 bra.l src_snan
11135
11136 global ftwotox
11137ftwotox:
11138 mov.b STAG(%a6),%d1
11139 beq.l stwotox
11140 cmpi.b %d1,&ZERO
11141 beq.l ld_pone
11142 cmpi.b %d1,&INF
11143 beq.l szr_inf
11144 cmpi.b %d1,&DENORM
11145 beq.l stwotoxd
11146 cmpi.b %d1,&QNAN
11147 beq.l src_qnan
11148 bra.l src_snan
11149
11150 global ftentox
11151ftentox:
11152 mov.b STAG(%a6),%d1
11153 beq.l stentox
11154 cmpi.b %d1,&ZERO
11155 beq.l ld_pone
11156 cmpi.b %d1,&INF
11157 beq.l szr_inf
11158 cmpi.b %d1,&DENORM
11159 beq.l stentoxd
11160 cmpi.b %d1,&QNAN
11161 beq.l src_qnan
11162 bra.l src_snan
11163
11164 global flogn
11165flogn:
11166 mov.b STAG(%a6),%d1
11167 beq.l slogn
11168 cmpi.b %d1,&ZERO
11169 beq.l t_dz2
11170 cmpi.b %d1,&INF
11171 beq.l sopr_inf
11172 cmpi.b %d1,&DENORM
11173 beq.l slognd
11174 cmpi.b %d1,&QNAN
11175 beq.l src_qnan
11176 bra.l src_snan
11177
11178 global flog10
11179flog10:
11180 mov.b STAG(%a6),%d1
11181 beq.l slog10
11182 cmpi.b %d1,&ZERO
11183 beq.l t_dz2
11184 cmpi.b %d1,&INF
11185 beq.l sopr_inf
11186 cmpi.b %d1,&DENORM
11187 beq.l slog10d
11188 cmpi.b %d1,&QNAN
11189 beq.l src_qnan
11190 bra.l src_snan
11191
11192 global flog2
11193flog2:
11194 mov.b STAG(%a6),%d1
11195 beq.l slog2
11196 cmpi.b %d1,&ZERO
11197 beq.l t_dz2
11198 cmpi.b %d1,&INF
11199 beq.l sopr_inf
11200 cmpi.b %d1,&DENORM
11201 beq.l slog2d
11202 cmpi.b %d1,&QNAN
11203 beq.l src_qnan
11204 bra.l src_snan
11205
11206 global fcosh
11207fcosh:
11208 mov.b STAG(%a6),%d1
11209 beq.l scosh
11210 cmpi.b %d1,&ZERO
11211 beq.l ld_pone
11212 cmpi.b %d1,&INF
11213 beq.l ld_pinf
11214 cmpi.b %d1,&DENORM
11215 beq.l scoshd
11216 cmpi.b %d1,&QNAN
11217 beq.l src_qnan
11218 bra.l src_snan
11219
11220 global facos
11221facos:
11222 mov.b STAG(%a6),%d1
11223 beq.l sacos
11224 cmpi.b %d1,&ZERO
11225 beq.l ld_ppi2
11226 cmpi.b %d1,&INF
11227 beq.l t_operr
11228 cmpi.b %d1,&DENORM
11229 beq.l sacosd
11230 cmpi.b %d1,&QNAN
11231 beq.l src_qnan
11232 bra.l src_snan
11233
11234 global fcos
11235fcos:
11236 mov.b STAG(%a6),%d1
11237 beq.l scos
11238 cmpi.b %d1,&ZERO
11239 beq.l ld_pone
11240 cmpi.b %d1,&INF
11241 beq.l t_operr
11242 cmpi.b %d1,&DENORM
11243 beq.l scosd
11244 cmpi.b %d1,&QNAN
11245 beq.l src_qnan
11246 bra.l src_snan
11247
11248 global fgetexp
11249fgetexp:
11250 mov.b STAG(%a6),%d1
11251 beq.l sgetexp
11252 cmpi.b %d1,&ZERO
11253 beq.l src_zero
11254 cmpi.b %d1,&INF
11255 beq.l t_operr
11256 cmpi.b %d1,&DENORM
11257 beq.l sgetexpd
11258 cmpi.b %d1,&QNAN
11259 beq.l src_qnan
11260 bra.l src_snan
11261
11262 global fgetman
11263fgetman:
11264 mov.b STAG(%a6),%d1
11265 beq.l sgetman
11266 cmpi.b %d1,&ZERO
11267 beq.l src_zero
11268 cmpi.b %d1,&INF
11269 beq.l t_operr
11270 cmpi.b %d1,&DENORM
11271 beq.l sgetmand
11272 cmpi.b %d1,&QNAN
11273 beq.l src_qnan
11274 bra.l src_snan
11275
11276 global fsincos
11277fsincos:
11278 mov.b STAG(%a6),%d1
11279 beq.l ssincos
11280 cmpi.b %d1,&ZERO
11281 beq.l ssincosz
11282 cmpi.b %d1,&INF
11283 beq.l ssincosi
11284 cmpi.b %d1,&DENORM
11285 beq.l ssincosd
11286 cmpi.b %d1,&QNAN
11287 beq.l ssincosqnan
11288 bra.l ssincossnan
11289
11290 global fmod
11291fmod:
11292 mov.b STAG(%a6),%d1
11293 beq.l smod_snorm
11294 cmpi.b %d1,&ZERO
11295 beq.l smod_szero
11296 cmpi.b %d1,&INF
11297 beq.l smod_sinf
11298 cmpi.b %d1,&DENORM
11299 beq.l smod_sdnrm
11300 cmpi.b %d1,&QNAN
11301 beq.l sop_sqnan
11302 bra.l sop_ssnan
11303
11304 global frem
11305frem:
11306 mov.b STAG(%a6),%d1
11307 beq.l srem_snorm
11308 cmpi.b %d1,&ZERO
11309 beq.l srem_szero
11310 cmpi.b %d1,&INF
11311 beq.l srem_sinf
11312 cmpi.b %d1,&DENORM
11313 beq.l srem_sdnrm
11314 cmpi.b %d1,&QNAN
11315 beq.l sop_sqnan
11316 bra.l sop_ssnan
11317
11318 global fscale
11319fscale:
11320 mov.b STAG(%a6),%d1
11321 beq.l sscale_snorm
11322 cmpi.b %d1,&ZERO
11323 beq.l sscale_szero
11324 cmpi.b %d1,&INF
11325 beq.l sscale_sinf
11326 cmpi.b %d1,&DENORM
11327 beq.l sscale_sdnrm
11328 cmpi.b %d1,&QNAN
11329 beq.l sop_sqnan
11330 bra.l sop_ssnan
11331
11332#########################################################################
11333# XDEF **************************************************************** #
11334# fgen_except(): catch an exception during transcendental #
11335# emulation #
11336# #
11337# XREF **************************************************************** #
11338# fmul() - emulate a multiply instruction #
11339# fadd() - emulate an add instruction #
11340# fin() - emulate an fmove instruction #
11341# #
11342# INPUT *************************************************************** #
11343# fp0 = destination operand #
11344# d0 = type of instruction that took exception #
11345# fsave frame = source operand #
11346# #
11347# OUTPUT ************************************************************** #
11348# fp0 = result #
11349# fp1 = EXOP #
11350# #
11351# ALGORITHM *********************************************************** #
11352# An exception occurred on the last instruction of the #
11353# transcendental emulation. hopefully, this won't be happening much #
11354# because it will be VERY slow. #
11355# The only exceptions capable of passing through here are #
11356# Overflow, Underflow, and Unsupported Data Type. #
11357# #
11358#########################################################################
11359
11360 global fgen_except
11361fgen_except:
11362 cmpi.b 0x3(%sp),&0x7 # is exception UNSUPP?
11363 beq.b fge_unsupp # yes
11364
11365 mov.b &NORM,STAG(%a6)
11366
11367fge_cont:
11368 mov.b &NORM,DTAG(%a6)
11369
11370# ok, I have a problem with putting the dst op at FP_DST. the emulation
11371# routines aren't supposed to alter the operands but we've just squashed
11372# FP_DST here...
11373
11374# 8/17/93 - this turns out to be more of a "cleanliness" standpoint
11375# then a potential bug. to begin with, only the dyadic functions
11376# frem,fmod, and fscale would get the dst trashed here. But, for
11377# the 060SP, the FP_DST is never used again anyways.
11378 fmovm.x &0x80,FP_DST(%a6) # dst op is in fp0
11379
11380 lea 0x4(%sp),%a0 # pass: ptr to src op
11381 lea FP_DST(%a6),%a1 # pass: ptr to dst op
11382
11383 cmpi.b %d1,&FMOV_OP
11384 beq.b fge_fin # it was an "fmov"
11385 cmpi.b %d1,&FADD_OP
11386 beq.b fge_fadd # it was an "fadd"
11387fge_fmul:
11388 bsr.l fmul
11389 rts
11390fge_fadd:
11391 bsr.l fadd
11392 rts
11393fge_fin:
11394 bsr.l fin
11395 rts
11396
11397fge_unsupp:
11398 mov.b &DENORM,STAG(%a6)
11399 bra.b fge_cont
11400
11401#
11402# This table holds the offsets of the emulation routines for each individual
11403# math operation relative to the address of this table. Included are
11404# routines like fadd/fmul/fabs as well as the transcendentals.
11405# The location within the table is determined by the extension bits of the
11406# operation longword.
11407#
11408
11409 swbeg &109
11410tbl_unsupp:
11411 long fin - tbl_unsupp # 00: fmove
11412 long fint - tbl_unsupp # 01: fint
11413 long fsinh - tbl_unsupp # 02: fsinh
11414 long fintrz - tbl_unsupp # 03: fintrz
11415 long fsqrt - tbl_unsupp # 04: fsqrt
11416 long tbl_unsupp - tbl_unsupp
11417 long flognp1 - tbl_unsupp # 06: flognp1
11418 long tbl_unsupp - tbl_unsupp
11419 long fetoxm1 - tbl_unsupp # 08: fetoxm1
11420 long ftanh - tbl_unsupp # 09: ftanh
11421 long fatan - tbl_unsupp # 0a: fatan
11422 long tbl_unsupp - tbl_unsupp
11423 long fasin - tbl_unsupp # 0c: fasin
11424 long fatanh - tbl_unsupp # 0d: fatanh
11425 long fsine - tbl_unsupp # 0e: fsin
11426 long ftan - tbl_unsupp # 0f: ftan
11427 long fetox - tbl_unsupp # 10: fetox
11428 long ftwotox - tbl_unsupp # 11: ftwotox
11429 long ftentox - tbl_unsupp # 12: ftentox
11430 long tbl_unsupp - tbl_unsupp
11431 long flogn - tbl_unsupp # 14: flogn
11432 long flog10 - tbl_unsupp # 15: flog10
11433 long flog2 - tbl_unsupp # 16: flog2
11434 long tbl_unsupp - tbl_unsupp
11435 long fabs - tbl_unsupp # 18: fabs
11436 long fcosh - tbl_unsupp # 19: fcosh
11437 long fneg - tbl_unsupp # 1a: fneg
11438 long tbl_unsupp - tbl_unsupp
11439 long facos - tbl_unsupp # 1c: facos
11440 long fcos - tbl_unsupp # 1d: fcos
11441 long fgetexp - tbl_unsupp # 1e: fgetexp
11442 long fgetman - tbl_unsupp # 1f: fgetman
11443 long fdiv - tbl_unsupp # 20: fdiv
11444 long fmod - tbl_unsupp # 21: fmod
11445 long fadd - tbl_unsupp # 22: fadd
11446 long fmul - tbl_unsupp # 23: fmul
11447 long fsgldiv - tbl_unsupp # 24: fsgldiv
11448 long frem - tbl_unsupp # 25: frem
11449 long fscale - tbl_unsupp # 26: fscale
11450 long fsglmul - tbl_unsupp # 27: fsglmul
11451 long fsub - tbl_unsupp # 28: fsub
11452 long tbl_unsupp - tbl_unsupp
11453 long tbl_unsupp - tbl_unsupp
11454 long tbl_unsupp - tbl_unsupp
11455 long tbl_unsupp - tbl_unsupp
11456 long tbl_unsupp - tbl_unsupp
11457 long tbl_unsupp - tbl_unsupp
11458 long tbl_unsupp - tbl_unsupp
11459 long fsincos - tbl_unsupp # 30: fsincos
11460 long fsincos - tbl_unsupp # 31: fsincos
11461 long fsincos - tbl_unsupp # 32: fsincos
11462 long fsincos - tbl_unsupp # 33: fsincos
11463 long fsincos - tbl_unsupp # 34: fsincos
11464 long fsincos - tbl_unsupp # 35: fsincos
11465 long fsincos - tbl_unsupp # 36: fsincos
11466 long fsincos - tbl_unsupp # 37: fsincos
11467 long fcmp - tbl_unsupp # 38: fcmp
11468 long tbl_unsupp - tbl_unsupp
11469 long ftst - tbl_unsupp # 3a: ftst
11470 long tbl_unsupp - tbl_unsupp
11471 long tbl_unsupp - tbl_unsupp
11472 long tbl_unsupp - tbl_unsupp
11473 long tbl_unsupp - tbl_unsupp
11474 long tbl_unsupp - tbl_unsupp
11475 long fsin - tbl_unsupp # 40: fsmove
11476 long fssqrt - tbl_unsupp # 41: fssqrt
11477 long tbl_unsupp - tbl_unsupp
11478 long tbl_unsupp - tbl_unsupp
11479 long fdin - tbl_unsupp # 44: fdmove
11480 long fdsqrt - tbl_unsupp # 45: fdsqrt
11481 long tbl_unsupp - tbl_unsupp
11482 long tbl_unsupp - tbl_unsupp
11483 long tbl_unsupp - tbl_unsupp
11484 long tbl_unsupp - tbl_unsupp
11485 long tbl_unsupp - tbl_unsupp
11486 long tbl_unsupp - tbl_unsupp
11487 long tbl_unsupp - tbl_unsupp
11488 long tbl_unsupp - tbl_unsupp
11489 long tbl_unsupp - tbl_unsupp
11490 long tbl_unsupp - tbl_unsupp
11491 long tbl_unsupp - tbl_unsupp
11492 long tbl_unsupp - tbl_unsupp
11493 long tbl_unsupp - tbl_unsupp
11494 long tbl_unsupp - tbl_unsupp
11495 long tbl_unsupp - tbl_unsupp
11496 long tbl_unsupp - tbl_unsupp
11497 long tbl_unsupp - tbl_unsupp
11498 long tbl_unsupp - tbl_unsupp
11499 long fsabs - tbl_unsupp # 58: fsabs
11500 long tbl_unsupp - tbl_unsupp
11501 long fsneg - tbl_unsupp # 5a: fsneg
11502 long tbl_unsupp - tbl_unsupp
11503 long fdabs - tbl_unsupp # 5c: fdabs
11504 long tbl_unsupp - tbl_unsupp
11505 long fdneg - tbl_unsupp # 5e: fdneg
11506 long tbl_unsupp - tbl_unsupp
11507 long fsdiv - tbl_unsupp # 60: fsdiv
11508 long tbl_unsupp - tbl_unsupp
11509 long fsadd - tbl_unsupp # 62: fsadd
11510 long fsmul - tbl_unsupp # 63: fsmul
11511 long fddiv - tbl_unsupp # 64: fddiv
11512 long tbl_unsupp - tbl_unsupp
11513 long fdadd - tbl_unsupp # 66: fdadd
11514 long fdmul - tbl_unsupp # 67: fdmul
11515 long fssub - tbl_unsupp # 68: fssub
11516 long tbl_unsupp - tbl_unsupp
11517 long tbl_unsupp - tbl_unsupp
11518 long tbl_unsupp - tbl_unsupp
11519 long fdsub - tbl_unsupp # 6c: fdsub
11520
11521#########################################################################
11522# XDEF **************************************************************** #
11523# fmul(): emulates the fmul instruction #
11524# fsmul(): emulates the fsmul instruction #
11525# fdmul(): emulates the fdmul instruction #
11526# #
11527# XREF **************************************************************** #
11528# scale_to_zero_src() - scale src exponent to zero #
11529# scale_to_zero_dst() - scale dst exponent to zero #
11530# unf_res() - return default underflow result #
11531# ovf_res() - return default overflow result #
11532# res_qnan() - return QNAN result #
11533# res_snan() - return SNAN result #
11534# #
11535# INPUT *************************************************************** #
11536# a0 = pointer to extended precision source operand #
11537# a1 = pointer to extended precision destination operand #
11538# d0 rnd prec,mode #
11539# #
11540# OUTPUT ************************************************************** #
11541# fp0 = result #
11542# fp1 = EXOP (if exception occurred) #
11543# #
11544# ALGORITHM *********************************************************** #
11545# Handle NANs, infinities, and zeroes as special cases. Divide #
11546# norms/denorms into ext/sgl/dbl precision. #
11547# For norms/denorms, scale the exponents such that a multiply #
11548# instruction won't cause an exception. Use the regular fmul to #
11549# compute a result. Check if the regular operands would have taken #
11550# an exception. If so, return the default overflow/underflow result #
11551# and return the EXOP if exceptions are enabled. Else, scale the #
11552# result operand to the proper exponent. #
11553# #
11554#########################################################################
11555
11556 align 0x10
11557tbl_fmul_ovfl:
11558 long 0x3fff - 0x7ffe # ext_max
11559 long 0x3fff - 0x407e # sgl_max
11560 long 0x3fff - 0x43fe # dbl_max
11561tbl_fmul_unfl:
11562 long 0x3fff + 0x0001 # ext_unfl
11563 long 0x3fff - 0x3f80 # sgl_unfl
11564 long 0x3fff - 0x3c00 # dbl_unfl
11565
11566 global fsmul
11567fsmul:
11568 andi.b &0x30,%d0 # clear rnd prec
11569 ori.b &s_mode*0x10,%d0 # insert sgl prec
11570 bra.b fmul
11571
11572 global fdmul
11573fdmul:
11574 andi.b &0x30,%d0
11575 ori.b &d_mode*0x10,%d0 # insert dbl prec
11576
11577 global fmul
11578fmul:
11579 mov.l %d0,L_SCR3(%a6) # store rnd info
11580
11581 clr.w %d1
11582 mov.b DTAG(%a6),%d1
11583 lsl.b &0x3,%d1
11584 or.b STAG(%a6),%d1 # combine src tags
11585 bne.w fmul_not_norm # optimize on non-norm input
11586
11587fmul_norm:
11588 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
11589 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
11590 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
11591
11592 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
11593 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
11594 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
11595
11596 bsr.l scale_to_zero_src # scale src exponent
11597 mov.l %d0,-(%sp) # save scale factor 1
11598
11599 bsr.l scale_to_zero_dst # scale dst exponent
11600
11601 add.l %d0,(%sp) # SCALE_FACTOR = scale1 + scale2
11602
11603 mov.w 2+L_SCR3(%a6),%d1 # fetch precision
11604 lsr.b &0x6,%d1 # shift to lo bits
11605 mov.l (%sp)+,%d0 # load S.F.
11606 cmp.l %d0,(tbl_fmul_ovfl.w,%pc,%d1.w*4) # would result ovfl?
11607 beq.w fmul_may_ovfl # result may rnd to overflow
11608 blt.w fmul_ovfl # result will overflow
11609
11610 cmp.l %d0,(tbl_fmul_unfl.w,%pc,%d1.w*4) # would result unfl?
11611 beq.w fmul_may_unfl # result may rnd to no unfl
11612 bgt.w fmul_unfl # result will underflow
11613
11614#
11615# NORMAL:
11616# - the result of the multiply operation will neither overflow nor underflow.
11617# - do the multiply to the proper precision and rounding mode.
11618# - scale the result exponent using the scale factor. if both operands were
11619# normalized then we really don't need to go through this scaling. but for now,
11620# this will do.
11621#
11622fmul_normal:
11623 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
11624
11625 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11626 fmov.l &0x0,%fpsr # clear FPSR
11627
11628 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
11629
11630 fmov.l %fpsr,%d1 # save status
11631 fmov.l &0x0,%fpcr # clear FPCR
11632
11633 or.l %d1,USER_FPSR(%a6) # save INEX2,N
11634
11635fmul_normal_exit:
11636 fmovm.x &0x80,FP_SCR0(%a6) # store out result
11637 mov.l %d2,-(%sp) # save d2
11638 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
11639 mov.l %d1,%d2 # make a copy
11640 andi.l &0x7fff,%d1 # strip sign
11641 andi.w &0x8000,%d2 # keep old sign
11642 sub.l %d0,%d1 # add scale factor
11643 or.w %d2,%d1 # concat old sign,new exp
11644 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
11645 mov.l (%sp)+,%d2 # restore d2
11646 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
11647 rts
11648
11649#
11650# OVERFLOW:
11651# - the result of the multiply operation is an overflow.
11652# - do the multiply to the proper precision and rounding mode in order to
11653# set the inexact bits.
11654# - calculate the default result and return it in fp0.
11655# - if overflow or inexact is enabled, we need a multiply result rounded to
11656# extended precision. if the original operation was extended, then we have this
11657# result. if the original operation was single or double, we have to do another
11658# multiply using extended precision and the correct rounding mode. the result
11659# of this operation then has its exponent scaled by -0x6000 to create the
11660# exceptional operand.
11661#
11662fmul_ovfl:
11663 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
11664
11665 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11666 fmov.l &0x0,%fpsr # clear FPSR
11667
11668 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
11669
11670 fmov.l %fpsr,%d1 # save status
11671 fmov.l &0x0,%fpcr # clear FPCR
11672
11673 or.l %d1,USER_FPSR(%a6) # save INEX2,N
11674
11675# save setting this until now because this is where fmul_may_ovfl may jump in
11676fmul_ovfl_tst:
11677 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
11678
11679 mov.b FPCR_ENABLE(%a6),%d1
11680 andi.b &0x13,%d1 # is OVFL or INEX enabled?
11681 bne.b fmul_ovfl_ena # yes
11682
11683# calculate the default result
11684fmul_ovfl_dis:
11685 btst &neg_bit,FPSR_CC(%a6) # is result negative?
11686 sne %d1 # set sign param accordingly
11687 mov.l L_SCR3(%a6),%d0 # pass rnd prec,mode
11688 bsr.l ovf_res # calculate default result
11689 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
11690 fmovm.x (%a0),&0x80 # return default result in fp0
11691 rts
11692
11693#
11694# OVFL is enabled; Create EXOP:
11695# - if precision is extended, then we have the EXOP. simply bias the exponent
11696# with an extra -0x6000. if the precision is single or double, we need to
11697# calculate a result rounded to extended precision.
11698#
11699fmul_ovfl_ena:
11700 mov.l L_SCR3(%a6),%d1
11701 andi.b &0xc0,%d1 # test the rnd prec
11702 bne.b fmul_ovfl_ena_sd # it's sgl or dbl
11703
11704fmul_ovfl_ena_cont:
11705 fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
11706
11707 mov.l %d2,-(%sp) # save d2
11708 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
11709 mov.w %d1,%d2 # make a copy
11710 andi.l &0x7fff,%d1 # strip sign
11711 sub.l %d0,%d1 # add scale factor
11712 subi.l &0x6000,%d1 # subtract bias
11713 andi.w &0x7fff,%d1 # clear sign bit
11714 andi.w &0x8000,%d2 # keep old sign
11715 or.w %d2,%d1 # concat old sign,new exp
11716 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
11717 mov.l (%sp)+,%d2 # restore d2
11718 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
11719 bra.b fmul_ovfl_dis
11720
11721fmul_ovfl_ena_sd:
11722 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
11723
11724 mov.l L_SCR3(%a6),%d1
11725 andi.b &0x30,%d1 # keep rnd mode only
11726 fmov.l %d1,%fpcr # set FPCR
11727
11728 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
11729
11730 fmov.l &0x0,%fpcr # clear FPCR
11731 bra.b fmul_ovfl_ena_cont
11732
11733#
11734# may OVERFLOW:
11735# - the result of the multiply operation MAY overflow.
11736# - do the multiply to the proper precision and rounding mode in order to
11737# set the inexact bits.
11738# - calculate the default result and return it in fp0.
11739#
11740fmul_may_ovfl:
11741 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11742
11743 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11744 fmov.l &0x0,%fpsr # clear FPSR
11745
11746 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
11747
11748 fmov.l %fpsr,%d1 # save status
11749 fmov.l &0x0,%fpcr # clear FPCR
11750
11751 or.l %d1,USER_FPSR(%a6) # save INEX2,N
11752
11753 fabs.x %fp0,%fp1 # make a copy of result
11754 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
11755 fbge.w fmul_ovfl_tst # yes; overflow has occurred
11756
11757# no, it didn't overflow; we have correct result
11758 bra.w fmul_normal_exit
11759
11760#
11761# UNDERFLOW:
11762# - the result of the multiply operation is an underflow.
11763# - do the multiply to the proper precision and rounding mode in order to
11764# set the inexact bits.
11765# - calculate the default result and return it in fp0.
11766# - if overflow or inexact is enabled, we need a multiply result rounded to
11767# extended precision. if the original operation was extended, then we have this
11768# result. if the original operation was single or double, we have to do another
11769# multiply using extended precision and the correct rounding mode. the result
11770# of this operation then has its exponent scaled by -0x6000 to create the
11771# exceptional operand.
11772#
11773fmul_unfl:
11774 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
11775
11776# for fun, let's use only extended precision, round to zero. then, let
11777# the unf_res() routine figure out all the rest.
11778# will we get the correct answer.
11779 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
11780
11781 fmov.l &rz_mode*0x10,%fpcr # set FPCR
11782 fmov.l &0x0,%fpsr # clear FPSR
11783
11784 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
11785
11786 fmov.l %fpsr,%d1 # save status
11787 fmov.l &0x0,%fpcr # clear FPCR
11788
11789 or.l %d1,USER_FPSR(%a6) # save INEX2,N
11790
11791 mov.b FPCR_ENABLE(%a6),%d1
11792 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
11793 bne.b fmul_unfl_ena # yes
11794
11795fmul_unfl_dis:
11796 fmovm.x &0x80,FP_SCR0(%a6) # store out result
11797
11798 lea FP_SCR0(%a6),%a0 # pass: result addr
11799 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
11800 bsr.l unf_res # calculate default result
11801 or.b %d0,FPSR_CC(%a6) # unf_res2 may have set 'Z'
11802 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
11803 rts
11804
11805#
11806# UNFL is enabled.
11807#
11808fmul_unfl_ena:
11809 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
11810
11811 mov.l L_SCR3(%a6),%d1
11812 andi.b &0xc0,%d1 # is precision extended?
11813 bne.b fmul_unfl_ena_sd # no, sgl or dbl
11814
11815# if the rnd mode is anything but RZ, then we have to re-do the above
11816# multiplication becuase we used RZ for all.
11817 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11818
11819fmul_unfl_ena_cont:
11820 fmov.l &0x0,%fpsr # clear FPSR
11821
11822 fmul.x FP_SCR0(%a6),%fp1 # execute multiply
11823
11824 fmov.l &0x0,%fpcr # clear FPCR
11825
11826 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
11827 mov.l %d2,-(%sp) # save d2
11828 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
11829 mov.l %d1,%d2 # make a copy
11830 andi.l &0x7fff,%d1 # strip sign
11831 andi.w &0x8000,%d2 # keep old sign
11832 sub.l %d0,%d1 # add scale factor
11833 addi.l &0x6000,%d1 # add bias
11834 andi.w &0x7fff,%d1
11835 or.w %d2,%d1 # concat old sign,new exp
11836 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
11837 mov.l (%sp)+,%d2 # restore d2
11838 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
11839 bra.w fmul_unfl_dis
11840
11841fmul_unfl_ena_sd:
11842 mov.l L_SCR3(%a6),%d1
11843 andi.b &0x30,%d1 # use only rnd mode
11844 fmov.l %d1,%fpcr # set FPCR
11845
11846 bra.b fmul_unfl_ena_cont
11847
11848# MAY UNDERFLOW:
11849# -use the correct rounding mode and precision. this code favors operations
11850# that do not underflow.
11851fmul_may_unfl:
11852 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
11853
11854 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11855 fmov.l &0x0,%fpsr # clear FPSR
11856
11857 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
11858
11859 fmov.l %fpsr,%d1 # save status
11860 fmov.l &0x0,%fpcr # clear FPCR
11861
11862 or.l %d1,USER_FPSR(%a6) # save INEX2,N
11863
11864 fabs.x %fp0,%fp1 # make a copy of result
11865 fcmp.b %fp1,&0x2 # is |result| > 2.b?
11866 fbgt.w fmul_normal_exit # no; no underflow occurred
11867 fblt.w fmul_unfl # yes; underflow occurred
11868
11869#
11870# we still don't know if underflow occurred. result is ~ equal to 2. but,
11871# we don't know if the result was an underflow that rounded up to a 2 or
11872# a normalized number that rounded down to a 2. so, redo the entire operation
11873# using RZ as the rounding mode to see what the pre-rounded result is.
11874# this case should be relatively rare.
11875#
11876 fmovm.x FP_SCR1(%a6),&0x40 # load dst operand
11877
11878 mov.l L_SCR3(%a6),%d1
11879 andi.b &0xc0,%d1 # keep rnd prec
11880 ori.b &rz_mode*0x10,%d1 # insert RZ
11881
11882 fmov.l %d1,%fpcr # set FPCR
11883 fmov.l &0x0,%fpsr # clear FPSR
11884
11885 fmul.x FP_SCR0(%a6),%fp1 # execute multiply
11886
11887 fmov.l &0x0,%fpcr # clear FPCR
11888 fabs.x %fp1 # make absolute value
11889 fcmp.b %fp1,&0x2 # is |result| < 2.b?
11890 fbge.w fmul_normal_exit # no; no underflow occurred
11891 bra.w fmul_unfl # yes, underflow occurred
11892
11893################################################################################
11894
11895#
11896# Multiply: inputs are not both normalized; what are they?
11897#
11898fmul_not_norm:
11899 mov.w (tbl_fmul_op.b,%pc,%d1.w*2),%d1
11900 jmp (tbl_fmul_op.b,%pc,%d1.w)
11901
11902 swbeg &48
11903tbl_fmul_op:
11904 short fmul_norm - tbl_fmul_op # NORM x NORM
11905 short fmul_zero - tbl_fmul_op # NORM x ZERO
11906 short fmul_inf_src - tbl_fmul_op # NORM x INF
11907 short fmul_res_qnan - tbl_fmul_op # NORM x QNAN
11908 short fmul_norm - tbl_fmul_op # NORM x DENORM
11909 short fmul_res_snan - tbl_fmul_op # NORM x SNAN
11910 short tbl_fmul_op - tbl_fmul_op #
11911 short tbl_fmul_op - tbl_fmul_op #
11912
11913 short fmul_zero - tbl_fmul_op # ZERO x NORM
11914 short fmul_zero - tbl_fmul_op # ZERO x ZERO
11915 short fmul_res_operr - tbl_fmul_op # ZERO x INF
11916 short fmul_res_qnan - tbl_fmul_op # ZERO x QNAN
11917 short fmul_zero - tbl_fmul_op # ZERO x DENORM
11918 short fmul_res_snan - tbl_fmul_op # ZERO x SNAN
11919 short tbl_fmul_op - tbl_fmul_op #
11920 short tbl_fmul_op - tbl_fmul_op #
11921
11922 short fmul_inf_dst - tbl_fmul_op # INF x NORM
11923 short fmul_res_operr - tbl_fmul_op # INF x ZERO
11924 short fmul_inf_dst - tbl_fmul_op # INF x INF
11925 short fmul_res_qnan - tbl_fmul_op # INF x QNAN
11926 short fmul_inf_dst - tbl_fmul_op # INF x DENORM
11927 short fmul_res_snan - tbl_fmul_op # INF x SNAN
11928 short tbl_fmul_op - tbl_fmul_op #
11929 short tbl_fmul_op - tbl_fmul_op #
11930
11931 short fmul_res_qnan - tbl_fmul_op # QNAN x NORM
11932 short fmul_res_qnan - tbl_fmul_op # QNAN x ZERO
11933 short fmul_res_qnan - tbl_fmul_op # QNAN x INF
11934 short fmul_res_qnan - tbl_fmul_op # QNAN x QNAN
11935 short fmul_res_qnan - tbl_fmul_op # QNAN x DENORM
11936 short fmul_res_snan - tbl_fmul_op # QNAN x SNAN
11937 short tbl_fmul_op - tbl_fmul_op #
11938 short tbl_fmul_op - tbl_fmul_op #
11939
11940 short fmul_norm - tbl_fmul_op # NORM x NORM
11941 short fmul_zero - tbl_fmul_op # NORM x ZERO
11942 short fmul_inf_src - tbl_fmul_op # NORM x INF
11943 short fmul_res_qnan - tbl_fmul_op # NORM x QNAN
11944 short fmul_norm - tbl_fmul_op # NORM x DENORM
11945 short fmul_res_snan - tbl_fmul_op # NORM x SNAN
11946 short tbl_fmul_op - tbl_fmul_op #
11947 short tbl_fmul_op - tbl_fmul_op #
11948
11949 short fmul_res_snan - tbl_fmul_op # SNAN x NORM
11950 short fmul_res_snan - tbl_fmul_op # SNAN x ZERO
11951 short fmul_res_snan - tbl_fmul_op # SNAN x INF
11952 short fmul_res_snan - tbl_fmul_op # SNAN x QNAN
11953 short fmul_res_snan - tbl_fmul_op # SNAN x DENORM
11954 short fmul_res_snan - tbl_fmul_op # SNAN x SNAN
11955 short tbl_fmul_op - tbl_fmul_op #
11956 short tbl_fmul_op - tbl_fmul_op #
11957
11958fmul_res_operr:
11959 bra.l res_operr
11960fmul_res_snan:
11961 bra.l res_snan
11962fmul_res_qnan:
11963 bra.l res_qnan
11964
11965#
11966# Multiply: (Zero x Zero) || (Zero x norm) || (Zero x denorm)
11967#
11968 global fmul_zero # global for fsglmul
11969fmul_zero:
11970 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
11971 mov.b DST_EX(%a1),%d1
11972 eor.b %d0,%d1
11973 bpl.b fmul_zero_p # result ZERO is pos.
11974fmul_zero_n:
11975 fmov.s &0x80000000,%fp0 # load -ZERO
11976 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
11977 rts
11978fmul_zero_p:
11979 fmov.s &0x00000000,%fp0 # load +ZERO
11980 mov.b &z_bmask,FPSR_CC(%a6) # set Z
11981 rts
11982
11983#
11984# Multiply: (inf x inf) || (inf x norm) || (inf x denorm)
11985#
11986# Note: The j-bit for an infinity is a don't-care. However, to be
11987# strictly compatible w/ the 68881/882, we make sure to return an
11988# INF w/ the j-bit set if the input INF j-bit was set. Destination
11989# INFs take priority.
11990#
11991 global fmul_inf_dst # global for fsglmul
11992fmul_inf_dst:
11993 fmovm.x DST(%a1),&0x80 # return INF result in fp0
11994 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
11995 mov.b DST_EX(%a1),%d1
11996 eor.b %d0,%d1
11997 bpl.b fmul_inf_dst_p # result INF is pos.
11998fmul_inf_dst_n:
11999 fabs.x %fp0 # clear result sign
12000 fneg.x %fp0 # set result sign
12001 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
12002 rts
12003fmul_inf_dst_p:
12004 fabs.x %fp0 # clear result sign
12005 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
12006 rts
12007
12008 global fmul_inf_src # global for fsglmul
12009fmul_inf_src:
12010 fmovm.x SRC(%a0),&0x80 # return INF result in fp0
12011 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
12012 mov.b DST_EX(%a1),%d1
12013 eor.b %d0,%d1
12014 bpl.b fmul_inf_dst_p # result INF is pos.
12015 bra.b fmul_inf_dst_n
12016
12017#########################################################################
12018# XDEF **************************************************************** #
12019# fin(): emulates the fmove instruction #
12020# fsin(): emulates the fsmove instruction #
12021# fdin(): emulates the fdmove instruction #
12022# #
12023# XREF **************************************************************** #
12024# norm() - normalize mantissa for EXOP on denorm #
12025# scale_to_zero_src() - scale src exponent to zero #
12026# ovf_res() - return default overflow result #
12027# unf_res() - return default underflow result #
12028# res_qnan_1op() - return QNAN result #
12029# res_snan_1op() - return SNAN result #
12030# #
12031# INPUT *************************************************************** #
12032# a0 = pointer to extended precision source operand #
12033# d0 = round prec/mode #
12034# #
12035# OUTPUT ************************************************************** #
12036# fp0 = result #
12037# fp1 = EXOP (if exception occurred) #
12038# #
12039# ALGORITHM *********************************************************** #
12040# Handle NANs, infinities, and zeroes as special cases. Divide #
12041# norms into extended, single, and double precision. #
12042# Norms can be emulated w/ a regular fmove instruction. For #
12043# sgl/dbl, must scale exponent and perform an "fmove". Check to see #
12044# if the result would have overflowed/underflowed. If so, use unf_res() #
12045# or ovf_res() to return the default result. Also return EXOP if #
12046# exception is enabled. If no exception, return the default result. #
12047# Unnorms don't pass through here. #
12048# #
12049#########################################################################
12050
12051 global fsin
12052fsin:
12053 andi.b &0x30,%d0 # clear rnd prec
12054 ori.b &s_mode*0x10,%d0 # insert sgl precision
12055 bra.b fin
12056
12057 global fdin
12058fdin:
12059 andi.b &0x30,%d0 # clear rnd prec
12060 ori.b &d_mode*0x10,%d0 # insert dbl precision
12061
12062 global fin
12063fin:
12064 mov.l %d0,L_SCR3(%a6) # store rnd info
12065
12066 mov.b STAG(%a6),%d1 # fetch src optype tag
12067 bne.w fin_not_norm # optimize on non-norm input
12068
12069#
12070# FP MOVE IN: NORMs and DENORMs ONLY!
12071#
12072fin_norm:
12073 andi.b &0xc0,%d0 # is precision extended?
12074 bne.w fin_not_ext # no, so go handle dbl or sgl
12075
12076#
12077# precision selected is extended. so...we cannot get an underflow
12078# or overflow because of rounding to the correct precision. so...
12079# skip the scaling and unscaling...
12080#
12081 tst.b SRC_EX(%a0) # is the operand negative?
12082 bpl.b fin_norm_done # no
12083 bset &neg_bit,FPSR_CC(%a6) # yes, so set 'N' ccode bit
12084fin_norm_done:
12085 fmovm.x SRC(%a0),&0x80 # return result in fp0
12086 rts
12087
12088#
12089# for an extended precision DENORM, the UNFL exception bit is set
12090# the accrued bit is NOT set in this instance(no inexactness!)
12091#
12092fin_denorm:
12093 andi.b &0xc0,%d0 # is precision extended?
12094 bne.w fin_not_ext # no, so go handle dbl or sgl
12095
12096 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
12097 tst.b SRC_EX(%a0) # is the operand negative?
12098 bpl.b fin_denorm_done # no
12099 bset &neg_bit,FPSR_CC(%a6) # yes, so set 'N' ccode bit
12100fin_denorm_done:
12101 fmovm.x SRC(%a0),&0x80 # return result in fp0
12102 btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
12103 bne.b fin_denorm_unfl_ena # yes
12104 rts
12105
12106#
12107# the input is an extended DENORM and underflow is enabled in the FPCR.
12108# normalize the mantissa and add the bias of 0x6000 to the resulting negative
12109# exponent and insert back into the operand.
12110#
12111fin_denorm_unfl_ena:
12112 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12113 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12114 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12115 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
12116 bsr.l norm # normalize result
12117 neg.w %d0 # new exponent = -(shft val)
12118 addi.w &0x6000,%d0 # add new bias to exponent
12119 mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
12120 andi.w &0x8000,%d1 # keep old sign
12121 andi.w &0x7fff,%d0 # clear sign position
12122 or.w %d1,%d0 # concat new exo,old sign
12123 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
12124 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
12125 rts
12126
12127#
12128# operand is to be rounded to single or double precision
12129#
12130fin_not_ext:
12131 cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
12132 bne.b fin_dbl
12133
12134#
12135# operand is to be rounded to single precision
12136#
12137fin_sgl:
12138 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12139 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12140 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12141 bsr.l scale_to_zero_src # calculate scale factor
12142
12143 cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
12144 bge.w fin_sd_unfl # yes; go handle underflow
12145 cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
12146 beq.w fin_sd_may_ovfl # maybe; go check
12147 blt.w fin_sd_ovfl # yes; go handle overflow
12148
12149#
12150# operand will NOT overflow or underflow when moved into the fp reg file
12151#
12152fin_sd_normal:
12153 fmov.l &0x0,%fpsr # clear FPSR
12154 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12155
12156 fmov.x FP_SCR0(%a6),%fp0 # perform move
12157
12158 fmov.l %fpsr,%d1 # save FPSR
12159 fmov.l &0x0,%fpcr # clear FPCR
12160
12161 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12162
12163fin_sd_normal_exit:
12164 mov.l %d2,-(%sp) # save d2
12165 fmovm.x &0x80,FP_SCR0(%a6) # store out result
12166 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
12167 mov.w %d1,%d2 # make a copy
12168 andi.l &0x7fff,%d1 # strip sign
12169 sub.l %d0,%d1 # add scale factor
12170 andi.w &0x8000,%d2 # keep old sign
12171 or.w %d1,%d2 # concat old sign,new exponent
12172 mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
12173 mov.l (%sp)+,%d2 # restore d2
12174 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
12175 rts
12176
12177#
12178# operand is to be rounded to double precision
12179#
12180fin_dbl:
12181 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12182 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12183 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12184 bsr.l scale_to_zero_src # calculate scale factor
12185
12186 cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
12187 bge.w fin_sd_unfl # yes; go handle underflow
12188 cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
12189 beq.w fin_sd_may_ovfl # maybe; go check
12190 blt.w fin_sd_ovfl # yes; go handle overflow
12191 bra.w fin_sd_normal # no; ho handle normalized op
12192
12193#
12194# operand WILL underflow when moved in to the fp register file
12195#
12196fin_sd_unfl:
12197 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
12198
12199 tst.b FP_SCR0_EX(%a6) # is operand negative?
12200 bpl.b fin_sd_unfl_tst
12201 bset &neg_bit,FPSR_CC(%a6) # set 'N' ccode bit
12202
12203# if underflow or inexact is enabled, then go calculate the EXOP first.
12204fin_sd_unfl_tst:
12205 mov.b FPCR_ENABLE(%a6),%d1
12206 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
12207 bne.b fin_sd_unfl_ena # yes
12208
12209fin_sd_unfl_dis:
12210 lea FP_SCR0(%a6),%a0 # pass: result addr
12211 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
12212 bsr.l unf_res # calculate default result
12213 or.b %d0,FPSR_CC(%a6) # unf_res may have set 'Z'
12214 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
12215 rts
12216
12217#
12218# operand will underflow AND underflow or inexact is enabled.
12219# therefore, we must return the result rounded to extended precision.
12220#
12221fin_sd_unfl_ena:
12222 mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
12223 mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
12224 mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
12225
12226 mov.l %d2,-(%sp) # save d2
12227 mov.w %d1,%d2 # make a copy
12228 andi.l &0x7fff,%d1 # strip sign
12229 sub.l %d0,%d1 # subtract scale factor
12230 andi.w &0x8000,%d2 # extract old sign
12231 addi.l &0x6000,%d1 # add new bias
12232 andi.w &0x7fff,%d1
12233 or.w %d1,%d2 # concat old sign,new exp
12234 mov.w %d2,FP_SCR1_EX(%a6) # insert new exponent
12235 fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
12236 mov.l (%sp)+,%d2 # restore d2
12237 bra.b fin_sd_unfl_dis
12238
12239#
12240# operand WILL overflow.
12241#
12242fin_sd_ovfl:
12243 fmov.l &0x0,%fpsr # clear FPSR
12244 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12245
12246 fmov.x FP_SCR0(%a6),%fp0 # perform move
12247
12248 fmov.l &0x0,%fpcr # clear FPCR
12249 fmov.l %fpsr,%d1 # save FPSR
12250
12251 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12252
12253fin_sd_ovfl_tst:
12254 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
12255
12256 mov.b FPCR_ENABLE(%a6),%d1
12257 andi.b &0x13,%d1 # is OVFL or INEX enabled?
12258 bne.b fin_sd_ovfl_ena # yes
12259
12260#
12261# OVFL is not enabled; therefore, we must create the default result by
12262# calling ovf_res().
12263#
12264fin_sd_ovfl_dis:
12265 btst &neg_bit,FPSR_CC(%a6) # is result negative?
12266 sne %d1 # set sign param accordingly
12267 mov.l L_SCR3(%a6),%d0 # pass: prec,mode
12268 bsr.l ovf_res # calculate default result
12269 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
12270 fmovm.x (%a0),&0x80 # return default result in fp0
12271 rts
12272
12273#
12274# OVFL is enabled.
12275# the INEX2 bit has already been updated by the round to the correct precision.
12276# now, round to extended(and don't alter the FPSR).
12277#
12278fin_sd_ovfl_ena:
12279 mov.l %d2,-(%sp) # save d2
12280 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
12281 mov.l %d1,%d2 # make a copy
12282 andi.l &0x7fff,%d1 # strip sign
12283 andi.w &0x8000,%d2 # keep old sign
12284 sub.l %d0,%d1 # add scale factor
12285 sub.l &0x6000,%d1 # subtract bias
12286 andi.w &0x7fff,%d1
12287 or.w %d2,%d1
12288 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
12289 mov.l (%sp)+,%d2 # restore d2
12290 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
12291 bra.b fin_sd_ovfl_dis
12292
12293#
12294# the move in MAY overflow. so...
12295#
12296fin_sd_may_ovfl:
12297 fmov.l &0x0,%fpsr # clear FPSR
12298 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12299
12300 fmov.x FP_SCR0(%a6),%fp0 # perform the move
12301
12302 fmov.l %fpsr,%d1 # save status
12303 fmov.l &0x0,%fpcr # clear FPCR
12304
12305 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12306
12307 fabs.x %fp0,%fp1 # make a copy of result
12308 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
12309 fbge.w fin_sd_ovfl_tst # yes; overflow has occurred
12310
12311# no, it didn't overflow; we have correct result
12312 bra.w fin_sd_normal_exit
12313
12314##########################################################################
12315
12316#
12317# operand is not a NORM: check its optype and branch accordingly
12318#
12319fin_not_norm:
12320 cmpi.b %d1,&DENORM # weed out DENORM
12321 beq.w fin_denorm
12322 cmpi.b %d1,&SNAN # weed out SNANs
12323 beq.l res_snan_1op
12324 cmpi.b %d1,&QNAN # weed out QNANs
12325 beq.l res_qnan_1op
12326
12327#
12328# do the fmove in; at this point, only possible ops are ZERO and INF.
12329# use fmov to determine ccodes.
12330# prec:mode should be zero at this point but it won't affect answer anyways.
12331#
12332 fmov.x SRC(%a0),%fp0 # do fmove in
12333 fmov.l %fpsr,%d0 # no exceptions possible
12334 rol.l &0x8,%d0 # put ccodes in lo byte
12335 mov.b %d0,FPSR_CC(%a6) # insert correct ccodes
12336 rts
12337
12338#########################################################################
12339# XDEF **************************************************************** #
12340# fdiv(): emulates the fdiv instruction #
12341# fsdiv(): emulates the fsdiv instruction #
12342# fddiv(): emulates the fddiv instruction #
12343# #
12344# XREF **************************************************************** #
12345# scale_to_zero_src() - scale src exponent to zero #
12346# scale_to_zero_dst() - scale dst exponent to zero #
12347# unf_res() - return default underflow result #
12348# ovf_res() - return default overflow result #
12349# res_qnan() - return QNAN result #
12350# res_snan() - return SNAN result #
12351# #
12352# INPUT *************************************************************** #
12353# a0 = pointer to extended precision source operand #
12354# a1 = pointer to extended precision destination operand #
12355# d0 rnd prec,mode #
12356# #
12357# OUTPUT ************************************************************** #
12358# fp0 = result #
12359# fp1 = EXOP (if exception occurred) #
12360# #
12361# ALGORITHM *********************************************************** #
12362# Handle NANs, infinities, and zeroes as special cases. Divide #
12363# norms/denorms into ext/sgl/dbl precision. #
12364# For norms/denorms, scale the exponents such that a divide #
12365# instruction won't cause an exception. Use the regular fdiv to #
12366# compute a result. Check if the regular operands would have taken #
12367# an exception. If so, return the default overflow/underflow result #
12368# and return the EXOP if exceptions are enabled. Else, scale the #
12369# result operand to the proper exponent. #
12370# #
12371#########################################################################
12372
12373 align 0x10
12374tbl_fdiv_unfl:
12375 long 0x3fff - 0x0000 # ext_unfl
12376 long 0x3fff - 0x3f81 # sgl_unfl
12377 long 0x3fff - 0x3c01 # dbl_unfl
12378
12379tbl_fdiv_ovfl:
12380 long 0x3fff - 0x7ffe # ext overflow exponent
12381 long 0x3fff - 0x407e # sgl overflow exponent
12382 long 0x3fff - 0x43fe # dbl overflow exponent
12383
12384 global fsdiv
12385fsdiv:
12386 andi.b &0x30,%d0 # clear rnd prec
12387 ori.b &s_mode*0x10,%d0 # insert sgl prec
12388 bra.b fdiv
12389
12390 global fddiv
12391fddiv:
12392 andi.b &0x30,%d0 # clear rnd prec
12393 ori.b &d_mode*0x10,%d0 # insert dbl prec
12394
12395 global fdiv
12396fdiv:
12397 mov.l %d0,L_SCR3(%a6) # store rnd info
12398
12399 clr.w %d1
12400 mov.b DTAG(%a6),%d1
12401 lsl.b &0x3,%d1
12402 or.b STAG(%a6),%d1 # combine src tags
12403
12404 bne.w fdiv_not_norm # optimize on non-norm input
12405
12406#
12407# DIVIDE: NORMs and DENORMs ONLY!
12408#
12409fdiv_norm:
12410 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
12411 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
12412 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
12413
12414 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12415 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12416 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12417
12418 bsr.l scale_to_zero_src # scale src exponent
12419 mov.l %d0,-(%sp) # save scale factor 1
12420
12421 bsr.l scale_to_zero_dst # scale dst exponent
12422
12423 neg.l (%sp) # SCALE FACTOR = scale1 - scale2
12424 add.l %d0,(%sp)
12425
12426 mov.w 2+L_SCR3(%a6),%d1 # fetch precision
12427 lsr.b &0x6,%d1 # shift to lo bits
12428 mov.l (%sp)+,%d0 # load S.F.
12429 cmp.l %d0,(tbl_fdiv_ovfl.b,%pc,%d1.w*4) # will result overflow?
12430 ble.w fdiv_may_ovfl # result will overflow
12431
12432 cmp.l %d0,(tbl_fdiv_unfl.w,%pc,%d1.w*4) # will result underflow?
12433 beq.w fdiv_may_unfl # maybe
12434 bgt.w fdiv_unfl # yes; go handle underflow
12435
12436fdiv_normal:
12437 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
12438
12439 fmov.l L_SCR3(%a6),%fpcr # save FPCR
12440 fmov.l &0x0,%fpsr # clear FPSR
12441
12442 fdiv.x FP_SCR0(%a6),%fp0 # perform divide
12443
12444 fmov.l %fpsr,%d1 # save FPSR
12445 fmov.l &0x0,%fpcr # clear FPCR
12446
12447 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12448
12449fdiv_normal_exit:
12450 fmovm.x &0x80,FP_SCR0(%a6) # store result on stack
12451 mov.l %d2,-(%sp) # store d2
12452 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
12453 mov.l %d1,%d2 # make a copy
12454 andi.l &0x7fff,%d1 # strip sign
12455 andi.w &0x8000,%d2 # keep old sign
12456 sub.l %d0,%d1 # add scale factor
12457 or.w %d2,%d1 # concat old sign,new exp
12458 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
12459 mov.l (%sp)+,%d2 # restore d2
12460 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
12461 rts
12462
12463tbl_fdiv_ovfl2:
12464 long 0x7fff
12465 long 0x407f
12466 long 0x43ff
12467
12468fdiv_no_ovfl:
12469 mov.l (%sp)+,%d0 # restore scale factor
12470 bra.b fdiv_normal_exit
12471
12472fdiv_may_ovfl:
12473 mov.l %d0,-(%sp) # save scale factor
12474
12475 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
12476
12477 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12478 fmov.l &0x0,%fpsr # set FPSR
12479
12480 fdiv.x FP_SCR0(%a6),%fp0 # execute divide
12481
12482 fmov.l %fpsr,%d0
12483 fmov.l &0x0,%fpcr
12484
12485 or.l %d0,USER_FPSR(%a6) # save INEX,N
12486
12487 fmovm.x &0x01,-(%sp) # save result to stack
12488 mov.w (%sp),%d0 # fetch new exponent
12489 add.l &0xc,%sp # clear result from stack
12490 andi.l &0x7fff,%d0 # strip sign
12491 sub.l (%sp),%d0 # add scale factor
12492 cmp.l %d0,(tbl_fdiv_ovfl2.b,%pc,%d1.w*4)
12493 blt.b fdiv_no_ovfl
12494 mov.l (%sp)+,%d0
12495
12496fdiv_ovfl_tst:
12497 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
12498
12499 mov.b FPCR_ENABLE(%a6),%d1
12500 andi.b &0x13,%d1 # is OVFL or INEX enabled?
12501 bne.b fdiv_ovfl_ena # yes
12502
12503fdiv_ovfl_dis:
12504 btst &neg_bit,FPSR_CC(%a6) # is result negative?
12505 sne %d1 # set sign param accordingly
12506 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
12507 bsr.l ovf_res # calculate default result
12508 or.b %d0,FPSR_CC(%a6) # set INF if applicable
12509 fmovm.x (%a0),&0x80 # return default result in fp0
12510 rts
12511
12512fdiv_ovfl_ena:
12513 mov.l L_SCR3(%a6),%d1
12514 andi.b &0xc0,%d1 # is precision extended?
12515 bne.b fdiv_ovfl_ena_sd # no, do sgl or dbl
12516
12517fdiv_ovfl_ena_cont:
12518 fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
12519
12520 mov.l %d2,-(%sp) # save d2
12521 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
12522 mov.w %d1,%d2 # make a copy
12523 andi.l &0x7fff,%d1 # strip sign
12524 sub.l %d0,%d1 # add scale factor
12525 subi.l &0x6000,%d1 # subtract bias
12526 andi.w &0x7fff,%d1 # clear sign bit
12527 andi.w &0x8000,%d2 # keep old sign
12528 or.w %d2,%d1 # concat old sign,new exp
12529 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
12530 mov.l (%sp)+,%d2 # restore d2
12531 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
12532 bra.b fdiv_ovfl_dis
12533
12534fdiv_ovfl_ena_sd:
12535 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
12536
12537 mov.l L_SCR3(%a6),%d1
12538 andi.b &0x30,%d1 # keep rnd mode
12539 fmov.l %d1,%fpcr # set FPCR
12540
12541 fdiv.x FP_SCR0(%a6),%fp0 # execute divide
12542
12543 fmov.l &0x0,%fpcr # clear FPCR
12544 bra.b fdiv_ovfl_ena_cont
12545
12546fdiv_unfl:
12547 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
12548
12549 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
12550
12551 fmov.l &rz_mode*0x10,%fpcr # set FPCR
12552 fmov.l &0x0,%fpsr # clear FPSR
12553
12554 fdiv.x FP_SCR0(%a6),%fp0 # execute divide
12555
12556 fmov.l %fpsr,%d1 # save status
12557 fmov.l &0x0,%fpcr # clear FPCR
12558
12559 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12560
12561 mov.b FPCR_ENABLE(%a6),%d1
12562 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
12563 bne.b fdiv_unfl_ena # yes
12564
12565fdiv_unfl_dis:
12566 fmovm.x &0x80,FP_SCR0(%a6) # store out result
12567
12568 lea FP_SCR0(%a6),%a0 # pass: result addr
12569 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
12570 bsr.l unf_res # calculate default result
12571 or.b %d0,FPSR_CC(%a6) # 'Z' may have been set
12572 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
12573 rts
12574
12575#
12576# UNFL is enabled.
12577#
12578fdiv_unfl_ena:
12579 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
12580
12581 mov.l L_SCR3(%a6),%d1
12582 andi.b &0xc0,%d1 # is precision extended?
12583 bne.b fdiv_unfl_ena_sd # no, sgl or dbl
12584
12585 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12586
12587fdiv_unfl_ena_cont:
12588 fmov.l &0x0,%fpsr # clear FPSR
12589
12590 fdiv.x FP_SCR0(%a6),%fp1 # execute divide
12591
12592 fmov.l &0x0,%fpcr # clear FPCR
12593
12594 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
12595 mov.l %d2,-(%sp) # save d2
12596 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
12597 mov.l %d1,%d2 # make a copy
12598 andi.l &0x7fff,%d1 # strip sign
12599 andi.w &0x8000,%d2 # keep old sign
12600 sub.l %d0,%d1 # add scale factoer
12601 addi.l &0x6000,%d1 # add bias
12602 andi.w &0x7fff,%d1
12603 or.w %d2,%d1 # concat old sign,new exp
12604 mov.w %d1,FP_SCR0_EX(%a6) # insert new exp
12605 mov.l (%sp)+,%d2 # restore d2
12606 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
12607 bra.w fdiv_unfl_dis
12608
12609fdiv_unfl_ena_sd:
12610 mov.l L_SCR3(%a6),%d1
12611 andi.b &0x30,%d1 # use only rnd mode
12612 fmov.l %d1,%fpcr # set FPCR
12613
12614 bra.b fdiv_unfl_ena_cont
12615
12616#
12617# the divide operation MAY underflow:
12618#
12619fdiv_may_unfl:
12620 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
12621
12622 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12623 fmov.l &0x0,%fpsr # clear FPSR
12624
12625 fdiv.x FP_SCR0(%a6),%fp0 # execute divide
12626
12627 fmov.l %fpsr,%d1 # save status
12628 fmov.l &0x0,%fpcr # clear FPCR
12629
12630 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12631
12632 fabs.x %fp0,%fp1 # make a copy of result
12633 fcmp.b %fp1,&0x1 # is |result| > 1.b?
12634 fbgt.w fdiv_normal_exit # no; no underflow occurred
12635 fblt.w fdiv_unfl # yes; underflow occurred
12636
12637#
12638# we still don't know if underflow occurred. result is ~ equal to 1. but,
12639# we don't know if the result was an underflow that rounded up to a 1
12640# or a normalized number that rounded down to a 1. so, redo the entire
12641# operation using RZ as the rounding mode to see what the pre-rounded
12642# result is. this case should be relatively rare.
12643#
12644 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
12645
12646 mov.l L_SCR3(%a6),%d1
12647 andi.b &0xc0,%d1 # keep rnd prec
12648 ori.b &rz_mode*0x10,%d1 # insert RZ
12649
12650 fmov.l %d1,%fpcr # set FPCR
12651 fmov.l &0x0,%fpsr # clear FPSR
12652
12653 fdiv.x FP_SCR0(%a6),%fp1 # execute divide
12654
12655 fmov.l &0x0,%fpcr # clear FPCR
12656 fabs.x %fp1 # make absolute value
12657 fcmp.b %fp1,&0x1 # is |result| < 1.b?
12658 fbge.w fdiv_normal_exit # no; no underflow occurred
12659 bra.w fdiv_unfl # yes; underflow occurred
12660
12661############################################################################
12662
12663#
12664# Divide: inputs are not both normalized; what are they?
12665#
12666fdiv_not_norm:
12667 mov.w (tbl_fdiv_op.b,%pc,%d1.w*2),%d1
12668 jmp (tbl_fdiv_op.b,%pc,%d1.w*1)
12669
12670 swbeg &48
12671tbl_fdiv_op:
12672 short fdiv_norm - tbl_fdiv_op # NORM / NORM
12673 short fdiv_inf_load - tbl_fdiv_op # NORM / ZERO
12674 short fdiv_zero_load - tbl_fdiv_op # NORM / INF
12675 short fdiv_res_qnan - tbl_fdiv_op # NORM / QNAN
12676 short fdiv_norm - tbl_fdiv_op # NORM / DENORM
12677 short fdiv_res_snan - tbl_fdiv_op # NORM / SNAN
12678 short tbl_fdiv_op - tbl_fdiv_op #
12679 short tbl_fdiv_op - tbl_fdiv_op #
12680
12681 short fdiv_zero_load - tbl_fdiv_op # ZERO / NORM
12682 short fdiv_res_operr - tbl_fdiv_op # ZERO / ZERO
12683 short fdiv_zero_load - tbl_fdiv_op # ZERO / INF
12684 short fdiv_res_qnan - tbl_fdiv_op # ZERO / QNAN
12685 short fdiv_zero_load - tbl_fdiv_op # ZERO / DENORM
12686 short fdiv_res_snan - tbl_fdiv_op # ZERO / SNAN
12687 short tbl_fdiv_op - tbl_fdiv_op #
12688 short tbl_fdiv_op - tbl_fdiv_op #
12689
12690 short fdiv_inf_dst - tbl_fdiv_op # INF / NORM
12691 short fdiv_inf_dst - tbl_fdiv_op # INF / ZERO
12692 short fdiv_res_operr - tbl_fdiv_op # INF / INF
12693 short fdiv_res_qnan - tbl_fdiv_op # INF / QNAN
12694 short fdiv_inf_dst - tbl_fdiv_op # INF / DENORM
12695 short fdiv_res_snan - tbl_fdiv_op # INF / SNAN
12696 short tbl_fdiv_op - tbl_fdiv_op #
12697 short tbl_fdiv_op - tbl_fdiv_op #
12698
12699 short fdiv_res_qnan - tbl_fdiv_op # QNAN / NORM
12700 short fdiv_res_qnan - tbl_fdiv_op # QNAN / ZERO
12701 short fdiv_res_qnan - tbl_fdiv_op # QNAN / INF
12702 short fdiv_res_qnan - tbl_fdiv_op # QNAN / QNAN
12703 short fdiv_res_qnan - tbl_fdiv_op # QNAN / DENORM
12704 short fdiv_res_snan - tbl_fdiv_op # QNAN / SNAN
12705 short tbl_fdiv_op - tbl_fdiv_op #
12706 short tbl_fdiv_op - tbl_fdiv_op #
12707
12708 short fdiv_norm - tbl_fdiv_op # DENORM / NORM
12709 short fdiv_inf_load - tbl_fdiv_op # DENORM / ZERO
12710 short fdiv_zero_load - tbl_fdiv_op # DENORM / INF
12711 short fdiv_res_qnan - tbl_fdiv_op # DENORM / QNAN
12712 short fdiv_norm - tbl_fdiv_op # DENORM / DENORM
12713 short fdiv_res_snan - tbl_fdiv_op # DENORM / SNAN
12714 short tbl_fdiv_op - tbl_fdiv_op #
12715 short tbl_fdiv_op - tbl_fdiv_op #
12716
12717 short fdiv_res_snan - tbl_fdiv_op # SNAN / NORM
12718 short fdiv_res_snan - tbl_fdiv_op # SNAN / ZERO
12719 short fdiv_res_snan - tbl_fdiv_op # SNAN / INF
12720 short fdiv_res_snan - tbl_fdiv_op # SNAN / QNAN
12721 short fdiv_res_snan - tbl_fdiv_op # SNAN / DENORM
12722 short fdiv_res_snan - tbl_fdiv_op # SNAN / SNAN
12723 short tbl_fdiv_op - tbl_fdiv_op #
12724 short tbl_fdiv_op - tbl_fdiv_op #
12725
12726fdiv_res_qnan:
12727 bra.l res_qnan
12728fdiv_res_snan:
12729 bra.l res_snan
12730fdiv_res_operr:
12731 bra.l res_operr
12732
12733 global fdiv_zero_load # global for fsgldiv
12734fdiv_zero_load:
12735 mov.b SRC_EX(%a0),%d0 # result sign is exclusive
12736 mov.b DST_EX(%a1),%d1 # or of input signs.
12737 eor.b %d0,%d1
12738 bpl.b fdiv_zero_load_p # result is positive
12739 fmov.s &0x80000000,%fp0 # load a -ZERO
12740 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
12741 rts
12742fdiv_zero_load_p:
12743 fmov.s &0x00000000,%fp0 # load a +ZERO
12744 mov.b &z_bmask,FPSR_CC(%a6) # set Z
12745 rts
12746
12747#
12748# The destination was In Range and the source was a ZERO. The result,
12749# therefore, is an INF w/ the proper sign.
12750# So, determine the sign and return a new INF (w/ the j-bit cleared).
12751#
12752 global fdiv_inf_load # global for fsgldiv
12753fdiv_inf_load:
12754 ori.w &dz_mask+adz_mask,2+USER_FPSR(%a6) # no; set DZ/ADZ
12755 mov.b SRC_EX(%a0),%d0 # load both signs
12756 mov.b DST_EX(%a1),%d1
12757 eor.b %d0,%d1
12758 bpl.b fdiv_inf_load_p # result is positive
12759 fmov.s &0xff800000,%fp0 # make result -INF
12760 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
12761 rts
12762fdiv_inf_load_p:
12763 fmov.s &0x7f800000,%fp0 # make result +INF
12764 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
12765 rts
12766
12767#
12768# The destination was an INF w/ an In Range or ZERO source, the result is
12769# an INF w/ the proper sign.
12770# The 68881/882 returns the destination INF w/ the new sign(if the j-bit of the
12771# dst INF is set, then then j-bit of the result INF is also set).
12772#
12773 global fdiv_inf_dst # global for fsgldiv
12774fdiv_inf_dst:
12775 mov.b DST_EX(%a1),%d0 # load both signs
12776 mov.b SRC_EX(%a0),%d1
12777 eor.b %d0,%d1
12778 bpl.b fdiv_inf_dst_p # result is positive
12779
12780 fmovm.x DST(%a1),&0x80 # return result in fp0
12781 fabs.x %fp0 # clear sign bit
12782 fneg.x %fp0 # set sign bit
12783 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/NEG
12784 rts
12785
12786fdiv_inf_dst_p:
12787 fmovm.x DST(%a1),&0x80 # return result in fp0
12788 fabs.x %fp0 # return positive INF
12789 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
12790 rts
12791
12792#########################################################################
12793# XDEF **************************************************************** #
12794# fneg(): emulates the fneg instruction #
12795# fsneg(): emulates the fsneg instruction #
12796# fdneg(): emulates the fdneg instruction #
12797# #
12798# XREF **************************************************************** #
12799# norm() - normalize a denorm to provide EXOP #
12800# scale_to_zero_src() - scale sgl/dbl source exponent #
12801# ovf_res() - return default overflow result #
12802# unf_res() - return default underflow result #
12803# res_qnan_1op() - return QNAN result #
12804# res_snan_1op() - return SNAN result #
12805# #
12806# INPUT *************************************************************** #
12807# a0 = pointer to extended precision source operand #
12808# d0 = rnd prec,mode #
12809# #
12810# OUTPUT ************************************************************** #
12811# fp0 = result #
12812# fp1 = EXOP (if exception occurred) #
12813# #
12814# ALGORITHM *********************************************************** #
12815# Handle NANs, zeroes, and infinities as special cases. Separate #
12816# norms/denorms into ext/sgl/dbl precisions. Extended precision can be #
12817# emulated by simply setting sign bit. Sgl/dbl operands must be scaled #
12818# and an actual fneg performed to see if overflow/underflow would have #
12819# occurred. If so, return default underflow/overflow result. Else, #
12820# scale the result exponent and return result. FPSR gets set based on #
12821# the result value. #
12822# #
12823#########################################################################
12824
12825 global fsneg
12826fsneg:
12827 andi.b &0x30,%d0 # clear rnd prec
12828 ori.b &s_mode*0x10,%d0 # insert sgl precision
12829 bra.b fneg
12830
12831 global fdneg
12832fdneg:
12833 andi.b &0x30,%d0 # clear rnd prec
12834 ori.b &d_mode*0x10,%d0 # insert dbl prec
12835
12836 global fneg
12837fneg:
12838 mov.l %d0,L_SCR3(%a6) # store rnd info
12839 mov.b STAG(%a6),%d1
12840 bne.w fneg_not_norm # optimize on non-norm input
12841
12842#
12843# NEGATE SIGN : norms and denorms ONLY!
12844#
12845fneg_norm:
12846 andi.b &0xc0,%d0 # is precision extended?
12847 bne.w fneg_not_ext # no; go handle sgl or dbl
12848
12849#
12850# precision selected is extended. so...we can not get an underflow
12851# or overflow because of rounding to the correct precision. so...
12852# skip the scaling and unscaling...
12853#
12854 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12855 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12856 mov.w SRC_EX(%a0),%d0
12857 eori.w &0x8000,%d0 # negate sign
12858 bpl.b fneg_norm_load # sign is positive
12859 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
12860fneg_norm_load:
12861 mov.w %d0,FP_SCR0_EX(%a6)
12862 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
12863 rts
12864
12865#
12866# for an extended precision DENORM, the UNFL exception bit is set
12867# the accrued bit is NOT set in this instance(no inexactness!)
12868#
12869fneg_denorm:
12870 andi.b &0xc0,%d0 # is precision extended?
12871 bne.b fneg_not_ext # no; go handle sgl or dbl
12872
12873 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
12874
12875 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12876 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12877 mov.w SRC_EX(%a0),%d0
12878 eori.w &0x8000,%d0 # negate sign
12879 bpl.b fneg_denorm_done # no
12880 mov.b &neg_bmask,FPSR_CC(%a6) # yes, set 'N' ccode bit
12881fneg_denorm_done:
12882 mov.w %d0,FP_SCR0_EX(%a6)
12883 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
12884
12885 btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
12886 bne.b fneg_ext_unfl_ena # yes
12887 rts
12888
12889#
12890# the input is an extended DENORM and underflow is enabled in the FPCR.
12891# normalize the mantissa and add the bias of 0x6000 to the resulting negative
12892# exponent and insert back into the operand.
12893#
12894fneg_ext_unfl_ena:
12895 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
12896 bsr.l norm # normalize result
12897 neg.w %d0 # new exponent = -(shft val)
12898 addi.w &0x6000,%d0 # add new bias to exponent
12899 mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
12900 andi.w &0x8000,%d1 # keep old sign
12901 andi.w &0x7fff,%d0 # clear sign position
12902 or.w %d1,%d0 # concat old sign, new exponent
12903 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
12904 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
12905 rts
12906
12907#
12908# operand is either single or double
12909#
12910fneg_not_ext:
12911 cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
12912 bne.b fneg_dbl
12913
12914#
12915# operand is to be rounded to single precision
12916#
12917fneg_sgl:
12918 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12919 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12920 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12921 bsr.l scale_to_zero_src # calculate scale factor
12922
12923 cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
12924 bge.w fneg_sd_unfl # yes; go handle underflow
12925 cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
12926 beq.w fneg_sd_may_ovfl # maybe; go check
12927 blt.w fneg_sd_ovfl # yes; go handle overflow
12928
12929#
12930# operand will NOT overflow or underflow when moved in to the fp reg file
12931#
12932fneg_sd_normal:
12933 fmov.l &0x0,%fpsr # clear FPSR
12934 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12935
12936 fneg.x FP_SCR0(%a6),%fp0 # perform negation
12937
12938 fmov.l %fpsr,%d1 # save FPSR
12939 fmov.l &0x0,%fpcr # clear FPCR
12940
12941 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12942
12943fneg_sd_normal_exit:
12944 mov.l %d2,-(%sp) # save d2
12945 fmovm.x &0x80,FP_SCR0(%a6) # store out result
12946 mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
12947 mov.w %d1,%d2 # make a copy
12948 andi.l &0x7fff,%d1 # strip sign
12949 sub.l %d0,%d1 # add scale factor
12950 andi.w &0x8000,%d2 # keep old sign
12951 or.w %d1,%d2 # concat old sign,new exp
12952 mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
12953 mov.l (%sp)+,%d2 # restore d2
12954 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
12955 rts
12956
12957#
12958# operand is to be rounded to double precision
12959#
12960fneg_dbl:
12961 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12962 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12963 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12964 bsr.l scale_to_zero_src # calculate scale factor
12965
12966 cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
12967 bge.b fneg_sd_unfl # yes; go handle underflow
12968 cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
12969 beq.w fneg_sd_may_ovfl # maybe; go check
12970 blt.w fneg_sd_ovfl # yes; go handle overflow
12971 bra.w fneg_sd_normal # no; ho handle normalized op
12972
12973#
12974# operand WILL underflow when moved in to the fp register file
12975#
12976fneg_sd_unfl:
12977 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
12978
12979 eori.b &0x80,FP_SCR0_EX(%a6) # negate sign
12980 bpl.b fneg_sd_unfl_tst
12981 bset &neg_bit,FPSR_CC(%a6) # set 'N' ccode bit
12982
12983# if underflow or inexact is enabled, go calculate EXOP first.
12984fneg_sd_unfl_tst:
12985 mov.b FPCR_ENABLE(%a6),%d1
12986 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
12987 bne.b fneg_sd_unfl_ena # yes
12988
12989fneg_sd_unfl_dis:
12990 lea FP_SCR0(%a6),%a0 # pass: result addr
12991 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
12992 bsr.l unf_res # calculate default result
12993 or.b %d0,FPSR_CC(%a6) # unf_res may have set 'Z'
12994 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
12995 rts
12996
12997#
12998# operand will underflow AND underflow is enabled.
12999# therefore, we must return the result rounded to extended precision.
13000#
13001fneg_sd_unfl_ena:
13002 mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
13003 mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
13004 mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
13005
13006 mov.l %d2,-(%sp) # save d2
13007 mov.l %d1,%d2 # make a copy
13008 andi.l &0x7fff,%d1 # strip sign
13009 andi.w &0x8000,%d2 # keep old sign
13010 sub.l %d0,%d1 # subtract scale factor
13011 addi.l &0x6000,%d1 # add new bias
13012 andi.w &0x7fff,%d1
13013 or.w %d2,%d1 # concat new sign,new exp
13014 mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
13015 fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
13016 mov.l (%sp)+,%d2 # restore d2
13017 bra.b fneg_sd_unfl_dis
13018
13019#
13020# operand WILL overflow.
13021#
13022fneg_sd_ovfl:
13023 fmov.l &0x0,%fpsr # clear FPSR
13024 fmov.l L_SCR3(%a6),%fpcr # set FPCR
13025
13026 fneg.x FP_SCR0(%a6),%fp0 # perform negation
13027
13028 fmov.l &0x0,%fpcr # clear FPCR
13029 fmov.l %fpsr,%d1 # save FPSR
13030
13031 or.l %d1,USER_FPSR(%a6) # save INEX2,N
13032
13033fneg_sd_ovfl_tst:
13034 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
13035
13036 mov.b FPCR_ENABLE(%a6),%d1
13037 andi.b &0x13,%d1 # is OVFL or INEX enabled?
13038 bne.b fneg_sd_ovfl_ena # yes
13039
13040#
13041# OVFL is not enabled; therefore, we must create the default result by
13042# calling ovf_res().
13043#
13044fneg_sd_ovfl_dis:
13045 btst &neg_bit,FPSR_CC(%a6) # is result negative?
13046 sne %d1 # set sign param accordingly
13047 mov.l L_SCR3(%a6),%d0 # pass: prec,mode
13048 bsr.l ovf_res # calculate default result
13049 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
13050 fmovm.x (%a0),&0x80 # return default result in fp0
13051 rts
13052
13053#
13054# OVFL is enabled.
13055# the INEX2 bit has already been updated by the round to the correct precision.
13056# now, round to extended(and don't alter the FPSR).
13057#
13058fneg_sd_ovfl_ena:
13059 mov.l %d2,-(%sp) # save d2
13060 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
13061 mov.l %d1,%d2 # make a copy
13062 andi.l &0x7fff,%d1 # strip sign
13063 andi.w &0x8000,%d2 # keep old sign
13064 sub.l %d0,%d1 # add scale factor
13065 subi.l &0x6000,%d1 # subtract bias
13066 andi.w &0x7fff,%d1
13067 or.w %d2,%d1 # concat sign,exp
13068 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
13069 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
13070 mov.l (%sp)+,%d2 # restore d2
13071 bra.b fneg_sd_ovfl_dis
13072
13073#
13074# the move in MAY underflow. so...
13075#
13076fneg_sd_may_ovfl:
13077 fmov.l &0x0,%fpsr # clear FPSR
13078 fmov.l L_SCR3(%a6),%fpcr # set FPCR
13079
13080 fneg.x FP_SCR0(%a6),%fp0 # perform negation
13081
13082 fmov.l %fpsr,%d1 # save status
13083 fmov.l &0x0,%fpcr # clear FPCR
13084
13085 or.l %d1,USER_FPSR(%a6) # save INEX2,N
13086
13087 fabs.x %fp0,%fp1 # make a copy of result
13088 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
13089 fbge.w fneg_sd_ovfl_tst # yes; overflow has occurred
13090
13091# no, it didn't overflow; we have correct result
13092 bra.w fneg_sd_normal_exit
13093
13094##########################################################################
13095
13096#
13097# input is not normalized; what is it?
13098#
13099fneg_not_norm:
13100 cmpi.b %d1,&DENORM # weed out DENORM
13101 beq.w fneg_denorm
13102 cmpi.b %d1,&SNAN # weed out SNAN
13103 beq.l res_snan_1op
13104 cmpi.b %d1,&QNAN # weed out QNAN
13105 beq.l res_qnan_1op
13106
13107#
13108# do the fneg; at this point, only possible ops are ZERO and INF.
13109# use fneg to determine ccodes.
13110# prec:mode should be zero at this point but it won't affect answer anyways.
13111#
13112 fneg.x SRC_EX(%a0),%fp0 # do fneg
13113 fmov.l %fpsr,%d0
13114 rol.l &0x8,%d0 # put ccodes in lo byte
13115 mov.b %d0,FPSR_CC(%a6) # insert correct ccodes
13116 rts
13117
13118#########################################################################
13119# XDEF **************************************************************** #
13120# ftst(): emulates the ftest instruction #
13121# #
13122# XREF **************************************************************** #
13123# res{s,q}nan_1op() - set NAN result for monadic instruction #
13124# #
13125# INPUT *************************************************************** #
13126# a0 = pointer to extended precision source operand #
13127# #
13128# OUTPUT ************************************************************** #
13129# none #
13130# #
13131# ALGORITHM *********************************************************** #
13132# Check the source operand tag (STAG) and set the FPCR according #
13133# to the operand type and sign. #
13134# #
13135#########################################################################
13136
13137 global ftst
13138ftst:
13139 mov.b STAG(%a6),%d1
13140 bne.b ftst_not_norm # optimize on non-norm input
13141
13142#
13143# Norm:
13144#
13145ftst_norm:
13146 tst.b SRC_EX(%a0) # is operand negative?
13147 bmi.b ftst_norm_m # yes
13148 rts
13149ftst_norm_m:
13150 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
13151 rts
13152
13153#
13154# input is not normalized; what is it?
13155#
13156ftst_not_norm:
13157 cmpi.b %d1,&ZERO # weed out ZERO
13158 beq.b ftst_zero
13159 cmpi.b %d1,&INF # weed out INF
13160 beq.b ftst_inf
13161 cmpi.b %d1,&SNAN # weed out SNAN
13162 beq.l res_snan_1op
13163 cmpi.b %d1,&QNAN # weed out QNAN
13164 beq.l res_qnan_1op
13165
13166#
13167# Denorm:
13168#
13169ftst_denorm:
13170 tst.b SRC_EX(%a0) # is operand negative?
13171 bmi.b ftst_denorm_m # yes
13172 rts
13173ftst_denorm_m:
13174 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
13175 rts
13176
13177#
13178# Infinity:
13179#
13180ftst_inf:
13181 tst.b SRC_EX(%a0) # is operand negative?
13182 bmi.b ftst_inf_m # yes
13183ftst_inf_p:
13184 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
13185 rts
13186ftst_inf_m:
13187 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'I','N' ccode bits
13188 rts
13189
13190#
13191# Zero:
13192#
13193ftst_zero:
13194 tst.b SRC_EX(%a0) # is operand negative?
13195 bmi.b ftst_zero_m # yes
13196ftst_zero_p:
13197 mov.b &z_bmask,FPSR_CC(%a6) # set 'N' ccode bit
13198 rts
13199ftst_zero_m:
13200 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
13201 rts
13202
13203#########################################################################
13204# XDEF **************************************************************** #
13205# fint(): emulates the fint instruction #
13206# #
13207# XREF **************************************************************** #
13208# res_{s,q}nan_1op() - set NAN result for monadic operation #
13209# #
13210# INPUT *************************************************************** #
13211# a0 = pointer to extended precision source operand #
13212# d0 = round precision/mode #
13213# #
13214# OUTPUT ************************************************************** #
13215# fp0 = result #
13216# #
13217# ALGORITHM *********************************************************** #
13218# Separate according to operand type. Unnorms don't pass through #
13219# here. For norms, load the rounding mode/prec, execute a "fint", then #
13220# store the resulting FPSR bits. #
13221# For denorms, force the j-bit to a one and do the same as for #
13222# norms. Denorms are so low that the answer will either be a zero or a #
13223# one. #
13224# For zeroes/infs/NANs, return the same while setting the FPSR #
13225# as appropriate. #
13226# #
13227#########################################################################
13228
13229 global fint
13230fint:
13231 mov.b STAG(%a6),%d1
13232 bne.b fint_not_norm # optimize on non-norm input
13233
13234#
13235# Norm:
13236#
13237fint_norm:
13238 andi.b &0x30,%d0 # set prec = ext
13239
13240 fmov.l %d0,%fpcr # set FPCR
13241 fmov.l &0x0,%fpsr # clear FPSR
13242
13243 fint.x SRC(%a0),%fp0 # execute fint
13244
13245 fmov.l &0x0,%fpcr # clear FPCR
13246 fmov.l %fpsr,%d0 # save FPSR
13247 or.l %d0,USER_FPSR(%a6) # set exception bits
13248
13249 rts
13250
13251#
13252# input is not normalized; what is it?
13253#
13254fint_not_norm:
13255 cmpi.b %d1,&ZERO # weed out ZERO
13256 beq.b fint_zero
13257 cmpi.b %d1,&INF # weed out INF
13258 beq.b fint_inf
13259 cmpi.b %d1,&DENORM # weed out DENORM
13260 beq.b fint_denorm
13261 cmpi.b %d1,&SNAN # weed out SNAN
13262 beq.l res_snan_1op
13263 bra.l res_qnan_1op # weed out QNAN
13264
13265#
13266# Denorm:
13267#
13268# for DENORMs, the result will be either (+/-)ZERO or (+/-)1.
13269# also, the INEX2 and AINEX exception bits will be set.
13270# so, we could either set these manually or force the DENORM
13271# to a very small NORM and ship it to the NORM routine.
13272# I do the latter.
13273#
13274fint_denorm:
13275 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
13276 mov.b &0x80,FP_SCR0_HI(%a6) # force DENORM ==> small NORM
13277 lea FP_SCR0(%a6),%a0
13278 bra.b fint_norm
13279
13280#
13281# Zero:
13282#
13283fint_zero:
13284 tst.b SRC_EX(%a0) # is ZERO negative?
13285 bmi.b fint_zero_m # yes
13286fint_zero_p:
13287 fmov.s &0x00000000,%fp0 # return +ZERO in fp0
13288 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
13289 rts
13290fint_zero_m:
13291 fmov.s &0x80000000,%fp0 # return -ZERO in fp0
13292 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
13293 rts
13294
13295#
13296# Infinity:
13297#
13298fint_inf:
13299 fmovm.x SRC(%a0),&0x80 # return result in fp0
13300 tst.b SRC_EX(%a0) # is INF negative?
13301 bmi.b fint_inf_m # yes
13302fint_inf_p:
13303 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
13304 rts
13305fint_inf_m:
13306 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
13307 rts
13308
13309#########################################################################
13310# XDEF **************************************************************** #
13311# fintrz(): emulates the fintrz instruction #
13312# #
13313# XREF **************************************************************** #
13314# res_{s,q}nan_1op() - set NAN result for monadic operation #
13315# #
13316# INPUT *************************************************************** #
13317# a0 = pointer to extended precision source operand #
13318# d0 = round precision/mode #
13319# #
13320# OUTPUT ************************************************************** #
13321# fp0 = result #
13322# #
13323# ALGORITHM *********************************************************** #
13324# Separate according to operand type. Unnorms don't pass through #
13325# here. For norms, load the rounding mode/prec, execute a "fintrz", #
13326# then store the resulting FPSR bits. #
13327# For denorms, force the j-bit to a one and do the same as for #
13328# norms. Denorms are so low that the answer will either be a zero or a #
13329# one. #
13330# For zeroes/infs/NANs, return the same while setting the FPSR #
13331# as appropriate. #
13332# #
13333#########################################################################
13334
13335 global fintrz
13336fintrz:
13337 mov.b STAG(%a6),%d1
13338 bne.b fintrz_not_norm # optimize on non-norm input
13339
13340#
13341# Norm:
13342#
13343fintrz_norm:
13344 fmov.l &0x0,%fpsr # clear FPSR
13345
13346 fintrz.x SRC(%a0),%fp0 # execute fintrz
13347
13348 fmov.l %fpsr,%d0 # save FPSR
13349 or.l %d0,USER_FPSR(%a6) # set exception bits
13350
13351 rts
13352
13353#
13354# input is not normalized; what is it?
13355#
13356fintrz_not_norm:
13357 cmpi.b %d1,&ZERO # weed out ZERO
13358 beq.b fintrz_zero
13359 cmpi.b %d1,&INF # weed out INF
13360 beq.b fintrz_inf
13361 cmpi.b %d1,&DENORM # weed out DENORM
13362 beq.b fintrz_denorm
13363 cmpi.b %d1,&SNAN # weed out SNAN
13364 beq.l res_snan_1op
13365 bra.l res_qnan_1op # weed out QNAN
13366
13367#
13368# Denorm:
13369#
13370# for DENORMs, the result will be (+/-)ZERO.
13371# also, the INEX2 and AINEX exception bits will be set.
13372# so, we could either set these manually or force the DENORM
13373# to a very small NORM and ship it to the NORM routine.
13374# I do the latter.
13375#
13376fintrz_denorm:
13377 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
13378 mov.b &0x80,FP_SCR0_HI(%a6) # force DENORM ==> small NORM
13379 lea FP_SCR0(%a6),%a0
13380 bra.b fintrz_norm
13381
13382#
13383# Zero:
13384#
13385fintrz_zero:
13386 tst.b SRC_EX(%a0) # is ZERO negative?
13387 bmi.b fintrz_zero_m # yes
13388fintrz_zero_p:
13389 fmov.s &0x00000000,%fp0 # return +ZERO in fp0
13390 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
13391 rts
13392fintrz_zero_m:
13393 fmov.s &0x80000000,%fp0 # return -ZERO in fp0
13394 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
13395 rts
13396
13397#
13398# Infinity:
13399#
13400fintrz_inf:
13401 fmovm.x SRC(%a0),&0x80 # return result in fp0
13402 tst.b SRC_EX(%a0) # is INF negative?
13403 bmi.b fintrz_inf_m # yes
13404fintrz_inf_p:
13405 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
13406 rts
13407fintrz_inf_m:
13408 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
13409 rts
13410
13411#########################################################################
13412# XDEF **************************************************************** #
13413# fabs(): emulates the fabs instruction #
13414# fsabs(): emulates the fsabs instruction #
13415# fdabs(): emulates the fdabs instruction #
13416# #
13417# XREF **************************************************************** #
13418# norm() - normalize denorm mantissa to provide EXOP #
13419# scale_to_zero_src() - make exponent. = 0; get scale factor #
13420# unf_res() - calculate underflow result #
13421# ovf_res() - calculate overflow result #
13422# res_{s,q}nan_1op() - set NAN result for monadic operation #
13423# #
13424# INPUT *************************************************************** #
13425# a0 = pointer to extended precision source operand #
13426# d0 = rnd precision/mode #
13427# #
13428# OUTPUT ************************************************************** #
13429# fp0 = result #
13430# fp1 = EXOP (if exception occurred) #
13431# #
13432# ALGORITHM *********************************************************** #
13433# Handle NANs, infinities, and zeroes as special cases. Divide #
13434# norms into extended, single, and double precision. #
13435# Simply clear sign for extended precision norm. Ext prec denorm #
13436# gets an EXOP created for it since it's an underflow. #
13437# Double and single precision can overflow and underflow. First, #
13438# scale the operand such that the exponent is zero. Perform an "fabs" #
13439# using the correct rnd mode/prec. Check to see if the original #
13440# exponent would take an exception. If so, use unf_res() or ovf_res() #
13441# to calculate the default result. Also, create the EXOP for the #
13442# exceptional case. If no exception should occur, insert the correct #
13443# result exponent and return. #
13444# Unnorms don't pass through here. #
13445# #
13446#########################################################################
13447
13448 global fsabs
13449fsabs:
13450 andi.b &0x30,%d0 # clear rnd prec
13451 ori.b &s_mode*0x10,%d0 # insert sgl precision
13452 bra.b fabs
13453
13454 global fdabs
13455fdabs:
13456 andi.b &0x30,%d0 # clear rnd prec
13457 ori.b &d_mode*0x10,%d0 # insert dbl precision
13458
13459 global fabs
13460fabs:
13461 mov.l %d0,L_SCR3(%a6) # store rnd info
13462 mov.b STAG(%a6),%d1
13463 bne.w fabs_not_norm # optimize on non-norm input
13464
13465#
13466# ABSOLUTE VALUE: norms and denorms ONLY!
13467#
13468fabs_norm:
13469 andi.b &0xc0,%d0 # is precision extended?
13470 bne.b fabs_not_ext # no; go handle sgl or dbl
13471
13472#
13473# precision selected is extended. so...we can not get an underflow
13474# or overflow because of rounding to the correct precision. so...
13475# skip the scaling and unscaling...
13476#
13477 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
13478 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
13479 mov.w SRC_EX(%a0),%d1
13480 bclr &15,%d1 # force absolute value
13481 mov.w %d1,FP_SCR0_EX(%a6) # insert exponent
13482 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
13483 rts
13484
13485#
13486# for an extended precision DENORM, the UNFL exception bit is set
13487# the accrued bit is NOT set in this instance(no inexactness!)
13488#
13489fabs_denorm:
13490 andi.b &0xc0,%d0 # is precision extended?
13491 bne.b fabs_not_ext # no
13492
13493 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
13494
13495 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
13496 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
13497 mov.w SRC_EX(%a0),%d0
13498 bclr &15,%d0 # clear sign
13499 mov.w %d0,FP_SCR0_EX(%a6) # insert exponent
13500
13501 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
13502
13503 btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
13504 bne.b fabs_ext_unfl_ena
13505 rts
13506
13507#
13508# the input is an extended DENORM and underflow is enabled in the FPCR.
13509# normalize the mantissa and add the bias of 0x6000 to the resulting negative
13510# exponent and insert back into the operand.
13511#
13512fabs_ext_unfl_ena:
13513 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
13514 bsr.l norm # normalize result
13515 neg.w %d0 # new exponent = -(shft val)
13516 addi.w &0x6000,%d0 # add new bias to exponent
13517 mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
13518 andi.w &0x8000,%d1 # keep old sign
13519 andi.w &0x7fff,%d0 # clear sign position
13520 or.w %d1,%d0 # concat old sign, new exponent
13521 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
13522 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
13523 rts
13524
13525#
13526# operand is either single or double
13527#
13528fabs_not_ext:
13529 cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
13530 bne.b fabs_dbl
13531
13532#
13533# operand is to be rounded to single precision
13534#
13535fabs_sgl:
13536 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
13537 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
13538 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
13539 bsr.l scale_to_zero_src # calculate scale factor
13540
13541 cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
13542 bge.w fabs_sd_unfl # yes; go handle underflow
13543 cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
13544 beq.w fabs_sd_may_ovfl # maybe; go check
13545 blt.w fabs_sd_ovfl # yes; go handle overflow
13546
13547#
13548# operand will NOT overflow or underflow when moved in to the fp reg file
13549#
13550fabs_sd_normal:
13551 fmov.l &0x0,%fpsr # clear FPSR
13552 fmov.l L_SCR3(%a6),%fpcr # set FPCR
13553
13554 fabs.x FP_SCR0(%a6),%fp0 # perform absolute
13555
13556 fmov.l %fpsr,%d1 # save FPSR
13557 fmov.l &0x0,%fpcr # clear FPCR
13558
13559 or.l %d1,USER_FPSR(%a6) # save INEX2,N
13560
13561fabs_sd_normal_exit:
13562 mov.l %d2,-(%sp) # save d2
13563 fmovm.x &0x80,FP_SCR0(%a6) # store out result
13564 mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
13565 mov.l %d1,%d2 # make a copy
13566 andi.l &0x7fff,%d1 # strip sign
13567 sub.l %d0,%d1 # add scale factor
13568 andi.w &0x8000,%d2 # keep old sign
13569 or.w %d1,%d2 # concat old sign,new exp
13570 mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
13571 mov.l (%sp)+,%d2 # restore d2
13572 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
13573 rts
13574
13575#
13576# operand is to be rounded to double precision
13577#
13578fabs_dbl:
13579 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
13580 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
13581 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
13582 bsr.l scale_to_zero_src # calculate scale factor
13583
13584 cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
13585 bge.b fabs_sd_unfl # yes; go handle underflow
13586 cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
13587 beq.w fabs_sd_may_ovfl # maybe; go check
13588 blt.w fabs_sd_ovfl # yes; go handle overflow
13589 bra.w fabs_sd_normal # no; ho handle normalized op
13590
13591#
13592# operand WILL underflow when moved in to the fp register file
13593#
13594fabs_sd_unfl:
13595 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
13596
13597 bclr &0x7,FP_SCR0_EX(%a6) # force absolute value
13598
13599# if underflow or inexact is enabled, go calculate EXOP first.
13600 mov.b FPCR_ENABLE(%a6),%d1
13601 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
13602 bne.b fabs_sd_unfl_ena # yes
13603
13604fabs_sd_unfl_dis:
13605 lea FP_SCR0(%a6),%a0 # pass: result addr
13606 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
13607 bsr.l unf_res # calculate default result
13608 or.b %d0,FPSR_CC(%a6) # set possible 'Z' ccode
13609 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
13610 rts
13611
13612#
13613# operand will underflow AND underflow is enabled.
13614# therefore, we must return the result rounded to extended precision.
13615#
13616fabs_sd_unfl_ena:
13617 mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
13618 mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
13619 mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
13620
13621 mov.l %d2,-(%sp) # save d2
13622 mov.l %d1,%d2 # make a copy
13623 andi.l &0x7fff,%d1 # strip sign
13624 andi.w &0x8000,%d2 # keep old sign
13625 sub.l %d0,%d1 # subtract scale factor
13626 addi.l &0x6000,%d1 # add new bias
13627 andi.w &0x7fff,%d1
13628 or.w %d2,%d1 # concat new sign,new exp
13629 mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
13630 fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
13631 mov.l (%sp)+,%d2 # restore d2
13632 bra.b fabs_sd_unfl_dis
13633
13634#
13635# operand WILL overflow.
13636#
13637fabs_sd_ovfl:
13638 fmov.l &0x0,%fpsr # clear FPSR
13639 fmov.l L_SCR3(%a6),%fpcr # set FPCR
13640
13641 fabs.x FP_SCR0(%a6),%fp0 # perform absolute
13642
13643 fmov.l &0x0,%fpcr # clear FPCR
13644 fmov.l %fpsr,%d1 # save FPSR
13645
13646 or.l %d1,USER_FPSR(%a6) # save INEX2,N
13647
13648fabs_sd_ovfl_tst:
13649 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
13650
13651 mov.b FPCR_ENABLE(%a6),%d1
13652 andi.b &0x13,%d1 # is OVFL or INEX enabled?
13653 bne.b fabs_sd_ovfl_ena # yes
13654
13655#
13656# OVFL is not enabled; therefore, we must create the default result by
13657# calling ovf_res().
13658#
13659fabs_sd_ovfl_dis:
13660 btst &neg_bit,FPSR_CC(%a6) # is result negative?
13661 sne %d1 # set sign param accordingly
13662 mov.l L_SCR3(%a6),%d0 # pass: prec,mode
13663 bsr.l ovf_res # calculate default result
13664 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
13665 fmovm.x (%a0),&0x80 # return default result in fp0
13666 rts
13667
13668#
13669# OVFL is enabled.
13670# the INEX2 bit has already been updated by the round to the correct precision.
13671# now, round to extended(and don't alter the FPSR).
13672#
13673fabs_sd_ovfl_ena:
13674 mov.l %d2,-(%sp) # save d2
13675 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
13676 mov.l %d1,%d2 # make a copy
13677 andi.l &0x7fff,%d1 # strip sign
13678 andi.w &0x8000,%d2 # keep old sign
13679 sub.l %d0,%d1 # add scale factor
13680 subi.l &0x6000,%d1 # subtract bias
13681 andi.w &0x7fff,%d1
13682 or.w %d2,%d1 # concat sign,exp
13683 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
13684 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
13685 mov.l (%sp)+,%d2 # restore d2
13686 bra.b fabs_sd_ovfl_dis
13687
13688#
13689# the move in MAY underflow. so...
13690#
13691fabs_sd_may_ovfl:
13692 fmov.l &0x0,%fpsr # clear FPSR
13693 fmov.l L_SCR3(%a6),%fpcr # set FPCR
13694
13695 fabs.x FP_SCR0(%a6),%fp0 # perform absolute
13696
13697 fmov.l %fpsr,%d1 # save status
13698 fmov.l &0x0,%fpcr # clear FPCR
13699
13700 or.l %d1,USER_FPSR(%a6) # save INEX2,N
13701
13702 fabs.x %fp0,%fp1 # make a copy of result
13703 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
13704 fbge.w fabs_sd_ovfl_tst # yes; overflow has occurred
13705
13706# no, it didn't overflow; we have correct result
13707 bra.w fabs_sd_normal_exit
13708
13709##########################################################################
13710
13711#
13712# input is not normalized; what is it?
13713#
13714fabs_not_norm:
13715 cmpi.b %d1,&DENORM # weed out DENORM
13716 beq.w fabs_denorm
13717 cmpi.b %d1,&SNAN # weed out SNAN
13718 beq.l res_snan_1op
13719 cmpi.b %d1,&QNAN # weed out QNAN
13720 beq.l res_qnan_1op
13721
13722 fabs.x SRC(%a0),%fp0 # force absolute value
13723
13724 cmpi.b %d1,&INF # weed out INF
13725 beq.b fabs_inf
13726fabs_zero:
13727 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
13728 rts
13729fabs_inf:
13730 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
13731 rts
13732
13733#########################################################################
13734# XDEF **************************************************************** #
13735# fcmp(): fp compare op routine #
13736# #
13737# XREF **************************************************************** #
13738# res_qnan() - return QNAN result #
13739# res_snan() - return SNAN result #
13740# #
13741# INPUT *************************************************************** #
13742# a0 = pointer to extended precision source operand #
13743# a1 = pointer to extended precision destination operand #
13744# d0 = round prec/mode #
13745# #
13746# OUTPUT ************************************************************** #
13747# None #
13748# #
13749# ALGORITHM *********************************************************** #
13750# Handle NANs and denorms as special cases. For everything else, #
13751# just use the actual fcmp instruction to produce the correct condition #
13752# codes. #
13753# #
13754#########################################################################
13755
13756 global fcmp
13757fcmp:
13758 clr.w %d1
13759 mov.b DTAG(%a6),%d1
13760 lsl.b &0x3,%d1
13761 or.b STAG(%a6),%d1
13762 bne.b fcmp_not_norm # optimize on non-norm input
13763
13764#
13765# COMPARE FP OPs : NORMs, ZEROs, INFs, and "corrected" DENORMs
13766#
13767fcmp_norm:
13768 fmovm.x DST(%a1),&0x80 # load dst op
13769
13770 fcmp.x %fp0,SRC(%a0) # do compare
13771
13772 fmov.l %fpsr,%d0 # save FPSR
13773 rol.l &0x8,%d0 # extract ccode bits
13774 mov.b %d0,FPSR_CC(%a6) # set ccode bits(no exc bits are set)
13775
13776 rts
13777
13778#
13779# fcmp: inputs are not both normalized; what are they?
13780#
13781fcmp_not_norm:
13782 mov.w (tbl_fcmp_op.b,%pc,%d1.w*2),%d1
13783 jmp (tbl_fcmp_op.b,%pc,%d1.w*1)
13784
13785 swbeg &48
13786tbl_fcmp_op:
13787 short fcmp_norm - tbl_fcmp_op # NORM - NORM
13788 short fcmp_norm - tbl_fcmp_op # NORM - ZERO
13789 short fcmp_norm - tbl_fcmp_op # NORM - INF
13790 short fcmp_res_qnan - tbl_fcmp_op # NORM - QNAN
13791 short fcmp_nrm_dnrm - tbl_fcmp_op # NORM - DENORM
13792 short fcmp_res_snan - tbl_fcmp_op # NORM - SNAN
13793 short tbl_fcmp_op - tbl_fcmp_op #
13794 short tbl_fcmp_op - tbl_fcmp_op #
13795
13796 short fcmp_norm - tbl_fcmp_op # ZERO - NORM
13797 short fcmp_norm - tbl_fcmp_op # ZERO - ZERO
13798 short fcmp_norm - tbl_fcmp_op # ZERO - INF
13799 short fcmp_res_qnan - tbl_fcmp_op # ZERO - QNAN
13800 short fcmp_dnrm_s - tbl_fcmp_op # ZERO - DENORM
13801 short fcmp_res_snan - tbl_fcmp_op # ZERO - SNAN
13802 short tbl_fcmp_op - tbl_fcmp_op #
13803 short tbl_fcmp_op - tbl_fcmp_op #
13804
13805 short fcmp_norm - tbl_fcmp_op # INF - NORM
13806 short fcmp_norm - tbl_fcmp_op # INF - ZERO
13807 short fcmp_norm - tbl_fcmp_op # INF - INF
13808 short fcmp_res_qnan - tbl_fcmp_op # INF - QNAN
13809 short fcmp_dnrm_s - tbl_fcmp_op # INF - DENORM
13810 short fcmp_res_snan - tbl_fcmp_op # INF - SNAN
13811 short tbl_fcmp_op - tbl_fcmp_op #
13812 short tbl_fcmp_op - tbl_fcmp_op #
13813
13814 short fcmp_res_qnan - tbl_fcmp_op # QNAN - NORM
13815 short fcmp_res_qnan - tbl_fcmp_op # QNAN - ZERO
13816 short fcmp_res_qnan - tbl_fcmp_op # QNAN - INF
13817 short fcmp_res_qnan - tbl_fcmp_op # QNAN - QNAN
13818 short fcmp_res_qnan - tbl_fcmp_op # QNAN - DENORM
13819 short fcmp_res_snan - tbl_fcmp_op # QNAN - SNAN
13820 short tbl_fcmp_op - tbl_fcmp_op #
13821 short tbl_fcmp_op - tbl_fcmp_op #
13822
13823 short fcmp_dnrm_nrm - tbl_fcmp_op # DENORM - NORM
13824 short fcmp_dnrm_d - tbl_fcmp_op # DENORM - ZERO
13825 short fcmp_dnrm_d - tbl_fcmp_op # DENORM - INF
13826 short fcmp_res_qnan - tbl_fcmp_op # DENORM - QNAN
13827 short fcmp_dnrm_sd - tbl_fcmp_op # DENORM - DENORM
13828 short fcmp_res_snan - tbl_fcmp_op # DENORM - SNAN
13829 short tbl_fcmp_op - tbl_fcmp_op #
13830 short tbl_fcmp_op - tbl_fcmp_op #
13831
13832 short fcmp_res_snan - tbl_fcmp_op # SNAN - NORM
13833 short fcmp_res_snan - tbl_fcmp_op # SNAN - ZERO
13834 short fcmp_res_snan - tbl_fcmp_op # SNAN - INF
13835 short fcmp_res_snan - tbl_fcmp_op # SNAN - QNAN
13836 short fcmp_res_snan - tbl_fcmp_op # SNAN - DENORM
13837 short fcmp_res_snan - tbl_fcmp_op # SNAN - SNAN
13838 short tbl_fcmp_op - tbl_fcmp_op #
13839 short tbl_fcmp_op - tbl_fcmp_op #
13840
13841# unlike all other functions for QNAN and SNAN, fcmp does NOT set the
13842# 'N' bit for a negative QNAN or SNAN input so we must squelch it here.
13843fcmp_res_qnan:
13844 bsr.l res_qnan
13845 andi.b &0xf7,FPSR_CC(%a6)
13846 rts
13847fcmp_res_snan:
13848 bsr.l res_snan
13849 andi.b &0xf7,FPSR_CC(%a6)
13850 rts
13851
13852#
13853# DENORMs are a little more difficult.
13854# If you have a 2 DENORMs, then you can just force the j-bit to a one
13855# and use the fcmp_norm routine.
13856# If you have a DENORM and an INF or ZERO, just force the DENORM's j-bit to a one
13857# and use the fcmp_norm routine.
13858# If you have a DENORM and a NORM with opposite signs, then use fcmp_norm, also.
13859# But with a DENORM and a NORM of the same sign, the neg bit is set if the
13860# (1) signs are (+) and the DENORM is the dst or
13861# (2) signs are (-) and the DENORM is the src
13862#
13863
13864fcmp_dnrm_s:
13865 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
13866 mov.l SRC_HI(%a0),%d0
13867 bset &31,%d0 # DENORM src; make into small norm
13868 mov.l %d0,FP_SCR0_HI(%a6)
13869 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
13870 lea FP_SCR0(%a6),%a0
13871 bra.w fcmp_norm
13872
13873fcmp_dnrm_d:
13874 mov.l DST_EX(%a1),FP_SCR0_EX(%a6)
13875 mov.l DST_HI(%a1),%d0
13876 bset &31,%d0 # DENORM src; make into small norm
13877 mov.l %d0,FP_SCR0_HI(%a6)
13878 mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
13879 lea FP_SCR0(%a6),%a1
13880 bra.w fcmp_norm
13881
13882fcmp_dnrm_sd:
13883 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
13884 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
13885 mov.l DST_HI(%a1),%d0
13886 bset &31,%d0 # DENORM dst; make into small norm
13887 mov.l %d0,FP_SCR1_HI(%a6)
13888 mov.l SRC_HI(%a0),%d0
13889 bset &31,%d0 # DENORM dst; make into small norm
13890 mov.l %d0,FP_SCR0_HI(%a6)
13891 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
13892 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
13893 lea FP_SCR1(%a6),%a1
13894 lea FP_SCR0(%a6),%a0
13895 bra.w fcmp_norm
13896
13897fcmp_nrm_dnrm:
13898 mov.b SRC_EX(%a0),%d0 # determine if like signs
13899 mov.b DST_EX(%a1),%d1
13900 eor.b %d0,%d1
13901 bmi.w fcmp_dnrm_s
13902
13903# signs are the same, so must determine the answer ourselves.
13904 tst.b %d0 # is src op negative?
13905 bmi.b fcmp_nrm_dnrm_m # yes
13906 rts
13907fcmp_nrm_dnrm_m:
13908 mov.b &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
13909 rts
13910
13911fcmp_dnrm_nrm:
13912 mov.b SRC_EX(%a0),%d0 # determine if like signs
13913 mov.b DST_EX(%a1),%d1
13914 eor.b %d0,%d1
13915 bmi.w fcmp_dnrm_d
13916
13917# signs are the same, so must determine the answer ourselves.
13918 tst.b %d0 # is src op negative?
13919 bpl.b fcmp_dnrm_nrm_m # no
13920 rts
13921fcmp_dnrm_nrm_m:
13922 mov.b &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
13923 rts
13924
13925#########################################################################
13926# XDEF **************************************************************** #
13927# fsglmul(): emulates the fsglmul instruction #
13928# #
13929# XREF **************************************************************** #
13930# scale_to_zero_src() - scale src exponent to zero #
13931# scale_to_zero_dst() - scale dst exponent to zero #
13932# unf_res4() - return default underflow result for sglop #
13933# ovf_res() - return default overflow result #
13934# res_qnan() - return QNAN result #
13935# res_snan() - return SNAN result #
13936# #
13937# INPUT *************************************************************** #
13938# a0 = pointer to extended precision source operand #
13939# a1 = pointer to extended precision destination operand #
13940# d0 rnd prec,mode #
13941# #
13942# OUTPUT ************************************************************** #
13943# fp0 = result #
13944# fp1 = EXOP (if exception occurred) #
13945# #
13946# ALGORITHM *********************************************************** #
13947# Handle NANs, infinities, and zeroes as special cases. Divide #
13948# norms/denorms into ext/sgl/dbl precision. #
13949# For norms/denorms, scale the exponents such that a multiply #
13950# instruction won't cause an exception. Use the regular fsglmul to #
13951# compute a result. Check if the regular operands would have taken #
13952# an exception. If so, return the default overflow/underflow result #
13953# and return the EXOP if exceptions are enabled. Else, scale the #
13954# result operand to the proper exponent. #
13955# #
13956#########################################################################
13957
13958 global fsglmul
13959fsglmul:
13960 mov.l %d0,L_SCR3(%a6) # store rnd info
13961
13962 clr.w %d1
13963 mov.b DTAG(%a6),%d1
13964 lsl.b &0x3,%d1
13965 or.b STAG(%a6),%d1
13966
13967 bne.w fsglmul_not_norm # optimize on non-norm input
13968
13969fsglmul_norm:
13970 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
13971 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
13972 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
13973
13974 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
13975 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
13976 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
13977
13978 bsr.l scale_to_zero_src # scale exponent
13979 mov.l %d0,-(%sp) # save scale factor 1
13980
13981 bsr.l scale_to_zero_dst # scale dst exponent
13982
13983 add.l (%sp)+,%d0 # SCALE_FACTOR = scale1 + scale2
13984
13985 cmpi.l %d0,&0x3fff-0x7ffe # would result ovfl?
13986 beq.w fsglmul_may_ovfl # result may rnd to overflow
13987 blt.w fsglmul_ovfl # result will overflow
13988
13989 cmpi.l %d0,&0x3fff+0x0001 # would result unfl?
13990 beq.w fsglmul_may_unfl # result may rnd to no unfl
13991 bgt.w fsglmul_unfl # result will underflow
13992
13993fsglmul_normal:
13994 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
13995
13996 fmov.l L_SCR3(%a6),%fpcr # set FPCR
13997 fmov.l &0x0,%fpsr # clear FPSR
13998
13999 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
14000
14001 fmov.l %fpsr,%d1 # save status
14002 fmov.l &0x0,%fpcr # clear FPCR
14003
14004 or.l %d1,USER_FPSR(%a6) # save INEX2,N
14005
14006fsglmul_normal_exit:
14007 fmovm.x &0x80,FP_SCR0(%a6) # store out result
14008 mov.l %d2,-(%sp) # save d2
14009 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
14010 mov.l %d1,%d2 # make a copy
14011 andi.l &0x7fff,%d1 # strip sign
14012 andi.w &0x8000,%d2 # keep old sign
14013 sub.l %d0,%d1 # add scale factor
14014 or.w %d2,%d1 # concat old sign,new exp
14015 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
14016 mov.l (%sp)+,%d2 # restore d2
14017 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
14018 rts
14019
14020fsglmul_ovfl:
14021 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14022
14023 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14024 fmov.l &0x0,%fpsr # clear FPSR
14025
14026 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
14027
14028 fmov.l %fpsr,%d1 # save status
14029 fmov.l &0x0,%fpcr # clear FPCR
14030
14031 or.l %d1,USER_FPSR(%a6) # save INEX2,N
14032
14033fsglmul_ovfl_tst:
14034
14035# save setting this until now because this is where fsglmul_may_ovfl may jump in
14036 or.l &ovfl_inx_mask, USER_FPSR(%a6) # set ovfl/aovfl/ainex
14037
14038 mov.b FPCR_ENABLE(%a6),%d1
14039 andi.b &0x13,%d1 # is OVFL or INEX enabled?
14040 bne.b fsglmul_ovfl_ena # yes
14041
14042fsglmul_ovfl_dis:
14043 btst &neg_bit,FPSR_CC(%a6) # is result negative?
14044 sne %d1 # set sign param accordingly
14045 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
14046 andi.b &0x30,%d0 # force prec = ext
14047 bsr.l ovf_res # calculate default result
14048 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
14049 fmovm.x (%a0),&0x80 # return default result in fp0
14050 rts
14051
14052fsglmul_ovfl_ena:
14053 fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
14054
14055 mov.l %d2,-(%sp) # save d2
14056 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
14057 mov.l %d1,%d2 # make a copy
14058 andi.l &0x7fff,%d1 # strip sign
14059 sub.l %d0,%d1 # add scale factor
14060 subi.l &0x6000,%d1 # subtract bias
14061 andi.w &0x7fff,%d1
14062 andi.w &0x8000,%d2 # keep old sign
14063 or.w %d2,%d1 # concat old sign,new exp
14064 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
14065 mov.l (%sp)+,%d2 # restore d2
14066 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
14067 bra.b fsglmul_ovfl_dis
14068
14069fsglmul_may_ovfl:
14070 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14071
14072 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14073 fmov.l &0x0,%fpsr # clear FPSR
14074
14075 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
14076
14077 fmov.l %fpsr,%d1 # save status
14078 fmov.l &0x0,%fpcr # clear FPCR
14079
14080 or.l %d1,USER_FPSR(%a6) # save INEX2,N
14081
14082 fabs.x %fp0,%fp1 # make a copy of result
14083 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
14084 fbge.w fsglmul_ovfl_tst # yes; overflow has occurred
14085
14086# no, it didn't overflow; we have correct result
14087 bra.w fsglmul_normal_exit
14088
14089fsglmul_unfl:
14090 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
14091
14092 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14093
14094 fmov.l &rz_mode*0x10,%fpcr # set FPCR
14095 fmov.l &0x0,%fpsr # clear FPSR
14096
14097 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
14098
14099 fmov.l %fpsr,%d1 # save status
14100 fmov.l &0x0,%fpcr # clear FPCR
14101
14102 or.l %d1,USER_FPSR(%a6) # save INEX2,N
14103
14104 mov.b FPCR_ENABLE(%a6),%d1
14105 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
14106 bne.b fsglmul_unfl_ena # yes
14107
14108fsglmul_unfl_dis:
14109 fmovm.x &0x80,FP_SCR0(%a6) # store out result
14110
14111 lea FP_SCR0(%a6),%a0 # pass: result addr
14112 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
14113 bsr.l unf_res4 # calculate default result
14114 or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
14115 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
14116 rts
14117
14118#
14119# UNFL is enabled.
14120#
14121fsglmul_unfl_ena:
14122 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
14123
14124 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14125 fmov.l &0x0,%fpsr # clear FPSR
14126
14127 fsglmul.x FP_SCR0(%a6),%fp1 # execute sgl multiply
14128
14129 fmov.l &0x0,%fpcr # clear FPCR
14130
14131 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
14132 mov.l %d2,-(%sp) # save d2
14133 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
14134 mov.l %d1,%d2 # make a copy
14135 andi.l &0x7fff,%d1 # strip sign
14136 andi.w &0x8000,%d2 # keep old sign
14137 sub.l %d0,%d1 # add scale factor
14138 addi.l &0x6000,%d1 # add bias
14139 andi.w &0x7fff,%d1
14140 or.w %d2,%d1 # concat old sign,new exp
14141 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
14142 mov.l (%sp)+,%d2 # restore d2
14143 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
14144 bra.w fsglmul_unfl_dis
14145
14146fsglmul_may_unfl:
14147 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14148
14149 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14150 fmov.l &0x0,%fpsr # clear FPSR
14151
14152 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
14153
14154 fmov.l %fpsr,%d1 # save status
14155 fmov.l &0x0,%fpcr # clear FPCR
14156
14157 or.l %d1,USER_FPSR(%a6) # save INEX2,N
14158
14159 fabs.x %fp0,%fp1 # make a copy of result
14160 fcmp.b %fp1,&0x2 # is |result| > 2.b?
14161 fbgt.w fsglmul_normal_exit # no; no underflow occurred
14162 fblt.w fsglmul_unfl # yes; underflow occurred
14163
14164#
14165# we still don't know if underflow occurred. result is ~ equal to 2. but,
14166# we don't know if the result was an underflow that rounded up to a 2 or
14167# a normalized number that rounded down to a 2. so, redo the entire operation
14168# using RZ as the rounding mode to see what the pre-rounded result is.
14169# this case should be relatively rare.
14170#
14171 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
14172
14173 mov.l L_SCR3(%a6),%d1
14174 andi.b &0xc0,%d1 # keep rnd prec
14175 ori.b &rz_mode*0x10,%d1 # insert RZ
14176
14177 fmov.l %d1,%fpcr # set FPCR
14178 fmov.l &0x0,%fpsr # clear FPSR
14179
14180 fsglmul.x FP_SCR0(%a6),%fp1 # execute sgl multiply
14181
14182 fmov.l &0x0,%fpcr # clear FPCR
14183 fabs.x %fp1 # make absolute value
14184 fcmp.b %fp1,&0x2 # is |result| < 2.b?
14185 fbge.w fsglmul_normal_exit # no; no underflow occurred
14186 bra.w fsglmul_unfl # yes, underflow occurred
14187
14188##############################################################################
14189
14190#
14191# Single Precision Multiply: inputs are not both normalized; what are they?
14192#
14193fsglmul_not_norm:
14194 mov.w (tbl_fsglmul_op.b,%pc,%d1.w*2),%d1
14195 jmp (tbl_fsglmul_op.b,%pc,%d1.w*1)
14196
14197 swbeg &48
14198tbl_fsglmul_op:
14199 short fsglmul_norm - tbl_fsglmul_op # NORM x NORM
14200 short fsglmul_zero - tbl_fsglmul_op # NORM x ZERO
14201 short fsglmul_inf_src - tbl_fsglmul_op # NORM x INF
14202 short fsglmul_res_qnan - tbl_fsglmul_op # NORM x QNAN
14203 short fsglmul_norm - tbl_fsglmul_op # NORM x DENORM
14204 short fsglmul_res_snan - tbl_fsglmul_op # NORM x SNAN
14205 short tbl_fsglmul_op - tbl_fsglmul_op #
14206 short tbl_fsglmul_op - tbl_fsglmul_op #
14207
14208 short fsglmul_zero - tbl_fsglmul_op # ZERO x NORM
14209 short fsglmul_zero - tbl_fsglmul_op # ZERO x ZERO
14210 short fsglmul_res_operr - tbl_fsglmul_op # ZERO x INF
14211 short fsglmul_res_qnan - tbl_fsglmul_op # ZERO x QNAN
14212 short fsglmul_zero - tbl_fsglmul_op # ZERO x DENORM
14213 short fsglmul_res_snan - tbl_fsglmul_op # ZERO x SNAN
14214 short tbl_fsglmul_op - tbl_fsglmul_op #
14215 short tbl_fsglmul_op - tbl_fsglmul_op #
14216
14217 short fsglmul_inf_dst - tbl_fsglmul_op # INF x NORM
14218 short fsglmul_res_operr - tbl_fsglmul_op # INF x ZERO
14219 short fsglmul_inf_dst - tbl_fsglmul_op # INF x INF
14220 short fsglmul_res_qnan - tbl_fsglmul_op # INF x QNAN
14221 short fsglmul_inf_dst - tbl_fsglmul_op # INF x DENORM
14222 short fsglmul_res_snan - tbl_fsglmul_op # INF x SNAN
14223 short tbl_fsglmul_op - tbl_fsglmul_op #
14224 short tbl_fsglmul_op - tbl_fsglmul_op #
14225
14226 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x NORM
14227 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x ZERO
14228 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x INF
14229 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x QNAN
14230 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x DENORM
14231 short fsglmul_res_snan - tbl_fsglmul_op # QNAN x SNAN
14232 short tbl_fsglmul_op - tbl_fsglmul_op #
14233 short tbl_fsglmul_op - tbl_fsglmul_op #
14234
14235 short fsglmul_norm - tbl_fsglmul_op # NORM x NORM
14236 short fsglmul_zero - tbl_fsglmul_op # NORM x ZERO
14237 short fsglmul_inf_src - tbl_fsglmul_op # NORM x INF
14238 short fsglmul_res_qnan - tbl_fsglmul_op # NORM x QNAN
14239 short fsglmul_norm - tbl_fsglmul_op # NORM x DENORM
14240 short fsglmul_res_snan - tbl_fsglmul_op # NORM x SNAN
14241 short tbl_fsglmul_op - tbl_fsglmul_op #
14242 short tbl_fsglmul_op - tbl_fsglmul_op #
14243
14244 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x NORM
14245 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x ZERO
14246 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x INF
14247 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x QNAN
14248 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x DENORM
14249 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x SNAN
14250 short tbl_fsglmul_op - tbl_fsglmul_op #
14251 short tbl_fsglmul_op - tbl_fsglmul_op #
14252
14253fsglmul_res_operr:
14254 bra.l res_operr
14255fsglmul_res_snan:
14256 bra.l res_snan
14257fsglmul_res_qnan:
14258 bra.l res_qnan
14259fsglmul_zero:
14260 bra.l fmul_zero
14261fsglmul_inf_src:
14262 bra.l fmul_inf_src
14263fsglmul_inf_dst:
14264 bra.l fmul_inf_dst
14265
14266#########################################################################
14267# XDEF **************************************************************** #
14268# fsgldiv(): emulates the fsgldiv instruction #
14269# #
14270# XREF **************************************************************** #
14271# scale_to_zero_src() - scale src exponent to zero #
14272# scale_to_zero_dst() - scale dst exponent to zero #
14273# unf_res4() - return default underflow result for sglop #
14274# ovf_res() - return default overflow result #
14275# res_qnan() - return QNAN result #
14276# res_snan() - return SNAN result #
14277# #
14278# INPUT *************************************************************** #
14279# a0 = pointer to extended precision source operand #
14280# a1 = pointer to extended precision destination operand #
14281# d0 rnd prec,mode #
14282# #
14283# OUTPUT ************************************************************** #
14284# fp0 = result #
14285# fp1 = EXOP (if exception occurred) #
14286# #
14287# ALGORITHM *********************************************************** #
14288# Handle NANs, infinities, and zeroes as special cases. Divide #
14289# norms/denorms into ext/sgl/dbl precision. #
14290# For norms/denorms, scale the exponents such that a divide #
14291# instruction won't cause an exception. Use the regular fsgldiv to #
14292# compute a result. Check if the regular operands would have taken #
14293# an exception. If so, return the default overflow/underflow result #
14294# and return the EXOP if exceptions are enabled. Else, scale the #
14295# result operand to the proper exponent. #
14296# #
14297#########################################################################
14298
14299 global fsgldiv
14300fsgldiv:
14301 mov.l %d0,L_SCR3(%a6) # store rnd info
14302
14303 clr.w %d1
14304 mov.b DTAG(%a6),%d1
14305 lsl.b &0x3,%d1
14306 or.b STAG(%a6),%d1 # combine src tags
14307
14308 bne.w fsgldiv_not_norm # optimize on non-norm input
14309
14310#
14311# DIVIDE: NORMs and DENORMs ONLY!
14312#
14313fsgldiv_norm:
14314 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
14315 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
14316 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
14317
14318 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
14319 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
14320 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
14321
14322 bsr.l scale_to_zero_src # calculate scale factor 1
14323 mov.l %d0,-(%sp) # save scale factor 1
14324
14325 bsr.l scale_to_zero_dst # calculate scale factor 2
14326
14327 neg.l (%sp) # S.F. = scale1 - scale2
14328 add.l %d0,(%sp)
14329
14330 mov.w 2+L_SCR3(%a6),%d1 # fetch precision,mode
14331 lsr.b &0x6,%d1
14332 mov.l (%sp)+,%d0
14333 cmpi.l %d0,&0x3fff-0x7ffe
14334 ble.w fsgldiv_may_ovfl
14335
14336 cmpi.l %d0,&0x3fff-0x0000 # will result underflow?
14337 beq.w fsgldiv_may_unfl # maybe
14338 bgt.w fsgldiv_unfl # yes; go handle underflow
14339
14340fsgldiv_normal:
14341 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14342
14343 fmov.l L_SCR3(%a6),%fpcr # save FPCR
14344 fmov.l &0x0,%fpsr # clear FPSR
14345
14346 fsgldiv.x FP_SCR0(%a6),%fp0 # perform sgl divide
14347
14348 fmov.l %fpsr,%d1 # save FPSR
14349 fmov.l &0x0,%fpcr # clear FPCR
14350
14351 or.l %d1,USER_FPSR(%a6) # save INEX2,N
14352
14353fsgldiv_normal_exit:
14354 fmovm.x &0x80,FP_SCR0(%a6) # store result on stack
14355 mov.l %d2,-(%sp) # save d2
14356 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
14357 mov.l %d1,%d2 # make a copy
14358 andi.l &0x7fff,%d1 # strip sign
14359 andi.w &0x8000,%d2 # keep old sign
14360 sub.l %d0,%d1 # add scale factor
14361 or.w %d2,%d1 # concat old sign,new exp
14362 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
14363 mov.l (%sp)+,%d2 # restore d2
14364 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
14365 rts
14366
14367fsgldiv_may_ovfl:
14368 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14369
14370 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14371 fmov.l &0x0,%fpsr # set FPSR
14372
14373 fsgldiv.x FP_SCR0(%a6),%fp0 # execute divide
14374
14375 fmov.l %fpsr,%d1
14376 fmov.l &0x0,%fpcr
14377
14378 or.l %d1,USER_FPSR(%a6) # save INEX,N
14379
14380 fmovm.x &0x01,-(%sp) # save result to stack
14381 mov.w (%sp),%d1 # fetch new exponent
14382 add.l &0xc,%sp # clear result
14383 andi.l &0x7fff,%d1 # strip sign
14384 sub.l %d0,%d1 # add scale factor
14385 cmp.l %d1,&0x7fff # did divide overflow?
14386 blt.b fsgldiv_normal_exit
14387
14388fsgldiv_ovfl_tst:
14389 or.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
14390
14391 mov.b FPCR_ENABLE(%a6),%d1
14392 andi.b &0x13,%d1 # is OVFL or INEX enabled?
14393 bne.b fsgldiv_ovfl_ena # yes
14394
14395fsgldiv_ovfl_dis:
14396 btst &neg_bit,FPSR_CC(%a6) # is result negative
14397 sne %d1 # set sign param accordingly
14398 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
14399 andi.b &0x30,%d0 # kill precision
14400 bsr.l ovf_res # calculate default result
14401 or.b %d0,FPSR_CC(%a6) # set INF if applicable
14402 fmovm.x (%a0),&0x80 # return default result in fp0
14403 rts
14404
14405fsgldiv_ovfl_ena:
14406 fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
14407
14408 mov.l %d2,-(%sp) # save d2
14409 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
14410 mov.l %d1,%d2 # make a copy
14411 andi.l &0x7fff,%d1 # strip sign
14412 andi.w &0x8000,%d2 # keep old sign
14413 sub.l %d0,%d1 # add scale factor
14414 subi.l &0x6000,%d1 # subtract new bias
14415 andi.w &0x7fff,%d1 # clear ms bit
14416 or.w %d2,%d1 # concat old sign,new exp
14417 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
14418 mov.l (%sp)+,%d2 # restore d2
14419 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
14420 bra.b fsgldiv_ovfl_dis
14421
14422fsgldiv_unfl:
14423 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
14424
14425 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14426
14427 fmov.l &rz_mode*0x10,%fpcr # set FPCR
14428 fmov.l &0x0,%fpsr # clear FPSR
14429
14430 fsgldiv.x FP_SCR0(%a6),%fp0 # execute sgl divide
14431
14432 fmov.l %fpsr,%d1 # save status
14433 fmov.l &0x0,%fpcr # clear FPCR
14434
14435 or.l %d1,USER_FPSR(%a6) # save INEX2,N
14436
14437 mov.b FPCR_ENABLE(%a6),%d1
14438 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
14439 bne.b fsgldiv_unfl_ena # yes
14440
14441fsgldiv_unfl_dis:
14442 fmovm.x &0x80,FP_SCR0(%a6) # store out result
14443
14444 lea FP_SCR0(%a6),%a0 # pass: result addr
14445 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
14446 bsr.l unf_res4 # calculate default result
14447 or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
14448 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
14449 rts
14450
14451#
14452# UNFL is enabled.
14453#
14454fsgldiv_unfl_ena:
14455 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
14456
14457 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14458 fmov.l &0x0,%fpsr # clear FPSR
14459
14460 fsgldiv.x FP_SCR0(%a6),%fp1 # execute sgl divide
14461
14462 fmov.l &0x0,%fpcr # clear FPCR
14463
14464 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
14465 mov.l %d2,-(%sp) # save d2
14466 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
14467 mov.l %d1,%d2 # make a copy
14468 andi.l &0x7fff,%d1 # strip sign
14469 andi.w &0x8000,%d2 # keep old sign
14470 sub.l %d0,%d1 # add scale factor
14471 addi.l &0x6000,%d1 # add bias
14472 andi.w &0x7fff,%d1 # clear top bit
14473 or.w %d2,%d1 # concat old sign, new exp
14474 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
14475 mov.l (%sp)+,%d2 # restore d2
14476 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
14477 bra.b fsgldiv_unfl_dis
14478
14479#
14480# the divide operation MAY underflow:
14481#
14482fsgldiv_may_unfl:
14483 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14484
14485 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14486 fmov.l &0x0,%fpsr # clear FPSR
14487
14488 fsgldiv.x FP_SCR0(%a6),%fp0 # execute sgl divide
14489
14490 fmov.l %fpsr,%d1 # save status
14491 fmov.l &0x0,%fpcr # clear FPCR
14492
14493 or.l %d1,USER_FPSR(%a6) # save INEX2,N
14494
14495 fabs.x %fp0,%fp1 # make a copy of result
14496 fcmp.b %fp1,&0x1 # is |result| > 1.b?
14497 fbgt.w fsgldiv_normal_exit # no; no underflow occurred
14498 fblt.w fsgldiv_unfl # yes; underflow occurred
14499
14500#
14501# we still don't know if underflow occurred. result is ~ equal to 1. but,
14502# we don't know if the result was an underflow that rounded up to a 1
14503# or a normalized number that rounded down to a 1. so, redo the entire
14504# operation using RZ as the rounding mode to see what the pre-rounded
14505# result is. this case should be relatively rare.
14506#
14507 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into %fp1
14508
14509 clr.l %d1 # clear scratch register
14510 ori.b &rz_mode*0x10,%d1 # force RZ rnd mode
14511
14512 fmov.l %d1,%fpcr # set FPCR
14513 fmov.l &0x0,%fpsr # clear FPSR
14514
14515 fsgldiv.x FP_SCR0(%a6),%fp1 # execute sgl divide
14516
14517 fmov.l &0x0,%fpcr # clear FPCR
14518 fabs.x %fp1 # make absolute value
14519 fcmp.b %fp1,&0x1 # is |result| < 1.b?
14520 fbge.w fsgldiv_normal_exit # no; no underflow occurred
14521 bra.w fsgldiv_unfl # yes; underflow occurred
14522
14523############################################################################
14524
14525#
14526# Divide: inputs are not both normalized; what are they?
14527#
14528fsgldiv_not_norm:
14529 mov.w (tbl_fsgldiv_op.b,%pc,%d1.w*2),%d1
14530 jmp (tbl_fsgldiv_op.b,%pc,%d1.w*1)
14531
14532 swbeg &48
14533tbl_fsgldiv_op:
14534 short fsgldiv_norm - tbl_fsgldiv_op # NORM / NORM
14535 short fsgldiv_inf_load - tbl_fsgldiv_op # NORM / ZERO
14536 short fsgldiv_zero_load - tbl_fsgldiv_op # NORM / INF
14537 short fsgldiv_res_qnan - tbl_fsgldiv_op # NORM / QNAN
14538 short fsgldiv_norm - tbl_fsgldiv_op # NORM / DENORM
14539 short fsgldiv_res_snan - tbl_fsgldiv_op # NORM / SNAN
14540 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14541 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14542
14543 short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / NORM
14544 short fsgldiv_res_operr - tbl_fsgldiv_op # ZERO / ZERO
14545 short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / INF
14546 short fsgldiv_res_qnan - tbl_fsgldiv_op # ZERO / QNAN
14547 short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / DENORM
14548 short fsgldiv_res_snan - tbl_fsgldiv_op # ZERO / SNAN
14549 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14550 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14551
14552 short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / NORM
14553 short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / ZERO
14554 short fsgldiv_res_operr - tbl_fsgldiv_op # INF / INF
14555 short fsgldiv_res_qnan - tbl_fsgldiv_op # INF / QNAN
14556 short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / DENORM
14557 short fsgldiv_res_snan - tbl_fsgldiv_op # INF / SNAN
14558 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14559 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14560
14561 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / NORM
14562 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / ZERO
14563 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / INF
14564 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / QNAN
14565 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / DENORM
14566 short fsgldiv_res_snan - tbl_fsgldiv_op # QNAN / SNAN
14567 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14568 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14569
14570 short fsgldiv_norm - tbl_fsgldiv_op # DENORM / NORM
14571 short fsgldiv_inf_load - tbl_fsgldiv_op # DENORM / ZERO
14572 short fsgldiv_zero_load - tbl_fsgldiv_op # DENORM / INF
14573 short fsgldiv_res_qnan - tbl_fsgldiv_op # DENORM / QNAN
14574 short fsgldiv_norm - tbl_fsgldiv_op # DENORM / DENORM
14575 short fsgldiv_res_snan - tbl_fsgldiv_op # DENORM / SNAN
14576 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14577 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14578
14579 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / NORM
14580 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / ZERO
14581 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / INF
14582 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / QNAN
14583 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / DENORM
14584 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / SNAN
14585 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14586 short tbl_fsgldiv_op - tbl_fsgldiv_op #
14587
14588fsgldiv_res_qnan:
14589 bra.l res_qnan
14590fsgldiv_res_snan:
14591 bra.l res_snan
14592fsgldiv_res_operr:
14593 bra.l res_operr
14594fsgldiv_inf_load:
14595 bra.l fdiv_inf_load
14596fsgldiv_zero_load:
14597 bra.l fdiv_zero_load
14598fsgldiv_inf_dst:
14599 bra.l fdiv_inf_dst
14600
14601#########################################################################
14602# XDEF **************************************************************** #
14603# fadd(): emulates the fadd instruction #
14604# fsadd(): emulates the fadd instruction #
14605# fdadd(): emulates the fdadd instruction #
14606# #
14607# XREF **************************************************************** #
14608# addsub_scaler2() - scale the operands so they won't take exc #
14609# ovf_res() - return default overflow result #
14610# unf_res() - return default underflow result #
14611# res_qnan() - set QNAN result #
14612# res_snan() - set SNAN result #
14613# res_operr() - set OPERR result #
14614# scale_to_zero_src() - set src operand exponent equal to zero #
14615# scale_to_zero_dst() - set dst operand exponent equal to zero #
14616# #
14617# INPUT *************************************************************** #
14618# a0 = pointer to extended precision source operand #
14619# a1 = pointer to extended precision destination operand #
14620# #
14621# OUTPUT ************************************************************** #
14622# fp0 = result #
14623# fp1 = EXOP (if exception occurred) #
14624# #
14625# ALGORITHM *********************************************************** #
14626# Handle NANs, infinities, and zeroes as special cases. Divide #
14627# norms into extended, single, and double precision. #
14628# Do addition after scaling exponents such that exception won't #
14629# occur. Then, check result exponent to see if exception would have #
14630# occurred. If so, return default result and maybe EXOP. Else, insert #
14631# the correct result exponent and return. Set FPSR bits as appropriate. #
14632# #
14633#########################################################################
14634
14635 global fsadd
14636fsadd:
14637 andi.b &0x30,%d0 # clear rnd prec
14638 ori.b &s_mode*0x10,%d0 # insert sgl prec
14639 bra.b fadd
14640
14641 global fdadd
14642fdadd:
14643 andi.b &0x30,%d0 # clear rnd prec
14644 ori.b &d_mode*0x10,%d0 # insert dbl prec
14645
14646 global fadd
14647fadd:
14648 mov.l %d0,L_SCR3(%a6) # store rnd info
14649
14650 clr.w %d1
14651 mov.b DTAG(%a6),%d1
14652 lsl.b &0x3,%d1
14653 or.b STAG(%a6),%d1 # combine src tags
14654
14655 bne.w fadd_not_norm # optimize on non-norm input
14656
14657#
14658# ADD: norms and denorms
14659#
14660fadd_norm:
14661 bsr.l addsub_scaler2 # scale exponents
14662
14663fadd_zero_entry:
14664 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14665
14666 fmov.l &0x0,%fpsr # clear FPSR
14667 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14668
14669 fadd.x FP_SCR0(%a6),%fp0 # execute add
14670
14671 fmov.l &0x0,%fpcr # clear FPCR
14672 fmov.l %fpsr,%d1 # fetch INEX2,N,Z
14673
14674 or.l %d1,USER_FPSR(%a6) # save exc and ccode bits
14675
14676 fbeq.w fadd_zero_exit # if result is zero, end now
14677
14678 mov.l %d2,-(%sp) # save d2
14679
14680 fmovm.x &0x01,-(%sp) # save result to stack
14681
14682 mov.w 2+L_SCR3(%a6),%d1
14683 lsr.b &0x6,%d1
14684
14685 mov.w (%sp),%d2 # fetch new sign, exp
14686 andi.l &0x7fff,%d2 # strip sign
14687 sub.l %d0,%d2 # add scale factor
14688
14689 cmp.l %d2,(tbl_fadd_ovfl.b,%pc,%d1.w*4) # is it an overflow?
14690 bge.b fadd_ovfl # yes
14691
14692 cmp.l %d2,(tbl_fadd_unfl.b,%pc,%d1.w*4) # is it an underflow?
14693 blt.w fadd_unfl # yes
14694 beq.w fadd_may_unfl # maybe; go find out
14695
14696fadd_normal:
14697 mov.w (%sp),%d1
14698 andi.w &0x8000,%d1 # keep sign
14699 or.w %d2,%d1 # concat sign,new exp
14700 mov.w %d1,(%sp) # insert new exponent
14701
14702 fmovm.x (%sp)+,&0x80 # return result in fp0
14703
14704 mov.l (%sp)+,%d2 # restore d2
14705 rts
14706
14707fadd_zero_exit:
14708# fmov.s &0x00000000,%fp0 # return zero in fp0
14709 rts
14710
14711tbl_fadd_ovfl:
14712 long 0x7fff # ext ovfl
14713 long 0x407f # sgl ovfl
14714 long 0x43ff # dbl ovfl
14715
14716tbl_fadd_unfl:
14717 long 0x0000 # ext unfl
14718 long 0x3f81 # sgl unfl
14719 long 0x3c01 # dbl unfl
14720
14721fadd_ovfl:
14722 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
14723
14724 mov.b FPCR_ENABLE(%a6),%d1
14725 andi.b &0x13,%d1 # is OVFL or INEX enabled?
14726 bne.b fadd_ovfl_ena # yes
14727
14728 add.l &0xc,%sp
14729fadd_ovfl_dis:
14730 btst &neg_bit,FPSR_CC(%a6) # is result negative?
14731 sne %d1 # set sign param accordingly
14732 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
14733 bsr.l ovf_res # calculate default result
14734 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
14735 fmovm.x (%a0),&0x80 # return default result in fp0
14736 mov.l (%sp)+,%d2 # restore d2
14737 rts
14738
14739fadd_ovfl_ena:
14740 mov.b L_SCR3(%a6),%d1
14741 andi.b &0xc0,%d1 # is precision extended?
14742 bne.b fadd_ovfl_ena_sd # no; prec = sgl or dbl
14743
14744fadd_ovfl_ena_cont:
14745 mov.w (%sp),%d1
14746 andi.w &0x8000,%d1 # keep sign
14747 subi.l &0x6000,%d2 # add extra bias
14748 andi.w &0x7fff,%d2
14749 or.w %d2,%d1 # concat sign,new exp
14750 mov.w %d1,(%sp) # insert new exponent
14751
14752 fmovm.x (%sp)+,&0x40 # return EXOP in fp1
14753 bra.b fadd_ovfl_dis
14754
14755fadd_ovfl_ena_sd:
14756 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14757
14758 mov.l L_SCR3(%a6),%d1
14759 andi.b &0x30,%d1 # keep rnd mode
14760 fmov.l %d1,%fpcr # set FPCR
14761
14762 fadd.x FP_SCR0(%a6),%fp0 # execute add
14763
14764 fmov.l &0x0,%fpcr # clear FPCR
14765
14766 add.l &0xc,%sp
14767 fmovm.x &0x01,-(%sp)
14768 bra.b fadd_ovfl_ena_cont
14769
14770fadd_unfl:
14771 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
14772
14773 add.l &0xc,%sp
14774
14775 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
14776
14777 fmov.l &rz_mode*0x10,%fpcr # set FPCR
14778 fmov.l &0x0,%fpsr # clear FPSR
14779
14780 fadd.x FP_SCR0(%a6),%fp0 # execute add
14781
14782 fmov.l &0x0,%fpcr # clear FPCR
14783 fmov.l %fpsr,%d1 # save status
14784
14785 or.l %d1,USER_FPSR(%a6) # save INEX,N
14786
14787 mov.b FPCR_ENABLE(%a6),%d1
14788 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
14789 bne.b fadd_unfl_ena # yes
14790
14791fadd_unfl_dis:
14792 fmovm.x &0x80,FP_SCR0(%a6) # store out result
14793
14794 lea FP_SCR0(%a6),%a0 # pass: result addr
14795 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
14796 bsr.l unf_res # calculate default result
14797 or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
14798 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
14799 mov.l (%sp)+,%d2 # restore d2
14800 rts
14801
14802fadd_unfl_ena:
14803 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
14804
14805 mov.l L_SCR3(%a6),%d1
14806 andi.b &0xc0,%d1 # is precision extended?
14807 bne.b fadd_unfl_ena_sd # no; sgl or dbl
14808
14809 fmov.l L_SCR3(%a6),%fpcr # set FPCR
14810
14811fadd_unfl_ena_cont:
14812 fmov.l &0x0,%fpsr # clear FPSR
14813
14814 fadd.x FP_SCR0(%a6),%fp1 # execute multiply
14815
14816 fmov.l &0x0,%fpcr # clear FPCR
14817
14818 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
14819 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
14820 mov.l %d1,%d2 # make a copy
14821 andi.l &0x7fff,%d1 # strip sign
14822 andi.w &0x8000,%d2 # keep old sign
14823 sub.l %d0,%d1 # add scale factor
14824 addi.l &0x6000,%d1 # add new bias
14825 andi.w &0x7fff,%d1 # clear top bit
14826 or.w %d2,%d1 # concat sign,new exp
14827 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
14828 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
14829 bra.w fadd_unfl_dis
14830
14831fadd_unfl_ena_sd:
14832 mov.l L_SCR3(%a6),%d1
14833 andi.b &0x30,%d1 # use only rnd mode
14834 fmov.l %d1,%fpcr # set FPCR
14835
14836 bra.b fadd_unfl_ena_cont
14837
14838#
14839# result is equal to the smallest normalized number in the selected precision
14840# if the precision is extended, this result could not have come from an
14841# underflow that rounded up.
14842#
14843fadd_may_unfl:
14844 mov.l L_SCR3(%a6),%d1
14845 andi.b &0xc0,%d1
14846 beq.w fadd_normal # yes; no underflow occurred
14847
14848 mov.l 0x4(%sp),%d1 # extract hi(man)
14849 cmpi.l %d1,&0x80000000 # is hi(man) = 0x80000000?
14850 bne.w fadd_normal # no; no underflow occurred
14851
14852 tst.l 0x8(%sp) # is lo(man) = 0x0?
14853 bne.w fadd_normal # no; no underflow occurred
14854
14855 btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
14856 beq.w fadd_normal # no; no underflow occurred
14857
14858#
14859# ok, so now the result has a exponent equal to the smallest normalized
14860# exponent for the selected precision. also, the mantissa is equal to
14861# 0x8000000000000000 and this mantissa is the result of rounding non-zero
14862# g,r,s.
14863# now, we must determine whether the pre-rounded result was an underflow
14864# rounded "up" or a normalized number rounded "down".
14865# so, we do this be re-executing the add using RZ as the rounding mode and
14866# seeing if the new result is smaller or equal to the current result.
14867#
14868 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
14869
14870 mov.l L_SCR3(%a6),%d1
14871 andi.b &0xc0,%d1 # keep rnd prec
14872 ori.b &rz_mode*0x10,%d1 # insert rnd mode
14873 fmov.l %d1,%fpcr # set FPCR
14874 fmov.l &0x0,%fpsr # clear FPSR
14875
14876 fadd.x FP_SCR0(%a6),%fp1 # execute add
14877
14878 fmov.l &0x0,%fpcr # clear FPCR
14879
14880 fabs.x %fp0 # compare absolute values
14881 fabs.x %fp1
14882 fcmp.x %fp0,%fp1 # is first result > second?
14883
14884 fbgt.w fadd_unfl # yes; it's an underflow
14885 bra.w fadd_normal # no; it's not an underflow
14886
14887##########################################################################
14888
14889#
14890# Add: inputs are not both normalized; what are they?
14891#
14892fadd_not_norm:
14893 mov.w (tbl_fadd_op.b,%pc,%d1.w*2),%d1
14894 jmp (tbl_fadd_op.b,%pc,%d1.w*1)
14895
14896 swbeg &48
14897tbl_fadd_op:
14898 short fadd_norm - tbl_fadd_op # NORM + NORM
14899 short fadd_zero_src - tbl_fadd_op # NORM + ZERO
14900 short fadd_inf_src - tbl_fadd_op # NORM + INF
14901 short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
14902 short fadd_norm - tbl_fadd_op # NORM + DENORM
14903 short fadd_res_snan - tbl_fadd_op # NORM + SNAN
14904 short tbl_fadd_op - tbl_fadd_op #
14905 short tbl_fadd_op - tbl_fadd_op #
14906
14907 short fadd_zero_dst - tbl_fadd_op # ZERO + NORM
14908 short fadd_zero_2 - tbl_fadd_op # ZERO + ZERO
14909 short fadd_inf_src - tbl_fadd_op # ZERO + INF
14910 short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
14911 short fadd_zero_dst - tbl_fadd_op # ZERO + DENORM
14912 short fadd_res_snan - tbl_fadd_op # NORM + SNAN
14913 short tbl_fadd_op - tbl_fadd_op #
14914 short tbl_fadd_op - tbl_fadd_op #
14915
14916 short fadd_inf_dst - tbl_fadd_op # INF + NORM
14917 short fadd_inf_dst - tbl_fadd_op # INF + ZERO
14918 short fadd_inf_2 - tbl_fadd_op # INF + INF
14919 short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
14920 short fadd_inf_dst - tbl_fadd_op # INF + DENORM
14921 short fadd_res_snan - tbl_fadd_op # NORM + SNAN
14922 short tbl_fadd_op - tbl_fadd_op #
14923 short tbl_fadd_op - tbl_fadd_op #
14924
14925 short fadd_res_qnan - tbl_fadd_op # QNAN + NORM
14926 short fadd_res_qnan - tbl_fadd_op # QNAN + ZERO
14927 short fadd_res_qnan - tbl_fadd_op # QNAN + INF
14928 short fadd_res_qnan - tbl_fadd_op # QNAN + QNAN
14929 short fadd_res_qnan - tbl_fadd_op # QNAN + DENORM
14930 short fadd_res_snan - tbl_fadd_op # QNAN + SNAN
14931 short tbl_fadd_op - tbl_fadd_op #
14932 short tbl_fadd_op - tbl_fadd_op #
14933
14934 short fadd_norm - tbl_fadd_op # DENORM + NORM
14935 short fadd_zero_src - tbl_fadd_op # DENORM + ZERO
14936 short fadd_inf_src - tbl_fadd_op # DENORM + INF
14937 short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
14938 short fadd_norm - tbl_fadd_op # DENORM + DENORM
14939 short fadd_res_snan - tbl_fadd_op # NORM + SNAN
14940 short tbl_fadd_op - tbl_fadd_op #
14941 short tbl_fadd_op - tbl_fadd_op #
14942
14943 short fadd_res_snan - tbl_fadd_op # SNAN + NORM
14944 short fadd_res_snan - tbl_fadd_op # SNAN + ZERO
14945 short fadd_res_snan - tbl_fadd_op # SNAN + INF
14946 short fadd_res_snan - tbl_fadd_op # SNAN + QNAN
14947 short fadd_res_snan - tbl_fadd_op # SNAN + DENORM
14948 short fadd_res_snan - tbl_fadd_op # SNAN + SNAN
14949 short tbl_fadd_op - tbl_fadd_op #
14950 short tbl_fadd_op - tbl_fadd_op #
14951
14952fadd_res_qnan:
14953 bra.l res_qnan
14954fadd_res_snan:
14955 bra.l res_snan
14956
14957#
14958# both operands are ZEROes
14959#
14960fadd_zero_2:
14961 mov.b SRC_EX(%a0),%d0 # are the signs opposite
14962 mov.b DST_EX(%a1),%d1
14963 eor.b %d0,%d1
14964 bmi.w fadd_zero_2_chk_rm # weed out (-ZERO)+(+ZERO)
14965
14966# the signs are the same. so determine whether they are positive or negative
14967# and return the appropriately signed zero.
14968 tst.b %d0 # are ZEROes positive or negative?
14969 bmi.b fadd_zero_rm # negative
14970 fmov.s &0x00000000,%fp0 # return +ZERO
14971 mov.b &z_bmask,FPSR_CC(%a6) # set Z
14972 rts
14973
14974#
14975# the ZEROes have opposite signs:
14976# - therefore, we return +ZERO if the rounding modes are RN,RZ, or RP.
14977# - -ZERO is returned in the case of RM.
14978#
14979fadd_zero_2_chk_rm:
14980 mov.b 3+L_SCR3(%a6),%d1
14981 andi.b &0x30,%d1 # extract rnd mode
14982 cmpi.b %d1,&rm_mode*0x10 # is rnd mode == RM?
14983 beq.b fadd_zero_rm # yes
14984 fmov.s &0x00000000,%fp0 # return +ZERO
14985 mov.b &z_bmask,FPSR_CC(%a6) # set Z
14986 rts
14987
14988fadd_zero_rm:
14989 fmov.s &0x80000000,%fp0 # return -ZERO
14990 mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set NEG/Z
14991 rts
14992
14993#
14994# one operand is a ZERO and the other is a DENORM or NORM. scale
14995# the DENORM or NORM and jump to the regular fadd routine.
14996#
14997fadd_zero_dst:
14998 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
14999 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
15000 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
15001 bsr.l scale_to_zero_src # scale the operand
15002 clr.w FP_SCR1_EX(%a6)
15003 clr.l FP_SCR1_HI(%a6)
15004 clr.l FP_SCR1_LO(%a6)
15005 bra.w fadd_zero_entry # go execute fadd
15006
15007fadd_zero_src:
15008 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
15009 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
15010 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
15011 bsr.l scale_to_zero_dst # scale the operand
15012 clr.w FP_SCR0_EX(%a6)
15013 clr.l FP_SCR0_HI(%a6)
15014 clr.l FP_SCR0_LO(%a6)
15015 bra.w fadd_zero_entry # go execute fadd
15016
15017#
15018# both operands are INFs. an OPERR will result if the INFs have
15019# different signs. else, an INF of the same sign is returned
15020#
15021fadd_inf_2:
15022 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
15023 mov.b DST_EX(%a1),%d1
15024 eor.b %d1,%d0
15025 bmi.l res_operr # weed out (-INF)+(+INF)
15026
15027# ok, so it's not an OPERR. but, we do have to remember to return the
15028# src INF since that's where the 881/882 gets the j-bit from...
15029
15030#
15031# operands are INF and one of {ZERO, INF, DENORM, NORM}
15032#
15033fadd_inf_src:
15034 fmovm.x SRC(%a0),&0x80 # return src INF
15035 tst.b SRC_EX(%a0) # is INF positive?
15036 bpl.b fadd_inf_done # yes; we're done
15037 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
15038 rts
15039
15040#
15041# operands are INF and one of {ZERO, INF, DENORM, NORM}
15042#
15043fadd_inf_dst:
15044 fmovm.x DST(%a1),&0x80 # return dst INF
15045 tst.b DST_EX(%a1) # is INF positive?
15046 bpl.b fadd_inf_done # yes; we're done
15047 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
15048 rts
15049
15050fadd_inf_done:
15051 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
15052 rts
15053
15054#########################################################################
15055# XDEF **************************************************************** #
15056# fsub(): emulates the fsub instruction #
15057# fssub(): emulates the fssub instruction #
15058# fdsub(): emulates the fdsub instruction #
15059# #
15060# XREF **************************************************************** #
15061# addsub_scaler2() - scale the operands so they won't take exc #
15062# ovf_res() - return default overflow result #
15063# unf_res() - return default underflow result #
15064# res_qnan() - set QNAN result #
15065# res_snan() - set SNAN result #
15066# res_operr() - set OPERR result #
15067# scale_to_zero_src() - set src operand exponent equal to zero #
15068# scale_to_zero_dst() - set dst operand exponent equal to zero #
15069# #
15070# INPUT *************************************************************** #
15071# a0 = pointer to extended precision source operand #
15072# a1 = pointer to extended precision destination operand #
15073# #
15074# OUTPUT ************************************************************** #
15075# fp0 = result #
15076# fp1 = EXOP (if exception occurred) #
15077# #
15078# ALGORITHM *********************************************************** #
15079# Handle NANs, infinities, and zeroes as special cases. Divide #
15080# norms into extended, single, and double precision. #
15081# Do subtraction after scaling exponents such that exception won't#
15082# occur. Then, check result exponent to see if exception would have #
15083# occurred. If so, return default result and maybe EXOP. Else, insert #
15084# the correct result exponent and return. Set FPSR bits as appropriate. #
15085# #
15086#########################################################################
15087
15088 global fssub
15089fssub:
15090 andi.b &0x30,%d0 # clear rnd prec
15091 ori.b &s_mode*0x10,%d0 # insert sgl prec
15092 bra.b fsub
15093
15094 global fdsub
15095fdsub:
15096 andi.b &0x30,%d0 # clear rnd prec
15097 ori.b &d_mode*0x10,%d0 # insert dbl prec
15098
15099 global fsub
15100fsub:
15101 mov.l %d0,L_SCR3(%a6) # store rnd info
15102
15103 clr.w %d1
15104 mov.b DTAG(%a6),%d1
15105 lsl.b &0x3,%d1
15106 or.b STAG(%a6),%d1 # combine src tags
15107
15108 bne.w fsub_not_norm # optimize on non-norm input
15109
15110#
15111# SUB: norms and denorms
15112#
15113fsub_norm:
15114 bsr.l addsub_scaler2 # scale exponents
15115
15116fsub_zero_entry:
15117 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
15118
15119 fmov.l &0x0,%fpsr # clear FPSR
15120 fmov.l L_SCR3(%a6),%fpcr # set FPCR
15121
15122 fsub.x FP_SCR0(%a6),%fp0 # execute subtract
15123
15124 fmov.l &0x0,%fpcr # clear FPCR
15125 fmov.l %fpsr,%d1 # fetch INEX2, N, Z
15126
15127 or.l %d1,USER_FPSR(%a6) # save exc and ccode bits
15128
15129 fbeq.w fsub_zero_exit # if result zero, end now
15130
15131 mov.l %d2,-(%sp) # save d2
15132
15133 fmovm.x &0x01,-(%sp) # save result to stack
15134
15135 mov.w 2+L_SCR3(%a6),%d1
15136 lsr.b &0x6,%d1
15137
15138 mov.w (%sp),%d2 # fetch new exponent
15139 andi.l &0x7fff,%d2 # strip sign
15140 sub.l %d0,%d2 # add scale factor
15141
15142 cmp.l %d2,(tbl_fsub_ovfl.b,%pc,%d1.w*4) # is it an overflow?
15143 bge.b fsub_ovfl # yes
15144
15145 cmp.l %d2,(tbl_fsub_unfl.b,%pc,%d1.w*4) # is it an underflow?
15146 blt.w fsub_unfl # yes
15147 beq.w fsub_may_unfl # maybe; go find out
15148
15149fsub_normal:
15150 mov.w (%sp),%d1
15151 andi.w &0x8000,%d1 # keep sign
15152 or.w %d2,%d1 # insert new exponent
15153 mov.w %d1,(%sp) # insert new exponent
15154
15155 fmovm.x (%sp)+,&0x80 # return result in fp0
15156
15157 mov.l (%sp)+,%d2 # restore d2
15158 rts
15159
15160fsub_zero_exit:
15161# fmov.s &0x00000000,%fp0 # return zero in fp0
15162 rts
15163
15164tbl_fsub_ovfl:
15165 long 0x7fff # ext ovfl
15166 long 0x407f # sgl ovfl
15167 long 0x43ff # dbl ovfl
15168
15169tbl_fsub_unfl:
15170 long 0x0000 # ext unfl
15171 long 0x3f81 # sgl unfl
15172 long 0x3c01 # dbl unfl
15173
15174fsub_ovfl:
15175 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
15176
15177 mov.b FPCR_ENABLE(%a6),%d1
15178 andi.b &0x13,%d1 # is OVFL or INEX enabled?
15179 bne.b fsub_ovfl_ena # yes
15180
15181 add.l &0xc,%sp
15182fsub_ovfl_dis:
15183 btst &neg_bit,FPSR_CC(%a6) # is result negative?
15184 sne %d1 # set sign param accordingly
15185 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
15186 bsr.l ovf_res # calculate default result
15187 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
15188 fmovm.x (%a0),&0x80 # return default result in fp0
15189 mov.l (%sp)+,%d2 # restore d2
15190 rts
15191
15192fsub_ovfl_ena:
15193 mov.b L_SCR3(%a6),%d1
15194 andi.b &0xc0,%d1 # is precision extended?
15195 bne.b fsub_ovfl_ena_sd # no
15196
15197fsub_ovfl_ena_cont:
15198 mov.w (%sp),%d1 # fetch {sgn,exp}
15199 andi.w &0x8000,%d1 # keep sign
15200 subi.l &0x6000,%d2 # subtract new bias
15201 andi.w &0x7fff,%d2 # clear top bit
15202 or.w %d2,%d1 # concat sign,exp
15203 mov.w %d1,(%sp) # insert new exponent
15204
15205 fmovm.x (%sp)+,&0x40 # return EXOP in fp1
15206 bra.b fsub_ovfl_dis
15207
15208fsub_ovfl_ena_sd:
15209 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
15210
15211 mov.l L_SCR3(%a6),%d1
15212 andi.b &0x30,%d1 # clear rnd prec
15213 fmov.l %d1,%fpcr # set FPCR
15214
15215 fsub.x FP_SCR0(%a6),%fp0 # execute subtract
15216
15217 fmov.l &0x0,%fpcr # clear FPCR
15218
15219 add.l &0xc,%sp
15220 fmovm.x &0x01,-(%sp)
15221 bra.b fsub_ovfl_ena_cont
15222
15223fsub_unfl:
15224 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
15225
15226 add.l &0xc,%sp
15227
15228 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
15229
15230 fmov.l &rz_mode*0x10,%fpcr # set FPCR
15231 fmov.l &0x0,%fpsr # clear FPSR
15232
15233 fsub.x FP_SCR0(%a6),%fp0 # execute subtract
15234
15235 fmov.l &0x0,%fpcr # clear FPCR
15236 fmov.l %fpsr,%d1 # save status
15237
15238 or.l %d1,USER_FPSR(%a6)
15239
15240 mov.b FPCR_ENABLE(%a6),%d1
15241 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
15242 bne.b fsub_unfl_ena # yes
15243
15244fsub_unfl_dis:
15245 fmovm.x &0x80,FP_SCR0(%a6) # store out result
15246
15247 lea FP_SCR0(%a6),%a0 # pass: result addr
15248 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
15249 bsr.l unf_res # calculate default result
15250 or.b %d0,FPSR_CC(%a6) # 'Z' may have been set
15251 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
15252 mov.l (%sp)+,%d2 # restore d2
15253 rts
15254
15255fsub_unfl_ena:
15256 fmovm.x FP_SCR1(%a6),&0x40
15257
15258 mov.l L_SCR3(%a6),%d1
15259 andi.b &0xc0,%d1 # is precision extended?
15260 bne.b fsub_unfl_ena_sd # no
15261
15262 fmov.l L_SCR3(%a6),%fpcr # set FPCR
15263
15264fsub_unfl_ena_cont:
15265 fmov.l &0x0,%fpsr # clear FPSR
15266
15267 fsub.x FP_SCR0(%a6),%fp1 # execute subtract
15268
15269 fmov.l &0x0,%fpcr # clear FPCR
15270
15271 fmovm.x &0x40,FP_SCR0(%a6) # store result to stack
15272 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
15273 mov.l %d1,%d2 # make a copy
15274 andi.l &0x7fff,%d1 # strip sign
15275 andi.w &0x8000,%d2 # keep old sign
15276 sub.l %d0,%d1 # add scale factor
15277 addi.l &0x6000,%d1 # subtract new bias
15278 andi.w &0x7fff,%d1 # clear top bit
15279 or.w %d2,%d1 # concat sgn,exp
15280 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
15281 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
15282 bra.w fsub_unfl_dis
15283
15284fsub_unfl_ena_sd:
15285 mov.l L_SCR3(%a6),%d1
15286 andi.b &0x30,%d1 # clear rnd prec
15287 fmov.l %d1,%fpcr # set FPCR
15288
15289 bra.b fsub_unfl_ena_cont
15290
15291#
15292# result is equal to the smallest normalized number in the selected precision
15293# if the precision is extended, this result could not have come from an
15294# underflow that rounded up.
15295#
15296fsub_may_unfl:
15297 mov.l L_SCR3(%a6),%d1
15298 andi.b &0xc0,%d1 # fetch rnd prec
15299 beq.w fsub_normal # yes; no underflow occurred
15300
15301 mov.l 0x4(%sp),%d1
15302 cmpi.l %d1,&0x80000000 # is hi(man) = 0x80000000?
15303 bne.w fsub_normal # no; no underflow occurred
15304
15305 tst.l 0x8(%sp) # is lo(man) = 0x0?
15306 bne.w fsub_normal # no; no underflow occurred
15307
15308 btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
15309 beq.w fsub_normal # no; no underflow occurred
15310
15311#
15312# ok, so now the result has a exponent equal to the smallest normalized
15313# exponent for the selected precision. also, the mantissa is equal to
15314# 0x8000000000000000 and this mantissa is the result of rounding non-zero
15315# g,r,s.
15316# now, we must determine whether the pre-rounded result was an underflow
15317# rounded "up" or a normalized number rounded "down".
15318# so, we do this be re-executing the add using RZ as the rounding mode and
15319# seeing if the new result is smaller or equal to the current result.
15320#
15321 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
15322
15323 mov.l L_SCR3(%a6),%d1
15324 andi.b &0xc0,%d1 # keep rnd prec
15325 ori.b &rz_mode*0x10,%d1 # insert rnd mode
15326 fmov.l %d1,%fpcr # set FPCR
15327 fmov.l &0x0,%fpsr # clear FPSR
15328
15329 fsub.x FP_SCR0(%a6),%fp1 # execute subtract
15330
15331 fmov.l &0x0,%fpcr # clear FPCR
15332
15333 fabs.x %fp0 # compare absolute values
15334 fabs.x %fp1
15335 fcmp.x %fp0,%fp1 # is first result > second?
15336
15337 fbgt.w fsub_unfl # yes; it's an underflow
15338 bra.w fsub_normal # no; it's not an underflow
15339
15340##########################################################################
15341
15342#
15343# Sub: inputs are not both normalized; what are they?
15344#
15345fsub_not_norm:
15346 mov.w (tbl_fsub_op.b,%pc,%d1.w*2),%d1
15347 jmp (tbl_fsub_op.b,%pc,%d1.w*1)
15348
15349 swbeg &48
15350tbl_fsub_op:
15351 short fsub_norm - tbl_fsub_op # NORM - NORM
15352 short fsub_zero_src - tbl_fsub_op # NORM - ZERO
15353 short fsub_inf_src - tbl_fsub_op # NORM - INF
15354 short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
15355 short fsub_norm - tbl_fsub_op # NORM - DENORM
15356 short fsub_res_snan - tbl_fsub_op # NORM - SNAN
15357 short tbl_fsub_op - tbl_fsub_op #
15358 short tbl_fsub_op - tbl_fsub_op #
15359
15360 short fsub_zero_dst - tbl_fsub_op # ZERO - NORM
15361 short fsub_zero_2 - tbl_fsub_op # ZERO - ZERO
15362 short fsub_inf_src - tbl_fsub_op # ZERO - INF
15363 short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
15364 short fsub_zero_dst - tbl_fsub_op # ZERO - DENORM
15365 short fsub_res_snan - tbl_fsub_op # NORM - SNAN
15366 short tbl_fsub_op - tbl_fsub_op #
15367 short tbl_fsub_op - tbl_fsub_op #
15368
15369 short fsub_inf_dst - tbl_fsub_op # INF - NORM
15370 short fsub_inf_dst - tbl_fsub_op # INF - ZERO
15371 short fsub_inf_2 - tbl_fsub_op # INF - INF
15372 short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
15373 short fsub_inf_dst - tbl_fsub_op # INF - DENORM
15374 short fsub_res_snan - tbl_fsub_op # NORM - SNAN
15375 short tbl_fsub_op - tbl_fsub_op #
15376 short tbl_fsub_op - tbl_fsub_op #
15377
15378 short fsub_res_qnan - tbl_fsub_op # QNAN - NORM
15379 short fsub_res_qnan - tbl_fsub_op # QNAN - ZERO
15380 short fsub_res_qnan - tbl_fsub_op # QNAN - INF
15381 short fsub_res_qnan - tbl_fsub_op # QNAN - QNAN
15382 short fsub_res_qnan - tbl_fsub_op # QNAN - DENORM
15383 short fsub_res_snan - tbl_fsub_op # QNAN - SNAN
15384 short tbl_fsub_op - tbl_fsub_op #
15385 short tbl_fsub_op - tbl_fsub_op #
15386
15387 short fsub_norm - tbl_fsub_op # DENORM - NORM
15388 short fsub_zero_src - tbl_fsub_op # DENORM - ZERO
15389 short fsub_inf_src - tbl_fsub_op # DENORM - INF
15390 short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
15391 short fsub_norm - tbl_fsub_op # DENORM - DENORM
15392 short fsub_res_snan - tbl_fsub_op # NORM - SNAN
15393 short tbl_fsub_op - tbl_fsub_op #
15394 short tbl_fsub_op - tbl_fsub_op #
15395
15396 short fsub_res_snan - tbl_fsub_op # SNAN - NORM
15397 short fsub_res_snan - tbl_fsub_op # SNAN - ZERO
15398 short fsub_res_snan - tbl_fsub_op # SNAN - INF
15399 short fsub_res_snan - tbl_fsub_op # SNAN - QNAN
15400 short fsub_res_snan - tbl_fsub_op # SNAN - DENORM
15401 short fsub_res_snan - tbl_fsub_op # SNAN - SNAN
15402 short tbl_fsub_op - tbl_fsub_op #
15403 short tbl_fsub_op - tbl_fsub_op #
15404
15405fsub_res_qnan:
15406 bra.l res_qnan
15407fsub_res_snan:
15408 bra.l res_snan
15409
15410#
15411# both operands are ZEROes
15412#
15413fsub_zero_2:
15414 mov.b SRC_EX(%a0),%d0
15415 mov.b DST_EX(%a1),%d1
15416 eor.b %d1,%d0
15417 bpl.b fsub_zero_2_chk_rm
15418
15419# the signs are opposite, so, return a ZERO w/ the sign of the dst ZERO
15420 tst.b %d0 # is dst negative?
15421 bmi.b fsub_zero_2_rm # yes
15422 fmov.s &0x00000000,%fp0 # no; return +ZERO
15423 mov.b &z_bmask,FPSR_CC(%a6) # set Z
15424 rts
15425
15426#
15427# the ZEROes have the same signs:
15428# - therefore, we return +ZERO if the rounding mode is RN,RZ, or RP
15429# - -ZERO is returned in the case of RM.
15430#
15431fsub_zero_2_chk_rm:
15432 mov.b 3+L_SCR3(%a6),%d1
15433 andi.b &0x30,%d1 # extract rnd mode
15434 cmpi.b %d1,&rm_mode*0x10 # is rnd mode = RM?
15435 beq.b fsub_zero_2_rm # yes
15436 fmov.s &0x00000000,%fp0 # no; return +ZERO
15437 mov.b &z_bmask,FPSR_CC(%a6) # set Z
15438 rts
15439
15440fsub_zero_2_rm:
15441 fmov.s &0x80000000,%fp0 # return -ZERO
15442 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/NEG
15443 rts
15444
15445#
15446# one operand is a ZERO and the other is a DENORM or a NORM.
15447# scale the DENORM or NORM and jump to the regular fsub routine.
15448#
15449fsub_zero_dst:
15450 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
15451 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
15452 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
15453 bsr.l scale_to_zero_src # scale the operand
15454 clr.w FP_SCR1_EX(%a6)
15455 clr.l FP_SCR1_HI(%a6)
15456 clr.l FP_SCR1_LO(%a6)
15457 bra.w fsub_zero_entry # go execute fsub
15458
15459fsub_zero_src:
15460 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
15461 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
15462 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
15463 bsr.l scale_to_zero_dst # scale the operand
15464 clr.w FP_SCR0_EX(%a6)
15465 clr.l FP_SCR0_HI(%a6)
15466 clr.l FP_SCR0_LO(%a6)
15467 bra.w fsub_zero_entry # go execute fsub
15468
15469#
15470# both operands are INFs. an OPERR will result if the INFs have the
15471# same signs. else,
15472#
15473fsub_inf_2:
15474 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
15475 mov.b DST_EX(%a1),%d1
15476 eor.b %d1,%d0
15477 bpl.l res_operr # weed out (-INF)+(+INF)
15478
15479# ok, so it's not an OPERR. but we do have to remember to return
15480# the src INF since that's where the 881/882 gets the j-bit.
15481
15482fsub_inf_src:
15483 fmovm.x SRC(%a0),&0x80 # return src INF
15484 fneg.x %fp0 # invert sign
15485 fbge.w fsub_inf_done # sign is now positive
15486 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
15487 rts
15488
15489fsub_inf_dst:
15490 fmovm.x DST(%a1),&0x80 # return dst INF
15491 tst.b DST_EX(%a1) # is INF negative?
15492 bpl.b fsub_inf_done # no
15493 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
15494 rts
15495
15496fsub_inf_done:
15497 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
15498 rts
15499
15500#########################################################################
15501# XDEF **************************************************************** #
15502# fsqrt(): emulates the fsqrt instruction #
15503# fssqrt(): emulates the fssqrt instruction #
15504# fdsqrt(): emulates the fdsqrt instruction #
15505# #
15506# XREF **************************************************************** #
15507# scale_sqrt() - scale the source operand #
15508# unf_res() - return default underflow result #
15509# ovf_res() - return default overflow result #
15510# res_qnan_1op() - return QNAN result #
15511# res_snan_1op() - return SNAN result #
15512# #
15513# INPUT *************************************************************** #
15514# a0 = pointer to extended precision source operand #
15515# d0 rnd prec,mode #
15516# #
15517# OUTPUT ************************************************************** #
15518# fp0 = result #
15519# fp1 = EXOP (if exception occurred) #
15520# #
15521# ALGORITHM *********************************************************** #
15522# Handle NANs, infinities, and zeroes as special cases. Divide #
15523# norms/denorms into ext/sgl/dbl precision. #
15524# For norms/denorms, scale the exponents such that a sqrt #
15525# instruction won't cause an exception. Use the regular fsqrt to #
15526# compute a result. Check if the regular operands would have taken #
15527# an exception. If so, return the default overflow/underflow result #
15528# and return the EXOP if exceptions are enabled. Else, scale the #
15529# result operand to the proper exponent. #
15530# #
15531#########################################################################
15532
15533 global fssqrt
15534fssqrt:
15535 andi.b &0x30,%d0 # clear rnd prec
15536 ori.b &s_mode*0x10,%d0 # insert sgl precision
15537 bra.b fsqrt
15538
15539 global fdsqrt
15540fdsqrt:
15541 andi.b &0x30,%d0 # clear rnd prec
15542 ori.b &d_mode*0x10,%d0 # insert dbl precision
15543
15544 global fsqrt
15545fsqrt:
15546 mov.l %d0,L_SCR3(%a6) # store rnd info
15547 clr.w %d1
15548 mov.b STAG(%a6),%d1
15549 bne.w fsqrt_not_norm # optimize on non-norm input
15550
15551#
15552# SQUARE ROOT: norms and denorms ONLY!
15553#
15554fsqrt_norm:
15555 tst.b SRC_EX(%a0) # is operand negative?
15556 bmi.l res_operr # yes
15557
15558 andi.b &0xc0,%d0 # is precision extended?
15559 bne.b fsqrt_not_ext # no; go handle sgl or dbl
15560
15561 fmov.l L_SCR3(%a6),%fpcr # set FPCR
15562 fmov.l &0x0,%fpsr # clear FPSR
15563
15564 fsqrt.x (%a0),%fp0 # execute square root
15565
15566 fmov.l %fpsr,%d1
15567 or.l %d1,USER_FPSR(%a6) # set N,INEX
15568
15569 rts
15570
15571fsqrt_denorm:
15572 tst.b SRC_EX(%a0) # is operand negative?
15573 bmi.l res_operr # yes
15574
15575 andi.b &0xc0,%d0 # is precision extended?
15576 bne.b fsqrt_not_ext # no; go handle sgl or dbl
15577
15578 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
15579 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
15580 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
15581
15582 bsr.l scale_sqrt # calculate scale factor
15583
15584 bra.w fsqrt_sd_normal
15585
15586#
15587# operand is either single or double
15588#
15589fsqrt_not_ext:
15590 cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
15591 bne.w fsqrt_dbl
15592
15593#
15594# operand is to be rounded to single precision
15595#
15596fsqrt_sgl:
15597 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
15598 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
15599 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
15600
15601 bsr.l scale_sqrt # calculate scale factor
15602
15603 cmpi.l %d0,&0x3fff-0x3f81 # will move in underflow?
15604 beq.w fsqrt_sd_may_unfl
15605 bgt.w fsqrt_sd_unfl # yes; go handle underflow
15606 cmpi.l %d0,&0x3fff-0x407f # will move in overflow?
15607 beq.w fsqrt_sd_may_ovfl # maybe; go check
15608 blt.w fsqrt_sd_ovfl # yes; go handle overflow
15609
15610#
15611# operand will NOT overflow or underflow when moved in to the fp reg file
15612#
15613fsqrt_sd_normal:
15614 fmov.l &0x0,%fpsr # clear FPSR
15615 fmov.l L_SCR3(%a6),%fpcr # set FPCR
15616
15617 fsqrt.x FP_SCR0(%a6),%fp0 # perform absolute
15618
15619 fmov.l %fpsr,%d1 # save FPSR
15620 fmov.l &0x0,%fpcr # clear FPCR
15621
15622 or.l %d1,USER_FPSR(%a6) # save INEX2,N
15623
15624fsqrt_sd_normal_exit:
15625 mov.l %d2,-(%sp) # save d2
15626 fmovm.x &0x80,FP_SCR0(%a6) # store out result
15627 mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
15628 mov.l %d1,%d2 # make a copy
15629 andi.l &0x7fff,%d1 # strip sign
15630 sub.l %d0,%d1 # add scale factor
15631 andi.w &0x8000,%d2 # keep old sign
15632 or.w %d1,%d2 # concat old sign,new exp
15633 mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
15634 mov.l (%sp)+,%d2 # restore d2
15635 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
15636 rts
15637
15638#
15639# operand is to be rounded to double precision
15640#
15641fsqrt_dbl:
15642 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
15643 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
15644 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
15645
15646 bsr.l scale_sqrt # calculate scale factor
15647
15648 cmpi.l %d0,&0x3fff-0x3c01 # will move in underflow?
15649 beq.w fsqrt_sd_may_unfl
15650 bgt.b fsqrt_sd_unfl # yes; go handle underflow
15651 cmpi.l %d0,&0x3fff-0x43ff # will move in overflow?
15652 beq.w fsqrt_sd_may_ovfl # maybe; go check
15653 blt.w fsqrt_sd_ovfl # yes; go handle overflow
15654 bra.w fsqrt_sd_normal # no; ho handle normalized op
15655
15656# we're on the line here and the distinguising characteristic is whether
15657# the exponent is 3fff or 3ffe. if it's 3ffe, then it's a safe number
15658# elsewise fall through to underflow.
15659fsqrt_sd_may_unfl:
15660 btst &0x0,1+FP_SCR0_EX(%a6) # is exponent 0x3fff?
15661 bne.w fsqrt_sd_normal # yes, so no underflow
15662
15663#
15664# operand WILL underflow when moved in to the fp register file
15665#
15666fsqrt_sd_unfl:
15667 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
15668
15669 fmov.l &rz_mode*0x10,%fpcr # set FPCR
15670 fmov.l &0x0,%fpsr # clear FPSR
15671
15672 fsqrt.x FP_SCR0(%a6),%fp0 # execute square root
15673
15674 fmov.l %fpsr,%d1 # save status
15675 fmov.l &0x0,%fpcr # clear FPCR
15676
15677 or.l %d1,USER_FPSR(%a6) # save INEX2,N
15678
15679# if underflow or inexact is enabled, go calculate EXOP first.
15680 mov.b FPCR_ENABLE(%a6),%d1
15681 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
15682 bne.b fsqrt_sd_unfl_ena # yes
15683
15684fsqrt_sd_unfl_dis:
15685 fmovm.x &0x80,FP_SCR0(%a6) # store out result
15686
15687 lea FP_SCR0(%a6),%a0 # pass: result addr
15688 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
15689 bsr.l unf_res # calculate default result
15690 or.b %d0,FPSR_CC(%a6) # set possible 'Z' ccode
15691 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
15692 rts
15693
15694#
15695# operand will underflow AND underflow is enabled.
15696# therefore, we must return the result rounded to extended precision.
15697#
15698fsqrt_sd_unfl_ena:
15699 mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
15700 mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
15701 mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
15702
15703 mov.l %d2,-(%sp) # save d2
15704 mov.l %d1,%d2 # make a copy
15705 andi.l &0x7fff,%d1 # strip sign
15706 andi.w &0x8000,%d2 # keep old sign
15707 sub.l %d0,%d1 # subtract scale factor
15708 addi.l &0x6000,%d1 # add new bias
15709 andi.w &0x7fff,%d1
15710 or.w %d2,%d1 # concat new sign,new exp
15711 mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
15712 fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
15713 mov.l (%sp)+,%d2 # restore d2
15714 bra.b fsqrt_sd_unfl_dis
15715
15716#
15717# operand WILL overflow.
15718#
15719fsqrt_sd_ovfl:
15720 fmov.l &0x0,%fpsr # clear FPSR
15721 fmov.l L_SCR3(%a6),%fpcr # set FPCR
15722
15723 fsqrt.x FP_SCR0(%a6),%fp0 # perform square root
15724
15725 fmov.l &0x0,%fpcr # clear FPCR
15726 fmov.l %fpsr,%d1 # save FPSR
15727
15728 or.l %d1,USER_FPSR(%a6) # save INEX2,N
15729
15730fsqrt_sd_ovfl_tst:
15731 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
15732
15733 mov.b FPCR_ENABLE(%a6),%d1
15734 andi.b &0x13,%d1 # is OVFL or INEX enabled?
15735 bne.b fsqrt_sd_ovfl_ena # yes
15736
15737#
15738# OVFL is not enabled; therefore, we must create the default result by
15739# calling ovf_res().
15740#
15741fsqrt_sd_ovfl_dis:
15742 btst &neg_bit,FPSR_CC(%a6) # is result negative?
15743 sne %d1 # set sign param accordingly
15744 mov.l L_SCR3(%a6),%d0 # pass: prec,mode
15745 bsr.l ovf_res # calculate default result
15746 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
15747 fmovm.x (%a0),&0x80 # return default result in fp0
15748 rts
15749
15750#
15751# OVFL is enabled.
15752# the INEX2 bit has already been updated by the round to the correct precision.
15753# now, round to extended(and don't alter the FPSR).
15754#
15755fsqrt_sd_ovfl_ena:
15756 mov.l %d2,-(%sp) # save d2
15757 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
15758 mov.l %d1,%d2 # make a copy
15759 andi.l &0x7fff,%d1 # strip sign
15760 andi.w &0x8000,%d2 # keep old sign
15761 sub.l %d0,%d1 # add scale factor
15762 subi.l &0x6000,%d1 # subtract bias
15763 andi.w &0x7fff,%d1
15764 or.w %d2,%d1 # concat sign,exp
15765 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
15766 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
15767 mov.l (%sp)+,%d2 # restore d2
15768 bra.b fsqrt_sd_ovfl_dis
15769
15770#
15771# the move in MAY underflow. so...
15772#
15773fsqrt_sd_may_ovfl:
15774 btst &0x0,1+FP_SCR0_EX(%a6) # is exponent 0x3fff?
15775 bne.w fsqrt_sd_ovfl # yes, so overflow
15776
15777 fmov.l &0x0,%fpsr # clear FPSR
15778 fmov.l L_SCR3(%a6),%fpcr # set FPCR
15779
15780 fsqrt.x FP_SCR0(%a6),%fp0 # perform absolute
15781
15782 fmov.l %fpsr,%d1 # save status
15783 fmov.l &0x0,%fpcr # clear FPCR
15784
15785 or.l %d1,USER_FPSR(%a6) # save INEX2,N
15786
15787 fmov.x %fp0,%fp1 # make a copy of result
15788 fcmp.b %fp1,&0x1 # is |result| >= 1.b?
15789 fbge.w fsqrt_sd_ovfl_tst # yes; overflow has occurred
15790
15791# no, it didn't overflow; we have correct result
15792 bra.w fsqrt_sd_normal_exit
15793
15794##########################################################################
15795
15796#
15797# input is not normalized; what is it?
15798#
15799fsqrt_not_norm:
15800 cmpi.b %d1,&DENORM # weed out DENORM
15801 beq.w fsqrt_denorm
15802 cmpi.b %d1,&ZERO # weed out ZERO
15803 beq.b fsqrt_zero
15804 cmpi.b %d1,&INF # weed out INF
15805 beq.b fsqrt_inf
15806 cmpi.b %d1,&SNAN # weed out SNAN
15807 beq.l res_snan_1op
15808 bra.l res_qnan_1op
15809
15810#
15811# fsqrt(+0) = +0
15812# fsqrt(-0) = -0
15813# fsqrt(+INF) = +INF
15814# fsqrt(-INF) = OPERR
15815#
15816fsqrt_zero:
15817 tst.b SRC_EX(%a0) # is ZERO positive or negative?
15818 bmi.b fsqrt_zero_m # negative
15819fsqrt_zero_p:
15820 fmov.s &0x00000000,%fp0 # return +ZERO
15821 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
15822 rts
15823fsqrt_zero_m:
15824 fmov.s &0x80000000,%fp0 # return -ZERO
15825 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
15826 rts
15827
15828fsqrt_inf:
15829 tst.b SRC_EX(%a0) # is INF positive or negative?
15830 bmi.l res_operr # negative
15831fsqrt_inf_p:
15832 fmovm.x SRC(%a0),&0x80 # return +INF in fp0
15833 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
15834 rts
15835
15836##########################################################################
15837
15838#########################################################################
15839# XDEF **************************************************************** #
15840# addsub_scaler2(): scale inputs to fadd/fsub such that no #
15841# OVFL/UNFL exceptions will result #
15842# #
15843# XREF **************************************************************** #
15844# norm() - normalize mantissa after adjusting exponent #
15845# #
15846# INPUT *************************************************************** #
15847# FP_SRC(a6) = fp op1(src) #
15848# FP_DST(a6) = fp op2(dst) #
15849# #
15850# OUTPUT ************************************************************** #
15851# FP_SRC(a6) = fp op1 scaled(src) #
15852# FP_DST(a6) = fp op2 scaled(dst) #
15853# d0 = scale amount #
15854# #
15855# ALGORITHM *********************************************************** #
15856# If the DST exponent is > the SRC exponent, set the DST exponent #
15857# equal to 0x3fff and scale the SRC exponent by the value that the #
15858# DST exponent was scaled by. If the SRC exponent is greater or equal, #
15859# do the opposite. Return this scale factor in d0. #
15860# If the two exponents differ by > the number of mantissa bits #
15861# plus two, then set the smallest exponent to a very small value as a #
15862# quick shortcut. #
15863# #
15864#########################################################################
15865
15866 global addsub_scaler2
15867addsub_scaler2:
15868 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
15869 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
15870 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
15871 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
15872 mov.w SRC_EX(%a0),%d0
15873 mov.w DST_EX(%a1),%d1
15874 mov.w %d0,FP_SCR0_EX(%a6)
15875 mov.w %d1,FP_SCR1_EX(%a6)
15876
15877 andi.w &0x7fff,%d0
15878 andi.w &0x7fff,%d1
15879 mov.w %d0,L_SCR1(%a6) # store src exponent
15880 mov.w %d1,2+L_SCR1(%a6) # store dst exponent
15881
15882 cmp.w %d0, %d1 # is src exp >= dst exp?
15883 bge.l src_exp_ge2
15884
15885# dst exp is > src exp; scale dst to exp = 0x3fff
15886dst_exp_gt2:
15887 bsr.l scale_to_zero_dst
15888 mov.l %d0,-(%sp) # save scale factor
15889
15890 cmpi.b STAG(%a6),&DENORM # is dst denormalized?
15891 bne.b cmpexp12
15892
15893 lea FP_SCR0(%a6),%a0
15894 bsr.l norm # normalize the denorm; result is new exp
15895 neg.w %d0 # new exp = -(shft val)
15896 mov.w %d0,L_SCR1(%a6) # inset new exp
15897
15898cmpexp12:
15899 mov.w 2+L_SCR1(%a6),%d0
15900 subi.w &mantissalen+2,%d0 # subtract mantissalen+2 from larger exp
15901
15902 cmp.w %d0,L_SCR1(%a6) # is difference >= len(mantissa)+2?
15903 bge.b quick_scale12
15904
15905 mov.w L_SCR1(%a6),%d0
15906 add.w 0x2(%sp),%d0 # scale src exponent by scale factor
15907 mov.w FP_SCR0_EX(%a6),%d1
15908 and.w &0x8000,%d1
15909 or.w %d1,%d0 # concat {sgn,new exp}
15910 mov.w %d0,FP_SCR0_EX(%a6) # insert new dst exponent
15911
15912 mov.l (%sp)+,%d0 # return SCALE factor
15913 rts
15914
15915quick_scale12:
15916 andi.w &0x8000,FP_SCR0_EX(%a6) # zero src exponent
15917 bset &0x0,1+FP_SCR0_EX(%a6) # set exp = 1
15918
15919 mov.l (%sp)+,%d0 # return SCALE factor
15920 rts
15921
15922# src exp is >= dst exp; scale src to exp = 0x3fff
15923src_exp_ge2:
15924 bsr.l scale_to_zero_src
15925 mov.l %d0,-(%sp) # save scale factor
15926
15927 cmpi.b DTAG(%a6),&DENORM # is dst denormalized?
15928 bne.b cmpexp22
15929 lea FP_SCR1(%a6),%a0
15930 bsr.l norm # normalize the denorm; result is new exp
15931 neg.w %d0 # new exp = -(shft val)
15932 mov.w %d0,2+L_SCR1(%a6) # inset new exp
15933
15934cmpexp22:
15935 mov.w L_SCR1(%a6),%d0
15936 subi.w &mantissalen+2,%d0 # subtract mantissalen+2 from larger exp
15937
15938 cmp.w %d0,2+L_SCR1(%a6) # is difference >= len(mantissa)+2?
15939 bge.b quick_scale22
15940
15941 mov.w 2+L_SCR1(%a6),%d0
15942 add.w 0x2(%sp),%d0 # scale dst exponent by scale factor
15943 mov.w FP_SCR1_EX(%a6),%d1
15944 andi.w &0x8000,%d1
15945 or.w %d1,%d0 # concat {sgn,new exp}
15946 mov.w %d0,FP_SCR1_EX(%a6) # insert new dst exponent
15947
15948 mov.l (%sp)+,%d0 # return SCALE factor
15949 rts
15950
15951quick_scale22:
15952 andi.w &0x8000,FP_SCR1_EX(%a6) # zero dst exponent
15953 bset &0x0,1+FP_SCR1_EX(%a6) # set exp = 1
15954
15955 mov.l (%sp)+,%d0 # return SCALE factor
15956 rts
15957
15958##########################################################################
15959
15960#########################################################################
15961# XDEF **************************************************************** #
15962# scale_to_zero_src(): scale the exponent of extended precision #
15963# value at FP_SCR0(a6). #
15964# #
15965# XREF **************************************************************** #
15966# norm() - normalize the mantissa if the operand was a DENORM #
15967# #
15968# INPUT *************************************************************** #
15969# FP_SCR0(a6) = extended precision operand to be scaled #
15970# #
15971# OUTPUT ************************************************************** #
15972# FP_SCR0(a6) = scaled extended precision operand #
15973# d0 = scale value #
15974# #
15975# ALGORITHM *********************************************************** #
15976# Set the exponent of the input operand to 0x3fff. Save the value #
15977# of the difference between the original and new exponent. Then, #
15978# normalize the operand if it was a DENORM. Add this normalization #
15979# value to the previous value. Return the result. #
15980# #
15981#########################################################################
15982
15983 global scale_to_zero_src
15984scale_to_zero_src:
15985 mov.w FP_SCR0_EX(%a6),%d1 # extract operand's {sgn,exp}
15986 mov.w %d1,%d0 # make a copy
15987
15988 andi.l &0x7fff,%d1 # extract operand's exponent
15989
15990 andi.w &0x8000,%d0 # extract operand's sgn
15991 or.w &0x3fff,%d0 # insert new operand's exponent(=0)
15992
15993 mov.w %d0,FP_SCR0_EX(%a6) # insert biased exponent
15994
15995 cmpi.b STAG(%a6),&DENORM # is operand normalized?
15996 beq.b stzs_denorm # normalize the DENORM
15997
15998stzs_norm:
15999 mov.l &0x3fff,%d0
16000 sub.l %d1,%d0 # scale = BIAS + (-exp)
16001
16002 rts
16003
16004stzs_denorm:
16005 lea FP_SCR0(%a6),%a0 # pass ptr to src op
16006 bsr.l norm # normalize denorm
16007 neg.l %d0 # new exponent = -(shft val)
16008 mov.l %d0,%d1 # prepare for op_norm call
16009 bra.b stzs_norm # finish scaling
16010
16011###
16012
16013#########################################################################
16014# XDEF **************************************************************** #
16015# scale_sqrt(): scale the input operand exponent so a subsequent #
16016# fsqrt operation won't take an exception. #
16017# #
16018# XREF **************************************************************** #
16019# norm() - normalize the mantissa if the operand was a DENORM #
16020# #
16021# INPUT *************************************************************** #
16022# FP_SCR0(a6) = extended precision operand to be scaled #
16023# #
16024# OUTPUT ************************************************************** #
16025# FP_SCR0(a6) = scaled extended precision operand #
16026# d0 = scale value #
16027# #
16028# ALGORITHM *********************************************************** #
16029# If the input operand is a DENORM, normalize it. #
16030# If the exponent of the input operand is even, set the exponent #
16031# to 0x3ffe and return a scale factor of "(exp-0x3ffe)/2". If the #
16032# exponent of the input operand is off, set the exponent to ox3fff and #
16033# return a scale factor of "(exp-0x3fff)/2". #
16034# #
16035#########################################################################
16036
16037 global scale_sqrt
16038scale_sqrt:
16039 cmpi.b STAG(%a6),&DENORM # is operand normalized?
16040 beq.b ss_denorm # normalize the DENORM
16041
16042 mov.w FP_SCR0_EX(%a6),%d1 # extract operand's {sgn,exp}
16043 andi.l &0x7fff,%d1 # extract operand's exponent
16044
16045 andi.w &0x8000,FP_SCR0_EX(%a6) # extract operand's sgn
16046
16047 btst &0x0,%d1 # is exp even or odd?
16048 beq.b ss_norm_even
16049
16050 ori.w &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
16051
16052 mov.l &0x3fff,%d0
16053 sub.l %d1,%d0 # scale = BIAS + (-exp)
16054 asr.l &0x1,%d0 # divide scale factor by 2
16055 rts
16056
16057ss_norm_even:
16058 ori.w &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
16059
16060 mov.l &0x3ffe,%d0
16061 sub.l %d1,%d0 # scale = BIAS + (-exp)
16062 asr.l &0x1,%d0 # divide scale factor by 2
16063 rts
16064
16065ss_denorm:
16066 lea FP_SCR0(%a6),%a0 # pass ptr to src op
16067 bsr.l norm # normalize denorm
16068
16069 btst &0x0,%d0 # is exp even or odd?
16070 beq.b ss_denorm_even
16071
16072 ori.w &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
16073
16074 add.l &0x3fff,%d0
16075 asr.l &0x1,%d0 # divide scale factor by 2
16076 rts
16077
16078ss_denorm_even:
16079 ori.w &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
16080
16081 add.l &0x3ffe,%d0
16082 asr.l &0x1,%d0 # divide scale factor by 2
16083 rts
16084
16085###
16086
16087#########################################################################
16088# XDEF **************************************************************** #
16089# scale_to_zero_dst(): scale the exponent of extended precision #
16090# value at FP_SCR1(a6). #
16091# #
16092# XREF **************************************************************** #
16093# norm() - normalize the mantissa if the operand was a DENORM #
16094# #
16095# INPUT *************************************************************** #
16096# FP_SCR1(a6) = extended precision operand to be scaled #
16097# #
16098# OUTPUT ************************************************************** #
16099# FP_SCR1(a6) = scaled extended precision operand #
16100# d0 = scale value #
16101# #
16102# ALGORITHM *********************************************************** #
16103# Set the exponent of the input operand to 0x3fff. Save the value #
16104# of the difference between the original and new exponent. Then, #
16105# normalize the operand if it was a DENORM. Add this normalization #
16106# value to the previous value. Return the result. #
16107# #
16108#########################################################################
16109
16110 global scale_to_zero_dst
16111scale_to_zero_dst:
16112 mov.w FP_SCR1_EX(%a6),%d1 # extract operand's {sgn,exp}
16113 mov.w %d1,%d0 # make a copy
16114
16115 andi.l &0x7fff,%d1 # extract operand's exponent
16116
16117 andi.w &0x8000,%d0 # extract operand's sgn
16118 or.w &0x3fff,%d0 # insert new operand's exponent(=0)
16119
16120 mov.w %d0,FP_SCR1_EX(%a6) # insert biased exponent
16121
16122 cmpi.b DTAG(%a6),&DENORM # is operand normalized?
16123 beq.b stzd_denorm # normalize the DENORM
16124
16125stzd_norm:
16126 mov.l &0x3fff,%d0
16127 sub.l %d1,%d0 # scale = BIAS + (-exp)
16128 rts
16129
16130stzd_denorm:
16131 lea FP_SCR1(%a6),%a0 # pass ptr to dst op
16132 bsr.l norm # normalize denorm
16133 neg.l %d0 # new exponent = -(shft val)
16134 mov.l %d0,%d1 # prepare for op_norm call
16135 bra.b stzd_norm # finish scaling
16136
16137##########################################################################
16138
16139#########################################################################
16140# XDEF **************************************************************** #
16141# res_qnan(): return default result w/ QNAN operand for dyadic #
16142# res_snan(): return default result w/ SNAN operand for dyadic #
16143# res_qnan_1op(): return dflt result w/ QNAN operand for monadic #
16144# res_snan_1op(): return dflt result w/ SNAN operand for monadic #
16145# #
16146# XREF **************************************************************** #
16147# None #
16148# #
16149# INPUT *************************************************************** #
16150# FP_SRC(a6) = pointer to extended precision src operand #
16151# FP_DST(a6) = pointer to extended precision dst operand #
16152# #
16153# OUTPUT ************************************************************** #
16154# fp0 = default result #
16155# #
16156# ALGORITHM *********************************************************** #
16157# If either operand (but not both operands) of an operation is a #
16158# nonsignalling NAN, then that NAN is returned as the result. If both #
16159# operands are nonsignalling NANs, then the destination operand #
16160# nonsignalling NAN is returned as the result. #
16161# If either operand to an operation is a signalling NAN (SNAN), #
16162# then, the SNAN bit is set in the FPSR EXC byte. If the SNAN trap #
16163# enable bit is set in the FPCR, then the trap is taken and the #
16164# destination is not modified. If the SNAN trap enable bit is not set, #
16165# then the SNAN is converted to a nonsignalling NAN (by setting the #
16166# SNAN bit in the operand to one), and the operation continues as #
16167# described in the preceding paragraph, for nonsignalling NANs. #
16168# Make sure the appropriate FPSR bits are set before exiting. #
16169# #
16170#########################################################################
16171
16172 global res_qnan
16173 global res_snan
16174res_qnan:
16175res_snan:
16176 cmp.b DTAG(%a6), &SNAN # is the dst an SNAN?
16177 beq.b dst_snan2
16178 cmp.b DTAG(%a6), &QNAN # is the dst a QNAN?
16179 beq.b dst_qnan2
16180src_nan:
16181 cmp.b STAG(%a6), &QNAN
16182 beq.b src_qnan2
16183 global res_snan_1op
16184res_snan_1op:
16185src_snan2:
16186 bset &0x6, FP_SRC_HI(%a6) # set SNAN bit
16187 or.l &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
16188 lea FP_SRC(%a6), %a0
16189 bra.b nan_comp
16190 global res_qnan_1op
16191res_qnan_1op:
16192src_qnan2:
16193 or.l &nan_mask, USER_FPSR(%a6)
16194 lea FP_SRC(%a6), %a0
16195 bra.b nan_comp
16196dst_snan2:
16197 or.l &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
16198 bset &0x6, FP_DST_HI(%a6) # set SNAN bit
16199 lea FP_DST(%a6), %a0
16200 bra.b nan_comp
16201dst_qnan2:
16202 lea FP_DST(%a6), %a0
16203 cmp.b STAG(%a6), &SNAN
16204 bne nan_done
16205 or.l &aiop_mask+snan_mask, USER_FPSR(%a6)
16206nan_done:
16207 or.l &nan_mask, USER_FPSR(%a6)
16208nan_comp:
16209 btst &0x7, FTEMP_EX(%a0) # is NAN neg?
16210 beq.b nan_not_neg
16211 or.l &neg_mask, USER_FPSR(%a6)
16212nan_not_neg:
16213 fmovm.x (%a0), &0x80
16214 rts
16215
16216#########################################################################
16217# XDEF **************************************************************** #
16218# res_operr(): return default result during operand error #
16219# #
16220# XREF **************************************************************** #
16221# None #
16222# #
16223# INPUT *************************************************************** #
16224# None #
16225# #
16226# OUTPUT ************************************************************** #
16227# fp0 = default operand error result #
16228# #
16229# ALGORITHM *********************************************************** #
16230# An nonsignalling NAN is returned as the default result when #
16231# an operand error occurs for the following cases: #
16232# #
16233# Multiply: (Infinity x Zero) #
16234# Divide : (Zero / Zero) || (Infinity / Infinity) #
16235# #
16236#########################################################################
16237
16238 global res_operr
16239res_operr:
16240 or.l &nan_mask+operr_mask+aiop_mask, USER_FPSR(%a6)
16241 fmovm.x nan_return(%pc), &0x80
16242 rts
16243
16244nan_return:
16245 long 0x7fff0000, 0xffffffff, 0xffffffff
16246
16247#########################################################################
16248# fdbcc(): routine to emulate the fdbcc instruction #
16249# #
16250# XDEF **************************************************************** #
16251# _fdbcc() #
16252# #
16253# XREF **************************************************************** #
16254# fetch_dreg() - fetch Dn value #
16255# store_dreg_l() - store updated Dn value #
16256# #
16257# INPUT *************************************************************** #
16258# d0 = displacement #
16259# #
16260# OUTPUT ************************************************************** #
16261# none #
16262# #
16263# ALGORITHM *********************************************************** #
16264# This routine checks which conditional predicate is specified by #
16265# the stacked fdbcc instruction opcode and then branches to a routine #
16266# for that predicate. The corresponding fbcc instruction is then used #
16267# to see whether the condition (specified by the stacked FPSR) is true #
16268# or false. #
16269# If a BSUN exception should be indicated, the BSUN and ABSUN #
16270# bits are set in the stacked FPSR. If the BSUN exception is enabled, #
16271# the fbsun_flg is set in the SPCOND_FLG location on the stack. If an #
16272# enabled BSUN should not be flagged and the predicate is true, then #
16273# Dn is fetched and decremented by one. If Dn is not equal to -1, add #
16274# the displacement value to the stacked PC so that when an "rte" is #
16275# finally executed, the branch occurs. #
16276# #
16277#########################################################################
16278 global _fdbcc
16279_fdbcc:
16280 mov.l %d0,L_SCR1(%a6) # save displacement
16281
16282 mov.w EXC_CMDREG(%a6),%d0 # fetch predicate
16283
16284 clr.l %d1 # clear scratch reg
16285 mov.b FPSR_CC(%a6),%d1 # fetch fp ccodes
16286 ror.l &0x8,%d1 # rotate to top byte
16287 fmov.l %d1,%fpsr # insert into FPSR
16288
16289 mov.w (tbl_fdbcc.b,%pc,%d0.w*2),%d1 # load table
16290 jmp (tbl_fdbcc.b,%pc,%d1.w) # jump to fdbcc routine
16291
16292tbl_fdbcc:
16293 short fdbcc_f - tbl_fdbcc # 00
16294 short fdbcc_eq - tbl_fdbcc # 01
16295 short fdbcc_ogt - tbl_fdbcc # 02
16296 short fdbcc_oge - tbl_fdbcc # 03
16297 short fdbcc_olt - tbl_fdbcc # 04
16298 short fdbcc_ole - tbl_fdbcc # 05
16299 short fdbcc_ogl - tbl_fdbcc # 06
16300 short fdbcc_or - tbl_fdbcc # 07
16301 short fdbcc_un - tbl_fdbcc # 08
16302 short fdbcc_ueq - tbl_fdbcc # 09
16303 short fdbcc_ugt - tbl_fdbcc # 10
16304 short fdbcc_uge - tbl_fdbcc # 11
16305 short fdbcc_ult - tbl_fdbcc # 12
16306 short fdbcc_ule - tbl_fdbcc # 13
16307 short fdbcc_neq - tbl_fdbcc # 14
16308 short fdbcc_t - tbl_fdbcc # 15
16309 short fdbcc_sf - tbl_fdbcc # 16
16310 short fdbcc_seq - tbl_fdbcc # 17
16311 short fdbcc_gt - tbl_fdbcc # 18
16312 short fdbcc_ge - tbl_fdbcc # 19
16313 short fdbcc_lt - tbl_fdbcc # 20
16314 short fdbcc_le - tbl_fdbcc # 21
16315 short fdbcc_gl - tbl_fdbcc # 22
16316 short fdbcc_gle - tbl_fdbcc # 23
16317 short fdbcc_ngle - tbl_fdbcc # 24
16318 short fdbcc_ngl - tbl_fdbcc # 25
16319 short fdbcc_nle - tbl_fdbcc # 26
16320 short fdbcc_nlt - tbl_fdbcc # 27
16321 short fdbcc_nge - tbl_fdbcc # 28
16322 short fdbcc_ngt - tbl_fdbcc # 29
16323 short fdbcc_sneq - tbl_fdbcc # 30
16324 short fdbcc_st - tbl_fdbcc # 31
16325
16326#########################################################################
16327# #
16328# IEEE Nonaware tests #
16329# #
16330# For the IEEE nonaware tests, only the false branch changes the #
16331# counter. However, the true branch may set bsun so we check to see #
16332# if the NAN bit is set, in which case BSUN and AIOP will be set. #
16333# #
16334# The cases EQ and NE are shared by the Aware and Nonaware groups #
16335# and are incapable of setting the BSUN exception bit. #
16336# #
16337# Typically, only one of the two possible branch directions could #
16338# have the NAN bit set. #
16339# (This is assuming the mutual exclusiveness of FPSR cc bit groupings #
16340# is preserved.) #
16341# #
16342#########################################################################
16343
16344#
16345# equal:
16346#
16347# Z
16348#
16349fdbcc_eq:
16350 fbeq.w fdbcc_eq_yes # equal?
16351fdbcc_eq_no:
16352 bra.w fdbcc_false # no; go handle counter
16353fdbcc_eq_yes:
16354 rts
16355
16356#
16357# not equal:
16358# _
16359# Z
16360#
16361fdbcc_neq:
16362 fbneq.w fdbcc_neq_yes # not equal?
16363fdbcc_neq_no:
16364 bra.w fdbcc_false # no; go handle counter
16365fdbcc_neq_yes:
16366 rts
16367
16368#
16369# greater than:
16370# _______
16371# NANvZvN
16372#
16373fdbcc_gt:
16374 fbgt.w fdbcc_gt_yes # greater than?
16375 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16376 beq.w fdbcc_false # no;go handle counter
16377 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16378 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16379 bne.w fdbcc_bsun # yes; we have an exception
16380 bra.w fdbcc_false # no; go handle counter
16381fdbcc_gt_yes:
16382 rts # do nothing
16383
16384#
16385# not greater than:
16386#
16387# NANvZvN
16388#
16389fdbcc_ngt:
16390 fbngt.w fdbcc_ngt_yes # not greater than?
16391fdbcc_ngt_no:
16392 bra.w fdbcc_false # no; go handle counter
16393fdbcc_ngt_yes:
16394 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16395 beq.b fdbcc_ngt_done # no;go finish
16396 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16397 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16398 bne.w fdbcc_bsun # yes; we have an exception
16399fdbcc_ngt_done:
16400 rts # no; do nothing
16401
16402#
16403# greater than or equal:
16404# _____
16405# Zv(NANvN)
16406#
16407fdbcc_ge:
16408 fbge.w fdbcc_ge_yes # greater than or equal?
16409fdbcc_ge_no:
16410 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16411 beq.w fdbcc_false # no;go handle counter
16412 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16413 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16414 bne.w fdbcc_bsun # yes; we have an exception
16415 bra.w fdbcc_false # no; go handle counter
16416fdbcc_ge_yes:
16417 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16418 beq.b fdbcc_ge_yes_done # no;go do nothing
16419 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16420 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16421 bne.w fdbcc_bsun # yes; we have an exception
16422fdbcc_ge_yes_done:
16423 rts # do nothing
16424
16425#
16426# not (greater than or equal):
16427# _
16428# NANv(N^Z)
16429#
16430fdbcc_nge:
16431 fbnge.w fdbcc_nge_yes # not (greater than or equal)?
16432fdbcc_nge_no:
16433 bra.w fdbcc_false # no; go handle counter
16434fdbcc_nge_yes:
16435 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16436 beq.b fdbcc_nge_done # no;go finish
16437 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16438 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16439 bne.w fdbcc_bsun # yes; we have an exception
16440fdbcc_nge_done:
16441 rts # no; do nothing
16442
16443#
16444# less than:
16445# _____
16446# N^(NANvZ)
16447#
16448fdbcc_lt:
16449 fblt.w fdbcc_lt_yes # less than?
16450fdbcc_lt_no:
16451 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16452 beq.w fdbcc_false # no; go handle counter
16453 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16454 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16455 bne.w fdbcc_bsun # yes; we have an exception
16456 bra.w fdbcc_false # no; go handle counter
16457fdbcc_lt_yes:
16458 rts # do nothing
16459
16460#
16461# not less than:
16462# _
16463# NANv(ZvN)
16464#
16465fdbcc_nlt:
16466 fbnlt.w fdbcc_nlt_yes # not less than?
16467fdbcc_nlt_no:
16468 bra.w fdbcc_false # no; go handle counter
16469fdbcc_nlt_yes:
16470 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16471 beq.b fdbcc_nlt_done # no;go finish
16472 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16473 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16474 bne.w fdbcc_bsun # yes; we have an exception
16475fdbcc_nlt_done:
16476 rts # no; do nothing
16477
16478#
16479# less than or equal:
16480# ___
16481# Zv(N^NAN)
16482#
16483fdbcc_le:
16484 fble.w fdbcc_le_yes # less than or equal?
16485fdbcc_le_no:
16486 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16487 beq.w fdbcc_false # no; go handle counter
16488 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16489 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16490 bne.w fdbcc_bsun # yes; we have an exception
16491 bra.w fdbcc_false # no; go handle counter
16492fdbcc_le_yes:
16493 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16494 beq.b fdbcc_le_yes_done # no; go do nothing
16495 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16496 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16497 bne.w fdbcc_bsun # yes; we have an exception
16498fdbcc_le_yes_done:
16499 rts # do nothing
16500
16501#
16502# not (less than or equal):
16503# ___
16504# NANv(NvZ)
16505#
16506fdbcc_nle:
16507 fbnle.w fdbcc_nle_yes # not (less than or equal)?
16508fdbcc_nle_no:
16509 bra.w fdbcc_false # no; go handle counter
16510fdbcc_nle_yes:
16511 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16512 beq.w fdbcc_nle_done # no; go finish
16513 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16514 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16515 bne.w fdbcc_bsun # yes; we have an exception
16516fdbcc_nle_done:
16517 rts # no; do nothing
16518
16519#
16520# greater or less than:
16521# _____
16522# NANvZ
16523#
16524fdbcc_gl:
16525 fbgl.w fdbcc_gl_yes # greater or less than?
16526fdbcc_gl_no:
16527 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16528 beq.w fdbcc_false # no; handle counter
16529 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16530 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16531 bne.w fdbcc_bsun # yes; we have an exception
16532 bra.w fdbcc_false # no; go handle counter
16533fdbcc_gl_yes:
16534 rts # do nothing
16535
16536#
16537# not (greater or less than):
16538#
16539# NANvZ
16540#
16541fdbcc_ngl:
16542 fbngl.w fdbcc_ngl_yes # not (greater or less than)?
16543fdbcc_ngl_no:
16544 bra.w fdbcc_false # no; go handle counter
16545fdbcc_ngl_yes:
16546 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16547 beq.b fdbcc_ngl_done # no; go finish
16548 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16549 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16550 bne.w fdbcc_bsun # yes; we have an exception
16551fdbcc_ngl_done:
16552 rts # no; do nothing
16553
16554#
16555# greater, less, or equal:
16556# ___
16557# NAN
16558#
16559fdbcc_gle:
16560 fbgle.w fdbcc_gle_yes # greater, less, or equal?
16561fdbcc_gle_no:
16562 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16563 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16564 bne.w fdbcc_bsun # yes; we have an exception
16565 bra.w fdbcc_false # no; go handle counter
16566fdbcc_gle_yes:
16567 rts # do nothing
16568
16569#
16570# not (greater, less, or equal):
16571#
16572# NAN
16573#
16574fdbcc_ngle:
16575 fbngle.w fdbcc_ngle_yes # not (greater, less, or equal)?
16576fdbcc_ngle_no:
16577 bra.w fdbcc_false # no; go handle counter
16578fdbcc_ngle_yes:
16579 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16580 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16581 bne.w fdbcc_bsun # yes; we have an exception
16582 rts # no; do nothing
16583
16584#########################################################################
16585# #
16586# Miscellaneous tests #
16587# #
16588# For the IEEE miscellaneous tests, all but fdbf and fdbt can set bsun. #
16589# #
16590#########################################################################
16591
16592#
16593# false:
16594#
16595# False
16596#
16597fdbcc_f: # no bsun possible
16598 bra.w fdbcc_false # go handle counter
16599
16600#
16601# true:
16602#
16603# True
16604#
16605fdbcc_t: # no bsun possible
16606 rts # do nothing
16607
16608#
16609# signalling false:
16610#
16611# False
16612#
16613fdbcc_sf:
16614 btst &nan_bit, FPSR_CC(%a6) # is NAN set?
16615 beq.w fdbcc_false # no;go handle counter
16616 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16617 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16618 bne.w fdbcc_bsun # yes; we have an exception
16619 bra.w fdbcc_false # go handle counter
16620
16621#
16622# signalling true:
16623#
16624# True
16625#
16626fdbcc_st:
16627 btst &nan_bit, FPSR_CC(%a6) # is NAN set?
16628 beq.b fdbcc_st_done # no;go finish
16629 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16630 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16631 bne.w fdbcc_bsun # yes; we have an exception
16632fdbcc_st_done:
16633 rts
16634
16635#
16636# signalling equal:
16637#
16638# Z
16639#
16640fdbcc_seq:
16641 fbseq.w fdbcc_seq_yes # signalling equal?
16642fdbcc_seq_no:
16643 btst &nan_bit, FPSR_CC(%a6) # is NAN set?
16644 beq.w fdbcc_false # no;go handle counter
16645 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16646 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16647 bne.w fdbcc_bsun # yes; we have an exception
16648 bra.w fdbcc_false # go handle counter
16649fdbcc_seq_yes:
16650 btst &nan_bit, FPSR_CC(%a6) # is NAN set?
16651 beq.b fdbcc_seq_yes_done # no;go do nothing
16652 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16653 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16654 bne.w fdbcc_bsun # yes; we have an exception
16655fdbcc_seq_yes_done:
16656 rts # yes; do nothing
16657
16658#
16659# signalling not equal:
16660# _
16661# Z
16662#
16663fdbcc_sneq:
16664 fbsneq.w fdbcc_sneq_yes # signalling not equal?
16665fdbcc_sneq_no:
16666 btst &nan_bit, FPSR_CC(%a6) # is NAN set?
16667 beq.w fdbcc_false # no;go handle counter
16668 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16669 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16670 bne.w fdbcc_bsun # yes; we have an exception
16671 bra.w fdbcc_false # go handle counter
16672fdbcc_sneq_yes:
16673 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
16674 beq.w fdbcc_sneq_done # no;go finish
16675 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
16676 btst &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
16677 bne.w fdbcc_bsun # yes; we have an exception
16678fdbcc_sneq_done:
16679 rts
16680
16681#########################################################################
16682# #
16683# IEEE Aware tests #
16684# #
16685# For the IEEE aware tests, action is only taken if the result is false.#
16686# Therefore, the opposite branch type is used to jump to the decrement #
16687# routine. #
16688# The BSUN exception will not be set for any of these tests. #
16689# #
16690#########################################################################
16691
16692#
16693# ordered greater than:
16694# _______
16695# NANvZvN
16696#
16697fdbcc_ogt:
16698 fbogt.w fdbcc_ogt_yes # ordered greater than?
16699fdbcc_ogt_no:
16700 bra.w fdbcc_false # no; go handle counter
16701fdbcc_ogt_yes:
16702 rts # yes; do nothing
16703
16704#
16705# unordered or less or equal:
16706# _______
16707# NANvZvN
16708#
16709fdbcc_ule:
16710 fbule.w fdbcc_ule_yes # unordered or less or equal?
16711fdbcc_ule_no:
16712 bra.w fdbcc_false # no; go handle counter
16713fdbcc_ule_yes:
16714 rts # yes; do nothing
16715
16716#
16717# ordered greater than or equal:
16718# _____
16719# Zv(NANvN)
16720#
16721fdbcc_oge:
16722 fboge.w fdbcc_oge_yes # ordered greater than or equal?
16723fdbcc_oge_no:
16724 bra.w fdbcc_false # no; go handle counter
16725fdbcc_oge_yes:
16726 rts # yes; do nothing
16727
16728#
16729# unordered or less than:
16730# _
16731# NANv(N^Z)
16732#
16733fdbcc_ult:
16734 fbult.w fdbcc_ult_yes # unordered or less than?
16735fdbcc_ult_no:
16736 bra.w fdbcc_false # no; go handle counter
16737fdbcc_ult_yes:
16738 rts # yes; do nothing
16739
16740#
16741# ordered less than:
16742# _____
16743# N^(NANvZ)
16744#
16745fdbcc_olt:
16746 fbolt.w fdbcc_olt_yes # ordered less than?
16747fdbcc_olt_no:
16748 bra.w fdbcc_false # no; go handle counter
16749fdbcc_olt_yes:
16750 rts # yes; do nothing
16751
16752#
16753# unordered or greater or equal:
16754#
16755# NANvZvN
16756#
16757fdbcc_uge:
16758 fbuge.w fdbcc_uge_yes # unordered or greater than?
16759fdbcc_uge_no:
16760 bra.w fdbcc_false # no; go handle counter
16761fdbcc_uge_yes:
16762 rts # yes; do nothing
16763
16764#
16765# ordered less than or equal:
16766# ___
16767# Zv(N^NAN)
16768#
16769fdbcc_ole:
16770 fbole.w fdbcc_ole_yes # ordered greater or less than?
16771fdbcc_ole_no:
16772 bra.w fdbcc_false # no; go handle counter
16773fdbcc_ole_yes:
16774 rts # yes; do nothing
16775
16776#
16777# unordered or greater than:
16778# ___
16779# NANv(NvZ)
16780#
16781fdbcc_ugt:
16782 fbugt.w fdbcc_ugt_yes # unordered or greater than?
16783fdbcc_ugt_no:
16784 bra.w fdbcc_false # no; go handle counter
16785fdbcc_ugt_yes:
16786 rts # yes; do nothing
16787
16788#
16789# ordered greater or less than:
16790# _____
16791# NANvZ
16792#
16793fdbcc_ogl:
16794 fbogl.w fdbcc_ogl_yes # ordered greater or less than?
16795fdbcc_ogl_no:
16796 bra.w fdbcc_false # no; go handle counter
16797fdbcc_ogl_yes:
16798 rts # yes; do nothing
16799
16800#
16801# unordered or equal:
16802#
16803# NANvZ
16804#
16805fdbcc_ueq:
16806 fbueq.w fdbcc_ueq_yes # unordered or equal?
16807fdbcc_ueq_no:
16808 bra.w fdbcc_false # no; go handle counter
16809fdbcc_ueq_yes:
16810 rts # yes; do nothing
16811
16812#
16813# ordered:
16814# ___
16815# NAN
16816#
16817fdbcc_or:
16818 fbor.w fdbcc_or_yes # ordered?
16819fdbcc_or_no:
16820 bra.w fdbcc_false # no; go handle counter
16821fdbcc_or_yes:
16822 rts # yes; do nothing
16823
16824#
16825# unordered:
16826#
16827# NAN
16828#
16829fdbcc_un:
16830 fbun.w fdbcc_un_yes # unordered?
16831fdbcc_un_no:
16832 bra.w fdbcc_false # no; go handle counter
16833fdbcc_un_yes:
16834 rts # yes; do nothing
16835
16836#######################################################################
16837
16838#
16839# the bsun exception bit was not set.
16840#
16841# (1) subtract 1 from the count register
16842# (2) if (cr == -1) then
16843# pc = pc of next instruction
16844# else
16845# pc += sign_ext(16-bit displacement)
16846#
16847fdbcc_false:
16848 mov.b 1+EXC_OPWORD(%a6), %d1 # fetch lo opword
16849 andi.w &0x7, %d1 # extract count register
16850
16851 bsr.l fetch_dreg # fetch count value
16852# make sure that d0 isn't corrupted between calls...
16853
16854 subq.w &0x1, %d0 # Dn - 1 -> Dn
16855
16856 bsr.l store_dreg_l # store new count value
16857
16858 cmpi.w %d0, &-0x1 # is (Dn == -1)?
16859 bne.b fdbcc_false_cont # no;
16860 rts
16861
16862fdbcc_false_cont:
16863 mov.l L_SCR1(%a6),%d0 # fetch displacement
16864 add.l USER_FPIAR(%a6),%d0 # add instruction PC
16865 addq.l &0x4,%d0 # add instruction length
16866 mov.l %d0,EXC_PC(%a6) # set new PC
16867 rts
16868
16869# the emulation routine set bsun and BSUN was enabled. have to
16870# fix stack and jump to the bsun handler.
16871# let the caller of this routine shift the stack frame up to
16872# eliminate the effective address field.
16873fdbcc_bsun:
16874 mov.b &fbsun_flg,SPCOND_FLG(%a6)
16875 rts
16876
16877#########################################################################
16878# ftrapcc(): routine to emulate the ftrapcc instruction #
16879# #
16880# XDEF **************************************************************** #
16881# _ftrapcc() #
16882# #
16883# XREF **************************************************************** #
16884# none #
16885# #
16886# INPUT *************************************************************** #
16887# none #
16888# #
16889# OUTPUT ************************************************************** #
16890# none #
16891# #
16892# ALGORITHM *********************************************************** #
16893# This routine checks which conditional predicate is specified by #
16894# the stacked ftrapcc instruction opcode and then branches to a routine #
16895# for that predicate. The corresponding fbcc instruction is then used #
16896# to see whether the condition (specified by the stacked FPSR) is true #
16897# or false. #
16898# If a BSUN exception should be indicated, the BSUN and ABSUN #
16899# bits are set in the stacked FPSR. If the BSUN exception is enabled, #
16900# the fbsun_flg is set in the SPCOND_FLG location on the stack. If an #
16901# enabled BSUN should not be flagged and the predicate is true, then #
16902# the ftrapcc_flg is set in the SPCOND_FLG location. These special #
16903# flags indicate to the calling routine to emulate the exceptional #
16904# condition. #
16905# #
16906#########################################################################
16907
16908 global _ftrapcc
16909_ftrapcc:
16910 mov.w EXC_CMDREG(%a6),%d0 # fetch predicate
16911
16912 clr.l %d1 # clear scratch reg
16913 mov.b FPSR_CC(%a6),%d1 # fetch fp ccodes
16914 ror.l &0x8,%d1 # rotate to top byte
16915 fmov.l %d1,%fpsr # insert into FPSR
16916
16917 mov.w (tbl_ftrapcc.b,%pc,%d0.w*2), %d1 # load table
16918 jmp (tbl_ftrapcc.b,%pc,%d1.w) # jump to ftrapcc routine
16919
16920tbl_ftrapcc:
16921 short ftrapcc_f - tbl_ftrapcc # 00
16922 short ftrapcc_eq - tbl_ftrapcc # 01
16923 short ftrapcc_ogt - tbl_ftrapcc # 02
16924 short ftrapcc_oge - tbl_ftrapcc # 03
16925 short ftrapcc_olt - tbl_ftrapcc # 04
16926 short ftrapcc_ole - tbl_ftrapcc # 05
16927 short ftrapcc_ogl - tbl_ftrapcc # 06
16928 short ftrapcc_or - tbl_ftrapcc # 07
16929 short ftrapcc_un - tbl_ftrapcc # 08
16930 short ftrapcc_ueq - tbl_ftrapcc # 09
16931 short ftrapcc_ugt - tbl_ftrapcc # 10
16932 short ftrapcc_uge - tbl_ftrapcc # 11
16933 short ftrapcc_ult - tbl_ftrapcc # 12
16934 short ftrapcc_ule - tbl_ftrapcc # 13
16935 short ftrapcc_neq - tbl_ftrapcc # 14
16936 short ftrapcc_t - tbl_ftrapcc # 15
16937 short ftrapcc_sf - tbl_ftrapcc # 16
16938 short ftrapcc_seq - tbl_ftrapcc # 17
16939 short ftrapcc_gt - tbl_ftrapcc # 18
16940 short ftrapcc_ge - tbl_ftrapcc # 19
16941 short ftrapcc_lt - tbl_ftrapcc # 20
16942 short ftrapcc_le - tbl_ftrapcc # 21
16943 short ftrapcc_gl - tbl_ftrapcc # 22
16944 short ftrapcc_gle - tbl_ftrapcc # 23
16945 short ftrapcc_ngle - tbl_ftrapcc # 24
16946 short ftrapcc_ngl - tbl_ftrapcc # 25
16947 short ftrapcc_nle - tbl_ftrapcc # 26
16948 short ftrapcc_nlt - tbl_ftrapcc # 27
16949 short ftrapcc_nge - tbl_ftrapcc # 28
16950 short ftrapcc_ngt - tbl_ftrapcc # 29
16951 short ftrapcc_sneq - tbl_ftrapcc # 30
16952 short ftrapcc_st - tbl_ftrapcc # 31
16953
16954#########################################################################
16955# #
16956# IEEE Nonaware tests #
16957# #
16958# For the IEEE nonaware tests, we set the result based on the #
16959# floating point condition codes. In addition, we check to see #
16960# if the NAN bit is set, in which case BSUN and AIOP will be set. #
16961# #
16962# The cases EQ and NE are shared by the Aware and Nonaware groups #
16963# and are incapable of setting the BSUN exception bit. #
16964# #
16965# Typically, only one of the two possible branch directions could #
16966# have the NAN bit set. #
16967# #
16968#########################################################################
16969
16970#
16971# equal:
16972#
16973# Z
16974#
16975ftrapcc_eq:
16976 fbeq.w ftrapcc_trap # equal?
16977ftrapcc_eq_no:
16978 rts # do nothing
16979
16980#
16981# not equal:
16982# _
16983# Z
16984#
16985ftrapcc_neq:
16986 fbneq.w ftrapcc_trap # not equal?
16987ftrapcc_neq_no:
16988 rts # do nothing
16989
16990#
16991# greater than:
16992# _______
16993# NANvZvN
16994#
16995ftrapcc_gt:
16996 fbgt.w ftrapcc_trap # greater than?
16997ftrapcc_gt_no:
16998 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
16999 beq.b ftrapcc_gt_done # no
17000 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17001 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17002 bne.w ftrapcc_bsun # yes
17003ftrapcc_gt_done:
17004 rts # no; do nothing
17005
17006#
17007# not greater than:
17008#
17009# NANvZvN
17010#
17011ftrapcc_ngt:
17012 fbngt.w ftrapcc_ngt_yes # not greater than?
17013ftrapcc_ngt_no:
17014 rts # do nothing
17015ftrapcc_ngt_yes:
17016 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17017 beq.w ftrapcc_trap # no; go take trap
17018 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17019 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17020 bne.w ftrapcc_bsun # yes
17021 bra.w ftrapcc_trap # no; go take trap
17022
17023#
17024# greater than or equal:
17025# _____
17026# Zv(NANvN)
17027#
17028ftrapcc_ge:
17029 fbge.w ftrapcc_ge_yes # greater than or equal?
17030ftrapcc_ge_no:
17031 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17032 beq.b ftrapcc_ge_done # no; go finish
17033 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17034 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17035 bne.w ftrapcc_bsun # yes
17036ftrapcc_ge_done:
17037 rts # no; do nothing
17038ftrapcc_ge_yes:
17039 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17040 beq.w ftrapcc_trap # no; go take trap
17041 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17042 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17043 bne.w ftrapcc_bsun # yes
17044 bra.w ftrapcc_trap # no; go take trap
17045
17046#
17047# not (greater than or equal):
17048# _
17049# NANv(N^Z)
17050#
17051ftrapcc_nge:
17052 fbnge.w ftrapcc_nge_yes # not (greater than or equal)?
17053ftrapcc_nge_no:
17054 rts # do nothing
17055ftrapcc_nge_yes:
17056 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17057 beq.w ftrapcc_trap # no; go take trap
17058 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17059 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17060 bne.w ftrapcc_bsun # yes
17061 bra.w ftrapcc_trap # no; go take trap
17062
17063#
17064# less than:
17065# _____
17066# N^(NANvZ)
17067#
17068ftrapcc_lt:
17069 fblt.w ftrapcc_trap # less than?
17070ftrapcc_lt_no:
17071 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17072 beq.b ftrapcc_lt_done # no; go finish
17073 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17074 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17075 bne.w ftrapcc_bsun # yes
17076ftrapcc_lt_done:
17077 rts # no; do nothing
17078
17079#
17080# not less than:
17081# _
17082# NANv(ZvN)
17083#
17084ftrapcc_nlt:
17085 fbnlt.w ftrapcc_nlt_yes # not less than?
17086ftrapcc_nlt_no:
17087 rts # do nothing
17088ftrapcc_nlt_yes:
17089 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17090 beq.w ftrapcc_trap # no; go take trap
17091 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17092 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17093 bne.w ftrapcc_bsun # yes
17094 bra.w ftrapcc_trap # no; go take trap
17095
17096#
17097# less than or equal:
17098# ___
17099# Zv(N^NAN)
17100#
17101ftrapcc_le:
17102 fble.w ftrapcc_le_yes # less than or equal?
17103ftrapcc_le_no:
17104 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17105 beq.b ftrapcc_le_done # no; go finish
17106 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17107 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17108 bne.w ftrapcc_bsun # yes
17109ftrapcc_le_done:
17110 rts # no; do nothing
17111ftrapcc_le_yes:
17112 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17113 beq.w ftrapcc_trap # no; go take trap
17114 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17115 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17116 bne.w ftrapcc_bsun # yes
17117 bra.w ftrapcc_trap # no; go take trap
17118
17119#
17120# not (less than or equal):
17121# ___
17122# NANv(NvZ)
17123#
17124ftrapcc_nle:
17125 fbnle.w ftrapcc_nle_yes # not (less than or equal)?
17126ftrapcc_nle_no:
17127 rts # do nothing
17128ftrapcc_nle_yes:
17129 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17130 beq.w ftrapcc_trap # no; go take trap
17131 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17132 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17133 bne.w ftrapcc_bsun # yes
17134 bra.w ftrapcc_trap # no; go take trap
17135
17136#
17137# greater or less than:
17138# _____
17139# NANvZ
17140#
17141ftrapcc_gl:
17142 fbgl.w ftrapcc_trap # greater or less than?
17143ftrapcc_gl_no:
17144 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17145 beq.b ftrapcc_gl_done # no; go finish
17146 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17147 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17148 bne.w ftrapcc_bsun # yes
17149ftrapcc_gl_done:
17150 rts # no; do nothing
17151
17152#
17153# not (greater or less than):
17154#
17155# NANvZ
17156#
17157ftrapcc_ngl:
17158 fbngl.w ftrapcc_ngl_yes # not (greater or less than)?
17159ftrapcc_ngl_no:
17160 rts # do nothing
17161ftrapcc_ngl_yes:
17162 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17163 beq.w ftrapcc_trap # no; go take trap
17164 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17165 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17166 bne.w ftrapcc_bsun # yes
17167 bra.w ftrapcc_trap # no; go take trap
17168
17169#
17170# greater, less, or equal:
17171# ___
17172# NAN
17173#
17174ftrapcc_gle:
17175 fbgle.w ftrapcc_trap # greater, less, or equal?
17176ftrapcc_gle_no:
17177 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17178 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17179 bne.w ftrapcc_bsun # yes
17180 rts # no; do nothing
17181
17182#
17183# not (greater, less, or equal):
17184#
17185# NAN
17186#
17187ftrapcc_ngle:
17188 fbngle.w ftrapcc_ngle_yes # not (greater, less, or equal)?
17189ftrapcc_ngle_no:
17190 rts # do nothing
17191ftrapcc_ngle_yes:
17192 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17193 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17194 bne.w ftrapcc_bsun # yes
17195 bra.w ftrapcc_trap # no; go take trap
17196
17197#########################################################################
17198# #
17199# Miscellaneous tests #
17200# #
17201# For the IEEE aware tests, we only have to set the result based on the #
17202# floating point condition codes. The BSUN exception will not be #
17203# set for any of these tests. #
17204# #
17205#########################################################################
17206
17207#
17208# false:
17209#
17210# False
17211#
17212ftrapcc_f:
17213 rts # do nothing
17214
17215#
17216# true:
17217#
17218# True
17219#
17220ftrapcc_t:
17221 bra.w ftrapcc_trap # go take trap
17222
17223#
17224# signalling false:
17225#
17226# False
17227#
17228ftrapcc_sf:
17229 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17230 beq.b ftrapcc_sf_done # no; go finish
17231 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17232 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17233 bne.w ftrapcc_bsun # yes
17234ftrapcc_sf_done:
17235 rts # no; do nothing
17236
17237#
17238# signalling true:
17239#
17240# True
17241#
17242ftrapcc_st:
17243 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17244 beq.w ftrapcc_trap # no; go take trap
17245 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17246 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17247 bne.w ftrapcc_bsun # yes
17248 bra.w ftrapcc_trap # no; go take trap
17249
17250#
17251# signalling equal:
17252#
17253# Z
17254#
17255ftrapcc_seq:
17256 fbseq.w ftrapcc_seq_yes # signalling equal?
17257ftrapcc_seq_no:
17258 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17259 beq.w ftrapcc_seq_done # no; go finish
17260 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17261 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17262 bne.w ftrapcc_bsun # yes
17263ftrapcc_seq_done:
17264 rts # no; do nothing
17265ftrapcc_seq_yes:
17266 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17267 beq.w ftrapcc_trap # no; go take trap
17268 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17269 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17270 bne.w ftrapcc_bsun # yes
17271 bra.w ftrapcc_trap # no; go take trap
17272
17273#
17274# signalling not equal:
17275# _
17276# Z
17277#
17278ftrapcc_sneq:
17279 fbsneq.w ftrapcc_sneq_yes # signalling equal?
17280ftrapcc_sneq_no:
17281 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17282 beq.w ftrapcc_sneq_no_done # no; go finish
17283 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17284 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17285 bne.w ftrapcc_bsun # yes
17286ftrapcc_sneq_no_done:
17287 rts # do nothing
17288ftrapcc_sneq_yes:
17289 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17290 beq.w ftrapcc_trap # no; go take trap
17291 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17292 btst &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
17293 bne.w ftrapcc_bsun # yes
17294 bra.w ftrapcc_trap # no; go take trap
17295
17296#########################################################################
17297# #
17298# IEEE Aware tests #
17299# #
17300# For the IEEE aware tests, we only have to set the result based on the #
17301# floating point condition codes. The BSUN exception will not be #
17302# set for any of these tests. #
17303# #
17304#########################################################################
17305
17306#
17307# ordered greater than:
17308# _______
17309# NANvZvN
17310#
17311ftrapcc_ogt:
17312 fbogt.w ftrapcc_trap # ordered greater than?
17313ftrapcc_ogt_no:
17314 rts # do nothing
17315
17316#
17317# unordered or less or equal:
17318# _______
17319# NANvZvN
17320#
17321ftrapcc_ule:
17322 fbule.w ftrapcc_trap # unordered or less or equal?
17323ftrapcc_ule_no:
17324 rts # do nothing
17325
17326#
17327# ordered greater than or equal:
17328# _____
17329# Zv(NANvN)
17330#
17331ftrapcc_oge:
17332 fboge.w ftrapcc_trap # ordered greater than or equal?
17333ftrapcc_oge_no:
17334 rts # do nothing
17335
17336#
17337# unordered or less than:
17338# _
17339# NANv(N^Z)
17340#
17341ftrapcc_ult:
17342 fbult.w ftrapcc_trap # unordered or less than?
17343ftrapcc_ult_no:
17344 rts # do nothing
17345
17346#
17347# ordered less than:
17348# _____
17349# N^(NANvZ)
17350#
17351ftrapcc_olt:
17352 fbolt.w ftrapcc_trap # ordered less than?
17353ftrapcc_olt_no:
17354 rts # do nothing
17355
17356#
17357# unordered or greater or equal:
17358#
17359# NANvZvN
17360#
17361ftrapcc_uge:
17362 fbuge.w ftrapcc_trap # unordered or greater than?
17363ftrapcc_uge_no:
17364 rts # do nothing
17365
17366#
17367# ordered less than or equal:
17368# ___
17369# Zv(N^NAN)
17370#
17371ftrapcc_ole:
17372 fbole.w ftrapcc_trap # ordered greater or less than?
17373ftrapcc_ole_no:
17374 rts # do nothing
17375
17376#
17377# unordered or greater than:
17378# ___
17379# NANv(NvZ)
17380#
17381ftrapcc_ugt:
17382 fbugt.w ftrapcc_trap # unordered or greater than?
17383ftrapcc_ugt_no:
17384 rts # do nothing
17385
17386#
17387# ordered greater or less than:
17388# _____
17389# NANvZ
17390#
17391ftrapcc_ogl:
17392 fbogl.w ftrapcc_trap # ordered greater or less than?
17393ftrapcc_ogl_no:
17394 rts # do nothing
17395
17396#
17397# unordered or equal:
17398#
17399# NANvZ
17400#
17401ftrapcc_ueq:
17402 fbueq.w ftrapcc_trap # unordered or equal?
17403ftrapcc_ueq_no:
17404 rts # do nothing
17405
17406#
17407# ordered:
17408# ___
17409# NAN
17410#
17411ftrapcc_or:
17412 fbor.w ftrapcc_trap # ordered?
17413ftrapcc_or_no:
17414 rts # do nothing
17415
17416#
17417# unordered:
17418#
17419# NAN
17420#
17421ftrapcc_un:
17422 fbun.w ftrapcc_trap # unordered?
17423ftrapcc_un_no:
17424 rts # do nothing
17425
17426#######################################################################
17427
17428# the bsun exception bit was not set.
17429# we will need to jump to the ftrapcc vector. the stack frame
17430# is the same size as that of the fp unimp instruction. the
17431# only difference is that the <ea> field should hold the PC
17432# of the ftrapcc instruction and the vector offset field
17433# should denote the ftrapcc trap.
17434ftrapcc_trap:
17435 mov.b &ftrapcc_flg,SPCOND_FLG(%a6)
17436 rts
17437
17438# the emulation routine set bsun and BSUN was enabled. have to
17439# fix stack and jump to the bsun handler.
17440# let the caller of this routine shift the stack frame up to
17441# eliminate the effective address field.
17442ftrapcc_bsun:
17443 mov.b &fbsun_flg,SPCOND_FLG(%a6)
17444 rts
17445
17446#########################################################################
17447# fscc(): routine to emulate the fscc instruction #
17448# #
17449# XDEF **************************************************************** #
17450# _fscc() #
17451# #
17452# XREF **************************************************************** #
17453# store_dreg_b() - store result to data register file #
17454# dec_areg() - decrement an areg for -(an) mode #
17455# inc_areg() - increment an areg for (an)+ mode #
17456# _dmem_write_byte() - store result to memory #
17457# #
17458# INPUT *************************************************************** #
17459# none #
17460# #
17461# OUTPUT ************************************************************** #
17462# none #
17463# #
17464# ALGORITHM *********************************************************** #
17465# This routine checks which conditional predicate is specified by #
17466# the stacked fscc instruction opcode and then branches to a routine #
17467# for that predicate. The corresponding fbcc instruction is then used #
17468# to see whether the condition (specified by the stacked FPSR) is true #
17469# or false. #
17470# If a BSUN exception should be indicated, the BSUN and ABSUN #
17471# bits are set in the stacked FPSR. If the BSUN exception is enabled, #
17472# the fbsun_flg is set in the SPCOND_FLG location on the stack. If an #
17473# enabled BSUN should not be flagged and the predicate is true, then #
17474# the result is stored to the data register file or memory #
17475# #
17476#########################################################################
17477
17478 global _fscc
17479_fscc:
17480 mov.w EXC_CMDREG(%a6),%d0 # fetch predicate
17481
17482 clr.l %d1 # clear scratch reg
17483 mov.b FPSR_CC(%a6),%d1 # fetch fp ccodes
17484 ror.l &0x8,%d1 # rotate to top byte
17485 fmov.l %d1,%fpsr # insert into FPSR
17486
17487 mov.w (tbl_fscc.b,%pc,%d0.w*2),%d1 # load table
17488 jmp (tbl_fscc.b,%pc,%d1.w) # jump to fscc routine
17489
17490tbl_fscc:
17491 short fscc_f - tbl_fscc # 00
17492 short fscc_eq - tbl_fscc # 01
17493 short fscc_ogt - tbl_fscc # 02
17494 short fscc_oge - tbl_fscc # 03
17495 short fscc_olt - tbl_fscc # 04
17496 short fscc_ole - tbl_fscc # 05
17497 short fscc_ogl - tbl_fscc # 06
17498 short fscc_or - tbl_fscc # 07
17499 short fscc_un - tbl_fscc # 08
17500 short fscc_ueq - tbl_fscc # 09
17501 short fscc_ugt - tbl_fscc # 10
17502 short fscc_uge - tbl_fscc # 11
17503 short fscc_ult - tbl_fscc # 12
17504 short fscc_ule - tbl_fscc # 13
17505 short fscc_neq - tbl_fscc # 14
17506 short fscc_t - tbl_fscc # 15
17507 short fscc_sf - tbl_fscc # 16
17508 short fscc_seq - tbl_fscc # 17
17509 short fscc_gt - tbl_fscc # 18
17510 short fscc_ge - tbl_fscc # 19
17511 short fscc_lt - tbl_fscc # 20
17512 short fscc_le - tbl_fscc # 21
17513 short fscc_gl - tbl_fscc # 22
17514 short fscc_gle - tbl_fscc # 23
17515 short fscc_ngle - tbl_fscc # 24
17516 short fscc_ngl - tbl_fscc # 25
17517 short fscc_nle - tbl_fscc # 26
17518 short fscc_nlt - tbl_fscc # 27
17519 short fscc_nge - tbl_fscc # 28
17520 short fscc_ngt - tbl_fscc # 29
17521 short fscc_sneq - tbl_fscc # 30
17522 short fscc_st - tbl_fscc # 31
17523
17524#########################################################################
17525# #
17526# IEEE Nonaware tests #
17527# #
17528# For the IEEE nonaware tests, we set the result based on the #
17529# floating point condition codes. In addition, we check to see #
17530# if the NAN bit is set, in which case BSUN and AIOP will be set. #
17531# #
17532# The cases EQ and NE are shared by the Aware and Nonaware groups #
17533# and are incapable of setting the BSUN exception bit. #
17534# #
17535# Typically, only one of the two possible branch directions could #
17536# have the NAN bit set. #
17537# #
17538#########################################################################
17539
17540#
17541# equal:
17542#
17543# Z
17544#
17545fscc_eq:
17546 fbeq.w fscc_eq_yes # equal?
17547fscc_eq_no:
17548 clr.b %d0 # set false
17549 bra.w fscc_done # go finish
17550fscc_eq_yes:
17551 st %d0 # set true
17552 bra.w fscc_done # go finish
17553
17554#
17555# not equal:
17556# _
17557# Z
17558#
17559fscc_neq:
17560 fbneq.w fscc_neq_yes # not equal?
17561fscc_neq_no:
17562 clr.b %d0 # set false
17563 bra.w fscc_done # go finish
17564fscc_neq_yes:
17565 st %d0 # set true
17566 bra.w fscc_done # go finish
17567
17568#
17569# greater than:
17570# _______
17571# NANvZvN
17572#
17573fscc_gt:
17574 fbgt.w fscc_gt_yes # greater than?
17575fscc_gt_no:
17576 clr.b %d0 # set false
17577 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17578 beq.w fscc_done # no;go finish
17579 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17580 bra.w fscc_chk_bsun # go finish
17581fscc_gt_yes:
17582 st %d0 # set true
17583 bra.w fscc_done # go finish
17584
17585#
17586# not greater than:
17587#
17588# NANvZvN
17589#
17590fscc_ngt:
17591 fbngt.w fscc_ngt_yes # not greater than?
17592fscc_ngt_no:
17593 clr.b %d0 # set false
17594 bra.w fscc_done # go finish
17595fscc_ngt_yes:
17596 st %d0 # set true
17597 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17598 beq.w fscc_done # no;go finish
17599 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17600 bra.w fscc_chk_bsun # go finish
17601
17602#
17603# greater than or equal:
17604# _____
17605# Zv(NANvN)
17606#
17607fscc_ge:
17608 fbge.w fscc_ge_yes # greater than or equal?
17609fscc_ge_no:
17610 clr.b %d0 # set false
17611 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17612 beq.w fscc_done # no;go finish
17613 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17614 bra.w fscc_chk_bsun # go finish
17615fscc_ge_yes:
17616 st %d0 # set true
17617 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17618 beq.w fscc_done # no;go finish
17619 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17620 bra.w fscc_chk_bsun # go finish
17621
17622#
17623# not (greater than or equal):
17624# _
17625# NANv(N^Z)
17626#
17627fscc_nge:
17628 fbnge.w fscc_nge_yes # not (greater than or equal)?
17629fscc_nge_no:
17630 clr.b %d0 # set false
17631 bra.w fscc_done # go finish
17632fscc_nge_yes:
17633 st %d0 # set true
17634 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17635 beq.w fscc_done # no;go finish
17636 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17637 bra.w fscc_chk_bsun # go finish
17638
17639#
17640# less than:
17641# _____
17642# N^(NANvZ)
17643#
17644fscc_lt:
17645 fblt.w fscc_lt_yes # less than?
17646fscc_lt_no:
17647 clr.b %d0 # set false
17648 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17649 beq.w fscc_done # no;go finish
17650 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17651 bra.w fscc_chk_bsun # go finish
17652fscc_lt_yes:
17653 st %d0 # set true
17654 bra.w fscc_done # go finish
17655
17656#
17657# not less than:
17658# _
17659# NANv(ZvN)
17660#
17661fscc_nlt:
17662 fbnlt.w fscc_nlt_yes # not less than?
17663fscc_nlt_no:
17664 clr.b %d0 # set false
17665 bra.w fscc_done # go finish
17666fscc_nlt_yes:
17667 st %d0 # set true
17668 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17669 beq.w fscc_done # no;go finish
17670 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17671 bra.w fscc_chk_bsun # go finish
17672
17673#
17674# less than or equal:
17675# ___
17676# Zv(N^NAN)
17677#
17678fscc_le:
17679 fble.w fscc_le_yes # less than or equal?
17680fscc_le_no:
17681 clr.b %d0 # set false
17682 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17683 beq.w fscc_done # no;go finish
17684 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17685 bra.w fscc_chk_bsun # go finish
17686fscc_le_yes:
17687 st %d0 # set true
17688 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17689 beq.w fscc_done # no;go finish
17690 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17691 bra.w fscc_chk_bsun # go finish
17692
17693#
17694# not (less than or equal):
17695# ___
17696# NANv(NvZ)
17697#
17698fscc_nle:
17699 fbnle.w fscc_nle_yes # not (less than or equal)?
17700fscc_nle_no:
17701 clr.b %d0 # set false
17702 bra.w fscc_done # go finish
17703fscc_nle_yes:
17704 st %d0 # set true
17705 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17706 beq.w fscc_done # no;go finish
17707 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17708 bra.w fscc_chk_bsun # go finish
17709
17710#
17711# greater or less than:
17712# _____
17713# NANvZ
17714#
17715fscc_gl:
17716 fbgl.w fscc_gl_yes # greater or less than?
17717fscc_gl_no:
17718 clr.b %d0 # set false
17719 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17720 beq.w fscc_done # no;go finish
17721 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17722 bra.w fscc_chk_bsun # go finish
17723fscc_gl_yes:
17724 st %d0 # set true
17725 bra.w fscc_done # go finish
17726
17727#
17728# not (greater or less than):
17729#
17730# NANvZ
17731#
17732fscc_ngl:
17733 fbngl.w fscc_ngl_yes # not (greater or less than)?
17734fscc_ngl_no:
17735 clr.b %d0 # set false
17736 bra.w fscc_done # go finish
17737fscc_ngl_yes:
17738 st %d0 # set true
17739 btst &nan_bit, FPSR_CC(%a6) # is NAN set in cc?
17740 beq.w fscc_done # no;go finish
17741 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17742 bra.w fscc_chk_bsun # go finish
17743
17744#
17745# greater, less, or equal:
17746# ___
17747# NAN
17748#
17749fscc_gle:
17750 fbgle.w fscc_gle_yes # greater, less, or equal?
17751fscc_gle_no:
17752 clr.b %d0 # set false
17753 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17754 bra.w fscc_chk_bsun # go finish
17755fscc_gle_yes:
17756 st %d0 # set true
17757 bra.w fscc_done # go finish
17758
17759#
17760# not (greater, less, or equal):
17761#
17762# NAN
17763#
17764fscc_ngle:
17765 fbngle.w fscc_ngle_yes # not (greater, less, or equal)?
17766fscc_ngle_no:
17767 clr.b %d0 # set false
17768 bra.w fscc_done # go finish
17769fscc_ngle_yes:
17770 st %d0 # set true
17771 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17772 bra.w fscc_chk_bsun # go finish
17773
17774#########################################################################
17775# #
17776# Miscellaneous tests #
17777# #
17778# For the IEEE aware tests, we only have to set the result based on the #
17779# floating point condition codes. The BSUN exception will not be #
17780# set for any of these tests. #
17781# #
17782#########################################################################
17783
17784#
17785# false:
17786#
17787# False
17788#
17789fscc_f:
17790 clr.b %d0 # set false
17791 bra.w fscc_done # go finish
17792
17793#
17794# true:
17795#
17796# True
17797#
17798fscc_t:
17799 st %d0 # set true
17800 bra.w fscc_done # go finish
17801
17802#
17803# signalling false:
17804#
17805# False
17806#
17807fscc_sf:
17808 clr.b %d0 # set false
17809 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17810 beq.w fscc_done # no;go finish
17811 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17812 bra.w fscc_chk_bsun # go finish
17813
17814#
17815# signalling true:
17816#
17817# True
17818#
17819fscc_st:
17820 st %d0 # set false
17821 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17822 beq.w fscc_done # no;go finish
17823 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17824 bra.w fscc_chk_bsun # go finish
17825
17826#
17827# signalling equal:
17828#
17829# Z
17830#
17831fscc_seq:
17832 fbseq.w fscc_seq_yes # signalling equal?
17833fscc_seq_no:
17834 clr.b %d0 # set false
17835 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17836 beq.w fscc_done # no;go finish
17837 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17838 bra.w fscc_chk_bsun # go finish
17839fscc_seq_yes:
17840 st %d0 # set true
17841 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17842 beq.w fscc_done # no;go finish
17843 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17844 bra.w fscc_chk_bsun # go finish
17845
17846#
17847# signalling not equal:
17848# _
17849# Z
17850#
17851fscc_sneq:
17852 fbsneq.w fscc_sneq_yes # signalling equal?
17853fscc_sneq_no:
17854 clr.b %d0 # set false
17855 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17856 beq.w fscc_done # no;go finish
17857 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17858 bra.w fscc_chk_bsun # go finish
17859fscc_sneq_yes:
17860 st %d0 # set true
17861 btst &nan_bit, FPSR_CC(%a6) # set BSUN exc bit
17862 beq.w fscc_done # no;go finish
17863 ori.l &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
17864 bra.w fscc_chk_bsun # go finish
17865
17866#########################################################################
17867# #
17868# IEEE Aware tests #
17869# #
17870# For the IEEE aware tests, we only have to set the result based on the #
17871# floating point condition codes. The BSUN exception will not be #
17872# set for any of these tests. #
17873# #
17874#########################################################################
17875
17876#
17877# ordered greater than:
17878# _______
17879# NANvZvN
17880#
17881fscc_ogt:
17882 fbogt.w fscc_ogt_yes # ordered greater than?
17883fscc_ogt_no:
17884 clr.b %d0 # set false
17885 bra.w fscc_done # go finish
17886fscc_ogt_yes:
17887 st %d0 # set true
17888 bra.w fscc_done # go finish
17889
17890#
17891# unordered or less or equal:
17892# _______
17893# NANvZvN
17894#
17895fscc_ule:
17896 fbule.w fscc_ule_yes # unordered or less or equal?
17897fscc_ule_no:
17898 clr.b %d0 # set false
17899 bra.w fscc_done # go finish
17900fscc_ule_yes:
17901 st %d0 # set true
17902 bra.w fscc_done # go finish
17903
17904#
17905# ordered greater than or equal:
17906# _____
17907# Zv(NANvN)
17908#
17909fscc_oge:
17910 fboge.w fscc_oge_yes # ordered greater than or equal?
17911fscc_oge_no:
17912 clr.b %d0 # set false
17913 bra.w fscc_done # go finish
17914fscc_oge_yes:
17915 st %d0 # set true
17916 bra.w fscc_done # go finish
17917
17918#
17919# unordered or less than:
17920# _
17921# NANv(N^Z)
17922#
17923fscc_ult:
17924 fbult.w fscc_ult_yes # unordered or less than?
17925fscc_ult_no:
17926 clr.b %d0 # set false
17927 bra.w fscc_done # go finish
17928fscc_ult_yes:
17929 st %d0 # set true
17930 bra.w fscc_done # go finish
17931
17932#
17933# ordered less than:
17934# _____
17935# N^(NANvZ)
17936#
17937fscc_olt:
17938 fbolt.w fscc_olt_yes # ordered less than?
17939fscc_olt_no:
17940 clr.b %d0 # set false
17941 bra.w fscc_done # go finish
17942fscc_olt_yes:
17943 st %d0 # set true
17944 bra.w fscc_done # go finish
17945
17946#
17947# unordered or greater or equal:
17948#
17949# NANvZvN
17950#
17951fscc_uge:
17952 fbuge.w fscc_uge_yes # unordered or greater than?
17953fscc_uge_no:
17954 clr.b %d0 # set false
17955 bra.w fscc_done # go finish
17956fscc_uge_yes:
17957 st %d0 # set true
17958 bra.w fscc_done # go finish
17959
17960#
17961# ordered less than or equal:
17962# ___
17963# Zv(N^NAN)
17964#
17965fscc_ole:
17966 fbole.w fscc_ole_yes # ordered greater or less than?
17967fscc_ole_no:
17968 clr.b %d0 # set false
17969 bra.w fscc_done # go finish
17970fscc_ole_yes:
17971 st %d0 # set true
17972 bra.w fscc_done # go finish
17973
17974#
17975# unordered or greater than:
17976# ___
17977# NANv(NvZ)
17978#
17979fscc_ugt:
17980 fbugt.w fscc_ugt_yes # unordered or greater than?
17981fscc_ugt_no:
17982 clr.b %d0 # set false
17983 bra.w fscc_done # go finish
17984fscc_ugt_yes:
17985 st %d0 # set true
17986 bra.w fscc_done # go finish
17987
17988#
17989# ordered greater or less than:
17990# _____
17991# NANvZ
17992#
17993fscc_ogl:
17994 fbogl.w fscc_ogl_yes # ordered greater or less than?
17995fscc_ogl_no:
17996 clr.b %d0 # set false
17997 bra.w fscc_done # go finish
17998fscc_ogl_yes:
17999 st %d0 # set true
18000 bra.w fscc_done # go finish
18001
18002#
18003# unordered or equal:
18004#
18005# NANvZ
18006#
18007fscc_ueq:
18008 fbueq.w fscc_ueq_yes # unordered or equal?
18009fscc_ueq_no:
18010 clr.b %d0 # set false
18011 bra.w fscc_done # go finish
18012fscc_ueq_yes:
18013 st %d0 # set true
18014 bra.w fscc_done # go finish
18015
18016#
18017# ordered:
18018# ___
18019# NAN
18020#
18021fscc_or:
18022 fbor.w fscc_or_yes # ordered?
18023fscc_or_no:
18024 clr.b %d0 # set false
18025 bra.w fscc_done # go finish
18026fscc_or_yes:
18027 st %d0 # set true
18028 bra.w fscc_done # go finish
18029
18030#
18031# unordered:
18032#
18033# NAN
18034#
18035fscc_un:
18036 fbun.w fscc_un_yes # unordered?
18037fscc_un_no:
18038 clr.b %d0 # set false
18039 bra.w fscc_done # go finish
18040fscc_un_yes:
18041 st %d0 # set true
18042 bra.w fscc_done # go finish
18043
18044#######################################################################
18045
18046#
18047# the bsun exception bit was set. now, check to see is BSUN
18048# is enabled. if so, don't store result and correct stack frame
18049# for a bsun exception.
18050#
18051fscc_chk_bsun:
18052 btst &bsun_bit,FPCR_ENABLE(%a6) # was BSUN set?
18053 bne.w fscc_bsun
18054
18055#
18056# the bsun exception bit was not set.
18057# the result has been selected.
18058# now, check to see if the result is to be stored in the data register
18059# file or in memory.
18060#
18061fscc_done:
18062 mov.l %d0,%a0 # save result for a moment
18063
18064 mov.b 1+EXC_OPWORD(%a6),%d1 # fetch lo opword
18065 mov.l %d1,%d0 # make a copy
18066 andi.b &0x38,%d1 # extract src mode
18067
18068 bne.b fscc_mem_op # it's a memory operation
18069
18070 mov.l %d0,%d1
18071 andi.w &0x7,%d1 # pass index in d1
18072 mov.l %a0,%d0 # pass result in d0
18073 bsr.l store_dreg_b # save result in regfile
18074 rts
18075
18076#
18077# the stacked <ea> is correct with the exception of:
18078# -> Dn : <ea> is garbage
18079#
18080# if the addressing mode is post-increment or pre-decrement,
18081# then the address registers have not been updated.
18082#
18083fscc_mem_op:
18084 cmpi.b %d1,&0x18 # is <ea> (An)+ ?
18085 beq.b fscc_mem_inc # yes
18086 cmpi.b %d1,&0x20 # is <ea> -(An) ?
18087 beq.b fscc_mem_dec # yes
18088
18089 mov.l %a0,%d0 # pass result in d0
18090 mov.l EXC_EA(%a6),%a0 # fetch <ea>
18091 bsr.l _dmem_write_byte # write result byte
18092
18093 tst.l %d1 # did dstore fail?
18094 bne.w fscc_err # yes
18095
18096 rts
18097
18098# addresing mode is post-increment. write the result byte. if the write
18099# fails then don't update the address register. if write passes then
18100# call inc_areg() to update the address register.
18101fscc_mem_inc:
18102 mov.l %a0,%d0 # pass result in d0
18103 mov.l EXC_EA(%a6),%a0 # fetch <ea>
18104 bsr.l _dmem_write_byte # write result byte
18105
18106 tst.l %d1 # did dstore fail?
18107 bne.w fscc_err # yes
18108
18109 mov.b 0x1+EXC_OPWORD(%a6),%d1 # fetch opword
18110 andi.w &0x7,%d1 # pass index in d1
18111 movq.l &0x1,%d0 # pass amt to inc by
18112 bsr.l inc_areg # increment address register
18113
18114 rts
18115
18116# addressing mode is pre-decrement. write the result byte. if the write
18117# fails then don't update the address register. if the write passes then
18118# call dec_areg() to update the address register.
18119fscc_mem_dec:
18120 mov.l %a0,%d0 # pass result in d0
18121 mov.l EXC_EA(%a6),%a0 # fetch <ea>
18122 bsr.l _dmem_write_byte # write result byte
18123
18124 tst.l %d1 # did dstore fail?
18125 bne.w fscc_err # yes
18126
18127 mov.b 0x1+EXC_OPWORD(%a6),%d1 # fetch opword
18128 andi.w &0x7,%d1 # pass index in d1
18129 movq.l &0x1,%d0 # pass amt to dec by
18130 bsr.l dec_areg # decrement address register
18131
18132 rts
18133
18134# the emulation routine set bsun and BSUN was enabled. have to
18135# fix stack and jump to the bsun handler.
18136# let the caller of this routine shift the stack frame up to
18137# eliminate the effective address field.
18138fscc_bsun:
18139 mov.b &fbsun_flg,SPCOND_FLG(%a6)
18140 rts
18141
18142# the byte write to memory has failed. pass the failing effective address
18143# and a FSLW to funimp_dacc().
18144fscc_err:
18145 mov.w &0x00a1,EXC_VOFF(%a6)
18146 bra.l facc_finish
18147
18148#########################################################################
18149# XDEF **************************************************************** #
18150# fmovm_dynamic(): emulate "fmovm" dynamic instruction #
18151# #
18152# XREF **************************************************************** #
18153# fetch_dreg() - fetch data register #
18154# {i,d,}mem_read() - fetch data from memory #
18155# _mem_write() - write data to memory #
18156# iea_iacc() - instruction memory access error occurred #
18157# iea_dacc() - data memory access error occurred #
18158# restore() - restore An index regs if access error occurred #
18159# #
18160# INPUT *************************************************************** #
18161# None #
18162# #
18163# OUTPUT ************************************************************** #
18164# If instr is "fmovm Dn,-(A7)" from supervisor mode, #
18165# d0 = size of dump #
18166# d1 = Dn #
18167# Else if instruction access error, #
18168# d0 = FSLW #
18169# Else if data access error, #
18170# d0 = FSLW #
18171# a0 = address of fault #
18172# Else #
18173# none. #
18174# #
18175# ALGORITHM *********************************************************** #
18176# The effective address must be calculated since this is entered #
18177# from an "Unimplemented Effective Address" exception handler. So, we #
18178# have our own fcalc_ea() routine here. If an access error is flagged #
18179# by a _{i,d,}mem_read() call, we must exit through the special #
18180# handler. #
18181# The data register is determined and its value loaded to get the #
18182# string of FP registers affected. This value is used as an index into #
18183# a lookup table such that we can determine the number of bytes #
18184# involved. #
18185# If the instruction is "fmovm.x <ea>,Dn", a _mem_read() is used #
18186# to read in all FP values. Again, _mem_read() may fail and require a #
18187# special exit. #
18188# If the instruction is "fmovm.x DN,<ea>", a _mem_write() is used #
18189# to write all FP values. _mem_write() may also fail. #
18190# If the instruction is "fmovm.x DN,-(a7)" from supervisor mode, #
18191# then we return the size of the dump and the string to the caller #
18192# so that the move can occur outside of this routine. This special #
18193# case is required so that moves to the system stack are handled #
18194# correctly. #
18195# #
18196# DYNAMIC: #
18197# fmovm.x dn, <ea> #
18198# fmovm.x <ea>, dn #
18199# #
18200# <WORD 1> <WORD2> #
18201# 1111 0010 00 |<ea>| 11@& 1000 0$$$ 0000 #
18202# #
18203# & = (0): predecrement addressing mode #
18204# (1): postincrement or control addressing mode #
18205# @ = (0): move listed regs from memory to the FPU #
18206# (1): move listed regs from the FPU to memory #
18207# $$$ : index of data register holding reg select mask #
18208# #
18209# NOTES: #
18210# If the data register holds a zero, then the #
18211# instruction is a nop. #
18212# #
18213#########################################################################
18214
18215 global fmovm_dynamic
18216fmovm_dynamic:
18217
18218# extract the data register in which the bit string resides...
18219 mov.b 1+EXC_EXTWORD(%a6),%d1 # fetch extword
18220 andi.w &0x70,%d1 # extract reg bits
18221 lsr.b &0x4,%d1 # shift into lo bits
18222
18223# fetch the bit string into d0...
18224 bsr.l fetch_dreg # fetch reg string
18225
18226 andi.l &0x000000ff,%d0 # keep only lo byte
18227
18228 mov.l %d0,-(%sp) # save strg
18229 mov.b (tbl_fmovm_size.w,%pc,%d0),%d0
18230 mov.l %d0,-(%sp) # save size
18231 bsr.l fmovm_calc_ea # calculate <ea>
18232 mov.l (%sp)+,%d0 # restore size
18233 mov.l (%sp)+,%d1 # restore strg
18234
18235# if the bit string is a zero, then the operation is a no-op
18236# but, make sure that we've calculated ea and advanced the opword pointer
18237 beq.w fmovm_data_done
18238
18239# separate move ins from move outs...
18240 btst &0x5,EXC_EXTWORD(%a6) # is it a move in or out?
18241 beq.w fmovm_data_in # it's a move out
18242
18243#############
18244# MOVE OUT: #
18245#############
18246fmovm_data_out:
18247 btst &0x4,EXC_EXTWORD(%a6) # control or predecrement?
18248 bne.w fmovm_out_ctrl # control
18249
18250############################
18251fmovm_out_predec:
18252# for predecrement mode, the bit string is the opposite of both control
18253# operations and postincrement mode. (bit7 = FP7 ... bit0 = FP0)
18254# here, we convert it to be just like the others...
18255 mov.b (tbl_fmovm_convert.w,%pc,%d1.w*1),%d1
18256
18257 btst &0x5,EXC_SR(%a6) # user or supervisor mode?
18258 beq.b fmovm_out_ctrl # user
18259
18260fmovm_out_predec_s:
18261 cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
18262 bne.b fmovm_out_ctrl
18263
18264# the operation was unfortunately an: fmovm.x dn,-(sp)
18265# called from supervisor mode.
18266# we're also passing "size" and "strg" back to the calling routine
18267 rts
18268
18269############################
18270fmovm_out_ctrl:
18271 mov.l %a0,%a1 # move <ea> to a1
18272
18273 sub.l %d0,%sp # subtract size of dump
18274 lea (%sp),%a0
18275
18276 tst.b %d1 # should FP0 be moved?
18277 bpl.b fmovm_out_ctrl_fp1 # no
18278
18279 mov.l 0x0+EXC_FP0(%a6),(%a0)+ # yes
18280 mov.l 0x4+EXC_FP0(%a6),(%a0)+
18281 mov.l 0x8+EXC_FP0(%a6),(%a0)+
18282
18283fmovm_out_ctrl_fp1:
18284 lsl.b &0x1,%d1 # should FP1 be moved?
18285 bpl.b fmovm_out_ctrl_fp2 # no
18286
18287 mov.l 0x0+EXC_FP1(%a6),(%a0)+ # yes
18288 mov.l 0x4+EXC_FP1(%a6),(%a0)+
18289 mov.l 0x8+EXC_FP1(%a6),(%a0)+
18290
18291fmovm_out_ctrl_fp2:
18292 lsl.b &0x1,%d1 # should FP2 be moved?
18293 bpl.b fmovm_out_ctrl_fp3 # no
18294
18295 fmovm.x &0x20,(%a0) # yes
18296 add.l &0xc,%a0
18297
18298fmovm_out_ctrl_fp3:
18299 lsl.b &0x1,%d1 # should FP3 be moved?
18300 bpl.b fmovm_out_ctrl_fp4 # no
18301
18302 fmovm.x &0x10,(%a0) # yes
18303 add.l &0xc,%a0
18304
18305fmovm_out_ctrl_fp4:
18306 lsl.b &0x1,%d1 # should FP4 be moved?
18307 bpl.b fmovm_out_ctrl_fp5 # no
18308
18309 fmovm.x &0x08,(%a0) # yes
18310 add.l &0xc,%a0
18311
18312fmovm_out_ctrl_fp5:
18313 lsl.b &0x1,%d1 # should FP5 be moved?
18314 bpl.b fmovm_out_ctrl_fp6 # no
18315
18316 fmovm.x &0x04,(%a0) # yes
18317 add.l &0xc,%a0
18318
18319fmovm_out_ctrl_fp6:
18320 lsl.b &0x1,%d1 # should FP6 be moved?
18321 bpl.b fmovm_out_ctrl_fp7 # no
18322
18323 fmovm.x &0x02,(%a0) # yes
18324 add.l &0xc,%a0
18325
18326fmovm_out_ctrl_fp7:
18327 lsl.b &0x1,%d1 # should FP7 be moved?
18328 bpl.b fmovm_out_ctrl_done # no
18329
18330 fmovm.x &0x01,(%a0) # yes
18331 add.l &0xc,%a0
18332
18333fmovm_out_ctrl_done:
18334 mov.l %a1,L_SCR1(%a6)
18335
18336 lea (%sp),%a0 # pass: supervisor src
18337 mov.l %d0,-(%sp) # save size
18338 bsr.l _dmem_write # copy data to user mem
18339
18340 mov.l (%sp)+,%d0
18341 add.l %d0,%sp # clear fpreg data from stack
18342
18343 tst.l %d1 # did dstore err?
18344 bne.w fmovm_out_err # yes
18345
18346 rts
18347
18348############
18349# MOVE IN: #
18350############
18351fmovm_data_in:
18352 mov.l %a0,L_SCR1(%a6)
18353
18354 sub.l %d0,%sp # make room for fpregs
18355 lea (%sp),%a1
18356
18357 mov.l %d1,-(%sp) # save bit string for later
18358 mov.l %d0,-(%sp) # save # of bytes
18359
18360 bsr.l _dmem_read # copy data from user mem
18361
18362 mov.l (%sp)+,%d0 # retrieve # of bytes
18363
18364 tst.l %d1 # did dfetch fail?
18365 bne.w fmovm_in_err # yes
18366
18367 mov.l (%sp)+,%d1 # load bit string
18368
18369 lea (%sp),%a0 # addr of stack
18370
18371 tst.b %d1 # should FP0 be moved?
18372 bpl.b fmovm_data_in_fp1 # no
18373
18374 mov.l (%a0)+,0x0+EXC_FP0(%a6) # yes
18375 mov.l (%a0)+,0x4+EXC_FP0(%a6)
18376 mov.l (%a0)+,0x8+EXC_FP0(%a6)
18377
18378fmovm_data_in_fp1:
18379 lsl.b &0x1,%d1 # should FP1 be moved?
18380 bpl.b fmovm_data_in_fp2 # no
18381
18382 mov.l (%a0)+,0x0+EXC_FP1(%a6) # yes
18383 mov.l (%a0)+,0x4+EXC_FP1(%a6)
18384 mov.l (%a0)+,0x8+EXC_FP1(%a6)
18385
18386fmovm_data_in_fp2:
18387 lsl.b &0x1,%d1 # should FP2 be moved?
18388 bpl.b fmovm_data_in_fp3 # no
18389
18390 fmovm.x (%a0)+,&0x20 # yes
18391
18392fmovm_data_in_fp3:
18393 lsl.b &0x1,%d1 # should FP3 be moved?
18394 bpl.b fmovm_data_in_fp4 # no
18395
18396 fmovm.x (%a0)+,&0x10 # yes
18397
18398fmovm_data_in_fp4:
18399 lsl.b &0x1,%d1 # should FP4 be moved?
18400 bpl.b fmovm_data_in_fp5 # no
18401
18402 fmovm.x (%a0)+,&0x08 # yes
18403
18404fmovm_data_in_fp5:
18405 lsl.b &0x1,%d1 # should FP5 be moved?
18406 bpl.b fmovm_data_in_fp6 # no
18407
18408 fmovm.x (%a0)+,&0x04 # yes
18409
18410fmovm_data_in_fp6:
18411 lsl.b &0x1,%d1 # should FP6 be moved?
18412 bpl.b fmovm_data_in_fp7 # no
18413
18414 fmovm.x (%a0)+,&0x02 # yes
18415
18416fmovm_data_in_fp7:
18417 lsl.b &0x1,%d1 # should FP7 be moved?
18418 bpl.b fmovm_data_in_done # no
18419
18420 fmovm.x (%a0)+,&0x01 # yes
18421
18422fmovm_data_in_done:
18423 add.l %d0,%sp # remove fpregs from stack
18424 rts
18425
18426#####################################
18427
18428fmovm_data_done:
18429 rts
18430
18431##############################################################################
18432
18433#
18434# table indexed by the operation's bit string that gives the number
18435# of bytes that will be moved.
18436#
18437# number of bytes = (# of 1's in bit string) * 12(bytes/fpreg)
18438#
18439tbl_fmovm_size:
18440 byte 0x00,0x0c,0x0c,0x18,0x0c,0x18,0x18,0x24
18441 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
18442 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
18443 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18444 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
18445 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18446 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18447 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18448 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
18449 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18450 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18451 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18452 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18453 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18454 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18455 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
18456 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
18457 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18458 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18459 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18460 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18461 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18462 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18463 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
18464 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
18465 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18466 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18467 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
18468 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
18469 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
18470 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
18471 byte 0x3c,0x48,0x48,0x54,0x48,0x54,0x54,0x60
18472
18473#
18474# table to convert a pre-decrement bit string into a post-increment
18475# or control bit string.
18476# ex: 0x00 ==> 0x00
18477# 0x01 ==> 0x80
18478# 0x02 ==> 0x40
18479# .
18480# .
18481# 0xfd ==> 0xbf
18482# 0xfe ==> 0x7f
18483# 0xff ==> 0xff
18484#
18485tbl_fmovm_convert:
18486 byte 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0
18487 byte 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0
18488 byte 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8
18489 byte 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8
18490 byte 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4
18491 byte 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4
18492 byte 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec
18493 byte 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc
18494 byte 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2
18495 byte 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2
18496 byte 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea
18497 byte 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa
18498 byte 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6
18499 byte 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6
18500 byte 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee
18501 byte 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe
18502 byte 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1
18503 byte 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1
18504 byte 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9
18505 byte 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9
18506 byte 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5
18507 byte 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5
18508 byte 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed
18509 byte 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd
18510 byte 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3
18511 byte 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3
18512 byte 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb
18513 byte 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb
18514 byte 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7
18515 byte 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7
18516 byte 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef
18517 byte 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
18518
18519 global fmovm_calc_ea
18520###############################################
18521# _fmovm_calc_ea: calculate effective address #
18522###############################################
18523fmovm_calc_ea:
18524 mov.l %d0,%a0 # move # bytes to a0
18525
18526# currently, MODE and REG are taken from the EXC_OPWORD. this could be
18527# easily changed if they were inputs passed in registers.
18528 mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word
18529 mov.w %d0,%d1 # make a copy
18530
18531 andi.w &0x3f,%d0 # extract mode field
18532 andi.l &0x7,%d1 # extract reg field
18533
18534# jump to the corresponding function for each {MODE,REG} pair.
18535 mov.w (tbl_fea_mode.b,%pc,%d0.w*2),%d0 # fetch jmp distance
18536 jmp (tbl_fea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
18537
18538 swbeg &64
18539tbl_fea_mode:
18540 short tbl_fea_mode - tbl_fea_mode
18541 short tbl_fea_mode - tbl_fea_mode
18542 short tbl_fea_mode - tbl_fea_mode
18543 short tbl_fea_mode - tbl_fea_mode
18544 short tbl_fea_mode - tbl_fea_mode
18545 short tbl_fea_mode - tbl_fea_mode
18546 short tbl_fea_mode - tbl_fea_mode
18547 short tbl_fea_mode - tbl_fea_mode
18548
18549 short tbl_fea_mode - tbl_fea_mode
18550 short tbl_fea_mode - tbl_fea_mode
18551 short tbl_fea_mode - tbl_fea_mode
18552 short tbl_fea_mode - tbl_fea_mode
18553 short tbl_fea_mode - tbl_fea_mode
18554 short tbl_fea_mode - tbl_fea_mode
18555 short tbl_fea_mode - tbl_fea_mode
18556 short tbl_fea_mode - tbl_fea_mode
18557
18558 short faddr_ind_a0 - tbl_fea_mode
18559 short faddr_ind_a1 - tbl_fea_mode
18560 short faddr_ind_a2 - tbl_fea_mode
18561 short faddr_ind_a3 - tbl_fea_mode
18562 short faddr_ind_a4 - tbl_fea_mode
18563 short faddr_ind_a5 - tbl_fea_mode
18564 short faddr_ind_a6 - tbl_fea_mode
18565 short faddr_ind_a7 - tbl_fea_mode
18566
18567 short faddr_ind_p_a0 - tbl_fea_mode
18568 short faddr_ind_p_a1 - tbl_fea_mode
18569 short faddr_ind_p_a2 - tbl_fea_mode
18570 short faddr_ind_p_a3 - tbl_fea_mode
18571 short faddr_ind_p_a4 - tbl_fea_mode
18572 short faddr_ind_p_a5 - tbl_fea_mode
18573 short faddr_ind_p_a6 - tbl_fea_mode
18574 short faddr_ind_p_a7 - tbl_fea_mode
18575
18576 short faddr_ind_m_a0 - tbl_fea_mode
18577 short faddr_ind_m_a1 - tbl_fea_mode
18578 short faddr_ind_m_a2 - tbl_fea_mode
18579 short faddr_ind_m_a3 - tbl_fea_mode
18580 short faddr_ind_m_a4 - tbl_fea_mode
18581 short faddr_ind_m_a5 - tbl_fea_mode
18582 short faddr_ind_m_a6 - tbl_fea_mode
18583 short faddr_ind_m_a7 - tbl_fea_mode
18584
18585 short faddr_ind_disp_a0 - tbl_fea_mode
18586 short faddr_ind_disp_a1 - tbl_fea_mode
18587 short faddr_ind_disp_a2 - tbl_fea_mode
18588 short faddr_ind_disp_a3 - tbl_fea_mode
18589 short faddr_ind_disp_a4 - tbl_fea_mode
18590 short faddr_ind_disp_a5 - tbl_fea_mode
18591 short faddr_ind_disp_a6 - tbl_fea_mode
18592 short faddr_ind_disp_a7 - tbl_fea_mode
18593
18594 short faddr_ind_ext - tbl_fea_mode
18595 short faddr_ind_ext - tbl_fea_mode
18596 short faddr_ind_ext - tbl_fea_mode
18597 short faddr_ind_ext - tbl_fea_mode
18598 short faddr_ind_ext - tbl_fea_mode
18599 short faddr_ind_ext - tbl_fea_mode
18600 short faddr_ind_ext - tbl_fea_mode
18601 short faddr_ind_ext - tbl_fea_mode
18602
18603 short fabs_short - tbl_fea_mode
18604 short fabs_long - tbl_fea_mode
18605 short fpc_ind - tbl_fea_mode
18606 short fpc_ind_ext - tbl_fea_mode
18607 short tbl_fea_mode - tbl_fea_mode
18608 short tbl_fea_mode - tbl_fea_mode
18609 short tbl_fea_mode - tbl_fea_mode
18610 short tbl_fea_mode - tbl_fea_mode
18611
18612###################################
18613# Address register indirect: (An) #
18614###################################
18615faddr_ind_a0:
18616 mov.l EXC_DREGS+0x8(%a6),%a0 # Get current a0
18617 rts
18618
18619faddr_ind_a1:
18620 mov.l EXC_DREGS+0xc(%a6),%a0 # Get current a1
18621 rts
18622
18623faddr_ind_a2:
18624 mov.l %a2,%a0 # Get current a2
18625 rts
18626
18627faddr_ind_a3:
18628 mov.l %a3,%a0 # Get current a3
18629 rts
18630
18631faddr_ind_a4:
18632 mov.l %a4,%a0 # Get current a4
18633 rts
18634
18635faddr_ind_a5:
18636 mov.l %a5,%a0 # Get current a5
18637 rts
18638
18639faddr_ind_a6:
18640 mov.l (%a6),%a0 # Get current a6
18641 rts
18642
18643faddr_ind_a7:
18644 mov.l EXC_A7(%a6),%a0 # Get current a7
18645 rts
18646
18647#####################################################
18648# Address register indirect w/ postincrement: (An)+ #
18649#####################################################
18650faddr_ind_p_a0:
18651 mov.l EXC_DREGS+0x8(%a6),%d0 # Get current a0
18652 mov.l %d0,%d1
18653 add.l %a0,%d1 # Increment
18654 mov.l %d1,EXC_DREGS+0x8(%a6) # Save incr value
18655 mov.l %d0,%a0
18656 rts
18657
18658faddr_ind_p_a1:
18659 mov.l EXC_DREGS+0xc(%a6),%d0 # Get current a1
18660 mov.l %d0,%d1
18661 add.l %a0,%d1 # Increment
18662 mov.l %d1,EXC_DREGS+0xc(%a6) # Save incr value
18663 mov.l %d0,%a0
18664 rts
18665
18666faddr_ind_p_a2:
18667 mov.l %a2,%d0 # Get current a2
18668 mov.l %d0,%d1
18669 add.l %a0,%d1 # Increment
18670 mov.l %d1,%a2 # Save incr value
18671 mov.l %d0,%a0
18672 rts
18673
18674faddr_ind_p_a3:
18675 mov.l %a3,%d0 # Get current a3
18676 mov.l %d0,%d1
18677 add.l %a0,%d1 # Increment
18678 mov.l %d1,%a3 # Save incr value
18679 mov.l %d0,%a0
18680 rts
18681
18682faddr_ind_p_a4:
18683 mov.l %a4,%d0 # Get current a4
18684 mov.l %d0,%d1
18685 add.l %a0,%d1 # Increment
18686 mov.l %d1,%a4 # Save incr value
18687 mov.l %d0,%a0
18688 rts
18689
18690faddr_ind_p_a5:
18691 mov.l %a5,%d0 # Get current a5
18692 mov.l %d0,%d1
18693 add.l %a0,%d1 # Increment
18694 mov.l %d1,%a5 # Save incr value
18695 mov.l %d0,%a0
18696 rts
18697
18698faddr_ind_p_a6:
18699 mov.l (%a6),%d0 # Get current a6
18700 mov.l %d0,%d1
18701 add.l %a0,%d1 # Increment
18702 mov.l %d1,(%a6) # Save incr value
18703 mov.l %d0,%a0
18704 rts
18705
18706faddr_ind_p_a7:
18707 mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
18708
18709 mov.l EXC_A7(%a6),%d0 # Get current a7
18710 mov.l %d0,%d1
18711 add.l %a0,%d1 # Increment
18712 mov.l %d1,EXC_A7(%a6) # Save incr value
18713 mov.l %d0,%a0
18714 rts
18715
18716####################################################
18717# Address register indirect w/ predecrement: -(An) #
18718####################################################
18719faddr_ind_m_a0:
18720 mov.l EXC_DREGS+0x8(%a6),%d0 # Get current a0
18721 sub.l %a0,%d0 # Decrement
18722 mov.l %d0,EXC_DREGS+0x8(%a6) # Save decr value
18723 mov.l %d0,%a0
18724 rts
18725
18726faddr_ind_m_a1:
18727 mov.l EXC_DREGS+0xc(%a6),%d0 # Get current a1
18728 sub.l %a0,%d0 # Decrement
18729 mov.l %d0,EXC_DREGS+0xc(%a6) # Save decr value
18730 mov.l %d0,%a0
18731 rts
18732
18733faddr_ind_m_a2:
18734 mov.l %a2,%d0 # Get current a2
18735 sub.l %a0,%d0 # Decrement
18736 mov.l %d0,%a2 # Save decr value
18737 mov.l %d0,%a0
18738 rts
18739
18740faddr_ind_m_a3:
18741 mov.l %a3,%d0 # Get current a3
18742 sub.l %a0,%d0 # Decrement
18743 mov.l %d0,%a3 # Save decr value
18744 mov.l %d0,%a0
18745 rts
18746
18747faddr_ind_m_a4:
18748 mov.l %a4,%d0 # Get current a4
18749 sub.l %a0,%d0 # Decrement
18750 mov.l %d0,%a4 # Save decr value
18751 mov.l %d0,%a0
18752 rts
18753
18754faddr_ind_m_a5:
18755 mov.l %a5,%d0 # Get current a5
18756 sub.l %a0,%d0 # Decrement
18757 mov.l %d0,%a5 # Save decr value
18758 mov.l %d0,%a0
18759 rts
18760
18761faddr_ind_m_a6:
18762 mov.l (%a6),%d0 # Get current a6
18763 sub.l %a0,%d0 # Decrement
18764 mov.l %d0,(%a6) # Save decr value
18765 mov.l %d0,%a0
18766 rts
18767
18768faddr_ind_m_a7:
18769 mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
18770
18771 mov.l EXC_A7(%a6),%d0 # Get current a7
18772 sub.l %a0,%d0 # Decrement
18773 mov.l %d0,EXC_A7(%a6) # Save decr value
18774 mov.l %d0,%a0
18775 rts
18776
18777########################################################
18778# Address register indirect w/ displacement: (d16, An) #
18779########################################################
18780faddr_ind_disp_a0:
18781 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18782 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18783 bsr.l _imem_read_word
18784
18785 tst.l %d1 # did ifetch fail?
18786 bne.l iea_iacc # yes
18787
18788 mov.w %d0,%a0 # sign extend displacement
18789
18790 add.l EXC_DREGS+0x8(%a6),%a0 # a0 + d16
18791 rts
18792
18793faddr_ind_disp_a1:
18794 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18795 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18796 bsr.l _imem_read_word
18797
18798 tst.l %d1 # did ifetch fail?
18799 bne.l iea_iacc # yes
18800
18801 mov.w %d0,%a0 # sign extend displacement
18802
18803 add.l EXC_DREGS+0xc(%a6),%a0 # a1 + d16
18804 rts
18805
18806faddr_ind_disp_a2:
18807 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18808 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18809 bsr.l _imem_read_word
18810
18811 tst.l %d1 # did ifetch fail?
18812 bne.l iea_iacc # yes
18813
18814 mov.w %d0,%a0 # sign extend displacement
18815
18816 add.l %a2,%a0 # a2 + d16
18817 rts
18818
18819faddr_ind_disp_a3:
18820 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18821 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18822 bsr.l _imem_read_word
18823
18824 tst.l %d1 # did ifetch fail?
18825 bne.l iea_iacc # yes
18826
18827 mov.w %d0,%a0 # sign extend displacement
18828
18829 add.l %a3,%a0 # a3 + d16
18830 rts
18831
18832faddr_ind_disp_a4:
18833 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18834 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18835 bsr.l _imem_read_word
18836
18837 tst.l %d1 # did ifetch fail?
18838 bne.l iea_iacc # yes
18839
18840 mov.w %d0,%a0 # sign extend displacement
18841
18842 add.l %a4,%a0 # a4 + d16
18843 rts
18844
18845faddr_ind_disp_a5:
18846 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18847 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18848 bsr.l _imem_read_word
18849
18850 tst.l %d1 # did ifetch fail?
18851 bne.l iea_iacc # yes
18852
18853 mov.w %d0,%a0 # sign extend displacement
18854
18855 add.l %a5,%a0 # a5 + d16
18856 rts
18857
18858faddr_ind_disp_a6:
18859 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18860 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18861 bsr.l _imem_read_word
18862
18863 tst.l %d1 # did ifetch fail?
18864 bne.l iea_iacc # yes
18865
18866 mov.w %d0,%a0 # sign extend displacement
18867
18868 add.l (%a6),%a0 # a6 + d16
18869 rts
18870
18871faddr_ind_disp_a7:
18872 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18873 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18874 bsr.l _imem_read_word
18875
18876 tst.l %d1 # did ifetch fail?
18877 bne.l iea_iacc # yes
18878
18879 mov.w %d0,%a0 # sign extend displacement
18880
18881 add.l EXC_A7(%a6),%a0 # a7 + d16
18882 rts
18883
18884########################################################################
18885# Address register indirect w/ index(8-bit displacement): (d8, An, Xn) #
18886# " " " w/ " (base displacement): (bd, An, Xn) #
18887# Memory indirect postindexed: ([bd, An], Xn, od) #
18888# Memory indirect preindexed: ([bd, An, Xn], od) #
18889########################################################################
18890faddr_ind_ext:
18891 addq.l &0x8,%d1
18892 bsr.l fetch_dreg # fetch base areg
18893 mov.l %d0,-(%sp)
18894
18895 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18896 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18897 bsr.l _imem_read_word # fetch extword in d0
18898
18899 tst.l %d1 # did ifetch fail?
18900 bne.l iea_iacc # yes
18901
18902 mov.l (%sp)+,%a0
18903
18904 btst &0x8,%d0
18905 bne.w fcalc_mem_ind
18906
18907 mov.l %d0,L_SCR1(%a6) # hold opword
18908
18909 mov.l %d0,%d1
18910 rol.w &0x4,%d1
18911 andi.w &0xf,%d1 # extract index regno
18912
18913# count on fetch_dreg() not to alter a0...
18914 bsr.l fetch_dreg # fetch index
18915
18916 mov.l %d2,-(%sp) # save d2
18917 mov.l L_SCR1(%a6),%d2 # fetch opword
18918
18919 btst &0xb,%d2 # is it word or long?
18920 bne.b faii8_long
18921 ext.l %d0 # sign extend word index
18922faii8_long:
18923 mov.l %d2,%d1
18924 rol.w &0x7,%d1
18925 andi.l &0x3,%d1 # extract scale value
18926
18927 lsl.l %d1,%d0 # shift index by scale
18928
18929 extb.l %d2 # sign extend displacement
18930 add.l %d2,%d0 # index + disp
18931 add.l %d0,%a0 # An + (index + disp)
18932
18933 mov.l (%sp)+,%d2 # restore old d2
18934 rts
18935
18936###########################
18937# Absolute short: (XXX).W #
18938###########################
18939fabs_short:
18940 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18941 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18942 bsr.l _imem_read_word # fetch short address
18943
18944 tst.l %d1 # did ifetch fail?
18945 bne.l iea_iacc # yes
18946
18947 mov.w %d0,%a0 # return <ea> in a0
18948 rts
18949
18950##########################
18951# Absolute long: (XXX).L #
18952##########################
18953fabs_long:
18954 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18955 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
18956 bsr.l _imem_read_long # fetch long address
18957
18958 tst.l %d1 # did ifetch fail?
18959 bne.l iea_iacc # yes
18960
18961 mov.l %d0,%a0 # return <ea> in a0
18962 rts
18963
18964#######################################################
18965# Program counter indirect w/ displacement: (d16, PC) #
18966#######################################################
18967fpc_ind:
18968 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18969 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18970 bsr.l _imem_read_word # fetch word displacement
18971
18972 tst.l %d1 # did ifetch fail?
18973 bne.l iea_iacc # yes
18974
18975 mov.w %d0,%a0 # sign extend displacement
18976
18977 add.l EXC_EXTWPTR(%a6),%a0 # pc + d16
18978
18979# _imem_read_word() increased the extwptr by 2. need to adjust here.
18980 subq.l &0x2,%a0 # adjust <ea>
18981 rts
18982
18983##########################################################
18984# PC indirect w/ index(8-bit displacement): (d8, PC, An) #
18985# " " w/ " (base displacement): (bd, PC, An) #
18986# PC memory indirect postindexed: ([bd, PC], Xn, od) #
18987# PC memory indirect preindexed: ([bd, PC, Xn], od) #
18988##########################################################
18989fpc_ind_ext:
18990 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
18991 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
18992 bsr.l _imem_read_word # fetch ext word
18993
18994 tst.l %d1 # did ifetch fail?
18995 bne.l iea_iacc # yes
18996
18997 mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0
18998 subq.l &0x2,%a0 # adjust base
18999
19000 btst &0x8,%d0 # is disp only 8 bits?
19001 bne.w fcalc_mem_ind # calc memory indirect
19002
19003 mov.l %d0,L_SCR1(%a6) # store opword
19004
19005 mov.l %d0,%d1 # make extword copy
19006 rol.w &0x4,%d1 # rotate reg num into place
19007 andi.w &0xf,%d1 # extract register number
19008
19009# count on fetch_dreg() not to alter a0...
19010 bsr.l fetch_dreg # fetch index
19011
19012 mov.l %d2,-(%sp) # save d2
19013 mov.l L_SCR1(%a6),%d2 # fetch opword
19014
19015 btst &0xb,%d2 # is index word or long?
19016 bne.b fpii8_long # long
19017 ext.l %d0 # sign extend word index
19018fpii8_long:
19019 mov.l %d2,%d1
19020 rol.w &0x7,%d1 # rotate scale value into place
19021 andi.l &0x3,%d1 # extract scale value
19022
19023 lsl.l %d1,%d0 # shift index by scale
19024
19025 extb.l %d2 # sign extend displacement
19026 add.l %d2,%d0 # disp + index
19027 add.l %d0,%a0 # An + (index + disp)
19028
19029 mov.l (%sp)+,%d2 # restore temp register
19030 rts
19031
19032# d2 = index
19033# d3 = base
19034# d4 = od
19035# d5 = extword
19036fcalc_mem_ind:
19037 btst &0x6,%d0 # is the index suppressed?
19038 beq.b fcalc_index
19039
19040 movm.l &0x3c00,-(%sp) # save d2-d5
19041
19042 mov.l %d0,%d5 # put extword in d5
19043 mov.l %a0,%d3 # put base in d3
19044
19045 clr.l %d2 # yes, so index = 0
19046 bra.b fbase_supp_ck
19047
19048# index:
19049fcalc_index:
19050 mov.l %d0,L_SCR1(%a6) # save d0 (opword)
19051 bfextu %d0{&16:&4},%d1 # fetch dreg index
19052 bsr.l fetch_dreg
19053
19054 movm.l &0x3c00,-(%sp) # save d2-d5
19055 mov.l %d0,%d2 # put index in d2
19056 mov.l L_SCR1(%a6),%d5
19057 mov.l %a0,%d3
19058
19059 btst &0xb,%d5 # is index word or long?
19060 bne.b fno_ext
19061 ext.l %d2
19062
19063fno_ext:
19064 bfextu %d5{&21:&2},%d0
19065 lsl.l %d0,%d2
19066
19067# base address (passed as parameter in d3):
19068# we clear the value here if it should actually be suppressed.
19069fbase_supp_ck:
19070 btst &0x7,%d5 # is the bd suppressed?
19071 beq.b fno_base_sup
19072 clr.l %d3
19073
19074# base displacement:
19075fno_base_sup:
19076 bfextu %d5{&26:&2},%d0 # get bd size
19077# beq.l fmovm_error # if (size == 0) it's reserved
19078
19079 cmpi.b %d0,&0x2
19080 blt.b fno_bd
19081 beq.b fget_word_bd
19082
19083 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19084 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19085 bsr.l _imem_read_long
19086
19087 tst.l %d1 # did ifetch fail?
19088 bne.l fcea_iacc # yes
19089
19090 bra.b fchk_ind
19091
19092fget_word_bd:
19093 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19094 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
19095 bsr.l _imem_read_word
19096
19097 tst.l %d1 # did ifetch fail?
19098 bne.l fcea_iacc # yes
19099
19100 ext.l %d0 # sign extend bd
19101
19102fchk_ind:
19103 add.l %d0,%d3 # base += bd
19104
19105# outer displacement:
19106fno_bd:
19107 bfextu %d5{&30:&2},%d0 # is od suppressed?
19108 beq.w faii_bd
19109
19110 cmpi.b %d0,&0x2
19111 blt.b fnull_od
19112 beq.b fword_od
19113
19114 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19115 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19116 bsr.l _imem_read_long
19117
19118 tst.l %d1 # did ifetch fail?
19119 bne.l fcea_iacc # yes
19120
19121 bra.b fadd_them
19122
19123fword_od:
19124 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19125 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
19126 bsr.l _imem_read_word
19127
19128 tst.l %d1 # did ifetch fail?
19129 bne.l fcea_iacc # yes
19130
19131 ext.l %d0 # sign extend od
19132 bra.b fadd_them
19133
19134fnull_od:
19135 clr.l %d0
19136
19137fadd_them:
19138 mov.l %d0,%d4
19139
19140 btst &0x2,%d5 # pre or post indexing?
19141 beq.b fpre_indexed
19142
19143 mov.l %d3,%a0
19144 bsr.l _dmem_read_long
19145
19146 tst.l %d1 # did dfetch fail?
19147 bne.w fcea_err # yes
19148
19149 add.l %d2,%d0 # <ea> += index
19150 add.l %d4,%d0 # <ea> += od
19151 bra.b fdone_ea
19152
19153fpre_indexed:
19154 add.l %d2,%d3 # preindexing
19155 mov.l %d3,%a0
19156 bsr.l _dmem_read_long
19157
19158 tst.l %d1 # did dfetch fail?
19159 bne.w fcea_err # yes
19160
19161 add.l %d4,%d0 # ea += od
19162 bra.b fdone_ea
19163
19164faii_bd:
19165 add.l %d2,%d3 # ea = (base + bd) + index
19166 mov.l %d3,%d0
19167fdone_ea:
19168 mov.l %d0,%a0
19169
19170 movm.l (%sp)+,&0x003c # restore d2-d5
19171 rts
19172
19173#########################################################
19174fcea_err:
19175 mov.l %d3,%a0
19176
19177 movm.l (%sp)+,&0x003c # restore d2-d5
19178 mov.w &0x0101,%d0
19179 bra.l iea_dacc
19180
19181fcea_iacc:
19182 movm.l (%sp)+,&0x003c # restore d2-d5
19183 bra.l iea_iacc
19184
19185fmovm_out_err:
19186 bsr.l restore
19187 mov.w &0x00e1,%d0
19188 bra.b fmovm_err
19189
19190fmovm_in_err:
19191 bsr.l restore
19192 mov.w &0x0161,%d0
19193
19194fmovm_err:
19195 mov.l L_SCR1(%a6),%a0
19196 bra.l iea_dacc
19197
19198#########################################################################
19199# XDEF **************************************************************** #
19200# fmovm_ctrl(): emulate fmovm.l of control registers instr #
19201# #
19202# XREF **************************************************************** #
19203# _imem_read_long() - read longword from memory #
19204# iea_iacc() - _imem_read_long() failed; error recovery #
19205# #
19206# INPUT *************************************************************** #
19207# None #
19208# #
19209# OUTPUT ************************************************************** #
19210# If _imem_read_long() doesn't fail: #
19211# USER_FPCR(a6) = new FPCR value #
19212# USER_FPSR(a6) = new FPSR value #
19213# USER_FPIAR(a6) = new FPIAR value #
19214# #
19215# ALGORITHM *********************************************************** #
19216# Decode the instruction type by looking at the extension word #
19217# in order to see how many control registers to fetch from memory. #
19218# Fetch them using _imem_read_long(). If this fetch fails, exit through #
19219# the special access error exit handler iea_iacc(). #
19220# #
19221# Instruction word decoding: #
19222# #
19223# fmovem.l #<data>, {FPIAR&|FPCR&|FPSR} #
19224# #
19225# WORD1 WORD2 #
19226# 1111 0010 00 111100 100$ $$00 0000 0000 #
19227# #
19228# $$$ (100): FPCR #
19229# (010): FPSR #
19230# (001): FPIAR #
19231# (000): FPIAR #
19232# #
19233#########################################################################
19234
19235 global fmovm_ctrl
19236fmovm_ctrl:
19237 mov.b EXC_EXTWORD(%a6),%d0 # fetch reg select bits
19238 cmpi.b %d0,&0x9c # fpcr & fpsr & fpiar ?
19239 beq.w fctrl_in_7 # yes
19240 cmpi.b %d0,&0x98 # fpcr & fpsr ?
19241 beq.w fctrl_in_6 # yes
19242 cmpi.b %d0,&0x94 # fpcr & fpiar ?
19243 beq.b fctrl_in_5 # yes
19244
19245# fmovem.l #<data>, fpsr/fpiar
19246fctrl_in_3:
19247 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19248 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19249 bsr.l _imem_read_long # fetch FPSR from mem
19250
19251 tst.l %d1 # did ifetch fail?
19252 bne.l iea_iacc # yes
19253
19254 mov.l %d0,USER_FPSR(%a6) # store new FPSR to stack
19255 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19256 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19257 bsr.l _imem_read_long # fetch FPIAR from mem
19258
19259 tst.l %d1 # did ifetch fail?
19260 bne.l iea_iacc # yes
19261
19262 mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to stack
19263 rts
19264
19265# fmovem.l #<data>, fpcr/fpiar
19266fctrl_in_5:
19267 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19268 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19269 bsr.l _imem_read_long # fetch FPCR from mem
19270
19271 tst.l %d1 # did ifetch fail?
19272 bne.l iea_iacc # yes
19273
19274 mov.l %d0,USER_FPCR(%a6) # store new FPCR to stack
19275 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19276 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19277 bsr.l _imem_read_long # fetch FPIAR from mem
19278
19279 tst.l %d1 # did ifetch fail?
19280 bne.l iea_iacc # yes
19281
19282 mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to stack
19283 rts
19284
19285# fmovem.l #<data>, fpcr/fpsr
19286fctrl_in_6:
19287 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19288 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19289 bsr.l _imem_read_long # fetch FPCR from mem
19290
19291 tst.l %d1 # did ifetch fail?
19292 bne.l iea_iacc # yes
19293
19294 mov.l %d0,USER_FPCR(%a6) # store new FPCR to mem
19295 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19296 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19297 bsr.l _imem_read_long # fetch FPSR from mem
19298
19299 tst.l %d1 # did ifetch fail?
19300 bne.l iea_iacc # yes
19301
19302 mov.l %d0,USER_FPSR(%a6) # store new FPSR to mem
19303 rts
19304
19305# fmovem.l #<data>, fpcr/fpsr/fpiar
19306fctrl_in_7:
19307 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19308 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19309 bsr.l _imem_read_long # fetch FPCR from mem
19310
19311 tst.l %d1 # did ifetch fail?
19312 bne.l iea_iacc # yes
19313
19314 mov.l %d0,USER_FPCR(%a6) # store new FPCR to mem
19315 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19316 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19317 bsr.l _imem_read_long # fetch FPSR from mem
19318
19319 tst.l %d1 # did ifetch fail?
19320 bne.l iea_iacc # yes
19321
19322 mov.l %d0,USER_FPSR(%a6) # store new FPSR to mem
19323 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
19324 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
19325 bsr.l _imem_read_long # fetch FPIAR from mem
19326
19327 tst.l %d1 # did ifetch fail?
19328 bne.l iea_iacc # yes
19329
19330 mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to mem
19331 rts
19332
19333#########################################################################
19334# XDEF **************************************************************** #
19335# _dcalc_ea(): calc correct <ea> from <ea> stacked on exception #
19336# #
19337# XREF **************************************************************** #
19338# inc_areg() - increment an address register #
19339# dec_areg() - decrement an address register #
19340# #
19341# INPUT *************************************************************** #
19342# d0 = number of bytes to adjust <ea> by #
19343# #
19344# OUTPUT ************************************************************** #
19345# None #
19346# #
19347# ALGORITHM *********************************************************** #
19348# "Dummy" CALCulate Effective Address: #
19349# The stacked <ea> for FP unimplemented instructions and opclass #
19350# two packed instructions is correct with the exception of... #
19351# #
19352# 1) -(An) : The register is not updated regardless of size. #
19353# Also, for extended precision and packed, the #
19354# stacked <ea> value is 8 bytes too big #
19355# 2) (An)+ : The register is not updated. #
19356# 3) #<data> : The upper longword of the immediate operand is #
19357# stacked b,w,l and s sizes are completely stacked. #
19358# d,x, and p are not. #
19359# #
19360#########################################################################
19361
19362 global _dcalc_ea
19363_dcalc_ea:
19364 mov.l %d0, %a0 # move # bytes to %a0
19365
19366 mov.b 1+EXC_OPWORD(%a6), %d0 # fetch opcode word
19367 mov.l %d0, %d1 # make a copy
19368
19369 andi.w &0x38, %d0 # extract mode field
19370 andi.l &0x7, %d1 # extract reg field
19371
19372 cmpi.b %d0,&0x18 # is mode (An)+ ?
19373 beq.b dcea_pi # yes
19374
19375 cmpi.b %d0,&0x20 # is mode -(An) ?
19376 beq.b dcea_pd # yes
19377
19378 or.w %d1,%d0 # concat mode,reg
19379 cmpi.b %d0,&0x3c # is mode #<data>?
19380
19381 beq.b dcea_imm # yes
19382
19383 mov.l EXC_EA(%a6),%a0 # return <ea>
19384 rts
19385
19386# need to set immediate data flag here since we'll need to do
19387# an imem_read to fetch this later.
19388dcea_imm:
19389 mov.b &immed_flg,SPCOND_FLG(%a6)
19390 lea ([USER_FPIAR,%a6],0x4),%a0 # no; return <ea>
19391 rts
19392
19393# here, the <ea> is stacked correctly. however, we must update the
19394# address register...
19395dcea_pi:
19396 mov.l %a0,%d0 # pass amt to inc by
19397 bsr.l inc_areg # inc addr register
19398
19399 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
19400 rts
19401
19402# the <ea> is stacked correctly for all but extended and packed which
19403# the <ea>s are 8 bytes too large.
19404# it would make no sense to have a pre-decrement to a7 in supervisor
19405# mode so we don't even worry about this tricky case here : )
19406dcea_pd:
19407 mov.l %a0,%d0 # pass amt to dec by
19408 bsr.l dec_areg # dec addr register
19409
19410 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
19411
19412 cmpi.b %d0,&0xc # is opsize ext or packed?
19413 beq.b dcea_pd2 # yes
19414 rts
19415dcea_pd2:
19416 sub.l &0x8,%a0 # correct <ea>
19417 mov.l %a0,EXC_EA(%a6) # put correct <ea> on stack
19418 rts
19419
19420#########################################################################
19421# XDEF **************************************************************** #
19422# _calc_ea_fout(): calculate correct stacked <ea> for extended #
19423# and packed data opclass 3 operations. #
19424# #
19425# XREF **************************************************************** #
19426# None #
19427# #
19428# INPUT *************************************************************** #
19429# None #
19430# #
19431# OUTPUT ************************************************************** #
19432# a0 = return correct effective address #
19433# #
19434# ALGORITHM *********************************************************** #
19435# For opclass 3 extended and packed data operations, the <ea> #
19436# stacked for the exception is incorrect for -(an) and (an)+ addressing #
19437# modes. Also, while we're at it, the index register itself must get #
19438# updated. #
19439# So, for -(an), we must subtract 8 off of the stacked <ea> value #
19440# and return that value as the correct <ea> and store that value in An. #
19441# For (an)+, the stacked <ea> is correct but we must adjust An by +12. #
19442# #
19443#########################################################################
19444
19445# This calc_ea is currently used to retrieve the correct <ea>
19446# for fmove outs of type extended and packed.
19447 global _calc_ea_fout
19448_calc_ea_fout:
19449 mov.b 1+EXC_OPWORD(%a6),%d0 # fetch opcode word
19450 mov.l %d0,%d1 # make a copy
19451
19452 andi.w &0x38,%d0 # extract mode field
19453 andi.l &0x7,%d1 # extract reg field
19454
19455 cmpi.b %d0,&0x18 # is mode (An)+ ?
19456 beq.b ceaf_pi # yes
19457
19458 cmpi.b %d0,&0x20 # is mode -(An) ?
19459 beq.w ceaf_pd # yes
19460
19461 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
19462 rts
19463
19464# (An)+ : extended and packed fmove out
19465# : stacked <ea> is correct
19466# : "An" not updated
19467ceaf_pi:
19468 mov.w (tbl_ceaf_pi.b,%pc,%d1.w*2),%d1
19469 mov.l EXC_EA(%a6),%a0
19470 jmp (tbl_ceaf_pi.b,%pc,%d1.w*1)
19471
19472 swbeg &0x8
19473tbl_ceaf_pi:
19474 short ceaf_pi0 - tbl_ceaf_pi
19475 short ceaf_pi1 - tbl_ceaf_pi
19476 short ceaf_pi2 - tbl_ceaf_pi
19477 short ceaf_pi3 - tbl_ceaf_pi
19478 short ceaf_pi4 - tbl_ceaf_pi
19479 short ceaf_pi5 - tbl_ceaf_pi
19480 short ceaf_pi6 - tbl_ceaf_pi
19481 short ceaf_pi7 - tbl_ceaf_pi
19482
19483ceaf_pi0:
19484 addi.l &0xc,EXC_DREGS+0x8(%a6)
19485 rts
19486ceaf_pi1:
19487 addi.l &0xc,EXC_DREGS+0xc(%a6)
19488 rts
19489ceaf_pi2:
19490 add.l &0xc,%a2
19491 rts
19492ceaf_pi3:
19493 add.l &0xc,%a3
19494 rts
19495ceaf_pi4:
19496 add.l &0xc,%a4
19497 rts
19498ceaf_pi5:
19499 add.l &0xc,%a5
19500 rts
19501ceaf_pi6:
19502 addi.l &0xc,EXC_A6(%a6)
19503 rts
19504ceaf_pi7:
19505 mov.b &mia7_flg,SPCOND_FLG(%a6)
19506 addi.l &0xc,EXC_A7(%a6)
19507 rts
19508
19509# -(An) : extended and packed fmove out
19510# : stacked <ea> = actual <ea> + 8
19511# : "An" not updated
19512ceaf_pd:
19513 mov.w (tbl_ceaf_pd.b,%pc,%d1.w*2),%d1
19514 mov.l EXC_EA(%a6),%a0
19515 sub.l &0x8,%a0
19516 sub.l &0x8,EXC_EA(%a6)
19517 jmp (tbl_ceaf_pd.b,%pc,%d1.w*1)
19518
19519 swbeg &0x8
19520tbl_ceaf_pd:
19521 short ceaf_pd0 - tbl_ceaf_pd
19522 short ceaf_pd1 - tbl_ceaf_pd
19523 short ceaf_pd2 - tbl_ceaf_pd
19524 short ceaf_pd3 - tbl_ceaf_pd
19525 short ceaf_pd4 - tbl_ceaf_pd
19526 short ceaf_pd5 - tbl_ceaf_pd
19527 short ceaf_pd6 - tbl_ceaf_pd
19528 short ceaf_pd7 - tbl_ceaf_pd
19529
19530ceaf_pd0:
19531 mov.l %a0,EXC_DREGS+0x8(%a6)
19532 rts
19533ceaf_pd1:
19534 mov.l %a0,EXC_DREGS+0xc(%a6)
19535 rts
19536ceaf_pd2:
19537 mov.l %a0,%a2
19538 rts
19539ceaf_pd3:
19540 mov.l %a0,%a3
19541 rts
19542ceaf_pd4:
19543 mov.l %a0,%a4
19544 rts
19545ceaf_pd5:
19546 mov.l %a0,%a5
19547 rts
19548ceaf_pd6:
19549 mov.l %a0,EXC_A6(%a6)
19550 rts
19551ceaf_pd7:
19552 mov.l %a0,EXC_A7(%a6)
19553 mov.b &mda7_flg,SPCOND_FLG(%a6)
19554 rts
19555
19556#########################################################################
19557# XDEF **************************************************************** #
19558# _load_fop(): load operand for unimplemented FP exception #
19559# #
19560# XREF **************************************************************** #
19561# set_tag_x() - determine ext prec optype tag #
19562# set_tag_s() - determine sgl prec optype tag #
19563# set_tag_d() - determine dbl prec optype tag #
19564# unnorm_fix() - convert normalized number to denorm or zero #
19565# norm() - normalize a denormalized number #
19566# get_packed() - fetch a packed operand from memory #
19567# _dcalc_ea() - calculate <ea>, fixing An in process #
19568# #
19569# _imem_read_{word,long}() - read from instruction memory #
19570# _dmem_read() - read from data memory #
19571# _dmem_read_{byte,word,long}() - read from data memory #
19572# #
19573# facc_in_{b,w,l,d,x}() - mem read failed; special exit point #
19574# #
19575# INPUT *************************************************************** #
19576# None #
19577# #
19578# OUTPUT ************************************************************** #
19579# If memory access doesn't fail: #
19580# FP_SRC(a6) = source operand in extended precision #
19581# FP_DST(a6) = destination operand in extended precision #
19582# #
19583# ALGORITHM *********************************************************** #
19584# This is called from the Unimplemented FP exception handler in #
19585# order to load the source and maybe destination operand into #
19586# FP_SRC(a6) and FP_DST(a6). If the instruction was opclass zero, load #
19587# the source and destination from the FP register file. Set the optype #
19588# tags for both if dyadic, one for monadic. If a number is an UNNORM, #
19589# convert it to a DENORM or a ZERO. #
19590# If the instruction is opclass two (memory->reg), then fetch #
19591# the destination from the register file and the source operand from #
19592# memory. Tag and fix both as above w/ opclass zero instructions. #
19593# If the source operand is byte,word,long, or single, it may be #
19594# in the data register file. If it's actually out in memory, use one of #
19595# the mem_read() routines to fetch it. If the mem_read() access returns #
19596# a failing value, exit through the special facc_in() routine which #
19597# will create an access error exception frame from the current exception #
19598# frame. #
19599# Immediate data and regular data accesses are separated because #
19600# if an immediate data access fails, the resulting fault status #
19601# longword stacked for the access error exception must have the #
19602# instruction bit set. #
19603# #
19604#########################################################################
19605
19606 global _load_fop
19607_load_fop:
19608
19609# 15 13 12 10 9 7 6 0
19610# / \ / \ / \ / \
19611# ---------------------------------
19612# | opclass | RX | RY | EXTENSION | (2nd word of general FP instruction)
19613# ---------------------------------
19614#
19615
19616# bfextu EXC_CMDREG(%a6){&0:&3}, %d0 # extract opclass
19617# cmpi.b %d0, &0x2 # which class is it? ('000,'010,'011)
19618# beq.w op010 # handle <ea> -> fpn
19619# bgt.w op011 # handle fpn -> <ea>
19620
19621# we're not using op011 for now...
19622 btst &0x6,EXC_CMDREG(%a6)
19623 bne.b op010
19624
19625############################
19626# OPCLASS '000: reg -> reg #
19627############################
19628op000:
19629 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension word lo
19630 btst &0x5,%d0 # testing extension bits
19631 beq.b op000_src # (bit 5 == 0) => monadic
19632 btst &0x4,%d0 # (bit 5 == 1)
19633 beq.b op000_dst # (bit 4 == 0) => dyadic
19634 and.w &0x007f,%d0 # extract extension bits {6:0}
19635 cmpi.w %d0,&0x0038 # is it an fcmp (dyadic) ?
19636 bne.b op000_src # it's an fcmp
19637
19638op000_dst:
19639 bfextu EXC_CMDREG(%a6){&6:&3}, %d0 # extract dst field
19640 bsr.l load_fpn2 # fetch dst fpreg into FP_DST
19641
19642 bsr.l set_tag_x # get dst optype tag
19643
19644 cmpi.b %d0, &UNNORM # is dst fpreg an UNNORM?
19645 beq.b op000_dst_unnorm # yes
19646op000_dst_cont:
19647 mov.b %d0, DTAG(%a6) # store the dst optype tag
19648
19649op000_src:
19650 bfextu EXC_CMDREG(%a6){&3:&3}, %d0 # extract src field
19651 bsr.l load_fpn1 # fetch src fpreg into FP_SRC
19652
19653 bsr.l set_tag_x # get src optype tag
19654
19655 cmpi.b %d0, &UNNORM # is src fpreg an UNNORM?
19656 beq.b op000_src_unnorm # yes
19657op000_src_cont:
19658 mov.b %d0, STAG(%a6) # store the src optype tag
19659 rts
19660
19661op000_dst_unnorm:
19662 bsr.l unnorm_fix # fix the dst UNNORM
19663 bra.b op000_dst_cont
19664op000_src_unnorm:
19665 bsr.l unnorm_fix # fix the src UNNORM
19666 bra.b op000_src_cont
19667
19668#############################
19669# OPCLASS '010: <ea> -> reg #
19670#############################
19671op010:
19672 mov.w EXC_CMDREG(%a6),%d0 # fetch extension word
19673 btst &0x5,%d0 # testing extension bits
19674 beq.b op010_src # (bit 5 == 0) => monadic
19675 btst &0x4,%d0 # (bit 5 == 1)
19676 beq.b op010_dst # (bit 4 == 0) => dyadic
19677 and.w &0x007f,%d0 # extract extension bits {6:0}
19678 cmpi.w %d0,&0x0038 # is it an fcmp (dyadic) ?
19679 bne.b op010_src # it's an fcmp
19680
19681op010_dst:
19682 bfextu EXC_CMDREG(%a6){&6:&3}, %d0 # extract dst field
19683 bsr.l load_fpn2 # fetch dst fpreg ptr
19684
19685 bsr.l set_tag_x # get dst type tag
19686
19687 cmpi.b %d0, &UNNORM # is dst fpreg an UNNORM?
19688 beq.b op010_dst_unnorm # yes
19689op010_dst_cont:
19690 mov.b %d0, DTAG(%a6) # store the dst optype tag
19691
19692op010_src:
19693 bfextu EXC_CMDREG(%a6){&3:&3}, %d0 # extract src type field
19694
19695 bfextu EXC_OPWORD(%a6){&10:&3}, %d1 # extract <ea> mode field
19696 bne.w fetch_from_mem # src op is in memory
19697
19698op010_dreg:
19699 clr.b STAG(%a6) # either NORM or ZERO
19700 bfextu EXC_OPWORD(%a6){&13:&3}, %d1 # extract src reg field
19701
19702 mov.w (tbl_op010_dreg.b,%pc,%d0.w*2), %d0 # jmp based on optype
19703 jmp (tbl_op010_dreg.b,%pc,%d0.w*1) # fetch src from dreg
19704
19705op010_dst_unnorm:
19706 bsr.l unnorm_fix # fix the dst UNNORM
19707 bra.b op010_dst_cont
19708
19709 swbeg &0x8
19710tbl_op010_dreg:
19711 short opd_long - tbl_op010_dreg
19712 short opd_sgl - tbl_op010_dreg
19713 short tbl_op010_dreg - tbl_op010_dreg
19714 short tbl_op010_dreg - tbl_op010_dreg
19715 short opd_word - tbl_op010_dreg
19716 short tbl_op010_dreg - tbl_op010_dreg
19717 short opd_byte - tbl_op010_dreg
19718 short tbl_op010_dreg - tbl_op010_dreg
19719
19720#
19721# LONG: can be either NORM or ZERO...
19722#
19723opd_long:
19724 bsr.l fetch_dreg # fetch long in d0
19725 fmov.l %d0, %fp0 # load a long
19726 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
19727 fbeq.w opd_long_zero # long is a ZERO
19728 rts
19729opd_long_zero:
19730 mov.b &ZERO, STAG(%a6) # set ZERO optype flag
19731 rts
19732
19733#
19734# WORD: can be either NORM or ZERO...
19735#
19736opd_word:
19737 bsr.l fetch_dreg # fetch word in d0
19738 fmov.w %d0, %fp0 # load a word
19739 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
19740 fbeq.w opd_word_zero # WORD is a ZERO
19741 rts
19742opd_word_zero:
19743 mov.b &ZERO, STAG(%a6) # set ZERO optype flag
19744 rts
19745
19746#
19747# BYTE: can be either NORM or ZERO...
19748#
19749opd_byte:
19750 bsr.l fetch_dreg # fetch word in d0
19751 fmov.b %d0, %fp0 # load a byte
19752 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
19753 fbeq.w opd_byte_zero # byte is a ZERO
19754 rts
19755opd_byte_zero:
19756 mov.b &ZERO, STAG(%a6) # set ZERO optype flag
19757 rts
19758
19759#
19760# SGL: can be either NORM, DENORM, ZERO, INF, QNAN or SNAN but not UNNORM
19761#
19762# separate SNANs and DENORMs so they can be loaded w/ special care.
19763# all others can simply be moved "in" using fmove.
19764#
19765opd_sgl:
19766 bsr.l fetch_dreg # fetch sgl in d0
19767 mov.l %d0,L_SCR1(%a6)
19768
19769 lea L_SCR1(%a6), %a0 # pass: ptr to the sgl
19770 bsr.l set_tag_s # determine sgl type
19771 mov.b %d0, STAG(%a6) # save the src tag
19772
19773 cmpi.b %d0, &SNAN # is it an SNAN?
19774 beq.w get_sgl_snan # yes
19775
19776 cmpi.b %d0, &DENORM # is it a DENORM?
19777 beq.w get_sgl_denorm # yes
19778
19779 fmov.s (%a0), %fp0 # no, so can load it regular
19780 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
19781 rts
19782
19783##############################################################################
19784
19785#########################################################################
19786# fetch_from_mem(): #
19787# - src is out in memory. must: #
19788# (1) calc ea - must read AFTER you know the src type since #
19789# if the ea is -() or ()+, need to know # of bytes. #
19790# (2) read it in from either user or supervisor space #
19791# (3) if (b || w || l) then simply read in #
19792# if (s || d || x) then check for SNAN,UNNORM,DENORM #
19793# if (packed) then punt for now #
19794# INPUT: #
19795# %d0 : src type field #
19796#########################################################################
19797fetch_from_mem:
19798 clr.b STAG(%a6) # either NORM or ZERO
19799
19800 mov.w (tbl_fp_type.b,%pc,%d0.w*2), %d0 # index by src type field
19801 jmp (tbl_fp_type.b,%pc,%d0.w*1)
19802
19803 swbeg &0x8
19804tbl_fp_type:
19805 short load_long - tbl_fp_type
19806 short load_sgl - tbl_fp_type
19807 short load_ext - tbl_fp_type
19808 short load_packed - tbl_fp_type
19809 short load_word - tbl_fp_type
19810 short load_dbl - tbl_fp_type
19811 short load_byte - tbl_fp_type
19812 short tbl_fp_type - tbl_fp_type
19813
19814#########################################
19815# load a LONG into %fp0: #
19816# -number can't fault #
19817# (1) calc ea #
19818# (2) read 4 bytes into L_SCR1 #
19819# (3) fmov.l into %fp0 #
19820#########################################
19821load_long:
19822 movq.l &0x4, %d0 # pass: 4 (bytes)
19823 bsr.l _dcalc_ea # calc <ea>; <ea> in %a0
19824
19825 cmpi.b SPCOND_FLG(%a6),&immed_flg
19826 beq.b load_long_immed
19827
19828 bsr.l _dmem_read_long # fetch src operand from memory
19829
19830 tst.l %d1 # did dfetch fail?
19831 bne.l facc_in_l # yes
19832
19833load_long_cont:
19834 fmov.l %d0, %fp0 # read into %fp0;convert to xprec
19835 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
19836
19837 fbeq.w load_long_zero # src op is a ZERO
19838 rts
19839load_long_zero:
19840 mov.b &ZERO, STAG(%a6) # set optype tag to ZERO
19841 rts
19842
19843load_long_immed:
19844 bsr.l _imem_read_long # fetch src operand immed data
19845
19846 tst.l %d1 # did ifetch fail?
19847 bne.l funimp_iacc # yes
19848 bra.b load_long_cont
19849
19850#########################################
19851# load a WORD into %fp0: #
19852# -number can't fault #
19853# (1) calc ea #
19854# (2) read 2 bytes into L_SCR1 #
19855# (3) fmov.w into %fp0 #
19856#########################################
19857load_word:
19858 movq.l &0x2, %d0 # pass: 2 (bytes)
19859 bsr.l _dcalc_ea # calc <ea>; <ea> in %a0
19860
19861 cmpi.b SPCOND_FLG(%a6),&immed_flg
19862 beq.b load_word_immed
19863
19864 bsr.l _dmem_read_word # fetch src operand from memory
19865
19866 tst.l %d1 # did dfetch fail?
19867 bne.l facc_in_w # yes
19868
19869load_word_cont:
19870 fmov.w %d0, %fp0 # read into %fp0;convert to xprec
19871 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
19872
19873 fbeq.w load_word_zero # src op is a ZERO
19874 rts
19875load_word_zero:
19876 mov.b &ZERO, STAG(%a6) # set optype tag to ZERO
19877 rts
19878
19879load_word_immed:
19880 bsr.l _imem_read_word # fetch src operand immed data
19881
19882 tst.l %d1 # did ifetch fail?
19883 bne.l funimp_iacc # yes
19884 bra.b load_word_cont
19885
19886#########################################
19887# load a BYTE into %fp0: #
19888# -number can't fault #
19889# (1) calc ea #
19890# (2) read 1 byte into L_SCR1 #
19891# (3) fmov.b into %fp0 #
19892#########################################
19893load_byte:
19894 movq.l &0x1, %d0 # pass: 1 (byte)
19895 bsr.l _dcalc_ea # calc <ea>; <ea> in %a0
19896
19897 cmpi.b SPCOND_FLG(%a6),&immed_flg
19898 beq.b load_byte_immed
19899
19900 bsr.l _dmem_read_byte # fetch src operand from memory
19901
19902 tst.l %d1 # did dfetch fail?
19903 bne.l facc_in_b # yes
19904
19905load_byte_cont:
19906 fmov.b %d0, %fp0 # read into %fp0;convert to xprec
19907 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
19908
19909 fbeq.w load_byte_zero # src op is a ZERO
19910 rts
19911load_byte_zero:
19912 mov.b &ZERO, STAG(%a6) # set optype tag to ZERO
19913 rts
19914
19915load_byte_immed:
19916 bsr.l _imem_read_word # fetch src operand immed data
19917
19918 tst.l %d1 # did ifetch fail?
19919 bne.l funimp_iacc # yes
19920 bra.b load_byte_cont
19921
19922#########################################
19923# load a SGL into %fp0: #
19924# -number can't fault #
19925# (1) calc ea #
19926# (2) read 4 bytes into L_SCR1 #
19927# (3) fmov.s into %fp0 #
19928#########################################
19929load_sgl:
19930 movq.l &0x4, %d0 # pass: 4 (bytes)
19931 bsr.l _dcalc_ea # calc <ea>; <ea> in %a0
19932
19933 cmpi.b SPCOND_FLG(%a6),&immed_flg
19934 beq.b load_sgl_immed
19935
19936 bsr.l _dmem_read_long # fetch src operand from memory
19937 mov.l %d0, L_SCR1(%a6) # store src op on stack
19938
19939 tst.l %d1 # did dfetch fail?
19940 bne.l facc_in_l # yes
19941
19942load_sgl_cont:
19943 lea L_SCR1(%a6), %a0 # pass: ptr to sgl src op
19944 bsr.l set_tag_s # determine src type tag
19945 mov.b %d0, STAG(%a6) # save src optype tag on stack
19946
19947 cmpi.b %d0, &DENORM # is it a sgl DENORM?
19948 beq.w get_sgl_denorm # yes
19949
19950 cmpi.b %d0, &SNAN # is it a sgl SNAN?
19951 beq.w get_sgl_snan # yes
19952
19953 fmov.s L_SCR1(%a6), %fp0 # read into %fp0;convert to xprec
19954 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
19955 rts
19956
19957load_sgl_immed:
19958 bsr.l _imem_read_long # fetch src operand immed data
19959
19960 tst.l %d1 # did ifetch fail?
19961 bne.l funimp_iacc # yes
19962 bra.b load_sgl_cont
19963
19964# must convert sgl denorm format to an Xprec denorm fmt suitable for
19965# normalization...
19966# %a0 : points to sgl denorm
19967get_sgl_denorm:
19968 clr.w FP_SRC_EX(%a6)
19969 bfextu (%a0){&9:&23}, %d0 # fetch sgl hi(_mantissa)
19970 lsl.l &0x8, %d0
19971 mov.l %d0, FP_SRC_HI(%a6) # set ext hi(_mantissa)
19972 clr.l FP_SRC_LO(%a6) # set ext lo(_mantissa)
19973
19974 clr.w FP_SRC_EX(%a6)
19975 btst &0x7, (%a0) # is sgn bit set?
19976 beq.b sgl_dnrm_norm
19977 bset &0x7, FP_SRC_EX(%a6) # set sgn of xprec value
19978
19979sgl_dnrm_norm:
19980 lea FP_SRC(%a6), %a0
19981 bsr.l norm # normalize number
19982 mov.w &0x3f81, %d1 # xprec exp = 0x3f81
19983 sub.w %d0, %d1 # exp = 0x3f81 - shft amt.
19984 or.w %d1, FP_SRC_EX(%a6) # {sgn,exp}
19985
19986 mov.b &NORM, STAG(%a6) # fix src type tag
19987 rts
19988
19989# convert sgl to ext SNAN
19990# %a0 : points to sgl SNAN
19991get_sgl_snan:
19992 mov.w &0x7fff, FP_SRC_EX(%a6) # set exp of SNAN
19993 bfextu (%a0){&9:&23}, %d0
19994 lsl.l &0x8, %d0 # extract and insert hi(man)
19995 mov.l %d0, FP_SRC_HI(%a6)
19996 clr.l FP_SRC_LO(%a6)
19997
19998 btst &0x7, (%a0) # see if sign of SNAN is set
19999 beq.b no_sgl_snan_sgn
20000 bset &0x7, FP_SRC_EX(%a6)
20001no_sgl_snan_sgn:
20002 rts
20003
20004#########################################
20005# load a DBL into %fp0: #
20006# -number can't fault #
20007# (1) calc ea #
20008# (2) read 8 bytes into L_SCR(1,2)#
20009# (3) fmov.d into %fp0 #
20010#########################################
20011load_dbl:
20012 movq.l &0x8, %d0 # pass: 8 (bytes)
20013 bsr.l _dcalc_ea # calc <ea>; <ea> in %a0
20014
20015 cmpi.b SPCOND_FLG(%a6),&immed_flg
20016 beq.b load_dbl_immed
20017
20018 lea L_SCR1(%a6), %a1 # pass: ptr to input dbl tmp space
20019 movq.l &0x8, %d0 # pass: # bytes to read
20020 bsr.l _dmem_read # fetch src operand from memory
20021
20022 tst.l %d1 # did dfetch fail?
20023 bne.l facc_in_d # yes
20024
20025load_dbl_cont:
20026 lea L_SCR1(%a6), %a0 # pass: ptr to input dbl
20027 bsr.l set_tag_d # determine src type tag
20028 mov.b %d0, STAG(%a6) # set src optype tag
20029
20030 cmpi.b %d0, &DENORM # is it a dbl DENORM?
20031 beq.w get_dbl_denorm # yes
20032
20033 cmpi.b %d0, &SNAN # is it a dbl SNAN?
20034 beq.w get_dbl_snan # yes
20035
20036 fmov.d L_SCR1(%a6), %fp0 # read into %fp0;convert to xprec
20037 fmovm.x &0x80, FP_SRC(%a6) # return src op in FP_SRC
20038 rts
20039
20040load_dbl_immed:
20041 lea L_SCR1(%a6), %a1 # pass: ptr to input dbl tmp space
20042 movq.l &0x8, %d0 # pass: # bytes to read
20043 bsr.l _imem_read # fetch src operand from memory
20044
20045 tst.l %d1 # did ifetch fail?
20046 bne.l funimp_iacc # yes
20047 bra.b load_dbl_cont
20048
20049# must convert dbl denorm format to an Xprec denorm fmt suitable for
20050# normalization...
20051# %a0 : loc. of dbl denorm
20052get_dbl_denorm:
20053 clr.w FP_SRC_EX(%a6)
20054 bfextu (%a0){&12:&31}, %d0 # fetch hi(_mantissa)
20055 mov.l %d0, FP_SRC_HI(%a6)
20056 bfextu 4(%a0){&11:&21}, %d0 # fetch lo(_mantissa)
20057 mov.l &0xb, %d1
20058 lsl.l %d1, %d0
20059 mov.l %d0, FP_SRC_LO(%a6)
20060
20061 btst &0x7, (%a0) # is sgn bit set?
20062 beq.b dbl_dnrm_norm
20063 bset &0x7, FP_SRC_EX(%a6) # set sgn of xprec value
20064
20065dbl_dnrm_norm:
20066 lea FP_SRC(%a6), %a0
20067 bsr.l norm # normalize number
20068 mov.w &0x3c01, %d1 # xprec exp = 0x3c01
20069 sub.w %d0, %d1 # exp = 0x3c01 - shft amt.
20070 or.w %d1, FP_SRC_EX(%a6) # {sgn,exp}
20071
20072 mov.b &NORM, STAG(%a6) # fix src type tag
20073 rts
20074
20075# convert dbl to ext SNAN
20076# %a0 : points to dbl SNAN
20077get_dbl_snan:
20078 mov.w &0x7fff, FP_SRC_EX(%a6) # set exp of SNAN
20079
20080 bfextu (%a0){&12:&31}, %d0 # fetch hi(_mantissa)
20081 mov.l %d0, FP_SRC_HI(%a6)
20082 bfextu 4(%a0){&11:&21}, %d0 # fetch lo(_mantissa)
20083 mov.l &0xb, %d1
20084 lsl.l %d1, %d0
20085 mov.l %d0, FP_SRC_LO(%a6)
20086
20087 btst &0x7, (%a0) # see if sign of SNAN is set
20088 beq.b no_dbl_snan_sgn
20089 bset &0x7, FP_SRC_EX(%a6)
20090no_dbl_snan_sgn:
20091 rts
20092
20093#################################################
20094# load a Xprec into %fp0: #
20095# -number can't fault #
20096# (1) calc ea #
20097# (2) read 12 bytes into L_SCR(1,2) #
20098# (3) fmov.x into %fp0 #
20099#################################################
20100load_ext:
20101 mov.l &0xc, %d0 # pass: 12 (bytes)
20102 bsr.l _dcalc_ea # calc <ea>
20103
20104 lea FP_SRC(%a6), %a1 # pass: ptr to input ext tmp space
20105 mov.l &0xc, %d0 # pass: # of bytes to read
20106 bsr.l _dmem_read # fetch src operand from memory
20107
20108 tst.l %d1 # did dfetch fail?
20109 bne.l facc_in_x # yes
20110
20111 lea FP_SRC(%a6), %a0 # pass: ptr to src op
20112 bsr.l set_tag_x # determine src type tag
20113
20114 cmpi.b %d0, &UNNORM # is the src op an UNNORM?
20115 beq.b load_ext_unnorm # yes
20116
20117 mov.b %d0, STAG(%a6) # store the src optype tag
20118 rts
20119
20120load_ext_unnorm:
20121 bsr.l unnorm_fix # fix the src UNNORM
20122 mov.b %d0, STAG(%a6) # store the src optype tag
20123 rts
20124
20125#################################################
20126# load a packed into %fp0: #
20127# -number can't fault #
20128# (1) calc ea #
20129# (2) read 12 bytes into L_SCR(1,2,3) #
20130# (3) fmov.x into %fp0 #
20131#################################################
20132load_packed:
20133 bsr.l get_packed
20134
20135 lea FP_SRC(%a6),%a0 # pass ptr to src op
20136 bsr.l set_tag_x # determine src type tag
20137 cmpi.b %d0,&UNNORM # is the src op an UNNORM ZERO?
20138 beq.b load_packed_unnorm # yes
20139
20140 mov.b %d0,STAG(%a6) # store the src optype tag
20141 rts
20142
20143load_packed_unnorm:
20144 bsr.l unnorm_fix # fix the UNNORM ZERO
20145 mov.b %d0,STAG(%a6) # store the src optype tag
20146 rts
20147
20148#########################################################################
20149# XDEF **************************************************************** #
20150# fout(): move from fp register to memory or data register #
20151# #
20152# XREF **************************************************************** #
20153# _round() - needed to create EXOP for sgl/dbl precision #
20154# norm() - needed to create EXOP for extended precision #
20155# ovf_res() - create default overflow result for sgl/dbl precision#
20156# unf_res() - create default underflow result for sgl/dbl prec. #
20157# dst_dbl() - create rounded dbl precision result. #
20158# dst_sgl() - create rounded sgl precision result. #
20159# fetch_dreg() - fetch dynamic k-factor reg for packed. #
20160# bindec() - convert FP binary number to packed number. #
20161# _mem_write() - write data to memory. #
20162# _mem_write2() - write data to memory unless supv mode -(a7) exc.#
20163# _dmem_write_{byte,word,long}() - write data to memory. #
20164# store_dreg_{b,w,l}() - store data to data register file. #
20165# facc_out_{b,w,l,d,x}() - data access error occurred. #
20166# #
20167# INPUT *************************************************************** #
20168# a0 = pointer to extended precision source operand #
20169# d0 = round prec,mode #
20170# #
20171# OUTPUT ************************************************************** #
20172# fp0 : intermediate underflow or overflow result if #
20173# OVFL/UNFL occurred for a sgl or dbl operand #
20174# #
20175# ALGORITHM *********************************************************** #
20176# This routine is accessed by many handlers that need to do an #
20177# opclass three move of an operand out to memory. #
20178# Decode an fmove out (opclass 3) instruction to determine if #
20179# it's b,w,l,s,d,x, or p in size. b,w,l can be stored to either a data #
20180# register or memory. The algorithm uses a standard "fmove" to create #
20181# the rounded result. Also, since exceptions are disabled, this also #
20182# create the correct OPERR default result if appropriate. #
20183# For sgl or dbl precision, overflow or underflow can occur. If #
20184# either occurs and is enabled, the EXOP. #
20185# For extended precision, the stacked <ea> must be fixed along #
20186# w/ the address index register as appropriate w/ _calc_ea_fout(). If #
20187# the source is a denorm and if underflow is enabled, an EXOP must be #
20188# created. #
20189# For packed, the k-factor must be fetched from the instruction #
20190# word or a data register. The <ea> must be fixed as w/ extended #
20191# precision. Then, bindec() is called to create the appropriate #
20192# packed result. #
20193# If at any time an access error is flagged by one of the move- #
20194# to-memory routines, then a special exit must be made so that the #
20195# access error can be handled properly. #
20196# #
20197#########################################################################
20198
20199 global fout
20200fout:
20201 bfextu EXC_CMDREG(%a6){&3:&3},%d1 # extract dst fmt
20202 mov.w (tbl_fout.b,%pc,%d1.w*2),%a1 # use as index
20203 jmp (tbl_fout.b,%pc,%a1) # jump to routine
20204
20205 swbeg &0x8
20206tbl_fout:
20207 short fout_long - tbl_fout
20208 short fout_sgl - tbl_fout
20209 short fout_ext - tbl_fout
20210 short fout_pack - tbl_fout
20211 short fout_word - tbl_fout
20212 short fout_dbl - tbl_fout
20213 short fout_byte - tbl_fout
20214 short fout_pack - tbl_fout
20215
20216#################################################################
20217# fmove.b out ###################################################
20218#################################################################
20219
20220# Only "Unimplemented Data Type" exceptions enter here. The operand
20221# is either a DENORM or a NORM.
20222fout_byte:
20223 tst.b STAG(%a6) # is operand normalized?
20224 bne.b fout_byte_denorm # no
20225
20226 fmovm.x SRC(%a0),&0x80 # load value
20227
20228fout_byte_norm:
20229 fmov.l %d0,%fpcr # insert rnd prec,mode
20230
20231 fmov.b %fp0,%d0 # exec move out w/ correct rnd mode
20232
20233 fmov.l &0x0,%fpcr # clear FPCR
20234 fmov.l %fpsr,%d1 # fetch FPSR
20235 or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
20236
20237 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
20238 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
20239 beq.b fout_byte_dn # must save to integer regfile
20240
20241 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
20242 bsr.l _dmem_write_byte # write byte
20243
20244 tst.l %d1 # did dstore fail?
20245 bne.l facc_out_b # yes
20246
20247 rts
20248
20249fout_byte_dn:
20250 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
20251 andi.w &0x7,%d1
20252 bsr.l store_dreg_b
20253 rts
20254
20255fout_byte_denorm:
20256 mov.l SRC_EX(%a0),%d1
20257 andi.l &0x80000000,%d1 # keep DENORM sign
20258 ori.l &0x00800000,%d1 # make smallest sgl
20259 fmov.s %d1,%fp0
20260 bra.b fout_byte_norm
20261
20262#################################################################
20263# fmove.w out ###################################################
20264#################################################################
20265
20266# Only "Unimplemented Data Type" exceptions enter here. The operand
20267# is either a DENORM or a NORM.
20268fout_word:
20269 tst.b STAG(%a6) # is operand normalized?
20270 bne.b fout_word_denorm # no
20271
20272 fmovm.x SRC(%a0),&0x80 # load value
20273
20274fout_word_norm:
20275 fmov.l %d0,%fpcr # insert rnd prec:mode
20276
20277 fmov.w %fp0,%d0 # exec move out w/ correct rnd mode
20278
20279 fmov.l &0x0,%fpcr # clear FPCR
20280 fmov.l %fpsr,%d1 # fetch FPSR
20281 or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
20282
20283 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
20284 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
20285 beq.b fout_word_dn # must save to integer regfile
20286
20287 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
20288 bsr.l _dmem_write_word # write word
20289
20290 tst.l %d1 # did dstore fail?
20291 bne.l facc_out_w # yes
20292
20293 rts
20294
20295fout_word_dn:
20296 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
20297 andi.w &0x7,%d1
20298 bsr.l store_dreg_w
20299 rts
20300
20301fout_word_denorm:
20302 mov.l SRC_EX(%a0),%d1
20303 andi.l &0x80000000,%d1 # keep DENORM sign
20304 ori.l &0x00800000,%d1 # make smallest sgl
20305 fmov.s %d1,%fp0
20306 bra.b fout_word_norm
20307
20308#################################################################
20309# fmove.l out ###################################################
20310#################################################################
20311
20312# Only "Unimplemented Data Type" exceptions enter here. The operand
20313# is either a DENORM or a NORM.
20314fout_long:
20315 tst.b STAG(%a6) # is operand normalized?
20316 bne.b fout_long_denorm # no
20317
20318 fmovm.x SRC(%a0),&0x80 # load value
20319
20320fout_long_norm:
20321 fmov.l %d0,%fpcr # insert rnd prec:mode
20322
20323 fmov.l %fp0,%d0 # exec move out w/ correct rnd mode
20324
20325 fmov.l &0x0,%fpcr # clear FPCR
20326 fmov.l %fpsr,%d1 # fetch FPSR
20327 or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
20328
20329fout_long_write:
20330 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
20331 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
20332 beq.b fout_long_dn # must save to integer regfile
20333
20334 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
20335 bsr.l _dmem_write_long # write long
20336
20337 tst.l %d1 # did dstore fail?
20338 bne.l facc_out_l # yes
20339
20340 rts
20341
20342fout_long_dn:
20343 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
20344 andi.w &0x7,%d1
20345 bsr.l store_dreg_l
20346 rts
20347
20348fout_long_denorm:
20349 mov.l SRC_EX(%a0),%d1
20350 andi.l &0x80000000,%d1 # keep DENORM sign
20351 ori.l &0x00800000,%d1 # make smallest sgl
20352 fmov.s %d1,%fp0
20353 bra.b fout_long_norm
20354
20355#################################################################
20356# fmove.x out ###################################################
20357#################################################################
20358
20359# Only "Unimplemented Data Type" exceptions enter here. The operand
20360# is either a DENORM or a NORM.
20361# The DENORM causes an Underflow exception.
20362fout_ext:
20363
20364# we copy the extended precision result to FP_SCR0 so that the reserved
20365# 16-bit field gets zeroed. we do this since we promise not to disturb
20366# what's at SRC(a0).
20367 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
20368 clr.w 2+FP_SCR0_EX(%a6) # clear reserved field
20369 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
20370 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
20371
20372 fmovm.x SRC(%a0),&0x80 # return result
20373
20374 bsr.l _calc_ea_fout # fix stacked <ea>
20375
20376 mov.l %a0,%a1 # pass: dst addr
20377 lea FP_SCR0(%a6),%a0 # pass: src addr
20378 mov.l &0xc,%d0 # pass: opsize is 12 bytes
20379
20380# we must not yet write the extended precision data to the stack
20381# in the pre-decrement case from supervisor mode or else we'll corrupt
20382# the stack frame. so, leave it in FP_SRC for now and deal with it later...
20383 cmpi.b SPCOND_FLG(%a6),&mda7_flg
20384 beq.b fout_ext_a7
20385
20386 bsr.l _dmem_write # write ext prec number to memory
20387
20388 tst.l %d1 # did dstore fail?
20389 bne.w fout_ext_err # yes
20390
20391 tst.b STAG(%a6) # is operand normalized?
20392 bne.b fout_ext_denorm # no
20393 rts
20394
20395# the number is a DENORM. must set the underflow exception bit
20396fout_ext_denorm:
20397 bset &unfl_bit,FPSR_EXCEPT(%a6) # set underflow exc bit
20398
20399 mov.b FPCR_ENABLE(%a6),%d0
20400 andi.b &0x0a,%d0 # is UNFL or INEX enabled?
20401 bne.b fout_ext_exc # yes
20402 rts
20403
20404# we don't want to do the write if the exception occurred in supervisor mode
20405# so _mem_write2() handles this for us.
20406fout_ext_a7:
20407 bsr.l _mem_write2 # write ext prec number to memory
20408
20409 tst.l %d1 # did dstore fail?
20410 bne.w fout_ext_err # yes
20411
20412 tst.b STAG(%a6) # is operand normalized?
20413 bne.b fout_ext_denorm # no
20414 rts
20415
20416fout_ext_exc:
20417 lea FP_SCR0(%a6),%a0
20418 bsr.l norm # normalize the mantissa
20419 neg.w %d0 # new exp = -(shft amt)
20420 andi.w &0x7fff,%d0
20421 andi.w &0x8000,FP_SCR0_EX(%a6) # keep only old sign
20422 or.w %d0,FP_SCR0_EX(%a6) # insert new exponent
20423 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
20424 rts
20425
20426fout_ext_err:
20427 mov.l EXC_A6(%a6),(%a6) # fix stacked a6
20428 bra.l facc_out_x
20429
20430#########################################################################
20431# fmove.s out ###########################################################
20432#########################################################################
20433fout_sgl:
20434 andi.b &0x30,%d0 # clear rnd prec
20435 ori.b &s_mode*0x10,%d0 # insert sgl prec
20436 mov.l %d0,L_SCR3(%a6) # save rnd prec,mode on stack
20437
20438#
20439# operand is a normalized number. first, we check to see if the move out
20440# would cause either an underflow or overflow. these cases are handled
20441# separately. otherwise, set the FPCR to the proper rounding mode and
20442# execute the move.
20443#
20444 mov.w SRC_EX(%a0),%d0 # extract exponent
20445 andi.w &0x7fff,%d0 # strip sign
20446
20447 cmpi.w %d0,&SGL_HI # will operand overflow?
20448 bgt.w fout_sgl_ovfl # yes; go handle OVFL
20449 beq.w fout_sgl_may_ovfl # maybe; go handle possible OVFL
20450 cmpi.w %d0,&SGL_LO # will operand underflow?
20451 blt.w fout_sgl_unfl # yes; go handle underflow
20452
20453#
20454# NORMs(in range) can be stored out by a simple "fmov.s"
20455# Unnormalized inputs can come through this point.
20456#
20457fout_sgl_exg:
20458 fmovm.x SRC(%a0),&0x80 # fetch fop from stack
20459
20460 fmov.l L_SCR3(%a6),%fpcr # set FPCR
20461 fmov.l &0x0,%fpsr # clear FPSR
20462
20463 fmov.s %fp0,%d0 # store does convert and round
20464
20465 fmov.l &0x0,%fpcr # clear FPCR
20466 fmov.l %fpsr,%d1 # save FPSR
20467
20468 or.w %d1,2+USER_FPSR(%a6) # set possible inex2/ainex
20469
20470fout_sgl_exg_write:
20471 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
20472 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
20473 beq.b fout_sgl_exg_write_dn # must save to integer regfile
20474
20475 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
20476 bsr.l _dmem_write_long # write long
20477
20478 tst.l %d1 # did dstore fail?
20479 bne.l facc_out_l # yes
20480
20481 rts
20482
20483fout_sgl_exg_write_dn:
20484 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
20485 andi.w &0x7,%d1
20486 bsr.l store_dreg_l
20487 rts
20488
20489#
20490# here, we know that the operand would UNFL if moved out to single prec,
20491# so, denorm and round and then use generic store single routine to
20492# write the value to memory.
20493#
20494fout_sgl_unfl:
20495 bset &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
20496
20497 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
20498 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
20499 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
20500 mov.l %a0,-(%sp)
20501
20502 clr.l %d0 # pass: S.F. = 0
20503
20504 cmpi.b STAG(%a6),&DENORM # fetch src optype tag
20505 bne.b fout_sgl_unfl_cont # let DENORMs fall through
20506
20507 lea FP_SCR0(%a6),%a0
20508 bsr.l norm # normalize the DENORM
20509
20510fout_sgl_unfl_cont:
20511 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
20512 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
20513 bsr.l unf_res # calc default underflow result
20514
20515 lea FP_SCR0(%a6),%a0 # pass: ptr to fop
20516 bsr.l dst_sgl # convert to single prec
20517
20518 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
20519 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
20520 beq.b fout_sgl_unfl_dn # must save to integer regfile
20521
20522 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
20523 bsr.l _dmem_write_long # write long
20524
20525 tst.l %d1 # did dstore fail?
20526 bne.l facc_out_l # yes
20527
20528 bra.b fout_sgl_unfl_chkexc
20529
20530fout_sgl_unfl_dn:
20531 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
20532 andi.w &0x7,%d1
20533 bsr.l store_dreg_l
20534
20535fout_sgl_unfl_chkexc:
20536 mov.b FPCR_ENABLE(%a6),%d1
20537 andi.b &0x0a,%d1 # is UNFL or INEX enabled?
20538 bne.w fout_sd_exc_unfl # yes
20539 addq.l &0x4,%sp
20540 rts
20541
20542#
20543# it's definitely an overflow so call ovf_res to get the correct answer
20544#
20545fout_sgl_ovfl:
20546 tst.b 3+SRC_HI(%a0) # is result inexact?
20547 bne.b fout_sgl_ovfl_inex2
20548 tst.l SRC_LO(%a0) # is result inexact?
20549 bne.b fout_sgl_ovfl_inex2
20550 ori.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
20551 bra.b fout_sgl_ovfl_cont
20552fout_sgl_ovfl_inex2:
20553 ori.w &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
20554
20555fout_sgl_ovfl_cont:
20556 mov.l %a0,-(%sp)
20557
20558# call ovf_res() w/ sgl prec and the correct rnd mode to create the default
20559# overflow result. DON'T save the returned ccodes from ovf_res() since
20560# fmove out doesn't alter them.
20561 tst.b SRC_EX(%a0) # is operand negative?
20562 smi %d1 # set if so
20563 mov.l L_SCR3(%a6),%d0 # pass: sgl prec,rnd mode
20564 bsr.l ovf_res # calc OVFL result
20565 fmovm.x (%a0),&0x80 # load default overflow result
20566 fmov.s %fp0,%d0 # store to single
20567
20568 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
20569 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
20570 beq.b fout_sgl_ovfl_dn # must save to integer regfile
20571
20572 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
20573 bsr.l _dmem_write_long # write long
20574
20575 tst.l %d1 # did dstore fail?
20576 bne.l facc_out_l # yes
20577
20578 bra.b fout_sgl_ovfl_chkexc
20579
20580fout_sgl_ovfl_dn:
20581 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
20582 andi.w &0x7,%d1
20583 bsr.l store_dreg_l
20584
20585fout_sgl_ovfl_chkexc:
20586 mov.b FPCR_ENABLE(%a6),%d1
20587 andi.b &0x0a,%d1 # is UNFL or INEX enabled?
20588 bne.w fout_sd_exc_ovfl # yes
20589 addq.l &0x4,%sp
20590 rts
20591
20592#
20593# move out MAY overflow:
20594# (1) force the exp to 0x3fff
20595# (2) do a move w/ appropriate rnd mode
20596# (3) if exp still equals zero, then insert original exponent
20597# for the correct result.
20598# if exp now equals one, then it overflowed so call ovf_res.
20599#
20600fout_sgl_may_ovfl:
20601 mov.w SRC_EX(%a0),%d1 # fetch current sign
20602 andi.w &0x8000,%d1 # keep it,clear exp
20603 ori.w &0x3fff,%d1 # insert exp = 0
20604 mov.w %d1,FP_SCR0_EX(%a6) # insert scaled exp
20605 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
20606 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
20607
20608 fmov.l L_SCR3(%a6),%fpcr # set FPCR
20609
20610 fmov.x FP_SCR0(%a6),%fp0 # force fop to be rounded
20611 fmov.l &0x0,%fpcr # clear FPCR
20612
20613 fabs.x %fp0 # need absolute value
20614 fcmp.b %fp0,&0x2 # did exponent increase?
20615 fblt.w fout_sgl_exg # no; go finish NORM
20616 bra.w fout_sgl_ovfl # yes; go handle overflow
20617
20618################
20619
20620fout_sd_exc_unfl:
20621 mov.l (%sp)+,%a0
20622
20623 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
20624 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
20625 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
20626
20627 cmpi.b STAG(%a6),&DENORM # was src a DENORM?
20628 bne.b fout_sd_exc_cont # no
20629
20630 lea FP_SCR0(%a6),%a0
20631 bsr.l norm
20632 neg.l %d0
20633 andi.w &0x7fff,%d0
20634 bfins %d0,FP_SCR0_EX(%a6){&1:&15}
20635 bra.b fout_sd_exc_cont
20636
20637fout_sd_exc:
20638fout_sd_exc_ovfl:
20639 mov.l (%sp)+,%a0 # restore a0
20640
20641 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
20642 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
20643 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
20644
20645fout_sd_exc_cont:
20646 bclr &0x7,FP_SCR0_EX(%a6) # clear sign bit
20647 sne.b 2+FP_SCR0_EX(%a6) # set internal sign bit
20648 lea FP_SCR0(%a6),%a0 # pass: ptr to DENORM
20649
20650 mov.b 3+L_SCR3(%a6),%d1
20651 lsr.b &0x4,%d1
20652 andi.w &0x0c,%d1
20653 swap %d1
20654 mov.b 3+L_SCR3(%a6),%d1
20655 lsr.b &0x4,%d1
20656 andi.w &0x03,%d1
20657 clr.l %d0 # pass: zero g,r,s
20658 bsr.l _round # round the DENORM
20659
20660 tst.b 2+FP_SCR0_EX(%a6) # is EXOP negative?
20661 beq.b fout_sd_exc_done # no
20662 bset &0x7,FP_SCR0_EX(%a6) # yes
20663
20664fout_sd_exc_done:
20665 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
20666 rts
20667
20668#################################################################
20669# fmove.d out ###################################################
20670#################################################################
20671fout_dbl:
20672 andi.b &0x30,%d0 # clear rnd prec
20673 ori.b &d_mode*0x10,%d0 # insert dbl prec
20674 mov.l %d0,L_SCR3(%a6) # save rnd prec,mode on stack
20675
20676#
20677# operand is a normalized number. first, we check to see if the move out
20678# would cause either an underflow or overflow. these cases are handled
20679# separately. otherwise, set the FPCR to the proper rounding mode and
20680# execute the move.
20681#
20682 mov.w SRC_EX(%a0),%d0 # extract exponent
20683 andi.w &0x7fff,%d0 # strip sign
20684
20685 cmpi.w %d0,&DBL_HI # will operand overflow?
20686 bgt.w fout_dbl_ovfl # yes; go handle OVFL
20687 beq.w fout_dbl_may_ovfl # maybe; go handle possible OVFL
20688 cmpi.w %d0,&DBL_LO # will operand underflow?
20689 blt.w fout_dbl_unfl # yes; go handle underflow
20690
20691#
20692# NORMs(in range) can be stored out by a simple "fmov.d"
20693# Unnormalized inputs can come through this point.
20694#
20695fout_dbl_exg:
20696 fmovm.x SRC(%a0),&0x80 # fetch fop from stack
20697
20698 fmov.l L_SCR3(%a6),%fpcr # set FPCR
20699 fmov.l &0x0,%fpsr # clear FPSR
20700
20701 fmov.d %fp0,L_SCR1(%a6) # store does convert and round
20702
20703 fmov.l &0x0,%fpcr # clear FPCR
20704 fmov.l %fpsr,%d0 # save FPSR
20705
20706 or.w %d0,2+USER_FPSR(%a6) # set possible inex2/ainex
20707
20708 mov.l EXC_EA(%a6),%a1 # pass: dst addr
20709 lea L_SCR1(%a6),%a0 # pass: src addr
20710 movq.l &0x8,%d0 # pass: opsize is 8 bytes
20711 bsr.l _dmem_write # store dbl fop to memory
20712
20713 tst.l %d1 # did dstore fail?
20714 bne.l facc_out_d # yes
20715
20716 rts # no; so we're finished
20717
20718#
20719# here, we know that the operand would UNFL if moved out to double prec,
20720# so, denorm and round and then use generic store double routine to
20721# write the value to memory.
20722#
20723fout_dbl_unfl:
20724 bset &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
20725
20726 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
20727 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
20728 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
20729 mov.l %a0,-(%sp)
20730
20731 clr.l %d0 # pass: S.F. = 0
20732
20733 cmpi.b STAG(%a6),&DENORM # fetch src optype tag
20734 bne.b fout_dbl_unfl_cont # let DENORMs fall through
20735
20736 lea FP_SCR0(%a6),%a0
20737 bsr.l norm # normalize the DENORM
20738
20739fout_dbl_unfl_cont:
20740 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
20741 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
20742 bsr.l unf_res # calc default underflow result
20743
20744 lea FP_SCR0(%a6),%a0 # pass: ptr to fop
20745 bsr.l dst_dbl # convert to single prec
20746 mov.l %d0,L_SCR1(%a6)
20747 mov.l %d1,L_SCR2(%a6)
20748
20749 mov.l EXC_EA(%a6),%a1 # pass: dst addr
20750 lea L_SCR1(%a6),%a0 # pass: src addr
20751 movq.l &0x8,%d0 # pass: opsize is 8 bytes
20752 bsr.l _dmem_write # store dbl fop to memory
20753
20754 tst.l %d1 # did dstore fail?
20755 bne.l facc_out_d # yes
20756
20757 mov.b FPCR_ENABLE(%a6),%d1
20758 andi.b &0x0a,%d1 # is UNFL or INEX enabled?
20759 bne.w fout_sd_exc_unfl # yes
20760 addq.l &0x4,%sp
20761 rts
20762
20763#
20764# it's definitely an overflow so call ovf_res to get the correct answer
20765#
20766fout_dbl_ovfl:
20767 mov.w 2+SRC_LO(%a0),%d0
20768 andi.w &0x7ff,%d0
20769 bne.b fout_dbl_ovfl_inex2
20770
20771 ori.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
20772 bra.b fout_dbl_ovfl_cont
20773fout_dbl_ovfl_inex2:
20774 ori.w &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
20775
20776fout_dbl_ovfl_cont:
20777 mov.l %a0,-(%sp)
20778
20779# call ovf_res() w/ dbl prec and the correct rnd mode to create the default
20780# overflow result. DON'T save the returned ccodes from ovf_res() since
20781# fmove out doesn't alter them.
20782 tst.b SRC_EX(%a0) # is operand negative?
20783 smi %d1 # set if so
20784 mov.l L_SCR3(%a6),%d0 # pass: dbl prec,rnd mode
20785 bsr.l ovf_res # calc OVFL result
20786 fmovm.x (%a0),&0x80 # load default overflow result
20787 fmov.d %fp0,L_SCR1(%a6) # store to double
20788
20789 mov.l EXC_EA(%a6),%a1 # pass: dst addr
20790 lea L_SCR1(%a6),%a0 # pass: src addr
20791 movq.l &0x8,%d0 # pass: opsize is 8 bytes
20792 bsr.l _dmem_write # store dbl fop to memory
20793
20794 tst.l %d1 # did dstore fail?
20795 bne.l facc_out_d # yes
20796
20797 mov.b FPCR_ENABLE(%a6),%d1
20798 andi.b &0x0a,%d1 # is UNFL or INEX enabled?
20799 bne.w fout_sd_exc_ovfl # yes
20800 addq.l &0x4,%sp
20801 rts
20802
20803#
20804# move out MAY overflow:
20805# (1) force the exp to 0x3fff
20806# (2) do a move w/ appropriate rnd mode
20807# (3) if exp still equals zero, then insert original exponent
20808# for the correct result.
20809# if exp now equals one, then it overflowed so call ovf_res.
20810#
20811fout_dbl_may_ovfl:
20812 mov.w SRC_EX(%a0),%d1 # fetch current sign
20813 andi.w &0x8000,%d1 # keep it,clear exp
20814 ori.w &0x3fff,%d1 # insert exp = 0
20815 mov.w %d1,FP_SCR0_EX(%a6) # insert scaled exp
20816 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
20817 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
20818
20819 fmov.l L_SCR3(%a6),%fpcr # set FPCR
20820
20821 fmov.x FP_SCR0(%a6),%fp0 # force fop to be rounded
20822 fmov.l &0x0,%fpcr # clear FPCR
20823
20824 fabs.x %fp0 # need absolute value
20825 fcmp.b %fp0,&0x2 # did exponent increase?
20826 fblt.w fout_dbl_exg # no; go finish NORM
20827 bra.w fout_dbl_ovfl # yes; go handle overflow
20828
20829#########################################################################
20830# XDEF **************************************************************** #
20831# dst_dbl(): create double precision value from extended prec. #
20832# #
20833# XREF **************************************************************** #
20834# None #
20835# #
20836# INPUT *************************************************************** #
20837# a0 = pointer to source operand in extended precision #
20838# #
20839# OUTPUT ************************************************************** #
20840# d0 = hi(double precision result) #
20841# d1 = lo(double precision result) #
20842# #
20843# ALGORITHM *********************************************************** #
20844# #
20845# Changes extended precision to double precision. #
20846# Note: no attempt is made to round the extended value to double. #
20847# dbl_sign = ext_sign #
20848# dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias) #
20849# get rid of ext integer bit #
20850# dbl_mant = ext_mant{62:12} #
20851# #
20852# --------------- --------------- --------------- #
20853# extended -> |s| exp | |1| ms mant | | ls mant | #
20854# --------------- --------------- --------------- #
20855# 95 64 63 62 32 31 11 0 #
20856# | | #
20857# | | #
20858# | | #
20859# v v #
20860# --------------- --------------- #
20861# double -> |s|exp| mant | | mant | #
20862# --------------- --------------- #
20863# 63 51 32 31 0 #
20864# #
20865#########################################################################
20866
20867dst_dbl:
20868 clr.l %d0 # clear d0
20869 mov.w FTEMP_EX(%a0),%d0 # get exponent
20870 subi.w &EXT_BIAS,%d0 # subtract extended precision bias
20871 addi.w &DBL_BIAS,%d0 # add double precision bias
20872 tst.b FTEMP_HI(%a0) # is number a denorm?
20873 bmi.b dst_get_dupper # no
20874 subq.w &0x1,%d0 # yes; denorm bias = DBL_BIAS - 1
20875dst_get_dupper:
20876 swap %d0 # d0 now in upper word
20877 lsl.l &0x4,%d0 # d0 in proper place for dbl prec exp
20878 tst.b FTEMP_EX(%a0) # test sign
20879 bpl.b dst_get_dman # if postive, go process mantissa
20880 bset &0x1f,%d0 # if negative, set sign
20881dst_get_dman:
20882 mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
20883 bfextu %d1{&1:&20},%d1 # get upper 20 bits of ms
20884 or.l %d1,%d0 # put these bits in ms word of double
20885 mov.l %d0,L_SCR1(%a6) # put the new exp back on the stack
20886 mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
20887 mov.l &21,%d0 # load shift count
20888 lsl.l %d0,%d1 # put lower 11 bits in upper bits
20889 mov.l %d1,L_SCR2(%a6) # build lower lword in memory
20890 mov.l FTEMP_LO(%a0),%d1 # get ls mantissa
20891 bfextu %d1{&0:&21},%d0 # get ls 21 bits of double
20892 mov.l L_SCR2(%a6),%d1
20893 or.l %d0,%d1 # put them in double result
20894 mov.l L_SCR1(%a6),%d0
20895 rts
20896
20897#########################################################################
20898# XDEF **************************************************************** #
20899# dst_sgl(): create single precision value from extended prec #
20900# #
20901# XREF **************************************************************** #
20902# #
20903# INPUT *************************************************************** #
20904# a0 = pointer to source operand in extended precision #
20905# #
20906# OUTPUT ************************************************************** #
20907# d0 = single precision result #
20908# #
20909# ALGORITHM *********************************************************** #
20910# #
20911# Changes extended precision to single precision. #
20912# sgl_sign = ext_sign #
20913# sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias) #
20914# get rid of ext integer bit #
20915# sgl_mant = ext_mant{62:12} #
20916# #
20917# --------------- --------------- --------------- #
20918# extended -> |s| exp | |1| ms mant | | ls mant | #
20919# --------------- --------------- --------------- #
20920# 95 64 63 62 40 32 31 12 0 #
20921# | | #
20922# | | #
20923# | | #
20924# v v #
20925# --------------- #
20926# single -> |s|exp| mant | #
20927# --------------- #
20928# 31 22 0 #
20929# #
20930#########################################################################
20931
20932dst_sgl:
20933 clr.l %d0
20934 mov.w FTEMP_EX(%a0),%d0 # get exponent
20935 subi.w &EXT_BIAS,%d0 # subtract extended precision bias
20936 addi.w &SGL_BIAS,%d0 # add single precision bias
20937 tst.b FTEMP_HI(%a0) # is number a denorm?
20938 bmi.b dst_get_supper # no
20939 subq.w &0x1,%d0 # yes; denorm bias = SGL_BIAS - 1
20940dst_get_supper:
20941 swap %d0 # put exp in upper word of d0
20942 lsl.l &0x7,%d0 # shift it into single exp bits
20943 tst.b FTEMP_EX(%a0) # test sign
20944 bpl.b dst_get_sman # if positive, continue
20945 bset &0x1f,%d0 # if negative, put in sign first
20946dst_get_sman:
20947 mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
20948 andi.l &0x7fffff00,%d1 # get upper 23 bits of ms
20949 lsr.l &0x8,%d1 # and put them flush right
20950 or.l %d1,%d0 # put these bits in ms word of single
20951 rts
20952
20953##############################################################################
20954fout_pack:
20955 bsr.l _calc_ea_fout # fetch the <ea>
20956 mov.l %a0,-(%sp)
20957
20958 mov.b STAG(%a6),%d0 # fetch input type
20959 bne.w fout_pack_not_norm # input is not NORM
20960
20961fout_pack_norm:
20962 btst &0x4,EXC_CMDREG(%a6) # static or dynamic?
20963 beq.b fout_pack_s # static
20964
20965fout_pack_d:
20966 mov.b 1+EXC_CMDREG(%a6),%d1 # fetch dynamic reg
20967 lsr.b &0x4,%d1
20968 andi.w &0x7,%d1
20969
20970 bsr.l fetch_dreg # fetch Dn w/ k-factor
20971
20972 bra.b fout_pack_type
20973fout_pack_s:
20974 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch static field
20975
20976fout_pack_type:
20977 bfexts %d0{&25:&7},%d0 # extract k-factor
20978 mov.l %d0,-(%sp)
20979
20980 lea FP_SRC(%a6),%a0 # pass: ptr to input
20981
20982# bindec is currently scrambling FP_SRC for denorm inputs.
20983# we'll have to change this, but for now, tough luck!!!
20984 bsr.l bindec # convert xprec to packed
20985
20986# andi.l &0xcfff000f,FP_SCR0(%a6) # clear unused fields
20987 andi.l &0xcffff00f,FP_SCR0(%a6) # clear unused fields
20988
20989 mov.l (%sp)+,%d0
20990
20991 tst.b 3+FP_SCR0_EX(%a6)
20992 bne.b fout_pack_set
20993 tst.l FP_SCR0_HI(%a6)
20994 bne.b fout_pack_set
20995 tst.l FP_SCR0_LO(%a6)
20996 bne.b fout_pack_set
20997
20998# add the extra condition that only if the k-factor was zero, too, should
20999# we zero the exponent
21000 tst.l %d0
21001 bne.b fout_pack_set
21002# "mantissa" is all zero which means that the answer is zero. but, the '040
21003# algorithm allows the exponent to be non-zero. the 881/2 do not. therefore,
21004# if the mantissa is zero, I will zero the exponent, too.
21005# the question now is whether the exponents sign bit is allowed to be non-zero
21006# for a zero, also...
21007 andi.w &0xf000,FP_SCR0(%a6)
21008
21009fout_pack_set:
21010
21011 lea FP_SCR0(%a6),%a0 # pass: src addr
21012
21013fout_pack_write:
21014 mov.l (%sp)+,%a1 # pass: dst addr
21015 mov.l &0xc,%d0 # pass: opsize is 12 bytes
21016
21017 cmpi.b SPCOND_FLG(%a6),&mda7_flg
21018 beq.b fout_pack_a7
21019
21020 bsr.l _dmem_write # write ext prec number to memory
21021
21022 tst.l %d1 # did dstore fail?
21023 bne.w fout_ext_err # yes
21024
21025 rts
21026
21027# we don't want to do the write if the exception occurred in supervisor mode
21028# so _mem_write2() handles this for us.
21029fout_pack_a7:
21030 bsr.l _mem_write2 # write ext prec number to memory
21031
21032 tst.l %d1 # did dstore fail?
21033 bne.w fout_ext_err # yes
21034
21035 rts
21036
21037fout_pack_not_norm:
21038 cmpi.b %d0,&DENORM # is it a DENORM?
21039 beq.w fout_pack_norm # yes
21040 lea FP_SRC(%a6),%a0
21041 clr.w 2+FP_SRC_EX(%a6)
21042 cmpi.b %d0,&SNAN # is it an SNAN?
21043 beq.b fout_pack_snan # yes
21044 bra.b fout_pack_write # no
21045
21046fout_pack_snan:
21047 ori.w &snaniop2_mask,FPSR_EXCEPT(%a6) # set SNAN/AIOP
21048 bset &0x6,FP_SRC_HI(%a6) # set snan bit
21049 bra.b fout_pack_write
21050
21051#########################################################################
21052# XDEF **************************************************************** #
21053# fetch_dreg(): fetch register according to index in d1 #
21054# #
21055# XREF **************************************************************** #
21056# None #
21057# #
21058# INPUT *************************************************************** #
21059# d1 = index of register to fetch from #
21060# #
21061# OUTPUT ************************************************************** #
21062# d0 = value of register fetched #
21063# #
21064# ALGORITHM *********************************************************** #
21065# According to the index value in d1 which can range from zero #
21066# to fifteen, load the corresponding register file value (where #
21067# address register indexes start at 8). D0/D1/A0/A1/A6/A7 are on the #
21068# stack. The rest should still be in their original places. #
21069# #
21070#########################################################################
21071
21072# this routine leaves d1 intact for subsequent store_dreg calls.
21073 global fetch_dreg
21074fetch_dreg:
21075 mov.w (tbl_fdreg.b,%pc,%d1.w*2),%d0
21076 jmp (tbl_fdreg.b,%pc,%d0.w*1)
21077
21078tbl_fdreg:
21079 short fdreg0 - tbl_fdreg
21080 short fdreg1 - tbl_fdreg
21081 short fdreg2 - tbl_fdreg
21082 short fdreg3 - tbl_fdreg
21083 short fdreg4 - tbl_fdreg
21084 short fdreg5 - tbl_fdreg
21085 short fdreg6 - tbl_fdreg
21086 short fdreg7 - tbl_fdreg
21087 short fdreg8 - tbl_fdreg
21088 short fdreg9 - tbl_fdreg
21089 short fdrega - tbl_fdreg
21090 short fdregb - tbl_fdreg
21091 short fdregc - tbl_fdreg
21092 short fdregd - tbl_fdreg
21093 short fdrege - tbl_fdreg
21094 short fdregf - tbl_fdreg
21095
21096fdreg0:
21097 mov.l EXC_DREGS+0x0(%a6),%d0
21098 rts
21099fdreg1:
21100 mov.l EXC_DREGS+0x4(%a6),%d0
21101 rts
21102fdreg2:
21103 mov.l %d2,%d0
21104 rts
21105fdreg3:
21106 mov.l %d3,%d0
21107 rts
21108fdreg4:
21109 mov.l %d4,%d0
21110 rts
21111fdreg5:
21112 mov.l %d5,%d0
21113 rts
21114fdreg6:
21115 mov.l %d6,%d0
21116 rts
21117fdreg7:
21118 mov.l %d7,%d0
21119 rts
21120fdreg8:
21121 mov.l EXC_DREGS+0x8(%a6),%d0
21122 rts
21123fdreg9:
21124 mov.l EXC_DREGS+0xc(%a6),%d0
21125 rts
21126fdrega:
21127 mov.l %a2,%d0
21128 rts
21129fdregb:
21130 mov.l %a3,%d0
21131 rts
21132fdregc:
21133 mov.l %a4,%d0
21134 rts
21135fdregd:
21136 mov.l %a5,%d0
21137 rts
21138fdrege:
21139 mov.l (%a6),%d0
21140 rts
21141fdregf:
21142 mov.l EXC_A7(%a6),%d0
21143 rts
21144
21145#########################################################################
21146# XDEF **************************************************************** #
21147# store_dreg_l(): store longword to data register specified by d1 #
21148# #
21149# XREF **************************************************************** #
21150# None #
21151# #
21152# INPUT *************************************************************** #
21153# d0 = longowrd value to store #
21154# d1 = index of register to fetch from #
21155# #
21156# OUTPUT ************************************************************** #
21157# (data register is updated) #
21158# #
21159# ALGORITHM *********************************************************** #
21160# According to the index value in d1, store the longword value #
21161# in d0 to the corresponding data register. D0/D1 are on the stack #
21162# while the rest are in their initial places. #
21163# #
21164#########################################################################
21165
21166 global store_dreg_l
21167store_dreg_l:
21168 mov.w (tbl_sdregl.b,%pc,%d1.w*2),%d1
21169 jmp (tbl_sdregl.b,%pc,%d1.w*1)
21170
21171tbl_sdregl:
21172 short sdregl0 - tbl_sdregl
21173 short sdregl1 - tbl_sdregl
21174 short sdregl2 - tbl_sdregl
21175 short sdregl3 - tbl_sdregl
21176 short sdregl4 - tbl_sdregl
21177 short sdregl5 - tbl_sdregl
21178 short sdregl6 - tbl_sdregl
21179 short sdregl7 - tbl_sdregl
21180
21181sdregl0:
21182 mov.l %d0,EXC_DREGS+0x0(%a6)
21183 rts
21184sdregl1:
21185 mov.l %d0,EXC_DREGS+0x4(%a6)
21186 rts
21187sdregl2:
21188 mov.l %d0,%d2
21189 rts
21190sdregl3:
21191 mov.l %d0,%d3
21192 rts
21193sdregl4:
21194 mov.l %d0,%d4
21195 rts
21196sdregl5:
21197 mov.l %d0,%d5
21198 rts
21199sdregl6:
21200 mov.l %d0,%d6
21201 rts
21202sdregl7:
21203 mov.l %d0,%d7
21204 rts
21205
21206#########################################################################
21207# XDEF **************************************************************** #
21208# store_dreg_w(): store word to data register specified by d1 #
21209# #
21210# XREF **************************************************************** #
21211# None #
21212# #
21213# INPUT *************************************************************** #
21214# d0 = word value to store #
21215# d1 = index of register to fetch from #
21216# #
21217# OUTPUT ************************************************************** #
21218# (data register is updated) #
21219# #
21220# ALGORITHM *********************************************************** #
21221# According to the index value in d1, store the word value #
21222# in d0 to the corresponding data register. D0/D1 are on the stack #
21223# while the rest are in their initial places. #
21224# #
21225#########################################################################
21226
21227 global store_dreg_w
21228store_dreg_w:
21229 mov.w (tbl_sdregw.b,%pc,%d1.w*2),%d1
21230 jmp (tbl_sdregw.b,%pc,%d1.w*1)
21231
21232tbl_sdregw:
21233 short sdregw0 - tbl_sdregw
21234 short sdregw1 - tbl_sdregw
21235 short sdregw2 - tbl_sdregw
21236 short sdregw3 - tbl_sdregw
21237 short sdregw4 - tbl_sdregw
21238 short sdregw5 - tbl_sdregw
21239 short sdregw6 - tbl_sdregw
21240 short sdregw7 - tbl_sdregw
21241
21242sdregw0:
21243 mov.w %d0,2+EXC_DREGS+0x0(%a6)
21244 rts
21245sdregw1:
21246 mov.w %d0,2+EXC_DREGS+0x4(%a6)
21247 rts
21248sdregw2:
21249 mov.w %d0,%d2
21250 rts
21251sdregw3:
21252 mov.w %d0,%d3
21253 rts
21254sdregw4:
21255 mov.w %d0,%d4
21256 rts
21257sdregw5:
21258 mov.w %d0,%d5
21259 rts
21260sdregw6:
21261 mov.w %d0,%d6
21262 rts
21263sdregw7:
21264 mov.w %d0,%d7
21265 rts
21266
21267#########################################################################
21268# XDEF **************************************************************** #
21269# store_dreg_b(): store byte to data register specified by d1 #
21270# #
21271# XREF **************************************************************** #
21272# None #
21273# #
21274# INPUT *************************************************************** #
21275# d0 = byte value to store #
21276# d1 = index of register to fetch from #
21277# #
21278# OUTPUT ************************************************************** #
21279# (data register is updated) #
21280# #
21281# ALGORITHM *********************************************************** #
21282# According to the index value in d1, store the byte value #
21283# in d0 to the corresponding data register. D0/D1 are on the stack #
21284# while the rest are in their initial places. #
21285# #
21286#########################################################################
21287
21288 global store_dreg_b
21289store_dreg_b:
21290 mov.w (tbl_sdregb.b,%pc,%d1.w*2),%d1
21291 jmp (tbl_sdregb.b,%pc,%d1.w*1)
21292
21293tbl_sdregb:
21294 short sdregb0 - tbl_sdregb
21295 short sdregb1 - tbl_sdregb
21296 short sdregb2 - tbl_sdregb
21297 short sdregb3 - tbl_sdregb
21298 short sdregb4 - tbl_sdregb
21299 short sdregb5 - tbl_sdregb
21300 short sdregb6 - tbl_sdregb
21301 short sdregb7 - tbl_sdregb
21302
21303sdregb0:
21304 mov.b %d0,3+EXC_DREGS+0x0(%a6)
21305 rts
21306sdregb1:
21307 mov.b %d0,3+EXC_DREGS+0x4(%a6)
21308 rts
21309sdregb2:
21310 mov.b %d0,%d2
21311 rts
21312sdregb3:
21313 mov.b %d0,%d3
21314 rts
21315sdregb4:
21316 mov.b %d0,%d4
21317 rts
21318sdregb5:
21319 mov.b %d0,%d5
21320 rts
21321sdregb6:
21322 mov.b %d0,%d6
21323 rts
21324sdregb7:
21325 mov.b %d0,%d7
21326 rts
21327
21328#########################################################################
21329# XDEF **************************************************************** #
21330# inc_areg(): increment an address register by the value in d0 #
21331# #
21332# XREF **************************************************************** #
21333# None #
21334# #
21335# INPUT *************************************************************** #
21336# d0 = amount to increment by #
21337# d1 = index of address register to increment #
21338# #
21339# OUTPUT ************************************************************** #
21340# (address register is updated) #
21341# #
21342# ALGORITHM *********************************************************** #
21343# Typically used for an instruction w/ a post-increment <ea>, #
21344# this routine adds the increment value in d0 to the address register #
21345# specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside #
21346# in their original places. #
21347# For a7, if the increment amount is one, then we have to #
21348# increment by two. For any a7 update, set the mia7_flag so that if #
21349# an access error exception occurs later in emulation, this address #
21350# register update can be undone. #
21351# #
21352#########################################################################
21353
21354 global inc_areg
21355inc_areg:
21356 mov.w (tbl_iareg.b,%pc,%d1.w*2),%d1
21357 jmp (tbl_iareg.b,%pc,%d1.w*1)
21358
21359tbl_iareg:
21360 short iareg0 - tbl_iareg
21361 short iareg1 - tbl_iareg
21362 short iareg2 - tbl_iareg
21363 short iareg3 - tbl_iareg
21364 short iareg4 - tbl_iareg
21365 short iareg5 - tbl_iareg
21366 short iareg6 - tbl_iareg
21367 short iareg7 - tbl_iareg
21368
21369iareg0: add.l %d0,EXC_DREGS+0x8(%a6)
21370 rts
21371iareg1: add.l %d0,EXC_DREGS+0xc(%a6)
21372 rts
21373iareg2: add.l %d0,%a2
21374 rts
21375iareg3: add.l %d0,%a3
21376 rts
21377iareg4: add.l %d0,%a4
21378 rts
21379iareg5: add.l %d0,%a5
21380 rts
21381iareg6: add.l %d0,(%a6)
21382 rts
21383iareg7: mov.b &mia7_flg,SPCOND_FLG(%a6)
21384 cmpi.b %d0,&0x1
21385 beq.b iareg7b
21386 add.l %d0,EXC_A7(%a6)
21387 rts
21388iareg7b:
21389 addq.l &0x2,EXC_A7(%a6)
21390 rts
21391
21392#########################################################################
21393# XDEF **************************************************************** #
21394# dec_areg(): decrement an address register by the value in d0 #
21395# #
21396# XREF **************************************************************** #
21397# None #
21398# #
21399# INPUT *************************************************************** #
21400# d0 = amount to decrement by #
21401# d1 = index of address register to decrement #
21402# #
21403# OUTPUT ************************************************************** #
21404# (address register is updated) #
21405# #
21406# ALGORITHM *********************************************************** #
21407# Typically used for an instruction w/ a pre-decrement <ea>, #
21408# this routine adds the decrement value in d0 to the address register #
21409# specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside #
21410# in their original places. #
21411# For a7, if the decrement amount is one, then we have to #
21412# decrement by two. For any a7 update, set the mda7_flag so that if #
21413# an access error exception occurs later in emulation, this address #
21414# register update can be undone. #
21415# #
21416#########################################################################
21417
21418 global dec_areg
21419dec_areg:
21420 mov.w (tbl_dareg.b,%pc,%d1.w*2),%d1
21421 jmp (tbl_dareg.b,%pc,%d1.w*1)
21422
21423tbl_dareg:
21424 short dareg0 - tbl_dareg
21425 short dareg1 - tbl_dareg
21426 short dareg2 - tbl_dareg
21427 short dareg3 - tbl_dareg
21428 short dareg4 - tbl_dareg
21429 short dareg5 - tbl_dareg
21430 short dareg6 - tbl_dareg
21431 short dareg7 - tbl_dareg
21432
21433dareg0: sub.l %d0,EXC_DREGS+0x8(%a6)
21434 rts
21435dareg1: sub.l %d0,EXC_DREGS+0xc(%a6)
21436 rts
21437dareg2: sub.l %d0,%a2
21438 rts
21439dareg3: sub.l %d0,%a3
21440 rts
21441dareg4: sub.l %d0,%a4
21442 rts
21443dareg5: sub.l %d0,%a5
21444 rts
21445dareg6: sub.l %d0,(%a6)
21446 rts
21447dareg7: mov.b &mda7_flg,SPCOND_FLG(%a6)
21448 cmpi.b %d0,&0x1
21449 beq.b dareg7b
21450 sub.l %d0,EXC_A7(%a6)
21451 rts
21452dareg7b:
21453 subq.l &0x2,EXC_A7(%a6)
21454 rts
21455
21456##############################################################################
21457
21458#########################################################################
21459# XDEF **************************************************************** #
21460# load_fpn1(): load FP register value into FP_SRC(a6). #
21461# #
21462# XREF **************************************************************** #
21463# None #
21464# #
21465# INPUT *************************************************************** #
21466# d0 = index of FP register to load #
21467# #
21468# OUTPUT ************************************************************** #
21469# FP_SRC(a6) = value loaded from FP register file #
21470# #
21471# ALGORITHM *********************************************************** #
21472# Using the index in d0, load FP_SRC(a6) with a number from the #
21473# FP register file. #
21474# #
21475#########################################################################
21476
21477 global load_fpn1
21478load_fpn1:
21479 mov.w (tbl_load_fpn1.b,%pc,%d0.w*2), %d0
21480 jmp (tbl_load_fpn1.b,%pc,%d0.w*1)
21481
21482tbl_load_fpn1:
21483 short load_fpn1_0 - tbl_load_fpn1
21484 short load_fpn1_1 - tbl_load_fpn1
21485 short load_fpn1_2 - tbl_load_fpn1
21486 short load_fpn1_3 - tbl_load_fpn1
21487 short load_fpn1_4 - tbl_load_fpn1
21488 short load_fpn1_5 - tbl_load_fpn1
21489 short load_fpn1_6 - tbl_load_fpn1
21490 short load_fpn1_7 - tbl_load_fpn1
21491
21492load_fpn1_0:
21493 mov.l 0+EXC_FP0(%a6), 0+FP_SRC(%a6)
21494 mov.l 4+EXC_FP0(%a6), 4+FP_SRC(%a6)
21495 mov.l 8+EXC_FP0(%a6), 8+FP_SRC(%a6)
21496 lea FP_SRC(%a6), %a0
21497 rts
21498load_fpn1_1:
21499 mov.l 0+EXC_FP1(%a6), 0+FP_SRC(%a6)
21500 mov.l 4+EXC_FP1(%a6), 4+FP_SRC(%a6)
21501 mov.l 8+EXC_FP1(%a6), 8+FP_SRC(%a6)
21502 lea FP_SRC(%a6), %a0
21503 rts
21504load_fpn1_2:
21505 fmovm.x &0x20, FP_SRC(%a6)
21506 lea FP_SRC(%a6), %a0
21507 rts
21508load_fpn1_3:
21509 fmovm.x &0x10, FP_SRC(%a6)
21510 lea FP_SRC(%a6), %a0
21511 rts
21512load_fpn1_4:
21513 fmovm.x &0x08, FP_SRC(%a6)
21514 lea FP_SRC(%a6), %a0
21515 rts
21516load_fpn1_5:
21517 fmovm.x &0x04, FP_SRC(%a6)
21518 lea FP_SRC(%a6), %a0
21519 rts
21520load_fpn1_6:
21521 fmovm.x &0x02, FP_SRC(%a6)
21522 lea FP_SRC(%a6), %a0
21523 rts
21524load_fpn1_7:
21525 fmovm.x &0x01, FP_SRC(%a6)
21526 lea FP_SRC(%a6), %a0
21527 rts
21528
21529#############################################################################
21530
21531#########################################################################
21532# XDEF **************************************************************** #
21533# load_fpn2(): load FP register value into FP_DST(a6). #
21534# #
21535# XREF **************************************************************** #
21536# None #
21537# #
21538# INPUT *************************************************************** #
21539# d0 = index of FP register to load #
21540# #
21541# OUTPUT ************************************************************** #
21542# FP_DST(a6) = value loaded from FP register file #
21543# #
21544# ALGORITHM *********************************************************** #
21545# Using the index in d0, load FP_DST(a6) with a number from the #
21546# FP register file. #
21547# #
21548#########################################################################
21549
21550 global load_fpn2
21551load_fpn2:
21552 mov.w (tbl_load_fpn2.b,%pc,%d0.w*2), %d0
21553 jmp (tbl_load_fpn2.b,%pc,%d0.w*1)
21554
21555tbl_load_fpn2:
21556 short load_fpn2_0 - tbl_load_fpn2
21557 short load_fpn2_1 - tbl_load_fpn2
21558 short load_fpn2_2 - tbl_load_fpn2
21559 short load_fpn2_3 - tbl_load_fpn2
21560 short load_fpn2_4 - tbl_load_fpn2
21561 short load_fpn2_5 - tbl_load_fpn2
21562 short load_fpn2_6 - tbl_load_fpn2
21563 short load_fpn2_7 - tbl_load_fpn2
21564
21565load_fpn2_0:
21566 mov.l 0+EXC_FP0(%a6), 0+FP_DST(%a6)
21567 mov.l 4+EXC_FP0(%a6), 4+FP_DST(%a6)
21568 mov.l 8+EXC_FP0(%a6), 8+FP_DST(%a6)
21569 lea FP_DST(%a6), %a0
21570 rts
21571load_fpn2_1:
21572 mov.l 0+EXC_FP1(%a6), 0+FP_DST(%a6)
21573 mov.l 4+EXC_FP1(%a6), 4+FP_DST(%a6)
21574 mov.l 8+EXC_FP1(%a6), 8+FP_DST(%a6)
21575 lea FP_DST(%a6), %a0
21576 rts
21577load_fpn2_2:
21578 fmovm.x &0x20, FP_DST(%a6)
21579 lea FP_DST(%a6), %a0
21580 rts
21581load_fpn2_3:
21582 fmovm.x &0x10, FP_DST(%a6)
21583 lea FP_DST(%a6), %a0
21584 rts
21585load_fpn2_4:
21586 fmovm.x &0x08, FP_DST(%a6)
21587 lea FP_DST(%a6), %a0
21588 rts
21589load_fpn2_5:
21590 fmovm.x &0x04, FP_DST(%a6)
21591 lea FP_DST(%a6), %a0
21592 rts
21593load_fpn2_6:
21594 fmovm.x &0x02, FP_DST(%a6)
21595 lea FP_DST(%a6), %a0
21596 rts
21597load_fpn2_7:
21598 fmovm.x &0x01, FP_DST(%a6)
21599 lea FP_DST(%a6), %a0
21600 rts
21601
21602#############################################################################
21603
21604#########################################################################
21605# XDEF **************************************************************** #
21606# store_fpreg(): store an fp value to the fpreg designated d0. #
21607# #
21608# XREF **************************************************************** #
21609# None #
21610# #
21611# INPUT *************************************************************** #
21612# fp0 = extended precision value to store #
21613# d0 = index of floating-point register #
21614# #
21615# OUTPUT ************************************************************** #
21616# None #
21617# #
21618# ALGORITHM *********************************************************** #
21619# Store the value in fp0 to the FP register designated by the #
21620# value in d0. The FP number can be DENORM or SNAN so we have to be #
21621# careful that we don't take an exception here. #
21622# #
21623#########################################################################
21624
21625 global store_fpreg
21626store_fpreg:
21627 mov.w (tbl_store_fpreg.b,%pc,%d0.w*2), %d0
21628 jmp (tbl_store_fpreg.b,%pc,%d0.w*1)
21629
21630tbl_store_fpreg:
21631 short store_fpreg_0 - tbl_store_fpreg
21632 short store_fpreg_1 - tbl_store_fpreg
21633 short store_fpreg_2 - tbl_store_fpreg
21634 short store_fpreg_3 - tbl_store_fpreg
21635 short store_fpreg_4 - tbl_store_fpreg
21636 short store_fpreg_5 - tbl_store_fpreg
21637 short store_fpreg_6 - tbl_store_fpreg
21638 short store_fpreg_7 - tbl_store_fpreg
21639
21640store_fpreg_0:
21641 fmovm.x &0x80, EXC_FP0(%a6)
21642 rts
21643store_fpreg_1:
21644 fmovm.x &0x80, EXC_FP1(%a6)
21645 rts
21646store_fpreg_2:
21647 fmovm.x &0x01, -(%sp)
21648 fmovm.x (%sp)+, &0x20
21649 rts
21650store_fpreg_3:
21651 fmovm.x &0x01, -(%sp)
21652 fmovm.x (%sp)+, &0x10
21653 rts
21654store_fpreg_4:
21655 fmovm.x &0x01, -(%sp)
21656 fmovm.x (%sp)+, &0x08
21657 rts
21658store_fpreg_5:
21659 fmovm.x &0x01, -(%sp)
21660 fmovm.x (%sp)+, &0x04
21661 rts
21662store_fpreg_6:
21663 fmovm.x &0x01, -(%sp)
21664 fmovm.x (%sp)+, &0x02
21665 rts
21666store_fpreg_7:
21667 fmovm.x &0x01, -(%sp)
21668 fmovm.x (%sp)+, &0x01
21669 rts
21670
21671#########################################################################
21672# XDEF **************************************************************** #
21673# _denorm(): denormalize an intermediate result #
21674# #
21675# XREF **************************************************************** #
21676# None #
21677# #
21678# INPUT *************************************************************** #
21679# a0 = points to the operand to be denormalized #
21680# (in the internal extended format) #
21681# #
21682# d0 = rounding precision #
21683# #
21684# OUTPUT ************************************************************** #
21685# a0 = pointer to the denormalized result #
21686# (in the internal extended format) #
21687# #
21688# d0 = guard,round,sticky #
21689# #
21690# ALGORITHM *********************************************************** #
21691# According to the exponent underflow threshold for the given #
21692# precision, shift the mantissa bits to the right in order raise the #
21693# exponent of the operand to the threshold value. While shifting the #
21694# mantissa bits right, maintain the value of the guard, round, and #
21695# sticky bits. #
21696# other notes: #
21697# (1) _denorm() is called by the underflow routines #
21698# (2) _denorm() does NOT affect the status register #
21699# #
21700#########################################################################
21701
21702#
21703# table of exponent threshold values for each precision
21704#
21705tbl_thresh:
21706 short 0x0
21707 short sgl_thresh
21708 short dbl_thresh
21709
21710 global _denorm
21711_denorm:
21712#
21713# Load the exponent threshold for the precision selected and check
21714# to see if (threshold - exponent) is > 65 in which case we can
21715# simply calculate the sticky bit and zero the mantissa. otherwise
21716# we have to call the denormalization routine.
21717#
21718 lsr.b &0x2, %d0 # shift prec to lo bits
21719 mov.w (tbl_thresh.b,%pc,%d0.w*2), %d1 # load prec threshold
21720 mov.w %d1, %d0 # copy d1 into d0
21721 sub.w FTEMP_EX(%a0), %d0 # diff = threshold - exp
21722 cmpi.w %d0, &66 # is diff > 65? (mant + g,r bits)
21723 bpl.b denorm_set_stky # yes; just calc sticky
21724
21725 clr.l %d0 # clear g,r,s
21726 btst &inex2_bit, FPSR_EXCEPT(%a6) # yes; was INEX2 set?
21727 beq.b denorm_call # no; don't change anything
21728 bset &29, %d0 # yes; set sticky bit
21729
21730denorm_call:
21731 bsr.l dnrm_lp # denormalize the number
21732 rts
21733
21734#
21735# all bit would have been shifted off during the denorm so simply
21736# calculate if the sticky should be set and clear the entire mantissa.
21737#
21738denorm_set_stky:
21739 mov.l &0x20000000, %d0 # set sticky bit in return value
21740 mov.w %d1, FTEMP_EX(%a0) # load exp with threshold
21741 clr.l FTEMP_HI(%a0) # set d1 = 0 (ms mantissa)
21742 clr.l FTEMP_LO(%a0) # set d2 = 0 (ms mantissa)
21743 rts
21744
21745# #
21746# dnrm_lp(): normalize exponent/mantissa to specified threshhold #
21747# #
21748# INPUT: #
21749# %a0 : points to the operand to be denormalized #
21750# %d0{31:29} : initial guard,round,sticky #
21751# %d1{15:0} : denormalization threshold #
21752# OUTPUT: #
21753# %a0 : points to the denormalized operand #
21754# %d0{31:29} : final guard,round,sticky #
21755# #
21756
21757# *** Local Equates *** #
21758set GRS, L_SCR2 # g,r,s temp storage
21759set FTEMP_LO2, L_SCR1 # FTEMP_LO copy
21760
21761 global dnrm_lp
21762dnrm_lp:
21763
21764#
21765# make a copy of FTEMP_LO and place the g,r,s bits directly after it
21766# in memory so as to make the bitfield extraction for denormalization easier.
21767#
21768 mov.l FTEMP_LO(%a0), FTEMP_LO2(%a6) # make FTEMP_LO copy
21769 mov.l %d0, GRS(%a6) # place g,r,s after it
21770
21771#
21772# check to see how much less than the underflow threshold the operand
21773# exponent is.
21774#
21775 mov.l %d1, %d0 # copy the denorm threshold
21776 sub.w FTEMP_EX(%a0), %d1 # d1 = threshold - uns exponent
21777 ble.b dnrm_no_lp # d1 <= 0
21778 cmpi.w %d1, &0x20 # is ( 0 <= d1 < 32) ?
21779 blt.b case_1 # yes
21780 cmpi.w %d1, &0x40 # is (32 <= d1 < 64) ?
21781 blt.b case_2 # yes
21782 bra.w case_3 # (d1 >= 64)
21783
21784#
21785# No normalization necessary
21786#
21787dnrm_no_lp:
21788 mov.l GRS(%a6), %d0 # restore original g,r,s
21789 rts
21790
21791#
21792# case (0<d1<32)
21793#
21794# %d0 = denorm threshold
21795# %d1 = "n" = amt to shift
21796#
21797# ---------------------------------------------------------
21798# | FTEMP_HI | FTEMP_LO |grs000.........000|
21799# ---------------------------------------------------------
21800# <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
21801# \ \ \ \
21802# \ \ \ \
21803# \ \ \ \
21804# \ \ \ \
21805# \ \ \ \
21806# \ \ \ \
21807# \ \ \ \
21808# \ \ \ \
21809# <-(n)-><-(32 - n)-><------(32)-------><------(32)------->
21810# ---------------------------------------------------------
21811# |0.....0| NEW_HI | NEW_FTEMP_LO |grs |
21812# ---------------------------------------------------------
21813#
21814case_1:
21815 mov.l %d2, -(%sp) # create temp storage
21816
21817 mov.w %d0, FTEMP_EX(%a0) # exponent = denorm threshold
21818 mov.l &32, %d0
21819 sub.w %d1, %d0 # %d0 = 32 - %d1
21820
21821 cmpi.w %d1, &29 # is shft amt >= 29
21822 blt.b case1_extract # no; no fix needed
21823 mov.b GRS(%a6), %d2
21824 or.b %d2, 3+FTEMP_LO2(%a6)
21825
21826case1_extract:
21827 bfextu FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_HI
21828 bfextu FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new FTEMP_LO
21829 bfextu FTEMP_LO2(%a6){%d0:&32}, %d0 # %d0 = new G,R,S
21830
21831 mov.l %d2, FTEMP_HI(%a0) # store new FTEMP_HI
21832 mov.l %d1, FTEMP_LO(%a0) # store new FTEMP_LO
21833
21834 bftst %d0{&2:&30} # were bits shifted off?
21835 beq.b case1_sticky_clear # no; go finish
21836 bset &rnd_stky_bit, %d0 # yes; set sticky bit
21837
21838case1_sticky_clear:
21839 and.l &0xe0000000, %d0 # clear all but G,R,S
21840 mov.l (%sp)+, %d2 # restore temp register
21841 rts
21842
21843#
21844# case (32<=d1<64)
21845#
21846# %d0 = denorm threshold
21847# %d1 = "n" = amt to shift
21848#
21849# ---------------------------------------------------------
21850# | FTEMP_HI | FTEMP_LO |grs000.........000|
21851# ---------------------------------------------------------
21852# <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
21853# \ \ \
21854# \ \ \
21855# \ \ -------------------
21856# \ -------------------- \
21857# ------------------- \ \
21858# \ \ \
21859# \ \ \
21860# \ \ \
21861# <-------(32)------><-(n)-><-(32 - n)-><------(32)------->
21862# ---------------------------------------------------------
21863# |0...............0|0....0| NEW_LO |grs |
21864# ---------------------------------------------------------
21865#
21866case_2:
21867 mov.l %d2, -(%sp) # create temp storage
21868
21869 mov.w %d0, FTEMP_EX(%a0) # exponent = denorm threshold
21870 subi.w &0x20, %d1 # %d1 now between 0 and 32
21871 mov.l &0x20, %d0
21872 sub.w %d1, %d0 # %d0 = 32 - %d1
21873
21874# subtle step here; or in the g,r,s at the bottom of FTEMP_LO to minimize
21875# the number of bits to check for the sticky detect.
21876# it only plays a role in shift amounts of 61-63.
21877 mov.b GRS(%a6), %d2
21878 or.b %d2, 3+FTEMP_LO2(%a6)
21879
21880 bfextu FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_LO
21881 bfextu FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new G,R,S
21882
21883 bftst %d1{&2:&30} # were any bits shifted off?
21884 bne.b case2_set_sticky # yes; set sticky bit
21885 bftst FTEMP_LO2(%a6){%d0:&31} # were any bits shifted off?
21886 bne.b case2_set_sticky # yes; set sticky bit
21887
21888 mov.l %d1, %d0 # move new G,R,S to %d0
21889 bra.b case2_end
21890
21891case2_set_sticky:
21892 mov.l %d1, %d0 # move new G,R,S to %d0
21893 bset &rnd_stky_bit, %d0 # set sticky bit
21894
21895case2_end:
21896 clr.l FTEMP_HI(%a0) # store FTEMP_HI = 0
21897 mov.l %d2, FTEMP_LO(%a0) # store FTEMP_LO
21898 and.l &0xe0000000, %d0 # clear all but G,R,S
21899
21900 mov.l (%sp)+,%d2 # restore temp register
21901 rts
21902
21903#
21904# case (d1>=64)
21905#
21906# %d0 = denorm threshold
21907# %d1 = amt to shift
21908#
21909case_3:
21910 mov.w %d0, FTEMP_EX(%a0) # insert denorm threshold
21911
21912 cmpi.w %d1, &65 # is shift amt > 65?
21913 blt.b case3_64 # no; it's == 64
21914 beq.b case3_65 # no; it's == 65
21915
21916#
21917# case (d1>65)
21918#
21919# Shift value is > 65 and out of range. All bits are shifted off.
21920# Return a zero mantissa with the sticky bit set
21921#
21922 clr.l FTEMP_HI(%a0) # clear hi(mantissa)
21923 clr.l FTEMP_LO(%a0) # clear lo(mantissa)
21924 mov.l &0x20000000, %d0 # set sticky bit
21925 rts
21926
21927#
21928# case (d1 == 64)
21929#
21930# ---------------------------------------------------------
21931# | FTEMP_HI | FTEMP_LO |grs000.........000|
21932# ---------------------------------------------------------
21933# <-------(32)------>
21934# \ \
21935# \ \
21936# \ \
21937# \ ------------------------------
21938# ------------------------------- \
21939# \ \
21940# \ \
21941# \ \
21942# <-------(32)------>
21943# ---------------------------------------------------------
21944# |0...............0|0................0|grs |
21945# ---------------------------------------------------------
21946#
21947case3_64:
21948 mov.l FTEMP_HI(%a0), %d0 # fetch hi(mantissa)
21949 mov.l %d0, %d1 # make a copy
21950 and.l &0xc0000000, %d0 # extract G,R
21951 and.l &0x3fffffff, %d1 # extract other bits
21952
21953 bra.b case3_complete
21954
21955#
21956# case (d1 == 65)
21957#
21958# ---------------------------------------------------------
21959# | FTEMP_HI | FTEMP_LO |grs000.........000|
21960# ---------------------------------------------------------
21961# <-------(32)------>
21962# \ \
21963# \ \
21964# \ \
21965# \ ------------------------------
21966# -------------------------------- \
21967# \ \
21968# \ \
21969# \ \
21970# <-------(31)----->
21971# ---------------------------------------------------------
21972# |0...............0|0................0|0rs |
21973# ---------------------------------------------------------
21974#
21975case3_65:
21976 mov.l FTEMP_HI(%a0), %d0 # fetch hi(mantissa)
21977 and.l &0x80000000, %d0 # extract R bit
21978 lsr.l &0x1, %d0 # shift high bit into R bit
21979 and.l &0x7fffffff, %d1 # extract other bits
21980
21981case3_complete:
21982# last operation done was an "and" of the bits shifted off so the condition
21983# codes are already set so branch accordingly.
21984 bne.b case3_set_sticky # yes; go set new sticky
21985 tst.l FTEMP_LO(%a0) # were any bits shifted off?
21986 bne.b case3_set_sticky # yes; go set new sticky
21987 tst.b GRS(%a6) # were any bits shifted off?
21988 bne.b case3_set_sticky # yes; go set new sticky
21989
21990#
21991# no bits were shifted off so don't set the sticky bit.
21992# the guard and
21993# the entire mantissa is zero.
21994#
21995 clr.l FTEMP_HI(%a0) # clear hi(mantissa)
21996 clr.l FTEMP_LO(%a0) # clear lo(mantissa)
21997 rts
21998
21999#
22000# some bits were shifted off so set the sticky bit.
22001# the entire mantissa is zero.
22002#
22003case3_set_sticky:
22004 bset &rnd_stky_bit,%d0 # set new sticky bit
22005 clr.l FTEMP_HI(%a0) # clear hi(mantissa)
22006 clr.l FTEMP_LO(%a0) # clear lo(mantissa)
22007 rts
22008
22009#########################################################################
22010# XDEF **************************************************************** #
22011# _round(): round result according to precision/mode #
22012# #
22013# XREF **************************************************************** #
22014# None #
22015# #
22016# INPUT *************************************************************** #
22017# a0 = ptr to input operand in internal extended format #
22018# d1(hi) = contains rounding precision: #
22019# ext = $0000xxxx #
22020# sgl = $0004xxxx #
22021# dbl = $0008xxxx #
22022# d1(lo) = contains rounding mode: #
22023# RN = $xxxx0000 #
22024# RZ = $xxxx0001 #
22025# RM = $xxxx0002 #
22026# RP = $xxxx0003 #
22027# d0{31:29} = contains the g,r,s bits (extended) #
22028# #
22029# OUTPUT ************************************************************** #
22030# a0 = pointer to rounded result #
22031# #
22032# ALGORITHM *********************************************************** #
22033# On return the value pointed to by a0 is correctly rounded, #
22034# a0 is preserved and the g-r-s bits in d0 are cleared. #
22035# The result is not typed - the tag field is invalid. The #
22036# result is still in the internal extended format. #
22037# #
22038# The INEX bit of USER_FPSR will be set if the rounded result was #
22039# inexact (i.e. if any of the g-r-s bits were set). #
22040# #
22041#########################################################################
22042
22043 global _round
22044_round:
22045#
22046# ext_grs() looks at the rounding precision and sets the appropriate
22047# G,R,S bits.
22048# If (G,R,S == 0) then result is exact and round is done, else set
22049# the inex flag in status reg and continue.
22050#
22051 bsr.l ext_grs # extract G,R,S
22052
22053 tst.l %d0 # are G,R,S zero?
22054 beq.w truncate # yes; round is complete
22055
22056 or.w &inx2a_mask, 2+USER_FPSR(%a6) # set inex2/ainex
22057
22058#
22059# Use rounding mode as an index into a jump table for these modes.
22060# All of the following assumes grs != 0.
22061#
22062 mov.w (tbl_mode.b,%pc,%d1.w*2), %a1 # load jump offset
22063 jmp (tbl_mode.b,%pc,%a1) # jmp to rnd mode handler
22064
22065tbl_mode:
22066 short rnd_near - tbl_mode
22067 short truncate - tbl_mode # RZ always truncates
22068 short rnd_mnus - tbl_mode
22069 short rnd_plus - tbl_mode
22070
22071#################################################################
22072# ROUND PLUS INFINITY #
22073# #
22074# If sign of fp number = 0 (positive), then add 1 to l. #
22075#################################################################
22076rnd_plus:
22077 tst.b FTEMP_SGN(%a0) # check for sign
22078 bmi.w truncate # if positive then truncate
22079
22080 mov.l &0xffffffff, %d0 # force g,r,s to be all f's
22081 swap %d1 # set up d1 for round prec.
22082
22083 cmpi.b %d1, &s_mode # is prec = sgl?
22084 beq.w add_sgl # yes
22085 bgt.w add_dbl # no; it's dbl
22086 bra.w add_ext # no; it's ext
22087
22088#################################################################
22089# ROUND MINUS INFINITY #
22090# #
22091# If sign of fp number = 1 (negative), then add 1 to l. #
22092#################################################################
22093rnd_mnus:
22094 tst.b FTEMP_SGN(%a0) # check for sign
22095 bpl.w truncate # if negative then truncate
22096
22097 mov.l &0xffffffff, %d0 # force g,r,s to be all f's
22098 swap %d1 # set up d1 for round prec.
22099
22100 cmpi.b %d1, &s_mode # is prec = sgl?
22101 beq.w add_sgl # yes
22102 bgt.w add_dbl # no; it's dbl
22103 bra.w add_ext # no; it's ext
22104
22105#################################################################
22106# ROUND NEAREST #
22107# #
22108# If (g=1), then add 1 to l and if (r=s=0), then clear l #
22109# Note that this will round to even in case of a tie. #
22110#################################################################
22111rnd_near:
22112 asl.l &0x1, %d0 # shift g-bit to c-bit
22113 bcc.w truncate # if (g=1) then
22114
22115 swap %d1 # set up d1 for round prec.
22116
22117 cmpi.b %d1, &s_mode # is prec = sgl?
22118 beq.w add_sgl # yes
22119 bgt.w add_dbl # no; it's dbl
22120 bra.w add_ext # no; it's ext
22121
22122# *** LOCAL EQUATES ***
22123set ad_1_sgl, 0x00000100 # constant to add 1 to l-bit in sgl prec
22124set ad_1_dbl, 0x00000800 # constant to add 1 to l-bit in dbl prec
22125
22126#########################
22127# ADD SINGLE #
22128#########################
22129add_sgl:
22130 add.l &ad_1_sgl, FTEMP_HI(%a0)
22131 bcc.b scc_clr # no mantissa overflow
22132 roxr.w FTEMP_HI(%a0) # shift v-bit back in
22133 roxr.w FTEMP_HI+2(%a0) # shift v-bit back in
22134 add.w &0x1, FTEMP_EX(%a0) # and incr exponent
22135scc_clr:
22136 tst.l %d0 # test for rs = 0
22137 bne.b sgl_done
22138 and.w &0xfe00, FTEMP_HI+2(%a0) # clear the l-bit
22139sgl_done:
22140 and.l &0xffffff00, FTEMP_HI(%a0) # truncate bits beyond sgl limit
22141 clr.l FTEMP_LO(%a0) # clear d2
22142 rts
22143
22144#########################
22145# ADD EXTENDED #
22146#########################
22147add_ext:
22148 addq.l &1,FTEMP_LO(%a0) # add 1 to l-bit
22149 bcc.b xcc_clr # test for carry out
22150 addq.l &1,FTEMP_HI(%a0) # propagate carry
22151 bcc.b xcc_clr
22152 roxr.w FTEMP_HI(%a0) # mant is 0 so restore v-bit
22153 roxr.w FTEMP_HI+2(%a0) # mant is 0 so restore v-bit
22154 roxr.w FTEMP_LO(%a0)
22155 roxr.w FTEMP_LO+2(%a0)
22156 add.w &0x1,FTEMP_EX(%a0) # and inc exp
22157xcc_clr:
22158 tst.l %d0 # test rs = 0
22159 bne.b add_ext_done
22160 and.b &0xfe,FTEMP_LO+3(%a0) # clear the l bit
22161add_ext_done:
22162 rts
22163
22164#########################
22165# ADD DOUBLE #
22166#########################
22167add_dbl:
22168 add.l &ad_1_dbl, FTEMP_LO(%a0) # add 1 to lsb
22169 bcc.b dcc_clr # no carry
22170 addq.l &0x1, FTEMP_HI(%a0) # propagate carry
22171 bcc.b dcc_clr # no carry
22172
22173 roxr.w FTEMP_HI(%a0) # mant is 0 so restore v-bit
22174 roxr.w FTEMP_HI+2(%a0) # mant is 0 so restore v-bit
22175 roxr.w FTEMP_LO(%a0)
22176 roxr.w FTEMP_LO+2(%a0)
22177 addq.w &0x1, FTEMP_EX(%a0) # incr exponent
22178dcc_clr:
22179 tst.l %d0 # test for rs = 0
22180 bne.b dbl_done
22181 and.w &0xf000, FTEMP_LO+2(%a0) # clear the l-bit
22182
22183dbl_done:
22184 and.l &0xfffff800,FTEMP_LO(%a0) # truncate bits beyond dbl limit
22185 rts
22186
22187###########################
22188# Truncate all other bits #
22189###########################
22190truncate:
22191 swap %d1 # select rnd prec
22192
22193 cmpi.b %d1, &s_mode # is prec sgl?
22194 beq.w sgl_done # yes
22195 bgt.b dbl_done # no; it's dbl
22196 rts # no; it's ext
22197
22198
22199#
22200# ext_grs(): extract guard, round and sticky bits according to
22201# rounding precision.
22202#
22203# INPUT
22204# d0 = extended precision g,r,s (in d0{31:29})
22205# d1 = {PREC,ROUND}
22206# OUTPUT
22207# d0{31:29} = guard, round, sticky
22208#
22209# The ext_grs extract the guard/round/sticky bits according to the
22210# selected rounding precision. It is called by the round subroutine
22211# only. All registers except d0 are kept intact. d0 becomes an
22212# updated guard,round,sticky in d0{31:29}
22213#
22214# Notes: the ext_grs uses the round PREC, and therefore has to swap d1
22215# prior to usage, and needs to restore d1 to original. this
22216# routine is tightly tied to the round routine and not meant to
22217# uphold standard subroutine calling practices.
22218#
22219
22220ext_grs:
22221 swap %d1 # have d1.w point to round precision
22222 tst.b %d1 # is rnd prec = extended?
22223 bne.b ext_grs_not_ext # no; go handle sgl or dbl
22224
22225#
22226# %d0 actually already hold g,r,s since _round() had it before calling
22227# this function. so, as long as we don't disturb it, we are "returning" it.
22228#
22229ext_grs_ext:
22230 swap %d1 # yes; return to correct positions
22231 rts
22232
22233ext_grs_not_ext:
22234 movm.l &0x3000, -(%sp) # make some temp registers {d2/d3}
22235
22236 cmpi.b %d1, &s_mode # is rnd prec = sgl?
22237 bne.b ext_grs_dbl # no; go handle dbl
22238
22239#
22240# sgl:
22241# 96 64 40 32 0
22242# -----------------------------------------------------
22243# | EXP |XXXXXXX| |xx | |grs|
22244# -----------------------------------------------------
22245# <--(24)--->nn\ /
22246# ee ---------------------
22247# ww |
22248# v
22249# gr new sticky
22250#
22251ext_grs_sgl:
22252 bfextu FTEMP_HI(%a0){&24:&2}, %d3 # sgl prec. g-r are 2 bits right
22253 mov.l &30, %d2 # of the sgl prec. limits
22254 lsl.l %d2, %d3 # shift g-r bits to MSB of d3
22255 mov.l FTEMP_HI(%a0), %d2 # get word 2 for s-bit test
22256 and.l &0x0000003f, %d2 # s bit is the or of all other
22257 bne.b ext_grs_st_stky # bits to the right of g-r
22258 tst.l FTEMP_LO(%a0) # test lower mantissa
22259 bne.b ext_grs_st_stky # if any are set, set sticky
22260 tst.l %d0 # test original g,r,s
22261 bne.b ext_grs_st_stky # if any are set, set sticky
22262 bra.b ext_grs_end_sd # if words 3 and 4 are clr, exit
22263
22264#
22265# dbl:
22266# 96 64 32 11 0
22267# -----------------------------------------------------
22268# | EXP |XXXXXXX| | |xx |grs|
22269# -----------------------------------------------------
22270# nn\ /
22271# ee -------
22272# ww |
22273# v
22274# gr new sticky
22275#
22276ext_grs_dbl:
22277 bfextu FTEMP_LO(%a0){&21:&2}, %d3 # dbl-prec. g-r are 2 bits right
22278 mov.l &30, %d2 # of the dbl prec. limits
22279 lsl.l %d2, %d3 # shift g-r bits to the MSB of d3
22280 mov.l FTEMP_LO(%a0), %d2 # get lower mantissa for s-bit test
22281 and.l &0x000001ff, %d2 # s bit is the or-ing of all
22282 bne.b ext_grs_st_stky # other bits to the right of g-r
22283 tst.l %d0 # test word original g,r,s
22284 bne.b ext_grs_st_stky # if any are set, set sticky
22285 bra.b ext_grs_end_sd # if clear, exit
22286
22287ext_grs_st_stky:
22288 bset &rnd_stky_bit, %d3 # set sticky bit
22289ext_grs_end_sd:
22290 mov.l %d3, %d0 # return grs to d0
22291
22292 movm.l (%sp)+, &0xc # restore scratch registers {d2/d3}
22293
22294 swap %d1 # restore d1 to original
22295 rts
22296
22297#########################################################################
22298# norm(): normalize the mantissa of an extended precision input. the #
22299# input operand should not be normalized already. #
22300# #
22301# XDEF **************************************************************** #
22302# norm() #
22303# #
22304# XREF **************************************************************** #
22305# none #
22306# #
22307# INPUT *************************************************************** #
22308# a0 = pointer fp extended precision operand to normalize #
22309# #
22310# OUTPUT ************************************************************** #
22311# d0 = number of bit positions the mantissa was shifted #
22312# a0 = the input operand's mantissa is normalized; the exponent #
22313# is unchanged. #
22314# #
22315#########################################################################
22316 global norm
22317norm:
22318 mov.l %d2, -(%sp) # create some temp regs
22319 mov.l %d3, -(%sp)
22320
22321 mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)
22322 mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)
22323
22324 bfffo %d0{&0:&32}, %d2 # how many places to shift?
22325 beq.b norm_lo # hi(man) is all zeroes!
22326
22327norm_hi:
22328 lsl.l %d2, %d0 # left shift hi(man)
22329 bfextu %d1{&0:%d2}, %d3 # extract lo bits
22330
22331 or.l %d3, %d0 # create hi(man)
22332 lsl.l %d2, %d1 # create lo(man)
22333
22334 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
22335 mov.l %d1, FTEMP_LO(%a0) # store new lo(man)
22336
22337 mov.l %d2, %d0 # return shift amount
22338
22339 mov.l (%sp)+, %d3 # restore temp regs
22340 mov.l (%sp)+, %d2
22341
22342 rts
22343
22344norm_lo:
22345 bfffo %d1{&0:&32}, %d2 # how many places to shift?
22346 lsl.l %d2, %d1 # shift lo(man)
22347 add.l &32, %d2 # add 32 to shft amount
22348
22349 mov.l %d1, FTEMP_HI(%a0) # store hi(man)
22350 clr.l FTEMP_LO(%a0) # lo(man) is now zero
22351
22352 mov.l %d2, %d0 # return shift amount
22353
22354 mov.l (%sp)+, %d3 # restore temp regs
22355 mov.l (%sp)+, %d2
22356
22357 rts
22358
22359#########################################################################
22360# unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #
22361# - returns corresponding optype tag #
22362# #
22363# XDEF **************************************************************** #
22364# unnorm_fix() #
22365# #
22366# XREF **************************************************************** #
22367# norm() - normalize the mantissa #
22368# #
22369# INPUT *************************************************************** #
22370# a0 = pointer to unnormalized extended precision number #
22371# #
22372# OUTPUT ************************************************************** #
22373# d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #
22374# a0 = input operand has been converted to a norm, denorm, or #
22375# zero; both the exponent and mantissa are changed. #
22376# #
22377#########################################################################
22378
22379 global unnorm_fix
22380unnorm_fix:
22381 bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
22382 bne.b unnorm_shift # hi(man) is not all zeroes
22383
22384#
22385# hi(man) is all zeroes so see if any bits in lo(man) are set
22386#
22387unnorm_chk_lo:
22388 bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
22389 beq.w unnorm_zero # yes
22390
22391 add.w &32, %d0 # no; fix shift distance
22392
22393#
22394# d0 = # shifts needed for complete normalization
22395#
22396unnorm_shift:
22397 clr.l %d1 # clear top word
22398 mov.w FTEMP_EX(%a0), %d1 # extract exponent
22399 and.w &0x7fff, %d1 # strip off sgn
22400
22401 cmp.w %d0, %d1 # will denorm push exp < 0?
22402 bgt.b unnorm_nrm_zero # yes; denorm only until exp = 0
22403
22404#
22405# exponent would not go < 0. therefore, number stays normalized
22406#
22407 sub.w %d0, %d1 # shift exponent value
22408 mov.w FTEMP_EX(%a0), %d0 # load old exponent
22409 and.w &0x8000, %d0 # save old sign
22410 or.w %d0, %d1 # {sgn,new exp}
22411 mov.w %d1, FTEMP_EX(%a0) # insert new exponent
22412
22413 bsr.l norm # normalize UNNORM
22414
22415 mov.b &NORM, %d0 # return new optype tag
22416 rts
22417
22418#
22419# exponent would go < 0, so only denormalize until exp = 0
22420#
22421unnorm_nrm_zero:
22422 cmp.b %d1, &32 # is exp <= 32?
22423 bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent
22424
22425 bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
22426 mov.l %d0, FTEMP_HI(%a0) # save new hi(man)
22427
22428 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
22429 lsl.l %d1, %d0 # extract new lo(man)
22430 mov.l %d0, FTEMP_LO(%a0) # save new lo(man)
22431
22432 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
22433
22434 mov.b &DENORM, %d0 # return new optype tag
22435 rts
22436
22437#
22438# only mantissa bits set are in lo(man)
22439#
22440unnorm_nrm_zero_lrg:
22441 sub.w &32, %d1 # adjust shft amt by 32
22442
22443 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
22444 lsl.l %d1, %d0 # left shift lo(man)
22445
22446 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
22447 clr.l FTEMP_LO(%a0) # lo(man) = 0
22448
22449 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
22450
22451 mov.b &DENORM, %d0 # return new optype tag
22452 rts
22453
22454#
22455# whole mantissa is zero so this UNNORM is actually a zero
22456#
22457unnorm_zero:
22458 and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero
22459
22460 mov.b &ZERO, %d0 # fix optype tag
22461 rts
22462
22463#########################################################################
22464# XDEF **************************************************************** #
22465# set_tag_x(): return the optype of the input ext fp number #
22466# #
22467# XREF **************************************************************** #
22468# None #
22469# #
22470# INPUT *************************************************************** #
22471# a0 = pointer to extended precision operand #
22472# #
22473# OUTPUT ************************************************************** #
22474# d0 = value of type tag #
22475# one of: NORM, INF, QNAN, SNAN, DENORM, UNNORM, ZERO #
22476# #
22477# ALGORITHM *********************************************************** #
22478# Simply test the exponent, j-bit, and mantissa values to #
22479# determine the type of operand. #
22480# If it's an unnormalized zero, alter the operand and force it #
22481# to be a normal zero. #
22482# #
22483#########################################################################
22484
22485 global set_tag_x
22486set_tag_x:
22487 mov.w FTEMP_EX(%a0), %d0 # extract exponent
22488 andi.w &0x7fff, %d0 # strip off sign
22489 cmpi.w %d0, &0x7fff # is (EXP == MAX)?
22490 beq.b inf_or_nan_x
22491not_inf_or_nan_x:
22492 btst &0x7,FTEMP_HI(%a0)
22493 beq.b not_norm_x
22494is_norm_x:
22495 mov.b &NORM, %d0
22496 rts
22497not_norm_x:
22498 tst.w %d0 # is exponent = 0?
22499 bne.b is_unnorm_x
22500not_unnorm_x:
22501 tst.l FTEMP_HI(%a0)
22502 bne.b is_denorm_x
22503 tst.l FTEMP_LO(%a0)
22504 bne.b is_denorm_x
22505is_zero_x:
22506 mov.b &ZERO, %d0
22507 rts
22508is_denorm_x:
22509 mov.b &DENORM, %d0
22510 rts
22511# must distinguish now "Unnormalized zeroes" which we
22512# must convert to zero.
22513is_unnorm_x:
22514 tst.l FTEMP_HI(%a0)
22515 bne.b is_unnorm_reg_x
22516 tst.l FTEMP_LO(%a0)
22517 bne.b is_unnorm_reg_x
22518# it's an "unnormalized zero". let's convert it to an actual zero...
22519 andi.w &0x8000,FTEMP_EX(%a0) # clear exponent
22520 mov.b &ZERO, %d0
22521 rts
22522is_unnorm_reg_x:
22523 mov.b &UNNORM, %d0
22524 rts
22525inf_or_nan_x:
22526 tst.l FTEMP_LO(%a0)
22527 bne.b is_nan_x
22528 mov.l FTEMP_HI(%a0), %d0
22529 and.l &0x7fffffff, %d0 # msb is a don't care!
22530 bne.b is_nan_x
22531is_inf_x:
22532 mov.b &INF, %d0
22533 rts
22534is_nan_x:
22535 btst &0x6, FTEMP_HI(%a0)
22536 beq.b is_snan_x
22537 mov.b &QNAN, %d0
22538 rts
22539is_snan_x:
22540 mov.b &SNAN, %d0
22541 rts
22542
22543#########################################################################
22544# XDEF **************************************************************** #
22545# set_tag_d(): return the optype of the input dbl fp number #
22546# #
22547# XREF **************************************************************** #
22548# None #
22549# #
22550# INPUT *************************************************************** #
22551# a0 = points to double precision operand #
22552# #
22553# OUTPUT ************************************************************** #
22554# d0 = value of type tag #
22555# one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
22556# #
22557# ALGORITHM *********************************************************** #
22558# Simply test the exponent, j-bit, and mantissa values to #
22559# determine the type of operand. #
22560# #
22561#########################################################################
22562
22563 global set_tag_d
22564set_tag_d:
22565 mov.l FTEMP(%a0), %d0
22566 mov.l %d0, %d1
22567
22568 andi.l &0x7ff00000, %d0
22569 beq.b zero_or_denorm_d
22570
22571 cmpi.l %d0, &0x7ff00000
22572 beq.b inf_or_nan_d
22573
22574is_norm_d:
22575 mov.b &NORM, %d0
22576 rts
22577zero_or_denorm_d:
22578 and.l &0x000fffff, %d1
22579 bne is_denorm_d
22580 tst.l 4+FTEMP(%a0)
22581 bne is_denorm_d
22582is_zero_d:
22583 mov.b &ZERO, %d0
22584 rts
22585is_denorm_d:
22586 mov.b &DENORM, %d0
22587 rts
22588inf_or_nan_d:
22589 and.l &0x000fffff, %d1
22590 bne is_nan_d
22591 tst.l 4+FTEMP(%a0)
22592 bne is_nan_d
22593is_inf_d:
22594 mov.b &INF, %d0
22595 rts
22596is_nan_d:
22597 btst &19, %d1
22598 bne is_qnan_d
22599is_snan_d:
22600 mov.b &SNAN, %d0
22601 rts
22602is_qnan_d:
22603 mov.b &QNAN, %d0
22604 rts
22605
22606#########################################################################
22607# XDEF **************************************************************** #
22608# set_tag_s(): return the optype of the input sgl fp number #
22609# #
22610# XREF **************************************************************** #
22611# None #
22612# #
22613# INPUT *************************************************************** #
22614# a0 = pointer to single precision operand #
22615# #
22616# OUTPUT ************************************************************** #
22617# d0 = value of type tag #
22618# one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
22619# #
22620# ALGORITHM *********************************************************** #
22621# Simply test the exponent, j-bit, and mantissa values to #
22622# determine the type of operand. #
22623# #
22624#########################################################################
22625
22626 global set_tag_s
22627set_tag_s:
22628 mov.l FTEMP(%a0), %d0
22629 mov.l %d0, %d1
22630
22631 andi.l &0x7f800000, %d0
22632 beq.b zero_or_denorm_s
22633
22634 cmpi.l %d0, &0x7f800000
22635 beq.b inf_or_nan_s
22636
22637is_norm_s:
22638 mov.b &NORM, %d0
22639 rts
22640zero_or_denorm_s:
22641 and.l &0x007fffff, %d1
22642 bne is_denorm_s
22643is_zero_s:
22644 mov.b &ZERO, %d0
22645 rts
22646is_denorm_s:
22647 mov.b &DENORM, %d0
22648 rts
22649inf_or_nan_s:
22650 and.l &0x007fffff, %d1
22651 bne is_nan_s
22652is_inf_s:
22653 mov.b &INF, %d0
22654 rts
22655is_nan_s:
22656 btst &22, %d1
22657 bne is_qnan_s
22658is_snan_s:
22659 mov.b &SNAN, %d0
22660 rts
22661is_qnan_s:
22662 mov.b &QNAN, %d0
22663 rts
22664
22665#########################################################################
22666# XDEF **************************************************************** #
22667# unf_res(): routine to produce default underflow result of a #
22668# scaled extended precision number; this is used by #
22669# fadd/fdiv/fmul/etc. emulation routines. #
22670# unf_res4(): same as above but for fsglmul/fsgldiv which use #
22671# single round prec and extended prec mode. #
22672# #
22673# XREF **************************************************************** #
22674# _denorm() - denormalize according to scale factor #
22675# _round() - round denormalized number according to rnd prec #
22676# #
22677# INPUT *************************************************************** #
22678# a0 = pointer to extended precison operand #
22679# d0 = scale factor #
22680# d1 = rounding precision/mode #
22681# #
22682# OUTPUT ************************************************************** #
22683# a0 = pointer to default underflow result in extended precision #
22684# d0.b = result FPSR_cc which caller may or may not want to save #
22685# #
22686# ALGORITHM *********************************************************** #
22687# Convert the input operand to "internal format" which means the #
22688# exponent is extended to 16 bits and the sign is stored in the unused #
22689# portion of the extended precison operand. Denormalize the number #
22690# according to the scale factor passed in d0. Then, round the #
22691# denormalized result. #
22692# Set the FPSR_exc bits as appropriate but return the cc bits in #
22693# d0 in case the caller doesn't want to save them (as is the case for #
22694# fmove out). #
22695# unf_res4() for fsglmul/fsgldiv forces the denorm to extended #
22696# precision and the rounding mode to single. #
22697# #
22698#########################################################################
22699 global unf_res
22700unf_res:
22701 mov.l %d1, -(%sp) # save rnd prec,mode on stack
22702
22703 btst &0x7, FTEMP_EX(%a0) # make "internal" format
22704 sne FTEMP_SGN(%a0)
22705
22706 mov.w FTEMP_EX(%a0), %d1 # extract exponent
22707 and.w &0x7fff, %d1
22708 sub.w %d0, %d1
22709 mov.w %d1, FTEMP_EX(%a0) # insert 16 bit exponent
22710
22711 mov.l %a0, -(%sp) # save operand ptr during calls
22712
22713 mov.l 0x4(%sp),%d0 # pass rnd prec.
22714 andi.w &0x00c0,%d0
22715 lsr.w &0x4,%d0
22716 bsr.l _denorm # denorm result
22717
22718 mov.l (%sp),%a0
22719 mov.w 0x6(%sp),%d1 # load prec:mode into %d1
22720 andi.w &0xc0,%d1 # extract rnd prec
22721 lsr.w &0x4,%d1
22722 swap %d1
22723 mov.w 0x6(%sp),%d1
22724 andi.w &0x30,%d1
22725 lsr.w &0x4,%d1
22726 bsr.l _round # round the denorm
22727
22728 mov.l (%sp)+, %a0
22729
22730# result is now rounded properly. convert back to normal format
22731 bclr &0x7, FTEMP_EX(%a0) # clear sgn first; may have residue
22732 tst.b FTEMP_SGN(%a0) # is "internal result" sign set?
22733 beq.b unf_res_chkifzero # no; result is positive
22734 bset &0x7, FTEMP_EX(%a0) # set result sgn
22735 clr.b FTEMP_SGN(%a0) # clear temp sign
22736
22737# the number may have become zero after rounding. set ccodes accordingly.
22738unf_res_chkifzero:
22739 clr.l %d0
22740 tst.l FTEMP_HI(%a0) # is value now a zero?
22741 bne.b unf_res_cont # no
22742 tst.l FTEMP_LO(%a0)
22743 bne.b unf_res_cont # no
22744# bset &z_bit, FPSR_CC(%a6) # yes; set zero ccode bit
22745 bset &z_bit, %d0 # yes; set zero ccode bit
22746
22747unf_res_cont:
22748
22749#
22750# can inex1 also be set along with unfl and inex2???
22751#
22752# we know that underflow has occurred. aunfl should be set if INEX2 is also set.
22753#
22754 btst &inex2_bit, FPSR_EXCEPT(%a6) # is INEX2 set?
22755 beq.b unf_res_end # no
22756 bset &aunfl_bit, FPSR_AEXCEPT(%a6) # yes; set aunfl
22757
22758unf_res_end:
22759 add.l &0x4, %sp # clear stack
22760 rts
22761
22762# unf_res() for fsglmul() and fsgldiv().
22763 global unf_res4
22764unf_res4:
22765 mov.l %d1,-(%sp) # save rnd prec,mode on stack
22766
22767 btst &0x7,FTEMP_EX(%a0) # make "internal" format
22768 sne FTEMP_SGN(%a0)
22769
22770 mov.w FTEMP_EX(%a0),%d1 # extract exponent
22771 and.w &0x7fff,%d1
22772 sub.w %d0,%d1
22773 mov.w %d1,FTEMP_EX(%a0) # insert 16 bit exponent
22774
22775 mov.l %a0,-(%sp) # save operand ptr during calls
22776
22777 clr.l %d0 # force rnd prec = ext
22778 bsr.l _denorm # denorm result
22779
22780 mov.l (%sp),%a0
22781 mov.w &s_mode,%d1 # force rnd prec = sgl
22782 swap %d1
22783 mov.w 0x6(%sp),%d1 # load rnd mode
22784 andi.w &0x30,%d1 # extract rnd prec
22785 lsr.w &0x4,%d1
22786 bsr.l _round # round the denorm
22787
22788 mov.l (%sp)+,%a0
22789
22790# result is now rounded properly. convert back to normal format
22791 bclr &0x7,FTEMP_EX(%a0) # clear sgn first; may have residue
22792 tst.b FTEMP_SGN(%a0) # is "internal result" sign set?
22793 beq.b unf_res4_chkifzero # no; result is positive
22794 bset &0x7,FTEMP_EX(%a0) # set result sgn
22795 clr.b FTEMP_SGN(%a0) # clear temp sign
22796
22797# the number may have become zero after rounding. set ccodes accordingly.
22798unf_res4_chkifzero:
22799 clr.l %d0
22800 tst.l FTEMP_HI(%a0) # is value now a zero?
22801 bne.b unf_res4_cont # no
22802 tst.l FTEMP_LO(%a0)
22803 bne.b unf_res4_cont # no
22804# bset &z_bit,FPSR_CC(%a6) # yes; set zero ccode bit
22805 bset &z_bit,%d0 # yes; set zero ccode bit
22806
22807unf_res4_cont:
22808
22809#
22810# can inex1 also be set along with unfl and inex2???
22811#
22812# we know that underflow has occurred. aunfl should be set if INEX2 is also set.
22813#
22814 btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
22815 beq.b unf_res4_end # no
22816 bset &aunfl_bit,FPSR_AEXCEPT(%a6) # yes; set aunfl
22817
22818unf_res4_end:
22819 add.l &0x4,%sp # clear stack
22820 rts
22821
22822#########################################################################
22823# XDEF **************************************************************** #
22824# ovf_res(): routine to produce the default overflow result of #
22825# an overflowing number. #
22826# ovf_res2(): same as above but the rnd mode/prec are passed #
22827# differently. #
22828# #
22829# XREF **************************************************************** #
22830# none #
22831# #
22832# INPUT *************************************************************** #
22833# d1.b = '-1' => (-); '0' => (+) #
22834# ovf_res(): #
22835# d0 = rnd mode/prec #
22836# ovf_res2(): #
22837# hi(d0) = rnd prec #
22838# lo(d0) = rnd mode #
22839# #
22840# OUTPUT ************************************************************** #
22841# a0 = points to extended precision result #
22842# d0.b = condition code bits #
22843# #
22844# ALGORITHM *********************************************************** #
22845# The default overflow result can be determined by the sign of #
22846# the result and the rounding mode/prec in effect. These bits are #
22847# concatenated together to create an index into the default result #
22848# table. A pointer to the correct result is returned in a0. The #
22849# resulting condition codes are returned in d0 in case the caller #
22850# doesn't want FPSR_cc altered (as is the case for fmove out). #
22851# #
22852#########################################################################
22853
22854 global ovf_res
22855ovf_res:
22856 andi.w &0x10,%d1 # keep result sign
22857 lsr.b &0x4,%d0 # shift prec/mode
22858 or.b %d0,%d1 # concat the two
22859 mov.w %d1,%d0 # make a copy
22860 lsl.b &0x1,%d1 # multiply d1 by 2
22861 bra.b ovf_res_load
22862
22863 global ovf_res2
22864ovf_res2:
22865 and.w &0x10, %d1 # keep result sign
22866 or.b %d0, %d1 # insert rnd mode
22867 swap %d0
22868 or.b %d0, %d1 # insert rnd prec
22869 mov.w %d1, %d0 # make a copy
22870 lsl.b &0x1, %d1 # shift left by 1
22871
22872#
22873# use the rounding mode, precision, and result sign as in index into the
22874# two tables below to fetch the default result and the result ccodes.
22875#
22876ovf_res_load:
22877 mov.b (tbl_ovfl_cc.b,%pc,%d0.w*1), %d0 # fetch result ccodes
22878 lea (tbl_ovfl_result.b,%pc,%d1.w*8), %a0 # return result ptr
22879
22880 rts
22881
22882tbl_ovfl_cc:
22883 byte 0x2, 0x0, 0x0, 0x2
22884 byte 0x2, 0x0, 0x0, 0x2
22885 byte 0x2, 0x0, 0x0, 0x2
22886 byte 0x0, 0x0, 0x0, 0x0
22887 byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
22888 byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
22889 byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
22890
22891tbl_ovfl_result:
22892 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
22893 long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RZ
22894 long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RM
22895 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
22896
22897 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
22898 long 0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RZ
22899 long 0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RM
22900 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
22901
22902 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
22903 long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RZ
22904 long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RM
22905 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
22906
22907 long 0x00000000,0x00000000,0x00000000,0x00000000
22908 long 0x00000000,0x00000000,0x00000000,0x00000000
22909 long 0x00000000,0x00000000,0x00000000,0x00000000
22910 long 0x00000000,0x00000000,0x00000000,0x00000000
22911
22912 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
22913 long 0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RZ
22914 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
22915 long 0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RP
22916
22917 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
22918 long 0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RZ
22919 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
22920 long 0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RP
22921
22922 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
22923 long 0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RZ
22924 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
22925 long 0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RP
22926
22927#########################################################################
22928# XDEF **************************************************************** #
22929# get_packed(): fetch a packed operand from memory and then #
22930# convert it to a floating-point binary number. #
22931# #
22932# XREF **************************************************************** #
22933# _dcalc_ea() - calculate the correct <ea> #
22934# _mem_read() - fetch the packed operand from memory #
22935# facc_in_x() - the fetch failed so jump to special exit code #
22936# decbin() - convert packed to binary extended precision #
22937# #
22938# INPUT *************************************************************** #
22939# None #
22940# #
22941# OUTPUT ************************************************************** #
22942# If no failure on _mem_read(): #
22943# FP_SRC(a6) = packed operand now as a binary FP number #
22944# #
22945# ALGORITHM *********************************************************** #
22946# Get the correct <ea> whihc is the value on the exception stack #
22947# frame w/ maybe a correction factor if the <ea> is -(an) or (an)+. #
22948# Then, fetch the operand from memory. If the fetch fails, exit #
22949# through facc_in_x(). #
22950# If the packed operand is a ZERO,NAN, or INF, convert it to #
22951# its binary representation here. Else, call decbin() which will #
22952# convert the packed value to an extended precision binary value. #
22953# #
22954#########################################################################
22955
22956# the stacked <ea> for packed is correct except for -(An).
22957# the base reg must be updated for both -(An) and (An)+.
22958 global get_packed
22959get_packed:
22960 mov.l &0xc,%d0 # packed is 12 bytes
22961 bsr.l _dcalc_ea # fetch <ea>; correct An
22962
22963 lea FP_SRC(%a6),%a1 # pass: ptr to super dst
22964 mov.l &0xc,%d0 # pass: 12 bytes
22965 bsr.l _dmem_read # read packed operand
22966
22967 tst.l %d1 # did dfetch fail?
22968 bne.l facc_in_x # yes
22969
22970# The packed operand is an INF or a NAN if the exponent field is all ones.
22971 bfextu FP_SRC(%a6){&1:&15},%d0 # get exp
22972 cmpi.w %d0,&0x7fff # INF or NAN?
22973 bne.b gp_try_zero # no
22974 rts # operand is an INF or NAN
22975
22976# The packed operand is a zero if the mantissa is all zero, else it's
22977# a normal packed op.
22978gp_try_zero:
22979 mov.b 3+FP_SRC(%a6),%d0 # get byte 4
22980 andi.b &0x0f,%d0 # clear all but last nybble
22981 bne.b gp_not_spec # not a zero
22982 tst.l FP_SRC_HI(%a6) # is lw 2 zero?
22983 bne.b gp_not_spec # not a zero
22984 tst.l FP_SRC_LO(%a6) # is lw 3 zero?
22985 bne.b gp_not_spec # not a zero
22986 rts # operand is a ZERO
22987gp_not_spec:
22988 lea FP_SRC(%a6),%a0 # pass: ptr to packed op
22989 bsr.l decbin # convert to extended
22990 fmovm.x &0x80,FP_SRC(%a6) # make this the srcop
22991 rts
22992
22993#########################################################################
22994# decbin(): Converts normalized packed bcd value pointed to by register #
22995# a0 to extended-precision value in fp0. #
22996# #
22997# INPUT *************************************************************** #
22998# a0 = pointer to normalized packed bcd value #
22999# #
23000# OUTPUT ************************************************************** #
23001# fp0 = exact fp representation of the packed bcd value. #
23002# #
23003# ALGORITHM *********************************************************** #
23004# Expected is a normal bcd (i.e. non-exceptional; all inf, zero, #
23005# and NaN operands are dispatched without entering this routine) #
23006# value in 68881/882 format at location (a0). #
23007# #
23008# A1. Convert the bcd exponent to binary by successive adds and #
23009# muls. Set the sign according to SE. Subtract 16 to compensate #
23010# for the mantissa which is to be interpreted as 17 integer #
23011# digits, rather than 1 integer and 16 fraction digits. #
23012# Note: this operation can never overflow. #
23013# #
23014# A2. Convert the bcd mantissa to binary by successive #
23015# adds and muls in FP0. Set the sign according to SM. #
23016# The mantissa digits will be converted with the decimal point #
23017# assumed following the least-significant digit. #
23018# Note: this operation can never overflow. #
23019# #
23020# A3. Count the number of leading/trailing zeros in the #
23021# bcd string. If SE is positive, count the leading zeros; #
23022# if negative, count the trailing zeros. Set the adjusted #
23023# exponent equal to the exponent from A1 and the zero count #
23024# added if SM = 1 and subtracted if SM = 0. Scale the #
23025# mantissa the equivalent of forcing in the bcd value: #
23026# #
23027# SM = 0 a non-zero digit in the integer position #
23028# SM = 1 a non-zero digit in Mant0, lsd of the fraction #
23029# #
23030# this will insure that any value, regardless of its #
23031# representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted #
23032# consistently. #
23033# #
23034# A4. Calculate the factor 10^exp in FP1 using a table of #
23035# 10^(2^n) values. To reduce the error in forming factors #
23036# greater than 10^27, a directed rounding scheme is used with #
23037# tables rounded to RN, RM, and RP, according to the table #
23038# in the comments of the pwrten section. #
23039# #
23040# A5. Form the final binary number by scaling the mantissa by #
23041# the exponent factor. This is done by multiplying the #
23042# mantissa in FP0 by the factor in FP1 if the adjusted #
23043# exponent sign is positive, and dividing FP0 by FP1 if #
23044# it is negative. #
23045# #
23046# Clean up and return. Check if the final mul or div was inexact. #
23047# If so, set INEX1 in USER_FPSR. #
23048# #
23049#########################################################################
23050
23051#
23052# PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded
23053# to nearest, minus, and plus, respectively. The tables include
23054# 10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}. No rounding
23055# is required until the power is greater than 27, however, all
23056# tables include the first 5 for ease of indexing.
23057#
23058RTABLE:
23059 byte 0,0,0,0
23060 byte 2,3,2,3
23061 byte 2,3,3,2
23062 byte 3,2,2,3
23063
23064 set FNIBS,7
23065 set FSTRT,0
23066
23067 set ESTRT,4
23068 set EDIGITS,2
23069
23070 global decbin
23071decbin:
23072 mov.l 0x0(%a0),FP_SCR0_EX(%a6) # make a copy of input
23073 mov.l 0x4(%a0),FP_SCR0_HI(%a6) # so we don't alter it
23074 mov.l 0x8(%a0),FP_SCR0_LO(%a6)
23075
23076 lea FP_SCR0(%a6),%a0
23077
23078 movm.l &0x3c00,-(%sp) # save d2-d5
23079 fmovm.x &0x1,-(%sp) # save fp1
23080#
23081# Calculate exponent:
23082# 1. Copy bcd value in memory for use as a working copy.
23083# 2. Calculate absolute value of exponent in d1 by mul and add.
23084# 3. Correct for exponent sign.
23085# 4. Subtract 16 to compensate for interpreting the mant as all integer digits.
23086# (i.e., all digits assumed left of the decimal point.)
23087#
23088# Register usage:
23089#
23090# calc_e:
23091# (*) d0: temp digit storage
23092# (*) d1: accumulator for binary exponent
23093# (*) d2: digit count
23094# (*) d3: offset pointer
23095# ( ) d4: first word of bcd
23096# ( ) a0: pointer to working bcd value
23097# ( ) a6: pointer to original bcd value
23098# (*) FP_SCR1: working copy of original bcd value
23099# (*) L_SCR1: copy of original exponent word
23100#
23101calc_e:
23102 mov.l &EDIGITS,%d2 # # of nibbles (digits) in fraction part
23103 mov.l &ESTRT,%d3 # counter to pick up digits
23104 mov.l (%a0),%d4 # get first word of bcd
23105 clr.l %d1 # zero d1 for accumulator
23106e_gd:
23107 mulu.l &0xa,%d1 # mul partial product by one digit place
23108 bfextu %d4{%d3:&4},%d0 # get the digit and zero extend into d0
23109 add.l %d0,%d1 # d1 = d1 + d0
23110 addq.b &4,%d3 # advance d3 to the next digit
23111 dbf.w %d2,e_gd # if we have used all 3 digits, exit loop
23112 btst &30,%d4 # get SE
23113 beq.b e_pos # don't negate if pos
23114 neg.l %d1 # negate before subtracting
23115e_pos:
23116 sub.l &16,%d1 # sub to compensate for shift of mant
23117 bge.b e_save # if still pos, do not neg
23118 neg.l %d1 # now negative, make pos and set SE
23119 or.l &0x40000000,%d4 # set SE in d4,
23120 or.l &0x40000000,(%a0) # and in working bcd
23121e_save:
23122 mov.l %d1,-(%sp) # save exp on stack
23123#
23124#
23125# Calculate mantissa:
23126# 1. Calculate absolute value of mantissa in fp0 by mul and add.
23127# 2. Correct for mantissa sign.
23128# (i.e., all digits assumed left of the decimal point.)
23129#
23130# Register usage:
23131#
23132# calc_m:
23133# (*) d0: temp digit storage
23134# (*) d1: lword counter
23135# (*) d2: digit count
23136# (*) d3: offset pointer
23137# ( ) d4: words 2 and 3 of bcd
23138# ( ) a0: pointer to working bcd value
23139# ( ) a6: pointer to original bcd value
23140# (*) fp0: mantissa accumulator
23141# ( ) FP_SCR1: working copy of original bcd value
23142# ( ) L_SCR1: copy of original exponent word
23143#
23144calc_m:
23145 mov.l &1,%d1 # word counter, init to 1
23146 fmov.s &0x00000000,%fp0 # accumulator
23147#
23148#
23149# Since the packed number has a long word between the first & second parts,
23150# get the integer digit then skip down & get the rest of the
23151# mantissa. We will unroll the loop once.
23152#
23153 bfextu (%a0){&28:&4},%d0 # integer part is ls digit in long word
23154 fadd.b %d0,%fp0 # add digit to sum in fp0
23155#
23156#
23157# Get the rest of the mantissa.
23158#
23159loadlw:
23160 mov.l (%a0,%d1.L*4),%d4 # load mantissa lonqword into d4
23161 mov.l &FSTRT,%d3 # counter to pick up digits
23162 mov.l &FNIBS,%d2 # reset number of digits per a0 ptr
23163md2b:
23164 fmul.s &0x41200000,%fp0 # fp0 = fp0 * 10
23165 bfextu %d4{%d3:&4},%d0 # get the digit and zero extend
23166 fadd.b %d0,%fp0 # fp0 = fp0 + digit
23167#
23168#
23169# If all the digits (8) in that long word have been converted (d2=0),
23170# then inc d1 (=2) to point to the next long word and reset d3 to 0
23171# to initialize the digit offset, and set d2 to 7 for the digit count;
23172# else continue with this long word.
23173#
23174 addq.b &4,%d3 # advance d3 to the next digit
23175 dbf.w %d2,md2b # check for last digit in this lw
23176nextlw:
23177 addq.l &1,%d1 # inc lw pointer in mantissa
23178 cmp.l %d1,&2 # test for last lw
23179 ble.b loadlw # if not, get last one
23180#
23181# Check the sign of the mant and make the value in fp0 the same sign.
23182#
23183m_sign:
23184 btst &31,(%a0) # test sign of the mantissa
23185 beq.b ap_st_z # if clear, go to append/strip zeros
23186 fneg.x %fp0 # if set, negate fp0
23187#
23188# Append/strip zeros:
23189#
23190# For adjusted exponents which have an absolute value greater than 27*,
23191# this routine calculates the amount needed to normalize the mantissa
23192# for the adjusted exponent. That number is subtracted from the exp
23193# if the exp was positive, and added if it was negative. The purpose
23194# of this is to reduce the value of the exponent and the possibility
23195# of error in calculation of pwrten.
23196#
23197# 1. Branch on the sign of the adjusted exponent.
23198# 2p.(positive exp)
23199# 2. Check M16 and the digits in lwords 2 and 3 in decending order.
23200# 3. Add one for each zero encountered until a non-zero digit.
23201# 4. Subtract the count from the exp.
23202# 5. Check if the exp has crossed zero in #3 above; make the exp abs
23203# and set SE.
23204# 6. Multiply the mantissa by 10**count.
23205# 2n.(negative exp)
23206# 2. Check the digits in lwords 3 and 2 in decending order.
23207# 3. Add one for each zero encountered until a non-zero digit.
23208# 4. Add the count to the exp.
23209# 5. Check if the exp has crossed zero in #3 above; clear SE.
23210# 6. Divide the mantissa by 10**count.
23211#
23212# *Why 27? If the adjusted exponent is within -28 < expA < 28, than
23213# any adjustment due to append/strip zeros will drive the resultane
23214# exponent towards zero. Since all pwrten constants with a power
23215# of 27 or less are exact, there is no need to use this routine to
23216# attempt to lessen the resultant exponent.
23217#
23218# Register usage:
23219#
23220# ap_st_z:
23221# (*) d0: temp digit storage
23222# (*) d1: zero count
23223# (*) d2: digit count
23224# (*) d3: offset pointer
23225# ( ) d4: first word of bcd
23226# (*) d5: lword counter
23227# ( ) a0: pointer to working bcd value
23228# ( ) FP_SCR1: working copy of original bcd value
23229# ( ) L_SCR1: copy of original exponent word
23230#
23231#
23232# First check the absolute value of the exponent to see if this
23233# routine is necessary. If so, then check the sign of the exponent
23234# and do append (+) or strip (-) zeros accordingly.
23235# This section handles a positive adjusted exponent.
23236#
23237ap_st_z:
23238 mov.l (%sp),%d1 # load expA for range test
23239 cmp.l %d1,&27 # test is with 27
23240 ble.w pwrten # if abs(expA) <28, skip ap/st zeros
23241 btst &30,(%a0) # check sign of exp
23242 bne.b ap_st_n # if neg, go to neg side
23243 clr.l %d1 # zero count reg
23244 mov.l (%a0),%d4 # load lword 1 to d4
23245 bfextu %d4{&28:&4},%d0 # get M16 in d0
23246 bne.b ap_p_fx # if M16 is non-zero, go fix exp
23247 addq.l &1,%d1 # inc zero count
23248 mov.l &1,%d5 # init lword counter
23249 mov.l (%a0,%d5.L*4),%d4 # get lword 2 to d4
23250 bne.b ap_p_cl # if lw 2 is zero, skip it
23251 addq.l &8,%d1 # and inc count by 8
23252 addq.l &1,%d5 # inc lword counter
23253 mov.l (%a0,%d5.L*4),%d4 # get lword 3 to d4
23254ap_p_cl:
23255 clr.l %d3 # init offset reg
23256 mov.l &7,%d2 # init digit counter
23257ap_p_gd:
23258 bfextu %d4{%d3:&4},%d0 # get digit
23259 bne.b ap_p_fx # if non-zero, go to fix exp
23260 addq.l &4,%d3 # point to next digit
23261 addq.l &1,%d1 # inc digit counter
23262 dbf.w %d2,ap_p_gd # get next digit
23263ap_p_fx:
23264 mov.l %d1,%d0 # copy counter to d2
23265 mov.l (%sp),%d1 # get adjusted exp from memory
23266 sub.l %d0,%d1 # subtract count from exp
23267 bge.b ap_p_fm # if still pos, go to pwrten
23268 neg.l %d1 # now its neg; get abs
23269 mov.l (%a0),%d4 # load lword 1 to d4
23270 or.l &0x40000000,%d4 # and set SE in d4
23271 or.l &0x40000000,(%a0) # and in memory
23272#
23273# Calculate the mantissa multiplier to compensate for the striping of
23274# zeros from the mantissa.
23275#
23276ap_p_fm:
23277 lea.l PTENRN(%pc),%a1 # get address of power-of-ten table
23278 clr.l %d3 # init table index
23279 fmov.s &0x3f800000,%fp1 # init fp1 to 1
23280 mov.l &3,%d2 # init d2 to count bits in counter
23281ap_p_el:
23282 asr.l &1,%d0 # shift lsb into carry
23283 bcc.b ap_p_en # if 1, mul fp1 by pwrten factor
23284 fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
23285ap_p_en:
23286 add.l &12,%d3 # inc d3 to next rtable entry
23287 tst.l %d0 # check if d0 is zero
23288 bne.b ap_p_el # if not, get next bit
23289 fmul.x %fp1,%fp0 # mul mantissa by 10**(no_bits_shifted)
23290 bra.b pwrten # go calc pwrten
23291#
23292# This section handles a negative adjusted exponent.
23293#
23294ap_st_n:
23295 clr.l %d1 # clr counter
23296 mov.l &2,%d5 # set up d5 to point to lword 3
23297 mov.l (%a0,%d5.L*4),%d4 # get lword 3
23298 bne.b ap_n_cl # if not zero, check digits
23299 sub.l &1,%d5 # dec d5 to point to lword 2
23300 addq.l &8,%d1 # inc counter by 8
23301 mov.l (%a0,%d5.L*4),%d4 # get lword 2
23302ap_n_cl:
23303 mov.l &28,%d3 # point to last digit
23304 mov.l &7,%d2 # init digit counter
23305ap_n_gd:
23306 bfextu %d4{%d3:&4},%d0 # get digit
23307 bne.b ap_n_fx # if non-zero, go to exp fix
23308 subq.l &4,%d3 # point to previous digit
23309 addq.l &1,%d1 # inc digit counter
23310 dbf.w %d2,ap_n_gd # get next digit
23311ap_n_fx:
23312 mov.l %d1,%d0 # copy counter to d0
23313 mov.l (%sp),%d1 # get adjusted exp from memory
23314 sub.l %d0,%d1 # subtract count from exp
23315 bgt.b ap_n_fm # if still pos, go fix mantissa
23316 neg.l %d1 # take abs of exp and clr SE
23317 mov.l (%a0),%d4 # load lword 1 to d4
23318 and.l &0xbfffffff,%d4 # and clr SE in d4
23319 and.l &0xbfffffff,(%a0) # and in memory
23320#
23321# Calculate the mantissa multiplier to compensate for the appending of
23322# zeros to the mantissa.
23323#
23324ap_n_fm:
23325 lea.l PTENRN(%pc),%a1 # get address of power-of-ten table
23326 clr.l %d3 # init table index
23327 fmov.s &0x3f800000,%fp1 # init fp1 to 1
23328 mov.l &3,%d2 # init d2 to count bits in counter
23329ap_n_el:
23330 asr.l &1,%d0 # shift lsb into carry
23331 bcc.b ap_n_en # if 1, mul fp1 by pwrten factor
23332 fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
23333ap_n_en:
23334 add.l &12,%d3 # inc d3 to next rtable entry
23335 tst.l %d0 # check if d0 is zero
23336 bne.b ap_n_el # if not, get next bit
23337 fdiv.x %fp1,%fp0 # div mantissa by 10**(no_bits_shifted)
23338#
23339#
23340# Calculate power-of-ten factor from adjusted and shifted exponent.
23341#
23342# Register usage:
23343#
23344# pwrten:
23345# (*) d0: temp
23346# ( ) d1: exponent
23347# (*) d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp
23348# (*) d3: FPCR work copy
23349# ( ) d4: first word of bcd
23350# (*) a1: RTABLE pointer
23351# calc_p:
23352# (*) d0: temp
23353# ( ) d1: exponent
23354# (*) d3: PWRTxx table index
23355# ( ) a0: pointer to working copy of bcd
23356# (*) a1: PWRTxx pointer
23357# (*) fp1: power-of-ten accumulator
23358#
23359# Pwrten calculates the exponent factor in the selected rounding mode
23360# according to the following table:
23361#
23362# Sign of Mant Sign of Exp Rounding Mode PWRTEN Rounding Mode
23363#
23364# ANY ANY RN RN
23365#
23366# + + RP RP
23367# - + RP RM
23368# + - RP RM
23369# - - RP RP
23370#
23371# + + RM RM
23372# - + RM RP
23373# + - RM RP
23374# - - RM RM
23375#
23376# + + RZ RM
23377# - + RZ RM
23378# + - RZ RP
23379# - - RZ RP
23380#
23381#
23382pwrten:
23383 mov.l USER_FPCR(%a6),%d3 # get user's FPCR
23384 bfextu %d3{&26:&2},%d2 # isolate rounding mode bits
23385 mov.l (%a0),%d4 # reload 1st bcd word to d4
23386 asl.l &2,%d2 # format d2 to be
23387 bfextu %d4{&0:&2},%d0 # {FPCR[6],FPCR[5],SM,SE}
23388 add.l %d0,%d2 # in d2 as index into RTABLE
23389 lea.l RTABLE(%pc),%a1 # load rtable base
23390 mov.b (%a1,%d2),%d0 # load new rounding bits from table
23391 clr.l %d3 # clear d3 to force no exc and extended
23392 bfins %d0,%d3{&26:&2} # stuff new rounding bits in FPCR
23393 fmov.l %d3,%fpcr # write new FPCR
23394 asr.l &1,%d0 # write correct PTENxx table
23395 bcc.b not_rp # to a1
23396 lea.l PTENRP(%pc),%a1 # it is RP
23397 bra.b calc_p # go to init section
23398not_rp:
23399 asr.l &1,%d0 # keep checking
23400 bcc.b not_rm
23401 lea.l PTENRM(%pc),%a1 # it is RM
23402 bra.b calc_p # go to init section
23403not_rm:
23404 lea.l PTENRN(%pc),%a1 # it is RN
23405calc_p:
23406 mov.l %d1,%d0 # copy exp to d0;use d0
23407 bpl.b no_neg # if exp is negative,
23408 neg.l %d0 # invert it
23409 or.l &0x40000000,(%a0) # and set SE bit
23410no_neg:
23411 clr.l %d3 # table index
23412 fmov.s &0x3f800000,%fp1 # init fp1 to 1
23413e_loop:
23414 asr.l &1,%d0 # shift next bit into carry
23415 bcc.b e_next # if zero, skip the mul
23416 fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
23417e_next:
23418 add.l &12,%d3 # inc d3 to next rtable entry
23419 tst.l %d0 # check if d0 is zero
23420 bne.b e_loop # not zero, continue shifting
23421#
23422#
23423# Check the sign of the adjusted exp and make the value in fp0 the
23424# same sign. If the exp was pos then multiply fp1*fp0;
23425# else divide fp0/fp1.
23426#
23427# Register Usage:
23428# norm:
23429# ( ) a0: pointer to working bcd value
23430# (*) fp0: mantissa accumulator
23431# ( ) fp1: scaling factor - 10**(abs(exp))
23432#
23433pnorm:
23434 btst &30,(%a0) # test the sign of the exponent
23435 beq.b mul # if clear, go to multiply
23436div:
23437 fdiv.x %fp1,%fp0 # exp is negative, so divide mant by exp
23438 bra.b end_dec
23439mul:
23440 fmul.x %fp1,%fp0 # exp is positive, so multiply by exp
23441#
23442#
23443# Clean up and return with result in fp0.
23444#
23445# If the final mul/div in decbin incurred an inex exception,
23446# it will be inex2, but will be reported as inex1 by get_op.
23447#
23448end_dec:
23449 fmov.l %fpsr,%d0 # get status register
23450 bclr &inex2_bit+8,%d0 # test for inex2 and clear it
23451 beq.b no_exc # skip this if no exc
23452 ori.w &inx1a_mask,2+USER_FPSR(%a6) # set INEX1/AINEX
23453no_exc:
23454 add.l &0x4,%sp # clear 1 lw param
23455 fmovm.x (%sp)+,&0x40 # restore fp1
23456 movm.l (%sp)+,&0x3c # restore d2-d5
23457 fmov.l &0x0,%fpcr
23458 fmov.l &0x0,%fpsr
23459 rts
23460
23461#########################################################################
23462# bindec(): Converts an input in extended precision format to bcd format#
23463# #
23464# INPUT *************************************************************** #
23465# a0 = pointer to the input extended precision value in memory. #
23466# the input may be either normalized, unnormalized, or #
23467# denormalized. #
23468# d0 = contains the k-factor sign-extended to 32-bits. #
23469# #
23470# OUTPUT ************************************************************** #
23471# FP_SCR0(a6) = bcd format result on the stack. #
23472# #
23473# ALGORITHM *********************************************************** #
23474# #
23475# A1. Set RM and size ext; Set SIGMA = sign of input. #
23476# The k-factor is saved for use in d7. Clear the #
23477# BINDEC_FLG for separating normalized/denormalized #
23478# input. If input is unnormalized or denormalized, #
23479# normalize it. #
23480# #
23481# A2. Set X = abs(input). #
23482# #
23483# A3. Compute ILOG. #
23484# ILOG is the log base 10 of the input value. It is #
23485# approximated by adding e + 0.f when the original #
23486# value is viewed as 2^^e * 1.f in extended precision. #
23487# This value is stored in d6. #
23488# #
23489# A4. Clr INEX bit. #
23490# The operation in A3 above may have set INEX2. #
23491# #
23492# A5. Set ICTR = 0; #
23493# ICTR is a flag used in A13. It must be set before the #
23494# loop entry A6. #
23495# #
23496# A6. Calculate LEN. #
23497# LEN is the number of digits to be displayed. The #
23498# k-factor can dictate either the total number of digits, #
23499# if it is a positive number, or the number of digits #
23500# after the decimal point which are to be included as #
23501# significant. See the 68882 manual for examples. #
23502# If LEN is computed to be greater than 17, set OPERR in #
23503# USER_FPSR. LEN is stored in d4. #
23504# #
23505# A7. Calculate SCALE. #
23506# SCALE is equal to 10^ISCALE, where ISCALE is the number #
23507# of decimal places needed to insure LEN integer digits #
23508# in the output before conversion to bcd. LAMBDA is the #
23509# sign of ISCALE, used in A9. Fp1 contains #
23510# 10^^(abs(ISCALE)) using a rounding mode which is a #
23511# function of the original rounding mode and the signs #
23512# of ISCALE and X. A table is given in the code. #
23513# #
23514# A8. Clr INEX; Force RZ. #
23515# The operation in A3 above may have set INEX2. #
23516# RZ mode is forced for the scaling operation to insure #
23517# only one rounding error. The grs bits are collected in #
23518# the INEX flag for use in A10. #
23519# #
23520# A9. Scale X -> Y. #
23521# The mantissa is scaled to the desired number of #
23522# significant digits. The excess digits are collected #
23523# in INEX2. #
23524# #
23525# A10. Or in INEX. #
23526# If INEX is set, round error occurred. This is #
23527# compensated for by 'or-ing' in the INEX2 flag to #
23528# the lsb of Y. #
23529# #
23530# A11. Restore original FPCR; set size ext. #
23531# Perform FINT operation in the user's rounding mode. #
23532# Keep the size to extended. #
23533# #
23534# A12. Calculate YINT = FINT(Y) according to user's rounding #
23535# mode. The FPSP routine sintd0 is used. The output #
23536# is in fp0. #
23537# #
23538# A13. Check for LEN digits. #
23539# If the int operation results in more than LEN digits, #
23540# or less than LEN -1 digits, adjust ILOG and repeat from #
23541# A6. This test occurs only on the first pass. If the #
23542# result is exactly 10^LEN, decrement ILOG and divide #
23543# the mantissa by 10. #
23544# #
23545# A14. Convert the mantissa to bcd. #
23546# The binstr routine is used to convert the LEN digit #
23547# mantissa to bcd in memory. The input to binstr is #
23548# to be a fraction; i.e. (mantissa)/10^LEN and adjusted #
23549# such that the decimal point is to the left of bit 63. #
23550# The bcd digits are stored in the correct position in #
23551# the final string area in memory. #
23552# #
23553# A15. Convert the exponent to bcd. #
23554# As in A14 above, the exp is converted to bcd and the #
23555# digits are stored in the final string. #
23556# Test the length of the final exponent string. If the #
23557# length is 4, set operr. #
23558# #
23559# A16. Write sign bits to final string. #
23560# #
23561#########################################################################
23562
23563set BINDEC_FLG, EXC_TEMP # DENORM flag
23564
23565# Constants in extended precision
23566PLOG2:
23567 long 0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000
23568PLOG2UP1:
23569 long 0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000
23570
23571# Constants in single precision
23572FONE:
23573 long 0x3F800000,0x00000000,0x00000000,0x00000000
23574FTWO:
23575 long 0x40000000,0x00000000,0x00000000,0x00000000
23576FTEN:
23577 long 0x41200000,0x00000000,0x00000000,0x00000000
23578F4933:
23579 long 0x459A2800,0x00000000,0x00000000,0x00000000
23580
23581RBDTBL:
23582 byte 0,0,0,0
23583 byte 3,3,2,2
23584 byte 3,2,2,3
23585 byte 2,3,3,2
23586
23587# Implementation Notes:
23588#
23589# The registers are used as follows:
23590#
23591# d0: scratch; LEN input to binstr
23592# d1: scratch
23593# d2: upper 32-bits of mantissa for binstr
23594# d3: scratch;lower 32-bits of mantissa for binstr
23595# d4: LEN
23596# d5: LAMBDA/ICTR
23597# d6: ILOG
23598# d7: k-factor
23599# a0: ptr for original operand/final result
23600# a1: scratch pointer
23601# a2: pointer to FP_X; abs(original value) in ext
23602# fp0: scratch
23603# fp1: scratch
23604# fp2: scratch
23605# F_SCR1:
23606# F_SCR2:
23607# L_SCR1:
23608# L_SCR2:
23609
23610 global bindec
23611bindec:
23612 movm.l &0x3f20,-(%sp) # {%d2-%d7/%a2}
23613 fmovm.x &0x7,-(%sp) # {%fp0-%fp2}
23614
23615# A1. Set RM and size ext. Set SIGMA = sign input;
23616# The k-factor is saved for use in d7. Clear BINDEC_FLG for
23617# separating normalized/denormalized input. If the input
23618# is a denormalized number, set the BINDEC_FLG memory word
23619# to signal denorm. If the input is unnormalized, normalize
23620# the input and test for denormalized result.
23621#
23622 fmov.l &rm_mode*0x10,%fpcr # set RM and ext
23623 mov.l (%a0),L_SCR2(%a6) # save exponent for sign check
23624 mov.l %d0,%d7 # move k-factor to d7
23625
23626 clr.b BINDEC_FLG(%a6) # clr norm/denorm flag
23627 cmpi.b STAG(%a6),&DENORM # is input a DENORM?
23628 bne.w A2_str # no; input is a NORM
23629
23630#
23631# Normalize the denorm
23632#
23633un_de_norm:
23634 mov.w (%a0),%d0
23635 and.w &0x7fff,%d0 # strip sign of normalized exp
23636 mov.l 4(%a0),%d1
23637 mov.l 8(%a0),%d2
23638norm_loop:
23639 sub.w &1,%d0
23640 lsl.l &1,%d2
23641 roxl.l &1,%d1
23642 tst.l %d1
23643 bge.b norm_loop
23644#
23645# Test if the normalized input is denormalized
23646#
23647 tst.w %d0
23648 bgt.b pos_exp # if greater than zero, it is a norm
23649 st BINDEC_FLG(%a6) # set flag for denorm
23650pos_exp:
23651 and.w &0x7fff,%d0 # strip sign of normalized exp
23652 mov.w %d0,(%a0)
23653 mov.l %d1,4(%a0)
23654 mov.l %d2,8(%a0)
23655
23656# A2. Set X = abs(input).
23657#
23658A2_str:
23659 mov.l (%a0),FP_SCR1(%a6) # move input to work space
23660 mov.l 4(%a0),FP_SCR1+4(%a6) # move input to work space
23661 mov.l 8(%a0),FP_SCR1+8(%a6) # move input to work space
23662 and.l &0x7fffffff,FP_SCR1(%a6) # create abs(X)
23663
23664# A3. Compute ILOG.
23665# ILOG is the log base 10 of the input value. It is approx-
23666# imated by adding e + 0.f when the original value is viewed
23667# as 2^^e * 1.f in extended precision. This value is stored
23668# in d6.
23669#
23670# Register usage:
23671# Input/Output
23672# d0: k-factor/exponent
23673# d2: x/x
23674# d3: x/x
23675# d4: x/x
23676# d5: x/x
23677# d6: x/ILOG
23678# d7: k-factor/Unchanged
23679# a0: ptr for original operand/final result
23680# a1: x/x
23681# a2: x/x
23682# fp0: x/float(ILOG)
23683# fp1: x/x
23684# fp2: x/x
23685# F_SCR1:x/x
23686# F_SCR2:Abs(X)/Abs(X) with $3fff exponent
23687# L_SCR1:x/x
23688# L_SCR2:first word of X packed/Unchanged
23689
23690 tst.b BINDEC_FLG(%a6) # check for denorm
23691 beq.b A3_cont # if clr, continue with norm
23692 mov.l &-4933,%d6 # force ILOG = -4933
23693 bra.b A4_str
23694A3_cont:
23695 mov.w FP_SCR1(%a6),%d0 # move exp to d0
23696 mov.w &0x3fff,FP_SCR1(%a6) # replace exponent with 0x3fff
23697 fmov.x FP_SCR1(%a6),%fp0 # now fp0 has 1.f
23698 sub.w &0x3fff,%d0 # strip off bias
23699 fadd.w %d0,%fp0 # add in exp
23700 fsub.s FONE(%pc),%fp0 # subtract off 1.0
23701 fbge.w pos_res # if pos, branch
23702 fmul.x PLOG2UP1(%pc),%fp0 # if neg, mul by LOG2UP1
23703 fmov.l %fp0,%d6 # put ILOG in d6 as a lword
23704 bra.b A4_str # go move out ILOG
23705pos_res:
23706 fmul.x PLOG2(%pc),%fp0 # if pos, mul by LOG2
23707 fmov.l %fp0,%d6 # put ILOG in d6 as a lword
23708
23709
23710# A4. Clr INEX bit.
23711# The operation in A3 above may have set INEX2.
23712
23713A4_str:
23714 fmov.l &0,%fpsr # zero all of fpsr - nothing needed
23715
23716
23717# A5. Set ICTR = 0;
23718# ICTR is a flag used in A13. It must be set before the
23719# loop entry A6. The lower word of d5 is used for ICTR.
23720
23721 clr.w %d5 # clear ICTR
23722
23723# A6. Calculate LEN.
23724# LEN is the number of digits to be displayed. The k-factor
23725# can dictate either the total number of digits, if it is
23726# a positive number, or the number of digits after the
23727# original decimal point which are to be included as
23728# significant. See the 68882 manual for examples.
23729# If LEN is computed to be greater than 17, set OPERR in
23730# USER_FPSR. LEN is stored in d4.
23731#
23732# Register usage:
23733# Input/Output
23734# d0: exponent/Unchanged
23735# d2: x/x/scratch
23736# d3: x/x
23737# d4: exc picture/LEN
23738# d5: ICTR/Unchanged
23739# d6: ILOG/Unchanged
23740# d7: k-factor/Unchanged
23741# a0: ptr for original operand/final result
23742# a1: x/x
23743# a2: x/x
23744# fp0: float(ILOG)/Unchanged
23745# fp1: x/x
23746# fp2: x/x
23747# F_SCR1:x/x
23748# F_SCR2:Abs(X) with $3fff exponent/Unchanged
23749# L_SCR1:x/x
23750# L_SCR2:first word of X packed/Unchanged
23751
23752A6_str:
23753 tst.l %d7 # branch on sign of k
23754 ble.b k_neg # if k <= 0, LEN = ILOG + 1 - k
23755 mov.l %d7,%d4 # if k > 0, LEN = k
23756 bra.b len_ck # skip to LEN check
23757k_neg:
23758 mov.l %d6,%d4 # first load ILOG to d4
23759 sub.l %d7,%d4 # subtract off k
23760 addq.l &1,%d4 # add in the 1
23761len_ck:
23762 tst.l %d4 # LEN check: branch on sign of LEN
23763 ble.b LEN_ng # if neg, set LEN = 1
23764 cmp.l %d4,&17 # test if LEN > 17
23765 ble.b A7_str # if not, forget it
23766 mov.l &17,%d4 # set max LEN = 17
23767 tst.l %d7 # if negative, never set OPERR
23768 ble.b A7_str # if positive, continue
23769 or.l &opaop_mask,USER_FPSR(%a6) # set OPERR & AIOP in USER_FPSR
23770 bra.b A7_str # finished here
23771LEN_ng:
23772 mov.l &1,%d4 # min LEN is 1
23773
23774
23775# A7. Calculate SCALE.
23776# SCALE is equal to 10^ISCALE, where ISCALE is the number
23777# of decimal places needed to insure LEN integer digits
23778# in the output before conversion to bcd. LAMBDA is the sign
23779# of ISCALE, used in A9. Fp1 contains 10^^(abs(ISCALE)) using
23780# the rounding mode as given in the following table (see
23781# Coonen, p. 7.23 as ref.; however, the SCALE variable is
23782# of opposite sign in bindec.sa from Coonen).
23783#
23784# Initial USE
23785# FPCR[6:5] LAMBDA SIGN(X) FPCR[6:5]
23786# ----------------------------------------------
23787# RN 00 0 0 00/0 RN
23788# RN 00 0 1 00/0 RN
23789# RN 00 1 0 00/0 RN
23790# RN 00 1 1 00/0 RN
23791# RZ 01 0 0 11/3 RP
23792# RZ 01 0 1 11/3 RP
23793# RZ 01 1 0 10/2 RM
23794# RZ 01 1 1 10/2 RM
23795# RM 10 0 0 11/3 RP
23796# RM 10 0 1 10/2 RM
23797# RM 10 1 0 10/2 RM
23798# RM 10 1 1 11/3 RP
23799# RP 11 0 0 10/2 RM
23800# RP 11 0 1 11/3 RP
23801# RP 11 1 0 11/3 RP
23802# RP 11 1 1 10/2 RM
23803#
23804# Register usage:
23805# Input/Output
23806# d0: exponent/scratch - final is 0
23807# d2: x/0 or 24 for A9
23808# d3: x/scratch - offset ptr into PTENRM array
23809# d4: LEN/Unchanged
23810# d5: 0/ICTR:LAMBDA
23811# d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
23812# d7: k-factor/Unchanged
23813# a0: ptr for original operand/final result
23814# a1: x/ptr to PTENRM array
23815# a2: x/x
23816# fp0: float(ILOG)/Unchanged
23817# fp1: x/10^ISCALE
23818# fp2: x/x
23819# F_SCR1:x/x
23820# F_SCR2:Abs(X) with $3fff exponent/Unchanged
23821# L_SCR1:x/x
23822# L_SCR2:first word of X packed/Unchanged
23823
23824A7_str:
23825 tst.l %d7 # test sign of k
23826 bgt.b k_pos # if pos and > 0, skip this
23827 cmp.l %d7,%d6 # test k - ILOG
23828 blt.b k_pos # if ILOG >= k, skip this
23829 mov.l %d7,%d6 # if ((k<0) & (ILOG < k)) ILOG = k
23830k_pos:
23831 mov.l %d6,%d0 # calc ILOG + 1 - LEN in d0
23832 addq.l &1,%d0 # add the 1
23833 sub.l %d4,%d0 # sub off LEN
23834 swap %d5 # use upper word of d5 for LAMBDA
23835 clr.w %d5 # set it zero initially
23836 clr.w %d2 # set up d2 for very small case
23837 tst.l %d0 # test sign of ISCALE
23838 bge.b iscale # if pos, skip next inst
23839 addq.w &1,%d5 # if neg, set LAMBDA true
23840 cmp.l %d0,&0xffffecd4 # test iscale <= -4908
23841 bgt.b no_inf # if false, skip rest
23842 add.l &24,%d0 # add in 24 to iscale
23843 mov.l &24,%d2 # put 24 in d2 for A9
23844no_inf:
23845 neg.l %d0 # and take abs of ISCALE
23846iscale:
23847 fmov.s FONE(%pc),%fp1 # init fp1 to 1
23848 bfextu USER_FPCR(%a6){&26:&2},%d1 # get initial rmode bits
23849 lsl.w &1,%d1 # put them in bits 2:1
23850 add.w %d5,%d1 # add in LAMBDA
23851 lsl.w &1,%d1 # put them in bits 3:1
23852 tst.l L_SCR2(%a6) # test sign of original x
23853 bge.b x_pos # if pos, don't set bit 0
23854 addq.l &1,%d1 # if neg, set bit 0
23855x_pos:
23856 lea.l RBDTBL(%pc),%a2 # load rbdtbl base
23857 mov.b (%a2,%d1),%d3 # load d3 with new rmode
23858 lsl.l &4,%d3 # put bits in proper position
23859 fmov.l %d3,%fpcr # load bits into fpu
23860 lsr.l &4,%d3 # put bits in proper position
23861 tst.b %d3 # decode new rmode for pten table
23862 bne.b not_rn # if zero, it is RN
23863 lea.l PTENRN(%pc),%a1 # load a1 with RN table base
23864 bra.b rmode # exit decode
23865not_rn:
23866 lsr.b &1,%d3 # get lsb in carry
23867 bcc.b not_rp2 # if carry clear, it is RM
23868 lea.l PTENRP(%pc),%a1 # load a1 with RP table base
23869 bra.b rmode # exit decode
23870not_rp2:
23871 lea.l PTENRM(%pc),%a1 # load a1 with RM table base
23872rmode:
23873 clr.l %d3 # clr table index
23874e_loop2:
23875 lsr.l &1,%d0 # shift next bit into carry
23876 bcc.b e_next2 # if zero, skip the mul
23877 fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
23878e_next2:
23879 add.l &12,%d3 # inc d3 to next pwrten table entry
23880 tst.l %d0 # test if ISCALE is zero
23881 bne.b e_loop2 # if not, loop
23882
23883# A8. Clr INEX; Force RZ.
23884# The operation in A3 above may have set INEX2.
23885# RZ mode is forced for the scaling operation to insure
23886# only one rounding error. The grs bits are collected in
23887# the INEX flag for use in A10.
23888#
23889# Register usage:
23890# Input/Output
23891
23892 fmov.l &0,%fpsr # clr INEX
23893 fmov.l &rz_mode*0x10,%fpcr # set RZ rounding mode
23894
23895# A9. Scale X -> Y.
23896# The mantissa is scaled to the desired number of significant
23897# digits. The excess digits are collected in INEX2. If mul,
23898# Check d2 for excess 10 exponential value. If not zero,
23899# the iscale value would have caused the pwrten calculation
23900# to overflow. Only a negative iscale can cause this, so
23901# multiply by 10^(d2), which is now only allowed to be 24,
23902# with a multiply by 10^8 and 10^16, which is exact since
23903# 10^24 is exact. If the input was denormalized, we must
23904# create a busy stack frame with the mul command and the
23905# two operands, and allow the fpu to complete the multiply.
23906#
23907# Register usage:
23908# Input/Output
23909# d0: FPCR with RZ mode/Unchanged
23910# d2: 0 or 24/unchanged
23911# d3: x/x
23912# d4: LEN/Unchanged
23913# d5: ICTR:LAMBDA
23914# d6: ILOG/Unchanged
23915# d7: k-factor/Unchanged
23916# a0: ptr for original operand/final result
23917# a1: ptr to PTENRM array/Unchanged
23918# a2: x/x
23919# fp0: float(ILOG)/X adjusted for SCALE (Y)
23920# fp1: 10^ISCALE/Unchanged
23921# fp2: x/x
23922# F_SCR1:x/x
23923# F_SCR2:Abs(X) with $3fff exponent/Unchanged
23924# L_SCR1:x/x
23925# L_SCR2:first word of X packed/Unchanged
23926
23927A9_str:
23928 fmov.x (%a0),%fp0 # load X from memory
23929 fabs.x %fp0 # use abs(X)
23930 tst.w %d5 # LAMBDA is in lower word of d5
23931 bne.b sc_mul # if neg (LAMBDA = 1), scale by mul
23932 fdiv.x %fp1,%fp0 # calculate X / SCALE -> Y to fp0
23933 bra.w A10_st # branch to A10
23934
23935sc_mul:
23936 tst.b BINDEC_FLG(%a6) # check for denorm
23937 beq.w A9_norm # if norm, continue with mul
23938
23939# for DENORM, we must calculate:
23940# fp0 = input_op * 10^ISCALE * 10^24
23941# since the input operand is a DENORM, we can't multiply it directly.
23942# so, we do the multiplication of the exponents and mantissas separately.
23943# in this way, we avoid underflow on intermediate stages of the
23944# multiplication and guarantee a result without exception.
23945 fmovm.x &0x2,-(%sp) # save 10^ISCALE to stack
23946
23947 mov.w (%sp),%d3 # grab exponent
23948 andi.w &0x7fff,%d3 # clear sign
23949 ori.w &0x8000,(%a0) # make DENORM exp negative
23950 add.w (%a0),%d3 # add DENORM exp to 10^ISCALE exp
23951 subi.w &0x3fff,%d3 # subtract BIAS
23952 add.w 36(%a1),%d3
23953 subi.w &0x3fff,%d3 # subtract BIAS
23954 add.w 48(%a1),%d3
23955 subi.w &0x3fff,%d3 # subtract BIAS
23956
23957 bmi.w sc_mul_err # is result is DENORM, punt!!!
23958
23959 andi.w &0x8000,(%sp) # keep sign
23960 or.w %d3,(%sp) # insert new exponent
23961 andi.w &0x7fff,(%a0) # clear sign bit on DENORM again
23962 mov.l 0x8(%a0),-(%sp) # put input op mantissa on stk
23963 mov.l 0x4(%a0),-(%sp)
23964 mov.l &0x3fff0000,-(%sp) # force exp to zero
23965 fmovm.x (%sp)+,&0x80 # load normalized DENORM into fp0
23966 fmul.x (%sp)+,%fp0
23967
23968# fmul.x 36(%a1),%fp0 # multiply fp0 by 10^8
23969# fmul.x 48(%a1),%fp0 # multiply fp0 by 10^16
23970 mov.l 36+8(%a1),-(%sp) # get 10^8 mantissa
23971 mov.l 36+4(%a1),-(%sp)
23972 mov.l &0x3fff0000,-(%sp) # force exp to zero
23973 mov.l 48+8(%a1),-(%sp) # get 10^16 mantissa
23974 mov.l 48+4(%a1),-(%sp)
23975 mov.l &0x3fff0000,-(%sp)# force exp to zero
23976 fmul.x (%sp)+,%fp0 # multiply fp0 by 10^8
23977 fmul.x (%sp)+,%fp0 # multiply fp0 by 10^16
23978 bra.b A10_st
23979
23980sc_mul_err:
23981 bra.b sc_mul_err
23982
23983A9_norm:
23984 tst.w %d2 # test for small exp case
23985 beq.b A9_con # if zero, continue as normal
23986 fmul.x 36(%a1),%fp0 # multiply fp0 by 10^8
23987 fmul.x 48(%a1),%fp0 # multiply fp0 by 10^16
23988A9_con:
23989 fmul.x %fp1,%fp0 # calculate X * SCALE -> Y to fp0
23990
23991# A10. Or in INEX.
23992# If INEX is set, round error occurred. This is compensated
23993# for by 'or-ing' in the INEX2 flag to the lsb of Y.
23994#
23995# Register usage:
23996# Input/Output
23997# d0: FPCR with RZ mode/FPSR with INEX2 isolated
23998# d2: x/x
23999# d3: x/x
24000# d4: LEN/Unchanged
24001# d5: ICTR:LAMBDA
24002# d6: ILOG/Unchanged
24003# d7: k-factor/Unchanged
24004# a0: ptr for original operand/final result
24005# a1: ptr to PTENxx array/Unchanged
24006# a2: x/ptr to FP_SCR1(a6)
24007# fp0: Y/Y with lsb adjusted
24008# fp1: 10^ISCALE/Unchanged
24009# fp2: x/x
24010
24011A10_st:
24012 fmov.l %fpsr,%d0 # get FPSR
24013 fmov.x %fp0,FP_SCR1(%a6) # move Y to memory
24014 lea.l FP_SCR1(%a6),%a2 # load a2 with ptr to FP_SCR1
24015 btst &9,%d0 # check if INEX2 set
24016 beq.b A11_st # if clear, skip rest
24017 or.l &1,8(%a2) # or in 1 to lsb of mantissa
24018 fmov.x FP_SCR1(%a6),%fp0 # write adjusted Y back to fpu
24019
24020
24021# A11. Restore original FPCR; set size ext.
24022# Perform FINT operation in the user's rounding mode. Keep
24023# the size to extended. The sintdo entry point in the sint
24024# routine expects the FPCR value to be in USER_FPCR for
24025# mode and precision. The original FPCR is saved in L_SCR1.
24026
24027A11_st:
24028 mov.l USER_FPCR(%a6),L_SCR1(%a6) # save it for later
24029 and.l &0x00000030,USER_FPCR(%a6) # set size to ext,
24030# ;block exceptions
24031
24032
24033# A12. Calculate YINT = FINT(Y) according to user's rounding mode.
24034# The FPSP routine sintd0 is used. The output is in fp0.
24035#
24036# Register usage:
24037# Input/Output
24038# d0: FPSR with AINEX cleared/FPCR with size set to ext
24039# d2: x/x/scratch
24040# d3: x/x
24041# d4: LEN/Unchanged
24042# d5: ICTR:LAMBDA/Unchanged
24043# d6: ILOG/Unchanged
24044# d7: k-factor/Unchanged
24045# a0: ptr for original operand/src ptr for sintdo
24046# a1: ptr to PTENxx array/Unchanged
24047# a2: ptr to FP_SCR1(a6)/Unchanged
24048# a6: temp pointer to FP_SCR1(a6) - orig value saved and restored
24049# fp0: Y/YINT
24050# fp1: 10^ISCALE/Unchanged
24051# fp2: x/x
24052# F_SCR1:x/x
24053# F_SCR2:Y adjusted for inex/Y with original exponent
24054# L_SCR1:x/original USER_FPCR
24055# L_SCR2:first word of X packed/Unchanged
24056
24057A12_st:
24058 movm.l &0xc0c0,-(%sp) # save regs used by sintd0 {%d0-%d1/%a0-%a1}
24059 mov.l L_SCR1(%a6),-(%sp)
24060 mov.l L_SCR2(%a6),-(%sp)
24061
24062 lea.l FP_SCR1(%a6),%a0 # a0 is ptr to FP_SCR1(a6)
24063 fmov.x %fp0,(%a0) # move Y to memory at FP_SCR1(a6)
24064 tst.l L_SCR2(%a6) # test sign of original operand
24065 bge.b do_fint12 # if pos, use Y
24066 or.l &0x80000000,(%a0) # if neg, use -Y
24067do_fint12:
24068 mov.l USER_FPSR(%a6),-(%sp)
24069# bsr sintdo # sint routine returns int in fp0
24070
24071 fmov.l USER_FPCR(%a6),%fpcr
24072 fmov.l &0x0,%fpsr # clear the AEXC bits!!!
24073## mov.l USER_FPCR(%a6),%d0 # ext prec/keep rnd mode
24074## andi.l &0x00000030,%d0
24075## fmov.l %d0,%fpcr
24076 fint.x FP_SCR1(%a6),%fp0 # do fint()
24077 fmov.l %fpsr,%d0
24078 or.w %d0,FPSR_EXCEPT(%a6)
24079## fmov.l &0x0,%fpcr
24080## fmov.l %fpsr,%d0 # don't keep ccodes
24081## or.w %d0,FPSR_EXCEPT(%a6)
24082
24083 mov.b (%sp),USER_FPSR(%a6)
24084 add.l &4,%sp
24085
24086 mov.l (%sp)+,L_SCR2(%a6)
24087 mov.l (%sp)+,L_SCR1(%a6)
24088 movm.l (%sp)+,&0x303 # restore regs used by sint {%d0-%d1/%a0-%a1}
24089
24090 mov.l L_SCR2(%a6),FP_SCR1(%a6) # restore original exponent
24091 mov.l L_SCR1(%a6),USER_FPCR(%a6) # restore user's FPCR
24092
24093# A13. Check for LEN digits.
24094# If the int operation results in more than LEN digits,
24095# or less than LEN -1 digits, adjust ILOG and repeat from
24096# A6. This test occurs only on the first pass. If the
24097# result is exactly 10^LEN, decrement ILOG and divide
24098# the mantissa by 10. The calculation of 10^LEN cannot
24099# be inexact, since all powers of ten upto 10^27 are exact
24100# in extended precision, so the use of a previous power-of-ten
24101# table will introduce no error.
24102#
24103#
24104# Register usage:
24105# Input/Output
24106# d0: FPCR with size set to ext/scratch final = 0
24107# d2: x/x
24108# d3: x/scratch final = x
24109# d4: LEN/LEN adjusted
24110# d5: ICTR:LAMBDA/LAMBDA:ICTR
24111# d6: ILOG/ILOG adjusted
24112# d7: k-factor/Unchanged
24113# a0: pointer into memory for packed bcd string formation
24114# a1: ptr to PTENxx array/Unchanged
24115# a2: ptr to FP_SCR1(a6)/Unchanged
24116# fp0: int portion of Y/abs(YINT) adjusted
24117# fp1: 10^ISCALE/Unchanged
24118# fp2: x/10^LEN
24119# F_SCR1:x/x
24120# F_SCR2:Y with original exponent/Unchanged
24121# L_SCR1:original USER_FPCR/Unchanged
24122# L_SCR2:first word of X packed/Unchanged
24123
24124A13_st:
24125 swap %d5 # put ICTR in lower word of d5
24126 tst.w %d5 # check if ICTR = 0
24127 bne not_zr # if non-zero, go to second test
24128#
24129# Compute 10^(LEN-1)
24130#
24131 fmov.s FONE(%pc),%fp2 # init fp2 to 1.0
24132 mov.l %d4,%d0 # put LEN in d0
24133 subq.l &1,%d0 # d0 = LEN -1
24134 clr.l %d3 # clr table index
24135l_loop:
24136 lsr.l &1,%d0 # shift next bit into carry
24137 bcc.b l_next # if zero, skip the mul
24138 fmul.x (%a1,%d3),%fp2 # mul by 10**(d3_bit_no)
24139l_next:
24140 add.l &12,%d3 # inc d3 to next pwrten table entry
24141 tst.l %d0 # test if LEN is zero
24142 bne.b l_loop # if not, loop
24143#
24144# 10^LEN-1 is computed for this test and A14. If the input was
24145# denormalized, check only the case in which YINT > 10^LEN.
24146#
24147 tst.b BINDEC_FLG(%a6) # check if input was norm
24148 beq.b A13_con # if norm, continue with checking
24149 fabs.x %fp0 # take abs of YINT
24150 bra test_2
24151#
24152# Compare abs(YINT) to 10^(LEN-1) and 10^LEN
24153#
24154A13_con:
24155 fabs.x %fp0 # take abs of YINT
24156 fcmp.x %fp0,%fp2 # compare abs(YINT) with 10^(LEN-1)
24157 fbge.w test_2 # if greater, do next test
24158 subq.l &1,%d6 # subtract 1 from ILOG
24159 mov.w &1,%d5 # set ICTR
24160 fmov.l &rm_mode*0x10,%fpcr # set rmode to RM
24161 fmul.s FTEN(%pc),%fp2 # compute 10^LEN
24162 bra.w A6_str # return to A6 and recompute YINT
24163test_2:
24164 fmul.s FTEN(%pc),%fp2 # compute 10^LEN
24165 fcmp.x %fp0,%fp2 # compare abs(YINT) with 10^LEN
24166 fblt.w A14_st # if less, all is ok, go to A14
24167 fbgt.w fix_ex # if greater, fix and redo
24168 fdiv.s FTEN(%pc),%fp0 # if equal, divide by 10
24169 addq.l &1,%d6 # and inc ILOG
24170 bra.b A14_st # and continue elsewhere
24171fix_ex:
24172 addq.l &1,%d6 # increment ILOG by 1
24173 mov.w &1,%d5 # set ICTR
24174 fmov.l &rm_mode*0x10,%fpcr # set rmode to RM
24175 bra.w A6_str # return to A6 and recompute YINT
24176#
24177# Since ICTR <> 0, we have already been through one adjustment,
24178# and shouldn't have another; this is to check if abs(YINT) = 10^LEN
24179# 10^LEN is again computed using whatever table is in a1 since the
24180# value calculated cannot be inexact.
24181#
24182not_zr:
24183 fmov.s FONE(%pc),%fp2 # init fp2 to 1.0
24184 mov.l %d4,%d0 # put LEN in d0
24185 clr.l %d3 # clr table index
24186z_loop:
24187 lsr.l &1,%d0 # shift next bit into carry
24188 bcc.b z_next # if zero, skip the mul
24189 fmul.x (%a1,%d3),%fp2 # mul by 10**(d3_bit_no)
24190z_next:
24191 add.l &12,%d3 # inc d3 to next pwrten table entry
24192 tst.l %d0 # test if LEN is zero
24193 bne.b z_loop # if not, loop
24194 fabs.x %fp0 # get abs(YINT)
24195 fcmp.x %fp0,%fp2 # check if abs(YINT) = 10^LEN
24196 fbneq.w A14_st # if not, skip this
24197 fdiv.s FTEN(%pc),%fp0 # divide abs(YINT) by 10
24198 addq.l &1,%d6 # and inc ILOG by 1
24199 addq.l &1,%d4 # and inc LEN
24200 fmul.s FTEN(%pc),%fp2 # if LEN++, the get 10^^LEN
24201
24202# A14. Convert the mantissa to bcd.
24203# The binstr routine is used to convert the LEN digit
24204# mantissa to bcd in memory. The input to binstr is
24205# to be a fraction; i.e. (mantissa)/10^LEN and adjusted
24206# such that the decimal point is to the left of bit 63.
24207# The bcd digits are stored in the correct position in
24208# the final string area in memory.
24209#
24210#
24211# Register usage:
24212# Input/Output
24213# d0: x/LEN call to binstr - final is 0
24214# d1: x/0
24215# d2: x/ms 32-bits of mant of abs(YINT)
24216# d3: x/ls 32-bits of mant of abs(YINT)
24217# d4: LEN/Unchanged
24218# d5: ICTR:LAMBDA/LAMBDA:ICTR
24219# d6: ILOG
24220# d7: k-factor/Unchanged
24221# a0: pointer into memory for packed bcd string formation
24222# /ptr to first mantissa byte in result string
24223# a1: ptr to PTENxx array/Unchanged
24224# a2: ptr to FP_SCR1(a6)/Unchanged
24225# fp0: int portion of Y/abs(YINT) adjusted
24226# fp1: 10^ISCALE/Unchanged
24227# fp2: 10^LEN/Unchanged
24228# F_SCR1:x/Work area for final result
24229# F_SCR2:Y with original exponent/Unchanged
24230# L_SCR1:original USER_FPCR/Unchanged
24231# L_SCR2:first word of X packed/Unchanged
24232
24233A14_st:
24234 fmov.l &rz_mode*0x10,%fpcr # force rz for conversion
24235 fdiv.x %fp2,%fp0 # divide abs(YINT) by 10^LEN
24236 lea.l FP_SCR0(%a6),%a0
24237 fmov.x %fp0,(%a0) # move abs(YINT)/10^LEN to memory
24238 mov.l 4(%a0),%d2 # move 2nd word of FP_RES to d2
24239 mov.l 8(%a0),%d3 # move 3rd word of FP_RES to d3
24240 clr.l 4(%a0) # zero word 2 of FP_RES
24241 clr.l 8(%a0) # zero word 3 of FP_RES
24242 mov.l (%a0),%d0 # move exponent to d0
24243 swap %d0 # put exponent in lower word
24244 beq.b no_sft # if zero, don't shift
24245 sub.l &0x3ffd,%d0 # sub bias less 2 to make fract
24246 tst.l %d0 # check if > 1
24247 bgt.b no_sft # if so, don't shift
24248 neg.l %d0 # make exp positive
24249m_loop:
24250 lsr.l &1,%d2 # shift d2:d3 right, add 0s
24251 roxr.l &1,%d3 # the number of places
24252 dbf.w %d0,m_loop # given in d0
24253no_sft:
24254 tst.l %d2 # check for mantissa of zero
24255 bne.b no_zr # if not, go on
24256 tst.l %d3 # continue zero check
24257 beq.b zer_m # if zero, go directly to binstr
24258no_zr:
24259 clr.l %d1 # put zero in d1 for addx
24260 add.l &0x00000080,%d3 # inc at bit 7
24261 addx.l %d1,%d2 # continue inc
24262 and.l &0xffffff80,%d3 # strip off lsb not used by 882
24263zer_m:
24264 mov.l %d4,%d0 # put LEN in d0 for binstr call
24265 addq.l &3,%a0 # a0 points to M16 byte in result
24266 bsr binstr # call binstr to convert mant
24267
24268
24269# A15. Convert the exponent to bcd.
24270# As in A14 above, the exp is converted to bcd and the
24271# digits are stored in the final string.
24272#
24273# Digits are stored in L_SCR1(a6) on return from BINDEC as:
24274#
24275# 32 16 15 0
24276# -----------------------------------------
24277# | 0 | e3 | e2 | e1 | e4 | X | X | X |
24278# -----------------------------------------
24279#
24280# And are moved into their proper places in FP_SCR0. If digit e4
24281# is non-zero, OPERR is signaled. In all cases, all 4 digits are
24282# written as specified in the 881/882 manual for packed decimal.
24283#
24284# Register usage:
24285# Input/Output
24286# d0: x/LEN call to binstr - final is 0
24287# d1: x/scratch (0);shift count for final exponent packing
24288# d2: x/ms 32-bits of exp fraction/scratch
24289# d3: x/ls 32-bits of exp fraction
24290# d4: LEN/Unchanged
24291# d5: ICTR:LAMBDA/LAMBDA:ICTR
24292# d6: ILOG
24293# d7: k-factor/Unchanged
24294# a0: ptr to result string/ptr to L_SCR1(a6)
24295# a1: ptr to PTENxx array/Unchanged
24296# a2: ptr to FP_SCR1(a6)/Unchanged
24297# fp0: abs(YINT) adjusted/float(ILOG)
24298# fp1: 10^ISCALE/Unchanged
24299# fp2: 10^LEN/Unchanged
24300# F_SCR1:Work area for final result/BCD result
24301# F_SCR2:Y with original exponent/ILOG/10^4
24302# L_SCR1:original USER_FPCR/Exponent digits on return from binstr
24303# L_SCR2:first word of X packed/Unchanged
24304
24305A15_st:
24306 tst.b BINDEC_FLG(%a6) # check for denorm
24307 beq.b not_denorm
24308 ftest.x %fp0 # test for zero
24309 fbeq.w den_zero # if zero, use k-factor or 4933
24310 fmov.l %d6,%fp0 # float ILOG
24311 fabs.x %fp0 # get abs of ILOG
24312 bra.b convrt
24313den_zero:
24314 tst.l %d7 # check sign of the k-factor
24315 blt.b use_ilog # if negative, use ILOG
24316 fmov.s F4933(%pc),%fp0 # force exponent to 4933
24317 bra.b convrt # do it
24318use_ilog:
24319 fmov.l %d6,%fp0 # float ILOG
24320 fabs.x %fp0 # get abs of ILOG
24321 bra.b convrt
24322not_denorm:
24323 ftest.x %fp0 # test for zero
24324 fbneq.w not_zero # if zero, force exponent
24325 fmov.s FONE(%pc),%fp0 # force exponent to 1
24326 bra.b convrt # do it
24327not_zero:
24328 fmov.l %d6,%fp0 # float ILOG
24329 fabs.x %fp0 # get abs of ILOG
24330convrt:
24331 fdiv.x 24(%a1),%fp0 # compute ILOG/10^4
24332 fmov.x %fp0,FP_SCR1(%a6) # store fp0 in memory
24333 mov.l 4(%a2),%d2 # move word 2 to d2
24334 mov.l 8(%a2),%d3 # move word 3 to d3
24335 mov.w (%a2),%d0 # move exp to d0
24336 beq.b x_loop_fin # if zero, skip the shift
24337 sub.w &0x3ffd,%d0 # subtract off bias
24338 neg.w %d0 # make exp positive
24339x_loop:
24340 lsr.l &1,%d2 # shift d2:d3 right
24341 roxr.l &1,%d3 # the number of places
24342 dbf.w %d0,x_loop # given in d0
24343x_loop_fin:
24344 clr.l %d1 # put zero in d1 for addx
24345 add.l &0x00000080,%d3 # inc at bit 6
24346 addx.l %d1,%d2 # continue inc
24347 and.l &0xffffff80,%d3 # strip off lsb not used by 882
24348 mov.l &4,%d0 # put 4 in d0 for binstr call
24349 lea.l L_SCR1(%a6),%a0 # a0 is ptr to L_SCR1 for exp digits
24350 bsr binstr # call binstr to convert exp
24351 mov.l L_SCR1(%a6),%d0 # load L_SCR1 lword to d0
24352 mov.l &12,%d1 # use d1 for shift count
24353 lsr.l %d1,%d0 # shift d0 right by 12
24354 bfins %d0,FP_SCR0(%a6){&4:&12} # put e3:e2:e1 in FP_SCR0
24355 lsr.l %d1,%d0 # shift d0 right by 12
24356 bfins %d0,FP_SCR0(%a6){&16:&4} # put e4 in FP_SCR0
24357 tst.b %d0 # check if e4 is zero
24358 beq.b A16_st # if zero, skip rest
24359 or.l &opaop_mask,USER_FPSR(%a6) # set OPERR & AIOP in USER_FPSR
24360
24361
24362# A16. Write sign bits to final string.
24363# Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
24364#
24365# Register usage:
24366# Input/Output
24367# d0: x/scratch - final is x
24368# d2: x/x
24369# d3: x/x
24370# d4: LEN/Unchanged
24371# d5: ICTR:LAMBDA/LAMBDA:ICTR
24372# d6: ILOG/ILOG adjusted
24373# d7: k-factor/Unchanged
24374# a0: ptr to L_SCR1(a6)/Unchanged
24375# a1: ptr to PTENxx array/Unchanged
24376# a2: ptr to FP_SCR1(a6)/Unchanged
24377# fp0: float(ILOG)/Unchanged
24378# fp1: 10^ISCALE/Unchanged
24379# fp2: 10^LEN/Unchanged
24380# F_SCR1:BCD result with correct signs
24381# F_SCR2:ILOG/10^4
24382# L_SCR1:Exponent digits on return from binstr
24383# L_SCR2:first word of X packed/Unchanged
24384
24385A16_st:
24386 clr.l %d0 # clr d0 for collection of signs
24387 and.b &0x0f,FP_SCR0(%a6) # clear first nibble of FP_SCR0
24388 tst.l L_SCR2(%a6) # check sign of original mantissa
24389 bge.b mant_p # if pos, don't set SM
24390 mov.l &2,%d0 # move 2 in to d0 for SM
24391mant_p:
24392 tst.l %d6 # check sign of ILOG
24393 bge.b wr_sgn # if pos, don't set SE
24394 addq.l &1,%d0 # set bit 0 in d0 for SE
24395wr_sgn:
24396 bfins %d0,FP_SCR0(%a6){&0:&2} # insert SM and SE into FP_SCR0
24397
24398# Clean up and restore all registers used.
24399
24400 fmov.l &0,%fpsr # clear possible inex2/ainex bits
24401 fmovm.x (%sp)+,&0xe0 # {%fp0-%fp2}
24402 movm.l (%sp)+,&0x4fc # {%d2-%d7/%a2}
24403 rts
24404
24405 global PTENRN
24406PTENRN:
24407 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
24408 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
24409 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
24410 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
24411 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
24412 long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
24413 long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
24414 long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
24415 long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
24416 long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
24417 long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
24418 long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
24419 long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
24420
24421 global PTENRP
24422PTENRP:
24423 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
24424 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
24425 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
24426 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
24427 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
24428 long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
24429 long 0x40D30000,0xC2781F49,0xFFCFA6D6 # 10 ^ 64
24430 long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
24431 long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
24432 long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
24433 long 0x4D480000,0xC9767586,0x81750C18 # 10 ^ 1024
24434 long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
24435 long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
24436
24437 global PTENRM
24438PTENRM:
24439 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
24440 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
24441 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
24442 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
24443 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
24444 long 0x40690000,0x9DC5ADA8,0x2B70B59D # 10 ^ 32
24445 long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
24446 long 0x41A80000,0x93BA47C9,0x80E98CDF # 10 ^ 128
24447 long 0x43510000,0xAA7EEBFB,0x9DF9DE8D # 10 ^ 256
24448 long 0x46A30000,0xE319A0AE,0xA60E91C6 # 10 ^ 512
24449 long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
24450 long 0x5A920000,0x9E8B3B5D,0xC53D5DE4 # 10 ^ 2048
24451 long 0x75250000,0xC4605202,0x8A20979A # 10 ^ 4096
24452
24453#########################################################################
24454# binstr(): Converts a 64-bit binary integer to bcd. #
24455# #
24456# INPUT *************************************************************** #
24457# d2:d3 = 64-bit binary integer #
24458# d0 = desired length (LEN) #
24459# a0 = pointer to start in memory for bcd characters #
24460# (This pointer must point to byte 4 of the first #
24461# lword of the packed decimal memory string.) #
24462# #
24463# OUTPUT ************************************************************** #
24464# a0 = pointer to LEN bcd digits representing the 64-bit integer. #
24465# #
24466# ALGORITHM *********************************************************** #
24467# The 64-bit binary is assumed to have a decimal point before #
24468# bit 63. The fraction is multiplied by 10 using a mul by 2 #
24469# shift and a mul by 8 shift. The bits shifted out of the #
24470# msb form a decimal digit. This process is iterated until #
24471# LEN digits are formed. #
24472# #
24473# A1. Init d7 to 1. D7 is the byte digit counter, and if 1, the #
24474# digit formed will be assumed the least significant. This is #
24475# to force the first byte formed to have a 0 in the upper 4 bits. #
24476# #
24477# A2. Beginning of the loop: #
24478# Copy the fraction in d2:d3 to d4:d5. #
24479# #
24480# A3. Multiply the fraction in d2:d3 by 8 using bit-field #
24481# extracts and shifts. The three msbs from d2 will go into d1. #
24482# #
24483# A4. Multiply the fraction in d4:d5 by 2 using shifts. The msb #
24484# will be collected by the carry. #
24485# #
24486# A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5 #
24487# into d2:d3. D1 will contain the bcd digit formed. #
24488# #
24489# A6. Test d7. If zero, the digit formed is the ms digit. If non- #
24490# zero, it is the ls digit. Put the digit in its place in the #
24491# upper word of d0. If it is the ls digit, write the word #
24492# from d0 to memory. #
24493# #
24494# A7. Decrement d6 (LEN counter) and repeat the loop until zero. #
24495# #
24496#########################################################################
24497
24498# Implementation Notes:
24499#
24500# The registers are used as follows:
24501#
24502# d0: LEN counter
24503# d1: temp used to form the digit
24504# d2: upper 32-bits of fraction for mul by 8
24505# d3: lower 32-bits of fraction for mul by 8
24506# d4: upper 32-bits of fraction for mul by 2
24507# d5: lower 32-bits of fraction for mul by 2
24508# d6: temp for bit-field extracts
24509# d7: byte digit formation word;digit count {0,1}
24510# a0: pointer into memory for packed bcd string formation
24511#
24512
24513 global binstr
24514binstr:
24515 movm.l &0xff00,-(%sp) # {%d0-%d7}
24516
24517#
24518# A1: Init d7
24519#
24520 mov.l &1,%d7 # init d7 for second digit
24521 subq.l &1,%d0 # for dbf d0 would have LEN+1 passes
24522#
24523# A2. Copy d2:d3 to d4:d5. Start loop.
24524#
24525loop:
24526 mov.l %d2,%d4 # copy the fraction before muls
24527 mov.l %d3,%d5 # to d4:d5
24528#
24529# A3. Multiply d2:d3 by 8; extract msbs into d1.
24530#
24531 bfextu %d2{&0:&3},%d1 # copy 3 msbs of d2 into d1
24532 asl.l &3,%d2 # shift d2 left by 3 places
24533 bfextu %d3{&0:&3},%d6 # copy 3 msbs of d3 into d6
24534 asl.l &3,%d3 # shift d3 left by 3 places
24535 or.l %d6,%d2 # or in msbs from d3 into d2
24536#
24537# A4. Multiply d4:d5 by 2; add carry out to d1.
24538#
24539 asl.l &1,%d5 # mul d5 by 2
24540 roxl.l &1,%d4 # mul d4 by 2
24541 swap %d6 # put 0 in d6 lower word
24542 addx.w %d6,%d1 # add in extend from mul by 2
24543#
24544# A5. Add mul by 8 to mul by 2. D1 contains the digit formed.
24545#
24546 add.l %d5,%d3 # add lower 32 bits
24547 nop # ERRATA FIX #13 (Rev. 1.2 6/6/90)
24548 addx.l %d4,%d2 # add with extend upper 32 bits
24549 nop # ERRATA FIX #13 (Rev. 1.2 6/6/90)
24550 addx.w %d6,%d1 # add in extend from add to d1
24551 swap %d6 # with d6 = 0; put 0 in upper word
24552#
24553# A6. Test d7 and branch.
24554#
24555 tst.w %d7 # if zero, store digit & to loop
24556 beq.b first_d # if non-zero, form byte & write
24557sec_d:
24558 swap %d7 # bring first digit to word d7b
24559 asl.w &4,%d7 # first digit in upper 4 bits d7b
24560 add.w %d1,%d7 # add in ls digit to d7b
24561 mov.b %d7,(%a0)+ # store d7b byte in memory
24562 swap %d7 # put LEN counter in word d7a
24563 clr.w %d7 # set d7a to signal no digits done
24564 dbf.w %d0,loop # do loop some more!
24565 bra.b end_bstr # finished, so exit
24566first_d:
24567 swap %d7 # put digit word in d7b
24568 mov.w %d1,%d7 # put new digit in d7b
24569 swap %d7 # put LEN counter in word d7a
24570 addq.w &1,%d7 # set d7a to signal first digit done
24571 dbf.w %d0,loop # do loop some more!
24572 swap %d7 # put last digit in string
24573 lsl.w &4,%d7 # move it to upper 4 bits
24574 mov.b %d7,(%a0)+ # store it in memory string
24575#
24576# Clean up and return with result in fp0.
24577#
24578end_bstr:
24579 movm.l (%sp)+,&0xff # {%d0-%d7}
24580 rts
24581
24582#########################################################################
24583# XDEF **************************************************************** #
24584# facc_in_b(): dmem_read_byte failed #
24585# facc_in_w(): dmem_read_word failed #
24586# facc_in_l(): dmem_read_long failed #
24587# facc_in_d(): dmem_read of dbl prec failed #
24588# facc_in_x(): dmem_read of ext prec failed #
24589# #
24590# facc_out_b(): dmem_write_byte failed #
24591# facc_out_w(): dmem_write_word failed #
24592# facc_out_l(): dmem_write_long failed #
24593# facc_out_d(): dmem_write of dbl prec failed #
24594# facc_out_x(): dmem_write of ext prec failed #
24595# #
24596# XREF **************************************************************** #
24597# _real_access() - exit through access error handler #
24598# #
24599# INPUT *************************************************************** #
24600# None #
24601# #
24602# OUTPUT ************************************************************** #
24603# None #
24604# #
24605# ALGORITHM *********************************************************** #
24606# Flow jumps here when an FP data fetch call gets an error #
24607# result. This means the operating system wants an access error frame #
24608# made out of the current exception stack frame. #
24609# So, we first call restore() which makes sure that any updated #
24610# -(an)+ register gets returned to its pre-exception value and then #
24611# we change the stack to an access error stack frame. #
24612# #
24613#########################################################################
24614
24615facc_in_b:
24616 movq.l &0x1,%d0 # one byte
24617 bsr.w restore # fix An
24618
24619 mov.w &0x0121,EXC_VOFF(%a6) # set FSLW
24620 bra.w facc_finish
24621
24622facc_in_w:
24623 movq.l &0x2,%d0 # two bytes
24624 bsr.w restore # fix An
24625
24626 mov.w &0x0141,EXC_VOFF(%a6) # set FSLW
24627 bra.b facc_finish
24628
24629facc_in_l:
24630 movq.l &0x4,%d0 # four bytes
24631 bsr.w restore # fix An
24632
24633 mov.w &0x0101,EXC_VOFF(%a6) # set FSLW
24634 bra.b facc_finish
24635
24636facc_in_d:
24637 movq.l &0x8,%d0 # eight bytes
24638 bsr.w restore # fix An
24639
24640 mov.w &0x0161,EXC_VOFF(%a6) # set FSLW
24641 bra.b facc_finish
24642
24643facc_in_x:
24644 movq.l &0xc,%d0 # twelve bytes
24645 bsr.w restore # fix An
24646
24647 mov.w &0x0161,EXC_VOFF(%a6) # set FSLW
24648 bra.b facc_finish
24649
24650################################################################
24651
24652facc_out_b:
24653 movq.l &0x1,%d0 # one byte
24654 bsr.w restore # restore An
24655
24656 mov.w &0x00a1,EXC_VOFF(%a6) # set FSLW
24657 bra.b facc_finish
24658
24659facc_out_w:
24660 movq.l &0x2,%d0 # two bytes
24661 bsr.w restore # restore An
24662
24663 mov.w &0x00c1,EXC_VOFF(%a6) # set FSLW
24664 bra.b facc_finish
24665
24666facc_out_l:
24667 movq.l &0x4,%d0 # four bytes
24668 bsr.w restore # restore An
24669
24670 mov.w &0x0081,EXC_VOFF(%a6) # set FSLW
24671 bra.b facc_finish
24672
24673facc_out_d:
24674 movq.l &0x8,%d0 # eight bytes
24675 bsr.w restore # restore An
24676
24677 mov.w &0x00e1,EXC_VOFF(%a6) # set FSLW
24678 bra.b facc_finish
24679
24680facc_out_x:
24681 mov.l &0xc,%d0 # twelve bytes
24682 bsr.w restore # restore An
24683
24684 mov.w &0x00e1,EXC_VOFF(%a6) # set FSLW
24685
24686# here's where we actually create the access error frame from the
24687# current exception stack frame.
24688facc_finish:
24689 mov.l USER_FPIAR(%a6),EXC_PC(%a6) # store current PC
24690
24691 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
24692 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
24693 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
24694
24695 unlk %a6
24696
24697 mov.l (%sp),-(%sp) # store SR, hi(PC)
24698 mov.l 0x8(%sp),0x4(%sp) # store lo(PC)
24699 mov.l 0xc(%sp),0x8(%sp) # store EA
24700 mov.l &0x00000001,0xc(%sp) # store FSLW
24701 mov.w 0x6(%sp),0xc(%sp) # fix FSLW (size)
24702 mov.w &0x4008,0x6(%sp) # store voff
24703
24704 btst &0x5,(%sp) # supervisor or user mode?
24705 beq.b facc_out2 # user
24706 bset &0x2,0xd(%sp) # set supervisor TM bit
24707
24708facc_out2:
24709 bra.l _real_access
24710
24711##################################################################
24712
24713# if the effective addressing mode was predecrement or postincrement,
24714# the emulation has already changed its value to the correct post-
24715# instruction value. but since we're exiting to the access error
24716# handler, then AN must be returned to its pre-instruction value.
24717# we do that here.
24718restore:
24719 mov.b EXC_OPWORD+0x1(%a6),%d1
24720 andi.b &0x38,%d1 # extract opmode
24721 cmpi.b %d1,&0x18 # postinc?
24722 beq.w rest_inc
24723 cmpi.b %d1,&0x20 # predec?
24724 beq.w rest_dec
24725 rts
24726
24727rest_inc:
24728 mov.b EXC_OPWORD+0x1(%a6),%d1
24729 andi.w &0x0007,%d1 # fetch An
24730
24731 mov.w (tbl_rest_inc.b,%pc,%d1.w*2),%d1
24732 jmp (tbl_rest_inc.b,%pc,%d1.w*1)
24733
24734tbl_rest_inc:
24735 short ri_a0 - tbl_rest_inc
24736 short ri_a1 - tbl_rest_inc
24737 short ri_a2 - tbl_rest_inc
24738 short ri_a3 - tbl_rest_inc
24739 short ri_a4 - tbl_rest_inc
24740 short ri_a5 - tbl_rest_inc
24741 short ri_a6 - tbl_rest_inc
24742 short ri_a7 - tbl_rest_inc
24743
24744ri_a0:
24745 sub.l %d0,EXC_DREGS+0x8(%a6) # fix stacked a0
24746 rts
24747ri_a1:
24748 sub.l %d0,EXC_DREGS+0xc(%a6) # fix stacked a1
24749 rts
24750ri_a2:
24751 sub.l %d0,%a2 # fix a2
24752 rts
24753ri_a3:
24754 sub.l %d0,%a3 # fix a3
24755 rts
24756ri_a4:
24757 sub.l %d0,%a4 # fix a4
24758 rts
24759ri_a5:
24760 sub.l %d0,%a5 # fix a5
24761 rts
24762ri_a6:
24763 sub.l %d0,(%a6) # fix stacked a6
24764 rts
24765# if it's a fmove out instruction, we don't have to fix a7
24766# because we hadn't changed it yet. if it's an opclass two
24767# instruction (data moved in) and the exception was in supervisor
24768# mode, then also also wasn't updated. if it was user mode, then
24769# restore the correct a7 which is in the USP currently.
24770ri_a7:
24771 cmpi.b EXC_VOFF(%a6),&0x30 # move in or out?
24772 bne.b ri_a7_done # out
24773
24774 btst &0x5,EXC_SR(%a6) # user or supervisor?
24775 bne.b ri_a7_done # supervisor
24776 movc %usp,%a0 # restore USP
24777 sub.l %d0,%a0
24778 movc %a0,%usp
24779ri_a7_done:
24780 rts
24781
24782# need to invert adjustment value if the <ea> was predec
24783rest_dec:
24784 neg.l %d0
24785 bra.b rest_inc
diff --git a/arch/m68k/ifpsp060/src/ftest.S b/arch/m68k/ifpsp060/src/ftest.S
new file mode 100644
index 000000000000..2edcbae0fd53
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/ftest.S
@@ -0,0 +1,1456 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29#############################################
30set SREGS, -64
31set IREGS, -128
32set IFPREGS, -224
33set SFPREGS, -320
34set IFPCREGS, -332
35set SFPCREGS, -344
36set ICCR, -346
37set SCCR, -348
38set TESTCTR, -352
39set DATA, -384
40
41#############################################
42TESTTOP:
43 bra.l _060TESTS_
44 short 0x0000
45
46 bra.l _060TESTS_unimp
47 short 0x0000
48
49 bra.l _060TESTS_enable
50 short 0x0000
51
52start_str:
53 string "Testing 68060 FPSP started:\n"
54
55start_str_unimp:
56 string "Testing 68060 FPSP unimplemented instruction started:\n"
57
58start_str_enable:
59 string "Testing 68060 FPSP exception enabled started:\n"
60
61pass_str:
62 string "passed\n"
63
64fail_str:
65 string " failed\n"
66
67 align 0x4
68chk_test:
69 tst.l %d0
70 bne.b test_fail
71test_pass:
72 pea pass_str(%pc)
73 bsr.l _print_str
74 addq.l &0x4,%sp
75 rts
76test_fail:
77 mov.l %d1,-(%sp)
78 bsr.l _print_num
79 addq.l &0x4,%sp
80
81 pea fail_str(%pc)
82 bsr.l _print_str
83 addq.l &0x4,%sp
84 rts
85
86#############################################
87_060TESTS_:
88 link %a6,&-384
89
90 movm.l &0x3f3c,-(%sp)
91 fmovm.x &0xff,-(%sp)
92
93 pea start_str(%pc)
94 bsr.l _print_str
95 addq.l &0x4,%sp
96
97### effadd
98 clr.l TESTCTR(%a6)
99 pea effadd_str(%pc)
100 bsr.l _print_str
101 addq.l &0x4,%sp
102
103 bsr.l effadd_0
104
105 bsr.l chk_test
106
107### unsupp
108 clr.l TESTCTR(%a6)
109 pea unsupp_str(%pc)
110 bsr.l _print_str
111 addq.l &0x4,%sp
112
113 bsr.l unsupp_0
114
115 bsr.l chk_test
116
117### ovfl non-maskable
118 clr.l TESTCTR(%a6)
119 pea ovfl_nm_str(%pc)
120 bsr.l _print_str
121 bsr.l ovfl_nm_0
122
123 bsr.l chk_test
124
125### unfl non-maskable
126 clr.l TESTCTR(%a6)
127 pea unfl_nm_str(%pc)
128 bsr.l _print_str
129 bsr.l unfl_nm_0
130
131 bsr.l chk_test
132
133 movm.l (%sp)+,&0x3cfc
134 fmovm.x (%sp)+,&0xff
135
136 unlk %a6
137 rts
138
139_060TESTS_unimp:
140 link %a6,&-384
141
142 movm.l &0x3f3c,-(%sp)
143 fmovm.x &0xff,-(%sp)
144
145 pea start_str_unimp(%pc)
146 bsr.l _print_str
147 addq.l &0x4,%sp
148
149### unimp
150 clr.l TESTCTR(%a6)
151 pea unimp_str(%pc)
152 bsr.l _print_str
153 addq.l &0x4,%sp
154
155 bsr.l unimp_0
156
157 bsr.l chk_test
158
159 movm.l (%sp)+,&0x3cfc
160 fmovm.x (%sp)+,&0xff
161
162 unlk %a6
163 rts
164
165_060TESTS_enable:
166 link %a6,&-384
167
168 movm.l &0x3f3c,-(%sp)
169 fmovm.x &0xff,-(%sp)
170
171 pea start_str_enable(%pc)
172 bsr.l _print_str
173 addq.l &0x4,%sp
174
175### snan
176 clr.l TESTCTR(%a6)
177 pea snan_str(%pc)
178 bsr.l _print_str
179 bsr.l snan_0
180
181 bsr.l chk_test
182
183### operr
184 clr.l TESTCTR(%a6)
185 pea operr_str(%pc)
186 bsr.l _print_str
187 bsr.l operr_0
188
189 bsr.l chk_test
190
191### ovfl
192 clr.l TESTCTR(%a6)
193 pea ovfl_str(%pc)
194 bsr.l _print_str
195 bsr.l ovfl_0
196
197 bsr.l chk_test
198
199### unfl
200 clr.l TESTCTR(%a6)
201 pea unfl_str(%pc)
202 bsr.l _print_str
203 bsr.l unfl_0
204
205 bsr.l chk_test
206
207### dz
208 clr.l TESTCTR(%a6)
209 pea dz_str(%pc)
210 bsr.l _print_str
211 bsr.l dz_0
212
213 bsr.l chk_test
214
215### inexact
216 clr.l TESTCTR(%a6)
217 pea inex_str(%pc)
218 bsr.l _print_str
219 bsr.l inex_0
220
221 bsr.l chk_test
222
223 movm.l (%sp)+,&0x3cfc
224 fmovm.x (%sp)+,&0xff
225
226 unlk %a6
227 rts
228
229#############################################
230#############################################
231
232unimp_str:
233 string "\tUnimplemented FP instructions..."
234
235 align 0x4
236unimp_0:
237 addq.l &0x1,TESTCTR(%a6)
238
239 movm.l DEF_REGS(%pc),&0x3fff
240 fmovm.x DEF_FPREGS(%pc),&0xff
241 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
242
243 mov.w &0x0000,ICCR(%a6)
244 movm.l &0x7fff,IREGS(%a6)
245 fmovm.x &0xff,IFPREGS(%a6)
246 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
247
248 mov.l &0x40000000,DATA+0x0(%a6)
249 mov.l &0xc90fdaa2,DATA+0x4(%a6)
250 mov.l &0x2168c235,DATA+0x8(%a6)
251
252 mov.w &0x0000,%cc
253unimp_0_pc:
254 fsin.x DATA(%a6),%fp0
255
256 mov.w %cc,SCCR(%a6)
257 movm.l &0x7fff,SREGS(%a6)
258 fmovm.x &0xff,SFPREGS(%a6)
259 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
260
261 mov.l &0xbfbf0000,IFPREGS+0x0(%a6)
262 mov.l &0x80000000,IFPREGS+0x4(%a6)
263 mov.l &0x00000000,IFPREGS+0x8(%a6)
264 mov.l &0x08000208,IFPCREGS+0x4(%a6)
265 lea unimp_0_pc(%pc),%a0
266 mov.l %a0,IFPCREGS+0x8(%a6)
267
268 bsr.l chkregs
269 tst.b %d0
270 bne.l error
271
272 bsr.l chkfpregs
273 tst.b %d0
274 bne.l error
275
276unimp_1:
277 addq.l &0x1,TESTCTR(%a6)
278
279 movm.l DEF_REGS(%pc),&0x3fff
280 fmovm.x DEF_FPREGS(%pc),&0xff
281 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
282
283 mov.w &0x0000,ICCR(%a6)
284 movm.l &0x7fff,IREGS(%a6)
285 fmovm.x &0xff,IFPREGS(%a6)
286 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
287
288 mov.l &0x3ffe0000,DATA+0x0(%a6)
289 mov.l &0xc90fdaa2,DATA+0x4(%a6)
290 mov.l &0x2168c235,DATA+0x8(%a6)
291
292 mov.w &0x0000,%cc
293unimp_1_pc:
294 ftan.x DATA(%a6),%fp0
295
296 mov.w %cc,SCCR(%a6)
297 movm.l &0x7fff,SREGS(%a6)
298 fmovm.x &0xff,SFPREGS(%a6)
299 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
300
301 mov.l &0x3fff0000,IFPREGS+0x0(%a6)
302 mov.l &0x80000000,IFPREGS+0x4(%a6)
303 mov.l &0x00000000,IFPREGS+0x8(%a6)
304 mov.l &0x00000208,IFPCREGS+0x4(%a6)
305 lea unimp_1_pc(%pc),%a0
306 mov.l %a0,IFPCREGS+0x8(%a6)
307
308 bsr.l chkregs
309 tst.b %d0
310 bne.l error
311
312 bsr.l chkfpregs
313 tst.b %d0
314 bne.l error
315
316# fmovecr
317unimp_2:
318 addq.l &0x1,TESTCTR(%a6)
319
320 movm.l DEF_REGS(%pc),&0x3fff
321 fmovm.x DEF_FPREGS(%pc),&0xff
322 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
323
324 mov.w &0x0000,ICCR(%a6)
325 movm.l &0x7fff,IREGS(%a6)
326 fmovm.x &0xff,IFPREGS(%a6)
327 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
328
329 mov.w &0x0000,%cc
330unimp_2_pc:
331 fmovcr.x &0x31,%fp0
332
333 mov.w %cc,SCCR(%a6)
334 movm.l &0x7fff,SREGS(%a6)
335 fmovm.x &0xff,SFPREGS(%a6)
336 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
337
338 mov.l &0x40000000,IFPREGS+0x0(%a6)
339 mov.l &0x935d8ddd,IFPREGS+0x4(%a6)
340 mov.l &0xaaa8ac17,IFPREGS+0x8(%a6)
341 mov.l &0x00000208,IFPCREGS+0x4(%a6)
342 lea unimp_2_pc(%pc),%a0
343 mov.l %a0,IFPCREGS+0x8(%a6)
344
345 bsr.l chkregs
346 tst.b %d0
347 bne.l error
348
349 bsr.l chkfpregs
350 tst.b %d0
351 bne.l error
352
353# fscc
354unimp_3:
355 addq.l &0x1,TESTCTR(%a6)
356
357 movm.l DEF_REGS(%pc),&0x3fff
358 fmovm.x DEF_FPREGS(%pc),&0xff
359 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
360
361 fmov.l &0x0f000000,%fpsr
362 mov.l &0x00,%d7
363
364 mov.w &0x0000,ICCR(%a6)
365 movm.l &0x7fff,IREGS(%a6)
366 fmovm.x &0xff,IFPREGS(%a6)
367 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
368
369 mov.w &0x0000,%cc
370unimp_3_pc:
371 fsgt %d7
372
373 mov.w %cc,SCCR(%a6)
374 movm.l &0x7fff,SREGS(%a6)
375 fmovm.x &0xff,SFPREGS(%a6)
376 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
377 mov.l &0x0f008080,IFPCREGS+0x4(%a6)
378 lea unimp_3_pc(%pc),%a0
379 mov.l %a0,IFPCREGS+0x8(%a6)
380
381 bsr.l chkregs
382 tst.b %d0
383 bne.l error
384
385 bsr.l chkfpregs
386 tst.b %d0
387 bne.l error
388
389# fdbcc
390unimp_4:
391 addq.l &0x1,TESTCTR(%a6)
392
393 movm.l DEF_REGS(%pc),&0x3fff
394 fmovm.x DEF_FPREGS(%pc),&0xff
395 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
396
397 fmov.l &0x0f000000,%fpsr
398 mov.l &0x2,%d7
399
400 mov.w &0x0000,ICCR(%a6)
401 movm.l &0x7fff,IREGS(%a6)
402 fmovm.x &0xff,IFPREGS(%a6)
403 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
404
405 mov.w &0x0000,%cc
406unimp_4_pc:
407 fdbgt.w %d7,unimp_4_pc
408
409 mov.w %cc,SCCR(%a6)
410 movm.l &0x7fff,SREGS(%a6)
411 fmovm.x &0xff,SFPREGS(%a6)
412 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
413 mov.w &0xffff,IREGS+28+2(%a6)
414 mov.l &0x0f008080,IFPCREGS+0x4(%a6)
415 lea unimp_4_pc(%pc),%a0
416 mov.l %a0,IFPCREGS+0x8(%a6)
417
418 bsr.l chkregs
419 tst.b %d0
420 bne.l error
421
422 bsr.l chkfpregs
423 tst.b %d0
424 bne.l error
425
426# ftrapcc
427unimp_5:
428 addq.l &0x1,TESTCTR(%a6)
429
430 movm.l DEF_REGS(%pc),&0x3fff
431 fmovm.x DEF_FPREGS(%pc),&0xff
432 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
433
434 fmov.l &0x0f000000,%fpsr
435
436 mov.w &0x0000,ICCR(%a6)
437 movm.l &0x7fff,IREGS(%a6)
438 fmovm.x &0xff,IFPREGS(%a6)
439 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
440
441 mov.w &0x0000,%cc
442unimp_5_pc:
443 ftpgt.l &0xabcdef01
444
445 mov.w %cc,SCCR(%a6)
446 movm.l &0x7fff,SREGS(%a6)
447 fmovm.x &0xff,SFPREGS(%a6)
448 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
449 mov.l &0x0f008080,IFPCREGS+0x4(%a6)
450 lea unimp_5_pc(%pc),%a0
451 mov.l %a0,IFPCREGS+0x8(%a6)
452
453 bsr.l chkregs
454 tst.b %d0
455 bne.l error
456
457 bsr.l chkfpregs
458 tst.b %d0
459 bne.l error
460
461 clr.l %d0
462 rts
463
464#############################################
465
466effadd_str:
467 string "\tUnimplemented <ea>..."
468
469 align 0x4
470effadd_0:
471 addq.l &0x1,TESTCTR(%a6)
472
473 movm.l DEF_REGS(%pc),&0x3fff
474 fmovm.x DEF_FPREGS(%pc),&0xff
475 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
476
477 mov.w &0x0000,ICCR(%a6)
478 movm.l &0x7fff,IREGS(%a6)
479 fmovm.x &0xff,IFPREGS(%a6)
480 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
481
482 fmov.b &0x2,%fp0
483
484 mov.w &0x0000,%cc
485effadd_0_pc:
486 fmul.x &0xc00000008000000000000000,%fp0
487
488 mov.w %cc,SCCR(%a6)
489 movm.l &0x7fff,SREGS(%a6)
490 fmovm.x &0xff,SFPREGS(%a6)
491 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
492
493 mov.l &0xc0010000,IFPREGS+0x0(%a6)
494 mov.l &0x80000000,IFPREGS+0x4(%a6)
495 mov.l &0x00000000,IFPREGS+0x8(%a6)
496 mov.l &0x08000000,IFPCREGS+0x4(%a6)
497 lea effadd_0_pc(%pc),%a0
498 mov.l %a0,IFPCREGS+0x8(%a6)
499
500 bsr.l chkregs
501 tst.b %d0
502 bne.l error
503
504 bsr.l chkfpregs
505 tst.b %d0
506 bne.l error
507
508effadd_1:
509 addq.l &0x1,TESTCTR(%a6)
510
511 movm.l DEF_REGS(%pc),&0x3fff
512 fmovm.x DEF_FPREGS(%pc),&0xff
513 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
514
515 mov.w &0x0000,ICCR(%a6)
516 movm.l &0x7fff,IREGS(%a6)
517 fmovm.x &0xff,IFPREGS(%a6)
518 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
519
520 mov.w &0x0000,%cc
521effadd_1_pc:
522 fabs.p &0xc12300012345678912345678,%fp0
523
524 mov.w %cc,SCCR(%a6)
525 movm.l &0x7fff,SREGS(%a6)
526 fmovm.x &0xff,SFPREGS(%a6)
527 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
528
529 mov.l &0x3e660000,IFPREGS+0x0(%a6)
530 mov.l &0xd0ed23e8,IFPREGS+0x4(%a6)
531 mov.l &0xd14035bc,IFPREGS+0x8(%a6)
532 mov.l &0x00000108,IFPCREGS+0x4(%a6)
533 lea effadd_1_pc(%pc),%a0
534 mov.l %a0,IFPCREGS+0x8(%a6)
535
536 bsr.l chkregs
537 tst.b %d0
538 bne.l error
539
540 bsr.l chkfpregs
541 tst.b %d0
542 bne.l error
543
544fmovml_0:
545 addq.l &0x1,TESTCTR(%a6)
546
547 movm.l DEF_REGS(%pc),&0x3fff
548 fmovm.x DEF_FPREGS(%pc),&0xff
549 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
550
551 mov.w &0x0000,ICCR(%a6)
552 mov.w &0x0000,%cc
553 movm.l &0x7fff,IREGS(%a6)
554 fmovm.x &0xff,IFPREGS(%a6)
555 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
556
557 fmovm.l &0xffffffffffffffff,%fpcr,%fpsr
558
559 mov.w %cc,SCCR(%a6)
560 movm.l &0x7fff,SREGS(%a6)
561 fmovm.x &0xff,SFPREGS(%a6)
562 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
563 mov.l &0x0000fff0,IFPCREGS+0x0(%a6)
564 mov.l &0x0ffffff8,IFPCREGS+0x4(%a6)
565
566 bsr.l chkregs
567 tst.b %d0
568 bne.l error
569
570 bsr.l chkfpregs
571 tst.b %d0
572 bne.l error
573
574fmovml_1:
575 addq.l &0x1,TESTCTR(%a6)
576
577 movm.l DEF_REGS(%pc),&0x3fff
578 fmovm.x DEF_FPREGS(%pc),&0xff
579 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
580
581 mov.w &0x0000,ICCR(%a6)
582 mov.w &0x0000,%cc
583 movm.l &0x7fff,IREGS(%a6)
584 fmovm.x &0xff,IFPREGS(%a6)
585 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
586
587 fmovm.l &0xffffffffffffffff,%fpcr,%fpiar
588
589 mov.w %cc,SCCR(%a6)
590 movm.l &0x7fff,SREGS(%a6)
591 fmovm.x &0xff,SFPREGS(%a6)
592 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
593 mov.l &0x0000fff0,IFPCREGS+0x0(%a6)
594 mov.l &0xffffffff,IFPCREGS+0x8(%a6)
595
596 bsr.l chkregs
597 tst.b %d0
598 bne.l error
599
600 bsr.l chkfpregs
601 tst.b %d0
602 bne.l error
603
604fmovml_2:
605 addq.l &0x1,TESTCTR(%a6)
606
607 movm.l DEF_REGS(%pc),&0x3fff
608 fmovm.x DEF_FPREGS(%pc),&0xff
609 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
610
611 mov.w &0x0000,ICCR(%a6)
612 mov.w &0x0000,%cc
613 movm.l &0x7fff,IREGS(%a6)
614 fmovm.x &0xff,IFPREGS(%a6)
615 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
616
617 fmovm.l &0xffffffffffffffff,%fpsr,%fpiar
618
619 mov.w %cc,SCCR(%a6)
620 movm.l &0x7fff,SREGS(%a6)
621 fmovm.x &0xff,SFPREGS(%a6)
622 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
623 mov.l &0x0ffffff8,IFPCREGS+0x4(%a6)
624 mov.l &0xffffffff,IFPCREGS+0x8(%a6)
625
626 bsr.l chkregs
627 tst.b %d0
628 bne.l error
629
630 bsr.l chkfpregs
631 tst.b %d0
632 bne.l error
633
634fmovml_3:
635 addq.l &0x1,TESTCTR(%a6)
636
637 movm.l DEF_REGS(%pc),&0x3fff
638 fmovm.x DEF_FPREGS(%pc),&0xff
639 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
640
641 mov.w &0x0000,ICCR(%a6)
642 mov.w &0x0000,%cc
643 movm.l &0x7fff,IREGS(%a6)
644 fmovm.x &0xff,IFPREGS(%a6)
645 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
646
647 fmovm.l &0xffffffffffffffffffffffff,%fpcr,%fpsr,%fpiar
648
649 mov.w %cc,SCCR(%a6)
650 movm.l &0x7fff,SREGS(%a6)
651 fmovm.x &0xff,SFPREGS(%a6)
652 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
653 mov.l &0x0000fff0,IFPCREGS+0x0(%a6)
654 mov.l &0x0ffffff8,IFPCREGS+0x4(%a6)
655 mov.l &0xffffffff,IFPCREGS+0x8(%a6)
656
657 bsr.l chkregs
658 tst.b %d0
659 bne.l error
660
661 bsr.l chkfpregs
662 tst.b %d0
663 bne.l error
664
665# fmovmx dynamic
666fmovmx_0:
667 addq.l &0x1,TESTCTR(%a6)
668
669 movm.l DEF_REGS(%pc),&0x3fff
670 fmovm.x DEF_FPREGS(%pc),&0xff
671 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
672
673 fmov.b &0x1,%fp0
674 fmov.b &0x2,%fp1
675 fmov.b &0x3,%fp2
676 fmov.b &0x4,%fp3
677 fmov.b &0x5,%fp4
678 fmov.b &0x6,%fp5
679 fmov.b &0x7,%fp6
680 fmov.b &0x8,%fp7
681
682 fmov.l &0x0,%fpiar
683 mov.l &0xffffffaa,%d0
684
685 mov.w &0x0000,ICCR(%a6)
686 movm.l &0xffff,IREGS(%a6)
687
688 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
689 fmovm.x &0xff,IFPREGS(%a6)
690
691 mov.w &0x0000,%cc
692
693 fmovm.x %d0,-(%sp)
694
695 mov.w %cc,SCCR(%a6)
696
697 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
698
699 fmov.s &0x7f800000,%fp1
700 fmov.s &0x7f800000,%fp3
701 fmov.s &0x7f800000,%fp5
702 fmov.s &0x7f800000,%fp7
703
704 fmov.x (%sp)+,%fp1
705 fmov.x (%sp)+,%fp3
706 fmov.x (%sp)+,%fp5
707 fmov.x (%sp)+,%fp7
708
709 movm.l &0xffff,SREGS(%a6)
710 fmovm.x &0xff,SFPREGS(%a6)
711
712 bsr.l chkregs
713 tst.b %d0
714 bne.l error
715
716 bsr.l chkfpregs
717 tst.b %d0
718 bne.l error
719
720fmovmx_1:
721 addq.l &0x1,TESTCTR(%a6)
722
723 movm.l DEF_REGS(%pc),&0x3fff
724 fmovm.x DEF_FPREGS(%pc),&0xff
725 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
726
727 fmov.b &0x1,%fp0
728 fmov.b &0x2,%fp1
729 fmov.b &0x3,%fp2
730 fmov.b &0x4,%fp3
731 fmov.b &0x5,%fp4
732 fmov.b &0x6,%fp5
733 fmov.b &0x7,%fp6
734 fmov.b &0x8,%fp7
735
736 fmov.x %fp6,-(%sp)
737 fmov.x %fp4,-(%sp)
738 fmov.x %fp2,-(%sp)
739 fmov.x %fp0,-(%sp)
740
741 fmovm.x &0xff,IFPREGS(%a6)
742
743 fmov.s &0x7f800000,%fp6
744 fmov.s &0x7f800000,%fp4
745 fmov.s &0x7f800000,%fp2
746 fmov.s &0x7f800000,%fp0
747
748 fmov.l &0x0,%fpiar
749 fmov.l &0x0,%fpsr
750 mov.l &0xffffffaa,%d0
751
752 mov.w &0x0000,ICCR(%a6)
753 movm.l &0xffff,IREGS(%a6)
754
755 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
756
757 mov.w &0x0000,%cc
758
759 fmovm.x (%sp)+,%d0
760
761 mov.w %cc,SCCR(%a6)
762
763 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
764
765 movm.l &0xffff,SREGS(%a6)
766 fmovm.x &0xff,SFPREGS(%a6)
767
768 bsr.l chkregs
769 tst.b %d0
770 bne.l error
771
772 bsr.l chkfpregs
773 tst.b %d0
774 bne.l error
775
776fmovmx_2:
777 addq.l &0x1,TESTCTR(%a6)
778
779 movm.l DEF_REGS(%pc),&0x3fff
780 fmovm.x DEF_FPREGS(%pc),&0xff
781 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
782
783 fmov.b &0x1,%fp0
784 fmov.b &0x2,%fp1
785 fmov.b &0x3,%fp2
786 fmov.b &0x4,%fp3
787 fmov.b &0x5,%fp4
788 fmov.b &0x6,%fp5
789 fmov.b &0x7,%fp6
790 fmov.b &0x8,%fp7
791
792 fmov.l &0x0,%fpiar
793 mov.l &0xffffff00,%d0
794
795 mov.w &0x0000,ICCR(%a6)
796 movm.l &0xffff,IREGS(%a6)
797
798 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
799 fmovm.x &0xff,IFPREGS(%a6)
800
801 mov.w &0x0000,%cc
802
803 fmovm.x %d0,-(%sp)
804
805 mov.w %cc,SCCR(%a6)
806
807 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
808
809 movm.l &0xffff,SREGS(%a6)
810 fmovm.x &0xff,SFPREGS(%a6)
811
812 bsr.l chkregs
813 tst.b %d0
814 bne.l error
815
816 bsr.l chkfpregs
817 tst.b %d0
818 bne.l error
819
820 clr.l %d0
821 rts
822
823###########################################################
824
825# This test will take a non-maskable overflow directly.
826ovfl_nm_str:
827 string "\tNon-maskable overflow..."
828
829 align 0x4
830ovfl_nm_0:
831 addq.l &0x1,TESTCTR(%a6)
832
833 movm.l DEF_REGS(%pc),&0x3fff
834 fmovm.x DEF_FPREGS(%pc),&0xff
835 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
836
837 mov.w &0x0000,ICCR(%a6)
838 movm.l &0x7fff,IREGS(%a6)
839 fmovm.x &0xff,IFPREGS(%a6)
840 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
841
842 fmov.b &0x2,%fp0
843 mov.l &0x7ffe0000,DATA+0x0(%a6)
844 mov.l &0x80000000,DATA+0x4(%a6)
845 mov.l &0x00000000,DATA+0x8(%a6)
846
847 mov.w &0x0000,%cc
848ovfl_nm_0_pc:
849 fmul.x DATA(%a6),%fp0
850
851 mov.w %cc,SCCR(%a6)
852 movm.l &0x7fff,SREGS(%a6)
853 fmovm.x &0xff,SFPREGS(%a6)
854 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
855
856 mov.l &0x7fff0000,IFPREGS+0x0(%a6)
857 mov.l &0x00000000,IFPREGS+0x4(%a6)
858 mov.l &0x00000000,IFPREGS+0x8(%a6)
859 mov.l &0x02001048,IFPCREGS+0x4(%a6)
860 lea ovfl_nm_0_pc(%pc),%a0
861 mov.l %a0,IFPCREGS+0x8(%a6)
862
863 bsr.l chkregs
864 tst.b %d0
865 bne.l error
866
867 bsr.l chkfpregs
868 tst.b %d0
869 bne.l error
870
871 clr.l %d0
872 rts
873
874###########################################################
875
876# This test will take an overflow directly.
877ovfl_str:
878 string "\tEnabled overflow..."
879
880 align 0x4
881ovfl_0:
882 addq.l &0x1,TESTCTR(%a6)
883
884 movm.l DEF_REGS(%pc),&0x3fff
885 fmovm.x DEF_FPREGS(%pc),&0xff
886 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
887
888 mov.w &0x0000,ICCR(%a6)
889 movm.l &0x7fff,IREGS(%a6)
890 fmovm.x &0xff,IFPREGS(%a6)
891 fmov.l &0x00001000,%fpcr
892 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
893
894 fmov.b &0x2,%fp0
895 mov.l &0x7ffe0000,DATA+0x0(%a6)
896 mov.l &0x80000000,DATA+0x4(%a6)
897 mov.l &0x00000000,DATA+0x8(%a6)
898
899 mov.w &0x0000,%cc
900ovfl_0_pc:
901 fmul.x DATA(%a6),%fp0
902
903 mov.w %cc,SCCR(%a6)
904 movm.l &0x7fff,SREGS(%a6)
905 fmovm.x &0xff,SFPREGS(%a6)
906 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
907
908 mov.l &0x7fff0000,IFPREGS+0x0(%a6)
909 mov.l &0x00000000,IFPREGS+0x4(%a6)
910 mov.l &0x00000000,IFPREGS+0x8(%a6)
911 mov.l &0x02001048,IFPCREGS+0x4(%a6)
912 lea ovfl_0_pc(%pc),%a0
913 mov.l %a0,IFPCREGS+0x8(%a6)
914
915 bsr.l chkregs
916 tst.b %d0
917 bne.l error
918
919 bsr.l chkfpregs
920 tst.b %d0
921 bne.l error
922
923 clr.l %d0
924 rts
925
926#####################################################################
927
928# This test will take an underflow directly.
929unfl_str:
930 string "\tEnabled underflow..."
931
932 align 0x4
933unfl_0:
934 addq.l &0x1,TESTCTR(%a6)
935
936 movm.l DEF_REGS(%pc),&0x3fff
937 fmovm.x DEF_FPREGS(%pc),&0xff
938 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
939
940 mov.w &0x0000,ICCR(%a6)
941 movm.l &0x7fff,IREGS(%a6)
942 fmovm.x &0xff,IFPREGS(%a6)
943 fmov.l &0x00000800,%fpcr
944 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
945
946 mov.l &0x00000000,DATA+0x0(%a6)
947 mov.l &0x80000000,DATA+0x4(%a6)
948 mov.l &0x00000000,DATA+0x8(%a6)
949 fmovm.x DATA(%a6),&0x80
950
951 mov.w &0x0000,%cc
952unfl_0_pc:
953 fdiv.b &0x2,%fp0
954
955 mov.w %cc,SCCR(%a6)
956 movm.l &0x7fff,SREGS(%a6)
957 fmovm.x &0xff,SFPREGS(%a6)
958 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
959
960 mov.l &0x00000000,IFPREGS+0x0(%a6)
961 mov.l &0x40000000,IFPREGS+0x4(%a6)
962 mov.l &0x00000000,IFPREGS+0x8(%a6)
963 mov.l &0x00000800,IFPCREGS+0x4(%a6)
964 lea unfl_0_pc(%pc),%a0
965 mov.l %a0,IFPCREGS+0x8(%a6)
966
967 bsr.l chkregs
968 tst.b %d0
969 bne.l error
970
971 bsr.l chkfpregs
972 tst.b %d0
973 bne.l error
974
975 clr.l %d0
976 rts
977
978#####################################################################
979
980# This test will take a non-maskable underflow directly.
981unfl_nm_str:
982 string "\tNon-maskable underflow..."
983
984 align 0x4
985unfl_nm_0:
986 addq.l &0x1,TESTCTR(%a6)
987
988 movm.l DEF_REGS(%pc),&0x3fff
989 fmovm.x DEF_FPREGS(%pc),&0xff
990 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
991
992 mov.w &0x0000,ICCR(%a6)
993 movm.l &0x7fff,IREGS(%a6)
994 fmovm.x &0xff,IFPREGS(%a6)
995 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
996
997 mov.l &0x00000000,DATA+0x0(%a6)
998 mov.l &0x80000000,DATA+0x4(%a6)
999 mov.l &0x00000000,DATA+0x8(%a6)
1000 fmovm.x DATA(%a6),&0x80
1001
1002 mov.w &0x0000,%cc
1003unfl_nm_0_pc:
1004 fdiv.b &0x2,%fp0
1005
1006 mov.w %cc,SCCR(%a6)
1007 movm.l &0x7fff,SREGS(%a6)
1008 fmovm.x &0xff,SFPREGS(%a6)
1009 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
1010
1011 mov.l &0x00000000,IFPREGS+0x0(%a6)
1012 mov.l &0x40000000,IFPREGS+0x4(%a6)
1013 mov.l &0x00000000,IFPREGS+0x8(%a6)
1014 mov.l &0x00000800,IFPCREGS+0x4(%a6)
1015 lea unfl_nm_0_pc(%pc),%a0
1016 mov.l %a0,IFPCREGS+0x8(%a6)
1017
1018 bsr.l chkregs
1019 tst.b %d0
1020 bne.l error
1021
1022 bsr.l chkfpregs
1023 tst.b %d0
1024 bne.l error
1025
1026 clr.l %d0
1027 rts
1028
1029#####################################################################
1030
1031inex_str:
1032 string "\tEnabled inexact..."
1033
1034 align 0x4
1035inex_0:
1036 addq.l &0x1,TESTCTR(%a6)
1037
1038 movm.l DEF_REGS(%pc),&0x3fff
1039 fmovm.x DEF_FPREGS(%pc),&0xff
1040 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
1041
1042 mov.w &0x0000,ICCR(%a6)
1043 movm.l &0x7fff,IREGS(%a6)
1044 fmovm.x &0xff,IFPREGS(%a6)
1045 fmov.l &0x00000200,%fpcr # enable inexact
1046 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
1047
1048 mov.l &0x50000000,DATA+0x0(%a6)
1049 mov.l &0x80000000,DATA+0x4(%a6)
1050 mov.l &0x00000000,DATA+0x8(%a6)
1051 fmovm.x DATA(%a6),&0x80
1052
1053 mov.w &0x0000,%cc
1054inex_0_pc:
1055 fadd.b &0x2,%fp0
1056
1057 mov.w %cc,SCCR(%a6)
1058 movm.l &0x7fff,SREGS(%a6)
1059 fmovm.x &0xff,SFPREGS(%a6)
1060 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
1061
1062 mov.l &0x50000000,IFPREGS+0x0(%a6)
1063 mov.l &0x80000000,IFPREGS+0x4(%a6)
1064 mov.l &0x00000000,IFPREGS+0x8(%a6)
1065 mov.l &0x00000208,IFPCREGS+0x4(%a6)
1066 lea inex_0_pc(%pc),%a0
1067 mov.l %a0,IFPCREGS+0x8(%a6)
1068
1069 bsr.l chkregs
1070 tst.b %d0
1071 bne.l error
1072
1073 bsr.l chkfpregs
1074 tst.b %d0
1075 bne.l error
1076
1077 clr.l %d0
1078 rts
1079
1080#####################################################################
1081
1082snan_str:
1083 string "\tEnabled SNAN..."
1084
1085 align 0x4
1086snan_0:
1087 addq.l &0x1,TESTCTR(%a6)
1088
1089 movm.l DEF_REGS(%pc),&0x3fff
1090 fmovm.x DEF_FPREGS(%pc),&0xff
1091 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
1092
1093 mov.w &0x0000,ICCR(%a6)
1094 movm.l &0x7fff,IREGS(%a6)
1095 fmovm.x &0xff,IFPREGS(%a6)
1096 fmov.l &0x00004000,%fpcr # enable SNAN
1097 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
1098
1099 mov.l &0xffff0000,DATA+0x0(%a6)
1100 mov.l &0x00000000,DATA+0x4(%a6)
1101 mov.l &0x00000001,DATA+0x8(%a6)
1102 fmovm.x DATA(%a6),&0x80
1103
1104 mov.w &0x0000,%cc
1105snan_0_pc:
1106 fadd.b &0x2,%fp0
1107
1108 mov.w %cc,SCCR(%a6)
1109 movm.l &0x7fff,SREGS(%a6)
1110 fmovm.x &0xff,SFPREGS(%a6)
1111 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
1112
1113 mov.l &0xffff0000,IFPREGS+0x0(%a6)
1114 mov.l &0x00000000,IFPREGS+0x4(%a6)
1115 mov.l &0x00000001,IFPREGS+0x8(%a6)
1116 mov.l &0x09004080,IFPCREGS+0x4(%a6)
1117 lea snan_0_pc(%pc),%a0
1118 mov.l %a0,IFPCREGS+0x8(%a6)
1119
1120 bsr.l chkregs
1121 tst.b %d0
1122 bne.l error
1123
1124 bsr.l chkfpregs
1125 tst.b %d0
1126 bne.l error
1127
1128 clr.l %d0
1129 rts
1130
1131#####################################################################
1132
1133operr_str:
1134 string "\tEnabled OPERR..."
1135
1136 align 0x4
1137operr_0:
1138 addq.l &0x1,TESTCTR(%a6)
1139
1140 movm.l DEF_REGS(%pc),&0x3fff
1141 fmovm.x DEF_FPREGS(%pc),&0xff
1142 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
1143
1144 mov.w &0x0000,ICCR(%a6)
1145 movm.l &0x7fff,IREGS(%a6)
1146 fmovm.x &0xff,IFPREGS(%a6)
1147 fmov.l &0x00002000,%fpcr # enable OPERR
1148 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
1149
1150 mov.l &0xffff0000,DATA+0x0(%a6)
1151 mov.l &0x00000000,DATA+0x4(%a6)
1152 mov.l &0x00000000,DATA+0x8(%a6)
1153 fmovm.x DATA(%a6),&0x80
1154
1155 mov.w &0x0000,%cc
1156operr_0_pc:
1157 fadd.s &0x7f800000,%fp0
1158
1159 mov.w %cc,SCCR(%a6)
1160 movm.l &0x7fff,SREGS(%a6)
1161 fmovm.x &0xff,SFPREGS(%a6)
1162 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
1163
1164 mov.l &0xffff0000,IFPREGS+0x0(%a6)
1165 mov.l &0x00000000,IFPREGS+0x4(%a6)
1166 mov.l &0x00000000,IFPREGS+0x8(%a6)
1167 mov.l &0x01002080,IFPCREGS+0x4(%a6)
1168 lea operr_0_pc(%pc),%a0
1169 mov.l %a0,IFPCREGS+0x8(%a6)
1170
1171 bsr.l chkregs
1172 tst.b %d0
1173 bne.l error
1174
1175 bsr.l chkfpregs
1176 tst.b %d0
1177 bne.l error
1178
1179 clr.l %d0
1180 rts
1181
1182#####################################################################
1183
1184dz_str:
1185 string "\tEnabled DZ..."
1186
1187 align 0x4
1188dz_0:
1189 addq.l &0x1,TESTCTR(%a6)
1190
1191 movm.l DEF_REGS(%pc),&0x3fff
1192 fmovm.x DEF_FPREGS(%pc),&0xff
1193 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
1194
1195 mov.w &0x0000,ICCR(%a6)
1196 movm.l &0x7fff,IREGS(%a6)
1197 fmovm.x &0xff,IFPREGS(%a6)
1198 fmov.l &0x00000400,%fpcr # enable DZ
1199 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
1200
1201 mov.l &0x40000000,DATA+0x0(%a6)
1202 mov.l &0x80000000,DATA+0x4(%a6)
1203 mov.l &0x00000000,DATA+0x8(%a6)
1204 fmovm.x DATA(%a6),&0x80
1205
1206 mov.w &0x0000,%cc
1207dz_0_pc:
1208 fdiv.b &0x0,%fp0
1209
1210 mov.w %cc,SCCR(%a6)
1211 movm.l &0x7fff,SREGS(%a6)
1212 fmovm.x &0xff,SFPREGS(%a6)
1213 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
1214
1215 mov.l &0x40000000,IFPREGS+0x0(%a6)
1216 mov.l &0x80000000,IFPREGS+0x4(%a6)
1217 mov.l &0x00000000,IFPREGS+0x8(%a6)
1218 mov.l &0x02000410,IFPCREGS+0x4(%a6)
1219 lea dz_0_pc(%pc),%a0
1220 mov.l %a0,IFPCREGS+0x8(%a6)
1221
1222 bsr.l chkregs
1223 tst.b %d0
1224 bne.l error
1225
1226 bsr.l chkfpregs
1227 tst.b %d0
1228 bne.l error
1229
1230 clr.l %d0
1231 rts
1232
1233#####################################################################
1234
1235unsupp_str:
1236 string "\tUnimplemented data type/format..."
1237
1238# an unnormalized number
1239 align 0x4
1240unsupp_0:
1241 addq.l &0x1,TESTCTR(%a6)
1242
1243 movm.l DEF_REGS(%pc),&0x3fff
1244 fmovm.x DEF_FPREGS(%pc),&0xff
1245 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
1246
1247 mov.w &0x0000,ICCR(%a6)
1248 movm.l &0x7fff,IREGS(%a6)
1249 fmovm.x &0xff,IFPREGS(%a6)
1250 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
1251
1252 mov.l &0xc03f0000,DATA+0x0(%a6)
1253 mov.l &0x00000000,DATA+0x4(%a6)
1254 mov.l &0x00000001,DATA+0x8(%a6)
1255 fmov.b &0x2,%fp0
1256 mov.w &0x0000,%cc
1257unsupp_0_pc:
1258 fmul.x DATA(%a6),%fp0
1259
1260 mov.w %cc,SCCR(%a6)
1261 movm.l &0x7fff,SREGS(%a6)
1262 fmovm.x &0xff,SFPREGS(%a6)
1263 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
1264
1265 mov.l &0xc0010000,IFPREGS+0x0(%a6)
1266 mov.l &0x80000000,IFPREGS+0x4(%a6)
1267 mov.l &0x00000000,IFPREGS+0x8(%a6)
1268 mov.l &0x08000000,IFPCREGS+0x4(%a6)
1269 lea unsupp_0_pc(%pc),%a0
1270 mov.l %a0,IFPCREGS+0x8(%a6)
1271
1272 bsr.l chkregs
1273 tst.b %d0
1274 bne.l error
1275
1276 bsr.l chkfpregs
1277 tst.b %d0
1278 bne.l error
1279
1280# a denormalized number
1281unsupp_1:
1282 addq.l &0x1,TESTCTR(%a6)
1283
1284 movm.l DEF_REGS(%pc),&0x3fff
1285 fmovm.x DEF_FPREGS(%pc),&0xff
1286 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
1287
1288 mov.w &0x0000,ICCR(%a6)
1289 movm.l &0x7fff,IREGS(%a6)
1290 fmovm.x &0xff,IFPREGS(%a6)
1291 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
1292
1293 mov.l &0x80000000,DATA+0x0(%a6)
1294 mov.l &0x01000000,DATA+0x4(%a6)
1295 mov.l &0x00000000,DATA+0x8(%a6)
1296 fmov.l &0x7fffffff,%fp0
1297
1298 mov.w &0x0000,%cc
1299unsupp_1_pc:
1300 fmul.x DATA(%a6),%fp0
1301
1302 mov.w %cc,SCCR(%a6)
1303 movm.l &0x7fff,SREGS(%a6)
1304 fmovm.x &0xff,SFPREGS(%a6)
1305 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
1306
1307 mov.l &0x80170000,IFPREGS+0x0(%a6)
1308 mov.l &0xfffffffe,IFPREGS+0x4(%a6)
1309 mov.l &0x00000000,IFPREGS+0x8(%a6)
1310 mov.l &0x08000000,IFPCREGS+0x4(%a6)
1311 lea unsupp_1_pc(%pc),%a0
1312 mov.l %a0,IFPCREGS+0x8(%a6)
1313
1314 bsr.l chkregs
1315 tst.b %d0
1316 bne.l error
1317
1318 bsr.l chkfpregs
1319 tst.b %d0
1320 bne.l error
1321
1322# packed
1323unsupp_2:
1324 addq.l &0x1,TESTCTR(%a6)
1325
1326 movm.l DEF_REGS(%pc),&0x3fff
1327 fmovm.x DEF_FPREGS(%pc),&0xff
1328 fmovm.l DEF_FPCREGS(%pc),%fpcr,%fpsr,%fpiar
1329
1330 mov.w &0x0000,ICCR(%a6)
1331 movm.l &0x7fff,IREGS(%a6)
1332 fmovm.x &0xff,IFPREGS(%a6)
1333 fmovm.l %fpcr,%fpsr,%fpiar,IFPCREGS(%a6)
1334
1335 mov.l &0xc1230001,DATA+0x0(%a6)
1336 mov.l &0x23456789,DATA+0x4(%a6)
1337 mov.l &0x12345678,DATA+0x8(%a6)
1338
1339 mov.w &0x0000,%cc
1340unsupp_2_pc:
1341 fabs.p DATA(%a6),%fp0
1342
1343 mov.w %cc,SCCR(%a6)
1344 movm.l &0x7fff,SREGS(%a6)
1345 fmovm.x &0xff,SFPREGS(%a6)
1346 fmovm.l %fpcr,%fpsr,%fpiar,SFPCREGS(%a6)
1347
1348 mov.l &0x3e660000,IFPREGS+0x0(%a6)
1349 mov.l &0xd0ed23e8,IFPREGS+0x4(%a6)
1350 mov.l &0xd14035bc,IFPREGS+0x8(%a6)
1351 mov.l &0x00000108,IFPCREGS+0x4(%a6)
1352 lea unsupp_2_pc(%pc),%a0
1353 mov.l %a0,IFPCREGS+0x8(%a6)
1354
1355 bsr.l chkregs
1356 tst.b %d0
1357 bne.l error
1358
1359 bsr.l chkfpregs
1360 tst.b %d0
1361 bne.l error
1362
1363 clr.l %d0
1364 rts
1365
1366###########################################################
1367###########################################################
1368
1369chkregs:
1370 lea IREGS(%a6),%a0
1371 lea SREGS(%a6),%a1
1372 mov.l &14,%d0
1373chkregs_loop:
1374 cmp.l (%a0)+,(%a1)+
1375 bne.l chkregs_error
1376 dbra.w %d0,chkregs_loop
1377
1378 mov.w ICCR(%a6),%d0
1379 mov.w SCCR(%a6),%d1
1380 cmp.w %d0,%d1
1381 bne.l chkregs_error
1382
1383 clr.l %d0
1384 rts
1385
1386chkregs_error:
1387 movq.l &0x1,%d0
1388 rts
1389
1390error:
1391 mov.l TESTCTR(%a6),%d1
1392 movq.l &0x1,%d0
1393 rts
1394
1395chkfpregs:
1396 lea IFPREGS(%a6),%a0
1397 lea SFPREGS(%a6),%a1
1398 mov.l &23,%d0
1399chkfpregs_loop:
1400 cmp.l (%a0)+,(%a1)+
1401 bne.l chkfpregs_error
1402 dbra.w %d0,chkfpregs_loop
1403
1404 lea IFPCREGS(%a6),%a0
1405 lea SFPCREGS(%a6),%a1
1406 cmp.l (%a0)+,(%a1)+
1407 bne.l chkfpregs_error
1408 cmp.l (%a0)+,(%a1)+
1409 bne.l chkfpregs_error
1410 cmp.l (%a0)+,(%a1)+
1411 bne.l chkfpregs_error
1412
1413 clr.l %d0
1414 rts
1415
1416chkfpregs_error:
1417 movq.l &0x1,%d0
1418 rts
1419
1420DEF_REGS:
1421 long 0xacacacac, 0xacacacac, 0xacacacac, 0xacacacac
1422 long 0xacacacac, 0xacacacac, 0xacacacac, 0xacacacac
1423
1424 long 0xacacacac, 0xacacacac, 0xacacacac, 0xacacacac
1425 long 0xacacacac, 0xacacacac, 0xacacacac, 0xacacacac
1426
1427DEF_FPREGS:
1428 long 0x7fff0000, 0xffffffff, 0xffffffff
1429 long 0x7fff0000, 0xffffffff, 0xffffffff
1430 long 0x7fff0000, 0xffffffff, 0xffffffff
1431 long 0x7fff0000, 0xffffffff, 0xffffffff
1432 long 0x7fff0000, 0xffffffff, 0xffffffff
1433 long 0x7fff0000, 0xffffffff, 0xffffffff
1434 long 0x7fff0000, 0xffffffff, 0xffffffff
1435 long 0x7fff0000, 0xffffffff, 0xffffffff
1436
1437DEF_FPCREGS:
1438 long 0x00000000, 0x00000000, 0x00000000
1439
1440############################################################
1441
1442_print_str:
1443 mov.l %d0,-(%sp)
1444 mov.l (TESTTOP-0x80+0x0,%pc),%d0
1445 pea (TESTTOP-0x80,%pc,%d0)
1446 mov.l 0x4(%sp),%d0
1447 rtd &0x4
1448
1449_print_num:
1450 mov.l %d0,-(%sp)
1451 mov.l (TESTTOP-0x80+0x4,%pc),%d0
1452 pea (TESTTOP-0x80,%pc,%d0)
1453 mov.l 0x4(%sp),%d0
1454 rtd &0x4
1455
1456############################################################
diff --git a/arch/m68k/ifpsp060/src/ilsp.S b/arch/m68k/ifpsp060/src/ilsp.S
new file mode 100644
index 000000000000..afa7422cddb5
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/ilsp.S
@@ -0,0 +1,932 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29# litop.s:
30# This file is appended to the top of the 060FPLSP package
31# and contains the entry points into the package. The user, in
32# effect, branches to one of the branch table entries located here.
33#
34
35 bra.l _060LSP__idivs64_
36 short 0x0000
37 bra.l _060LSP__idivu64_
38 short 0x0000
39
40 bra.l _060LSP__imuls64_
41 short 0x0000
42 bra.l _060LSP__imulu64_
43 short 0x0000
44
45 bra.l _060LSP__cmp2_Ab_
46 short 0x0000
47 bra.l _060LSP__cmp2_Aw_
48 short 0x0000
49 bra.l _060LSP__cmp2_Al_
50 short 0x0000
51 bra.l _060LSP__cmp2_Db_
52 short 0x0000
53 bra.l _060LSP__cmp2_Dw_
54 short 0x0000
55 bra.l _060LSP__cmp2_Dl_
56 short 0x0000
57
58# leave room for future possible aditions.
59 align 0x200
60
61#########################################################################
62# XDEF **************************************************************** #
63# _060LSP__idivu64_(): Emulate 64-bit unsigned div instruction. #
64# _060LSP__idivs64_(): Emulate 64-bit signed div instruction. #
65# #
66# This is the library version which is accessed as a subroutine #
67# and therefore does not work exactly like the 680X0 div{s,u}.l #
68# 64-bit divide instruction. #
69# #
70# XREF **************************************************************** #
71# None. #
72# #
73# INPUT *************************************************************** #
74# 0x4(sp) = divisor #
75# 0x8(sp) = hi(dividend) #
76# 0xc(sp) = lo(dividend) #
77# 0x10(sp) = pointer to location to place quotient/remainder #
78# #
79# OUTPUT ************************************************************** #
80# 0x10(sp) = points to location of remainder/quotient. #
81# remainder is in first longword, quotient is in 2nd. #
82# #
83# ALGORITHM *********************************************************** #
84# If the operands are signed, make them unsigned and save the #
85# sign info for later. Separate out special cases like divide-by-zero #
86# or 32-bit divides if possible. Else, use a special math algorithm #
87# to calculate the result. #
88# Restore sign info if signed instruction. Set the condition #
89# codes before performing the final "rts". If the divisor was equal to #
90# zero, then perform a divide-by-zero using a 16-bit implemented #
91# divide instruction. This way, the operating system can record that #
92# the event occurred even though it may not point to the correct place. #
93# #
94#########################################################################
95
96set POSNEG, -1
97set NDIVISOR, -2
98set NDIVIDEND, -3
99set DDSECOND, -4
100set DDNORMAL, -8
101set DDQUOTIENT, -12
102set DIV64_CC, -16
103
104##########
105# divs.l #
106##########
107 global _060LSP__idivs64_
108_060LSP__idivs64_:
109# PROLOGUE BEGIN ########################################################
110 link.w %a6,&-16
111 movm.l &0x3f00,-(%sp) # save d2-d7
112# fmovm.l &0x0,-(%sp) # save no fpregs
113# PROLOGUE END ##########################################################
114
115 mov.w %cc,DIV64_CC(%a6)
116 st POSNEG(%a6) # signed operation
117 bra.b ldiv64_cont
118
119##########
120# divu.l #
121##########
122 global _060LSP__idivu64_
123_060LSP__idivu64_:
124# PROLOGUE BEGIN ########################################################
125 link.w %a6,&-16
126 movm.l &0x3f00,-(%sp) # save d2-d7
127# fmovm.l &0x0,-(%sp) # save no fpregs
128# PROLOGUE END ##########################################################
129
130 mov.w %cc,DIV64_CC(%a6)
131 sf POSNEG(%a6) # unsigned operation
132
133ldiv64_cont:
134 mov.l 0x8(%a6),%d7 # fetch divisor
135
136 beq.w ldiv64eq0 # divisor is = 0!!!
137
138 mov.l 0xc(%a6), %d5 # get dividend hi
139 mov.l 0x10(%a6), %d6 # get dividend lo
140
141# separate signed and unsigned divide
142 tst.b POSNEG(%a6) # signed or unsigned?
143 beq.b ldspecialcases # use positive divide
144
145# save the sign of the divisor
146# make divisor unsigned if it's negative
147 tst.l %d7 # chk sign of divisor
148 slt NDIVISOR(%a6) # save sign of divisor
149 bpl.b ldsgndividend
150 neg.l %d7 # complement negative divisor
151
152# save the sign of the dividend
153# make dividend unsigned if it's negative
154ldsgndividend:
155 tst.l %d5 # chk sign of hi(dividend)
156 slt NDIVIDEND(%a6) # save sign of dividend
157 bpl.b ldspecialcases
158
159 mov.w &0x0, %cc # clear 'X' cc bit
160 negx.l %d6 # complement signed dividend
161 negx.l %d5
162
163# extract some special cases:
164# - is (dividend == 0) ?
165# - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
166ldspecialcases:
167 tst.l %d5 # is (hi(dividend) == 0)
168 bne.b ldnormaldivide # no, so try it the long way
169
170 tst.l %d6 # is (lo(dividend) == 0), too
171 beq.w lddone # yes, so (dividend == 0)
172
173 cmp.l %d7,%d6 # is (divisor <= lo(dividend))
174 bls.b ld32bitdivide # yes, so use 32 bit divide
175
176 exg %d5,%d6 # q = 0, r = dividend
177 bra.w ldivfinish # can't divide, we're done.
178
179ld32bitdivide:
180 tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div!
181
182 bra.b ldivfinish
183
184ldnormaldivide:
185# last special case:
186# - is hi(dividend) >= divisor ? if yes, then overflow
187 cmp.l %d7,%d5
188 bls.b lddovf # answer won't fit in 32 bits
189
190# perform the divide algorithm:
191 bsr.l ldclassical # do int divide
192
193# separate into signed and unsigned finishes.
194ldivfinish:
195 tst.b POSNEG(%a6) # do divs, divu separately
196 beq.b lddone # divu has no processing!!!
197
198# it was a divs.l, so ccode setting is a little more complicated...
199 tst.b NDIVIDEND(%a6) # remainder has same sign
200 beq.b ldcc # as dividend.
201 neg.l %d5 # sgn(rem) = sgn(dividend)
202ldcc:
203 mov.b NDIVISOR(%a6), %d0
204 eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative
205 beq.b ldqpos # branch to quot positive
206
207# 0x80000000 is the largest number representable as a 32-bit negative
208# number. the negative of 0x80000000 is 0x80000000.
209 cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits?
210 bhi.b lddovf
211
212 neg.l %d6 # make (-quot) 2's comp
213
214 bra.b lddone
215
216ldqpos:
217 btst &0x1f, %d6 # will (+quot) fit in 32 bits?
218 bne.b lddovf
219
220lddone:
221# if the register numbers are the same, only the quotient gets saved.
222# so, if we always save the quotient second, we save ourselves a cmp&beq
223 andi.w &0x10,DIV64_CC(%a6)
224 mov.w DIV64_CC(%a6),%cc
225 tst.l %d6 # may set 'N' ccode bit
226
227# here, the result is in d1 and d0. the current strategy is to save
228# the values at the location pointed to by a0.
229# use movm here to not disturb the condition codes.
230ldexit:
231 movm.l &0x0060,([0x14,%a6]) # save result
232
233# EPILOGUE BEGIN ########################################################
234# fmovm.l (%sp)+,&0x0 # restore no fpregs
235 movm.l (%sp)+,&0x00fc # restore d2-d7
236 unlk %a6
237# EPILOGUE END ##########################################################
238
239 rts
240
241# the result should be the unchanged dividend
242lddovf:
243 mov.l 0xc(%a6), %d5 # get dividend hi
244 mov.l 0x10(%a6), %d6 # get dividend lo
245
246 andi.w &0x1c,DIV64_CC(%a6)
247 ori.w &0x02,DIV64_CC(%a6) # set 'V' ccode bit
248 mov.w DIV64_CC(%a6),%cc
249
250 bra.b ldexit
251
252ldiv64eq0:
253 mov.l 0xc(%a6),([0x14,%a6])
254 mov.l 0x10(%a6),([0x14,%a6],0x4)
255
256 mov.w DIV64_CC(%a6),%cc
257
258# EPILOGUE BEGIN ########################################################
259# fmovm.l (%sp)+,&0x0 # restore no fpregs
260 movm.l (%sp)+,&0x00fc # restore d2-d7
261 unlk %a6
262# EPILOGUE END ##########################################################
263
264 divu.w &0x0,%d0 # force a divbyzero exception
265 rts
266
267###########################################################################
268#########################################################################
269# This routine uses the 'classical' Algorithm D from Donald Knuth's #
270# Art of Computer Programming, vol II, Seminumerical Algorithms. #
271# For this implementation b=2**16, and the target is U1U2U3U4/V1V2, #
272# where U,V are words of the quadword dividend and longword divisor, #
273# and U1, V1 are the most significant words. #
274# #
275# The most sig. longword of the 64 bit dividend must be in %d5, least #
276# in %d6. The divisor must be in the variable ddivisor, and the #
277# signed/unsigned flag ddusign must be set (0=unsigned,1=signed). #
278# The quotient is returned in %d6, remainder in %d5, unless the #
279# v (overflow) bit is set in the saved %ccr. If overflow, the dividend #
280# is unchanged. #
281#########################################################################
282ldclassical:
283# if the divisor msw is 0, use simpler algorithm then the full blown
284# one at ddknuth:
285
286 cmpi.l %d7, &0xffff
287 bhi.b lddknuth # go use D. Knuth algorithm
288
289# Since the divisor is only a word (and larger than the mslw of the dividend),
290# a simpler algorithm may be used :
291# In the general case, four quotient words would be created by
292# dividing the divisor word into each dividend word. In this case,
293# the first two quotient words must be zero, or overflow would occur.
294# Since we already checked this case above, we can treat the most significant
295# longword of the dividend as (0) remainder (see Knuth) and merely complete
296# the last two divisions to get a quotient longword and word remainder:
297
298 clr.l %d1
299 swap %d5 # same as r*b if previous step rqd
300 swap %d6 # get u3 to lsw position
301 mov.w %d6, %d5 # rb + u3
302
303 divu.w %d7, %d5
304
305 mov.w %d5, %d1 # first quotient word
306 swap %d6 # get u4
307 mov.w %d6, %d5 # rb + u4
308
309 divu.w %d7, %d5
310
311 swap %d1
312 mov.w %d5, %d1 # 2nd quotient 'digit'
313 clr.w %d5
314 swap %d5 # now remainder
315 mov.l %d1, %d6 # and quotient
316
317 rts
318
319lddknuth:
320# In this algorithm, the divisor is treated as a 2 digit (word) number
321# which is divided into a 3 digit (word) dividend to get one quotient
322# digit (word). After subtraction, the dividend is shifted and the
323# process repeated. Before beginning, the divisor and quotient are
324# 'normalized' so that the process of estimating the quotient digit
325# will yield verifiably correct results..
326
327 clr.l DDNORMAL(%a6) # count of shifts for normalization
328 clr.b DDSECOND(%a6) # clear flag for quotient digits
329 clr.l %d1 # %d1 will hold trial quotient
330lddnchk:
331 btst &31, %d7 # must we normalize? first word of
332 bne.b lddnormalized # divisor (V1) must be >= 65536/2
333 addq.l &0x1, DDNORMAL(%a6) # count normalization shifts
334 lsl.l &0x1, %d7 # shift the divisor
335 lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2
336 roxl.l &0x1, %d5 # shift u1,u2
337 bra.w lddnchk
338lddnormalized:
339
340# Now calculate an estimate of the quotient words (msw first, then lsw).
341# The comments use subscripts for the first quotient digit determination.
342 mov.l %d7, %d3 # divisor
343 mov.l %d5, %d2 # dividend mslw
344 swap %d2
345 swap %d3
346 cmp.w %d2, %d3 # V1 = U1 ?
347 bne.b lddqcalc1
348 mov.w &0xffff, %d1 # use max trial quotient word
349 bra.b lddadj0
350lddqcalc1:
351 mov.l %d5, %d1
352
353 divu.w %d3, %d1 # use quotient of mslw/msw
354
355 andi.l &0x0000ffff, %d1 # zero any remainder
356lddadj0:
357
358# now test the trial quotient and adjust. This step plus the
359# normalization assures (according to Knuth) that the trial
360# quotient will be at worst 1 too large.
361 mov.l %d6, -(%sp)
362 clr.w %d6 # word u3 left
363 swap %d6 # in lsw position
364lddadj1: mov.l %d7, %d3
365 mov.l %d1, %d2
366 mulu.w %d7, %d2 # V2q
367 swap %d3
368 mulu.w %d1, %d3 # V1q
369 mov.l %d5, %d4 # U1U2
370 sub.l %d3, %d4 # U1U2 - V1q
371
372 swap %d4
373
374 mov.w %d4,%d0
375 mov.w %d6,%d4 # insert lower word (U3)
376
377 tst.w %d0 # is upper word set?
378 bne.w lddadjd1
379
380# add.l %d6, %d4 # (U1U2 - V1q) + U3
381
382 cmp.l %d2, %d4
383 bls.b lddadjd1 # is V2q > (U1U2-V1q) + U3 ?
384 subq.l &0x1, %d1 # yes, decrement and recheck
385 bra.b lddadj1
386lddadjd1:
387# now test the word by multiplying it by the divisor (V1V2) and comparing
388# the 3 digit (word) result with the current dividend words
389 mov.l %d5, -(%sp) # save %d5 (%d6 already saved)
390 mov.l %d1, %d6
391 swap %d6 # shift answer to ms 3 words
392 mov.l %d7, %d5
393 bsr.l ldmm2
394 mov.l %d5, %d2 # now %d2,%d3 are trial*divisor
395 mov.l %d6, %d3
396 mov.l (%sp)+, %d5 # restore dividend
397 mov.l (%sp)+, %d6
398 sub.l %d3, %d6
399 subx.l %d2, %d5 # subtract double precision
400 bcc ldd2nd # no carry, do next quotient digit
401 subq.l &0x1, %d1 # q is one too large
402# need to add back divisor longword to current ms 3 digits of dividend
403# - according to Knuth, this is done only 2 out of 65536 times for random
404# divisor, dividend selection.
405 clr.l %d2
406 mov.l %d7, %d3
407 swap %d3
408 clr.w %d3 # %d3 now ls word of divisor
409 add.l %d3, %d6 # aligned with 3rd word of dividend
410 addx.l %d2, %d5
411 mov.l %d7, %d3
412 clr.w %d3 # %d3 now ms word of divisor
413 swap %d3 # aligned with 2nd word of dividend
414 add.l %d3, %d5
415ldd2nd:
416 tst.b DDSECOND(%a6) # both q words done?
417 bne.b lddremain
418# first quotient digit now correct. store digit and shift the
419# (subtracted) dividend
420 mov.w %d1, DDQUOTIENT(%a6)
421 clr.l %d1
422 swap %d5
423 swap %d6
424 mov.w %d6, %d5
425 clr.w %d6
426 st DDSECOND(%a6) # second digit
427 bra.w lddnormalized
428lddremain:
429# add 2nd word to quotient, get the remainder.
430 mov.w %d1, DDQUOTIENT+2(%a6)
431# shift down one word/digit to renormalize remainder.
432 mov.w %d5, %d6
433 swap %d6
434 swap %d5
435 mov.l DDNORMAL(%a6), %d7 # get norm shift count
436 beq.b lddrn
437 subq.l &0x1, %d7 # set for loop count
438lddnlp:
439 lsr.l &0x1, %d5 # shift into %d6
440 roxr.l &0x1, %d6
441 dbf %d7, lddnlp
442lddrn:
443 mov.l %d6, %d5 # remainder
444 mov.l DDQUOTIENT(%a6), %d6 # quotient
445
446 rts
447ldmm2:
448# factors for the 32X32->64 multiplication are in %d5 and %d6.
449# returns 64 bit result in %d5 (hi) %d6(lo).
450# destroys %d2,%d3,%d4.
451
452# multiply hi,lo words of each factor to get 4 intermediate products
453 mov.l %d6, %d2
454 mov.l %d6, %d3
455 mov.l %d5, %d4
456 swap %d3
457 swap %d4
458 mulu.w %d5, %d6 # %d6 <- lsw*lsw
459 mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source
460 mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest
461 mulu.w %d4, %d3 # %d3 <- msw*msw
462# now use swap and addx to consolidate to two longwords
463 clr.l %d4
464 swap %d6
465 add.w %d5, %d6 # add msw of l*l to lsw of m*l product
466 addx.w %d4, %d3 # add any carry to m*m product
467 add.w %d2, %d6 # add in lsw of other m*l product
468 addx.w %d4, %d3 # add any carry to m*m product
469 swap %d6 # %d6 is low 32 bits of final product
470 clr.w %d5
471 clr.w %d2 # lsw of two mixed products used,
472 swap %d5 # now use msws of longwords
473 swap %d2
474 add.l %d2, %d5
475 add.l %d3, %d5 # %d5 now ms 32 bits of final product
476 rts
477
478#########################################################################
479# XDEF **************************************************************** #
480# _060LSP__imulu64_(): Emulate 64-bit unsigned mul instruction #
481# _060LSP__imuls64_(): Emulate 64-bit signed mul instruction. #
482# #
483# This is the library version which is accessed as a subroutine #
484# and therefore does not work exactly like the 680X0 mul{s,u}.l #
485# 64-bit multiply instruction. #
486# #
487# XREF **************************************************************** #
488# None #
489# #
490# INPUT *************************************************************** #
491# 0x4(sp) = multiplier #
492# 0x8(sp) = multiplicand #
493# 0xc(sp) = pointer to location to place 64-bit result #
494# #
495# OUTPUT ************************************************************** #
496# 0xc(sp) = points to location of 64-bit result #
497# #
498# ALGORITHM *********************************************************** #
499# Perform the multiply in pieces using 16x16->32 unsigned #
500# multiplies and "add" instructions. #
501# Set the condition codes as appropriate before performing an #
502# "rts". #
503# #
504#########################################################################
505
506set MUL64_CC, -4
507
508 global _060LSP__imulu64_
509_060LSP__imulu64_:
510
511# PROLOGUE BEGIN ########################################################
512 link.w %a6,&-4
513 movm.l &0x3800,-(%sp) # save d2-d4
514# fmovm.l &0x0,-(%sp) # save no fpregs
515# PROLOGUE END ##########################################################
516
517 mov.w %cc,MUL64_CC(%a6) # save incoming ccodes
518
519 mov.l 0x8(%a6),%d0 # store multiplier in d0
520 beq.w mulu64_zero # handle zero separately
521
522 mov.l 0xc(%a6),%d1 # get multiplicand in d1
523 beq.w mulu64_zero # handle zero separately
524
525#########################################################################
526# 63 32 0 #
527# ---------------------------- #
528# | hi(mplier) * hi(mplicand)| #
529# ---------------------------- #
530# ----------------------------- #
531# | hi(mplier) * lo(mplicand) | #
532# ----------------------------- #
533# ----------------------------- #
534# | lo(mplier) * hi(mplicand) | #
535# ----------------------------- #
536# | ----------------------------- #
537# --|-- | lo(mplier) * lo(mplicand) | #
538# | ----------------------------- #
539# ======================================================== #
540# -------------------------------------------------------- #
541# | hi(result) | lo(result) | #
542# -------------------------------------------------------- #
543#########################################################################
544mulu64_alg:
545# load temp registers with operands
546 mov.l %d0,%d2 # mr in d2
547 mov.l %d0,%d3 # mr in d3
548 mov.l %d1,%d4 # md in d4
549 swap %d3 # hi(mr) in lo d3
550 swap %d4 # hi(md) in lo d4
551
552# complete necessary multiplies:
553 mulu.w %d1,%d0 # [1] lo(mr) * lo(md)
554 mulu.w %d3,%d1 # [2] hi(mr) * lo(md)
555 mulu.w %d4,%d2 # [3] lo(mr) * hi(md)
556 mulu.w %d4,%d3 # [4] hi(mr) * hi(md)
557
558# add lo portions of [2],[3] to hi portion of [1].
559# add carries produced from these adds to [4].
560# lo([1]) is the final lo 16 bits of the result.
561 clr.l %d4 # load d4 w/ zero value
562 swap %d0 # hi([1]) <==> lo([1])
563 add.w %d1,%d0 # hi([1]) + lo([2])
564 addx.l %d4,%d3 # [4] + carry
565 add.w %d2,%d0 # hi([1]) + lo([3])
566 addx.l %d4,%d3 # [4] + carry
567 swap %d0 # lo([1]) <==> hi([1])
568
569# lo portions of [2],[3] have been added in to final result.
570# now, clear lo, put hi in lo reg, and add to [4]
571 clr.w %d1 # clear lo([2])
572 clr.w %d2 # clear hi([3])
573 swap %d1 # hi([2]) in lo d1
574 swap %d2 # hi([3]) in lo d2
575 add.l %d2,%d1 # [4] + hi([2])
576 add.l %d3,%d1 # [4] + hi([3])
577
578# now, grab the condition codes. only one that can be set is 'N'.
579# 'N' CAN be set if the operation is unsigned if bit 63 is set.
580 mov.w MUL64_CC(%a6),%d4
581 andi.b &0x10,%d4 # keep old 'X' bit
582 tst.l %d1 # may set 'N' bit
583 bpl.b mulu64_ddone
584 ori.b &0x8,%d4 # set 'N' bit
585mulu64_ddone:
586 mov.w %d4,%cc
587
588# here, the result is in d1 and d0. the current strategy is to save
589# the values at the location pointed to by a0.
590# use movm here to not disturb the condition codes.
591mulu64_end:
592 exg %d1,%d0
593 movm.l &0x0003,([0x10,%a6]) # save result
594
595# EPILOGUE BEGIN ########################################################
596# fmovm.l (%sp)+,&0x0 # restore no fpregs
597 movm.l (%sp)+,&0x001c # restore d2-d4
598 unlk %a6
599# EPILOGUE END ##########################################################
600
601 rts
602
603# one or both of the operands is zero so the result is also zero.
604# save the zero result to the register file and set the 'Z' ccode bit.
605mulu64_zero:
606 clr.l %d0
607 clr.l %d1
608
609 mov.w MUL64_CC(%a6),%d4
610 andi.b &0x10,%d4
611 ori.b &0x4,%d4
612 mov.w %d4,%cc # set 'Z' ccode bit
613
614 bra.b mulu64_end
615
616##########
617# muls.l #
618##########
619 global _060LSP__imuls64_
620_060LSP__imuls64_:
621
622# PROLOGUE BEGIN ########################################################
623 link.w %a6,&-4
624 movm.l &0x3c00,-(%sp) # save d2-d5
625# fmovm.l &0x0,-(%sp) # save no fpregs
626# PROLOGUE END ##########################################################
627
628 mov.w %cc,MUL64_CC(%a6) # save incoming ccodes
629
630 mov.l 0x8(%a6),%d0 # store multiplier in d0
631 beq.b mulu64_zero # handle zero separately
632
633 mov.l 0xc(%a6),%d1 # get multiplicand in d1
634 beq.b mulu64_zero # handle zero separately
635
636 clr.b %d5 # clear sign tag
637 tst.l %d0 # is multiplier negative?
638 bge.b muls64_chk_md_sgn # no
639 neg.l %d0 # make multiplier positive
640
641 ori.b &0x1,%d5 # save multiplier sgn
642
643# the result sign is the exclusive or of the operand sign bits.
644muls64_chk_md_sgn:
645 tst.l %d1 # is multiplicand negative?
646 bge.b muls64_alg # no
647 neg.l %d1 # make multiplicand positive
648
649 eori.b &0x1,%d5 # calculate correct sign
650
651#########################################################################
652# 63 32 0 #
653# ---------------------------- #
654# | hi(mplier) * hi(mplicand)| #
655# ---------------------------- #
656# ----------------------------- #
657# | hi(mplier) * lo(mplicand) | #
658# ----------------------------- #
659# ----------------------------- #
660# | lo(mplier) * hi(mplicand) | #
661# ----------------------------- #
662# | ----------------------------- #
663# --|-- | lo(mplier) * lo(mplicand) | #
664# | ----------------------------- #
665# ======================================================== #
666# -------------------------------------------------------- #
667# | hi(result) | lo(result) | #
668# -------------------------------------------------------- #
669#########################################################################
670muls64_alg:
671# load temp registers with operands
672 mov.l %d0,%d2 # mr in d2
673 mov.l %d0,%d3 # mr in d3
674 mov.l %d1,%d4 # md in d4
675 swap %d3 # hi(mr) in lo d3
676 swap %d4 # hi(md) in lo d4
677
678# complete necessary multiplies:
679 mulu.w %d1,%d0 # [1] lo(mr) * lo(md)
680 mulu.w %d3,%d1 # [2] hi(mr) * lo(md)
681 mulu.w %d4,%d2 # [3] lo(mr) * hi(md)
682 mulu.w %d4,%d3 # [4] hi(mr) * hi(md)
683
684# add lo portions of [2],[3] to hi portion of [1].
685# add carries produced from these adds to [4].
686# lo([1]) is the final lo 16 bits of the result.
687 clr.l %d4 # load d4 w/ zero value
688 swap %d0 # hi([1]) <==> lo([1])
689 add.w %d1,%d0 # hi([1]) + lo([2])
690 addx.l %d4,%d3 # [4] + carry
691 add.w %d2,%d0 # hi([1]) + lo([3])
692 addx.l %d4,%d3 # [4] + carry
693 swap %d0 # lo([1]) <==> hi([1])
694
695# lo portions of [2],[3] have been added in to final result.
696# now, clear lo, put hi in lo reg, and add to [4]
697 clr.w %d1 # clear lo([2])
698 clr.w %d2 # clear hi([3])
699 swap %d1 # hi([2]) in lo d1
700 swap %d2 # hi([3]) in lo d2
701 add.l %d2,%d1 # [4] + hi([2])
702 add.l %d3,%d1 # [4] + hi([3])
703
704 tst.b %d5 # should result be signed?
705 beq.b muls64_done # no
706
707# result should be a signed negative number.
708# compute 2's complement of the unsigned number:
709# -negate all bits and add 1
710muls64_neg:
711 not.l %d0 # negate lo(result) bits
712 not.l %d1 # negate hi(result) bits
713 addq.l &1,%d0 # add 1 to lo(result)
714 addx.l %d4,%d1 # add carry to hi(result)
715
716muls64_done:
717 mov.w MUL64_CC(%a6),%d4
718 andi.b &0x10,%d4 # keep old 'X' bit
719 tst.l %d1 # may set 'N' bit
720 bpl.b muls64_ddone
721 ori.b &0x8,%d4 # set 'N' bit
722muls64_ddone:
723 mov.w %d4,%cc
724
725# here, the result is in d1 and d0. the current strategy is to save
726# the values at the location pointed to by a0.
727# use movm here to not disturb the condition codes.
728muls64_end:
729 exg %d1,%d0
730 movm.l &0x0003,([0x10,%a6]) # save result at (a0)
731
732# EPILOGUE BEGIN ########################################################
733# fmovm.l (%sp)+,&0x0 # restore no fpregs
734 movm.l (%sp)+,&0x003c # restore d2-d5
735 unlk %a6
736# EPILOGUE END ##########################################################
737
738 rts
739
740# one or both of the operands is zero so the result is also zero.
741# save the zero result to the register file and set the 'Z' ccode bit.
742muls64_zero:
743 clr.l %d0
744 clr.l %d1
745
746 mov.w MUL64_CC(%a6),%d4
747 andi.b &0x10,%d4
748 ori.b &0x4,%d4
749 mov.w %d4,%cc # set 'Z' ccode bit
750
751 bra.b muls64_end
752
753#########################################################################
754# XDEF **************************************************************** #
755# _060LSP__cmp2_Ab_(): Emulate "cmp2.b An,<ea>". #
756# _060LSP__cmp2_Aw_(): Emulate "cmp2.w An,<ea>". #
757# _060LSP__cmp2_Al_(): Emulate "cmp2.l An,<ea>". #
758# _060LSP__cmp2_Db_(): Emulate "cmp2.b Dn,<ea>". #
759# _060LSP__cmp2_Dw_(): Emulate "cmp2.w Dn,<ea>". #
760# _060LSP__cmp2_Dl_(): Emulate "cmp2.l Dn,<ea>". #
761# #
762# This is the library version which is accessed as a subroutine #
763# and therefore does not work exactly like the 680X0 "cmp2" #
764# instruction. #
765# #
766# XREF **************************************************************** #
767# None #
768# #
769# INPUT *************************************************************** #
770# 0x4(sp) = Rn #
771# 0x8(sp) = pointer to boundary pair #
772# #
773# OUTPUT ************************************************************** #
774# cc = condition codes are set correctly #
775# #
776# ALGORITHM *********************************************************** #
777# In the interest of simplicity, all operands are converted to #
778# longword size whether the operation is byte, word, or long. The #
779# bounds are sign extended accordingly. If Rn is a data regsiter, Rn is #
780# also sign extended. If Rn is an address register, it need not be sign #
781# extended since the full register is always used. #
782# The condition codes are set correctly before the final "rts". #
783# #
784#########################################################################
785
786set CMP2_CC, -4
787
788 global _060LSP__cmp2_Ab_
789_060LSP__cmp2_Ab_:
790
791# PROLOGUE BEGIN ########################################################
792 link.w %a6,&-4
793 movm.l &0x3800,-(%sp) # save d2-d4
794# fmovm.l &0x0,-(%sp) # save no fpregs
795# PROLOGUE END ##########################################################
796
797 mov.w %cc,CMP2_CC(%a6)
798 mov.l 0x8(%a6), %d2 # get regval
799
800 mov.b ([0xc,%a6],0x0),%d0
801 mov.b ([0xc,%a6],0x1),%d1
802
803 extb.l %d0 # sign extend lo bnd
804 extb.l %d1 # sign extend hi bnd
805 bra.w l_cmp2_cmp # go do the compare emulation
806
807 global _060LSP__cmp2_Aw_
808_060LSP__cmp2_Aw_:
809
810# PROLOGUE BEGIN ########################################################
811 link.w %a6,&-4
812 movm.l &0x3800,-(%sp) # save d2-d4
813# fmovm.l &0x0,-(%sp) # save no fpregs
814# PROLOGUE END ##########################################################
815
816 mov.w %cc,CMP2_CC(%a6)
817 mov.l 0x8(%a6), %d2 # get regval
818
819 mov.w ([0xc,%a6],0x0),%d0
820 mov.w ([0xc,%a6],0x2),%d1
821
822 ext.l %d0 # sign extend lo bnd
823 ext.l %d1 # sign extend hi bnd
824 bra.w l_cmp2_cmp # go do the compare emulation
825
826 global _060LSP__cmp2_Al_
827_060LSP__cmp2_Al_:
828
829# PROLOGUE BEGIN ########################################################
830 link.w %a6,&-4
831 movm.l &0x3800,-(%sp) # save d2-d4
832# fmovm.l &0x0,-(%sp) # save no fpregs
833# PROLOGUE END ##########################################################
834
835 mov.w %cc,CMP2_CC(%a6)
836 mov.l 0x8(%a6), %d2 # get regval
837
838 mov.l ([0xc,%a6],0x0),%d0
839 mov.l ([0xc,%a6],0x4),%d1
840 bra.w l_cmp2_cmp # go do the compare emulation
841
842 global _060LSP__cmp2_Db_
843_060LSP__cmp2_Db_:
844
845# PROLOGUE BEGIN ########################################################
846 link.w %a6,&-4
847 movm.l &0x3800,-(%sp) # save d2-d4
848# fmovm.l &0x0,-(%sp) # save no fpregs
849# PROLOGUE END ##########################################################
850
851 mov.w %cc,CMP2_CC(%a6)
852 mov.l 0x8(%a6), %d2 # get regval
853
854 mov.b ([0xc,%a6],0x0),%d0
855 mov.b ([0xc,%a6],0x1),%d1
856
857 extb.l %d0 # sign extend lo bnd
858 extb.l %d1 # sign extend hi bnd
859
860# operation is a data register compare.
861# sign extend byte to long so we can do simple longword compares.
862 extb.l %d2 # sign extend data byte
863 bra.w l_cmp2_cmp # go do the compare emulation
864
865 global _060LSP__cmp2_Dw_
866_060LSP__cmp2_Dw_:
867
868# PROLOGUE BEGIN ########################################################
869 link.w %a6,&-4
870 movm.l &0x3800,-(%sp) # save d2-d4
871# fmovm.l &0x0,-(%sp) # save no fpregs
872# PROLOGUE END ##########################################################
873
874 mov.w %cc,CMP2_CC(%a6)
875 mov.l 0x8(%a6), %d2 # get regval
876
877 mov.w ([0xc,%a6],0x0),%d0
878 mov.w ([0xc,%a6],0x2),%d1
879
880 ext.l %d0 # sign extend lo bnd
881 ext.l %d1 # sign extend hi bnd
882
883# operation is a data register compare.
884# sign extend word to long so we can do simple longword compares.
885 ext.l %d2 # sign extend data word
886 bra.w l_cmp2_cmp # go emulate compare
887
888 global _060LSP__cmp2_Dl_
889_060LSP__cmp2_Dl_:
890
891# PROLOGUE BEGIN ########################################################
892 link.w %a6,&-4
893 movm.l &0x3800,-(%sp) # save d2-d4
894# fmovm.l &0x0,-(%sp) # save no fpregs
895# PROLOGUE END ##########################################################
896
897 mov.w %cc,CMP2_CC(%a6)
898 mov.l 0x8(%a6), %d2 # get regval
899
900 mov.l ([0xc,%a6],0x0),%d0
901 mov.l ([0xc,%a6],0x4),%d1
902
903#
904# To set the ccodes correctly:
905# (1) save 'Z' bit from (Rn - lo)
906# (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
907# (3) keep 'X', 'N', and 'V' from before instruction
908# (4) combine ccodes
909#
910l_cmp2_cmp:
911 sub.l %d0, %d2 # (Rn - lo)
912 mov.w %cc, %d3 # fetch resulting ccodes
913 andi.b &0x4, %d3 # keep 'Z' bit
914 sub.l %d0, %d1 # (hi - lo)
915 cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi))
916
917 mov.w %cc, %d4 # fetch resulting ccodes
918 or.b %d4, %d3 # combine w/ earlier ccodes
919 andi.b &0x5, %d3 # keep 'Z' and 'N'
920
921 mov.w CMP2_CC(%a6), %d4 # fetch old ccodes
922 andi.b &0x1a, %d4 # keep 'X','N','V' bits
923 or.b %d3, %d4 # insert new ccodes
924 mov.w %d4,%cc # save new ccodes
925
926# EPILOGUE BEGIN ########################################################
927# fmovm.l (%sp)+,&0x0 # restore no fpregs
928 movm.l (%sp)+,&0x001c # restore d2-d4
929 unlk %a6
930# EPILOGUE END ##########################################################
931
932 rts
diff --git a/arch/m68k/ifpsp060/src/isp.S b/arch/m68k/ifpsp060/src/isp.S
new file mode 100644
index 000000000000..b269091d9df6
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/isp.S
@@ -0,0 +1,4299 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29# ireal.s:
30# This file is appended to the top of the 060ISP package
31# and contains the entry points into the package. The user, in
32# effect, branches to one of the branch table entries located
33# after _060ISP_TABLE.
34# Also, subroutine stubs exist in this file (_isp_done for
35# example) that are referenced by the ISP package itself in order
36# to call a given routine. The stub routine actually performs the
37# callout. The ISP code does a "bsr" to the stub routine. This
38# extra layer of hierarchy adds a slight performance penalty but
39# it makes the ISP code easier to read and more mainatinable.
40#
41
42set _off_chk, 0x00
43set _off_divbyzero, 0x04
44set _off_trace, 0x08
45set _off_access, 0x0c
46set _off_done, 0x10
47
48set _off_cas, 0x14
49set _off_cas2, 0x18
50set _off_lock, 0x1c
51set _off_unlock, 0x20
52
53set _off_imr, 0x40
54set _off_dmr, 0x44
55set _off_dmw, 0x48
56set _off_irw, 0x4c
57set _off_irl, 0x50
58set _off_drb, 0x54
59set _off_drw, 0x58
60set _off_drl, 0x5c
61set _off_dwb, 0x60
62set _off_dww, 0x64
63set _off_dwl, 0x68
64
65_060ISP_TABLE:
66
67# Here's the table of ENTRY POINTS for those linking the package.
68 bra.l _isp_unimp
69 short 0x0000
70
71 bra.l _isp_cas
72 short 0x0000
73
74 bra.l _isp_cas2
75 short 0x0000
76
77 bra.l _isp_cas_finish
78 short 0x0000
79
80 bra.l _isp_cas2_finish
81 short 0x0000
82
83 bra.l _isp_cas_inrange
84 short 0x0000
85
86 bra.l _isp_cas_terminate
87 short 0x0000
88
89 bra.l _isp_cas_restart
90 short 0x0000
91
92 space 64
93
94#############################################################
95
96 global _real_chk
97_real_chk:
98 mov.l %d0,-(%sp)
99 mov.l (_060ISP_TABLE-0x80+_off_chk,%pc),%d0
100 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
101 mov.l 0x4(%sp),%d0
102 rtd &0x4
103
104 global _real_divbyzero
105_real_divbyzero:
106 mov.l %d0,-(%sp)
107 mov.l (_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
108 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
109 mov.l 0x4(%sp),%d0
110 rtd &0x4
111
112 global _real_trace
113_real_trace:
114 mov.l %d0,-(%sp)
115 mov.l (_060ISP_TABLE-0x80+_off_trace,%pc),%d0
116 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
117 mov.l 0x4(%sp),%d0
118 rtd &0x4
119
120 global _real_access
121_real_access:
122 mov.l %d0,-(%sp)
123 mov.l (_060ISP_TABLE-0x80+_off_access,%pc),%d0
124 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
125 mov.l 0x4(%sp),%d0
126 rtd &0x4
127
128 global _isp_done
129_isp_done:
130 mov.l %d0,-(%sp)
131 mov.l (_060ISP_TABLE-0x80+_off_done,%pc),%d0
132 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
133 mov.l 0x4(%sp),%d0
134 rtd &0x4
135
136#######################################
137
138 global _real_cas
139_real_cas:
140 mov.l %d0,-(%sp)
141 mov.l (_060ISP_TABLE-0x80+_off_cas,%pc),%d0
142 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
143 mov.l 0x4(%sp),%d0
144 rtd &0x4
145
146 global _real_cas2
147_real_cas2:
148 mov.l %d0,-(%sp)
149 mov.l (_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
150 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
151 mov.l 0x4(%sp),%d0
152 rtd &0x4
153
154 global _real_lock_page
155_real_lock_page:
156 mov.l %d0,-(%sp)
157 mov.l (_060ISP_TABLE-0x80+_off_lock,%pc),%d0
158 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
159 mov.l 0x4(%sp),%d0
160 rtd &0x4
161
162 global _real_unlock_page
163_real_unlock_page:
164 mov.l %d0,-(%sp)
165 mov.l (_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
166 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
167 mov.l 0x4(%sp),%d0
168 rtd &0x4
169
170#######################################
171
172 global _imem_read
173_imem_read:
174 mov.l %d0,-(%sp)
175 mov.l (_060ISP_TABLE-0x80+_off_imr,%pc),%d0
176 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
177 mov.l 0x4(%sp),%d0
178 rtd &0x4
179
180 global _dmem_read
181_dmem_read:
182 mov.l %d0,-(%sp)
183 mov.l (_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
184 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
185 mov.l 0x4(%sp),%d0
186 rtd &0x4
187
188 global _dmem_write
189_dmem_write:
190 mov.l %d0,-(%sp)
191 mov.l (_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
192 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
193 mov.l 0x4(%sp),%d0
194 rtd &0x4
195
196 global _imem_read_word
197_imem_read_word:
198 mov.l %d0,-(%sp)
199 mov.l (_060ISP_TABLE-0x80+_off_irw,%pc),%d0
200 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
201 mov.l 0x4(%sp),%d0
202 rtd &0x4
203
204 global _imem_read_long
205_imem_read_long:
206 mov.l %d0,-(%sp)
207 mov.l (_060ISP_TABLE-0x80+_off_irl,%pc),%d0
208 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
209 mov.l 0x4(%sp),%d0
210 rtd &0x4
211
212 global _dmem_read_byte
213_dmem_read_byte:
214 mov.l %d0,-(%sp)
215 mov.l (_060ISP_TABLE-0x80+_off_drb,%pc),%d0
216 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
217 mov.l 0x4(%sp),%d0
218 rtd &0x4
219
220 global _dmem_read_word
221_dmem_read_word:
222 mov.l %d0,-(%sp)
223 mov.l (_060ISP_TABLE-0x80+_off_drw,%pc),%d0
224 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
225 mov.l 0x4(%sp),%d0
226 rtd &0x4
227
228 global _dmem_read_long
229_dmem_read_long:
230 mov.l %d0,-(%sp)
231 mov.l (_060ISP_TABLE-0x80+_off_drl,%pc),%d0
232 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
233 mov.l 0x4(%sp),%d0
234 rtd &0x4
235
236 global _dmem_write_byte
237_dmem_write_byte:
238 mov.l %d0,-(%sp)
239 mov.l (_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
240 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
241 mov.l 0x4(%sp),%d0
242 rtd &0x4
243
244 global _dmem_write_word
245_dmem_write_word:
246 mov.l %d0,-(%sp)
247 mov.l (_060ISP_TABLE-0x80+_off_dww,%pc),%d0
248 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
249 mov.l 0x4(%sp),%d0
250 rtd &0x4
251
252 global _dmem_write_long
253_dmem_write_long:
254 mov.l %d0,-(%sp)
255 mov.l (_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
256 pea.l (_060ISP_TABLE-0x80,%pc,%d0)
257 mov.l 0x4(%sp),%d0
258 rtd &0x4
259
260#
261# This file contains a set of define statements for constants
262# in oreder to promote readability within the core code itself.
263#
264
265set LOCAL_SIZE, 96 # stack frame size(bytes)
266set LV, -LOCAL_SIZE # stack offset
267
268set EXC_ISR, 0x4 # stack status register
269set EXC_IPC, 0x6 # stack pc
270set EXC_IVOFF, 0xa # stacked vector offset
271
272set EXC_AREGS, LV+64 # offset of all address regs
273set EXC_DREGS, LV+32 # offset of all data regs
274
275set EXC_A7, EXC_AREGS+(7*4) # offset of a7
276set EXC_A6, EXC_AREGS+(6*4) # offset of a6
277set EXC_A5, EXC_AREGS+(5*4) # offset of a5
278set EXC_A4, EXC_AREGS+(4*4) # offset of a4
279set EXC_A3, EXC_AREGS+(3*4) # offset of a3
280set EXC_A2, EXC_AREGS+(2*4) # offset of a2
281set EXC_A1, EXC_AREGS+(1*4) # offset of a1
282set EXC_A0, EXC_AREGS+(0*4) # offset of a0
283set EXC_D7, EXC_DREGS+(7*4) # offset of d7
284set EXC_D6, EXC_DREGS+(6*4) # offset of d6
285set EXC_D5, EXC_DREGS+(5*4) # offset of d5
286set EXC_D4, EXC_DREGS+(4*4) # offset of d4
287set EXC_D3, EXC_DREGS+(3*4) # offset of d3
288set EXC_D2, EXC_DREGS+(2*4) # offset of d2
289set EXC_D1, EXC_DREGS+(1*4) # offset of d1
290set EXC_D0, EXC_DREGS+(0*4) # offset of d0
291
292set EXC_TEMP, LV+16 # offset of temp stack space
293
294set EXC_SAVVAL, LV+12 # offset of old areg value
295set EXC_SAVREG, LV+11 # offset of old areg index
296
297set SPCOND_FLG, LV+10 # offset of spc condition flg
298
299set EXC_CC, LV+8 # offset of cc register
300set EXC_EXTWPTR, LV+4 # offset of current PC
301set EXC_EXTWORD, LV+2 # offset of current ext opword
302set EXC_OPWORD, LV+0 # offset of current opword
303
304###########################
305# SPecial CONDition FLaGs #
306###########################
307set mia7_flg, 0x04 # (a7)+ flag
308set mda7_flg, 0x08 # -(a7) flag
309set ichk_flg, 0x10 # chk exception flag
310set idbyz_flg, 0x20 # divbyzero flag
311set restore_flg, 0x40 # restore -(an)+ flag
312set immed_flg, 0x80 # immediate data flag
313
314set mia7_bit, 0x2 # (a7)+ bit
315set mda7_bit, 0x3 # -(a7) bit
316set ichk_bit, 0x4 # chk exception bit
317set idbyz_bit, 0x5 # divbyzero bit
318set restore_bit, 0x6 # restore -(a7)+ bit
319set immed_bit, 0x7 # immediate data bit
320
321#########
322# Misc. #
323#########
324set BYTE, 1 # len(byte) == 1 byte
325set WORD, 2 # len(word) == 2 bytes
326set LONG, 4 # len(longword) == 4 bytes
327
328#########################################################################
329# XDEF **************************************************************** #
330# _isp_unimp(): 060ISP entry point for Unimplemented Instruction #
331# #
332# This handler should be the first code executed upon taking the #
333# "Unimplemented Integer Instruction" exception in an operating #
334# system. #
335# #
336# XREF **************************************************************** #
337# _imem_read_{word,long}() - read instruction word/longword #
338# _mul64() - emulate 64-bit multiply #
339# _div64() - emulate 64-bit divide #
340# _moveperipheral() - emulate "movep" #
341# _compandset() - emulate misaligned "cas" #
342# _compandset2() - emulate "cas2" #
343# _chk2_cmp2() - emulate "cmp2" and "chk2" #
344# _isp_done() - "callout" for normal final exit #
345# _real_trace() - "callout" for Trace exception #
346# _real_chk() - "callout" for Chk exception #
347# _real_divbyzero() - "callout" for DZ exception #
348# _real_access() - "callout" for access error exception #
349# #
350# INPUT *************************************************************** #
351# - The system stack contains the Unimp Int Instr stack frame #
352# #
353# OUTPUT ************************************************************** #
354# If Trace exception: #
355# - The system stack changed to contain Trace exc stack frame #
356# If Chk exception: #
357# - The system stack changed to contain Chk exc stack frame #
358# If DZ exception: #
359# - The system stack changed to contain DZ exc stack frame #
360# If access error exception: #
361# - The system stack changed to contain access err exc stk frame #
362# Else: #
363# - Results saved as appropriate #
364# #
365# ALGORITHM *********************************************************** #
366# This handler fetches the first instruction longword from #
367# memory and decodes it to determine which of the unimplemented #
368# integer instructions caused this exception. This handler then calls #
369# one of _mul64(), _div64(), _moveperipheral(), _compandset(), #
370# _compandset2(), or _chk2_cmp2() as appropriate. #
371# Some of these instructions, by their nature, may produce other #
372# types of exceptions. "div" can produce a divide-by-zero exception, #
373# and "chk2" can cause a "Chk" exception. In both cases, the current #
374# exception stack frame must be converted to an exception stack frame #
375# of the correct exception type and an exit must be made through #
376# _real_divbyzero() or _real_chk() as appropriate. In addition, all #
377# instructions may be executing while Trace is enabled. If so, then #
378# a Trace exception stack frame must be created and an exit made #
379# through _real_trace(). #
380# Meanwhile, if any read or write to memory using the #
381# _mem_{read,write}() "callout"s returns a failing value, then an #
382# access error frame must be created and an exit made through #
383# _real_access(). #
384# If none of these occur, then a normal exit is made through #
385# _isp_done(). #
386# #
387# This handler, upon entry, saves almost all user-visible #
388# address and data registers to the stack. Although this may seem to #
389# cause excess memory traffic, it was found that due to having to #
390# access these register files for things like data retrieval and <ea> #
391# calculations, it was more efficient to have them on the stack where #
392# they could be accessed by indexing rather than to make subroutine #
393# calls to retrieve a register of a particular index. #
394# #
395#########################################################################
396
397 global _isp_unimp
398_isp_unimp:
399 link.w %a6,&-LOCAL_SIZE # create room for stack frame
400
401 movm.l &0x3fff,EXC_DREGS(%a6) # store d0-d7/a0-a5
402 mov.l (%a6),EXC_A6(%a6) # store a6
403
404 btst &0x5,EXC_ISR(%a6) # from s or u mode?
405 bne.b uieh_s # supervisor mode
406uieh_u:
407 mov.l %usp,%a0 # fetch user stack pointer
408 mov.l %a0,EXC_A7(%a6) # store a7
409 bra.b uieh_cont
410uieh_s:
411 lea 0xc(%a6),%a0
412 mov.l %a0,EXC_A7(%a6) # store corrected sp
413
414###############################################################################
415
416uieh_cont:
417 clr.b SPCOND_FLG(%a6) # clear "special case" flag
418
419 mov.w EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
420 mov.l EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
421
422#
423# fetch the opword and first extension word pointed to by the stacked pc
424# and store them to the stack for now
425#
426 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
427 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
428 bsr.l _imem_read_long # fetch opword & extword
429 mov.l %d0,EXC_OPWORD(%a6) # store extword on stack
430
431
432#########################################################################
433# muls.l 0100 1100 00 |<ea>| 0*** 1100 0000 0*** #
434# mulu.l 0100 1100 00 |<ea>| 0*** 0100 0000 0*** #
435# #
436# divs.l 0100 1100 01 |<ea>| 0*** 1100 0000 0*** #
437# divu.l 0100 1100 01 |<ea>| 0*** 0100 0000 0*** #
438# #
439# movep.w m2r 0000 ***1 00 001*** | <displacement> | #
440# movep.l m2r 0000 ***1 01 001*** | <displacement> | #
441# movep.w r2m 0000 ***1 10 001*** | <displacement> | #
442# movep.l r2m 0000 ***1 11 001*** | <displacement> | #
443# #
444# cas.w 0000 1100 11 |<ea>| 0000 000* **00 0*** #
445# cas.l 0000 1110 11 |<ea>| 0000 000* **00 0*** #
446# #
447# cas2.w 0000 1100 11 111100 **** 000* **00 0*** #
448# **** 000* **00 0*** #
449# cas2.l 0000 1110 11 111100 **** 000* **00 0*** #
450# **** 000* **00 0*** #
451# #
452# chk2.b 0000 0000 11 |<ea>| **** 1000 0000 0000 #
453# chk2.w 0000 0010 11 |<ea>| **** 1000 0000 0000 #
454# chk2.l 0000 0100 11 |<ea>| **** 1000 0000 0000 #
455# #
456# cmp2.b 0000 0000 11 |<ea>| **** 0000 0000 0000 #
457# cmp2.w 0000 0010 11 |<ea>| **** 0000 0000 0000 #
458# cmp2.l 0000 0100 11 |<ea>| **** 0000 0000 0000 #
459#########################################################################
460
461#
462# using bit 14 of the operation word, separate into 2 groups:
463# (group1) mul64, div64
464# (group2) movep, chk2, cmp2, cas2, cas
465#
466 btst &0x1e,%d0 # group1 or group2
467 beq.b uieh_group2 # go handle group2
468
469#
470# now, w/ group1, make mul64's decode the fastest since it will
471# most likely be used the most.
472#
473uieh_group1:
474 btst &0x16,%d0 # test for div64
475 bne.b uieh_div64 # go handle div64
476
477uieh_mul64:
478# mul64() may use ()+ addressing and may, therefore, alter a7
479
480 bsr.l _mul64 # _mul64()
481
482 btst &0x5,EXC_ISR(%a6) # supervisor mode?
483 beq.w uieh_done
484 btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
485 beq.w uieh_done # no
486 btst &0x7,EXC_ISR(%a6) # is trace enabled?
487 bne.w uieh_trace_a7 # yes
488 bra.w uieh_a7 # no
489
490uieh_div64:
491# div64() may use ()+ addressing and may, therefore, alter a7.
492# div64() may take a divide by zero exception.
493
494 bsr.l _div64 # _div64()
495
496# here, we sort out all of the special cases that may have happened.
497 btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
498 bne.b uieh_div64_a7 # yes
499uieh_div64_dbyz:
500 btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
501 bne.w uieh_divbyzero # yes
502 bra.w uieh_done # no
503uieh_div64_a7:
504 btst &0x5,EXC_ISR(%a6) # supervisor mode?
505 beq.b uieh_div64_dbyz # no
506# here, a7 has been incremented by 4 bytes in supervisor mode. we still
507# may have the following 3 cases:
508# (i) (a7)+
509# (ii) (a7)+; trace
510# (iii) (a7)+; divide-by-zero
511#
512 btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
513 bne.w uieh_divbyzero_a7 # yes
514 tst.b EXC_ISR(%a6) # no; is trace enabled?
515 bmi.w uieh_trace_a7 # yes
516 bra.w uieh_a7 # no
517
518#
519# now, w/ group2, make movep's decode the fastest since it will
520# most likely be used the most.
521#
522uieh_group2:
523 btst &0x18,%d0 # test for not movep
524 beq.b uieh_not_movep
525
526
527 bsr.l _moveperipheral # _movep()
528 bra.w uieh_done
529
530uieh_not_movep:
531 btst &0x1b,%d0 # test for chk2,cmp2
532 beq.b uieh_chk2cmp2 # go handle chk2,cmp2
533
534 swap %d0 # put opword in lo word
535 cmpi.b %d0,&0xfc # test for cas2
536 beq.b uieh_cas2 # go handle cas2
537
538uieh_cas:
539
540 bsr.l _compandset # _cas()
541
542# the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
543# mode are simply not considered valid and therefore are not handled.
544
545 bra.w uieh_done
546
547uieh_cas2:
548
549 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
550 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
551 bsr.l _imem_read_word # read extension word
552
553 tst.l %d1 # ifetch error?
554 bne.w isp_iacc # yes
555
556 bsr.l _compandset2 # _cas2()
557 bra.w uieh_done
558
559uieh_chk2cmp2:
560# chk2 may take a chk exception
561
562 bsr.l _chk2_cmp2 # _chk2_cmp2()
563
564# here we check to see if a chk trap should be taken
565 cmpi.b SPCOND_FLG(%a6),&ichk_flg
566 bne.w uieh_done
567 bra.b uieh_chk_trap
568
569###########################################################################
570
571#
572# the required emulation has been completed. now, clean up the necessary stack
573# info and prepare for rte
574#
575uieh_done:
576 mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
577
578# if exception occurred in user mode, then we have to restore a7 in case it
579# changed. we don't have to update a7 for supervisor mose because that case
580# doesn't flow through here
581 btst &0x5,EXC_ISR(%a6) # user or supervisor?
582 bne.b uieh_finish # supervisor
583
584 mov.l EXC_A7(%a6),%a0 # fetch user stack pointer
585 mov.l %a0,%usp # restore it
586
587uieh_finish:
588 movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
589
590 btst &0x7,EXC_ISR(%a6) # is trace mode on?
591 bne.b uieh_trace # yes;go handle trace mode
592
593 mov.l EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
594 mov.l EXC_A6(%a6),(%a6) # prepare new a6 for unlink
595 unlk %a6 # unlink stack frame
596 bra.l _isp_done
597
598#
599# The instruction that was just emulated was also being traced. The trace
600# trap for this instruction will be lost unless we jump to the trace handler.
601# So, here we create a Trace Exception format number two exception stack
602# frame from the Unimplemented Integer Intruction Exception stack frame
603# format number zero and jump to the user supplied hook "_real_trace()".
604#
605# UIEH FRAME TRACE FRAME
606# ***************** *****************
607# * 0x0 * 0x0f4 * * Current *
608# ***************** * PC *
609# * Current * *****************
610# * PC * * 0x2 * 0x024 *
611# ***************** *****************
612# * SR * * Next *
613# ***************** * PC *
614# ->* Old * *****************
615# from link -->* A6 * * SR *
616# ***************** *****************
617# /* A7 * * New * <-- for final unlink
618# / * * * A6 *
619# link frame < ***************** *****************
620# \ ~ ~ ~ ~
621# \***************** *****************
622#
623uieh_trace:
624 mov.l EXC_A6(%a6),-0x4(%a6)
625 mov.w EXC_ISR(%a6),0x0(%a6)
626 mov.l EXC_IPC(%a6),0x8(%a6)
627 mov.l EXC_EXTWPTR(%a6),0x2(%a6)
628 mov.w &0x2024,0x6(%a6)
629 sub.l &0x4,%a6
630 unlk %a6
631 bra.l _real_trace
632
633#
634# UIEH FRAME CHK FRAME
635# ***************** *****************
636# * 0x0 * 0x0f4 * * Current *
637# ***************** * PC *
638# * Current * *****************
639# * PC * * 0x2 * 0x018 *
640# ***************** *****************
641# * SR * * Next *
642# ***************** * PC *
643# (4 words) *****************
644# * SR *
645# *****************
646# (6 words)
647#
648# the chk2 instruction should take a chk trap. so, here we must create a
649# chk stack frame from an unimplemented integer instruction exception frame
650# and jump to the user supplied entry point "_real_chk()".
651#
652uieh_chk_trap:
653 mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
654 movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
655
656 mov.w EXC_ISR(%a6),(%a6) # put new SR on stack
657 mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack
658 mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
659 mov.w &0x2018,0x6(%a6) # put Vector Offset on stack
660
661 mov.l EXC_A6(%a6),%a6 # restore a6
662 add.l &LOCAL_SIZE,%sp # clear stack frame
663
664 bra.l _real_chk
665
666#
667# UIEH FRAME DIVBYZERO FRAME
668# ***************** *****************
669# * 0x0 * 0x0f4 * * Current *
670# ***************** * PC *
671# * Current * *****************
672# * PC * * 0x2 * 0x014 *
673# ***************** *****************
674# * SR * * Next *
675# ***************** * PC *
676# (4 words) *****************
677# * SR *
678# *****************
679# (6 words)
680#
681# the divide instruction should take an integer divide by zero trap. so, here
682# we must create a divbyzero stack frame from an unimplemented integer
683# instruction exception frame and jump to the user supplied entry point
684# "_real_divbyzero()".
685#
686uieh_divbyzero:
687 mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
688 movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
689
690 mov.w EXC_ISR(%a6),(%a6) # put new SR on stack
691 mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack
692 mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
693 mov.w &0x2014,0x6(%a6) # put Vector Offset on stack
694
695 mov.l EXC_A6(%a6),%a6 # restore a6
696 add.l &LOCAL_SIZE,%sp # clear stack frame
697
698 bra.l _real_divbyzero
699
700#
701# DIVBYZERO FRAME
702# *****************
703# * Current *
704# UIEH FRAME * PC *
705# ***************** *****************
706# * 0x0 * 0x0f4 * * 0x2 * 0x014 *
707# ***************** *****************
708# * Current * * Next *
709# * PC * * PC *
710# ***************** *****************
711# * SR * * SR *
712# ***************** *****************
713# (4 words) (6 words)
714#
715# the divide instruction should take an integer divide by zero trap. so, here
716# we must create a divbyzero stack frame from an unimplemented integer
717# instruction exception frame and jump to the user supplied entry point
718# "_real_divbyzero()".
719#
720# However, we must also deal with the fact that (a7)+ was used from supervisor
721# mode, thereby shifting the stack frame up 4 bytes.
722#
723uieh_divbyzero_a7:
724 mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
725 movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
726
727 mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack
728 mov.w &0x2014,0xa(%a6) # put Vector Offset on stack
729 mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
730
731 mov.l EXC_A6(%a6),%a6 # restore a6
732 add.l &4+LOCAL_SIZE,%sp # clear stack frame
733
734 bra.l _real_divbyzero
735
736#
737# TRACE FRAME
738# *****************
739# * Current *
740# UIEH FRAME * PC *
741# ***************** *****************
742# * 0x0 * 0x0f4 * * 0x2 * 0x024 *
743# ***************** *****************
744# * Current * * Next *
745# * PC * * PC *
746# ***************** *****************
747# * SR * * SR *
748# ***************** *****************
749# (4 words) (6 words)
750#
751#
752# The instruction that was just emulated was also being traced. The trace
753# trap for this instruction will be lost unless we jump to the trace handler.
754# So, here we create a Trace Exception format number two exception stack
755# frame from the Unimplemented Integer Intruction Exception stack frame
756# format number zero and jump to the user supplied hook "_real_trace()".
757#
758# However, we must also deal with the fact that (a7)+ was used from supervisor
759# mode, thereby shifting the stack frame up 4 bytes.
760#
761uieh_trace_a7:
762 mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
763 movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
764
765 mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack
766 mov.w &0x2024,0xa(%a6) # put Vector Offset on stack
767 mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
768
769 mov.l EXC_A6(%a6),%a6 # restore a6
770 add.l &4+LOCAL_SIZE,%sp # clear stack frame
771
772 bra.l _real_trace
773
774#
775# UIEH FRAME
776# *****************
777# * 0x0 * 0x0f4 *
778# UIEH FRAME *****************
779# ***************** * Next *
780# * 0x0 * 0x0f4 * * PC *
781# ***************** *****************
782# * Current * * SR *
783# * PC * *****************
784# ***************** (4 words)
785# * SR *
786# *****************
787# (4 words)
788uieh_a7:
789 mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
790 movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
791
792 mov.w &0x00f4,0xe(%a6) # put Vector Offset on stack
793 mov.l EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
794 mov.w EXC_ISR(%a6),0x8(%a6) # put SR on stack
795
796 mov.l EXC_A6(%a6),%a6 # restore a6
797 add.l &8+LOCAL_SIZE,%sp # clear stack frame
798 bra.l _isp_done
799
800##########
801
802# this is the exit point if a data read or write fails.
803# a0 = failing address
804# d0 = fslw
805isp_dacc:
806 mov.l %a0,(%a6) # save address
807 mov.l %d0,-0x4(%a6) # save partial fslw
808
809 lea -64(%a6),%sp
810 movm.l (%sp)+,&0x7fff # restore d0-d7/a0-a6
811
812 mov.l 0xc(%sp),-(%sp) # move voff,hi(pc)
813 mov.l 0x4(%sp),0x10(%sp) # store fslw
814 mov.l 0xc(%sp),0x4(%sp) # store sr,lo(pc)
815 mov.l 0x8(%sp),0xc(%sp) # store address
816 mov.l (%sp)+,0x4(%sp) # store voff,hi(pc)
817 mov.w &0x4008,0x6(%sp) # store new voff
818
819 bra.b isp_acc_exit
820
821# this is the exit point if an instruction word read fails.
822# FSLW:
823# misaligned = true
824# read = true
825# size = word
826# instruction = true
827# software emulation error = true
828isp_iacc:
829 movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
830 unlk %a6 # unlink frame
831 sub.w &0x8,%sp # make room for acc frame
832 mov.l 0x8(%sp),(%sp) # store sr,lo(pc)
833 mov.w 0xc(%sp),0x4(%sp) # store hi(pc)
834 mov.w &0x4008,0x6(%sp) # store new voff
835 mov.l 0x2(%sp),0x8(%sp) # store address (=pc)
836 mov.l &0x09428001,0xc(%sp) # store fslw
837
838isp_acc_exit:
839 btst &0x5,(%sp) # user or supervisor?
840 beq.b isp_acc_exit2 # user
841 bset &0x2,0xd(%sp) # set supervisor TM bit
842isp_acc_exit2:
843 bra.l _real_access
844
845# if the addressing mode was (an)+ or -(an), the address register must
846# be restored to its pre-exception value before entering _real_access.
847isp_restore:
848 cmpi.b SPCOND_FLG(%a6),&restore_flg # do we need a restore?
849 bne.b isp_restore_done # no
850 clr.l %d0
851 mov.b EXC_SAVREG(%a6),%d0 # regno to restore
852 mov.l EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
853isp_restore_done:
854 rts
855
856#########################################################################
857# XDEF **************************************************************** #
858# _calc_ea(): routine to calculate effective address #
859# #
860# XREF **************************************************************** #
861# _imem_read_word() - read instruction word #
862# _imem_read_long() - read instruction longword #
863# _dmem_read_long() - read data longword (for memory indirect) #
864# isp_iacc() - handle instruction access error exception #
865# isp_dacc() - handle data access error exception #
866# #
867# INPUT *************************************************************** #
868# d0 = number of bytes related to effective address (w,l) #
869# #
870# OUTPUT ************************************************************** #
871# If exiting through isp_dacc... #
872# a0 = failing address #
873# d0 = FSLW #
874# elsif exiting though isp_iacc... #
875# none #
876# else #
877# a0 = effective address #
878# #
879# ALGORITHM *********************************************************** #
880# The effective address type is decoded from the opword residing #
881# on the stack. A jump table is used to vector to a routine for the #
882# appropriate mode. Since none of the emulated integer instructions #
883# uses byte-sized operands, only handle word and long operations. #
884# #
885# Dn,An - shouldn't enter here #
886# (An) - fetch An value from stack #
887# -(An) - fetch An value from stack; return decr value; #
888# place decr value on stack; store old value in case of #
889# future access error; if -(a7), set mda7_flg in #
890# SPCOND_FLG #
891# (An)+ - fetch An value from stack; return value; #
892# place incr value on stack; store old value in case of #
893# future access error; if (a7)+, set mia7_flg in #
894# SPCOND_FLG #
895# (d16,An) - fetch An value from stack; read d16 using #
896# _imem_read_word(); fetch may fail -> branch to #
897# isp_iacc() #
898# (xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch #
899# address; fetch may fail #
900# #<data> - return address of immediate value; set immed_flg #
901# in SPCOND_FLG #
902# (d16,PC) - fetch stacked PC value; read d16 using #
903# _imem_read_word(); fetch may fail -> branch to #
904# isp_iacc() #
905# everything else - read needed displacements as appropriate w/ #
906# _imem_read_{word,long}(); read may fail; if memory #
907# indirect, read indirect address using #
908# _dmem_read_long() which may also fail #
909# #
910#########################################################################
911
912 global _calc_ea
913_calc_ea:
914 mov.l %d0,%a0 # move # bytes to a0
915
916# MODE and REG are taken from the EXC_OPWORD.
917 mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word
918 mov.w %d0,%d1 # make a copy
919
920 andi.w &0x3f,%d0 # extract mode field
921 andi.l &0x7,%d1 # extract reg field
922
923# jump to the corresponding function for each {MODE,REG} pair.
924 mov.w (tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
925 jmp (tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
926
927 swbeg &64
928tbl_ea_mode:
929 short tbl_ea_mode - tbl_ea_mode
930 short tbl_ea_mode - tbl_ea_mode
931 short tbl_ea_mode - tbl_ea_mode
932 short tbl_ea_mode - tbl_ea_mode
933 short tbl_ea_mode - tbl_ea_mode
934 short tbl_ea_mode - tbl_ea_mode
935 short tbl_ea_mode - tbl_ea_mode
936 short tbl_ea_mode - tbl_ea_mode
937
938 short tbl_ea_mode - tbl_ea_mode
939 short tbl_ea_mode - tbl_ea_mode
940 short tbl_ea_mode - tbl_ea_mode
941 short tbl_ea_mode - tbl_ea_mode
942 short tbl_ea_mode - tbl_ea_mode
943 short tbl_ea_mode - tbl_ea_mode
944 short tbl_ea_mode - tbl_ea_mode
945 short tbl_ea_mode - tbl_ea_mode
946
947 short addr_ind_a0 - tbl_ea_mode
948 short addr_ind_a1 - tbl_ea_mode
949 short addr_ind_a2 - tbl_ea_mode
950 short addr_ind_a3 - tbl_ea_mode
951 short addr_ind_a4 - tbl_ea_mode
952 short addr_ind_a5 - tbl_ea_mode
953 short addr_ind_a6 - tbl_ea_mode
954 short addr_ind_a7 - tbl_ea_mode
955
956 short addr_ind_p_a0 - tbl_ea_mode
957 short addr_ind_p_a1 - tbl_ea_mode
958 short addr_ind_p_a2 - tbl_ea_mode
959 short addr_ind_p_a3 - tbl_ea_mode
960 short addr_ind_p_a4 - tbl_ea_mode
961 short addr_ind_p_a5 - tbl_ea_mode
962 short addr_ind_p_a6 - tbl_ea_mode
963 short addr_ind_p_a7 - tbl_ea_mode
964
965 short addr_ind_m_a0 - tbl_ea_mode
966 short addr_ind_m_a1 - tbl_ea_mode
967 short addr_ind_m_a2 - tbl_ea_mode
968 short addr_ind_m_a3 - tbl_ea_mode
969 short addr_ind_m_a4 - tbl_ea_mode
970 short addr_ind_m_a5 - tbl_ea_mode
971 short addr_ind_m_a6 - tbl_ea_mode
972 short addr_ind_m_a7 - tbl_ea_mode
973
974 short addr_ind_disp_a0 - tbl_ea_mode
975 short addr_ind_disp_a1 - tbl_ea_mode
976 short addr_ind_disp_a2 - tbl_ea_mode
977 short addr_ind_disp_a3 - tbl_ea_mode
978 short addr_ind_disp_a4 - tbl_ea_mode
979 short addr_ind_disp_a5 - tbl_ea_mode
980 short addr_ind_disp_a6 - tbl_ea_mode
981 short addr_ind_disp_a7 - tbl_ea_mode
982
983 short _addr_ind_ext - tbl_ea_mode
984 short _addr_ind_ext - tbl_ea_mode
985 short _addr_ind_ext - tbl_ea_mode
986 short _addr_ind_ext - tbl_ea_mode
987 short _addr_ind_ext - tbl_ea_mode
988 short _addr_ind_ext - tbl_ea_mode
989 short _addr_ind_ext - tbl_ea_mode
990 short _addr_ind_ext - tbl_ea_mode
991
992 short abs_short - tbl_ea_mode
993 short abs_long - tbl_ea_mode
994 short pc_ind - tbl_ea_mode
995 short pc_ind_ext - tbl_ea_mode
996 short immediate - tbl_ea_mode
997 short tbl_ea_mode - tbl_ea_mode
998 short tbl_ea_mode - tbl_ea_mode
999 short tbl_ea_mode - tbl_ea_mode
1000
1001###################################
1002# Address register indirect: (An) #
1003###################################
1004addr_ind_a0:
1005 mov.l EXC_A0(%a6),%a0 # Get current a0
1006 rts
1007
1008addr_ind_a1:
1009 mov.l EXC_A1(%a6),%a0 # Get current a1
1010 rts
1011
1012addr_ind_a2:
1013 mov.l EXC_A2(%a6),%a0 # Get current a2
1014 rts
1015
1016addr_ind_a3:
1017 mov.l EXC_A3(%a6),%a0 # Get current a3
1018 rts
1019
1020addr_ind_a4:
1021 mov.l EXC_A4(%a6),%a0 # Get current a4
1022 rts
1023
1024addr_ind_a5:
1025 mov.l EXC_A5(%a6),%a0 # Get current a5
1026 rts
1027
1028addr_ind_a6:
1029 mov.l EXC_A6(%a6),%a0 # Get current a6
1030 rts
1031
1032addr_ind_a7:
1033 mov.l EXC_A7(%a6),%a0 # Get current a7
1034 rts
1035
1036#####################################################
1037# Address register indirect w/ postincrement: (An)+ #
1038#####################################################
1039addr_ind_p_a0:
1040 mov.l %a0,%d0 # copy no. bytes
1041 mov.l EXC_A0(%a6),%a0 # load current value
1042 add.l %a0,%d0 # increment
1043 mov.l %d0,EXC_A0(%a6) # save incremented value
1044
1045 mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1046 mov.b &0x0,EXC_SAVREG(%a6) # save regno, too
1047 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1048 rts
1049
1050addr_ind_p_a1:
1051 mov.l %a0,%d0 # copy no. bytes
1052 mov.l EXC_A1(%a6),%a0 # load current value
1053 add.l %a0,%d0 # increment
1054 mov.l %d0,EXC_A1(%a6) # save incremented value
1055
1056 mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1057 mov.b &0x1,EXC_SAVREG(%a6) # save regno, too
1058 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1059 rts
1060
1061addr_ind_p_a2:
1062 mov.l %a0,%d0 # copy no. bytes
1063 mov.l EXC_A2(%a6),%a0 # load current value
1064 add.l %a0,%d0 # increment
1065 mov.l %d0,EXC_A2(%a6) # save incremented value
1066
1067 mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1068 mov.b &0x2,EXC_SAVREG(%a6) # save regno, too
1069 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1070 rts
1071
1072addr_ind_p_a3:
1073 mov.l %a0,%d0 # copy no. bytes
1074 mov.l EXC_A3(%a6),%a0 # load current value
1075 add.l %a0,%d0 # increment
1076 mov.l %d0,EXC_A3(%a6) # save incremented value
1077
1078 mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1079 mov.b &0x3,EXC_SAVREG(%a6) # save regno, too
1080 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1081 rts
1082
1083addr_ind_p_a4:
1084 mov.l %a0,%d0 # copy no. bytes
1085 mov.l EXC_A4(%a6),%a0 # load current value
1086 add.l %a0,%d0 # increment
1087 mov.l %d0,EXC_A4(%a6) # save incremented value
1088
1089 mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1090 mov.b &0x4,EXC_SAVREG(%a6) # save regno, too
1091 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1092 rts
1093
1094addr_ind_p_a5:
1095 mov.l %a0,%d0 # copy no. bytes
1096 mov.l EXC_A5(%a6),%a0 # load current value
1097 add.l %a0,%d0 # increment
1098 mov.l %d0,EXC_A5(%a6) # save incremented value
1099
1100 mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1101 mov.b &0x5,EXC_SAVREG(%a6) # save regno, too
1102 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1103 rts
1104
1105addr_ind_p_a6:
1106 mov.l %a0,%d0 # copy no. bytes
1107 mov.l EXC_A6(%a6),%a0 # load current value
1108 add.l %a0,%d0 # increment
1109 mov.l %d0,EXC_A6(%a6) # save incremented value
1110
1111 mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1112 mov.b &0x6,EXC_SAVREG(%a6) # save regno, too
1113 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1114 rts
1115
1116addr_ind_p_a7:
1117 mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
1118
1119 mov.l %a0,%d0 # copy no. bytes
1120 mov.l EXC_A7(%a6),%a0 # load current value
1121 add.l %a0,%d0 # increment
1122 mov.l %d0,EXC_A7(%a6) # save incremented value
1123 rts
1124
1125####################################################
1126# Address register indirect w/ predecrement: -(An) #
1127####################################################
1128addr_ind_m_a0:
1129 mov.l EXC_A0(%a6),%d0 # Get current a0
1130 mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1131 sub.l %a0,%d0 # Decrement
1132 mov.l %d0,EXC_A0(%a6) # Save decr value
1133 mov.l %d0,%a0
1134
1135 mov.b &0x0,EXC_SAVREG(%a6) # save regno, too
1136 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1137 rts
1138
1139addr_ind_m_a1:
1140 mov.l EXC_A1(%a6),%d0 # Get current a1
1141 mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1142 sub.l %a0,%d0 # Decrement
1143 mov.l %d0,EXC_A1(%a6) # Save decr value
1144 mov.l %d0,%a0
1145
1146 mov.b &0x1,EXC_SAVREG(%a6) # save regno, too
1147 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1148 rts
1149
1150addr_ind_m_a2:
1151 mov.l EXC_A2(%a6),%d0 # Get current a2
1152 mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1153 sub.l %a0,%d0 # Decrement
1154 mov.l %d0,EXC_A2(%a6) # Save decr value
1155 mov.l %d0,%a0
1156
1157 mov.b &0x2,EXC_SAVREG(%a6) # save regno, too
1158 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1159 rts
1160
1161addr_ind_m_a3:
1162 mov.l EXC_A3(%a6),%d0 # Get current a3
1163 mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1164 sub.l %a0,%d0 # Decrement
1165 mov.l %d0,EXC_A3(%a6) # Save decr value
1166 mov.l %d0,%a0
1167
1168 mov.b &0x3,EXC_SAVREG(%a6) # save regno, too
1169 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1170 rts
1171
1172addr_ind_m_a4:
1173 mov.l EXC_A4(%a6),%d0 # Get current a4
1174 mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1175 sub.l %a0,%d0 # Decrement
1176 mov.l %d0,EXC_A4(%a6) # Save decr value
1177 mov.l %d0,%a0
1178
1179 mov.b &0x4,EXC_SAVREG(%a6) # save regno, too
1180 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1181 rts
1182
1183addr_ind_m_a5:
1184 mov.l EXC_A5(%a6),%d0 # Get current a5
1185 mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1186 sub.l %a0,%d0 # Decrement
1187 mov.l %d0,EXC_A5(%a6) # Save decr value
1188 mov.l %d0,%a0
1189
1190 mov.b &0x5,EXC_SAVREG(%a6) # save regno, too
1191 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1192 rts
1193
1194addr_ind_m_a6:
1195 mov.l EXC_A6(%a6),%d0 # Get current a6
1196 mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1197 sub.l %a0,%d0 # Decrement
1198 mov.l %d0,EXC_A6(%a6) # Save decr value
1199 mov.l %d0,%a0
1200
1201 mov.b &0x6,EXC_SAVREG(%a6) # save regno, too
1202 mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1203 rts
1204
1205addr_ind_m_a7:
1206 mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
1207
1208 mov.l EXC_A7(%a6),%d0 # Get current a7
1209 sub.l %a0,%d0 # Decrement
1210 mov.l %d0,EXC_A7(%a6) # Save decr value
1211 mov.l %d0,%a0
1212 rts
1213
1214########################################################
1215# Address register indirect w/ displacement: (d16, An) #
1216########################################################
1217addr_ind_disp_a0:
1218 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1219 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1220 bsr.l _imem_read_word
1221
1222 tst.l %d1 # ifetch error?
1223 bne.l isp_iacc # yes
1224
1225 mov.w %d0,%a0 # sign extend displacement
1226 add.l EXC_A0(%a6),%a0 # a0 + d16
1227 rts
1228
1229addr_ind_disp_a1:
1230 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1231 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1232 bsr.l _imem_read_word
1233
1234 tst.l %d1 # ifetch error?
1235 bne.l isp_iacc # yes
1236
1237 mov.w %d0,%a0 # sign extend displacement
1238 add.l EXC_A1(%a6),%a0 # a1 + d16
1239 rts
1240
1241addr_ind_disp_a2:
1242 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1243 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1244 bsr.l _imem_read_word
1245
1246 tst.l %d1 # ifetch error?
1247 bne.l isp_iacc # yes
1248
1249 mov.w %d0,%a0 # sign extend displacement
1250 add.l EXC_A2(%a6),%a0 # a2 + d16
1251 rts
1252
1253addr_ind_disp_a3:
1254 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1255 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1256 bsr.l _imem_read_word
1257
1258 tst.l %d1 # ifetch error?
1259 bne.l isp_iacc # yes
1260
1261 mov.w %d0,%a0 # sign extend displacement
1262 add.l EXC_A3(%a6),%a0 # a3 + d16
1263 rts
1264
1265addr_ind_disp_a4:
1266 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1267 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1268 bsr.l _imem_read_word
1269
1270 tst.l %d1 # ifetch error?
1271 bne.l isp_iacc # yes
1272
1273 mov.w %d0,%a0 # sign extend displacement
1274 add.l EXC_A4(%a6),%a0 # a4 + d16
1275 rts
1276
1277addr_ind_disp_a5:
1278 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1279 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1280 bsr.l _imem_read_word
1281
1282 tst.l %d1 # ifetch error?
1283 bne.l isp_iacc # yes
1284
1285 mov.w %d0,%a0 # sign extend displacement
1286 add.l EXC_A5(%a6),%a0 # a5 + d16
1287 rts
1288
1289addr_ind_disp_a6:
1290 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1291 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1292 bsr.l _imem_read_word
1293
1294 tst.l %d1 # ifetch error?
1295 bne.l isp_iacc # yes
1296
1297 mov.w %d0,%a0 # sign extend displacement
1298 add.l EXC_A6(%a6),%a0 # a6 + d16
1299 rts
1300
1301addr_ind_disp_a7:
1302 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1303 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1304 bsr.l _imem_read_word
1305
1306 tst.l %d1 # ifetch error?
1307 bne.l isp_iacc # yes
1308
1309 mov.w %d0,%a0 # sign extend displacement
1310 add.l EXC_A7(%a6),%a0 # a7 + d16
1311 rts
1312
1313########################################################################
1314# Address register indirect w/ index(8-bit displacement): (dn, An, Xn) #
1315# " " " w/ " (base displacement): (bd, An, Xn) #
1316# Memory indirect postindexed: ([bd, An], Xn, od) #
1317# Memory indirect preindexed: ([bd, An, Xn], od) #
1318########################################################################
1319_addr_ind_ext:
1320 mov.l %d1,-(%sp)
1321
1322 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1323 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1324 bsr.l _imem_read_word # fetch extword in d0
1325
1326 tst.l %d1 # ifetch error?
1327 bne.l isp_iacc # yes
1328
1329 mov.l (%sp)+,%d1
1330
1331 mov.l (EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0
1332
1333 btst &0x8,%d0
1334 beq.b addr_ind_index_8bit # for ext word or not?
1335
1336 movm.l &0x3c00,-(%sp) # save d2-d5
1337
1338 mov.l %d0,%d5 # put extword in d5
1339 mov.l %a0,%d3 # put base in d3
1340
1341 bra.l calc_mem_ind # calc memory indirect
1342
1343addr_ind_index_8bit:
1344 mov.l %d2,-(%sp) # save old d2
1345
1346 mov.l %d0,%d1
1347 rol.w &0x4,%d1
1348 andi.w &0xf,%d1 # extract index regno
1349
1350 mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
1351
1352 btst &0xb,%d0 # is it word or long?
1353 bne.b aii8_long
1354 ext.l %d1 # sign extend word index
1355aii8_long:
1356 mov.l %d0,%d2
1357 rol.w &0x7,%d2
1358 andi.l &0x3,%d2 # extract scale value
1359
1360 lsl.l %d2,%d1 # shift index by scale
1361
1362 extb.l %d0 # sign extend displacement
1363 add.l %d1,%d0 # index + disp
1364 add.l %d0,%a0 # An + (index + disp)
1365
1366 mov.l (%sp)+,%d2 # restore old d2
1367 rts
1368
1369######################
1370# Immediate: #<data> #
1371#########################################################################
1372# word, long: <ea> of the data is the current extension word #
1373# pointer value. new extension word pointer is simply the old #
1374# plus the number of bytes in the data type(2 or 4). #
1375#########################################################################
1376immediate:
1377 mov.b &immed_flg,SPCOND_FLG(%a6) # set immediate flag
1378
1379 mov.l EXC_EXTWPTR(%a6),%a0 # fetch extension word ptr
1380 rts
1381
1382###########################
1383# Absolute short: (XXX).W #
1384###########################
1385abs_short:
1386 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1387 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1388 bsr.l _imem_read_word # fetch short address
1389
1390 tst.l %d1 # ifetch error?
1391 bne.l isp_iacc # yes
1392
1393 mov.w %d0,%a0 # return <ea> in a0
1394 rts
1395
1396##########################
1397# Absolute long: (XXX).L #
1398##########################
1399abs_long:
1400 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1401 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1402 bsr.l _imem_read_long # fetch long address
1403
1404 tst.l %d1 # ifetch error?
1405 bne.l isp_iacc # yes
1406
1407 mov.l %d0,%a0 # return <ea> in a0
1408 rts
1409
1410#######################################################
1411# Program counter indirect w/ displacement: (d16, PC) #
1412#######################################################
1413pc_ind:
1414 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1415 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1416 bsr.l _imem_read_word # fetch word displacement
1417
1418 tst.l %d1 # ifetch error?
1419 bne.l isp_iacc # yes
1420
1421 mov.w %d0,%a0 # sign extend displacement
1422
1423 add.l EXC_EXTWPTR(%a6),%a0 # pc + d16
1424
1425# _imem_read_word() increased the extwptr by 2. need to adjust here.
1426 subq.l &0x2,%a0 # adjust <ea>
1427
1428 rts
1429
1430##########################################################
1431# PC indirect w/ index(8-bit displacement): (d8, PC, An) #
1432# " " w/ " (base displacement): (bd, PC, An) #
1433# PC memory indirect postindexed: ([bd, PC], Xn, od) #
1434# PC memory indirect preindexed: ([bd, PC, Xn], od) #
1435##########################################################
1436pc_ind_ext:
1437 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1438 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1439 bsr.l _imem_read_word # fetch ext word
1440
1441 tst.l %d1 # ifetch error?
1442 bne.l isp_iacc # yes
1443
1444 mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0
1445 subq.l &0x2,%a0 # adjust base
1446
1447 btst &0x8,%d0 # is disp only 8 bits?
1448 beq.b pc_ind_index_8bit # yes
1449
1450# the indexed addressing mode uses a base displacement of size
1451# word or long
1452 movm.l &0x3c00,-(%sp) # save d2-d5
1453
1454 mov.l %d0,%d5 # put extword in d5
1455 mov.l %a0,%d3 # put base in d3
1456
1457 bra.l calc_mem_ind # calc memory indirect
1458
1459pc_ind_index_8bit:
1460 mov.l %d2,-(%sp) # create a temp register
1461
1462 mov.l %d0,%d1 # make extword copy
1463 rol.w &0x4,%d1 # rotate reg num into place
1464 andi.w &0xf,%d1 # extract register number
1465
1466 mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
1467
1468 btst &0xb,%d0 # is index word or long?
1469 bne.b pii8_long # long
1470 ext.l %d1 # sign extend word index
1471pii8_long:
1472 mov.l %d0,%d2 # make extword copy
1473 rol.w &0x7,%d2 # rotate scale value into place
1474 andi.l &0x3,%d2 # extract scale value
1475
1476 lsl.l %d2,%d1 # shift index by scale
1477
1478 extb.l %d0 # sign extend displacement
1479 add.l %d1,%d0 # index + disp
1480 add.l %d0,%a0 # An + (index + disp)
1481
1482 mov.l (%sp)+,%d2 # restore temp register
1483
1484 rts
1485
1486# a5 = exc_extwptr (global to uaeh)
1487# a4 = exc_opword (global to uaeh)
1488# a3 = exc_dregs (global to uaeh)
1489
1490# d2 = index (internal " " )
1491# d3 = base (internal " " )
1492# d4 = od (internal " " )
1493# d5 = extword (internal " " )
1494calc_mem_ind:
1495 btst &0x6,%d5 # is the index suppressed?
1496 beq.b calc_index
1497 clr.l %d2 # yes, so index = 0
1498 bra.b base_supp_ck
1499calc_index:
1500 bfextu %d5{&16:&4},%d2
1501 mov.l (EXC_DREGS,%a6,%d2.w*4),%d2
1502 btst &0xb,%d5 # is index word or long?
1503 bne.b no_ext
1504 ext.l %d2
1505no_ext:
1506 bfextu %d5{&21:&2},%d0
1507 lsl.l %d0,%d2
1508base_supp_ck:
1509 btst &0x7,%d5 # is the bd suppressed?
1510 beq.b no_base_sup
1511 clr.l %d3
1512no_base_sup:
1513 bfextu %d5{&26:&2},%d0 # get bd size
1514# beq.l _error # if (size == 0) it's reserved
1515 cmpi.b %d0,&2
1516 blt.b no_bd
1517 beq.b get_word_bd
1518
1519 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1520 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1521 bsr.l _imem_read_long
1522
1523 tst.l %d1 # ifetch error?
1524 bne.l isp_iacc # yes
1525
1526 bra.b chk_ind
1527get_word_bd:
1528 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1529 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1530 bsr.l _imem_read_word
1531
1532 tst.l %d1 # ifetch error?
1533 bne.l isp_iacc # yes
1534
1535 ext.l %d0 # sign extend bd
1536
1537chk_ind:
1538 add.l %d0,%d3 # base += bd
1539no_bd:
1540 bfextu %d5{&30:&2},%d0 # is od suppressed?
1541 beq.w aii_bd
1542 cmpi.b %d0,&0x2
1543 blt.b null_od
1544 beq.b word_od
1545
1546 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1547 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1548 bsr.l _imem_read_long
1549
1550 tst.l %d1 # ifetch error?
1551 bne.l isp_iacc # yes
1552
1553 bra.b add_them
1554
1555word_od:
1556 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1557 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1558 bsr.l _imem_read_word
1559
1560 tst.l %d1 # ifetch error?
1561 bne.l isp_iacc # yes
1562
1563 ext.l %d0 # sign extend od
1564 bra.b add_them
1565
1566null_od:
1567 clr.l %d0
1568add_them:
1569 mov.l %d0,%d4
1570 btst &0x2,%d5 # pre or post indexing?
1571 beq.b pre_indexed
1572
1573 mov.l %d3,%a0
1574 bsr.l _dmem_read_long
1575
1576 tst.l %d1 # dfetch error?
1577 bne.b calc_ea_err # yes
1578
1579 add.l %d2,%d0 # <ea> += index
1580 add.l %d4,%d0 # <ea> += od
1581 bra.b done_ea
1582
1583pre_indexed:
1584 add.l %d2,%d3 # preindexing
1585 mov.l %d3,%a0
1586 bsr.l _dmem_read_long
1587
1588 tst.l %d1 # ifetch error?
1589 bne.b calc_ea_err # yes
1590
1591 add.l %d4,%d0 # ea += od
1592 bra.b done_ea
1593
1594aii_bd:
1595 add.l %d2,%d3 # ea = (base + bd) + index
1596 mov.l %d3,%d0
1597done_ea:
1598 mov.l %d0,%a0
1599
1600 movm.l (%sp)+,&0x003c # restore d2-d5
1601 rts
1602
1603# if dmem_read_long() returns a fail message in d1, the package
1604# must create an access error frame. here, we pass a skeleton fslw
1605# and the failing address to the routine that creates the new frame.
1606# FSLW:
1607# read = true
1608# size = longword
1609# TM = data
1610# software emulation error = true
1611calc_ea_err:
1612 mov.l %d3,%a0 # pass failing address
1613 mov.l &0x01010001,%d0 # pass fslw
1614 bra.l isp_dacc
1615
1616#########################################################################
1617# XDEF **************************************************************** #
1618# _moveperipheral(): routine to emulate movep instruction #
1619# #
1620# XREF **************************************************************** #
1621# _dmem_read_byte() - read byte from memory #
1622# _dmem_write_byte() - write byte to memory #
1623# isp_dacc() - handle data access error exception #
1624# #
1625# INPUT *************************************************************** #
1626# none #
1627# #
1628# OUTPUT ************************************************************** #
1629# If exiting through isp_dacc... #
1630# a0 = failing address #
1631# d0 = FSLW #
1632# else #
1633# none #
1634# #
1635# ALGORITHM *********************************************************** #
1636# Decode the movep instruction words stored at EXC_OPWORD and #
1637# either read or write the required bytes from/to memory. Use the #
1638# _dmem_{read,write}_byte() routines. If one of the memory routines #
1639# returns a failing value, we must pass the failing address and a FSLW #
1640# to the _isp_dacc() routine. #
1641# Since this instruction is used to access peripherals, make sure #
1642# to only access the required bytes. #
1643# #
1644#########################################################################
1645
1646###########################
1647# movep.(w,l) Dx,(d,Ay) #
1648# movep.(w,l) (d,Ay),Dx #
1649###########################
1650 global _moveperipheral
1651_moveperipheral:
1652 mov.w EXC_OPWORD(%a6),%d1 # fetch the opcode word
1653
1654 mov.b %d1,%d0
1655 and.w &0x7,%d0 # extract Ay from opcode word
1656
1657 mov.l (EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay
1658
1659 add.w EXC_EXTWORD(%a6),%a0 # add: an + sgn_ext(disp)
1660
1661 btst &0x7,%d1 # (reg 2 mem) or (mem 2 reg)
1662 beq.w mem2reg
1663
1664# reg2mem: fetch dx, then write it to memory
1665reg2mem:
1666 mov.w %d1,%d0
1667 rol.w &0x7,%d0
1668 and.w &0x7,%d0 # extract Dx from opcode word
1669
1670 mov.l (EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx
1671
1672 btst &0x6,%d1 # word or long operation?
1673 beq.b r2mwtrans
1674
1675# a0 = dst addr
1676# d0 = Dx
1677r2mltrans:
1678 mov.l %d0,%d2 # store data
1679 mov.l %a0,%a2 # store addr
1680 rol.l &0x8,%d2
1681 mov.l %d2,%d0
1682
1683 bsr.l _dmem_write_byte # os : write hi
1684
1685 tst.l %d1 # dfetch error?
1686 bne.w movp_write_err # yes
1687
1688 add.w &0x2,%a2 # incr addr
1689 mov.l %a2,%a0
1690 rol.l &0x8,%d2
1691 mov.l %d2,%d0
1692
1693 bsr.l _dmem_write_byte # os : write lo
1694
1695 tst.l %d1 # dfetch error?
1696 bne.w movp_write_err # yes
1697
1698 add.w &0x2,%a2 # incr addr
1699 mov.l %a2,%a0
1700 rol.l &0x8,%d2
1701 mov.l %d2,%d0
1702
1703 bsr.l _dmem_write_byte # os : write lo
1704
1705 tst.l %d1 # dfetch error?
1706 bne.w movp_write_err # yes
1707
1708 add.w &0x2,%a2 # incr addr
1709 mov.l %a2,%a0
1710 rol.l &0x8,%d2
1711 mov.l %d2,%d0
1712
1713 bsr.l _dmem_write_byte # os : write lo
1714
1715 tst.l %d1 # dfetch error?
1716 bne.w movp_write_err # yes
1717
1718 rts
1719
1720# a0 = dst addr
1721# d0 = Dx
1722r2mwtrans:
1723 mov.l %d0,%d2 # store data
1724 mov.l %a0,%a2 # store addr
1725 lsr.w &0x8,%d0
1726
1727 bsr.l _dmem_write_byte # os : write hi
1728
1729 tst.l %d1 # dfetch error?
1730 bne.w movp_write_err # yes
1731
1732 add.w &0x2,%a2
1733 mov.l %a2,%a0
1734 mov.l %d2,%d0
1735
1736 bsr.l _dmem_write_byte # os : write lo
1737
1738 tst.l %d1 # dfetch error?
1739 bne.w movp_write_err # yes
1740
1741 rts
1742
1743# mem2reg: read bytes from memory.
1744# determines the dest register, and then writes the bytes into it.
1745mem2reg:
1746 btst &0x6,%d1 # word or long operation?
1747 beq.b m2rwtrans
1748
1749# a0 = dst addr
1750m2rltrans:
1751 mov.l %a0,%a2 # store addr
1752
1753 bsr.l _dmem_read_byte # read first byte
1754
1755 tst.l %d1 # dfetch error?
1756 bne.w movp_read_err # yes
1757
1758 mov.l %d0,%d2
1759
1760 add.w &0x2,%a2 # incr addr by 2 bytes
1761 mov.l %a2,%a0
1762
1763 bsr.l _dmem_read_byte # read second byte
1764
1765 tst.l %d1 # dfetch error?
1766 bne.w movp_read_err # yes
1767
1768 lsl.w &0x8,%d2
1769 mov.b %d0,%d2 # append bytes
1770
1771 add.w &0x2,%a2 # incr addr by 2 bytes
1772 mov.l %a2,%a0
1773
1774 bsr.l _dmem_read_byte # read second byte
1775
1776 tst.l %d1 # dfetch error?
1777 bne.w movp_read_err # yes
1778
1779 lsl.l &0x8,%d2
1780 mov.b %d0,%d2 # append bytes
1781
1782 add.w &0x2,%a2 # incr addr by 2 bytes
1783 mov.l %a2,%a0
1784
1785 bsr.l _dmem_read_byte # read second byte
1786
1787 tst.l %d1 # dfetch error?
1788 bne.w movp_read_err # yes
1789
1790 lsl.l &0x8,%d2
1791 mov.b %d0,%d2 # append bytes
1792
1793 mov.b EXC_OPWORD(%a6),%d1
1794 lsr.b &0x1,%d1
1795 and.w &0x7,%d1 # extract Dx from opcode word
1796
1797 mov.l %d2,(EXC_DREGS,%a6,%d1.w*4) # store dx
1798
1799 rts
1800
1801# a0 = dst addr
1802m2rwtrans:
1803 mov.l %a0,%a2 # store addr
1804
1805 bsr.l _dmem_read_byte # read first byte
1806
1807 tst.l %d1 # dfetch error?
1808 bne.w movp_read_err # yes
1809
1810 mov.l %d0,%d2
1811
1812 add.w &0x2,%a2 # incr addr by 2 bytes
1813 mov.l %a2,%a0
1814
1815 bsr.l _dmem_read_byte # read second byte
1816
1817 tst.l %d1 # dfetch error?
1818 bne.w movp_read_err # yes
1819
1820 lsl.w &0x8,%d2
1821 mov.b %d0,%d2 # append bytes
1822
1823 mov.b EXC_OPWORD(%a6),%d1
1824 lsr.b &0x1,%d1
1825 and.w &0x7,%d1 # extract Dx from opcode word
1826
1827 mov.w %d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx
1828
1829 rts
1830
1831# if dmem_{read,write}_byte() returns a fail message in d1, the package
1832# must create an access error frame. here, we pass a skeleton fslw
1833# and the failing address to the routine that creates the new frame.
1834# FSLW:
1835# write = true
1836# size = byte
1837# TM = data
1838# software emulation error = true
1839movp_write_err:
1840 mov.l %a2,%a0 # pass failing address
1841 mov.l &0x00a10001,%d0 # pass fslw
1842 bra.l isp_dacc
1843
1844# FSLW:
1845# read = true
1846# size = byte
1847# TM = data
1848# software emulation error = true
1849movp_read_err:
1850 mov.l %a2,%a0 # pass failing address
1851 mov.l &0x01210001,%d0 # pass fslw
1852 bra.l isp_dacc
1853
1854#########################################################################
1855# XDEF **************************************************************** #
1856# _chk2_cmp2(): routine to emulate chk2/cmp2 instructions #
1857# #
1858# XREF **************************************************************** #
1859# _calc_ea(): calculate effective address #
1860# _dmem_read_long(): read operands #
1861# _dmem_read_word(): read operands #
1862# isp_dacc(): handle data access error exception #
1863# #
1864# INPUT *************************************************************** #
1865# none #
1866# #
1867# OUTPUT ************************************************************** #
1868# If exiting through isp_dacc... #
1869# a0 = failing address #
1870# d0 = FSLW #
1871# else #
1872# none #
1873# #
1874# ALGORITHM *********************************************************** #
1875# First, calculate the effective address, then fetch the byte, #
1876# word, or longword sized operands. Then, in the interest of #
1877# simplicity, all operands are converted to longword size whether the #
1878# operation is byte, word, or long. The bounds are sign extended #
1879# accordingly. If Rn is a data regsiter, Rn is also sign extended. If #
1880# Rn is an address register, it need not be sign extended since the #
1881# full register is always used. #
1882# The comparisons are made and the condition codes calculated. #
1883# If the instruction is chk2 and the Rn value is out-of-bounds, set #
1884# the ichk_flg in SPCOND_FLG. #
1885# If the memory fetch returns a failing value, pass the failing #
1886# address and FSLW to the isp_dacc() routine. #
1887# #
1888#########################################################################
1889
1890 global _chk2_cmp2
1891_chk2_cmp2:
1892
1893# passing size parameter doesn't matter since chk2 & cmp2 can't do
1894# either predecrement, postincrement, or immediate.
1895 bsr.l _calc_ea # calculate <ea>
1896
1897 mov.b EXC_EXTWORD(%a6), %d0 # fetch hi extension word
1898 rol.b &0x4, %d0 # rotate reg bits into lo
1899 and.w &0xf, %d0 # extract reg bits
1900
1901 mov.l (EXC_DREGS,%a6,%d0.w*4), %d2 # get regval
1902
1903 cmpi.b EXC_OPWORD(%a6), &0x2 # what size is operation?
1904 blt.b chk2_cmp2_byte # size == byte
1905 beq.b chk2_cmp2_word # size == word
1906
1907# the bounds are longword size. call routine to read the lower
1908# bound into d0 and the higher bound into d1.
1909chk2_cmp2_long:
1910 mov.l %a0,%a2 # save copy of <ea>
1911 bsr.l _dmem_read_long # fetch long lower bound
1912
1913 tst.l %d1 # dfetch error?
1914 bne.w chk2_cmp2_err_l # yes
1915
1916 mov.l %d0,%d3 # save long lower bound
1917 addq.l &0x4,%a2
1918 mov.l %a2,%a0 # pass <ea> of long upper bound
1919 bsr.l _dmem_read_long # fetch long upper bound
1920
1921 tst.l %d1 # dfetch error?
1922 bne.w chk2_cmp2_err_l # yes
1923
1924 mov.l %d0,%d1 # long upper bound in d1
1925 mov.l %d3,%d0 # long lower bound in d0
1926 bra.w chk2_cmp2_compare # go do the compare emulation
1927
1928# the bounds are word size. fetch them in one subroutine call by
1929# reading a longword. sign extend both. if it's a data operation,
1930# sign extend Rn to long, also.
1931chk2_cmp2_word:
1932 mov.l %a0,%a2
1933 bsr.l _dmem_read_long # fetch 2 word bounds
1934
1935 tst.l %d1 # dfetch error?
1936 bne.w chk2_cmp2_err_l # yes
1937
1938 mov.w %d0, %d1 # place hi in %d1
1939 swap %d0 # place lo in %d0
1940
1941 ext.l %d0 # sign extend lo bnd
1942 ext.l %d1 # sign extend hi bnd
1943
1944 btst &0x7, EXC_EXTWORD(%a6) # address compare?
1945 bne.w chk2_cmp2_compare # yes; don't sign extend
1946
1947# operation is a data register compare.
1948# sign extend word to long so we can do simple longword compares.
1949 ext.l %d2 # sign extend data word
1950 bra.w chk2_cmp2_compare # go emulate compare
1951
1952# the bounds are byte size. fetch them in one subroutine call by
1953# reading a word. sign extend both. if it's a data operation,
1954# sign extend Rn to long, also.
1955chk2_cmp2_byte:
1956 mov.l %a0,%a2
1957 bsr.l _dmem_read_word # fetch 2 byte bounds
1958
1959 tst.l %d1 # dfetch error?
1960 bne.w chk2_cmp2_err_w # yes
1961
1962 mov.b %d0, %d1 # place hi in %d1
1963 lsr.w &0x8, %d0 # place lo in %d0
1964
1965 extb.l %d0 # sign extend lo bnd
1966 extb.l %d1 # sign extend hi bnd
1967
1968 btst &0x7, EXC_EXTWORD(%a6) # address compare?
1969 bne.b chk2_cmp2_compare # yes; don't sign extend
1970
1971# operation is a data register compare.
1972# sign extend byte to long so we can do simple longword compares.
1973 extb.l %d2 # sign extend data byte
1974
1975#
1976# To set the ccodes correctly:
1977# (1) save 'Z' bit from (Rn - lo)
1978# (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
1979# (3) keep 'X', 'N', and 'V' from before instruction
1980# (4) combine ccodes
1981#
1982chk2_cmp2_compare:
1983 sub.l %d0, %d2 # (Rn - lo)
1984 mov.w %cc, %d3 # fetch resulting ccodes
1985 andi.b &0x4, %d3 # keep 'Z' bit
1986 sub.l %d0, %d1 # (hi - lo)
1987 cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi))
1988
1989 mov.w %cc, %d4 # fetch resulting ccodes
1990 or.b %d4, %d3 # combine w/ earlier ccodes
1991 andi.b &0x5, %d3 # keep 'Z' and 'N'
1992
1993 mov.w EXC_CC(%a6), %d4 # fetch old ccodes
1994 andi.b &0x1a, %d4 # keep 'X','N','V' bits
1995 or.b %d3, %d4 # insert new ccodes
1996 mov.w %d4, EXC_CC(%a6) # save new ccodes
1997
1998 btst &0x3, EXC_EXTWORD(%a6) # separate chk2,cmp2
1999 bne.b chk2_finish # it's a chk2
2000
2001 rts
2002
2003# this code handles the only difference between chk2 and cmp2. chk2 would
2004# have trapped out if the value was out of bounds. we check this by seeing
2005# if the 'N' bit was set by the operation.
2006chk2_finish:
2007 btst &0x0, %d4 # is 'N' bit set?
2008 bne.b chk2_trap # yes;chk2 should trap
2009 rts
2010chk2_trap:
2011 mov.b &ichk_flg,SPCOND_FLG(%a6) # set "special case" flag
2012 rts
2013
2014# if dmem_read_{long,word}() returns a fail message in d1, the package
2015# must create an access error frame. here, we pass a skeleton fslw
2016# and the failing address to the routine that creates the new frame.
2017# FSLW:
2018# read = true
2019# size = longword
2020# TM = data
2021# software emulation error = true
2022chk2_cmp2_err_l:
2023 mov.l %a2,%a0 # pass failing address
2024 mov.l &0x01010001,%d0 # pass fslw
2025 bra.l isp_dacc
2026
2027# FSLW:
2028# read = true
2029# size = word
2030# TM = data
2031# software emulation error = true
2032chk2_cmp2_err_w:
2033 mov.l %a2,%a0 # pass failing address
2034 mov.l &0x01410001,%d0 # pass fslw
2035 bra.l isp_dacc
2036
2037#########################################################################
2038# XDEF **************************************************************** #
2039# _div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq #
2040# 64/32->32r:32q #
2041# #
2042# XREF **************************************************************** #
2043# _calc_ea() - calculate effective address #
2044# isp_iacc() - handle instruction access error exception #
2045# isp_dacc() - handle data access error exception #
2046# isp_restore() - restore An on access error w/ -() or ()+ #
2047# #
2048# INPUT *************************************************************** #
2049# none #
2050# #
2051# OUTPUT ************************************************************** #
2052# If exiting through isp_dacc... #
2053# a0 = failing address #
2054# d0 = FSLW #
2055# else #
2056# none #
2057# #
2058# ALGORITHM *********************************************************** #
2059# First, decode the operand location. If it's in Dn, fetch from #
2060# the stack. If it's in memory, use _calc_ea() to calculate the #
2061# effective address. Use _dmem_read_long() to fetch at that address. #
2062# Unless the operand is immediate data. Then use _imem_read_long(). #
2063# Send failures to isp_dacc() or isp_iacc() as appropriate. #
2064# If the operands are signed, make them unsigned and save the #
2065# sign info for later. Separate out special cases like divide-by-zero #
2066# or 32-bit divides if possible. Else, use a special math algorithm #
2067# to calculate the result. #
2068# Restore sign info if signed instruction. Set the condition #
2069# codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the #
2070# quotient and remainder in the appropriate data registers on the stack.#
2071# #
2072#########################################################################
2073
2074set NDIVISOR, EXC_TEMP+0x0
2075set NDIVIDEND, EXC_TEMP+0x1
2076set NDRSAVE, EXC_TEMP+0x2
2077set NDQSAVE, EXC_TEMP+0x4
2078set DDSECOND, EXC_TEMP+0x6
2079set DDQUOTIENT, EXC_TEMP+0x8
2080set DDNORMAL, EXC_TEMP+0xc
2081
2082 global _div64
2083#############
2084# div(u,s)l #
2085#############
2086_div64:
2087 mov.b EXC_OPWORD+1(%a6), %d0
2088 andi.b &0x38, %d0 # extract src mode
2089
2090 bne.w dcontrolmodel_s # %dn dest or control mode?
2091
2092 mov.b EXC_OPWORD+1(%a6), %d0 # extract Dn from opcode
2093 andi.w &0x7, %d0
2094 mov.l (EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register
2095
2096dgotsrcl:
2097 beq.w div64eq0 # divisor is = 0!!!
2098
2099 mov.b EXC_EXTWORD+1(%a6), %d0 # extract Dr from extword
2100 mov.b EXC_EXTWORD(%a6), %d1 # extract Dq from extword
2101 and.w &0x7, %d0
2102 lsr.b &0x4, %d1
2103 and.w &0x7, %d1
2104 mov.w %d0, NDRSAVE(%a6) # save Dr for later
2105 mov.w %d1, NDQSAVE(%a6) # save Dq for later
2106
2107# fetch %dr and %dq directly off stack since all regs are saved there
2108 mov.l (EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi
2109 mov.l (EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo
2110
2111# separate signed and unsigned divide
2112 btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned?
2113 beq.b dspecialcases # use positive divide
2114
2115# save the sign of the divisor
2116# make divisor unsigned if it's negative
2117 tst.l %d7 # chk sign of divisor
2118 slt NDIVISOR(%a6) # save sign of divisor
2119 bpl.b dsgndividend
2120 neg.l %d7 # complement negative divisor
2121
2122# save the sign of the dividend
2123# make dividend unsigned if it's negative
2124dsgndividend:
2125 tst.l %d5 # chk sign of hi(dividend)
2126 slt NDIVIDEND(%a6) # save sign of dividend
2127 bpl.b dspecialcases
2128
2129 mov.w &0x0, %cc # clear 'X' cc bit
2130 negx.l %d6 # complement signed dividend
2131 negx.l %d5
2132
2133# extract some special cases:
2134# - is (dividend == 0) ?
2135# - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
2136dspecialcases:
2137 tst.l %d5 # is (hi(dividend) == 0)
2138 bne.b dnormaldivide # no, so try it the long way
2139
2140 tst.l %d6 # is (lo(dividend) == 0), too
2141 beq.w ddone # yes, so (dividend == 0)
2142
2143 cmp.l %d7,%d6 # is (divisor <= lo(dividend))
2144 bls.b d32bitdivide # yes, so use 32 bit divide
2145
2146 exg %d5,%d6 # q = 0, r = dividend
2147 bra.w divfinish # can't divide, we're done.
2148
2149d32bitdivide:
2150 tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div!
2151
2152 bra.b divfinish
2153
2154dnormaldivide:
2155# last special case:
2156# - is hi(dividend) >= divisor ? if yes, then overflow
2157 cmp.l %d7,%d5
2158 bls.b ddovf # answer won't fit in 32 bits
2159
2160# perform the divide algorithm:
2161 bsr.l dclassical # do int divide
2162
2163# separate into signed and unsigned finishes.
2164divfinish:
2165 btst &0x3, EXC_EXTWORD(%a6) # do divs, divu separately
2166 beq.b ddone # divu has no processing!!!
2167
2168# it was a divs.l, so ccode setting is a little more complicated...
2169 tst.b NDIVIDEND(%a6) # remainder has same sign
2170 beq.b dcc # as dividend.
2171 neg.l %d5 # sgn(rem) = sgn(dividend)
2172dcc:
2173 mov.b NDIVISOR(%a6), %d0
2174 eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative
2175 beq.b dqpos # branch to quot positive
2176
2177# 0x80000000 is the largest number representable as a 32-bit negative
2178# number. the negative of 0x80000000 is 0x80000000.
2179 cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits?
2180 bhi.b ddovf
2181
2182 neg.l %d6 # make (-quot) 2's comp
2183
2184 bra.b ddone
2185
2186dqpos:
2187 btst &0x1f, %d6 # will (+quot) fit in 32 bits?
2188 bne.b ddovf
2189
2190ddone:
2191# at this point, result is normal so ccodes are set based on result.
2192 mov.w EXC_CC(%a6), %cc
2193 tst.l %d6 # set %ccode bits
2194 mov.w %cc, EXC_CC(%a6)
2195
2196 mov.w NDRSAVE(%a6), %d0 # get Dr off stack
2197 mov.w NDQSAVE(%a6), %d1 # get Dq off stack
2198
2199# if the register numbers are the same, only the quotient gets saved.
2200# so, if we always save the quotient second, we save ourselves a cmp&beq
2201 mov.l %d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder
2202 mov.l %d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient
2203
2204 rts
2205
2206ddovf:
2207 bset &0x1, EXC_CC+1(%a6) # 'V' set on overflow
2208 bclr &0x0, EXC_CC+1(%a6) # 'C' cleared on overflow
2209
2210 rts
2211
2212div64eq0:
2213 andi.b &0x1e, EXC_CC+1(%a6) # clear 'C' bit on divbyzero
2214 ori.b &idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag
2215 rts
2216
2217###########################################################################
2218#########################################################################
2219# This routine uses the 'classical' Algorithm D from Donald Knuth's #
2220# Art of Computer Programming, vol II, Seminumerical Algorithms. #
2221# For this implementation b=2**16, and the target is U1U2U3U4/V1V2, #
2222# where U,V are words of the quadword dividend and longword divisor, #
2223# and U1, V1 are the most significant words. #
2224# #
2225# The most sig. longword of the 64 bit dividend must be in %d5, least #
2226# in %d6. The divisor must be in the variable ddivisor, and the #
2227# signed/unsigned flag ddusign must be set (0=unsigned,1=signed). #
2228# The quotient is returned in %d6, remainder in %d5, unless the #
2229# v (overflow) bit is set in the saved %ccr. If overflow, the dividend #
2230# is unchanged. #
2231#########################################################################
2232dclassical:
2233# if the divisor msw is 0, use simpler algorithm then the full blown
2234# one at ddknuth:
2235
2236 cmpi.l %d7, &0xffff
2237 bhi.b ddknuth # go use D. Knuth algorithm
2238
2239# Since the divisor is only a word (and larger than the mslw of the dividend),
2240# a simpler algorithm may be used :
2241# In the general case, four quotient words would be created by
2242# dividing the divisor word into each dividend word. In this case,
2243# the first two quotient words must be zero, or overflow would occur.
2244# Since we already checked this case above, we can treat the most significant
2245# longword of the dividend as (0) remainder (see Knuth) and merely complete
2246# the last two divisions to get a quotient longword and word remainder:
2247
2248 clr.l %d1
2249 swap %d5 # same as r*b if previous step rqd
2250 swap %d6 # get u3 to lsw position
2251 mov.w %d6, %d5 # rb + u3
2252
2253 divu.w %d7, %d5
2254
2255 mov.w %d5, %d1 # first quotient word
2256 swap %d6 # get u4
2257 mov.w %d6, %d5 # rb + u4
2258
2259 divu.w %d7, %d5
2260
2261 swap %d1
2262 mov.w %d5, %d1 # 2nd quotient 'digit'
2263 clr.w %d5
2264 swap %d5 # now remainder
2265 mov.l %d1, %d6 # and quotient
2266
2267 rts
2268
2269ddknuth:
2270# In this algorithm, the divisor is treated as a 2 digit (word) number
2271# which is divided into a 3 digit (word) dividend to get one quotient
2272# digit (word). After subtraction, the dividend is shifted and the
2273# process repeated. Before beginning, the divisor and quotient are
2274# 'normalized' so that the process of estimating the quotient digit
2275# will yield verifiably correct results..
2276
2277 clr.l DDNORMAL(%a6) # count of shifts for normalization
2278 clr.b DDSECOND(%a6) # clear flag for quotient digits
2279 clr.l %d1 # %d1 will hold trial quotient
2280ddnchk:
2281 btst &31, %d7 # must we normalize? first word of
2282 bne.b ddnormalized # divisor (V1) must be >= 65536/2
2283 addq.l &0x1, DDNORMAL(%a6) # count normalization shifts
2284 lsl.l &0x1, %d7 # shift the divisor
2285 lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2
2286 roxl.l &0x1, %d5 # shift u1,u2
2287 bra.w ddnchk
2288ddnormalized:
2289
2290# Now calculate an estimate of the quotient words (msw first, then lsw).
2291# The comments use subscripts for the first quotient digit determination.
2292 mov.l %d7, %d3 # divisor
2293 mov.l %d5, %d2 # dividend mslw
2294 swap %d2
2295 swap %d3
2296 cmp.w %d2, %d3 # V1 = U1 ?
2297 bne.b ddqcalc1
2298 mov.w &0xffff, %d1 # use max trial quotient word
2299 bra.b ddadj0
2300ddqcalc1:
2301 mov.l %d5, %d1
2302
2303 divu.w %d3, %d1 # use quotient of mslw/msw
2304
2305 andi.l &0x0000ffff, %d1 # zero any remainder
2306ddadj0:
2307
2308# now test the trial quotient and adjust. This step plus the
2309# normalization assures (according to Knuth) that the trial
2310# quotient will be at worst 1 too large.
2311 mov.l %d6, -(%sp)
2312 clr.w %d6 # word u3 left
2313 swap %d6 # in lsw position
2314ddadj1: mov.l %d7, %d3
2315 mov.l %d1, %d2
2316 mulu.w %d7, %d2 # V2q
2317 swap %d3
2318 mulu.w %d1, %d3 # V1q
2319 mov.l %d5, %d4 # U1U2
2320 sub.l %d3, %d4 # U1U2 - V1q
2321
2322 swap %d4
2323
2324 mov.w %d4,%d0
2325 mov.w %d6,%d4 # insert lower word (U3)
2326
2327 tst.w %d0 # is upper word set?
2328 bne.w ddadjd1
2329
2330# add.l %d6, %d4 # (U1U2 - V1q) + U3
2331
2332 cmp.l %d2, %d4
2333 bls.b ddadjd1 # is V2q > (U1U2-V1q) + U3 ?
2334 subq.l &0x1, %d1 # yes, decrement and recheck
2335 bra.b ddadj1
2336ddadjd1:
2337# now test the word by multiplying it by the divisor (V1V2) and comparing
2338# the 3 digit (word) result with the current dividend words
2339 mov.l %d5, -(%sp) # save %d5 (%d6 already saved)
2340 mov.l %d1, %d6
2341 swap %d6 # shift answer to ms 3 words
2342 mov.l %d7, %d5
2343 bsr.l dmm2
2344 mov.l %d5, %d2 # now %d2,%d3 are trial*divisor
2345 mov.l %d6, %d3
2346 mov.l (%sp)+, %d5 # restore dividend
2347 mov.l (%sp)+, %d6
2348 sub.l %d3, %d6
2349 subx.l %d2, %d5 # subtract double precision
2350 bcc dd2nd # no carry, do next quotient digit
2351 subq.l &0x1, %d1 # q is one too large
2352# need to add back divisor longword to current ms 3 digits of dividend
2353# - according to Knuth, this is done only 2 out of 65536 times for random
2354# divisor, dividend selection.
2355 clr.l %d2
2356 mov.l %d7, %d3
2357 swap %d3
2358 clr.w %d3 # %d3 now ls word of divisor
2359 add.l %d3, %d6 # aligned with 3rd word of dividend
2360 addx.l %d2, %d5
2361 mov.l %d7, %d3
2362 clr.w %d3 # %d3 now ms word of divisor
2363 swap %d3 # aligned with 2nd word of dividend
2364 add.l %d3, %d5
2365dd2nd:
2366 tst.b DDSECOND(%a6) # both q words done?
2367 bne.b ddremain
2368# first quotient digit now correct. store digit and shift the
2369# (subtracted) dividend
2370 mov.w %d1, DDQUOTIENT(%a6)
2371 clr.l %d1
2372 swap %d5
2373 swap %d6
2374 mov.w %d6, %d5
2375 clr.w %d6
2376 st DDSECOND(%a6) # second digit
2377 bra.w ddnormalized
2378ddremain:
2379# add 2nd word to quotient, get the remainder.
2380 mov.w %d1, DDQUOTIENT+2(%a6)
2381# shift down one word/digit to renormalize remainder.
2382 mov.w %d5, %d6
2383 swap %d6
2384 swap %d5
2385 mov.l DDNORMAL(%a6), %d7 # get norm shift count
2386 beq.b ddrn
2387 subq.l &0x1, %d7 # set for loop count
2388ddnlp:
2389 lsr.l &0x1, %d5 # shift into %d6
2390 roxr.l &0x1, %d6
2391 dbf %d7, ddnlp
2392ddrn:
2393 mov.l %d6, %d5 # remainder
2394 mov.l DDQUOTIENT(%a6), %d6 # quotient
2395
2396 rts
2397dmm2:
2398# factors for the 32X32->64 multiplication are in %d5 and %d6.
2399# returns 64 bit result in %d5 (hi) %d6(lo).
2400# destroys %d2,%d3,%d4.
2401
2402# multiply hi,lo words of each factor to get 4 intermediate products
2403 mov.l %d6, %d2
2404 mov.l %d6, %d3
2405 mov.l %d5, %d4
2406 swap %d3
2407 swap %d4
2408 mulu.w %d5, %d6 # %d6 <- lsw*lsw
2409 mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source
2410 mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest
2411 mulu.w %d4, %d3 # %d3 <- msw*msw
2412# now use swap and addx to consolidate to two longwords
2413 clr.l %d4
2414 swap %d6
2415 add.w %d5, %d6 # add msw of l*l to lsw of m*l product
2416 addx.w %d4, %d3 # add any carry to m*m product
2417 add.w %d2, %d6 # add in lsw of other m*l product
2418 addx.w %d4, %d3 # add any carry to m*m product
2419 swap %d6 # %d6 is low 32 bits of final product
2420 clr.w %d5
2421 clr.w %d2 # lsw of two mixed products used,
2422 swap %d5 # now use msws of longwords
2423 swap %d2
2424 add.l %d2, %d5
2425 add.l %d3, %d5 # %d5 now ms 32 bits of final product
2426 rts
2427
2428##########
2429dcontrolmodel_s:
2430 movq.l &LONG,%d0
2431 bsr.l _calc_ea # calc <ea>
2432
2433 cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
2434 beq.b dimmed # yes
2435
2436 mov.l %a0,%a2
2437 bsr.l _dmem_read_long # fetch divisor from <ea>
2438
2439 tst.l %d1 # dfetch error?
2440 bne.b div64_err # yes
2441
2442 mov.l %d0, %d7
2443 bra.w dgotsrcl
2444
2445# we have to split out immediate data here because it must be read using
2446# imem_read() instead of dmem_read(). this becomes especially important
2447# if the fetch runs into some deadly fault.
2448dimmed:
2449 addq.l &0x4,EXC_EXTWPTR(%a6)
2450 bsr.l _imem_read_long # read immediate value
2451
2452 tst.l %d1 # ifetch error?
2453 bne.l isp_iacc # yes
2454
2455 mov.l %d0,%d7
2456 bra.w dgotsrcl
2457
2458##########
2459
2460# if dmem_read_long() returns a fail message in d1, the package
2461# must create an access error frame. here, we pass a skeleton fslw
2462# and the failing address to the routine that creates the new frame.
2463# also, we call isp_restore in case the effective addressing mode was
2464# (an)+ or -(an) in which case the previous "an" value must be restored.
2465# FSLW:
2466# read = true
2467# size = longword
2468# TM = data
2469# software emulation error = true
2470div64_err:
2471 bsr.l isp_restore # restore addr reg
2472 mov.l %a2,%a0 # pass failing address
2473 mov.l &0x01010001,%d0 # pass fslw
2474 bra.l isp_dacc
2475
2476#########################################################################
2477# XDEF **************************************************************** #
2478# _mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64 #
2479# #
2480# XREF **************************************************************** #
2481# _calc_ea() - calculate effective address #
2482# isp_iacc() - handle instruction access error exception #
2483# isp_dacc() - handle data access error exception #
2484# isp_restore() - restore An on access error w/ -() or ()+ #
2485# #
2486# INPUT *************************************************************** #
2487# none #
2488# #
2489# OUTPUT ************************************************************** #
2490# If exiting through isp_dacc... #
2491# a0 = failing address #
2492# d0 = FSLW #
2493# else #
2494# none #
2495# #
2496# ALGORITHM *********************************************************** #
2497# First, decode the operand location. If it's in Dn, fetch from #
2498# the stack. If it's in memory, use _calc_ea() to calculate the #
2499# effective address. Use _dmem_read_long() to fetch at that address. #
2500# Unless the operand is immediate data. Then use _imem_read_long(). #
2501# Send failures to isp_dacc() or isp_iacc() as appropriate. #
2502# If the operands are signed, make them unsigned and save the #
2503# sign info for later. Perform the multiplication using 16x16->32 #
2504# unsigned multiplies and "add" instructions. Store the high and low #
2505# portions of the result in the appropriate data registers on the #
2506# stack. Calculate the condition codes, also. #
2507# #
2508#########################################################################
2509
2510#############
2511# mul(u,s)l #
2512#############
2513 global _mul64
2514_mul64:
2515 mov.b EXC_OPWORD+1(%a6), %d0 # extract src {mode,reg}
2516 cmpi.b %d0, &0x7 # is src mode Dn or other?
2517 bgt.w mul64_memop # src is in memory
2518
2519# multiplier operand in the data register file.
2520# must extract the register number and fetch the operand from the stack.
2521mul64_regop:
2522 andi.w &0x7, %d0 # extract Dn
2523 mov.l (EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier
2524
2525# multiplier is in %d3. now, extract Dl and Dh fields and fetch the
2526# multiplicand from the data register specified by Dl.
2527mul64_multiplicand:
2528 mov.w EXC_EXTWORD(%a6), %d2 # fetch ext word
2529 clr.w %d1 # clear Dh reg
2530 mov.b %d2, %d1 # grab Dh
2531 rol.w &0x4, %d2 # align Dl byte
2532 andi.w &0x7, %d2 # extract Dl
2533
2534 mov.l (EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand
2535
2536# check for the case of "zero" result early
2537 tst.l %d4 # test multiplicand
2538 beq.w mul64_zero # handle zero separately
2539 tst.l %d3 # test multiplier
2540 beq.w mul64_zero # handle zero separately
2541
2542# multiplier is in %d3 and multiplicand is in %d4.
2543# if the operation is to be signed, then the operands are converted
2544# to unsigned and the result sign is saved for the end.
2545 clr.b EXC_TEMP(%a6) # clear temp space
2546 btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned?
2547 beq.b mul64_alg # unsigned; skip sgn calc
2548
2549 tst.l %d3 # is multiplier negative?
2550 bge.b mul64_chk_md_sgn # no
2551 neg.l %d3 # make multiplier positive
2552 ori.b &0x1, EXC_TEMP(%a6) # save multiplier sgn
2553
2554# the result sign is the exclusive or of the operand sign bits.
2555mul64_chk_md_sgn:
2556 tst.l %d4 # is multiplicand negative?
2557 bge.b mul64_alg # no
2558 neg.l %d4 # make multiplicand positive
2559 eori.b &0x1, EXC_TEMP(%a6) # calculate correct sign
2560
2561#########################################################################
2562# 63 32 0 #
2563# ---------------------------- #
2564# | hi(mplier) * hi(mplicand)| #
2565# ---------------------------- #
2566# ----------------------------- #
2567# | hi(mplier) * lo(mplicand) | #
2568# ----------------------------- #
2569# ----------------------------- #
2570# | lo(mplier) * hi(mplicand) | #
2571# ----------------------------- #
2572# | ----------------------------- #
2573# --|-- | lo(mplier) * lo(mplicand) | #
2574# | ----------------------------- #
2575# ======================================================== #
2576# -------------------------------------------------------- #
2577# | hi(result) | lo(result) | #
2578# -------------------------------------------------------- #
2579#########################################################################
2580mul64_alg:
2581# load temp registers with operands
2582 mov.l %d3, %d5 # mr in %d5
2583 mov.l %d3, %d6 # mr in %d6
2584 mov.l %d4, %d7 # md in %d7
2585 swap %d6 # hi(mr) in lo %d6
2586 swap %d7 # hi(md) in lo %d7
2587
2588# complete necessary multiplies:
2589 mulu.w %d4, %d3 # [1] lo(mr) * lo(md)
2590 mulu.w %d6, %d4 # [2] hi(mr) * lo(md)
2591 mulu.w %d7, %d5 # [3] lo(mr) * hi(md)
2592 mulu.w %d7, %d6 # [4] hi(mr) * hi(md)
2593
2594# add lo portions of [2],[3] to hi portion of [1].
2595# add carries produced from these adds to [4].
2596# lo([1]) is the final lo 16 bits of the result.
2597 clr.l %d7 # load %d7 w/ zero value
2598 swap %d3 # hi([1]) <==> lo([1])
2599 add.w %d4, %d3 # hi([1]) + lo([2])
2600 addx.l %d7, %d6 # [4] + carry
2601 add.w %d5, %d3 # hi([1]) + lo([3])
2602 addx.l %d7, %d6 # [4] + carry
2603 swap %d3 # lo([1]) <==> hi([1])
2604
2605# lo portions of [2],[3] have been added in to final result.
2606# now, clear lo, put hi in lo reg, and add to [4]
2607 clr.w %d4 # clear lo([2])
2608 clr.w %d5 # clear hi([3])
2609 swap %d4 # hi([2]) in lo %d4
2610 swap %d5 # hi([3]) in lo %d5
2611 add.l %d5, %d4 # [4] + hi([2])
2612 add.l %d6, %d4 # [4] + hi([3])
2613
2614# unsigned result is now in {%d4,%d3}
2615 tst.b EXC_TEMP(%a6) # should result be signed?
2616 beq.b mul64_done # no
2617
2618# result should be a signed negative number.
2619# compute 2's complement of the unsigned number:
2620# -negate all bits and add 1
2621mul64_neg:
2622 not.l %d3 # negate lo(result) bits
2623 not.l %d4 # negate hi(result) bits
2624 addq.l &1, %d3 # add 1 to lo(result)
2625 addx.l %d7, %d4 # add carry to hi(result)
2626
2627# the result is saved to the register file.
2628# for '040 compatibility, if Dl == Dh then only the hi(result) is
2629# saved. so, saving hi after lo accomplishes this without need to
2630# check Dl,Dh equality.
2631mul64_done:
2632 mov.l %d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
2633 mov.w &0x0, %cc
2634 mov.l %d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
2635
2636# now, grab the condition codes. only one that can be set is 'N'.
2637# 'N' CAN be set if the operation is unsigned if bit 63 is set.
2638 mov.w %cc, %d7 # fetch %ccr to see if 'N' set
2639 andi.b &0x8, %d7 # extract 'N' bit
2640
2641mul64_ccode_set:
2642 mov.b EXC_CC+1(%a6), %d6 # fetch previous %ccr
2643 andi.b &0x10, %d6 # all but 'X' bit changes
2644
2645 or.b %d7, %d6 # group 'X' and 'N'
2646 mov.b %d6, EXC_CC+1(%a6) # save new %ccr
2647
2648 rts
2649
2650# one or both of the operands is zero so the result is also zero.
2651# save the zero result to the register file and set the 'Z' ccode bit.
2652mul64_zero:
2653 clr.l (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
2654 clr.l (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
2655
2656 movq.l &0x4, %d7 # set 'Z' ccode bit
2657 bra.b mul64_ccode_set # finish ccode set
2658
2659##########
2660
2661# multiplier operand is in memory at the effective address.
2662# must calculate the <ea> and go fetch the 32-bit operand.
2663mul64_memop:
2664 movq.l &LONG, %d0 # pass # of bytes
2665 bsr.l _calc_ea # calculate <ea>
2666
2667 cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
2668 beq.b mul64_immed # yes
2669
2670 mov.l %a0,%a2
2671 bsr.l _dmem_read_long # fetch src from addr (%a0)
2672
2673 tst.l %d1 # dfetch error?
2674 bne.w mul64_err # yes
2675
2676 mov.l %d0, %d3 # store multiplier in %d3
2677
2678 bra.w mul64_multiplicand
2679
2680# we have to split out immediate data here because it must be read using
2681# imem_read() instead of dmem_read(). this becomes especially important
2682# if the fetch runs into some deadly fault.
2683mul64_immed:
2684 addq.l &0x4,EXC_EXTWPTR(%a6)
2685 bsr.l _imem_read_long # read immediate value
2686
2687 tst.l %d1 # ifetch error?
2688 bne.l isp_iacc # yes
2689
2690 mov.l %d0,%d3
2691 bra.w mul64_multiplicand
2692
2693##########
2694
2695# if dmem_read_long() returns a fail message in d1, the package
2696# must create an access error frame. here, we pass a skeleton fslw
2697# and the failing address to the routine that creates the new frame.
2698# also, we call isp_restore in case the effective addressing mode was
2699# (an)+ or -(an) in which case the previous "an" value must be restored.
2700# FSLW:
2701# read = true
2702# size = longword
2703# TM = data
2704# software emulation error = true
2705mul64_err:
2706 bsr.l isp_restore # restore addr reg
2707 mov.l %a2,%a0 # pass failing address
2708 mov.l &0x01010001,%d0 # pass fslw
2709 bra.l isp_dacc
2710
2711#########################################################################
2712# XDEF **************************************************************** #
2713# _compandset2(): routine to emulate cas2() #
2714# (internal to package) #
2715# #
2716# _isp_cas2_finish(): store ccodes, store compare regs #
2717# (external to package) #
2718# #
2719# XREF **************************************************************** #
2720# _real_lock_page() - "callout" to lock op's page from page-outs #
2721# _cas_terminate2() - access error exit #
2722# _real_cas2() - "callout" to core cas2 emulation code #
2723# _real_unlock_page() - "callout" to unlock page #
2724# #
2725# INPUT *************************************************************** #
2726# _compandset2(): #
2727# d0 = instruction extension word #
2728# #
2729# _isp_cas2_finish(): #
2730# see cas2 core emulation code #
2731# #
2732# OUTPUT ************************************************************** #
2733# _compandset2(): #
2734# see cas2 core emulation code #
2735# #
2736# _isp_cas_finish(): #
2737# None (register file or memroy changed as appropriate) #
2738# #
2739# ALGORITHM *********************************************************** #
2740# compandset2(): #
2741# Decode the instruction and fetch the appropriate Update and #
2742# Compare operands. Then call the "callout" _real_lock_page() for each #
2743# memory operand address so that the operating system can keep these #
2744# pages from being paged out. If either _real_lock_page() fails, exit #
2745# through _cas_terminate2(). Don't forget to unlock the 1st locked page #
2746# using _real_unlock_paged() if the 2nd lock-page fails. #
2747# Finally, branch to the core cas2 emulation code by calling the #
2748# "callout" _real_cas2(). #
2749# #
2750# _isp_cas2_finish(): #
2751# Re-perform the comparison so we can determine the condition #
2752# codes which were too much trouble to keep around during the locked #
2753# emulation. Then unlock each operands page by calling the "callout" #
2754# _real_unlock_page(). #
2755# #
2756#########################################################################
2757
2758set ADDR1, EXC_TEMP+0xc
2759set ADDR2, EXC_TEMP+0x0
2760set DC2, EXC_TEMP+0xa
2761set DC1, EXC_TEMP+0x8
2762
2763 global _compandset2
2764_compandset2:
2765 mov.l %d0,EXC_TEMP+0x4(%a6) # store for possible restart
2766 mov.l %d0,%d1 # extension word in d0
2767
2768 rol.w &0x4,%d0
2769 andi.w &0xf,%d0 # extract Rn2
2770 mov.l (EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2
2771 mov.l %a1,ADDR2(%a6)
2772
2773 mov.l %d1,%d0
2774
2775 lsr.w &0x6,%d1
2776 andi.w &0x7,%d1 # extract Du2
2777 mov.l (EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op
2778
2779 andi.w &0x7,%d0 # extract Dc2
2780 mov.l (EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op
2781 mov.w %d0,DC2(%a6)
2782
2783 mov.w EXC_EXTWORD(%a6),%d0
2784 mov.l %d0,%d1
2785
2786 rol.w &0x4,%d0
2787 andi.w &0xf,%d0 # extract Rn1
2788 mov.l (EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1
2789 mov.l %a0,ADDR1(%a6)
2790
2791 mov.l %d1,%d0
2792
2793 lsr.w &0x6,%d1
2794 andi.w &0x7,%d1 # extract Du1
2795 mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op
2796
2797 andi.w &0x7,%d0 # extract Dc1
2798 mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op
2799 mov.w %d0,DC1(%a6)
2800
2801 btst &0x1,EXC_OPWORD(%a6) # word or long?
2802 sne %d7
2803
2804 btst &0x5,EXC_ISR(%a6) # user or supervisor?
2805 sne %d6
2806
2807 mov.l %a0,%a2
2808 mov.l %a1,%a3
2809
2810 mov.l %d7,%d1 # pass size
2811 mov.l %d6,%d0 # pass mode
2812 bsr.l _real_lock_page # lock page
2813 mov.l %a2,%a0
2814 tst.l %d0 # error?
2815 bne.l _cas_terminate2 # yes
2816
2817 mov.l %d7,%d1 # pass size
2818 mov.l %d6,%d0 # pass mode
2819 mov.l %a3,%a0 # pass addr
2820 bsr.l _real_lock_page # lock page
2821 mov.l %a3,%a0
2822 tst.l %d0 # error?
2823 bne.b cas_preterm # yes
2824
2825 mov.l %a2,%a0
2826 mov.l %a3,%a1
2827
2828 bra.l _real_cas2
2829
2830# if the 2nd lock attempt fails, then we must still unlock the
2831# first page(s).
2832cas_preterm:
2833 mov.l %d0,-(%sp) # save FSLW
2834 mov.l %d7,%d1 # pass size
2835 mov.l %d6,%d0 # pass mode
2836 mov.l %a2,%a0 # pass ADDR1
2837 bsr.l _real_unlock_page # unlock first page(s)
2838 mov.l (%sp)+,%d0 # restore FSLW
2839 mov.l %a3,%a0 # pass failing addr
2840 bra.l _cas_terminate2
2841
2842#############################################################
2843
2844 global _isp_cas2_finish
2845_isp_cas2_finish:
2846 btst &0x1,EXC_OPWORD(%a6)
2847 bne.b cas2_finish_l
2848
2849 mov.w EXC_CC(%a6),%cc # load old ccodes
2850 cmp.w %d0,%d2
2851 bne.b cas2_finish_w_save
2852 cmp.w %d1,%d3
2853cas2_finish_w_save:
2854 mov.w %cc,EXC_CC(%a6) # save new ccodes
2855
2856 tst.b %d4 # update compare reg?
2857 bne.b cas2_finish_w_done # no
2858
2859 mov.w DC2(%a6),%d3 # fetch Dc2
2860 mov.w %d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
2861
2862 mov.w DC1(%a6),%d2 # fetch Dc1
2863 mov.w %d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
2864
2865cas2_finish_w_done:
2866 btst &0x5,EXC_ISR(%a6)
2867 sne %d2
2868 mov.l %d2,%d0 # pass mode
2869 sf %d1 # pass size
2870 mov.l ADDR1(%a6),%a0 # pass ADDR1
2871 bsr.l _real_unlock_page # unlock page
2872
2873 mov.l %d2,%d0 # pass mode
2874 sf %d1 # pass size
2875 mov.l ADDR2(%a6),%a0 # pass ADDR2
2876 bsr.l _real_unlock_page # unlock page
2877 rts
2878
2879cas2_finish_l:
2880 mov.w EXC_CC(%a6),%cc # load old ccodes
2881 cmp.l %d0,%d2
2882 bne.b cas2_finish_l_save
2883 cmp.l %d1,%d3
2884cas2_finish_l_save:
2885 mov.w %cc,EXC_CC(%a6) # save new ccodes
2886
2887 tst.b %d4 # update compare reg?
2888 bne.b cas2_finish_l_done # no
2889
2890 mov.w DC2(%a6),%d3 # fetch Dc2
2891 mov.l %d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
2892
2893 mov.w DC1(%a6),%d2 # fetch Dc1
2894 mov.l %d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
2895
2896cas2_finish_l_done:
2897 btst &0x5,EXC_ISR(%a6)
2898 sne %d2
2899 mov.l %d2,%d0 # pass mode
2900 st %d1 # pass size
2901 mov.l ADDR1(%a6),%a0 # pass ADDR1
2902 bsr.l _real_unlock_page # unlock page
2903
2904 mov.l %d2,%d0 # pass mode
2905 st %d1 # pass size
2906 mov.l ADDR2(%a6),%a0 # pass ADDR2
2907 bsr.l _real_unlock_page # unlock page
2908 rts
2909
2910########
2911 global cr_cas2
2912cr_cas2:
2913 mov.l EXC_TEMP+0x4(%a6),%d0
2914 bra.w _compandset2
2915
2916#########################################################################
2917# XDEF **************************************************************** #
2918# _compandset(): routine to emulate cas w/ misaligned <ea> #
2919# (internal to package) #
2920# _isp_cas_finish(): routine called when cas emulation completes #
2921# (external and internal to package) #
2922# _isp_cas_restart(): restart cas emulation after a fault #
2923# (external to package) #
2924# _isp_cas_terminate(): create access error stack frame on fault #
2925# (external and internal to package) #
2926# _isp_cas_inrange(): checks whether instr addess is within range #
2927# of core cas/cas2emulation code #
2928# (external to package) #
2929# #
2930# XREF **************************************************************** #
2931# _calc_ea(): calculate effective address #
2932# #
2933# INPUT *************************************************************** #
2934# compandset(): #
2935# none #
2936# _isp_cas_restart(): #
2937# d6 = previous sfc/dfc #
2938# _isp_cas_finish(): #
2939# _isp_cas_terminate(): #
2940# a0 = failing address #
2941# d0 = FSLW #
2942# d6 = previous sfc/dfc #
2943# _isp_cas_inrange(): #
2944# a0 = instruction address to be checked #
2945# #
2946# OUTPUT ************************************************************** #
2947# compandset(): #
2948# none #
2949# _isp_cas_restart(): #
2950# a0 = effective address #
2951# d7 = word or longword flag #
2952# _isp_cas_finish(): #
2953# a0 = effective address #
2954# _isp_cas_terminate(): #
2955# initial register set before emulation exception #
2956# _isp_cas_inrange(): #
2957# d0 = 0 => in range; -1 => out of range #
2958# #
2959# ALGORITHM *********************************************************** #
2960# #
2961# compandset(): #
2962# First, calculate the effective address. Then, decode the #
2963# instruction word and fetch the "compare" (DC) and "update" (Du) #
2964# operands. #
2965# Next, call the external routine _real_lock_page() so that the #
2966# operating system can keep this page from being paged out while we're #
2967# in this routine. If this call fails, jump to _cas_terminate2(). #
2968# The routine then branches to _real_cas(). This external routine #
2969# that actually emulates cas can be supplied by the external os or #
2970# made to point directly back into the 060ISP which has a routine for #
2971# this purpose. #
2972# #
2973# _isp_cas_finish(): #
2974# Either way, after emulation, the package is re-entered at #
2975# _isp_cas_finish(). This routine re-compares the operands in order to #
2976# set the condition codes. Finally, these routines will call #
2977# _real_unlock_page() in order to unlock the pages that were previously #
2978# locked. #
2979# #
2980# _isp_cas_restart(): #
2981# This routine can be entered from an access error handler where #
2982# the emulation sequence should be re-started from the beginning. #
2983# #
2984# _isp_cas_terminate(): #
2985# This routine can be entered from an access error handler where #
2986# an emulation operand access failed and the operating system would #
2987# like an access error stack frame created instead of the current #
2988# unimplemented integer instruction frame. #
2989# Also, the package enters here if a call to _real_lock_page() #
2990# fails. #
2991# #
2992# _isp_cas_inrange(): #
2993# Checks to see whether the instruction address passed to it in #
2994# a0 is within the software package cas/cas2 emulation routines. This #
2995# can be helpful for an operating system to determine whether an access #
2996# error during emulation was due to a cas/cas2 emulation access. #
2997# #
2998#########################################################################
2999
3000set DC, EXC_TEMP+0x8
3001set ADDR, EXC_TEMP+0x4
3002
3003 global _compandset
3004_compandset:
3005 btst &0x1,EXC_OPWORD(%a6) # word or long operation?
3006 bne.b compandsetl # long
3007
3008compandsetw:
3009 movq.l &0x2,%d0 # size = 2 bytes
3010 bsr.l _calc_ea # a0 = calculated <ea>
3011 mov.l %a0,ADDR(%a6) # save <ea> for possible restart
3012 sf %d7 # clear d7 for word size
3013 bra.b compandsetfetch
3014
3015compandsetl:
3016 movq.l &0x4,%d0 # size = 4 bytes
3017 bsr.l _calc_ea # a0 = calculated <ea>
3018 mov.l %a0,ADDR(%a6) # save <ea> for possible restart
3019 st %d7 # set d7 for longword size
3020
3021compandsetfetch:
3022 mov.w EXC_EXTWORD(%a6),%d0 # fetch cas extension word
3023 mov.l %d0,%d1 # make a copy
3024
3025 lsr.w &0x6,%d0
3026 andi.w &0x7,%d0 # extract Du
3027 mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand
3028
3029 andi.w &0x7,%d1 # extract Dc
3030 mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand
3031 mov.w %d1,DC(%a6) # save Dc
3032
3033 btst &0x5,EXC_ISR(%a6) # which mode for exception?
3034 sne %d6 # set on supervisor mode
3035
3036 mov.l %a0,%a2 # save temporarily
3037 mov.l %d7,%d1 # pass size
3038 mov.l %d6,%d0 # pass mode
3039 bsr.l _real_lock_page # lock page
3040 tst.l %d0 # did error occur?
3041 bne.w _cas_terminate2 # yes, clean up the mess
3042 mov.l %a2,%a0 # pass addr in a0
3043
3044 bra.l _real_cas
3045
3046########
3047 global _isp_cas_finish
3048_isp_cas_finish:
3049 btst &0x1,EXC_OPWORD(%a6)
3050 bne.b cas_finish_l
3051
3052# just do the compare again since it's faster than saving the ccodes
3053# from the locked routine...
3054cas_finish_w:
3055 mov.w EXC_CC(%a6),%cc # restore cc
3056 cmp.w %d0,%d4 # do word compare
3057 mov.w %cc,EXC_CC(%a6) # save cc
3058
3059 tst.b %d1 # update compare reg?
3060 bne.b cas_finish_w_done # no
3061
3062 mov.w DC(%a6),%d3
3063 mov.w %d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination
3064
3065cas_finish_w_done:
3066 mov.l ADDR(%a6),%a0 # pass addr
3067 sf %d1 # pass size
3068 btst &0x5,EXC_ISR(%a6)
3069 sne %d0 # pass mode
3070 bsr.l _real_unlock_page # unlock page
3071 rts
3072
3073# just do the compare again since it's faster than saving the ccodes
3074# from the locked routine...
3075cas_finish_l:
3076 mov.w EXC_CC(%a6),%cc # restore cc
3077 cmp.l %d0,%d4 # do longword compare
3078 mov.w %cc,EXC_CC(%a6) # save cc
3079
3080 tst.b %d1 # update compare reg?
3081 bne.b cas_finish_l_done # no
3082
3083 mov.w DC(%a6),%d3
3084 mov.l %d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination
3085
3086cas_finish_l_done:
3087 mov.l ADDR(%a6),%a0 # pass addr
3088 st %d1 # pass size
3089 btst &0x5,EXC_ISR(%a6)
3090 sne %d0 # pass mode
3091 bsr.l _real_unlock_page # unlock page
3092 rts
3093
3094########
3095
3096 global _isp_cas_restart
3097_isp_cas_restart:
3098 mov.l %d6,%sfc # restore previous sfc
3099 mov.l %d6,%dfc # restore previous dfc
3100
3101 cmpi.b EXC_OPWORD+1(%a6),&0xfc # cas or cas2?
3102 beq.l cr_cas2 # cas2
3103cr_cas:
3104 mov.l ADDR(%a6),%a0 # load <ea>
3105 btst &0x1,EXC_OPWORD(%a6) # word or long operation?
3106 sne %d7 # set d7 accordingly
3107 bra.w compandsetfetch
3108
3109########
3110
3111# At this stage, it would be nice if d0 held the FSLW.
3112 global _isp_cas_terminate
3113_isp_cas_terminate:
3114 mov.l %d6,%sfc # restore previous sfc
3115 mov.l %d6,%dfc # restore previous dfc
3116
3117 global _cas_terminate2
3118_cas_terminate2:
3119 mov.l %a0,%a2 # copy failing addr to a2
3120
3121 mov.l %d0,-(%sp)
3122 bsr.l isp_restore # restore An (if ()+ or -())
3123 mov.l (%sp)+,%d0
3124
3125 addq.l &0x4,%sp # remove sub return addr
3126 subq.l &0x8,%sp # make room for bigger stack
3127 subq.l &0x8,%a6 # shift frame ptr down, too
3128 mov.l &26,%d1 # want to move 51 longwords
3129 lea 0x8(%sp),%a0 # get address of old stack
3130 lea 0x0(%sp),%a1 # get address of new stack
3131cas_term_cont:
3132 mov.l (%a0)+,(%a1)+ # move a longword
3133 dbra.w %d1,cas_term_cont # keep going
3134
3135 mov.w &0x4008,EXC_IVOFF(%a6) # put new stk fmt, voff
3136 mov.l %a2,EXC_IVOFF+0x2(%a6) # put faulting addr on stack
3137 mov.l %d0,EXC_IVOFF+0x6(%a6) # put FSLW on stack
3138 movm.l EXC_DREGS(%a6),&0x3fff # restore user regs
3139 unlk %a6 # unlink stack frame
3140 bra.l _real_access
3141
3142########
3143
3144 global _isp_cas_inrange
3145_isp_cas_inrange:
3146 clr.l %d0 # clear return result
3147 lea _CASHI(%pc),%a1 # load end of CAS core code
3148 cmp.l %a1,%a0 # is PC in range?
3149 blt.b cin_no # no
3150 lea _CASLO(%pc),%a1 # load begin of CAS core code
3151 cmp.l %a0,%a1 # is PC in range?
3152 blt.b cin_no # no
3153 rts # yes; return d0 = 0
3154cin_no:
3155 mov.l &-0x1,%d0 # out of range; return d0 = -1
3156 rts
3157
3158#################################################################
3159#################################################################
3160#################################################################
3161# This is the start of the cas and cas2 "core" emulation code. #
3162# This is the section that may need to be replaced by the host #
3163# OS if it is too operating system-specific. #
3164# Please refer to the package documentation to see how to #
3165# "replace" this section, if necessary. #
3166#################################################################
3167#################################################################
3168#################################################################
3169
3170# ###### ## ###### ####
3171# # # # # # #
3172# # ###### ###### #
3173# # # # # #
3174# ###### # # ###### ######
3175
3176#########################################################################
3177# XDEF **************************************************************** #
3178# _isp_cas2(): "core" emulation code for the cas2 instruction #
3179# #
3180# XREF **************************************************************** #
3181# _isp_cas2_finish() - only exit point for this emulation code; #
3182# do clean-up; calculate ccodes; store #
3183# Compare Ops if appropriate. #
3184# #
3185# INPUT *************************************************************** #
3186# *see chart below* #
3187# #
3188# OUTPUT ************************************************************** #
3189# *see chart below* #
3190# #
3191# ALGORITHM *********************************************************** #
3192# (1) Make several copies of the effective address. #
3193# (2) Save current SR; Then mask off all maskable interrupts. #
3194# (3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set #
3195# according to whether exception occurred in user or #
3196# supervisor mode. #
3197# (4) Use "plpaw" instruction to pre-load ATC with effective #
3198# address pages(s). THIS SHOULD NOT FAULT!!! The relevant #
3199# page(s) should have already been made resident prior to #
3200# entering this routine. #
3201# (5) Push the operand lines from the cache w/ "cpushl". #
3202# In the 68040, this was done within the locked region. In #
3203# the 68060, it is done outside of the locked region. #
3204# (6) Use "plpar" instruction to do a re-load of ATC entries for #
3205# ADDR1 since ADDR2 entries may have pushed ADDR1 out of the #
3206# ATC. #
3207# (7) Pre-fetch the core emulation instructions by executing #
3208# one branch within each physical line (16 bytes) of the code #
3209# before actually executing the code. #
3210# (8) Load the BUSCR w/ the bus lock value. #
3211# (9) Fetch the source operands using "moves". #
3212# (10)Do the compares. If both equal, go to step (13). #
3213# (11)Unequal. No update occurs. But, we do write the DST1 op #
3214# back to itself (as w/ the '040) so we can gracefully unlock #
3215# the bus (and assert LOCKE*) using BUSCR and the final move. #
3216# (12)Exit. #
3217# (13)Write update operand to the DST locations. Use BUSCR to #
3218# assert LOCKE* for the final write operation. #
3219# (14)Exit. #
3220# #
3221# The algorithm is actually implemented slightly differently #
3222# depending on the size of the operation and the misalignment of the #
3223# operands. A misaligned operand must be written in aligned chunks or #
3224# else the BUSCR register control gets confused. #
3225# #
3226#########################################################################
3227
3228#################################################################
3229# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON #
3230# ENTERING _isp_cas2(). #
3231# #
3232# D0 = xxxxxxxx #
3233# D1 = xxxxxxxx #
3234# D2 = cmp operand 1 #
3235# D3 = cmp operand 2 #
3236# D4 = update oper 1 #
3237# D5 = update oper 2 #
3238# D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode #
3239# D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word #
3240# A0 = ADDR1 #
3241# A1 = ADDR2 #
3242# A2 = xxxxxxxx #
3243# A3 = xxxxxxxx #
3244# A4 = xxxxxxxx #
3245# A5 = xxxxxxxx #
3246# A6 = frame pointer #
3247# A7 = stack pointer #
3248#################################################################
3249
3250# align 0x1000
3251# beginning label used by _isp_cas_inrange()
3252 global _CASLO
3253_CASLO:
3254
3255 global _isp_cas2
3256_isp_cas2:
3257 tst.b %d6 # user or supervisor mode?
3258 bne.b cas2_supervisor # supervisor
3259cas2_user:
3260 movq.l &0x1,%d0 # load user data fc
3261 bra.b cas2_cont
3262cas2_supervisor:
3263 movq.l &0x5,%d0 # load supervisor data fc
3264cas2_cont:
3265 tst.b %d7 # word or longword?
3266 beq.w cas2w # word
3267
3268####
3269cas2l:
3270 mov.l %a0,%a2 # copy ADDR1
3271 mov.l %a1,%a3 # copy ADDR2
3272 mov.l %a0,%a4 # copy ADDR1
3273 mov.l %a1,%a5 # copy ADDR2
3274
3275 addq.l &0x3,%a4 # ADDR1+3
3276 addq.l &0x3,%a5 # ADDR2+3
3277 mov.l %a2,%d1 # ADDR1
3278
3279# mask interrupts levels 0-6. save old mask value.
3280 mov.w %sr,%d7 # save current SR
3281 ori.w &0x0700,%sr # inhibit interrupts
3282
3283# load the SFC and DFC with the appropriate mode.
3284 movc %sfc,%d6 # save old SFC/DFC
3285 movc %d0,%sfc # store new SFC
3286 movc %d0,%dfc # store new DFC
3287
3288# pre-load the operand ATC. no page faults should occur here because
3289# _real_lock_page() should have taken care of this.
3290 plpaw (%a2) # load atc for ADDR1
3291 plpaw (%a4) # load atc for ADDR1+3
3292 plpaw (%a3) # load atc for ADDR2
3293 plpaw (%a5) # load atc for ADDR2+3
3294
3295# push the operand lines from the cache if they exist.
3296 cpushl %dc,(%a2) # push line for ADDR1
3297 cpushl %dc,(%a4) # push line for ADDR1+3
3298 cpushl %dc,(%a3) # push line for ADDR2
3299 cpushl %dc,(%a5) # push line for ADDR2+2
3300
3301 mov.l %d1,%a2 # ADDR1
3302 addq.l &0x3,%d1
3303 mov.l %d1,%a4 # ADDR1+3
3304# if ADDR1 was ATC resident before the above "plpaw" and was executed
3305# and it was the next entry scheduled for replacement and ADDR2
3306# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
3307# entries from the ATC. so, we do a second set of "plpa"s.
3308 plpar (%a2) # load atc for ADDR1
3309 plpar (%a4) # load atc for ADDR1+3
3310
3311# load the BUSCR values.
3312 mov.l &0x80000000,%a2 # assert LOCK* buscr value
3313 mov.l &0xa0000000,%a3 # assert LOCKE* buscr value
3314 mov.l &0x00000000,%a4 # buscr unlock value
3315
3316# there are three possible mis-aligned cases for longword cas. they
3317# are separated because the final write which asserts LOCKE* must
3318# be aligned.
3319 mov.l %a0,%d0 # is ADDR1 misaligned?
3320 andi.b &0x3,%d0
3321 beq.b CAS2L_ENTER # no
3322 cmpi.b %d0,&0x2
3323 beq.w CAS2L2_ENTER # yes; word misaligned
3324 bra.w CAS2L3_ENTER # yes; byte misaligned
3325
3326#
3327# D0 = dst operand 1 <-
3328# D1 = dst operand 2 <-
3329# D2 = cmp operand 1
3330# D3 = cmp operand 2
3331# D4 = update oper 1
3332# D5 = update oper 2
3333# D6 = old SFC/DFC
3334# D7 = old SR
3335# A0 = ADDR1
3336# A1 = ADDR2
3337# A2 = bus LOCK* value
3338# A3 = bus LOCKE* value
3339# A4 = bus unlock value
3340# A5 = xxxxxxxx
3341#
3342 align 0x10
3343CAS2L_START:
3344 movc %a2,%buscr # assert LOCK*
3345 movs.l (%a1),%d1 # fetch Dest2[31:0]
3346 movs.l (%a0),%d0 # fetch Dest1[31:0]
3347 bra.b CAS2L_CONT
3348CAS2L_ENTER:
3349 bra.b ~+16
3350
3351CAS2L_CONT:
3352 cmp.l %d0,%d2 # Dest1 - Compare1
3353 bne.b CAS2L_NOUPDATE
3354 cmp.l %d1,%d3 # Dest2 - Compare2
3355 bne.b CAS2L_NOUPDATE
3356 movs.l %d5,(%a1) # Update2[31:0] -> DEST2
3357 bra.b CAS2L_UPDATE
3358 bra.b ~+16
3359
3360CAS2L_UPDATE:
3361 movc %a3,%buscr # assert LOCKE*
3362 movs.l %d4,(%a0) # Update1[31:0] -> DEST1
3363 movc %a4,%buscr # unlock the bus
3364 bra.b cas2l_update_done
3365 bra.b ~+16
3366
3367CAS2L_NOUPDATE:
3368 movc %a3,%buscr # assert LOCKE*
3369 movs.l %d0,(%a0) # Dest1[31:0] -> DEST1
3370 movc %a4,%buscr # unlock the bus
3371 bra.b cas2l_noupdate_done
3372 bra.b ~+16
3373
3374CAS2L_FILLER:
3375 nop
3376 nop
3377 nop
3378 nop
3379 nop
3380 nop
3381 nop
3382 bra.b CAS2L_START
3383
3384####
3385
3386#################################################################
3387# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
3388# ENTERING _isp_cas2(). #
3389# #
3390# D0 = destination[31:0] operand 1 #
3391# D1 = destination[31:0] operand 2 #
3392# D2 = cmp[31:0] operand 1 #
3393# D3 = cmp[31:0] operand 2 #
3394# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
3395# D5 = xxxxxxxx #
3396# D6 = xxxxxxxx #
3397# D7 = xxxxxxxx #
3398# A0 = xxxxxxxx #
3399# A1 = xxxxxxxx #
3400# A2 = xxxxxxxx #
3401# A3 = xxxxxxxx #
3402# A4 = xxxxxxxx #
3403# A5 = xxxxxxxx #
3404# A6 = frame pointer #
3405# A7 = stack pointer #
3406#################################################################
3407
3408cas2l_noupdate_done:
3409
3410# restore previous SFC/DFC value.
3411 movc %d6,%sfc # restore old SFC
3412 movc %d6,%dfc # restore old DFC
3413
3414# restore previous interrupt mask level.
3415 mov.w %d7,%sr # restore old SR
3416
3417 sf %d4 # indicate no update was done
3418 bra.l _isp_cas2_finish
3419
3420cas2l_update_done:
3421
3422# restore previous SFC/DFC value.
3423 movc %d6,%sfc # restore old SFC
3424 movc %d6,%dfc # restore old DFC
3425
3426# restore previous interrupt mask level.
3427 mov.w %d7,%sr # restore old SR
3428
3429 st %d4 # indicate update was done
3430 bra.l _isp_cas2_finish
3431####
3432
3433 align 0x10
3434CAS2L2_START:
3435 movc %a2,%buscr # assert LOCK*
3436 movs.l (%a1),%d1 # fetch Dest2[31:0]
3437 movs.l (%a0),%d0 # fetch Dest1[31:0]
3438 bra.b CAS2L2_CONT
3439CAS2L2_ENTER:
3440 bra.b ~+16
3441
3442CAS2L2_CONT:
3443 cmp.l %d0,%d2 # Dest1 - Compare1
3444 bne.b CAS2L2_NOUPDATE
3445 cmp.l %d1,%d3 # Dest2 - Compare2
3446 bne.b CAS2L2_NOUPDATE
3447 movs.l %d5,(%a1) # Update2[31:0] -> Dest2
3448 bra.b CAS2L2_UPDATE
3449 bra.b ~+16
3450
3451CAS2L2_UPDATE:
3452 swap %d4 # get Update1[31:16]
3453 movs.w %d4,(%a0)+ # Update1[31:16] -> DEST1
3454 movc %a3,%buscr # assert LOCKE*
3455 swap %d4 # get Update1[15:0]
3456 bra.b CAS2L2_UPDATE2
3457 bra.b ~+16
3458
3459CAS2L2_UPDATE2:
3460 movs.w %d4,(%a0) # Update1[15:0] -> DEST1+0x2
3461 movc %a4,%buscr # unlock the bus
3462 bra.w cas2l_update_done
3463 nop
3464 bra.b ~+16
3465
3466CAS2L2_NOUPDATE:
3467 swap %d0 # get Dest1[31:16]
3468 movs.w %d0,(%a0)+ # Dest1[31:16] -> DEST1
3469 movc %a3,%buscr # assert LOCKE*
3470 swap %d0 # get Dest1[15:0]
3471 bra.b CAS2L2_NOUPDATE2
3472 bra.b ~+16
3473
3474CAS2L2_NOUPDATE2:
3475 movs.w %d0,(%a0) # Dest1[15:0] -> DEST1+0x2
3476 movc %a4,%buscr # unlock the bus
3477 bra.w cas2l_noupdate_done
3478 nop
3479 bra.b ~+16
3480
3481CAS2L2_FILLER:
3482 nop
3483 nop
3484 nop
3485 nop
3486 nop
3487 nop
3488 nop
3489 bra.b CAS2L2_START
3490
3491#################################
3492
3493 align 0x10
3494CAS2L3_START:
3495 movc %a2,%buscr # assert LOCK*
3496 movs.l (%a1),%d1 # fetch Dest2[31:0]
3497 movs.l (%a0),%d0 # fetch Dest1[31:0]
3498 bra.b CAS2L3_CONT
3499CAS2L3_ENTER:
3500 bra.b ~+16
3501
3502CAS2L3_CONT:
3503 cmp.l %d0,%d2 # Dest1 - Compare1
3504 bne.b CAS2L3_NOUPDATE
3505 cmp.l %d1,%d3 # Dest2 - Compare2
3506 bne.b CAS2L3_NOUPDATE
3507 movs.l %d5,(%a1) # Update2[31:0] -> DEST2
3508 bra.b CAS2L3_UPDATE
3509 bra.b ~+16
3510
3511CAS2L3_UPDATE:
3512 rol.l &0x8,%d4 # get Update1[31:24]
3513 movs.b %d4,(%a0)+ # Update1[31:24] -> DEST1
3514 swap %d4 # get Update1[23:8]
3515 movs.w %d4,(%a0)+ # Update1[23:8] -> DEST1+0x1
3516 bra.b CAS2L3_UPDATE2
3517 bra.b ~+16
3518
3519CAS2L3_UPDATE2:
3520 rol.l &0x8,%d4 # get Update1[7:0]
3521 movc %a3,%buscr # assert LOCKE*
3522 movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x3
3523 bra.b CAS2L3_UPDATE3
3524 nop
3525 bra.b ~+16
3526
3527CAS2L3_UPDATE3:
3528 movc %a4,%buscr # unlock the bus
3529 bra.w cas2l_update_done
3530 nop
3531 nop
3532 nop
3533 bra.b ~+16
3534
3535CAS2L3_NOUPDATE:
3536 rol.l &0x8,%d0 # get Dest1[31:24]
3537 movs.b %d0,(%a0)+ # Dest1[31:24] -> DEST1
3538 swap %d0 # get Dest1[23:8]
3539 movs.w %d0,(%a0)+ # Dest1[23:8] -> DEST1+0x1
3540 bra.b CAS2L3_NOUPDATE2
3541 bra.b ~+16
3542
3543CAS2L3_NOUPDATE2:
3544 rol.l &0x8,%d0 # get Dest1[7:0]
3545 movc %a3,%buscr # assert LOCKE*
3546 movs.b %d0,(%a0) # Update1[7:0] -> DEST1+0x3
3547 bra.b CAS2L3_NOUPDATE3
3548 nop
3549 bra.b ~+16
3550
3551CAS2L3_NOUPDATE3:
3552 movc %a4,%buscr # unlock the bus
3553 bra.w cas2l_noupdate_done
3554 nop
3555 nop
3556 nop
3557 bra.b ~+14
3558
3559CAS2L3_FILLER:
3560 nop
3561 nop
3562 nop
3563 nop
3564 nop
3565 nop
3566 bra.w CAS2L3_START
3567
3568#############################################################
3569#############################################################
3570
3571cas2w:
3572 mov.l %a0,%a2 # copy ADDR1
3573 mov.l %a1,%a3 # copy ADDR2
3574 mov.l %a0,%a4 # copy ADDR1
3575 mov.l %a1,%a5 # copy ADDR2
3576
3577 addq.l &0x1,%a4 # ADDR1+1
3578 addq.l &0x1,%a5 # ADDR2+1
3579 mov.l %a2,%d1 # ADDR1
3580
3581# mask interrupt levels 0-6. save old mask value.
3582 mov.w %sr,%d7 # save current SR
3583 ori.w &0x0700,%sr # inhibit interrupts
3584
3585# load the SFC and DFC with the appropriate mode.
3586 movc %sfc,%d6 # save old SFC/DFC
3587 movc %d0,%sfc # store new SFC
3588 movc %d0,%dfc # store new DFC
3589
3590# pre-load the operand ATC. no page faults should occur because
3591# _real_lock_page() should have taken care of this.
3592 plpaw (%a2) # load atc for ADDR1
3593 plpaw (%a4) # load atc for ADDR1+1
3594 plpaw (%a3) # load atc for ADDR2
3595 plpaw (%a5) # load atc for ADDR2+1
3596
3597# push the operand cache lines from the cache if they exist.
3598 cpushl %dc,(%a2) # push line for ADDR1
3599 cpushl %dc,(%a4) # push line for ADDR1+1
3600 cpushl %dc,(%a3) # push line for ADDR2
3601 cpushl %dc,(%a5) # push line for ADDR2+1
3602
3603 mov.l %d1,%a2 # ADDR1
3604 addq.l &0x3,%d1
3605 mov.l %d1,%a4 # ADDR1+3
3606# if ADDR1 was ATC resident before the above "plpaw" and was executed
3607# and it was the next entry scheduled for replacement and ADDR2
3608# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
3609# entries from the ATC. so, we do a second set of "plpa"s.
3610 plpar (%a2) # load atc for ADDR1
3611 plpar (%a4) # load atc for ADDR1+3
3612
3613# load the BUSCR values.
3614 mov.l &0x80000000,%a2 # assert LOCK* buscr value
3615 mov.l &0xa0000000,%a3 # assert LOCKE* buscr value
3616 mov.l &0x00000000,%a4 # buscr unlock value
3617
3618# there are two possible mis-aligned cases for word cas. they
3619# are separated because the final write which asserts LOCKE* must
3620# be aligned.
3621 mov.l %a0,%d0 # is ADDR1 misaligned?
3622 btst &0x0,%d0
3623 bne.w CAS2W2_ENTER # yes
3624 bra.b CAS2W_ENTER # no
3625
3626#
3627# D0 = dst operand 1 <-
3628# D1 = dst operand 2 <-
3629# D2 = cmp operand 1
3630# D3 = cmp operand 2
3631# D4 = update oper 1
3632# D5 = update oper 2
3633# D6 = old SFC/DFC
3634# D7 = old SR
3635# A0 = ADDR1
3636# A1 = ADDR2
3637# A2 = bus LOCK* value
3638# A3 = bus LOCKE* value
3639# A4 = bus unlock value
3640# A5 = xxxxxxxx
3641#
3642 align 0x10
3643CAS2W_START:
3644 movc %a2,%buscr # assert LOCK*
3645 movs.w (%a1),%d1 # fetch Dest2[15:0]
3646 movs.w (%a0),%d0 # fetch Dest1[15:0]
3647 bra.b CAS2W_CONT2
3648CAS2W_ENTER:
3649 bra.b ~+16
3650
3651CAS2W_CONT2:
3652 cmp.w %d0,%d2 # Dest1 - Compare1
3653 bne.b CAS2W_NOUPDATE
3654 cmp.w %d1,%d3 # Dest2 - Compare2
3655 bne.b CAS2W_NOUPDATE
3656 movs.w %d5,(%a1) # Update2[15:0] -> DEST2
3657 bra.b CAS2W_UPDATE
3658 bra.b ~+16
3659
3660CAS2W_UPDATE:
3661 movc %a3,%buscr # assert LOCKE*
3662 movs.w %d4,(%a0) # Update1[15:0] -> DEST1
3663 movc %a4,%buscr # unlock the bus
3664 bra.b cas2w_update_done
3665 bra.b ~+16
3666
3667CAS2W_NOUPDATE:
3668 movc %a3,%buscr # assert LOCKE*
3669 movs.w %d0,(%a0) # Dest1[15:0] -> DEST1
3670 movc %a4,%buscr # unlock the bus
3671 bra.b cas2w_noupdate_done
3672 bra.b ~+16
3673
3674CAS2W_FILLER:
3675 nop
3676 nop
3677 nop
3678 nop
3679 nop
3680 nop
3681 nop
3682 bra.b CAS2W_START
3683
3684####
3685
3686#################################################################
3687# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
3688# ENTERING _isp_cas2(). #
3689# #
3690# D0 = destination[15:0] operand 1 #
3691# D1 = destination[15:0] operand 2 #
3692# D2 = cmp[15:0] operand 1 #
3693# D3 = cmp[15:0] operand 2 #
3694# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
3695# D5 = xxxxxxxx #
3696# D6 = xxxxxxxx #
3697# D7 = xxxxxxxx #
3698# A0 = xxxxxxxx #
3699# A1 = xxxxxxxx #
3700# A2 = xxxxxxxx #
3701# A3 = xxxxxxxx #
3702# A4 = xxxxxxxx #
3703# A5 = xxxxxxxx #
3704# A6 = frame pointer #
3705# A7 = stack pointer #
3706#################################################################
3707
3708cas2w_noupdate_done:
3709
3710# restore previous SFC/DFC value.
3711 movc %d6,%sfc # restore old SFC
3712 movc %d6,%dfc # restore old DFC
3713
3714# restore previous interrupt mask level.
3715 mov.w %d7,%sr # restore old SR
3716
3717 sf %d4 # indicate no update was done
3718 bra.l _isp_cas2_finish
3719
3720cas2w_update_done:
3721
3722# restore previous SFC/DFC value.
3723 movc %d6,%sfc # restore old SFC
3724 movc %d6,%dfc # restore old DFC
3725
3726# restore previous interrupt mask level.
3727 mov.w %d7,%sr # restore old SR
3728
3729 st %d4 # indicate update was done
3730 bra.l _isp_cas2_finish
3731####
3732
3733 align 0x10
3734CAS2W2_START:
3735 movc %a2,%buscr # assert LOCK*
3736 movs.w (%a1),%d1 # fetch Dest2[15:0]
3737 movs.w (%a0),%d0 # fetch Dest1[15:0]
3738 bra.b CAS2W2_CONT2
3739CAS2W2_ENTER:
3740 bra.b ~+16
3741
3742CAS2W2_CONT2:
3743 cmp.w %d0,%d2 # Dest1 - Compare1
3744 bne.b CAS2W2_NOUPDATE
3745 cmp.w %d1,%d3 # Dest2 - Compare2
3746 bne.b CAS2W2_NOUPDATE
3747 movs.w %d5,(%a1) # Update2[15:0] -> DEST2
3748 bra.b CAS2W2_UPDATE
3749 bra.b ~+16
3750
3751CAS2W2_UPDATE:
3752 ror.l &0x8,%d4 # get Update1[15:8]
3753 movs.b %d4,(%a0)+ # Update1[15:8] -> DEST1
3754 movc %a3,%buscr # assert LOCKE*
3755 rol.l &0x8,%d4 # get Update1[7:0]
3756 bra.b CAS2W2_UPDATE2
3757 bra.b ~+16
3758
3759CAS2W2_UPDATE2:
3760 movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x1
3761 movc %a4,%buscr # unlock the bus
3762 bra.w cas2w_update_done
3763 nop
3764 bra.b ~+16
3765
3766CAS2W2_NOUPDATE:
3767 ror.l &0x8,%d0 # get Dest1[15:8]
3768 movs.b %d0,(%a0)+ # Dest1[15:8] -> DEST1
3769 movc %a3,%buscr # assert LOCKE*
3770 rol.l &0x8,%d0 # get Dest1[7:0]
3771 bra.b CAS2W2_NOUPDATE2
3772 bra.b ~+16
3773
3774CAS2W2_NOUPDATE2:
3775 movs.b %d0,(%a0) # Dest1[7:0] -> DEST1+0x1
3776 movc %a4,%buscr # unlock the bus
3777 bra.w cas2w_noupdate_done
3778 nop
3779 bra.b ~+16
3780
3781CAS2W2_FILLER:
3782 nop
3783 nop
3784 nop
3785 nop
3786 nop
3787 nop
3788 nop
3789 bra.b CAS2W2_START
3790
3791# ###### ## ######
3792# # # # #
3793# # ###### ######
3794# # # # #
3795# ###### # # ######
3796
3797#########################################################################
3798# XDEF **************************************************************** #
3799# _isp_cas(): "core" emulation code for the cas instruction #
3800# #
3801# XREF **************************************************************** #
3802# _isp_cas_finish() - only exit point for this emulation code; #
3803# do clean-up #
3804# #
3805# INPUT *************************************************************** #
3806# *see entry chart below* #
3807# #
3808# OUTPUT ************************************************************** #
3809# *see exit chart below* #
3810# #
3811# ALGORITHM *********************************************************** #
3812# (1) Make several copies of the effective address. #
3813# (2) Save current SR; Then mask off all maskable interrupts. #
3814# (3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set #
3815# SFC/DFC according to whether exception occurred in user or #
3816# supervisor mode. #
3817# (4) Use "plpaw" instruction to pre-load ATC with efective #
3818# address page(s). THIS SHOULD NOT FAULT!!! The relevant #
3819# page(s) should have been made resident prior to entering #
3820# this routine. #
3821# (5) Push the operand lines from the cache w/ "cpushl". #
3822# In the 68040, this was done within the locked region. In #
3823# the 68060, it is done outside of the locked region. #
3824# (6) Pre-fetch the core emulation instructions by executing one #
3825# branch within each physical line (16 bytes) of the code #
3826# before actually executing the code. #
3827# (7) Load the BUSCR with the bus lock value. #
3828# (8) Fetch the source operand. #
3829# (9) Do the compare. If equal, go to step (12). #
3830# (10)Unequal. No update occurs. But, we do write the DST op back #
3831# to itself (as w/ the '040) so we can gracefully unlock #
3832# the bus (and assert LOCKE*) using BUSCR and the final move. #
3833# (11)Exit. #
3834# (12)Write update operand to the DST location. Use BUSCR to #
3835# assert LOCKE* for the final write operation. #
3836# (13)Exit. #
3837# #
3838# The algorithm is actually implemented slightly differently #
3839# depending on the size of the operation and the misalignment of the #
3840# operand. A misaligned operand must be written in aligned chunks or #
3841# else the BUSCR register control gets confused. #
3842# #
3843#########################################################################
3844
3845#########################################################
3846# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON #
3847# ENTERING _isp_cas(). #
3848# #
3849# D0 = xxxxxxxx #
3850# D1 = xxxxxxxx #
3851# D2 = update operand #
3852# D3 = xxxxxxxx #
3853# D4 = compare operand #
3854# D5 = xxxxxxxx #
3855# D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00) #
3856# D7 = longword ('xxxxxxff) or word size ('xxxxxx00) #
3857# A0 = ADDR #
3858# A1 = xxxxxxxx #
3859# A2 = xxxxxxxx #
3860# A3 = xxxxxxxx #
3861# A4 = xxxxxxxx #
3862# A5 = xxxxxxxx #
3863# A6 = frame pointer #
3864# A7 = stack pointer #
3865#########################################################
3866
3867 global _isp_cas
3868_isp_cas:
3869 tst.b %d6 # user or supervisor mode?
3870 bne.b cas_super # supervisor
3871cas_user:
3872 movq.l &0x1,%d0 # load user data fc
3873 bra.b cas_cont
3874cas_super:
3875 movq.l &0x5,%d0 # load supervisor data fc
3876
3877cas_cont:
3878 tst.b %d7 # word or longword?
3879 bne.w casl # longword
3880
3881####
3882casw:
3883 mov.l %a0,%a1 # make copy for plpaw1
3884 mov.l %a0,%a2 # make copy for plpaw2
3885 addq.l &0x1,%a2 # plpaw2 points to end of word
3886
3887 mov.l %d2,%d3 # d3 = update[7:0]
3888 lsr.w &0x8,%d2 # d2 = update[15:8]
3889
3890# mask interrupt levels 0-6. save old mask value.
3891 mov.w %sr,%d7 # save current SR
3892 ori.w &0x0700,%sr # inhibit interrupts
3893
3894# load the SFC and DFC with the appropriate mode.
3895 movc %sfc,%d6 # save old SFC/DFC
3896 movc %d0,%sfc # load new sfc
3897 movc %d0,%dfc # load new dfc
3898
3899# pre-load the operand ATC. no page faults should occur here because
3900# _real_lock_page() should have taken care of this.
3901 plpaw (%a1) # load atc for ADDR
3902 plpaw (%a2) # load atc for ADDR+1
3903
3904# push the operand lines from the cache if they exist.
3905 cpushl %dc,(%a1) # push dirty data
3906 cpushl %dc,(%a2) # push dirty data
3907
3908# load the BUSCR values.
3909 mov.l &0x80000000,%a1 # assert LOCK* buscr value
3910 mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
3911 mov.l &0x00000000,%a3 # buscr unlock value
3912
3913# pre-load the instruction cache for the following algorithm.
3914# this will minimize the number of cycles that LOCK* will be asserted.
3915 bra.b CASW_ENTER # start pre-loading icache
3916
3917#
3918# D0 = dst operand <-
3919# D1 = update[15:8] operand
3920# D2 = update[7:0] operand
3921# D3 = xxxxxxxx
3922# D4 = compare[15:0] operand
3923# D5 = xxxxxxxx
3924# D6 = old SFC/DFC
3925# D7 = old SR
3926# A0 = ADDR
3927# A1 = bus LOCK* value
3928# A2 = bus LOCKE* value
3929# A3 = bus unlock value
3930# A4 = xxxxxxxx
3931# A5 = xxxxxxxx
3932#
3933 align 0x10
3934CASW_START:
3935 movc %a1,%buscr # assert LOCK*
3936 movs.w (%a0),%d0 # fetch Dest[15:0]
3937 cmp.w %d0,%d4 # Dest - Compare
3938 bne.b CASW_NOUPDATE
3939 bra.b CASW_UPDATE
3940CASW_ENTER:
3941 bra.b ~+16
3942
3943CASW_UPDATE:
3944 movs.b %d2,(%a0)+ # Update[15:8] -> DEST
3945 movc %a2,%buscr # assert LOCKE*
3946 movs.b %d3,(%a0) # Update[7:0] -> DEST+0x1
3947 bra.b CASW_UPDATE2
3948 bra.b ~+16
3949
3950CASW_UPDATE2:
3951 movc %a3,%buscr # unlock the bus
3952 bra.b casw_update_done
3953 nop
3954 nop
3955 nop
3956 nop
3957 bra.b ~+16
3958
3959CASW_NOUPDATE:
3960 ror.l &0x8,%d0 # get Dest[15:8]
3961 movs.b %d0,(%a0)+ # Dest[15:8] -> DEST
3962 movc %a2,%buscr # assert LOCKE*
3963 rol.l &0x8,%d0 # get Dest[7:0]
3964 bra.b CASW_NOUPDATE2
3965 bra.b ~+16
3966
3967CASW_NOUPDATE2:
3968 movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x1
3969 movc %a3,%buscr # unlock the bus
3970 bra.b casw_noupdate_done
3971 nop
3972 nop
3973 bra.b ~+16
3974
3975CASW_FILLER:
3976 nop
3977 nop
3978 nop
3979 nop
3980 nop
3981 nop
3982 nop
3983 bra.b CASW_START
3984
3985#################################################################
3986# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
3987# CALLING _isp_cas_finish(). #
3988# #
3989# D0 = destination[15:0] operand #
3990# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
3991# D2 = xxxxxxxx #
3992# D3 = xxxxxxxx #
3993# D4 = compare[15:0] operand #
3994# D5 = xxxxxxxx #
3995# D6 = xxxxxxxx #
3996# D7 = xxxxxxxx #
3997# A0 = xxxxxxxx #
3998# A1 = xxxxxxxx #
3999# A2 = xxxxxxxx #
4000# A3 = xxxxxxxx #
4001# A4 = xxxxxxxx #
4002# A5 = xxxxxxxx #
4003# A6 = frame pointer #
4004# A7 = stack pointer #
4005#################################################################
4006
4007casw_noupdate_done:
4008
4009# restore previous SFC/DFC value.
4010 movc %d6,%sfc # restore old SFC
4011 movc %d6,%dfc # restore old DFC
4012
4013# restore previous interrupt mask level.
4014 mov.w %d7,%sr # restore old SR
4015
4016 sf %d1 # indicate no update was done
4017 bra.l _isp_cas_finish
4018
4019casw_update_done:
4020
4021# restore previous SFC/DFC value.
4022 movc %d6,%sfc # restore old SFC
4023 movc %d6,%dfc # restore old DFC
4024
4025# restore previous interrupt mask level.
4026 mov.w %d7,%sr # restore old SR
4027
4028 st %d1 # indicate update was done
4029 bra.l _isp_cas_finish
4030
4031################
4032
4033# there are two possible mis-aligned cases for longword cas. they
4034# are separated because the final write which asserts LOCKE* must
4035# be an aligned write.
4036casl:
4037 mov.l %a0,%a1 # make copy for plpaw1
4038 mov.l %a0,%a2 # make copy for plpaw2
4039 addq.l &0x3,%a2 # plpaw2 points to end of longword
4040
4041 mov.l %a0,%d1 # byte or word misaligned?
4042 btst &0x0,%d1
4043 bne.w casl2 # byte misaligned
4044
4045 mov.l %d2,%d3 # d3 = update[15:0]
4046 swap %d2 # d2 = update[31:16]
4047
4048# mask interrupts levels 0-6. save old mask value.
4049 mov.w %sr,%d7 # save current SR
4050 ori.w &0x0700,%sr # inhibit interrupts
4051
4052# load the SFC and DFC with the appropriate mode.
4053 movc %sfc,%d6 # save old SFC/DFC
4054 movc %d0,%sfc # load new sfc
4055 movc %d0,%dfc # load new dfc
4056
4057# pre-load the operand ATC. no page faults should occur here because
4058# _real_lock_page() should have taken care of this.
4059 plpaw (%a1) # load atc for ADDR
4060 plpaw (%a2) # load atc for ADDR+3
4061
4062# push the operand lines from the cache if they exist.
4063 cpushl %dc,(%a1) # push dirty data
4064 cpushl %dc,(%a2) # push dirty data
4065
4066# load the BUSCR values.
4067 mov.l &0x80000000,%a1 # assert LOCK* buscr value
4068 mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
4069 mov.l &0x00000000,%a3 # buscr unlock value
4070
4071 bra.b CASL_ENTER # start pre-loading icache
4072
4073#
4074# D0 = dst operand <-
4075# D1 = xxxxxxxx
4076# D2 = update[31:16] operand
4077# D3 = update[15:0] operand
4078# D4 = compare[31:0] operand
4079# D5 = xxxxxxxx
4080# D6 = old SFC/DFC
4081# D7 = old SR
4082# A0 = ADDR
4083# A1 = bus LOCK* value
4084# A2 = bus LOCKE* value
4085# A3 = bus unlock value
4086# A4 = xxxxxxxx
4087# A5 = xxxxxxxx
4088#
4089 align 0x10
4090CASL_START:
4091 movc %a1,%buscr # assert LOCK*
4092 movs.l (%a0),%d0 # fetch Dest[31:0]
4093 cmp.l %d0,%d4 # Dest - Compare
4094 bne.b CASL_NOUPDATE
4095 bra.b CASL_UPDATE
4096CASL_ENTER:
4097 bra.b ~+16
4098
4099CASL_UPDATE:
4100 movs.w %d2,(%a0)+ # Update[31:16] -> DEST
4101 movc %a2,%buscr # assert LOCKE*
4102 movs.w %d3,(%a0) # Update[15:0] -> DEST+0x2
4103 bra.b CASL_UPDATE2
4104 bra.b ~+16
4105
4106CASL_UPDATE2:
4107 movc %a3,%buscr # unlock the bus
4108 bra.b casl_update_done
4109 nop
4110 nop
4111 nop
4112 nop
4113 bra.b ~+16
4114
4115CASL_NOUPDATE:
4116 swap %d0 # get Dest[31:16]
4117 movs.w %d0,(%a0)+ # Dest[31:16] -> DEST
4118 swap %d0 # get Dest[15:0]
4119 movc %a2,%buscr # assert LOCKE*
4120 bra.b CASL_NOUPDATE2
4121 bra.b ~+16
4122
4123CASL_NOUPDATE2:
4124 movs.w %d0,(%a0) # Dest[15:0] -> DEST+0x2
4125 movc %a3,%buscr # unlock the bus
4126 bra.b casl_noupdate_done
4127 nop
4128 nop
4129 bra.b ~+16
4130
4131CASL_FILLER:
4132 nop
4133 nop
4134 nop
4135 nop
4136 nop
4137 nop
4138 nop
4139 bra.b CASL_START
4140
4141#################################################################
4142# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
4143# CALLING _isp_cas_finish(). #
4144# #
4145# D0 = destination[31:0] operand #
4146# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
4147# D2 = xxxxxxxx #
4148# D3 = xxxxxxxx #
4149# D4 = compare[31:0] operand #
4150# D5 = xxxxxxxx #
4151# D6 = xxxxxxxx #
4152# D7 = xxxxxxxx #
4153# A0 = xxxxxxxx #
4154# A1 = xxxxxxxx #
4155# A2 = xxxxxxxx #
4156# A3 = xxxxxxxx #
4157# A4 = xxxxxxxx #
4158# A5 = xxxxxxxx #
4159# A6 = frame pointer #
4160# A7 = stack pointer #
4161#################################################################
4162
4163casl_noupdate_done:
4164
4165# restore previous SFC/DFC value.
4166 movc %d6,%sfc # restore old SFC
4167 movc %d6,%dfc # restore old DFC
4168
4169# restore previous interrupt mask level.
4170 mov.w %d7,%sr # restore old SR
4171
4172 sf %d1 # indicate no update was done
4173 bra.l _isp_cas_finish
4174
4175casl_update_done:
4176
4177# restore previous SFC/DFC value.
4178 movc %d6,%sfc # restore old SFC
4179 movc %d6,%dfc # restore old DFC
4180
4181# restore previous interrupts mask level.
4182 mov.w %d7,%sr # restore old SR
4183
4184 st %d1 # indicate update was done
4185 bra.l _isp_cas_finish
4186
4187#######################################
4188casl2:
4189 mov.l %d2,%d5 # d5 = Update[7:0]
4190 lsr.l &0x8,%d2
4191 mov.l %d2,%d3 # d3 = Update[23:8]
4192 swap %d2 # d2 = Update[31:24]
4193
4194# mask interrupts levels 0-6. save old mask value.
4195 mov.w %sr,%d7 # save current SR
4196 ori.w &0x0700,%sr # inhibit interrupts
4197
4198# load the SFC and DFC with the appropriate mode.
4199 movc %sfc,%d6 # save old SFC/DFC
4200 movc %d0,%sfc # load new sfc
4201 movc %d0,%dfc # load new dfc
4202
4203# pre-load the operand ATC. no page faults should occur here because
4204# _real_lock_page() should have taken care of this already.
4205 plpaw (%a1) # load atc for ADDR
4206 plpaw (%a2) # load atc for ADDR+3
4207
4208# puch the operand lines from the cache if they exist.
4209 cpushl %dc,(%a1) # push dirty data
4210 cpushl %dc,(%a2) # push dirty data
4211
4212# load the BUSCR values.
4213 mov.l &0x80000000,%a1 # assert LOCK* buscr value
4214 mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
4215 mov.l &0x00000000,%a3 # buscr unlock value
4216
4217# pre-load the instruction cache for the following algorithm.
4218# this will minimize the number of cycles that LOCK* will be asserted.
4219 bra.b CASL2_ENTER # start pre-loading icache
4220
4221#
4222# D0 = dst operand <-
4223# D1 = xxxxxxxx
4224# D2 = update[31:24] operand
4225# D3 = update[23:8] operand
4226# D4 = compare[31:0] operand
4227# D5 = update[7:0] operand
4228# D6 = old SFC/DFC
4229# D7 = old SR
4230# A0 = ADDR
4231# A1 = bus LOCK* value
4232# A2 = bus LOCKE* value
4233# A3 = bus unlock value
4234# A4 = xxxxxxxx
4235# A5 = xxxxxxxx
4236#
4237 align 0x10
4238CASL2_START:
4239 movc %a1,%buscr # assert LOCK*
4240 movs.l (%a0),%d0 # fetch Dest[31:0]
4241 cmp.l %d0,%d4 # Dest - Compare
4242 bne.b CASL2_NOUPDATE
4243 bra.b CASL2_UPDATE
4244CASL2_ENTER:
4245 bra.b ~+16
4246
4247CASL2_UPDATE:
4248 movs.b %d2,(%a0)+ # Update[31:24] -> DEST
4249 movs.w %d3,(%a0)+ # Update[23:8] -> DEST+0x1
4250 movc %a2,%buscr # assert LOCKE*
4251 bra.b CASL2_UPDATE2
4252 bra.b ~+16
4253
4254CASL2_UPDATE2:
4255 movs.b %d5,(%a0) # Update[7:0] -> DEST+0x3
4256 movc %a3,%buscr # unlock the bus
4257 bra.w casl_update_done
4258 nop
4259 bra.b ~+16
4260
4261CASL2_NOUPDATE:
4262 rol.l &0x8,%d0 # get Dest[31:24]
4263 movs.b %d0,(%a0)+ # Dest[31:24] -> DEST
4264 swap %d0 # get Dest[23:8]
4265 movs.w %d0,(%a0)+ # Dest[23:8] -> DEST+0x1
4266 bra.b CASL2_NOUPDATE2
4267 bra.b ~+16
4268
4269CASL2_NOUPDATE2:
4270 rol.l &0x8,%d0 # get Dest[7:0]
4271 movc %a2,%buscr # assert LOCKE*
4272 movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x3
4273 bra.b CASL2_NOUPDATE3
4274 nop
4275 bra.b ~+16
4276
4277CASL2_NOUPDATE3:
4278 movc %a3,%buscr # unlock the bus
4279 bra.w casl_noupdate_done
4280 nop
4281 nop
4282 nop
4283 bra.b ~+16
4284
4285CASL2_FILLER:
4286 nop
4287 nop
4288 nop
4289 nop
4290 nop
4291 nop
4292 nop
4293 bra.b CASL2_START
4294
4295####
4296####
4297# end label used by _isp_cas_inrange()
4298 global _CASHI
4299_CASHI:
diff --git a/arch/m68k/ifpsp060/src/itest.S b/arch/m68k/ifpsp060/src/itest.S
new file mode 100644
index 000000000000..ba4a30cbcbea
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/itest.S
@@ -0,0 +1,6386 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29#############################################
30set SREGS, -64
31set IREGS, -128
32set SCCR, -130
33set ICCR, -132
34set TESTCTR, -136
35set EAMEM, -140
36set EASTORE, -144
37set DATA, -160
38
39#############################################
40TESTTOP:
41 bra.l _060TESTS_
42
43start_str:
44 string "Testing 68060 ISP started:\n"
45
46pass_str:
47 string "passed\n"
48fail_str:
49 string " failed\n"
50
51 align 0x4
52chk_test:
53 tst.l %d0
54 bne.b test_fail
55test_pass:
56 pea pass_str(%pc)
57 bsr.l _print_str
58 addq.l &0x4,%sp
59 rts
60test_fail:
61 mov.l %d1,-(%sp)
62 bsr.l _print_num
63 addq.l &0x4,%sp
64
65 pea fail_str(%pc)
66 bsr.l _print_str
67 addq.l &0x4,%sp
68 rts
69
70#############################################
71_060TESTS_:
72 link %a6,&-160
73
74 movm.l &0x3f3c,-(%sp)
75
76 pea start_str(%pc)
77 bsr.l _print_str
78 addq.l &0x4,%sp
79
80### mul
81 clr.l TESTCTR(%a6)
82 pea mulul_str(%pc)
83 bsr.l _print_str
84 addq.l &0x4,%sp
85
86 bsr.l mulul_0
87
88 bsr.l chk_test
89
90### div
91 clr.l TESTCTR(%a6)
92 pea divul_str(%pc)
93 bsr.l _print_str
94 addq.l &0x4,%sp
95
96 bsr.l divul_0
97
98 bsr.l chk_test
99
100### cmp2
101 clr.l TESTCTR(%a6)
102 pea cmp2_str(%pc)
103 bsr.l _print_str
104 addq.l &0x4,%sp
105
106 bsr.l cmp2_1
107
108 bsr.l chk_test
109
110### movp
111 clr.l TESTCTR(%a6)
112 pea movp_str(%pc)
113 bsr.l _print_str
114 addq.l &0x4,%sp
115
116 bsr.l movp_0
117
118 bsr.l chk_test
119
120### ea
121 clr.l TESTCTR(%a6)
122 pea ea_str(%pc)
123 bsr.l _print_str
124 addq.l &0x4,%sp
125
126 mov.l &0x2,EAMEM(%a6)
127 bsr.l ea_0
128
129 bsr.l chk_test
130
131### cas
132 clr.l TESTCTR(%a6)
133 pea cas_str(%pc)
134 bsr.l _print_str
135 addq.l &0x4,%sp
136
137 bsr.l cas0
138
139 bsr.l chk_test
140
141### cas2
142 clr.l TESTCTR(%a6)
143 pea cas2_str(%pc)
144 bsr.l _print_str
145 addq.l &0x4,%sp
146
147 bsr.l cas20
148
149 bsr.l chk_test
150
151###
152 movm.l (%sp)+,&0x3cfc
153
154 unlk %a6
155 rts
156
157#############################################
158#############################################
159
160mulul_str:
161 string "\t64-bit multiply..."
162
163 align 0x4
164mulul_0:
165 addq.l &0x1,TESTCTR(%a6)
166
167 movm.l DEF_REGS(%pc),&0x3fff
168
169 clr.l %d1
170 mov.l &0x99999999,%d2
171 mov.l &0x88888888,%d3
172
173 mov.w &0x0004,ICCR(%a6)
174 mov.w &0x0000,%cc
175 movm.l &0x7fff,IREGS(%a6)
176
177 mulu.l %d1,%d2:%d3
178
179 mov.w %cc,SCCR(%a6)
180 movm.l &0x7fff,SREGS(%a6)
181 clr.l IREGS+0x8(%a6)
182 clr.l IREGS+0xc(%a6)
183
184 bsr.l chkregs
185 tst.b %d0
186 bne.l error
187
188mulul_1:
189 addq.l &0x1,TESTCTR(%a6)
190
191 movm.l DEF_REGS(%pc),&0x3fff
192
193 mov.l &0x77777777,%d1
194 mov.l &0x99999999,%d2
195 mov.l &0x00000000,%d3
196
197 mov.w &0x0004,ICCR(%a6)
198 mov.w &0x0000,%cc
199 movm.l &0x7fff,IREGS(%a6)
200
201 mulu.l %d1,%d2:%d3
202
203 mov.w %cc,SCCR(%a6)
204 movm.l &0x7fff,SREGS(%a6)
205 clr.l IREGS+0x8(%a6)
206 clr.l IREGS+0xc(%a6)
207
208 bsr.l chkregs
209 tst.b %d0
210 bne.l error
211
212mulul_2:
213 addq.l &0x1,TESTCTR(%a6)
214
215 movm.l DEF_REGS(%pc),&0x3fff
216
217 mov.l &0x00000010,%d1
218 mov.l &0x66666666,%d2
219
220 mov.w &0x0000,ICCR(%a6)
221 mov.w &0x0000,%cc
222 movm.l &0x7fff,IREGS(%a6)
223
224 mulu.l %d1,%d2:%d2
225
226 mov.w %cc,SCCR(%a6)
227 movm.l &0x7fff,SREGS(%a6)
228 mov.l &0x00000006,IREGS+0x8(%a6)
229
230 bsr.l chkregs
231 tst.b %d0
232 bne.l error
233
234mulul_3:
235 addq.l &0x1,TESTCTR(%a6)
236
237 movm.l DEF_REGS(%pc),&0x3fff
238
239 mov.l &0x55555555,%d1
240 mov.l &0x00000000,%d2
241 mov.l &0x00000003,%d3
242
243 mov.w &0x0000,ICCR(%a6)
244 mov.w &0x0000,%cc
245 movm.l &0x7fff,IREGS(%a6)
246
247 mulu.l %d1,%d2:%d3
248
249 mov.w %cc,SCCR(%a6)
250 movm.l &0x7fff,SREGS(%a6)
251 mov.l &0x00000000,IREGS+0x8(%a6)
252 mov.l &0xffffffff,IREGS+0xc(%a6)
253
254 bsr.l chkregs
255 tst.b %d0
256 bne.l error
257
258mulul_4:
259 addq.l &0x1,TESTCTR(%a6)
260
261 movm.l DEF_REGS(%pc),&0x3fff
262
263 mov.l &0x40000000,%d1
264 mov.l &0x00000000,%d2
265 mov.l &0x00000004,%d3
266
267 mov.w &0x0000,ICCR(%a6)
268 mov.w &0x0000,%cc
269 movm.l &0x7fff,IREGS(%a6)
270
271 mulu.l %d1,%d2:%d3
272
273 mov.w %cc,SCCR(%a6)
274 movm.l &0x7fff,SREGS(%a6)
275 mov.l &0x00000001,IREGS+0x8(%a6)
276 mov.l &0x00000000,IREGS+0xc(%a6)
277
278 bsr.l chkregs
279 tst.b %d0
280 bne.l error
281
282mulul_5:
283 addq.l &0x1,TESTCTR(%a6)
284
285 movm.l DEF_REGS(%pc),&0x3fff
286
287 mov.l &0xffffffff,%d1
288 mov.l &0x00000000,%d2
289 mov.l &0xffffffff,%d3
290
291 mov.w &0x0008,ICCR(%a6)
292 mov.w &0x0000,%cc
293 movm.l &0x7fff,IREGS(%a6)
294
295 mulu.l %d1,%d2:%d3
296
297 mov.w %cc,SCCR(%a6)
298 movm.l &0x7fff,SREGS(%a6)
299 mov.l &0xfffffffe,IREGS+0x8(%a6)
300 mov.l &0x00000001,IREGS+0xc(%a6)
301
302 bsr.l chkregs
303 tst.b %d0
304 bne.l error
305
306mulul_6:
307 addq.l &0x1,TESTCTR(%a6)
308
309 movm.l DEF_REGS(%pc),&0x3fff
310
311 mov.l &0x80000000,%d1
312 mov.l &0x00000000,%d2
313 mov.l &0xffffffff,%d3
314
315 mov.w &0x00000,ICCR(%a6)
316 mov.w &0x0000,%cc
317 movm.l &0x7fff,IREGS(%a6)
318
319 muls.l %d1,%d2:%d3
320
321 mov.w %cc,SCCR(%a6)
322 movm.l &0x7fff,SREGS(%a6)
323 mov.l &0x00000000,IREGS+0x8(%a6)
324 mov.l &0x80000000,IREGS+0xc(%a6)
325
326 bsr.l chkregs
327 tst.b %d0
328 bne.l error
329
330mulul_7:
331 addq.l &0x1,TESTCTR(%a6)
332
333 movm.l DEF_REGS(%pc),&0x3fff
334
335 mov.l &0x80000000,%d1
336 mov.l &0x00000000,%d2
337 mov.l &0x00000001,%d3
338
339 mov.w &0x0008,ICCR(%a6)
340 mov.w &0x0000,%cc
341 movm.l &0x7fff,IREGS(%a6)
342
343 muls.l %d1,%d2:%d3
344
345 mov.w %cc,SCCR(%a6)
346 movm.l &0x7fff,SREGS(%a6)
347 mov.l &0xffffffff,IREGS+0x8(%a6)
348 mov.l &0x80000000,IREGS+0xc(%a6)
349
350 bsr.l chkregs
351 tst.b %d0
352 bne.l error
353
354mulul_8:
355 addq.l &0x1,TESTCTR(%a6)
356
357 movm.l DEF_REGS(%pc),&0x3fff
358
359 mov.l &0x00000001,%d1
360 mov.l &0x00000000,%d2
361 mov.l &0x80000000,%d3
362
363 mov.w &0x0008,ICCR(%a6)
364 mov.w &0x0000,%cc
365 movm.l &0x7fff,IREGS(%a6)
366
367 muls.l %d1,%d2:%d3
368
369 mov.w %cc,SCCR(%a6)
370 movm.l &0x7fff,SREGS(%a6)
371 mov.l &0xffffffff,IREGS+0x8(%a6)
372 mov.l &0x80000000,IREGS+0xc(%a6)
373
374 bsr.l chkregs
375 tst.b %d0
376 bne.l error
377
378 mov.l TESTCTR(%a6),%d1
379 clr.l %d0
380 rts
381
382#############################################
383
384movp_str:
385 string "\tmovep..."
386
387 align 0x4
388###############################
389# movep.w %d0,(0x0,%a0) #
390###############################
391movp_0:
392 addq.l &0x1,TESTCTR(%a6)
393
394 movm.l DEF_REGS(%pc),&0x3fff
395
396 lea DATA(%a6),%a0
397 mov.w &0xaaaa,%d0
398 clr.b 0x0(%a0)
399 clr.b 0x2(%a0)
400
401 mov.w &0x001f,ICCR(%a6)
402 mov.w &0x001f,%cc
403 movm.l &0x7fff,IREGS(%a6)
404
405 movp.w %d0,(0x0,%a0)
406
407 mov.w %cc,SCCR(%a6)
408 movm.l &0x7fff,SREGS(%a6)
409
410 mov.b 0x2(%a0),%d1
411 lsl.w &0x8,%d1
412 mov.b 0x0(%a0),%d1
413
414 cmp.w %d0,%d1
415 bne.l error
416
417 bsr.l chkregs
418 tst.b %d0
419 bne.l error
420
421###############################
422# movep.w %d0,(0x0,%a0) #
423###############################
424movp_1:
425 addq.l &0x1,TESTCTR(%a6)
426
427 movm.l DEF_REGS(%pc),&0x3fff
428
429 lea DATA+0x4(%a6),%a0
430 mov.w &0xaaaa,%d0
431 clr.l -0x4(%a0)
432 clr.l (%a0)
433 clr.l 0x4(%a0)
434
435 mov.w &0x001f,ICCR(%a6)
436 mov.w &0x001f,%cc
437 movm.l &0x7fff,IREGS(%a6)
438
439 movp.w %d0,(0x0,%a0)
440
441 mov.w %cc,SCCR(%a6)
442 movm.l &0x7fff,SREGS(%a6)
443
444 tst.l -0x4(%a0)
445 bne.l error
446 tst.l 0x4(%a0)
447 bne.l error
448 cmpi.l (%a0),&0xaa00aa00
449 bne.l error
450
451 bsr.l chkregs
452 tst.b %d0
453 bne.l error
454
455#####################################################
456# movep.w %d0,(0x0,%a0) #
457# - this test has %cc initially equal to zero #
458#####################################################
459movp_2:
460 addq.l &0x1,TESTCTR(%a6)
461
462 movm.l DEF_REGS(%pc),&0x3fff
463
464 lea DATA(%a6),%a0
465 mov.w &0xaaaa,%d0
466 clr.b 0x0(%a0)
467 clr.b 0x2(%a0)
468
469 mov.w &0x0000,ICCR(%a6)
470 mov.w &0x0000,%cc
471 movm.l &0x7fff,IREGS(%a6)
472
473 movp.w %d0,(0x0,%a0)
474
475 mov.w %cc,SCCR(%a6)
476 movm.l &0x7fff,SREGS(%a6)
477
478 mov.b 0x2(%a0),%d1
479 lsl.w &0x8,%d1
480 mov.b 0x0(%a0),%d1
481
482 cmp.w %d0,%d1
483 bne.l error
484
485 bsr.l chkregs
486 tst.b %d0
487 bne.l error
488
489###############################
490# movep.w (0x0,%a0),%d0 #
491###############################
492movp_3:
493 addq.l &0x1,TESTCTR(%a6)
494
495 movm.l DEF_REGS(%pc),&0x3fff
496
497 lea DATA(%a6),%a0
498 mov.b &0xaa,0x0(%a0)
499 mov.b &0xaa,0x2(%a0)
500
501 mov.w &0x001f,ICCR(%a6)
502 mov.w &0x001f,%cc
503 movm.l &0x7fff,IREGS(%a6)
504
505 movp.w (0x0,%a0),%d0
506
507 mov.w %cc,SCCR(%a6)
508 movm.l &0x7fff,SREGS(%a6)
509 mov.w &0xaaaa,IREGS+0x2(%a6)
510
511 mov.w &0xaaaa,%d1
512
513 cmp.w %d0,%d1
514 bne.l error
515
516 bsr.l chkregs
517 tst.b %d0
518 bne.l error
519
520###############################
521# movep.l %d0,(0x0,%a0) #
522###############################
523movp_4:
524 addq.l &0x1,TESTCTR(%a6)
525
526 movm.l DEF_REGS(%pc),&0x3fff
527
528 lea DATA(%a6),%a0
529 mov.l &0xaaaaaaaa,%d0
530 clr.b 0x0(%a0)
531 clr.b 0x2(%a0)
532 clr.b 0x4(%a0)
533 clr.b 0x6(%a0)
534
535 mov.w &0x001f,ICCR(%a6)
536 mov.w &0x001f,%cc
537 movm.l &0x7fff,IREGS(%a6)
538
539 movp.l %d0,(0x0,%a0)
540
541 mov.w %cc,SCCR(%a6)
542 movm.l &0x7fff,SREGS(%a6)
543
544 mov.b 0x6(%a0),%d1
545 lsl.l &0x8,%d1
546 mov.b 0x4(%a0),%d1
547 lsl.l &0x8,%d1
548 mov.b 0x2(%a0),%d1
549 lsl.l &0x8,%d1
550 mov.b 0x0(%a0),%d1
551
552 cmp.l %d0,%d1
553 bne.l error
554
555 bsr.l chkregs
556 tst.b %d0
557 bne.l error
558
559###############################
560# movep.l %d0,(0x0,%a0) #
561###############################
562movp_5:
563 addq.l &0x1,TESTCTR(%a6)
564
565 movm.l DEF_REGS(%pc),&0x3fff
566
567 lea DATA+0x4(%a6),%a0
568 mov.l &0xaaaaaaaa,%d0
569 clr.l -0x4(%a0)
570 clr.l (%a0)
571 clr.l 0x4(%a0)
572 clr.l 0x8(%a0)
573
574 mov.w &0x001f,ICCR(%a6)
575 mov.w &0x001f,%cc
576 movm.l &0x7fff,IREGS(%a6)
577
578 movp.l %d0,(0x0,%a0)
579
580 mov.w %cc,SCCR(%a6)
581 movm.l &0x7fff,SREGS(%a6)
582
583 tst.l -0x4(%a0)
584 bne.l error
585 tst.l 0x8(%a0)
586 bne.l error
587 cmpi.l (%a0),&0xaa00aa00
588 bne.l error
589 cmpi.l 0x4(%a0),&0xaa00aa00
590 bne.l error
591
592 bsr.l chkregs
593 tst.b %d0
594 bne.l error
595
596###############################
597# movep.l (0x0,%a0),%d0 #
598###############################
599movp_6:
600 addq.l &0x1,TESTCTR(%a6)
601
602 movm.l DEF_REGS(%pc),&0x3fff
603
604 lea DATA(%a6),%a0
605 mov.b &0xaa,0x0(%a0)
606 mov.b &0xaa,0x2(%a0)
607 mov.b &0xaa,0x4(%a0)
608 mov.b &0xaa,0x6(%a0)
609
610 mov.w &0x001f,ICCR(%a6)
611 mov.w &0x001f,%cc
612 movm.l &0x7fff,IREGS(%a6)
613
614 movp.l (0x0,%a0),%d0
615
616 mov.w %cc,SCCR(%a6)
617 movm.l &0x7fff,SREGS(%a6)
618 mov.l &0xaaaaaaaa,IREGS(%a6)
619
620 mov.l &0xaaaaaaaa,%d1
621
622 cmp.l %d0,%d1
623 bne.l error
624
625 bsr.l chkregs
626 tst.b %d0
627 bne.l error
628
629###############################
630# movep.w %d7,(0x0,%a0) #
631###############################
632movp_7:
633 addq.l &0x1,TESTCTR(%a6)
634
635 movm.l DEF_REGS(%pc),&0x3fff
636
637 lea DATA(%a6),%a0
638 mov.w &0xaaaa,%d7
639 clr.b 0x0(%a0)
640 clr.b 0x2(%a0)
641
642 mov.w &0x001f,ICCR(%a6)
643 mov.w &0x001f,%cc
644 movm.l &0x7fff,IREGS(%a6)
645
646 movp.w %d7,(0x0,%a0)
647
648 mov.w %cc,SCCR(%a6)
649 movm.l &0x7fff,SREGS(%a6)
650
651 mov.b 0x2(%a0),%d1
652 lsl.w &0x8,%d1
653 mov.b 0x0(%a0),%d1
654
655 cmp.w %d7,%d1
656 bne.l error
657
658 bsr.l chkregs
659 tst.b %d0
660 bne.l error
661
662###############################
663# movep.w (0x0,%a0),%d7 #
664###############################
665movp_8:
666 addq.l &0x1,TESTCTR(%a6)
667
668 movm.l DEF_REGS(%pc),&0x3fff
669
670 lea DATA(%a6),%a0
671 mov.b &0xaa,0x0(%a0)
672 mov.b &0xaa,0x2(%a0)
673
674 mov.w &0x001f,ICCR(%a6)
675 mov.w &0x001f,%cc
676 movm.l &0x7fff,IREGS(%a6)
677
678 movp.w (0x0,%a0),%d7
679
680 mov.w %cc,SCCR(%a6)
681 movm.l &0x7fff,SREGS(%a6)
682 mov.w &0xaaaa,IREGS+30(%a6)
683
684 mov.w &0xaaaa,%d1
685
686 cmp.w %d7,%d1
687 bne.l error
688
689 bsr.l chkregs
690 tst.b %d0
691 bne.l error
692
693###############################
694# movep.w %d0,(0x0,%a0) #
695###############################
696movp_9:
697 addq.l &0x1,TESTCTR(%a6)
698
699 movm.l DEF_REGS(%pc),&0x3fff
700
701 lea DATA(%a6),%a0
702 mov.w &0xaaaa,%d0
703 clr.b 0x0(%a0)
704 clr.b 0x2(%a0)
705
706 mov.w &0x001f,ICCR(%a6)
707 mov.w &0x001f,%cc
708 movm.l &0x7fff,IREGS(%a6)
709
710 movp.w %d0,(0x0,%a0)
711
712 mov.w %cc,SCCR(%a6)
713 movm.l &0x7fff,SREGS(%a6)
714
715 mov.b 0x2(%a0),%d1
716 lsl.w &0x8,%d1
717 mov.b 0x0(%a0),%d1
718
719 cmp.w %d0,%d1
720 bne.l error
721
722 bsr.l chkregs
723 tst.b %d0
724 bne.l error
725
726###############################
727# movep.w %d0,(0x8,%a0) #
728###############################
729movp_10:
730 addq.l &0x1,TESTCTR(%a6)
731
732 movm.l DEF_REGS(%pc),&0x3fff
733
734 lea DATA(%a6),%a0
735 mov.w &0xaaaa,%d0
736 clr.b 0x0+0x8(%a0)
737 clr.b 0x2+0x8(%a0)
738
739 mov.w &0x001f,ICCR(%a6)
740 mov.w &0x1f,%cc
741 movm.l &0x7fff,IREGS(%a6)
742
743 movp.w %d0,(0x8,%a0)
744
745 mov.w %cc,SCCR(%a6)
746 movm.l &0x7fff,SREGS(%a6)
747
748 mov.b 0x2+0x8(%a0),%d1
749 lsl.w &0x8,%d1
750 mov.b 0x0+0x8(%a0),%d1
751
752 cmp.w %d0,%d1
753 bne.l error
754
755 bsr.l chkregs
756 tst.b %d0
757 bne.l error
758
759###############################
760# movep.w (0x8,%a0),%d0 #
761###############################
762movp_11:
763 addq.l &0x1,TESTCTR(%a6)
764
765 movm.l DEF_REGS(%pc),&0x3fff
766
767 lea DATA(%a6),%a0
768 mov.b &0xaa,0x0+0x8(%a0)
769 mov.b &0xaa,0x2+0x8(%a0)
770
771 mov.w &0x001f,ICCR(%a6)
772 mov.w &0x1f,%cc
773 movm.l &0x7fff,IREGS(%a6)
774
775 movp.w (0x8,%a0),%d0
776
777 mov.w %cc,SCCR(%a6)
778 movm.l &0x7fff,SREGS(%a6)
779 mov.w &0xaaaa,IREGS+0x2(%a6)
780
781 mov.w &0xaaaa,%d1
782
783 cmp.w %d0,%d1
784 bne.l error
785
786 bsr.l chkregs
787 tst.b %d0
788 bne.l error
789
790###############################
791# movep.l %d0,(0x8,%a0) #
792###############################
793movp_12:
794 addq.l &0x1,TESTCTR(%a6)
795
796 movm.l DEF_REGS(%pc),&0x3fff
797
798 lea DATA(%a6),%a0
799 mov.l &0xaaaaaaaa,%d0
800 clr.b 0x0+0x8(%a0)
801 clr.b 0x2+0x8(%a0)
802 clr.b 0x4+0x8(%a0)
803 clr.b 0x6+0x8(%a0)
804
805 mov.w &0x001f,ICCR(%a6)
806 mov.w &0x1f,%cc
807 movm.l &0x7fff,IREGS(%a6)
808
809 movp.l %d0,(0x8,%a0)
810
811 mov.w %cc,SCCR(%a6)
812 movm.l &0x7fff,SREGS(%a6)
813
814 mov.b 0x6+0x8(%a0),%d1
815 lsl.l &0x8,%d1
816 mov.b 0x4+0x8(%a0),%d1
817 lsl.l &0x8,%d1
818 mov.b 0x2+0x8(%a0),%d1
819 lsl.l &0x8,%d1
820 mov.b 0x0+0x8(%a0),%d1
821
822 cmp.l %d0,%d1
823 bne.l error
824
825 bsr.l chkregs
826 tst.b %d0
827 bne.l error
828
829###############################
830# movep.l (0x8,%a0),%d0 #
831###############################
832movp_13:
833 addq.l &0x1,TESTCTR(%a6)
834
835 movm.l DEF_REGS(%pc),&0x3fff
836
837 lea DATA(%a6),%a0
838 mov.b &0xaa,0x0+0x8(%a0)
839 mov.b &0xaa,0x2+0x8(%a0)
840 mov.b &0xaa,0x4+0x8(%a0)
841 mov.b &0xaa,0x6+0x8(%a0)
842
843 mov.w &0x001f,ICCR(%a6)
844 mov.w &0x1f,%cc
845 movm.l &0x7fff,IREGS(%a6)
846
847 movp.l (0x8,%a0),%d0
848
849 mov.w %cc,SCCR(%a6)
850 movm.l &0x7fff,SREGS(%a6)
851 mov.l &0xaaaaaaaa,IREGS(%a6)
852
853 mov.l &0xaaaaaaaa,%d1
854
855 cmp.l %d0,%d1
856 bne.l error
857
858 bsr.l chkregs
859 tst.b %d0
860 bne.l error
861
862################################
863# movep.w %d0,(-0x8,%a0) #
864################################
865movp_14:
866 addq.l &0x1,TESTCTR(%a6)
867
868 movm.l DEF_REGS(%pc),&0x3fff
869
870 lea DATA+0x8(%a6),%a0
871 mov.w &0xaaaa,%d0
872 clr.b 0x0-0x8(%a0)
873 clr.b 0x2-0x8(%a0)
874
875 mov.w &0x001f,ICCR(%a6)
876 mov.w &0x1f,%cc
877 movm.l &0x7fff,IREGS(%a6)
878
879 movp.w %d0,(-0x8,%a0)
880
881 mov.w %cc,SCCR(%a6)
882 movm.l &0x7fff,SREGS(%a6)
883
884 mov.b 0x2-0x8(%a0),%d1
885 lsl.w &0x8,%d1
886 mov.b 0x0-0x8(%a0),%d1
887
888 cmp.w %d0,%d1
889 bne.l error
890
891 bsr.l chkregs
892 tst.b %d0
893 bne.l error
894
895################################
896# movep.w (-0x8,%a0),%d0 #
897################################
898movp_15:
899 addq.l &0x1,TESTCTR(%a6)
900
901 movm.l DEF_REGS(%pc),&0x3fff
902
903 lea DATA+0x8(%a6),%a0
904 mov.b &0xaa,0x0-0x8(%a0)
905 mov.b &0xaa,0x2-0x8(%a0)
906
907 mov.w &0x001f,ICCR(%a6)
908 mov.w &0x1f,%cc
909 movm.l &0x7fff,IREGS(%a6)
910
911 movp.w (-0x8,%a0),%d0
912
913 mov.w %cc,SCCR(%a6)
914 movm.l &0x7fff,SREGS(%a6)
915 mov.w &0xaaaa,IREGS+0x2(%a6)
916
917 mov.w &0xaaaa,%d1
918
919 cmp.w %d0,%d1
920 bne.l error
921
922 bsr.l chkregs
923 tst.b %d0
924 bne.l error
925
926################################
927# movep.l %d0,(-0x8,%a0) #
928################################
929movp_16:
930 addq.l &0x1,TESTCTR(%a6)
931
932 movm.l DEF_REGS(%pc),&0x3fff
933
934 lea DATA+0x8(%a6),%a0
935 mov.l &0xaaaaaaaa,%d0
936 clr.b 0x0-0x8(%a0)
937 clr.b 0x2-0x8(%a0)
938 clr.b 0x4-0x8(%a0)
939 clr.b 0x8-0x8(%a0)
940
941 mov.w &0x001f,ICCR(%a6)
942 mov.w &0x1f,%cc
943 movm.l &0x7fff,IREGS(%a6)
944
945 movp.l %d0,(-0x8,%a0)
946
947 mov.w %cc,SCCR(%a6)
948 movm.l &0x7fff,SREGS(%a6)
949
950 mov.b 0x6-0x8(%a0),%d1
951 lsl.l &0x8,%d1
952 mov.b 0x4-0x8(%a0),%d1
953 lsl.l &0x8,%d1
954 mov.b 0x2-0x8(%a0),%d1
955 lsl.l &0x8,%d1
956 mov.b 0x0-0x8(%a0),%d1
957
958 cmp.l %d0,%d1
959 bne.l error
960
961 bsr.l chkregs
962 tst.b %d0
963 bne.l error
964
965################################
966# movep.l (-0x8,%a0),%d0 #
967################################
968movp_17:
969 addq.l &0x1,TESTCTR(%a6)
970
971 movm.l DEF_REGS(%pc),&0x3fff
972
973 lea DATA+0x8(%a6),%a0
974 mov.b &0xaa,0x0-0x8(%a0)
975 mov.b &0xaa,0x2-0x8(%a0)
976 mov.b &0xaa,0x4-0x8(%a0)
977 mov.b &0xaa,0x8-0x8(%a0)
978
979 mov.w &0x001f,ICCR(%a6)
980 mov.w &0x1f,%cc
981 movm.l &0x7fff,IREGS(%a6)
982
983 movp.l (-0x8,%a0),%d0
984
985 mov.w %cc,SCCR(%a6)
986 movm.l &0x7fff,SREGS(%a6)
987 mov.l &0xaaaaaaaa,IREGS(%a6)
988
989 mov.l &0xaaaaaaaa,%d1
990
991 cmp.l %d0,%d1
992 bne.l error
993
994 bsr.l chkregs
995 tst.b %d0
996 bne.l error
997
998 mov.l TESTCTR(%a6),%d1
999 clr.l %d0
1000 rts
1001
1002###########################################################
1003
1004divul_str:
1005 string "\t64-bit divide..."
1006
1007 align 0x4
1008divul_0:
1009 addq.l &0x1,TESTCTR(%a6)
1010
1011# movm.l DEF_REGS(%pc),&0x3fff
1012
1013# clr.l %d1
1014# mov.l &0x99999999,%d2
1015# mov.l &0x88888888,%d3
1016
1017# mov.w &0x001e,ICCR(%a6)
1018# mov.w &0x001f,%cc
1019# movm.l &0x7fff,IREGS(%a6)
1020
1021# divu.l %d1,%d2:%d3
1022
1023# mov.w %cc,SCCR(%a6)
1024# movm.l &0x7fff,SREGS(%a6)
1025
1026# bsr.l chkregs
1027# tst.b %d0
1028# bne.l error
1029
1030divul_1:
1031 addq.l &0x1,TESTCTR(%a6)
1032
1033 movm.l DEF_REGS(%pc),&0x3fff
1034
1035 mov.l &0x00000001,%d1
1036 mov.l &0x00000000,%d2
1037 mov.l &0x00000000,%d3
1038
1039 mov.w &0x0014,ICCR(%a6)
1040 mov.w &0x001f,%cc
1041 movm.l &0x7fff,IREGS(%a6)
1042
1043 divu.l %d1,%d2:%d3
1044
1045 mov.w %cc,SCCR(%a6)
1046 movm.l &0x7fff,SREGS(%a6)
1047
1048 bsr.l chkregs
1049 tst.b %d0
1050 bne.l error
1051
1052divul_2:
1053 addq.l &0x1,TESTCTR(%a6)
1054
1055 movm.l DEF_REGS(%pc),&0x3fff
1056
1057 mov.l &0x44444444,%d1
1058 mov.l &0x00000000,%d2
1059 mov.l &0x55555555,%d3
1060
1061 mov.w &0x0010,ICCR(%a6)
1062 mov.w &0x001f,%cc
1063 movm.l &0x7fff,IREGS(%a6)
1064
1065 divu.l %d1,%d2:%d3
1066
1067 mov.w %cc,SCCR(%a6)
1068 movm.l &0x7fff,SREGS(%a6)
1069 mov.l &0x11111111,IREGS+0x8(%a6)
1070 mov.l &0x00000001,IREGS+0xc(%a6)
1071
1072 bsr.l chkregs
1073 tst.b %d0
1074 bne.l error
1075
1076divul_3:
1077 addq.l &0x1,TESTCTR(%a6)
1078
1079 movm.l DEF_REGS(%pc),&0x3fff
1080
1081 mov.l &0x55555555,%d1
1082 mov.l &0x00000000,%d2
1083 mov.l &0x44444444,%d3
1084
1085 mov.w &0x0014,ICCR(%a6)
1086 mov.w &0x001f,%cc
1087 movm.l &0x7fff,IREGS(%a6)
1088
1089 divu.l %d1,%d2:%d3
1090
1091 mov.w %cc,SCCR(%a6)
1092 movm.l &0x7fff,SREGS(%a6)
1093 mov.l &0x44444444,IREGS+0x8(%a6)
1094 mov.l &0x00000000,IREGS+0xc(%a6)
1095
1096 bsr.l chkregs
1097 tst.b %d0
1098 bne.l error
1099
1100divul_4:
1101 addq.l &0x1,TESTCTR(%a6)
1102
1103 movm.l DEF_REGS(%pc),&0x3fff
1104
1105 mov.l &0x11111111,%d1
1106 mov.l &0x44444444,%d2
1107 mov.l &0x44444444,%d3
1108
1109 mov.w &0x001e,ICCR(%a6)
1110 mov.w &0x001d,%cc
1111 movm.l &0x7fff,IREGS(%a6)
1112
1113 divu.l %d1,%d2:%d3
1114
1115 mov.w %cc,SCCR(%a6)
1116 movm.l &0x7fff,SREGS(%a6)
1117
1118 bsr.l chkregs
1119 tst.b %d0
1120 bne.l error
1121
1122divul_5:
1123 addq.l &0x1,TESTCTR(%a6)
1124
1125 movm.l DEF_REGS(%pc),&0x3fff
1126
1127 mov.l &0xfffffffe,%d1
1128 mov.l &0x00000001,%d2
1129 mov.l &0x00000002,%d3
1130
1131 mov.w &0x001e,ICCR(%a6)
1132 mov.w &0x001d,%cc
1133 movm.l &0x7fff,IREGS(%a6)
1134
1135 divs.l %d1,%d2:%d3
1136
1137 mov.w %cc,SCCR(%a6)
1138 movm.l &0x7fff,SREGS(%a6)
1139
1140 bsr.l chkregs
1141 tst.b %d0
1142 bne.l error
1143
1144divul_6:
1145 addq.l &0x1,TESTCTR(%a6)
1146
1147 movm.l DEF_REGS(%pc),&0x3fff
1148
1149 mov.l &0xfffffffe,%d1
1150 mov.l &0x00000001,%d2
1151 mov.l &0x00000000,%d3
1152
1153 mov.w &0x0018,ICCR(%a6)
1154 mov.w &0x001d,%cc
1155 movm.l &0x7fff,IREGS(%a6)
1156
1157 divs.l %d1,%d2:%d3
1158
1159 mov.w %cc,SCCR(%a6)
1160 movm.l &0x7fff,SREGS(%a6)
1161 mov.l &0x00000000,IREGS+0x8(%a6)
1162 mov.l &0x80000000,IREGS+0xc(%a6)
1163
1164 bsr.l chkregs
1165 tst.b %d0
1166 bne.l error
1167
1168divul_7:
1169 addq.l &0x1,TESTCTR(%a6)
1170
1171 movm.l DEF_REGS(%pc),&0x3fff
1172
1173 mov.l &0x00000002,%d1
1174 mov.l &0x00000001,%d2
1175 mov.l &0x00000000,%d3
1176
1177 mov.w &0x001e,ICCR(%a6)
1178 mov.w &0x001d,%cc
1179 movm.l &0x7fff,IREGS(%a6)
1180
1181 divs.l %d1,%d2:%d3
1182
1183 mov.w %cc,SCCR(%a6)
1184 movm.l &0x7fff,SREGS(%a6)
1185
1186 bsr.l chkregs
1187 tst.b %d0
1188 bne.l error
1189
1190divul_8:
1191 addq.l &0x1,TESTCTR(%a6)
1192
1193 movm.l DEF_REGS(%pc),&0x3fff
1194
1195 mov.l &0xffffffff,%d1
1196 mov.l &0xfffffffe,%d2
1197 mov.l &0xffffffff,%d3
1198
1199 mov.w &0x0008,ICCR(%a6)
1200 mov.w &0x0000,%cc
1201 movm.l &0x7fff,IREGS(%a6)
1202
1203 divu.l %d1,%d2:%d3
1204
1205 mov.w %cc,SCCR(%a6)
1206 movm.l &0x7fff,SREGS(%a6)
1207
1208 bsr.l chkregs
1209 tst.b %d0
1210 bne.l error
1211
1212divul_9:
1213 addq.l &0x1,TESTCTR(%a6)
1214
1215 movm.l DEF_REGS(%pc),&0x3fff
1216
1217 mov.l &0xffffffff,%d1
1218 mov.l &0xfffffffe,%d2
1219 mov.l &0xffffffff,%d3
1220
1221 mov.w &0x0008,ICCR(%a6)
1222 mov.w &0x0000,%cc
1223 movm.l &0x7fff,IREGS(%a6)
1224
1225 divu.l &0xffffffff,%d2:%d2
1226
1227 mov.w %cc,SCCR(%a6)
1228 movm.l &0x7fff,SREGS(%a6)
1229 mov.l &0xffffffff,IREGS+0x8(%a6)
1230
1231 bsr.l chkregs
1232 tst.b %d0
1233 bne.l error
1234
1235divul_10:
1236 addq.l &0x1,TESTCTR(%a6)
1237
1238 movm.l DEF_REGS(%pc),&0x3fff
1239
1240 mov.l &0x0000ffff,%d1
1241 mov.l &0x00000001,%d2
1242 mov.l &0x55555555,%d3
1243
1244 mov.w &0x0000,ICCR(%a6)
1245 mov.w &0x0000,%cc
1246 movm.l &0x7fff,IREGS(%a6)
1247
1248 divu.l %d1,%d2:%d3
1249
1250 mov.w %cc,SCCR(%a6)
1251 movm.l &0x7fff,SREGS(%a6)
1252 mov.l &0x0000aaab,IREGS+0x8(%a6)
1253 mov.l &0x00015556,IREGS+0xc(%a6)
1254
1255 bsr.l chkregs
1256 tst.b %d0
1257 bne.l error
1258
1259 mov.l TESTCTR(%a6),%d1
1260 clr.l %d0
1261 rts
1262
1263###########################################################
1264
1265cas_str:
1266 string "\tcas..."
1267
1268 align 0x4
1269cas0:
1270 addq.l &0x1,TESTCTR(%a6)
1271
1272 movm.l DEF_REGS(%pc),&0x3fff
1273
1274 lea DATA+0x1(%a6),%a0
1275
1276 mov.w &0xaaaa,(%a0)
1277
1278 mov.w &0xaaaa,%d1
1279 mov.w &0xbbbb,%d2
1280
1281 mov.w &0x0014,ICCR(%a6)
1282 mov.w &0x0010,%cc
1283 movm.l &0x7fff,IREGS(%a6)
1284
1285 cas.w %d1,%d2,(%a0) # Dc,Du,<ea>
1286
1287 mov.w %cc,SCCR(%a6)
1288 mov.w (%a0),%d3
1289 mov.w &0xbbbb,IREGS+0xc+0x2(%a6)
1290 movm.l &0x7fff,SREGS(%a6)
1291
1292 bsr.l chkregs
1293 tst.b %d0
1294 bne.l error
1295
1296cas1:
1297 addq.l &0x1,TESTCTR(%a6)
1298
1299 movm.l DEF_REGS(%pc),&0x3fff
1300
1301 lea DATA+0x1(%a6),%a0
1302
1303 mov.w &0xeeee,(%a0)
1304
1305 mov.w &0x0000aaaa,%d1
1306 mov.w &0x0000bbbb,%d2
1307
1308 mov.w &0x0000,ICCR(%a6)
1309 mov.w &0x0000,%cc
1310 movm.l &0x7fff,IREGS(%a6)
1311
1312 cas.w %d1,%d2,(%a0) # Dc,Du,<ea>
1313
1314 mov.w %cc,SCCR(%a6)
1315 mov.w (%a0),%d3
1316 mov.w &0xeeee,IREGS+0x4+0x2(%a6)
1317 mov.w &0xeeee,IREGS+0xc+0x2(%a6)
1318 movm.l &0x7fff,SREGS(%a6)
1319
1320 bsr.l chkregs
1321 tst.b %d0
1322 bne.l error
1323
1324cas2:
1325 addq.l &0x1,TESTCTR(%a6)
1326
1327 movm.l DEF_REGS(%pc),&0x3fff
1328
1329 lea DATA+0x2(%a6),%a0
1330
1331 mov.l &0xaaaaaaaa,(%a0)
1332
1333 mov.l &0xaaaaaaaa,%d1
1334 mov.l &0xbbbbbbbb,%d2
1335
1336 mov.w &0x0004,ICCR(%a6)
1337 mov.w &0x0000,%cc
1338 movm.l &0x7fff,IREGS(%a6)
1339
1340 cas.l %d1,%d2,(%a0) # Dc,Du,<ea>
1341
1342 mov.w %cc,SCCR(%a6)
1343 mov.l (%a0),%d3
1344 mov.l &0xbbbbbbbb,IREGS+0xc(%a6)
1345 movm.l &0x7fff,SREGS(%a6)
1346
1347 bsr.l chkregs
1348 tst.b %d0
1349 bne.l error
1350
1351cas3:
1352 addq.l &0x1,TESTCTR(%a6)
1353
1354 movm.l DEF_REGS(%pc),&0x3fff
1355
1356 lea DATA+0x2(%a6),%a0
1357
1358 mov.l &0xeeeeeeee,(%a0)
1359
1360 mov.l &0xaaaaaaaa,%d1
1361 mov.l &0xbbbbbbbb,%d2
1362
1363 mov.w &0x0000,ICCR(%a6)
1364 mov.w &0x0000,%cc
1365 movm.l &0x7fff,IREGS(%a6)
1366
1367 cas.l %d1,%d2,(%a0) # Dc,Du,<ea>
1368
1369 mov.w %cc,SCCR(%a6)
1370 mov.l (%a0),%d3
1371 mov.l &0xeeeeeeee,IREGS+0x4(%a6)
1372 mov.l &0xeeeeeeee,IREGS+0xc(%a6)
1373 movm.l &0x7fff,SREGS(%a6)
1374
1375 bsr.l chkregs
1376 tst.b %d0
1377 bne.l error
1378
1379cas4:
1380 addq.l &0x1,TESTCTR(%a6)
1381
1382 movm.l DEF_REGS(%pc),&0x3fff
1383
1384 lea DATA+0x1(%a6),%a0
1385
1386 mov.l &0xaaaaaaaa,(%a0)
1387
1388 mov.l &0xaaaaaaaa,%d1
1389 mov.l &0xbbbbbbbb,%d2
1390
1391 mov.w &0x0004,ICCR(%a6)
1392 mov.w &0x0000,%cc
1393 movm.l &0x7fff,IREGS(%a6)
1394
1395 cas.l %d1,%d2,(%a0) # Dc,Du,<ea>
1396
1397 mov.w %cc,SCCR(%a6)
1398 mov.l (%a0),%d3
1399 mov.l &0xbbbbbbbb,IREGS+0xc(%a6)
1400 movm.l &0x7fff,SREGS(%a6)
1401
1402 bsr.l chkregs
1403 tst.b %d0
1404 bne.l error
1405
1406cas5:
1407 addq.l &0x1,TESTCTR(%a6)
1408
1409 movm.l DEF_REGS(%pc),&0x3fff
1410
1411 lea DATA+0x1(%a6),%a0
1412
1413 mov.l &0x7fffffff,(%a0)
1414
1415 mov.l &0x80000000,%d1
1416 mov.l &0xbbbbbbbb,%d2
1417
1418 mov.w &0x001b,ICCR(%a6)
1419 mov.w &0x0010,%cc
1420 movm.l &0x7fff,IREGS(%a6)
1421
1422 cas.l %d1,%d2,(%a0) # Dc,Du,<ea>
1423
1424 mov.w %cc,SCCR(%a6)
1425 mov.l (%a0),%d3
1426 mov.l &0x7fffffff,IREGS+0x4(%a6)
1427 mov.l &0x7fffffff,IREGS+0xc(%a6)
1428 movm.l &0x7fff,SREGS(%a6)
1429
1430 bsr.l chkregs
1431 tst.b %d0
1432 bne.l error
1433
1434 mov.l TESTCTR(%a6),%d1
1435 clr.l %d0
1436 rts
1437
1438###########################################################
1439
1440cas2_str:
1441 string "\tcas2..."
1442
1443 align 0x4
1444cas20:
1445 addq.l &0x1,TESTCTR(%a6)
1446
1447 movm.l DEF_REGS(%pc),&0x3fff
1448
1449 lea DATA+0x0(%a6),%a0
1450 lea DATA+0x4(%a6),%a1
1451
1452 mov.l &0xaaaaaaaa,(%a0)
1453 mov.l &0xbbbbbbbb,(%a1)
1454
1455 mov.l &0xaaaaaaaa,%d1
1456 mov.l &0xbbbbbbbb,%d2
1457 mov.l &0xcccccccc,%d3
1458 mov.l &0xdddddddd,%d4
1459
1460 mov.w &0x0014,ICCR(%a6)
1461 mov.w &0x0010,%cc
1462 movm.l &0x7fff,IREGS(%a6)
1463
1464 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1465
1466 mov.w %cc,SCCR(%a6)
1467 mov.l (%a0),%d5
1468 mov.l (%a1),%d6
1469 mov.l &0xcccccccc,IREGS+0x14(%a6)
1470 mov.l &0xdddddddd,IREGS+0x18(%a6)
1471 movm.l &0x7fff,SREGS(%a6)
1472
1473 bsr.l chkregs
1474 tst.b %d0
1475 bne.l error
1476
1477cas21:
1478 addq.l &0x1,TESTCTR(%a6)
1479
1480 movm.l DEF_REGS(%pc),&0x3fff
1481
1482 lea DATA+0x1(%a6),%a0
1483 lea DATA+0x5(%a6),%a1
1484
1485 mov.l &0xaaaaaaaa,(%a0)
1486 mov.l &0xbbbbbbbb,(%a1)
1487
1488 mov.l &0xaaaaaaaa,%d1
1489 mov.l &0xbbbbbbbb,%d2
1490 mov.l &0xcccccccc,%d3
1491 mov.l &0xdddddddd,%d4
1492
1493 mov.w &0x0014,ICCR(%a6)
1494 mov.w &0x0010,%cc
1495 movm.l &0x7fff,IREGS(%a6)
1496
1497 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1498
1499 mov.w %cc,SCCR(%a6)
1500 mov.l (%a0),%d5
1501 mov.l (%a1),%d6
1502 mov.l &0xcccccccc,IREGS+0x14(%a6)
1503 mov.l &0xdddddddd,IREGS+0x18(%a6)
1504 movm.l &0x7fff,SREGS(%a6)
1505
1506 bsr.l chkregs
1507 tst.b %d0
1508 bne.l error
1509
1510cas22:
1511 addq.l &0x1,TESTCTR(%a6)
1512
1513 movm.l DEF_REGS(%pc),&0x3fff
1514
1515 lea DATA+0x2(%a6),%a0
1516 lea DATA+0x6(%a6),%a1
1517
1518 mov.l &0xaaaaaaaa,(%a0)
1519 mov.l &0xbbbbbbbb,(%a1)
1520
1521 mov.l &0xaaaaaaaa,%d1
1522 mov.l &0xbbbbbbbb,%d2
1523 mov.l &0xcccccccc,%d3
1524 mov.l &0xdddddddd,%d4
1525
1526 mov.w &0x0014,ICCR(%a6)
1527 mov.w &0x0010,%cc
1528 movm.l &0x7fff,IREGS(%a6)
1529
1530 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1531
1532 mov.w %cc,SCCR(%a6)
1533 mov.l (%a0),%d5
1534 mov.l (%a1),%d6
1535 mov.l &0xcccccccc,IREGS+0x14(%a6)
1536 mov.l &0xdddddddd,IREGS+0x18(%a6)
1537 movm.l &0x7fff,SREGS(%a6)
1538
1539 bsr.l chkregs
1540 tst.b %d0
1541 bne.l error
1542
1543cas23:
1544 addq.l &0x1,TESTCTR(%a6)
1545
1546 movm.l DEF_REGS(%pc),&0x3fff
1547
1548 lea DATA+0x0(%a6),%a0
1549 lea DATA+0x4(%a6),%a1
1550
1551 mov.l &0xeeeeeeee,(%a0)
1552 mov.l &0xbbbbbbbb,(%a1)
1553
1554 mov.l &0xaaaaaaaa,%d1
1555 mov.l &0xbbbbbbbb,%d2
1556 mov.l &0xcccccccc,%d3
1557 mov.l &0xdddddddd,%d4
1558
1559 mov.w &0x0000,ICCR(%a6)
1560 mov.w &0x0000,%cc
1561 movm.l &0x7fff,IREGS(%a6)
1562
1563 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1564
1565 mov.w %cc,SCCR(%a6)
1566 mov.l (%a0),%d5
1567 mov.l (%a1),%d6
1568 mov.l &0xeeeeeeee,IREGS+0x4(%a6)
1569 mov.l &0xbbbbbbbb,IREGS+0x8(%a6)
1570 mov.l &0xeeeeeeee,IREGS+0x14(%a6)
1571 mov.l &0xbbbbbbbb,IREGS+0x18(%a6)
1572 movm.l &0x7fff,SREGS(%a6)
1573
1574 bsr.l chkregs
1575 tst.b %d0
1576 bne.l error
1577
1578cas24:
1579 addq.l &0x1,TESTCTR(%a6)
1580
1581 movm.l DEF_REGS(%pc),&0x3fff
1582
1583 lea DATA+0x1(%a6),%a0
1584 lea DATA+0x5(%a6),%a1
1585
1586 mov.l &0xeeeeeeee,(%a0)
1587 mov.l &0xbbbbbbbb,(%a1)
1588
1589 mov.l &0xaaaaaaaa,%d1
1590 mov.l &0xbbbbbbbb,%d2
1591 mov.l &0xcccccccc,%d3
1592 mov.l &0xdddddddd,%d4
1593
1594 mov.w &0x0000,ICCR(%a6)
1595 mov.w &0x0000,%cc
1596 movm.l &0x7fff,IREGS(%a6)
1597
1598 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1599
1600 mov.w %cc,SCCR(%a6)
1601 mov.l (%a0),%d5
1602 mov.l (%a1),%d6
1603 mov.l &0xeeeeeeee,IREGS+0x4(%a6)
1604 mov.l &0xbbbbbbbb,IREGS+0x8(%a6)
1605 mov.l &0xeeeeeeee,IREGS+0x14(%a6)
1606 mov.l &0xbbbbbbbb,IREGS+0x18(%a6)
1607 movm.l &0x7fff,SREGS(%a6)
1608
1609 bsr.l chkregs
1610 tst.b %d0
1611 bne.l error
1612
1613cas25:
1614 addq.l &0x1,TESTCTR(%a6)
1615
1616 movm.l DEF_REGS(%pc),&0x3fff
1617
1618 lea DATA+0x2(%a6),%a0
1619 lea DATA+0x6(%a6),%a1
1620
1621 mov.l &0xeeeeeeee,(%a0)
1622 mov.l &0xbbbbbbbb,(%a1)
1623
1624 mov.l &0xaaaaaaaa,%d1
1625 mov.l &0xbbbbbbbb,%d2
1626 mov.l &0xcccccccc,%d3
1627 mov.l &0xdddddddd,%d4
1628
1629 mov.w &0x0000,ICCR(%a6)
1630 mov.w &0x0000,%cc
1631 movm.l &0x7fff,IREGS(%a6)
1632
1633 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1634
1635 mov.w %cc,SCCR(%a6)
1636 mov.l (%a0),%d5
1637 mov.l (%a1),%d6
1638 mov.l &0xeeeeeeee,IREGS+0x4(%a6)
1639 mov.l &0xbbbbbbbb,IREGS+0x8(%a6)
1640 mov.l &0xeeeeeeee,IREGS+0x14(%a6)
1641 mov.l &0xbbbbbbbb,IREGS+0x18(%a6)
1642 movm.l &0x7fff,SREGS(%a6)
1643
1644 bsr.l chkregs
1645 tst.b %d0
1646 bne.l error
1647
1648cas26:
1649 addq.l &0x1,TESTCTR(%a6)
1650
1651 movm.l DEF_REGS(%pc),&0x3fff
1652
1653 lea DATA+0x0(%a6),%a0
1654 lea DATA+0x4(%a6),%a1
1655
1656 mov.l &0xaaaaaaaa,(%a0)
1657 mov.l &0xeeeeeeee,(%a1)
1658
1659 mov.l &0xaaaaaaaa,%d1
1660 mov.l &0xbbbbbbbb,%d2
1661 mov.l &0xcccccccc,%d3
1662 mov.l &0xdddddddd,%d4
1663
1664 mov.w &0x0000,ICCR(%a6)
1665 mov.w &0x0000,%cc
1666 movm.l &0x7fff,IREGS(%a6)
1667
1668 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1669
1670 mov.w %cc,SCCR(%a6)
1671 mov.l (%a0),%d5
1672 mov.l (%a1),%d6
1673 mov.l &0xaaaaaaaa,IREGS+0x4(%a6)
1674 mov.l &0xeeeeeeee,IREGS+0x8(%a6)
1675 mov.l &0xaaaaaaaa,IREGS+0x14(%a6)
1676 mov.l &0xeeeeeeee,IREGS+0x18(%a6)
1677 movm.l &0x7fff,SREGS(%a6)
1678
1679 bsr.l chkregs
1680 tst.b %d0
1681 bne.l error
1682
1683cas27:
1684 addq.l &0x1,TESTCTR(%a6)
1685
1686 movm.l DEF_REGS(%pc),&0x3fff
1687
1688 lea DATA+0x1(%a6),%a0
1689 lea DATA+0x5(%a6),%a1
1690
1691 mov.l &0xaaaaaaaa,(%a0)
1692 mov.l &0xeeeeeeee,(%a1)
1693
1694 mov.l &0xaaaaaaaa,%d1
1695 mov.l &0xbbbbbbbb,%d2
1696 mov.l &0xcccccccc,%d3
1697 mov.l &0xdddddddd,%d4
1698
1699 mov.w &0x0000,ICCR(%a6)
1700 mov.w &0x0000,%cc
1701 movm.l &0x7fff,IREGS(%a6)
1702
1703 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1704
1705 mov.w %cc,SCCR(%a6)
1706 mov.l (%a0),%d5
1707 mov.l (%a1),%d6
1708 mov.l &0xaaaaaaaa,IREGS+0x4(%a6)
1709 mov.l &0xeeeeeeee,IREGS+0x8(%a6)
1710 mov.l &0xaaaaaaaa,IREGS+0x14(%a6)
1711 mov.l &0xeeeeeeee,IREGS+0x18(%a6)
1712 movm.l &0x7fff,SREGS(%a6)
1713
1714 bsr.l chkregs
1715 tst.b %d0
1716 bne.l error
1717
1718cas28:
1719 addq.l &0x1,TESTCTR(%a6)
1720
1721 movm.l DEF_REGS(%pc),&0x3fff
1722
1723 lea DATA+0x2(%a6),%a0
1724 lea DATA+0x6(%a6),%a1
1725
1726 mov.l &0xaaaaaaaa,(%a0)
1727 mov.l &0x7fffffff,(%a1)
1728
1729 mov.l &0xaaaaaaaa,%d1
1730 mov.l &0x80000000,%d2
1731 mov.l &0xcccccccc,%d3
1732 mov.l &0xdddddddd,%d4
1733
1734 mov.w &0x000b,ICCR(%a6)
1735 mov.w &0x0000,%cc
1736 movm.l &0x7fff,IREGS(%a6)
1737
1738 cas2.l %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1739
1740 mov.w %cc,SCCR(%a6)
1741 mov.l (%a0),%d5
1742 mov.l (%a1),%d6
1743 mov.l &0xaaaaaaaa,IREGS+0x4(%a6)
1744 mov.l &0x7fffffff,IREGS+0x8(%a6)
1745 mov.l &0xaaaaaaaa,IREGS+0x14(%a6)
1746 mov.l &0x7fffffff,IREGS+0x18(%a6)
1747 movm.l &0x7fff,SREGS(%a6)
1748
1749 bsr.l chkregs
1750 tst.b %d0
1751 bne.l error
1752
1753##################################
1754cas29:
1755 addq.l &0x1,TESTCTR(%a6)
1756
1757 movm.l DEF_REGS(%pc),&0x3fff
1758
1759 lea DATA+0x0(%a6),%a0
1760 lea DATA+0x4(%a6),%a1
1761
1762 mov.w &0xaaaa,(%a0)
1763 mov.w &0xbbbb,(%a1)
1764
1765 mov.w &0xaaaa,%d1
1766 mov.w &0xbbbb,%d2
1767 mov.w &0xcccc,%d3
1768 mov.w &0xdddd,%d4
1769
1770 mov.w &0x0014,ICCR(%a6)
1771 mov.w &0x0010,%cc
1772 movm.l &0x7fff,IREGS(%a6)
1773
1774 cas2.w %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1775
1776 mov.w %cc,SCCR(%a6)
1777 mov.w (%a0),%d5
1778 mov.w (%a1),%d6
1779 mov.w &0xcccc,IREGS+0x14+0x2(%a6)
1780 mov.w &0xdddd,IREGS+0x18+0x2(%a6)
1781 movm.l &0x7fff,SREGS(%a6)
1782
1783 bsr.l chkregs
1784 tst.b %d0
1785 bne.l error
1786
1787cas210:
1788 addq.l &0x1,TESTCTR(%a6)
1789
1790 movm.l DEF_REGS(%pc),&0x3fff
1791
1792 lea DATA+0x1(%a6),%a0
1793 lea DATA+0x5(%a6),%a1
1794
1795 mov.w &0xaaaa,(%a0)
1796 mov.w &0xbbbb,(%a1)
1797
1798 mov.w &0xaaaa,%d1
1799 mov.w &0xbbbb,%d2
1800 mov.w &0xcccc,%d3
1801 mov.w &0xdddd,%d4
1802
1803 mov.w &0x0004,ICCR(%a6)
1804 mov.w &0x0000,%cc
1805 movm.l &0x7fff,IREGS(%a6)
1806
1807 cas2.w %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1808
1809 mov.w %cc,SCCR(%a6)
1810 mov.w (%a0),%d5
1811 mov.w (%a1),%d6
1812 mov.w &0xcccc,IREGS+0x14+0x2(%a6)
1813 mov.w &0xdddd,IREGS+0x18+0x2(%a6)
1814 movm.l &0x7fff,SREGS(%a6)
1815
1816 bsr.l chkregs
1817 tst.b %d0
1818 bne.l error
1819
1820cas211:
1821 addq.l &0x1,TESTCTR(%a6)
1822
1823 movm.l DEF_REGS(%pc),&0x3fff
1824
1825 lea DATA+0x0(%a6),%a0
1826 lea DATA+0x4(%a6),%a1
1827
1828 mov.w &0xeeee,(%a0)
1829 mov.w &0xbbbb,(%a1)
1830
1831 mov.w &0xaaaa,%d1
1832 mov.w &0xbbbb,%d2
1833 mov.w &0xcccc,%d3
1834 mov.w &0xdddd,%d4
1835
1836 mov.w &0x0000,ICCR(%a6)
1837 mov.w &0x0000,%cc
1838 movm.l &0x7fff,IREGS(%a6)
1839
1840 cas2.w %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1841
1842 mov.w %cc,SCCR(%a6)
1843 mov.w (%a0),%d5
1844 mov.w (%a1),%d6
1845 mov.w &0xeeee,IREGS+0x4+0x2(%a6)
1846 mov.w &0xbbbb,IREGS+0x8+0x2(%a6)
1847 mov.w &0xeeee,IREGS+0x14+0x2(%a6)
1848 mov.w &0xbbbb,IREGS+0x18+0x2(%a6)
1849 movm.l &0x7fff,SREGS(%a6)
1850
1851 bsr.l chkregs
1852 tst.b %d0
1853 bne.l error
1854
1855cas212:
1856 addq.l &0x1,TESTCTR(%a6)
1857
1858 movm.l DEF_REGS(%pc),&0x3fff
1859
1860 lea DATA+0x1(%a6),%a0
1861 lea DATA+0x5(%a6),%a1
1862
1863 mov.w &0xeeee,(%a0)
1864 mov.w &0xbbbb,(%a1)
1865
1866 mov.w &0xaaaa,%d1
1867 mov.w &0xbbbb,%d2
1868 mov.w &0xcccc,%d3
1869 mov.w &0xdddd,%d4
1870
1871 mov.w &0x0000,ICCR(%a6)
1872 mov.w &0x0000,%cc
1873 movm.l &0x7fff,IREGS(%a6)
1874
1875 cas2.w %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1876
1877 mov.w %cc,SCCR(%a6)
1878 mov.w (%a0),%d5
1879 mov.w (%a1),%d6
1880 mov.w &0xeeee,IREGS+0x4+0x2(%a6)
1881 mov.w &0xbbbb,IREGS+0x8+0x2(%a6)
1882 mov.w &0xeeee,IREGS+0x14+0x2(%a6)
1883 mov.w &0xbbbb,IREGS+0x18+0x2(%a6)
1884 movm.l &0x7fff,SREGS(%a6)
1885
1886 bsr.l chkregs
1887 tst.b %d0
1888 bne.l error
1889
1890cas213:
1891 addq.l &0x1,TESTCTR(%a6)
1892
1893 movm.l DEF_REGS(%pc),&0x3fff
1894
1895 lea DATA+0x0(%a6),%a0
1896 lea DATA+0x4(%a6),%a1
1897
1898 mov.w &0xaaaa,(%a0)
1899 mov.w &0xeeee,(%a1)
1900
1901 mov.w &0xaaaa,%d1
1902 mov.w &0xbbbb,%d2
1903 mov.w &0xcccc,%d3
1904 mov.w &0xdddd,%d4
1905
1906 mov.w &0x0000,ICCR(%a6)
1907 mov.w &0x0000,%cc
1908 movm.l &0x7fff,IREGS(%a6)
1909
1910 cas2.w %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1911
1912 mov.w %cc,SCCR(%a6)
1913 mov.w (%a0),%d5
1914 mov.w (%a1),%d6
1915 mov.w &0xaaaa,IREGS+0x4+0x2(%a6)
1916 mov.w &0xeeee,IREGS+0x8+0x2(%a6)
1917 mov.w &0xaaaa,IREGS+0x14+0x2(%a6)
1918 mov.w &0xeeee,IREGS+0x18+0x2(%a6)
1919 movm.l &0x7fff,SREGS(%a6)
1920
1921 bsr.l chkregs
1922 tst.b %d0
1923 bne.l error
1924
1925cas214:
1926 addq.l &0x1,TESTCTR(%a6)
1927
1928 movm.l DEF_REGS(%pc),&0x3fff
1929
1930 lea DATA+0x1(%a6),%a0
1931 lea DATA+0x5(%a6),%a1
1932
1933 mov.w &0xaaaa,(%a0)
1934 mov.w &0x7fff,(%a1)
1935
1936 mov.w &0xaaaa,%d1
1937 mov.w &0x8000,%d2
1938 mov.w &0xcccc,%d3
1939 mov.w &0xdddd,%d4
1940
1941 mov.w &0x001b,ICCR(%a6)
1942 mov.w &0x0010,%cc
1943 movm.l &0x7fff,IREGS(%a6)
1944
1945 cas2.w %d1:%d2,%d3:%d4,(%a0):(%a1) # Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
1946
1947 mov.w %cc,SCCR(%a6)
1948 mov.w (%a0),%d5
1949 mov.w (%a1),%d6
1950 mov.w &0xaaaa,IREGS+0x4+0x2(%a6)
1951 mov.w &0x7fff,IREGS+0x8+0x2(%a6)
1952 mov.w &0xaaaa,IREGS+0x14+0x2(%a6)
1953 mov.w &0x7fff,IREGS+0x18+0x2(%a6)
1954 movm.l &0x7fff,SREGS(%a6)
1955
1956 bsr.l chkregs
1957 tst.b %d0
1958 bne.l error
1959
1960 mov.l TESTCTR(%a6),%d1
1961 clr.l %d0
1962 rts
1963
1964###########################################################
1965
1966cmp2_str:
1967 string "\tcmp2,chk2..."
1968
1969 align 0x4
1970# unsigned - small,small
1971cmp2_1:
1972 addq.l &0x1,TESTCTR(%a6)
1973
1974 movm.l DEF_REGS(%pc),&0x3fff
1975
1976 mov.w &0x2040,DATA(%a6)
1977 mov.l &0x11111120,%d1
1978
1979 mov.w &0x0004,ICCR(%a6)
1980 mov.w &0x0000,%cc
1981 movm.l &0x7fff,IREGS(%a6)
1982
1983 cmp2.b %d1,DATA(%a6)
1984
1985 mov.w %cc,SCCR(%a6)
1986 movm.l &0x7fff,SREGS(%a6)
1987
1988 bsr.l chkregs
1989 tst.b %d0
1990 bne.l error
1991
1992cmp2_2:
1993 addq.l &0x1,TESTCTR(%a6)
1994
1995 movm.l DEF_REGS(%pc),&0x3fff
1996
1997 mov.w &0x2040,DATA(%a6)
1998 mov.l &0x00000040,%a1
1999
2000 mov.w &0x0004,ICCR(%a6)
2001 mov.w &0x0000,%cc
2002 movm.l &0x7fff,IREGS(%a6)
2003
2004 cmp2.b %a1,DATA(%a6)
2005
2006 mov.w %cc,SCCR(%a6)
2007 movm.l &0x7fff,SREGS(%a6)
2008
2009 bsr.l chkregs
2010 tst.b %d0
2011 bne.l error
2012
2013cmp2_3:
2014 addq.l &0x1,TESTCTR(%a6)
2015
2016 movm.l DEF_REGS(%pc),&0x3fff
2017
2018 mov.w &0x2040,DATA(%a6)
2019 mov.l &0x11111130,%d1
2020
2021 mov.w &0x0000,ICCR(%a6)
2022 mov.w &0x0000,%cc
2023 movm.l &0x7fff,IREGS(%a6)
2024
2025 chk2.b DATA(%a6),%d1
2026
2027 mov.w %cc,SCCR(%a6)
2028 movm.l &0x7fff,SREGS(%a6)
2029
2030 bsr.l chkregs
2031 tst.b %d0
2032 bne.l error
2033
2034cmp2_4:
2035 addq.l &0x1,TESTCTR(%a6)
2036
2037 movm.l DEF_REGS(%pc),&0x3fff
2038
2039 mov.w &0x2040,DATA(%a6)
2040 mov.l &0x00000010,%a1
2041
2042 mov.w &0x0001,ICCR(%a6)
2043 mov.w &0x0000,%cc
2044 movm.l &0x7fff,IREGS(%a6)
2045
2046 cmp2.b %a1,DATA(%a6)
2047
2048 mov.w %cc,SCCR(%a6)
2049 movm.l &0x7fff,SREGS(%a6)
2050
2051 bsr.l chkregs
2052 tst.b %d0
2053 bne.l error
2054
2055cmp2_5:
2056 addq.l &0x1,TESTCTR(%a6)
2057
2058 movm.l DEF_REGS(%pc),&0x3fff
2059
2060 mov.w &0x2040,DATA(%a6)
2061 mov.l &0x11111150,%d1
2062
2063 mov.w &0x0001,ICCR(%a6)
2064 mov.w &0x0000,%cc
2065 movm.l &0x7fff,IREGS(%a6)
2066
2067 cmp2.b %d1,DATA(%a6)
2068
2069 mov.w %cc,SCCR(%a6)
2070 movm.l &0x7fff,SREGS(%a6)
2071
2072 bsr.l chkregs
2073 tst.b %d0
2074 bne.l error
2075
2076cmp2_6:
2077 addq.l &0x1,TESTCTR(%a6)
2078
2079 movm.l DEF_REGS(%pc),&0x3fff
2080
2081 mov.w &0x2040,DATA(%a6)
2082 mov.l &0x00000090,%a1
2083
2084 mov.w &0x0001,ICCR(%a6)
2085 mov.w &0x0000,%cc
2086 movm.l &0x7fff,IREGS(%a6)
2087
2088 cmp2.b %a1,DATA(%a6)
2089
2090 mov.w %cc,SCCR(%a6)
2091 movm.l &0x7fff,SREGS(%a6)
2092
2093 bsr.l chkregs
2094 tst.b %d0
2095 bne.l error
2096
2097# unsigned - small,large
2098cmp2_7:
2099 addq.l &0x1,TESTCTR(%a6)
2100
2101 movm.l DEF_REGS(%pc),&0x3fff
2102
2103 mov.l &0x2000a000,DATA(%a6)
2104 mov.l &0x11112000,%d1
2105
2106 mov.w &0x0004,ICCR(%a6)
2107 mov.w &0x0000,%cc
2108 movm.l &0x7fff,IREGS(%a6)
2109
2110 cmp2.w %d1,DATA(%a6)
2111
2112 mov.w %cc,SCCR(%a6)
2113 movm.l &0x7fff,SREGS(%a6)
2114
2115 bsr.l chkregs
2116 tst.b %d0
2117 bne.l error
2118
2119cmp2_8:
2120 addq.l &0x1,TESTCTR(%a6)
2121
2122 movm.l DEF_REGS(%pc),&0x3fff
2123
2124 mov.l &0x2000a000,DATA(%a6)
2125 mov.l &0xffffa000,%a1
2126
2127 mov.w &0x0004,ICCR(%a6)
2128 mov.w &0x0000,%cc
2129 movm.l &0x7fff,IREGS(%a6)
2130
2131 cmp2.w %a1,DATA(%a6)
2132
2133 mov.w %cc,SCCR(%a6)
2134 movm.l &0x7fff,SREGS(%a6)
2135
2136 bsr.l chkregs
2137 tst.b %d0
2138 bne.l error
2139
2140cmp2_9:
2141 addq.l &0x1,TESTCTR(%a6)
2142
2143 movm.l DEF_REGS(%pc),&0x3fff
2144
2145 mov.l &0x2000a000,DATA(%a6)
2146 mov.l &0x11113000,%d1
2147
2148 mov.w &0x0000,ICCR(%a6)
2149 mov.w &0x0000,%cc
2150 movm.l &0x7fff,IREGS(%a6)
2151
2152 chk2.w DATA(%a6),%d1
2153
2154 mov.w %cc,SCCR(%a6)
2155 movm.l &0x7fff,SREGS(%a6)
2156
2157 bsr.l chkregs
2158 tst.b %d0
2159 bne.l error
2160
2161cmp2_10:
2162 addq.l &0x1,TESTCTR(%a6)
2163
2164 movm.l DEF_REGS(%pc),&0x3fff
2165
2166 mov.l &0x2000a000,DATA(%a6)
2167 mov.l &0xffff9000,%a1
2168
2169 mov.w &0x0000,ICCR(%a6)
2170 mov.w &0x0000,%cc
2171 movm.l &0x7fff,IREGS(%a6)
2172
2173 cmp2.w %a1,DATA(%a6)
2174
2175 mov.w %cc,SCCR(%a6)
2176 movm.l &0x7fff,SREGS(%a6)
2177
2178 bsr.l chkregs
2179 tst.b %d0
2180 bne.l error
2181
2182cmp2_11:
2183 addq.l &0x1,TESTCTR(%a6)
2184
2185 movm.l DEF_REGS(%pc),&0x3fff
2186
2187 mov.l &0x2000a000,DATA(%a6)
2188 mov.l &0x11111000,%d1
2189
2190 mov.w &0x0001,ICCR(%a6)
2191 mov.w &0x0000,%cc
2192 movm.l &0x7fff,IREGS(%a6)
2193
2194 cmp2.w %d1,DATA(%a6)
2195
2196 mov.w %cc,SCCR(%a6)
2197 movm.l &0x7fff,SREGS(%a6)
2198
2199 bsr.l chkregs
2200 tst.b %d0
2201 bne.l error
2202
2203cmp2_12:
2204 addq.l &0x1,TESTCTR(%a6)
2205
2206 movm.l DEF_REGS(%pc),&0x3fff
2207
2208 mov.l &0x2000a000,DATA(%a6)
2209 mov.l &0xffffb000,%a1
2210
2211 mov.w &0x0001,ICCR(%a6)
2212 mov.w &0x0000,%cc
2213 movm.l &0x7fff,IREGS(%a6)
2214
2215 cmp2.w %a1,DATA(%a6)
2216
2217 mov.w %cc,SCCR(%a6)
2218 movm.l &0x7fff,SREGS(%a6)
2219
2220 bsr.l chkregs
2221 tst.b %d0
2222 bne.l error
2223
2224# unsigned - large,large
2225cmp2_13:
2226 addq.l &0x1,TESTCTR(%a6)
2227
2228 movm.l DEF_REGS(%pc),&0x3fff
2229
2230 mov.l &0xa0000000,DATA(%a6)
2231 mov.l &0xc0000000,DATA+0x4(%a6)
2232 mov.l &0xa0000000,%d1
2233
2234 mov.w &0x000c,ICCR(%a6)
2235 mov.w &0x0008,%cc
2236 movm.l &0x7fff,IREGS(%a6)
2237
2238 cmp2.l %d1,DATA(%a6)
2239
2240 mov.w %cc,SCCR(%a6)
2241 movm.l &0x7fff,SREGS(%a6)
2242
2243 bsr.l chkregs
2244 tst.b %d0
2245 bne.l error
2246
2247cmp2_14:
2248 addq.l &0x1,TESTCTR(%a6)
2249
2250 movm.l DEF_REGS(%pc),&0x3fff
2251
2252 mov.l &0xa0000000,DATA(%a6)
2253 mov.l &0xc0000000,DATA+0x4(%a6)
2254 mov.l &0xc0000000,%a1
2255
2256 mov.w &0x000c,ICCR(%a6)
2257 mov.w &0x0008,%cc
2258 movm.l &0x7fff,IREGS(%a6)
2259
2260 cmp2.l %a1,DATA(%a6)
2261
2262 mov.w %cc,SCCR(%a6)
2263 movm.l &0x7fff,SREGS(%a6)
2264
2265 bsr.l chkregs
2266 tst.b %d0
2267 bne.l error
2268
2269cmp2_15:
2270 addq.l &0x1,TESTCTR(%a6)
2271
2272 movm.l DEF_REGS(%pc),&0x3fff
2273
2274 mov.l &0xa0000000,DATA(%a6)
2275 mov.l &0xc0000000,DATA+0x4(%a6)
2276 mov.l &0xb0000000,%d1
2277
2278 mov.w &0x0008,ICCR(%a6)
2279 mov.w &0x0008,%cc
2280 movm.l &0x7fff,IREGS(%a6)
2281
2282 chk2.l DATA(%a6),%d1
2283
2284 mov.w %cc,SCCR(%a6)
2285 movm.l &0x7fff,SREGS(%a6)
2286
2287 bsr.l chkregs
2288 tst.b %d0
2289 bne.l error
2290
2291cmp2_16:
2292 addq.l &0x1,TESTCTR(%a6)
2293
2294 movm.l DEF_REGS(%pc),&0x3fff
2295
2296 mov.l &0xa0000000,DATA(%a6)
2297 mov.l &0xc0000000,DATA+0x4(%a6)
2298 mov.l &0x10000000,%a1
2299
2300 mov.w &0x0009,ICCR(%a6)
2301 mov.w &0x0008,%cc
2302 movm.l &0x7fff,IREGS(%a6)
2303
2304 cmp2.l %a1,DATA(%a6)
2305
2306 mov.w %cc,SCCR(%a6)
2307 movm.l &0x7fff,SREGS(%a6)
2308
2309 bsr.l chkregs
2310 tst.b %d0
2311 bne.l error
2312
2313cmp2_17:
2314 addq.l &0x1,TESTCTR(%a6)
2315
2316 movm.l DEF_REGS(%pc),&0x3fff
2317
2318 mov.l &0xa0000000,DATA(%a6)
2319 mov.l &0xc0000000,DATA+0x4(%a6)
2320 mov.l &0x90000000,%d1
2321
2322 mov.w &0x0009,ICCR(%a6)
2323 mov.w &0x0008,%cc
2324 movm.l &0x7fff,IREGS(%a6)
2325
2326 cmp2.l %d1,DATA(%a6)
2327
2328 mov.w %cc,SCCR(%a6)
2329 movm.l &0x7fff,SREGS(%a6)
2330
2331 bsr.l chkregs
2332 tst.b %d0
2333 bne.l error
2334
2335cmp2_18:
2336 addq.l &0x1,TESTCTR(%a6)
2337
2338 movm.l DEF_REGS(%pc),&0x3fff
2339
2340 mov.l &0xa0000000,DATA(%a6)
2341 mov.l &0xc0000000,DATA+0x4(%a6)
2342 mov.l &0xd0000000,%a1
2343
2344 mov.w &0x0009,ICCR(%a6)
2345 mov.w &0x0008,%cc
2346 movm.l &0x7fff,IREGS(%a6)
2347
2348 cmp2.l %a1,DATA(%a6)
2349
2350 mov.w %cc,SCCR(%a6)
2351 movm.l &0x7fff,SREGS(%a6)
2352
2353 bsr.l chkregs
2354 tst.b %d0
2355 bne.l error
2356
2357# signed - negative,positive
2358cmp2_19:
2359 addq.l &0x1,TESTCTR(%a6)
2360
2361 movm.l DEF_REGS(%pc),&0x3fff
2362
2363 mov.w &0xa040,DATA(%a6)
2364 mov.l &0x111111a0,%d1
2365
2366 mov.w &0x0004,ICCR(%a6)
2367 mov.w &0x0000,%cc
2368 movm.l &0x7fff,IREGS(%a6)
2369
2370 cmp2.b %d1,DATA(%a6)
2371
2372 mov.w %cc,SCCR(%a6)
2373 movm.l &0x7fff,SREGS(%a6)
2374
2375 bsr.l chkregs
2376 tst.b %d0
2377 bne.l error
2378
2379cmp2_20:
2380 addq.l &0x1,TESTCTR(%a6)
2381
2382 movm.l DEF_REGS(%pc),&0x3fff
2383
2384 mov.w &0xa040,DATA(%a6)
2385 mov.l &0x00000040,%a1
2386
2387 mov.w &0x0004,ICCR(%a6)
2388 mov.w &0x0000,%cc
2389 movm.l &0x7fff,IREGS(%a6)
2390
2391 chk2.b DATA(%a6),%a1
2392
2393 mov.w %cc,SCCR(%a6)
2394 movm.l &0x7fff,SREGS(%a6)
2395
2396 bsr.l chkregs
2397 tst.b %d0
2398 bne.l error
2399
2400cmp2_21:
2401 addq.l &0x1,TESTCTR(%a6)
2402
2403 movm.l DEF_REGS(%pc),&0x3fff
2404
2405 mov.w &0xa040,DATA(%a6)
2406 mov.l &0x111111b0,%d1
2407
2408 mov.w &0x0000,ICCR(%a6)
2409 mov.w &0x0000,%cc
2410 movm.l &0x7fff,IREGS(%a6)
2411
2412 cmp2.b %d1,DATA(%a6)
2413
2414 mov.w %cc,SCCR(%a6)
2415 movm.l &0x7fff,SREGS(%a6)
2416
2417 bsr.l chkregs
2418 tst.b %d0
2419 bne.l error
2420
2421cmp2_22:
2422 addq.l &0x1,TESTCTR(%a6)
2423
2424 movm.l DEF_REGS(%pc),&0x3fff
2425
2426 mov.w &0xa040,DATA(%a6)
2427 mov.l &0x00000010,%a1
2428
2429 mov.w &0x0000,ICCR(%a6)
2430 mov.w &0x0000,%cc
2431 movm.l &0x7fff,IREGS(%a6)
2432
2433 cmp2.b %a1,DATA(%a6)
2434
2435 mov.w %cc,SCCR(%a6)
2436 movm.l &0x7fff,SREGS(%a6)
2437
2438 bsr.l chkregs
2439 tst.b %d0
2440 bne.l error
2441
2442cmp2_23:
2443 addq.l &0x1,TESTCTR(%a6)
2444
2445 movm.l DEF_REGS(%pc),&0x3fff
2446
2447 mov.w &0xa040,DATA(%a6)
2448 mov.l &0x11111190,%d1
2449
2450 mov.w &0x0001,ICCR(%a6)
2451 mov.w &0x0000,%cc
2452 movm.l &0x7fff,IREGS(%a6)
2453
2454 cmp2.b %d1,DATA(%a6)
2455
2456 mov.w %cc,SCCR(%a6)
2457 movm.l &0x7fff,SREGS(%a6)
2458
2459 bsr.l chkregs
2460 tst.b %d0
2461 bne.l error
2462
2463cmp2_24:
2464 addq.l &0x1,TESTCTR(%a6)
2465
2466 movm.l DEF_REGS(%pc),&0x3fff
2467
2468 mov.w &0xa040,DATA(%a6)
2469 mov.l &0x00000050,%a1
2470
2471 mov.w &0x0001,ICCR(%a6)
2472 mov.w &0x0000,%cc
2473 movm.l &0x7fff,IREGS(%a6)
2474
2475 cmp2.b %a1,DATA(%a6)
2476
2477 mov.w %cc,SCCR(%a6)
2478 movm.l &0x7fff,SREGS(%a6)
2479
2480 bsr.l chkregs
2481 tst.b %d0
2482 bne.l error
2483
2484# signed - negative,negative
2485cmp2_25:
2486 addq.l &0x1,TESTCTR(%a6)
2487
2488 movm.l DEF_REGS(%pc),&0x3fff
2489
2490 mov.w &0xa0c0,DATA(%a6)
2491 mov.l &0x111111a0,%d1
2492
2493 mov.w &0x0004,ICCR(%a6)
2494 mov.w &0x0000,%cc
2495 movm.l &0x7fff,IREGS(%a6)
2496
2497 cmp2.b %d1,DATA(%a6)
2498
2499 mov.w %cc,SCCR(%a6)
2500 movm.l &0x7fff,SREGS(%a6)
2501
2502 bsr.l chkregs
2503 tst.b %d0
2504 bne.l error
2505
2506cmp2_26:
2507 addq.l &0x1,TESTCTR(%a6)
2508
2509 movm.l DEF_REGS(%pc),&0x3fff
2510
2511 mov.w &0xa0c0,DATA(%a6)
2512 mov.l &0xffffffc0,%a1
2513
2514 mov.w &0x0004,ICCR(%a6)
2515 mov.w &0x0000,%cc
2516 movm.l &0x7fff,IREGS(%a6)
2517
2518 cmp2.b %a1,DATA(%a6)
2519
2520 mov.w %cc,SCCR(%a6)
2521 movm.l &0x7fff,SREGS(%a6)
2522
2523 bsr.l chkregs
2524 tst.b %d0
2525 bne.l error
2526
2527cmp2_27:
2528 addq.l &0x1,TESTCTR(%a6)
2529
2530 movm.l DEF_REGS(%pc),&0x3fff
2531
2532 mov.w &0xa0c0,DATA(%a6)
2533 mov.l &0x111111b0,%d1
2534
2535 mov.w &0x0000,ICCR(%a6)
2536 mov.w &0x0000,%cc
2537 movm.l &0x7fff,IREGS(%a6)
2538
2539 chk2.b DATA(%a6),%d1
2540
2541 mov.w %cc,SCCR(%a6)
2542 movm.l &0x7fff,SREGS(%a6)
2543
2544 bsr.l chkregs
2545 tst.b %d0
2546 bne.l error
2547
2548cmp2_28:
2549 addq.l &0x1,TESTCTR(%a6)
2550
2551 movm.l DEF_REGS(%pc),&0x3fff
2552
2553 mov.w &0xa0c0,DATA(%a6)
2554 mov.l &0x11111190,%a1
2555
2556 mov.w &0x0001,ICCR(%a6)
2557 mov.w &0x0000,%cc
2558 movm.l &0x7fff,IREGS(%a6)
2559
2560 cmp2.b %a1,DATA(%a6)
2561
2562 mov.w %cc,SCCR(%a6)
2563 movm.l &0x7fff,SREGS(%a6)
2564
2565 bsr.l chkregs
2566 tst.b %d0
2567 bne.l error
2568
2569cmp2_29:
2570 addq.l &0x1,TESTCTR(%a6)
2571
2572 movm.l DEF_REGS(%pc),&0x3fff
2573
2574 mov.w &0xa0c0,DATA(%a6)
2575 mov.l &0x111111d0,%d1
2576
2577 mov.w &0x0001,ICCR(%a6)
2578 mov.w &0x0000,%cc
2579 movm.l &0x7fff,IREGS(%a6)
2580
2581 cmp2.b %d1,DATA(%a6)
2582
2583 mov.w %cc,SCCR(%a6)
2584 movm.l &0x7fff,SREGS(%a6)
2585
2586 bsr.l chkregs
2587 tst.b %d0
2588 bne.l error
2589
2590cmp2_30:
2591 addq.l &0x1,TESTCTR(%a6)
2592
2593 movm.l DEF_REGS(%pc),&0x3fff
2594
2595 mov.w &0xa0c0,DATA(%a6)
2596 mov.l &0x00000050,%a1
2597
2598 mov.w &0x001b,ICCR(%a6)
2599 mov.w &0x001f,%cc
2600 movm.l &0x7fff,IREGS(%a6)
2601
2602 cmp2.b %a1,DATA(%a6)
2603
2604 mov.w %cc,SCCR(%a6)
2605 movm.l &0x7fff,SREGS(%a6)
2606
2607 bsr.l chkregs
2608 tst.b %d0
2609 bne.l error
2610
2611 mov.l TESTCTR(%a6),%d1
2612 clr.l %d0
2613 rts
2614
2615###########################################################
2616
2617ea_str:
2618 string "\tEffective addresses..."
2619
2620 align 0x4
2621ea_0:
2622 addq.l &0x1,TESTCTR(%a6)
2623
2624 movm.l DEF_REGS(%pc),&0x3fff
2625
2626 clr.l %d2
2627 mov.l &0x00000002,%d3
2628 lea EAMEM(%a6),%a0
2629
2630 mov.w &0x0000,ICCR(%a6)
2631 mov.w &0x0000,%cc
2632 movm.l &0xffff,IREGS(%a6)
2633
2634 mulu.l (%a0),%d2:%d3
2635
2636 mov.w %cc,SCCR(%a6)
2637 movm.l &0xffff,SREGS(%a6)
2638 mov.l &0x00000004,IREGS+0xc(%a6)
2639
2640 bsr.l chkregs
2641 tst.b %d0
2642 bne.l error
2643
2644ea_1:
2645 addq.l &0x1,TESTCTR(%a6)
2646
2647 movm.l DEF_REGS(%pc),&0x3fff
2648
2649 clr.l %d2
2650 mov.l &0x00000002,%d3
2651 lea EAMEM(%a6),%a0
2652
2653 mov.w &0x0000,ICCR(%a6)
2654 mov.w &0x0000,%cc
2655 movm.l &0xffff,IREGS(%a6)
2656
2657 mulu.l (%a0)+,%d2:%d3
2658
2659 mov.w %cc,SCCR(%a6)
2660 movm.l &0xffff,SREGS(%a6)
2661 mov.l &0x00000004,IREGS+0xc(%a6)
2662 lea EAMEM+0x4(%a6),%a0
2663 mov.l %a0,IREGS+0x20(%a6)
2664
2665 bsr.l chkregs
2666 tst.b %d0
2667 bne.l error
2668
2669ea_2:
2670 addq.l &0x1,TESTCTR(%a6)
2671
2672 movm.l DEF_REGS(%pc),&0x3fff
2673 clr.l %d2
2674 mov.l &0x00000002,%d3
2675 lea EAMEM+0x4(%a6),%a0
2676
2677 mov.w &0x0000,ICCR(%a6)
2678 mov.w &0x0000,%cc
2679 movm.l &0xffff,IREGS(%a6)
2680
2681 mulu.l -(%a0),%d2:%d3
2682
2683 mov.w %cc,SCCR(%a6)
2684 movm.l &0xffff,SREGS(%a6)
2685 mov.l &0x00000004,IREGS+0xc(%a6)
2686 lea EAMEM(%a6),%a0
2687 mov.l %a0,IREGS+0x20(%a6)
2688
2689 bsr.l chkregs
2690 tst.b %d0
2691 bne.l error
2692
2693ea_3:
2694 addq.l &0x1,TESTCTR(%a6)
2695
2696 movm.l DEF_REGS(%pc),&0x3fff
2697
2698 clr.l %d2
2699 mov.l &0x00000002,%d3
2700 lea EAMEM+0x1000(%a6),%a0
2701
2702 mov.w &0x0000,ICCR(%a6)
2703 mov.w &0x0000,%cc
2704 movm.l &0xffff,IREGS(%a6)
2705
2706 mulu.l (-0x1000,%a0),%d2:%d3
2707
2708 mov.w %cc,SCCR(%a6)
2709 movm.l &0xffff,SREGS(%a6)
2710 mov.l &0x00000004,IREGS+0xc(%a6)
2711
2712 bsr.l chkregs
2713 tst.b %d0
2714 bne.l error
2715
2716ea_4:
2717 addq.l &0x1,TESTCTR(%a6)
2718
2719 movm.l DEF_REGS(%pc),&0x3fff
2720
2721 clr.l %d2
2722 mov.l &0x00000002,%d3
2723 lea EAMEM-0x1000(%a6),%a0
2724
2725 mov.w &0x0000,ICCR(%a6)
2726 mov.w &0x0000,%cc
2727 movm.l &0xffff,IREGS(%a6)
2728
2729 mulu.l (0x1000,%a0),%d2:%d3
2730
2731 mov.w %cc,SCCR(%a6)
2732 movm.l &0xffff,SREGS(%a6)
2733 mov.l &0x00000004,IREGS+0xc(%a6)
2734
2735 bsr.l chkregs
2736 tst.b %d0
2737 bne.l error
2738
2739ea_5:
2740 addq.l &0x1,TESTCTR(%a6)
2741
2742# movm.l DEF_REGS(%pc),&0x3fff
2743
2744# clr.l %d2
2745# mov.l &0x00000002,%d3
2746
2747# mov.w &0x0000,ICCR(%a6)
2748# mov.w &0x0000,%cc
2749# movm.l &0xffff,IREGS(%a6)
2750
2751# mulu.l EAMEM.w,%d2:%d3
2752
2753# mov.w %cc,SCCR(%a6)
2754# movm.l &0xffff,SREGS(%a6)
2755# mov.l &0x00000004,IREGS+0xc(%a6)
2756
2757# bsr.l chkregs
2758# tst.b %d0
2759# bne.l error
2760
2761ea_6:
2762 addq.l &0x1,TESTCTR(%a6)
2763
2764# movm.l DEF_REGS(%pc),&0x3fff
2765
2766# clr.l %d2
2767# mov.l &0x00000002,%d3
2768
2769# mov.w &0x0000,ICCR(%a6)
2770# mov.w &0x0000,%cc
2771# movm.l &0xffff,IREGS(%a6)
2772
2773# mulu.l EAMEM.l,%d2:%d3
2774
2775# mov.w %cc,SCCR(%a6)
2776# movm.l &0xffff,SREGS(%a6)
2777# mov.l &0x00000004,IREGS+0xc(%a6)
2778
2779# bsr.l chkregs
2780# tst.b %d0
2781# bne.l error
2782
2783ea_7:
2784 addq.l &0x1,TESTCTR(%a6)
2785
2786 movm.l DEF_REGS(%pc),&0x3fff
2787
2788 clr.l %d2
2789 mov.l &0x00000002,%d3
2790
2791 mov.w &0x0000,ICCR(%a6)
2792 mov.w &0x0000,%cc
2793 movm.l &0xffff,IREGS(%a6)
2794
2795 mulu.l &0x00000002,%d2:%d3
2796
2797 mov.w %cc,SCCR(%a6)
2798 movm.l &0xffff,SREGS(%a6)
2799 mov.l &0x00000004,IREGS+0xc(%a6)
2800
2801 bsr.l chkregs
2802 tst.b %d0
2803 bne.l error
2804
2805ea_8:
2806 addq.l &0x1,TESTCTR(%a6)
2807
2808 bra.b ea_8_next
2809ea_8_mem:
2810 long 0x00000002
2811ea_8_next:
2812 movm.l DEF_REGS(%pc),&0x3fff
2813
2814 clr.l %d2
2815 mov.l &0x00000002,%d3
2816
2817 mov.w &0x0000,ICCR(%a6)
2818 mov.w &0x0000,%cc
2819 movm.l &0xffff,IREGS(%a6)
2820
2821 mulu.l (ea_8_mem.w,%pc),%d2:%d3
2822
2823 mov.w %cc,SCCR(%a6)
2824 movm.l &0xffff,SREGS(%a6)
2825 mov.l &0x00000004,IREGS+0xc(%a6)
2826
2827 bsr.l chkregs
2828 tst.b %d0
2829 bne.l error
2830
2831ea_9:
2832 addq.l &0x1,TESTCTR(%a6)
2833
2834 movm.l DEF_REGS(%pc),&0x3fff
2835 clr.l %d2
2836 mov.l &0x00000002,%d3
2837 lea EAMEM+0x4(%a6),%a1
2838
2839 mov.w &0x0000,ICCR(%a6)
2840 mov.w &0x0000,%cc
2841 movm.l &0xffff,IREGS(%a6)
2842
2843 mulu.l -(%a1),%d2:%d3
2844
2845 mov.w %cc,SCCR(%a6)
2846 movm.l &0xffff,SREGS(%a6)
2847 mov.l &0x00000004,IREGS+0xc(%a6)
2848 lea EAMEM(%a6),%a0
2849 mov.l %a0,IREGS+0x24(%a6)
2850
2851 bsr.l chkregs
2852 tst.b %d0
2853 bne.l error
2854
2855ea_10:
2856 addq.l &0x1,TESTCTR(%a6)
2857
2858 movm.l DEF_REGS(%pc),&0x3fff
2859 clr.l %d2
2860 mov.l &0x00000002,%d3
2861 lea EAMEM+0x4(%a6),%a2
2862
2863 mov.w &0x0000,ICCR(%a6)
2864 mov.w &0x0000,%cc
2865 movm.l &0xffff,IREGS(%a6)
2866
2867 mulu.l -(%a2),%d2:%d3
2868
2869 mov.w %cc,SCCR(%a6)
2870 movm.l &0xffff,SREGS(%a6)
2871 mov.l &0x00000004,IREGS+0xc(%a6)
2872 lea EAMEM(%a6),%a0
2873 mov.l %a0,IREGS+0x28(%a6)
2874
2875 bsr.l chkregs
2876 tst.b %d0
2877 bne.l error
2878
2879ea_11:
2880 addq.l &0x1,TESTCTR(%a6)
2881
2882 movm.l DEF_REGS(%pc),&0x3fff
2883 clr.l %d2
2884 mov.l &0x00000002,%d3
2885 lea EAMEM+0x4(%a6),%a3
2886
2887 mov.w &0x0000,ICCR(%a6)
2888 mov.w &0x0000,%cc
2889 movm.l &0xffff,IREGS(%a6)
2890
2891 mulu.l -(%a3),%d2:%d3
2892
2893 mov.w %cc,SCCR(%a6)
2894 movm.l &0xffff,SREGS(%a6)
2895 mov.l &0x00000004,IREGS+0xc(%a6)
2896 lea EAMEM(%a6),%a0
2897 mov.l %a0,IREGS+0x2c(%a6)
2898
2899 bsr.l chkregs
2900 tst.b %d0
2901 bne.l error
2902
2903ea_12:
2904 addq.l &0x1,TESTCTR(%a6)
2905
2906 movm.l DEF_REGS(%pc),&0x3fff
2907 clr.l %d2
2908 mov.l &0x00000002,%d3
2909 lea EAMEM+0x4(%a6),%a4
2910
2911 mov.w &0x0000,ICCR(%a6)
2912 mov.w &0x0000,%cc
2913 movm.l &0xffff,IREGS(%a6)
2914
2915 mulu.l -(%a4),%d2:%d3
2916
2917 mov.w %cc,SCCR(%a6)
2918 movm.l &0xffff,SREGS(%a6)
2919 mov.l &0x00000004,IREGS+0xc(%a6)
2920 lea EAMEM(%a6),%a0
2921 mov.l %a0,IREGS+0x30(%a6)
2922
2923 bsr.l chkregs
2924 tst.b %d0
2925 bne.l error
2926
2927ea_13:
2928 addq.l &0x1,TESTCTR(%a6)
2929
2930 movm.l DEF_REGS(%pc),&0x3fff
2931 clr.l %d2
2932 mov.l &0x00000002,%d3
2933 lea EAMEM+0x4(%a6),%a5
2934
2935 mov.w &0x0000,ICCR(%a6)
2936 mov.w &0x0000,%cc
2937 movm.l &0xffff,IREGS(%a6)
2938
2939 mulu.l -(%a5),%d2:%d3
2940
2941 mov.w %cc,SCCR(%a6)
2942 movm.l &0xffff,SREGS(%a6)
2943 mov.l &0x00000004,IREGS+0xc(%a6)
2944 lea EAMEM(%a6),%a0
2945 mov.l %a0,IREGS+0x34(%a6)
2946
2947 bsr.l chkregs
2948 tst.b %d0
2949 bne.l error
2950
2951ea_14:
2952 addq.l &0x1,TESTCTR(%a6)
2953
2954 movm.l DEF_REGS(%pc),&0x3fff
2955
2956 mov.l %a6,%a1
2957
2958 clr.l %d2
2959 mov.l &0x00000002,%d3
2960 lea EAMEM+0x4(%a1),%a6
2961
2962 mov.w &0x0000,ICCR(%a1)
2963 mov.w &0x0000,%cc
2964 movm.l &0xffff,IREGS(%a1)
2965
2966 mulu.l -(%a6),%d2:%d3
2967
2968 mov.w %cc,SCCR(%a1)
2969 movm.l &0xffff,SREGS(%a1)
2970 mov.l &0x00000004,IREGS+0xc(%a1)
2971 lea EAMEM(%a1),%a0
2972 mov.l %a0,IREGS+0x38(%a1)
2973
2974 mov.l %a1,%a6
2975
2976 bsr.l chkregs
2977 tst.b %d0
2978 bne.l error
2979
2980ea_15:
2981 addq.l &0x1,TESTCTR(%a6)
2982
2983 movm.l DEF_REGS(%pc),&0x3fff
2984 clr.l %d2
2985 mov.l &0x00000002,%d3
2986 mov.l %a7,%a0
2987 lea EAMEM+0x4(%a6),%a7
2988
2989 mov.w &0x0000,ICCR(%a6)
2990 mov.w &0x0000,%cc
2991 movm.l &0xffff,IREGS(%a6)
2992
2993 mulu.l -(%a7),%d2:%d3
2994
2995 mov.w %cc,SCCR(%a6)
2996 movm.l &0xffff,SREGS(%a6)
2997 mov.l &0x00000004,IREGS+0xc(%a6)
2998 lea EAMEM(%a6),%a1
2999 mov.l %a1,IREGS+0x3c(%a6)
3000
3001 mov.l %a0,%a7
3002 bsr.l chkregs
3003 tst.b %d0
3004 bne.l error
3005
3006ea_16:
3007 addq.l &0x1,TESTCTR(%a6)
3008
3009 movm.l DEF_REGS(%pc),&0x3fff
3010
3011 clr.l %d2
3012 mov.l &0x00000002,%d3
3013 lea EAMEM(%a6),%a0
3014 mov.l &-0x10,%d4
3015
3016 mov.w &0x0000,ICCR(%a6)
3017 mov.w &0x0000,%cc
3018 movm.l &0xffff,IREGS(%a6)
3019
3020 mulu.l (0x10.b,%a0,%d4.w*1),%d2:%d3
3021
3022 mov.w %cc,SCCR(%a6)
3023 movm.l &0xffff,SREGS(%a6)
3024 mov.l &0x00000004,IREGS+0xc(%a6)
3025
3026 bsr.l chkregs
3027 tst.b %d0
3028 bne.l error
3029
3030ea_17:
3031 addq.l &0x1,TESTCTR(%a6)
3032
3033 movm.l DEF_REGS(%pc),&0x3fff
3034
3035 clr.l %d2
3036 mov.l &0x00000002,%d3
3037 lea EAMEM(%a6),%a0
3038 mov.l &-0x8,%d4
3039
3040 mov.w &0x0000,ICCR(%a6)
3041 mov.w &0x0000,%cc
3042 movm.l &0xffff,IREGS(%a6)
3043
3044 mulu.l (0x10.b,%a0,%d4.w*2),%d2:%d3
3045
3046 mov.w %cc,SCCR(%a6)
3047 movm.l &0xffff,SREGS(%a6)
3048 mov.l &0x00000004,IREGS+0xc(%a6)
3049
3050 bsr.l chkregs
3051 tst.b %d0
3052 bne.l error
3053
3054ea_18:
3055 addq.l &0x1,TESTCTR(%a6)
3056
3057 movm.l DEF_REGS(%pc),&0x3fff
3058
3059 clr.l %d2
3060 mov.l &0x00000002,%d3
3061 lea EAMEM(%a6),%a0
3062 mov.l &-0x4,%d4
3063
3064 mov.w &0x0000,ICCR(%a6)
3065 mov.w &0x0000,%cc
3066 movm.l &0xffff,IREGS(%a6)
3067
3068 mulu.l (0x10.b,%a0,%d4.w*4),%d2:%d3
3069
3070 mov.w %cc,SCCR(%a6)
3071 movm.l &0xffff,SREGS(%a6)
3072 mov.l &0x00000004,IREGS+0xc(%a6)
3073
3074 bsr.l chkregs
3075 tst.b %d0
3076 bne.l error
3077
3078ea_19:
3079 addq.l &0x1,TESTCTR(%a6)
3080
3081 movm.l DEF_REGS(%pc),&0x3fff
3082
3083 clr.l %d2
3084 mov.l &0x00000002,%d3
3085 lea EAMEM(%a6),%a0
3086 mov.l &-0x2,%d4
3087
3088 mov.w &0x0000,ICCR(%a6)
3089 mov.w &0x0000,%cc
3090 movm.l &0xffff,IREGS(%a6)
3091
3092 mulu.l (0x10.b,%a0,%d4.w*8),%d2:%d3
3093
3094 mov.w %cc,SCCR(%a6)
3095 movm.l &0xffff,SREGS(%a6)
3096 mov.l &0x00000004,IREGS+0xc(%a6)
3097
3098 bsr.l chkregs
3099 tst.b %d0
3100 bne.l error
3101
3102ea_20:
3103 addq.l &0x1,TESTCTR(%a6)
3104
3105 movm.l DEF_REGS(%pc),&0x3fff
3106
3107 clr.l %d2
3108 mov.l &0x00000002,%d3
3109 lea EAMEM(%a6),%a0
3110 mov.l &-0x10,%d4
3111
3112 mov.w &0x0000,ICCR(%a6)
3113 mov.w &0x0000,%cc
3114 movm.l &0xffff,IREGS(%a6)
3115
3116 mulu.l (0x10.b,%a0,%d4.l*1),%d2:%d3
3117
3118 mov.w %cc,SCCR(%a6)
3119 movm.l &0xffff,SREGS(%a6)
3120 mov.l &0x00000004,IREGS+0xc(%a6)
3121
3122 bsr.l chkregs
3123 tst.b %d0
3124 bne.l error
3125
3126ea_21:
3127 addq.l &0x1,TESTCTR(%a6)
3128
3129 movm.l DEF_REGS(%pc),&0x3fff
3130
3131 clr.l %d2
3132 mov.l &0x00000002,%d3
3133 lea EAMEM(%a6),%a0
3134 mov.l &-0x8,%d4
3135
3136 mov.w &0x0000,ICCR(%a6)
3137 mov.w &0x0000,%cc
3138 movm.l &0xffff,IREGS(%a6)
3139
3140 mulu.l (0x10.b,%a0,%d4.l*2),%d2:%d3
3141
3142 mov.w %cc,SCCR(%a6)
3143 movm.l &0xffff,SREGS(%a6)
3144 mov.l &0x00000004,IREGS+0xc(%a6)
3145
3146 bsr.l chkregs
3147 tst.b %d0
3148 bne.l error
3149
3150ea_22:
3151 addq.l &0x1,TESTCTR(%a6)
3152
3153 movm.l DEF_REGS(%pc),&0x3fff
3154
3155 clr.l %d2
3156 mov.l &0x00000002,%d3
3157 lea EAMEM(%a6),%a0
3158 mov.l &-0x4,%d4
3159
3160 mov.w &0x0000,ICCR(%a6)
3161 mov.w &0x0000,%cc
3162 movm.l &0xffff,IREGS(%a6)
3163
3164 mulu.l (0x10.b,%a0,%d4.l*4),%d2:%d3
3165
3166 mov.w %cc,SCCR(%a6)
3167 movm.l &0xffff,SREGS(%a6)
3168 mov.l &0x00000004,IREGS+0xc(%a6)
3169
3170 bsr.l chkregs
3171 tst.b %d0
3172 bne.l error
3173
3174ea_23:
3175 addq.l &0x1,TESTCTR(%a6)
3176
3177 movm.l DEF_REGS(%pc),&0x3fff
3178
3179 clr.l %d2
3180 mov.l &0x00000002,%d3
3181 lea EAMEM(%a6),%a0
3182 mov.l &-0x2,%d4
3183
3184 mov.w &0x0000,ICCR(%a6)
3185 mov.w &0x0000,%cc
3186 movm.l &0xffff,IREGS(%a6)
3187
3188 mulu.l (0x10.b,%a0,%d4.l*8),%d2:%d3
3189
3190 mov.w %cc,SCCR(%a6)
3191 movm.l &0xffff,SREGS(%a6)
3192 mov.l &0x00000004,IREGS+0xc(%a6)
3193
3194 bsr.l chkregs
3195 tst.b %d0
3196 bne.l error
3197
3198ea_24:
3199 addq.l &0x1,TESTCTR(%a6)
3200
3201 movm.l DEF_REGS(%pc),&0x3fff
3202
3203 clr.l %d2
3204 mov.l &0x00000002,%d3
3205 lea EAMEM(%a6),%a0
3206 mov.l &-0x2,%a4
3207
3208 mov.w &0x0000,ICCR(%a6)
3209 mov.w &0x0000,%cc
3210 movm.l &0xffff,IREGS(%a6)
3211
3212 mulu.l (0x10.b,%a0,%a4.l*8),%d2:%d3
3213
3214 mov.w %cc,SCCR(%a6)
3215 movm.l &0xffff,SREGS(%a6)
3216 mov.l &0x00000004,IREGS+0xc(%a6)
3217
3218 bsr.l chkregs
3219 tst.b %d0
3220 bne.l error
3221
3222ea_25:
3223 addq.l &0x1,TESTCTR(%a6)
3224
3225 movm.l DEF_REGS(%pc),&0x3fff
3226
3227 clr.l %d2
3228 mov.l &0x00000002,%d3
3229 lea EAMEM(%a6),%a0
3230 mov.l &0x2,%a4
3231
3232 mov.w &0x0000,ICCR(%a6)
3233 mov.w &0x0000,%cc
3234 movm.l &0xffff,IREGS(%a6)
3235
3236 mulu.l (-0x10.b,%a0,%a4.l*8),%d2:%d3
3237
3238 mov.w %cc,SCCR(%a6)
3239 movm.l &0xffff,SREGS(%a6)
3240 mov.l &0x00000004,IREGS+0xc(%a6)
3241
3242 bsr.l chkregs
3243 tst.b %d0
3244 bne.l error
3245
3246ea_26:
3247 addq.l &0x1,TESTCTR(%a6)
3248
3249 movm.l DEF_REGS(%pc),&0x3fff
3250
3251 clr.l %d2
3252 mov.l &0x00000002,%d3
3253 lea EAMEM(%a6),%a1
3254 mov.l &-0x10,%d4
3255
3256 mov.w &0x0000,ICCR(%a6)
3257 mov.w &0x0000,%cc
3258 movm.l &0xffff,IREGS(%a6)
3259
3260 mulu.l (0x10.b,%a1,%d4.w*1),%d2:%d3
3261
3262 mov.w %cc,SCCR(%a6)
3263 movm.l &0xffff,SREGS(%a6)
3264 mov.l &0x00000004,IREGS+0xc(%a6)
3265
3266 bsr.l chkregs
3267 tst.b %d0
3268 bne.l error
3269
3270ea_27:
3271 addq.l &0x1,TESTCTR(%a6)
3272
3273 movm.l DEF_REGS(%pc),&0x3fff
3274
3275 clr.l %d2
3276 mov.l &0x00000002,%d3
3277 lea EAMEM(%a6),%a2
3278 mov.l &-0x10,%d4
3279
3280 mov.w &0x0000,ICCR(%a6)
3281 mov.w &0x0000,%cc
3282 movm.l &0xffff,IREGS(%a6)
3283
3284 mulu.l (0x10.b,%a2,%d4.w*1),%d2:%d3
3285
3286 mov.w %cc,SCCR(%a6)
3287 movm.l &0xffff,SREGS(%a6)
3288 mov.l &0x00000004,IREGS+0xc(%a6)
3289
3290 bsr.l chkregs
3291 tst.b %d0
3292 bne.l error
3293
3294ea_28:
3295 addq.l &0x1,TESTCTR(%a6)
3296
3297 movm.l DEF_REGS(%pc),&0x3fff
3298
3299 clr.l %d2
3300 mov.l &0x00000002,%d3
3301 lea EAMEM(%a6),%a3
3302 mov.l &-0x10,%d4
3303
3304 mov.w &0x0000,ICCR(%a6)
3305 mov.w &0x0000,%cc
3306 movm.l &0xffff,IREGS(%a6)
3307
3308 mulu.l (0x10.b,%a3,%d4.w*1),%d2:%d3
3309
3310 mov.w %cc,SCCR(%a6)
3311 movm.l &0xffff,SREGS(%a6)
3312 mov.l &0x00000004,IREGS+0xc(%a6)
3313
3314 bsr.l chkregs
3315 tst.b %d0
3316 bne.l error
3317
3318ea_29:
3319 addq.l &0x1,TESTCTR(%a6)
3320
3321 movm.l DEF_REGS(%pc),&0x3fff
3322
3323 clr.l %d2
3324 mov.l &0x00000002,%d3
3325 lea EAMEM(%a6),%a4
3326 mov.l &-0x10,%d4
3327
3328 mov.w &0x0000,ICCR(%a6)
3329 mov.w &0x0000,%cc
3330 movm.l &0xffff,IREGS(%a6)
3331
3332 mulu.l (0x10.b,%a4,%d4.w*1),%d2:%d3
3333
3334 mov.w %cc,SCCR(%a6)
3335 movm.l &0xffff,SREGS(%a6)
3336 mov.l &0x00000004,IREGS+0xc(%a6)
3337
3338 bsr.l chkregs
3339 tst.b %d0
3340 bne.l error
3341
3342ea_30:
3343 addq.l &0x1,TESTCTR(%a6)
3344
3345 movm.l DEF_REGS(%pc),&0x3fff
3346
3347 clr.l %d2
3348 mov.l &0x00000002,%d3
3349 lea EAMEM(%a6),%a5
3350 mov.l &-0x10,%d4
3351
3352 mov.w &0x0000,ICCR(%a6)
3353 mov.w &0x0000,%cc
3354 movm.l &0xffff,IREGS(%a6)
3355
3356 mulu.l (0x10.b,%a5,%d4.w*1),%d2:%d3
3357
3358 mov.w %cc,SCCR(%a6)
3359 movm.l &0xffff,SREGS(%a6)
3360 mov.l &0x00000004,IREGS+0xc(%a6)
3361
3362 bsr.l chkregs
3363 tst.b %d0
3364 bne.l error
3365
3366ea_31:
3367 addq.l &0x1,TESTCTR(%a6)
3368
3369 movm.l DEF_REGS(%pc),&0x3fff
3370
3371 mov.l %a6,%a1
3372
3373 clr.l %d2
3374 mov.l &0x00000002,%d3
3375 lea EAMEM(%a1),%a6
3376 mov.l &-0x10,%d4
3377
3378 mov.w &0x0000,ICCR(%a1)
3379 mov.w &0x0000,%cc
3380 movm.l &0xffff,IREGS(%a1)
3381
3382 mulu.l (0x10.b,%a6,%d4.w*1),%d2:%d3
3383
3384 mov.w %cc,SCCR(%a1)
3385 movm.l &0xffff,SREGS(%a1)
3386 mov.l &0x00000004,IREGS+0xc(%a1)
3387
3388 mov.l %a1,%a6
3389
3390 bsr.l chkregs
3391 tst.b %d0
3392 bne.l error
3393
3394ea_32:
3395 addq.l &0x1,TESTCTR(%a6)
3396
3397 movm.l DEF_REGS(%pc),&0x3fff
3398
3399 clr.l %d2
3400 mov.l &0x00000002,%d3
3401 mov.l %a7,%a0
3402 lea EAMEM(%a6),%a7
3403 mov.l &-0x10,%d4
3404
3405 mov.w &0x0000,ICCR(%a6)
3406 mov.w &0x0000,%cc
3407 movm.l &0xffff,IREGS(%a6)
3408
3409 mulu.l (0x10.b,%a7,%d4.w*1),%d2:%d3
3410
3411 mov.w %cc,SCCR(%a6)
3412 movm.l &0xffff,SREGS(%a6)
3413 mov.l &0x00000004,IREGS+0xc(%a6)
3414
3415 mov.l %a0,%a7
3416 bsr.l chkregs
3417 tst.b %d0
3418 bne.l error
3419
3420ea_33:
3421 addq.l &0x1,TESTCTR(%a6)
3422
3423 movm.l DEF_REGS(%pc),&0x3fff
3424
3425 clr.l %d2
3426 mov.l &0x00000002,%d3
3427 lea EAMEM(%a6),%a1
3428
3429 mov.w &0x0000,ICCR(%a6)
3430 mov.w &0x0000,%cc
3431 movm.l &0xffff,IREGS(%a6)
3432
3433 mulu.l (%a1),%d2:%d3
3434
3435 mov.w %cc,SCCR(%a6)
3436 movm.l &0xffff,SREGS(%a6)
3437 mov.l &0x00000004,IREGS+0xc(%a6)
3438
3439 bsr.l chkregs
3440 tst.b %d0
3441 bne.l error
3442
3443ea_34:
3444 addq.l &0x1,TESTCTR(%a6)
3445
3446 movm.l DEF_REGS(%pc),&0x3fff
3447
3448 clr.l %d2
3449 mov.l &0x00000002,%d3
3450 lea EAMEM(%a6),%a2
3451
3452 mov.w &0x0000,ICCR(%a6)
3453 mov.w &0x0000,%cc
3454 movm.l &0xffff,IREGS(%a6)
3455
3456 mulu.l (%a2),%d2:%d3
3457
3458 mov.w %cc,SCCR(%a6)
3459 movm.l &0xffff,SREGS(%a6)
3460 mov.l &0x00000004,IREGS+0xc(%a6)
3461
3462 bsr.l chkregs
3463 tst.b %d0
3464 bne.l error
3465
3466ea_35:
3467 addq.l &0x1,TESTCTR(%a6)
3468
3469 movm.l DEF_REGS(%pc),&0x3fff
3470
3471 clr.l %d2
3472 mov.l &0x00000002,%d3
3473 lea EAMEM(%a6),%a3
3474
3475 mov.w &0x0000,ICCR(%a6)
3476 mov.w &0x0000,%cc
3477 movm.l &0xffff,IREGS(%a6)
3478
3479 mulu.l (%a3),%d2:%d3
3480
3481 mov.w %cc,SCCR(%a6)
3482 movm.l &0xffff,SREGS(%a6)
3483 mov.l &0x00000004,IREGS+0xc(%a6)
3484
3485 bsr.l chkregs
3486 tst.b %d0
3487 bne.l error
3488
3489ea_36:
3490 addq.l &0x1,TESTCTR(%a6)
3491
3492 movm.l DEF_REGS(%pc),&0x3fff
3493
3494 clr.l %d2
3495 mov.l &0x00000002,%d3
3496 lea EAMEM(%a6),%a4
3497
3498 mov.w &0x0000,ICCR(%a6)
3499 mov.w &0x0000,%cc
3500 movm.l &0xffff,IREGS(%a6)
3501
3502 mulu.l (%a4),%d2:%d3
3503
3504 mov.w %cc,SCCR(%a6)
3505 movm.l &0xffff,SREGS(%a6)
3506 mov.l &0x00000004,IREGS+0xc(%a6)
3507
3508 bsr.l chkregs
3509 tst.b %d0
3510 bne.l error
3511
3512ea_37:
3513 addq.l &0x1,TESTCTR(%a6)
3514
3515 movm.l DEF_REGS(%pc),&0x3fff
3516
3517 clr.l %d2
3518 mov.l &0x00000002,%d3
3519 lea EAMEM(%a6),%a5
3520
3521 mov.w &0x0000,ICCR(%a6)
3522 mov.w &0x0000,%cc
3523 movm.l &0xffff,IREGS(%a6)
3524
3525 mulu.l (%a5),%d2:%d3
3526
3527 mov.w %cc,SCCR(%a6)
3528 movm.l &0xffff,SREGS(%a6)
3529 mov.l &0x00000004,IREGS+0xc(%a6)
3530
3531 bsr.l chkregs
3532 tst.b %d0
3533 bne.l error
3534
3535ea_38:
3536 addq.l &0x1,TESTCTR(%a6)
3537
3538 movm.l DEF_REGS(%pc),&0x3fff
3539
3540 mov.l %a6,%a1
3541
3542 clr.l %d2
3543 mov.l &0x00000002,%d3
3544 lea EAMEM(%a1),%a6
3545
3546 mov.w &0x0000,ICCR(%a1)
3547 mov.w &0x0000,%cc
3548 movm.l &0xffff,IREGS(%a1)
3549
3550 mulu.l (%a6),%d2:%d3
3551
3552 mov.w %cc,SCCR(%a1)
3553 movm.l &0xffff,SREGS(%a1)
3554 mov.l &0x00000004,IREGS+0xc(%a1)
3555
3556 mov.l %a1,%a6
3557
3558 bsr.l chkregs
3559 tst.b %d0
3560 bne.l error
3561
3562ea_39:
3563 addq.l &0x1,TESTCTR(%a6)
3564
3565 movm.l DEF_REGS(%pc),&0x3fff
3566
3567 clr.l %d2
3568 mov.l &0x00000002,%d3
3569 mov.l %a7,%a0
3570 lea EAMEM(%a6),%a7
3571
3572 mov.w &0x0000,ICCR(%a6)
3573 mov.w &0x0000,%cc
3574 movm.l &0xffff,IREGS(%a6)
3575
3576 mulu.l (%a7),%d2:%d3
3577
3578 mov.w %cc,SCCR(%a6)
3579 movm.l &0xffff,SREGS(%a6)
3580 mov.l &0x00000004,IREGS+0xc(%a6)
3581
3582 mov.l %a0,%a7
3583 bsr.l chkregs
3584 tst.b %d0
3585 bne.l error
3586
3587ea_40:
3588 addq.l &0x1,TESTCTR(%a6)
3589
3590 movm.l DEF_REGS(%pc),&0x3fff
3591
3592 clr.l %d2
3593 mov.l &0x00000002,%d3
3594 lea EAMEM(%a6),%a1
3595
3596 mov.w &0x0000,ICCR(%a6)
3597 mov.w &0x0000,%cc
3598 movm.l &0xffff,IREGS(%a6)
3599
3600 mulu.l (%a1)+,%d2:%d3
3601
3602 mov.w %cc,SCCR(%a6)
3603 movm.l &0xffff,SREGS(%a6)
3604 mov.l &0x00000004,IREGS+0xc(%a6)
3605 lea EAMEM+0x4(%a6),%a0
3606 mov.l %a0,IREGS+0x24(%a6)
3607
3608 bsr.l chkregs
3609 tst.b %d0
3610 bne.l error
3611
3612ea_41:
3613 addq.l &0x1,TESTCTR(%a6)
3614
3615 movm.l DEF_REGS(%pc),&0x3fff
3616
3617 clr.l %d2
3618 mov.l &0x00000002,%d3
3619 lea EAMEM(%a6),%a2
3620
3621 mov.w &0x0000,ICCR(%a6)
3622 mov.w &0x0000,%cc
3623 movm.l &0xffff,IREGS(%a6)
3624
3625 mulu.l (%a2)+,%d2:%d3
3626
3627 mov.w %cc,SCCR(%a6)
3628 movm.l &0xffff,SREGS(%a6)
3629 mov.l &0x00000004,IREGS+0xc(%a6)
3630 lea EAMEM+0x4(%a6),%a0
3631 mov.l %a0,IREGS+0x28(%a6)
3632
3633 bsr.l chkregs
3634 tst.b %d0
3635 bne.l error
3636
3637ea_42:
3638 addq.l &0x1,TESTCTR(%a6)
3639
3640 movm.l DEF_REGS(%pc),&0x3fff
3641
3642 clr.l %d2
3643 mov.l &0x00000002,%d3
3644 lea EAMEM(%a6),%a3
3645
3646 mov.w &0x0000,ICCR(%a6)
3647 mov.w &0x0000,%cc
3648 movm.l &0xffff,IREGS(%a6)
3649
3650 mulu.l (%a3)+,%d2:%d3
3651
3652 mov.w %cc,SCCR(%a6)
3653 movm.l &0xffff,SREGS(%a6)
3654 mov.l &0x00000004,IREGS+0xc(%a6)
3655 lea EAMEM+0x4(%a6),%a0
3656 mov.l %a0,IREGS+0x2c(%a6)
3657
3658 bsr.l chkregs
3659 tst.b %d0
3660 bne.l error
3661
3662ea_43:
3663 addq.l &0x1,TESTCTR(%a6)
3664
3665 movm.l DEF_REGS(%pc),&0x3fff
3666
3667 clr.l %d2
3668 mov.l &0x00000002,%d3
3669 lea EAMEM(%a6),%a4
3670
3671 mov.w &0x0000,ICCR(%a6)
3672 mov.w &0x0000,%cc
3673 movm.l &0xffff,IREGS(%a6)
3674
3675 mulu.l (%a4)+,%d2:%d3
3676
3677 mov.w %cc,SCCR(%a6)
3678 movm.l &0xffff,SREGS(%a6)
3679 mov.l &0x00000004,IREGS+0xc(%a6)
3680 lea EAMEM+0x4(%a6),%a0
3681 mov.l %a0,IREGS+0x30(%a6)
3682
3683 bsr.l chkregs
3684 tst.b %d0
3685 bne.l error
3686
3687ea_44:
3688 addq.l &0x1,TESTCTR(%a6)
3689
3690 movm.l DEF_REGS(%pc),&0x3fff
3691
3692 clr.l %d2
3693 mov.l &0x00000002,%d3
3694 lea EAMEM(%a6),%a5
3695
3696 mov.w &0x0000,ICCR(%a6)
3697 mov.w &0x0000,%cc
3698 movm.l &0xffff,IREGS(%a6)
3699
3700 mulu.l (%a5)+,%d2:%d3
3701
3702 mov.w %cc,SCCR(%a6)
3703 movm.l &0xffff,SREGS(%a6)
3704 mov.l &0x00000004,IREGS+0xc(%a6)
3705 lea EAMEM+0x4(%a6),%a0
3706 mov.l %a0,IREGS+0x34(%a6)
3707
3708 bsr.l chkregs
3709 tst.b %d0
3710 bne.l error
3711
3712ea_45:
3713 addq.l &0x1,TESTCTR(%a6)
3714
3715 movm.l DEF_REGS(%pc),&0x3fff
3716
3717 mov.l %a6,%a1
3718
3719 clr.l %d2
3720 mov.l &0x00000002,%d3
3721 lea EAMEM(%a1),%a6
3722
3723 mov.w &0x0000,ICCR(%a1)
3724 mov.w &0x0000,%cc
3725 movm.l &0xffff,IREGS(%a1)
3726
3727 mulu.l (%a6)+,%d2:%d3
3728
3729 mov.w %cc,SCCR(%a1)
3730 movm.l &0xffff,SREGS(%a1)
3731 mov.l &0x00000004,IREGS+0xc(%a1)
3732 lea EAMEM+0x4(%a1),%a0
3733 mov.l %a0,IREGS+0x38(%a1)
3734
3735 mov.l %a1,%a6
3736
3737 bsr.l chkregs
3738 tst.b %d0
3739 bne.l error
3740
3741ea_46:
3742 addq.l &0x1,TESTCTR(%a6)
3743
3744 movm.l DEF_REGS(%pc),&0x3fff
3745
3746 clr.l %d2
3747 mov.l &0x00000002,%d3
3748 mov.l %a7,%a0
3749 lea EAMEM(%a6),%a7
3750
3751 mov.w &0x0000,ICCR(%a6)
3752 mov.w &0x0000,%cc
3753 movm.l &0xffff,IREGS(%a6)
3754
3755 mulu.l (%a7)+,%d2:%d3
3756
3757 mov.w %cc,SCCR(%a6)
3758 movm.l &0xffff,SREGS(%a6)
3759 mov.l &0x00000004,IREGS+0xc(%a6)
3760 lea EAMEM+0x4(%a6),%a1
3761 mov.l %a1,IREGS+0x3c(%a6)
3762
3763 mov.l %a0,%a7
3764 bsr.l chkregs
3765 tst.b %d0
3766 bne.l error
3767
3768ea_47:
3769 addq.l &0x1,TESTCTR(%a6)
3770
3771 movm.l DEF_REGS(%pc),&0x3fff
3772
3773 clr.l %d2
3774 mov.l &0x00000002,%d3
3775 lea EAMEM-0x1000(%a6),%a1
3776
3777 mov.w &0x0000,ICCR(%a6)
3778 mov.w &0x0000,%cc
3779 movm.l &0xffff,IREGS(%a6)
3780
3781 mulu.l (0x1000,%a1),%d2:%d3
3782
3783 mov.w %cc,SCCR(%a6)
3784 movm.l &0xffff,SREGS(%a6)
3785 mov.l &0x00000004,IREGS+0xc(%a6)
3786
3787 bsr.l chkregs
3788 tst.b %d0
3789 bne.l error
3790
3791ea_48:
3792 addq.l &0x1,TESTCTR(%a6)
3793
3794 movm.l DEF_REGS(%pc),&0x3fff
3795
3796 clr.l %d2
3797 mov.l &0x00000002,%d3
3798 lea EAMEM-0x1000(%a6),%a2
3799
3800 mov.w &0x0000,ICCR(%a6)
3801 mov.w &0x0000,%cc
3802 movm.l &0xffff,IREGS(%a6)
3803
3804 mulu.l (0x1000,%a2),%d2:%d3
3805
3806 mov.w %cc,SCCR(%a6)
3807 movm.l &0xffff,SREGS(%a6)
3808 mov.l &0x00000004,IREGS+0xc(%a6)
3809
3810 bsr.l chkregs
3811 tst.b %d0
3812 bne.l error
3813
3814ea_49:
3815 addq.l &0x1,TESTCTR(%a6)
3816
3817 movm.l DEF_REGS(%pc),&0x3fff
3818
3819 clr.l %d2
3820 mov.l &0x00000002,%d3
3821 lea EAMEM-0x1000(%a6),%a3
3822
3823 mov.w &0x0000,ICCR(%a6)
3824 mov.w &0x0000,%cc
3825 movm.l &0xffff,IREGS(%a6)
3826
3827 mulu.l (0x1000,%a3),%d2:%d3
3828
3829 mov.w %cc,SCCR(%a6)
3830 movm.l &0xffff,SREGS(%a6)
3831 mov.l &0x00000004,IREGS+0xc(%a6)
3832
3833 bsr.l chkregs
3834 tst.b %d0
3835 bne.l error
3836
3837ea_50:
3838 addq.l &0x1,TESTCTR(%a6)
3839
3840 movm.l DEF_REGS(%pc),&0x3fff
3841
3842 clr.l %d2
3843 mov.l &0x00000002,%d3
3844 lea EAMEM-0x1000(%a6),%a4
3845
3846 mov.w &0x0000,ICCR(%a6)
3847 mov.w &0x0000,%cc
3848 movm.l &0xffff,IREGS(%a6)
3849
3850 mulu.l (0x1000,%a4),%d2:%d3
3851
3852 mov.w %cc,SCCR(%a6)
3853 movm.l &0xffff,SREGS(%a6)
3854 mov.l &0x00000004,IREGS+0xc(%a6)
3855
3856 bsr.l chkregs
3857 tst.b %d0
3858 bne.l error
3859
3860ea_51:
3861 addq.l &0x1,TESTCTR(%a6)
3862
3863 movm.l DEF_REGS(%pc),&0x3fff
3864
3865 clr.l %d2
3866 mov.l &0x00000002,%d3
3867 lea EAMEM-0x1000(%a6),%a5
3868
3869 mov.w &0x0000,ICCR(%a6)
3870 mov.w &0x0000,%cc
3871 movm.l &0xffff,IREGS(%a6)
3872
3873 mulu.l (0x1000,%a5),%d2:%d3
3874
3875 mov.w %cc,SCCR(%a6)
3876 movm.l &0xffff,SREGS(%a6)
3877 mov.l &0x00000004,IREGS+0xc(%a6)
3878
3879 bsr.l chkregs
3880 tst.b %d0
3881 bne.l error
3882
3883ea_52:
3884 addq.l &0x1,TESTCTR(%a6)
3885
3886 movm.l DEF_REGS(%pc),&0x3fff
3887
3888 mov.l %a6,%a1
3889
3890 clr.l %d2
3891 mov.l &0x00000002,%d3
3892 lea EAMEM-0x1000(%a1),%a6
3893
3894 mov.w &0x0000,ICCR(%a1)
3895 mov.w &0x0000,%cc
3896 movm.l &0xffff,IREGS(%a1)
3897
3898 mulu.l (0x1000,%a6),%d2:%d3
3899
3900 mov.w %cc,SCCR(%a1)
3901 movm.l &0xffff,SREGS(%a1)
3902 mov.l &0x00000004,IREGS+0xc(%a1)
3903
3904 mov.l %a1,%a6
3905
3906 bsr.l chkregs
3907 tst.b %d0
3908 bne.l error
3909
3910ea_53:
3911 addq.l &0x1,TESTCTR(%a6)
3912
3913 movm.l DEF_REGS(%pc),&0x3fff
3914
3915 clr.l %d2
3916 mov.l &0x00000002,%d3
3917 mov.l %a7,%a0
3918 lea EAMEM-0x1000(%a6),%a7
3919
3920 mov.w &0x0000,ICCR(%a6)
3921 mov.w &0x0000,%cc
3922 movm.l &0xffff,IREGS(%a6)
3923
3924 mulu.l (0x1000,%a7),%d2:%d3
3925
3926 mov.w %cc,SCCR(%a6)
3927 movm.l &0xffff,SREGS(%a6)
3928 mov.l &0x00000004,IREGS+0xc(%a6)
3929
3930 mov.l %a0,%a7
3931 bsr.l chkregs
3932 tst.b %d0
3933 bne.l error
3934
3935ea_54:
3936 addq.l &0x1,TESTCTR(%a6)
3937
3938 movm.l DEF_REGS(%pc),&0x3fff
3939
3940 clr.l %d2
3941 mov.l &0x00000002,%d3
3942 lea EAMEM+0x1000(%a6),%a0
3943
3944 mov.w &0x0000,ICCR(%a6)
3945 mov.w &0x0000,%cc
3946 movm.l &0xffff,IREGS(%a6)
3947
3948 mulu.l (-0x1000,%a0),%d2:%d3
3949
3950 mov.w %cc,SCCR(%a6)
3951 movm.l &0xffff,SREGS(%a6)
3952 mov.l &0x00000004,IREGS+0xc(%a6)
3953
3954 bsr.l chkregs
3955 tst.b %d0
3956 bne.l error
3957
3958ea_55:
3959 addq.l &0x1,TESTCTR(%a6)
3960
3961 bra.b ea_55_next
3962
3963ea_55_data:
3964 long 0x00000002
3965ea_55_next:
3966 movm.l DEF_REGS(%pc),&0x3fff
3967
3968 clr.l %d2
3969 mov.l &0x00000002,%d3
3970
3971 mov.w &0x0000,ICCR(%a6)
3972 mov.w &0x0000,%cc
3973 movm.l &0xffff,IREGS(%a6)
3974
3975 mulu.l (ea_55_data.w,%pc),%d2:%d3
3976
3977 mov.w %cc,SCCR(%a6)
3978 movm.l &0xffff,SREGS(%a6)
3979 mov.l &0x00000004,IREGS+0xc(%a6)
3980
3981 bsr.l chkregs
3982 tst.b %d0
3983 bne.l error
3984
3985ea_56:
3986 addq.l &0x1,TESTCTR(%a6)
3987
3988 movm.l DEF_REGS(%pc),&0x3fff
3989
3990 clr.l %d2
3991 mov.l &0x00000002,%d3
3992 lea EAMEM(%a6),%a3
3993 mov.l &-0x10,%d4
3994
3995 mov.w &0x0000,ICCR(%a6)
3996 mov.w &0x0000,%cc
3997 movm.l &0xffff,IREGS(%a6)
3998
3999 mulu.l (0x10.w,%a3,%d4.w*1),%d2:%d3
4000
4001 mov.w %cc,SCCR(%a6)
4002 movm.l &0xffff,SREGS(%a6)
4003 mov.l &0x00000004,IREGS+0xc(%a6)
4004
4005 bsr.l chkregs
4006 tst.b %d0
4007 bne.l error
4008
4009ea_57:
4010 addq.l &0x1,TESTCTR(%a6)
4011
4012 movm.l DEF_REGS(%pc),&0x3fff
4013
4014 clr.l %d2
4015 mov.l &0x00000002,%d3
4016 lea EAMEM(%a6),%a3
4017 mov.l &-0x8,%d4
4018
4019 mov.w &0x0000,ICCR(%a6)
4020 mov.w &0x0000,%cc
4021 movm.l &0xffff,IREGS(%a6)
4022
4023 mulu.l (0x10.w,%a3,%d4.w*2),%d2:%d3
4024
4025 mov.w %cc,SCCR(%a6)
4026 movm.l &0xffff,SREGS(%a6)
4027 mov.l &0x00000004,IREGS+0xc(%a6)
4028
4029 bsr.l chkregs
4030 tst.b %d0
4031 bne.l error
4032
4033ea_58:
4034 addq.l &0x1,TESTCTR(%a6)
4035
4036 movm.l DEF_REGS(%pc),&0x3fff
4037
4038 clr.l %d2
4039 mov.l &0x00000002,%d3
4040 lea EAMEM(%a6),%a3
4041 mov.l &-0x4,%d4
4042
4043 mov.w &0x0000,ICCR(%a6)
4044 mov.w &0x0000,%cc
4045 movm.l &0xffff,IREGS(%a6)
4046
4047 mulu.l (0x10.w,%a3,%d4.w*4),%d2:%d3
4048
4049 mov.w %cc,SCCR(%a6)
4050 movm.l &0xffff,SREGS(%a6)
4051 mov.l &0x00000004,IREGS+0xc(%a6)
4052
4053 bsr.l chkregs
4054 tst.b %d0
4055 bne.l error
4056
4057ea_59:
4058 addq.l &0x1,TESTCTR(%a6)
4059
4060 movm.l DEF_REGS(%pc),&0x3fff
4061
4062 clr.l %d2
4063 mov.l &0x00000002,%d3
4064 lea EAMEM(%a6),%a3
4065 mov.l &-0x2,%d4
4066
4067 mov.w &0x0000,ICCR(%a6)
4068 mov.w &0x0000,%cc
4069 movm.l &0xffff,IREGS(%a6)
4070
4071 mulu.l (0x10.w,%a3,%d4.w*8),%d2:%d3
4072
4073 mov.w %cc,SCCR(%a6)
4074 movm.l &0xffff,SREGS(%a6)
4075 mov.l &0x00000004,IREGS+0xc(%a6)
4076
4077 bsr.l chkregs
4078 tst.b %d0
4079 bne.l error
4080
4081ea_60:
4082 addq.l &0x1,TESTCTR(%a6)
4083
4084 movm.l DEF_REGS(%pc),&0x3fff
4085
4086 clr.l %d2
4087 mov.l &0x00000002,%d3
4088 lea EAMEM(%a6),%a3
4089 mov.l &-0x10,%d4
4090
4091 mov.w &0x0000,ICCR(%a6)
4092 mov.w &0x0000,%cc
4093 movm.l &0xffff,IREGS(%a6)
4094
4095 mulu.l (0x10.w,%a3,%d4.l*1),%d2:%d3
4096
4097 mov.w %cc,SCCR(%a6)
4098 movm.l &0xffff,SREGS(%a6)
4099 mov.l &0x00000004,IREGS+0xc(%a6)
4100
4101 bsr.l chkregs
4102 tst.b %d0
4103 bne.l error
4104
4105ea_61:
4106 addq.l &0x1,TESTCTR(%a6)
4107
4108 movm.l DEF_REGS(%pc),&0x3fff
4109
4110 clr.l %d2
4111 mov.l &0x00000002,%d3
4112 lea EAMEM(%a6),%a3
4113 mov.l &-0x8,%d4
4114
4115 mov.w &0x0000,ICCR(%a6)
4116 mov.w &0x0000,%cc
4117 movm.l &0xffff,IREGS(%a6)
4118
4119 mulu.l (0x10.w,%a3,%d4.l*2),%d2:%d3
4120
4121 mov.w %cc,SCCR(%a6)
4122 movm.l &0xffff,SREGS(%a6)
4123 mov.l &0x00000004,IREGS+0xc(%a6)
4124
4125 bsr.l chkregs
4126 tst.b %d0
4127 bne.l error
4128
4129ea_62:
4130 addq.l &0x1,TESTCTR(%a6)
4131
4132 movm.l DEF_REGS(%pc),&0x3fff
4133
4134 clr.l %d2
4135 mov.l &0x00000002,%d3
4136 lea EAMEM(%a6),%a3
4137 mov.l &-0x4,%d4
4138
4139 mov.w &0x0000,ICCR(%a6)
4140 mov.w &0x0000,%cc
4141 movm.l &0xffff,IREGS(%a6)
4142
4143 mulu.l (0x10.w,%a3,%d4.l*4),%d2:%d3
4144
4145 mov.w %cc,SCCR(%a6)
4146 movm.l &0xffff,SREGS(%a6)
4147 mov.l &0x00000004,IREGS+0xc(%a6)
4148
4149 bsr.l chkregs
4150 tst.b %d0
4151 bne.l error
4152
4153ea_63:
4154 addq.l &0x1,TESTCTR(%a6)
4155
4156 movm.l DEF_REGS(%pc),&0x3fff
4157
4158 clr.l %d2
4159 mov.l &0x00000002,%d3
4160 lea EAMEM(%a6),%a3
4161 mov.l &-0x2,%d4
4162
4163 mov.w &0x0000,ICCR(%a6)
4164 mov.w &0x0000,%cc
4165 movm.l &0xffff,IREGS(%a6)
4166
4167 mulu.l (0x10.w,%a3,%d4.l*8),%d2:%d3
4168
4169 mov.w %cc,SCCR(%a6)
4170 movm.l &0xffff,SREGS(%a6)
4171 mov.l &0x00000004,IREGS+0xc(%a6)
4172
4173 bsr.l chkregs
4174 tst.b %d0
4175 bne.l error
4176
4177ea_64:
4178 addq.l &0x1,TESTCTR(%a6)
4179
4180 movm.l DEF_REGS(%pc),&0x3fff
4181
4182 clr.l %d2
4183 mov.l &0x00000002,%d3
4184 lea EAMEM(%a6),%a3
4185 mov.l &0x2,%a4
4186
4187 mov.w &0x0000,ICCR(%a6)
4188 mov.w &0x0000,%cc
4189 movm.l &0xffff,IREGS(%a6)
4190
4191 mulu.l (-0x10.w,%a3,%a4.l*8),%d2:%d3
4192
4193 mov.w %cc,SCCR(%a6)
4194 movm.l &0xffff,SREGS(%a6)
4195 mov.l &0x00000004,IREGS+0xc(%a6)
4196
4197 bsr.l chkregs
4198 tst.b %d0
4199 bne.l error
4200
4201ea_65:
4202 addq.l &0x1,TESTCTR(%a6)
4203
4204 movm.l DEF_REGS(%pc),&0x3fff
4205
4206 clr.l %d2
4207 mov.l &0x00000002,%d3
4208 lea EAMEM(%a6),%a3
4209 mov.l &0x2,%a4
4210
4211 mov.w &0x0000,ICCR(%a6)
4212 mov.w &0x0000,%cc
4213 movm.l &0xffff,IREGS(%a6)
4214
4215 mulu.l (0x00.w,%a3,%za4.l*8),%d2:%d3
4216
4217 mov.w %cc,SCCR(%a6)
4218 movm.l &0xffff,SREGS(%a6)
4219 mov.l &0x00000004,IREGS+0xc(%a6)
4220
4221 bsr.l chkregs
4222 tst.b %d0
4223 bne.l error
4224
4225ea_66:
4226 addq.l &0x1,TESTCTR(%a6)
4227
4228 movm.l DEF_REGS(%pc),&0x3fff
4229
4230 clr.l %d2
4231 mov.l &0x00000002,%d3
4232 lea EAMEM(%a6),%a3
4233 mov.l %a3,%a4
4234 add.l &0x10,%a4
4235
4236 mov.w &0x0000,ICCR(%a6)
4237 mov.w &0x0000,%cc
4238 movm.l &0xffff,IREGS(%a6)
4239
4240 mulu.l (-0x10.w,%za3,%a4.l*1),%d2:%d3
4241
4242 mov.w %cc,SCCR(%a6)
4243 movm.l &0xffff,SREGS(%a6)
4244 mov.l &0x00000004,IREGS+0xc(%a6)
4245
4246 bsr.l chkregs
4247 tst.b %d0
4248 bne.l error
4249
4250ea_67:
4251 addq.l &0x1,TESTCTR(%a6)
4252
4253 movm.l DEF_REGS(%pc),&0x3fff
4254
4255 clr.l %d2
4256 mov.l &0x00000002,%d3
4257 lea EAMEM(%a6),%a3
4258 mov.l &0x2,%a4
4259
4260 mov.w &0x0000,ICCR(%a6)
4261 mov.w &0x0000,%cc
4262 movm.l &0xffff,IREGS(%a6)
4263
4264 mulu.l (-0x10.l,%a3,%a4.l*8),%d2:%d3
4265
4266 mov.w %cc,SCCR(%a6)
4267 movm.l &0xffff,SREGS(%a6)
4268 mov.l &0x00000004,IREGS+0xc(%a6)
4269
4270 bsr.l chkregs
4271 tst.b %d0
4272 bne.l error
4273
4274ea_68:
4275 addq.l &0x1,TESTCTR(%a6)
4276
4277 bra.b ea_68_next
4278ea_68_mem:
4279 long 0x00000002
4280ea_68_next:
4281 movm.l DEF_REGS(%pc),&0x3fff
4282
4283 clr.l %d2
4284 mov.l &0x00000002,%d3
4285 lea EAMEM(%a6),%a3
4286 mov.l &-0x10,%d4
4287
4288 mov.w &0x0000,ICCR(%a6)
4289 mov.w &0x0000,%cc
4290 movm.l &0xffff,IREGS(%a6)
4291
4292 mulu.l (ea_68_mem+0x10.w,%pc,%d4.w*1),%d2:%d3
4293
4294 mov.w %cc,SCCR(%a6)
4295 movm.l &0xffff,SREGS(%a6)
4296 mov.l &0x00000004,IREGS+0xc(%a6)
4297
4298 bsr.l chkregs
4299 tst.b %d0
4300 bne.l error
4301
4302ea_69:
4303 addq.l &0x1,TESTCTR(%a6)
4304
4305 bra.b ea_69_next
4306ea_69_mem:
4307 long 0x00000002
4308ea_69_next:
4309 movm.l DEF_REGS(%pc),&0x3fff
4310
4311 clr.l %d2
4312 mov.l &0x00000002,%d3
4313 lea EAMEM(%a6),%a0
4314 mov.l &-0x8,%d4
4315
4316 mov.w &0x0000,ICCR(%a6)
4317 mov.w &0x0000,%cc
4318 movm.l &0x7fff,IREGS(%a6)
4319
4320 mulu.l (ea_69_mem+0x10.w,%pc,%d4.w*2),%d2:%d3
4321
4322 mov.w %cc,SCCR(%a6)
4323 movm.l &0x7fff,SREGS(%a6)
4324 mov.l &0x00000004,IREGS+0xc(%a6)
4325
4326 bsr.l chkregs
4327 tst.b %d0
4328 bne.l error
4329
4330ea_70:
4331 addq.l &0x1,TESTCTR(%a6)
4332
4333 bra.b ea_70_next
4334ea_70_mem:
4335 long 0x00000002
4336ea_70_next:
4337 movm.l DEF_REGS(%pc),&0x3fff
4338
4339 clr.l %d2
4340 mov.l &0x00000002,%d3
4341 lea EAMEM(%a6),%a0
4342 mov.l &-0x4,%d4
4343
4344 mov.w &0x0000,ICCR(%a6)
4345 mov.w &0x0000,%cc
4346 movm.l &0x7fff,IREGS(%a6)
4347
4348 mulu.l (ea_70_mem+0x10.w,%pc,%d4.w*4),%d2:%d3
4349
4350 mov.w %cc,SCCR(%a6)
4351 movm.l &0x7fff,SREGS(%a6)
4352 mov.l &0x00000004,IREGS+0xc(%a6)
4353
4354 bsr.l chkregs
4355 tst.b %d0
4356 bne.l error
4357
4358ea_71:
4359 addq.l &0x1,TESTCTR(%a6)
4360
4361 bra.b ea_71_next
4362ea_71_mem:
4363 long 0x00000002
4364ea_71_next:
4365 movm.l DEF_REGS(%pc),&0x3fff
4366
4367 clr.l %d2
4368 mov.l &0x00000002,%d3
4369 lea EAMEM(%a6),%a0
4370 mov.l &-0x2,%d4
4371
4372 mov.w &0x0000,ICCR(%a6)
4373 mov.w &0x0000,%cc
4374 movm.l &0x7fff,IREGS(%a6)
4375
4376 mulu.l (ea_71_mem+0x10.w,%pc,%d4.w*8),%d2:%d3
4377
4378 mov.w %cc,SCCR(%a6)
4379 movm.l &0x7fff,SREGS(%a6)
4380 mov.l &0x00000004,IREGS+0xc(%a6)
4381
4382 bsr.l chkregs
4383 tst.b %d0
4384 bne.l error
4385
4386ea_72:
4387 addq.l &0x1,TESTCTR(%a6)
4388
4389 bra.b ea_72_next
4390ea_72_mem:
4391 long 0x00000002
4392ea_72_next:
4393 movm.l DEF_REGS(%pc),&0x3fff
4394
4395 clr.l %d2
4396 mov.l &0x00000002,%d3
4397 lea EAMEM(%a6),%a0
4398 mov.l &-0x10,%d4
4399
4400 mov.w &0x0000,ICCR(%a6)
4401 mov.w &0x0000,%cc
4402 movm.l &0x7fff,IREGS(%a6)
4403
4404 mulu.l (ea_72_mem+0x10.w,%pc,%d4.l*1),%d2:%d3
4405
4406 mov.w %cc,SCCR(%a6)
4407 movm.l &0x7fff,SREGS(%a6)
4408 mov.l &0x00000004,IREGS+0xc(%a6)
4409
4410 bsr.l chkregs
4411 tst.b %d0
4412 bne.l error
4413
4414ea_73:
4415 addq.l &0x1,TESTCTR(%a6)
4416
4417 bra.b ea_73_next
4418ea_73_mem:
4419 long 0x00000002
4420ea_73_next:
4421 movm.l DEF_REGS(%pc),&0x3fff
4422
4423 clr.l %d2
4424 mov.l &0x00000002,%d3
4425 lea EAMEM(%a6),%a0
4426 mov.l &-0x8,%d4
4427
4428 mov.w &0x0000,ICCR(%a6)
4429 mov.w &0x0000,%cc
4430 movm.l &0x7fff,IREGS(%a6)
4431
4432 mulu.l (ea_73_mem+0x10.w,%pc,%d4.l*2),%d2:%d3
4433
4434 mov.w %cc,SCCR(%a6)
4435 movm.l &0x7fff,SREGS(%a6)
4436 mov.l &0x00000004,IREGS+0xc(%a6)
4437
4438 bsr.l chkregs
4439 tst.b %d0
4440 bne.l error
4441
4442ea_74:
4443 addq.l &0x1,TESTCTR(%a6)
4444
4445 bra.b ea_74_next
4446ea_74_mem:
4447 long 0x00000002
4448ea_74_next:
4449 movm.l DEF_REGS(%pc),&0x3fff
4450
4451 clr.l %d2
4452 mov.l &0x00000002,%d3
4453 lea EAMEM(%a6),%a0
4454 mov.l &-0x4,%d4
4455
4456 mov.w &0x0000,ICCR(%a6)
4457 mov.w &0x0000,%cc
4458 movm.l &0x7fff,IREGS(%a6)
4459
4460 mulu.l (ea_74_mem+0x10.w,%pc,%d4.l*4),%d2:%d3
4461
4462 mov.w %cc,SCCR(%a6)
4463 movm.l &0x7fff,SREGS(%a6)
4464 mov.l &0x00000004,IREGS+0xc(%a6)
4465
4466 bsr.l chkregs
4467 tst.b %d0
4468 bne.l error
4469
4470ea_75:
4471 addq.l &0x1,TESTCTR(%a6)
4472
4473 bra.b ea_75_next
4474ea_75_mem:
4475 long 0x00000002
4476ea_75_next:
4477 movm.l DEF_REGS(%pc),&0x3fff
4478
4479 clr.l %d2
4480 mov.l &0x00000002,%d3
4481 lea EAMEM(%a6),%a0
4482 mov.l &-0x2,%d4
4483
4484 mov.w &0x0000,ICCR(%a6)
4485 mov.w &0x0000,%cc
4486 movm.l &0x7fff,IREGS(%a6)
4487
4488 mulu.l (ea_75_mem+0x10.w,%pc,%d4.l*8),%d2:%d3
4489
4490 mov.w %cc,SCCR(%a6)
4491 movm.l &0x7fff,SREGS(%a6)
4492 mov.l &0x00000004,IREGS+0xc(%a6)
4493
4494 bsr.l chkregs
4495 tst.b %d0
4496 bne.l error
4497
4498ea_76:
4499 addq.l &0x1,TESTCTR(%a6)
4500
4501 bra.b ea_76_next
4502ea_76_mem:
4503 long 0x00000002
4504ea_76_next:
4505 movm.l DEF_REGS(%pc),&0x3fff
4506
4507 clr.l %d2
4508 mov.l &0x00000002,%d3
4509 lea EAMEM(%a6),%a3
4510 mov.l &-0x2,%a4
4511
4512 mov.w &0x0000,ICCR(%a6)
4513 mov.w &0x0000,%cc
4514 movm.l &0xffff,IREGS(%a6)
4515
4516 mulu.l (ea_76_mem+0x10.w,%pc,%a4.l*8),%d2:%d3
4517
4518 mov.w %cc,SCCR(%a6)
4519 movm.l &0xffff,SREGS(%a6)
4520 mov.l &0x00000004,IREGS+0xc(%a6)
4521
4522 bsr.l chkregs
4523 tst.b %d0
4524 bne.l error
4525
4526ea_77:
4527 addq.l &0x1,TESTCTR(%a6)
4528
4529 bra.b ea_77_next
4530ea_77_mem:
4531 long 0x00000002
4532ea_77_next:
4533 movm.l DEF_REGS(%pc),&0x3fff
4534
4535 clr.l %d2
4536 mov.l &0x00000002,%d3
4537 lea EAMEM(%a6),%a3
4538 mov.l &0x2,%a4
4539
4540 mov.w &0x0000,ICCR(%a6)
4541 mov.w &0x0000,%cc
4542 movm.l &0xffff,IREGS(%a6)
4543
4544 mulu.l (ea_77_mem+0x00.w,%pc,%za4.l*8),%d2:%d3
4545
4546 mov.w %cc,SCCR(%a6)
4547 movm.l &0xffff,SREGS(%a6)
4548 mov.l &0x00000004,IREGS+0xc(%a6)
4549
4550 bsr.l chkregs
4551 tst.b %d0
4552 bne.l error
4553
4554ea_78:
4555 addq.l &0x1,TESTCTR(%a6)
4556
4557# movm.l DEF_REGS(%pc),&0x3fff
4558
4559# clr.l %d2
4560# mov.l &0x00000002,%d3
4561# lea EAMEM,%a3
4562# mov.l %a3,%a4
4563# add.l &0x10,%a4
4564
4565# mov.w &0x0000,ICCR(%a6)
4566# mov.w &0x0000,%cc
4567# movm.l &0xffff,IREGS(%a6)
4568
4569# mulu.l (EAMEM-0x10.w,%zpc,%a4.l*1),%d2:%d3
4570
4571# mov.w %cc,SCCR(%a6)
4572# movm.l &0xffff,SREGS(%a6)
4573# mov.l &0x00000004,IREGS+0xc(%a6)
4574
4575# bsr.l chkregs
4576# tst.b %d0
4577# bne.l error
4578
4579ea_79:
4580 addq.l &0x1,TESTCTR(%a6)
4581
4582 movm.l DEF_REGS(%pc),&0x3fff
4583
4584 clr.l %d2
4585 mov.l &0x00000002,%d3
4586 lea EAMEM,%a3
4587 mov.l &0x2,%a4
4588
4589 mov.w &0x0000,ICCR(%a6)
4590 mov.w &0x0000,%cc
4591 movm.l &0xffff,IREGS(%a6)
4592
4593 mulu.l (ea_79_mem-0x10.l,%pc,%a4.l*8),%d2:%d3
4594
4595 mov.w %cc,SCCR(%a6)
4596 movm.l &0xffff,SREGS(%a6)
4597 mov.l &0x00000004,IREGS+0xc(%a6)
4598
4599 bra.b ea_79_next
4600ea_79_mem:
4601 long 0x00000002
4602ea_79_next:
4603
4604 bsr.l chkregs
4605 tst.b %d0
4606 bne.l error
4607
4608ea_80:
4609 addq.l &0x1,TESTCTR(%a6)
4610
4611 bra.b ea_80_next
4612ea_80_mem:
4613 long 0x00000002
4614ea_80_next:
4615 movm.l DEF_REGS(%pc),&0x3fff
4616
4617 clr.l %d2
4618 mov.l &0x00000002,%d3
4619 lea EAMEM(%a6),%a1
4620 mov.l &-0x10,%d4
4621
4622 mov.w &0x0000,ICCR(%a6)
4623 mov.w &0x0000,%cc
4624 movm.l &0xffff,IREGS(%a6)
4625
4626 mulu.l (ea_80_mem+0x10.b,%pc,%d4.w*1),%d2:%d3
4627
4628 mov.w %cc,SCCR(%a6)
4629 movm.l &0xffff,SREGS(%a6)
4630 mov.l &0x00000004,IREGS+0xc(%a6)
4631
4632 bsr.l chkregs
4633 tst.b %d0
4634 bne.l error
4635
4636ea_81:
4637 addq.l &0x1,TESTCTR(%a6)
4638
4639 bra.b ea_81_next
4640ea_81_mem:
4641 long 0x00000002
4642ea_81_next:
4643 movm.l DEF_REGS(%pc),&0x3fff
4644
4645 clr.l %d2
4646 mov.l &0x00000002,%d3
4647 lea EAMEM(%a6),%a0
4648 mov.l &-0x8,%d4
4649
4650 mov.w &0x0000,ICCR(%a6)
4651 mov.w &0x0000,%cc
4652 movm.l &0xffff,IREGS(%a6)
4653
4654 mulu.l (ea_81_mem+0x10.b,%pc,%d4.w*2),%d2:%d3
4655
4656 mov.w %cc,SCCR(%a6)
4657 movm.l &0xffff,SREGS(%a6)
4658 mov.l &0x00000004,IREGS+0xc(%a6)
4659
4660 bsr.l chkregs
4661 tst.b %d0
4662 bne.l error
4663
4664ea_82:
4665 addq.l &0x1,TESTCTR(%a6)
4666
4667 bra.b ea_82_next
4668ea_82_mem:
4669 long 0x00000002
4670ea_82_next:
4671 movm.l DEF_REGS(%pc),&0x3fff
4672
4673 clr.l %d2
4674 mov.l &0x00000002,%d3
4675 lea EAMEM(%a6),%a0
4676 mov.l &-0x4,%d4
4677
4678 mov.w &0x0000,ICCR(%a6)
4679 mov.w &0x0000,%cc
4680 movm.l &0xffff,IREGS(%a6)
4681
4682 mulu.l (ea_82_mem+0x10.b,%pc,%d4.w*4),%d2:%d3
4683
4684 mov.w %cc,SCCR(%a6)
4685 movm.l &0xffff,SREGS(%a6)
4686 mov.l &0x00000004,IREGS+0xc(%a6)
4687
4688 bsr.l chkregs
4689 tst.b %d0
4690 bne.l error
4691
4692ea_83:
4693 addq.l &0x1,TESTCTR(%a6)
4694
4695 bra.b ea_83_next
4696ea_83_mem:
4697 long 0x00000002
4698ea_83_next:
4699 movm.l DEF_REGS(%pc),&0x3fff
4700
4701 clr.l %d2
4702 mov.l &0x00000002,%d3
4703 lea EAMEM(%a6),%a0
4704 mov.l &-0x2,%d4
4705
4706 mov.w &0x0000,ICCR(%a6)
4707 mov.w &0x0000,%cc
4708 movm.l &0xffff,IREGS(%a6)
4709
4710 mulu.l (ea_83_mem+0x10.b,%pc,%d4.w*8),%d2:%d3
4711
4712 mov.w %cc,SCCR(%a6)
4713 movm.l &0xffff,SREGS(%a6)
4714 mov.l &0x00000004,IREGS+0xc(%a6)
4715
4716 bsr.l chkregs
4717 tst.b %d0
4718 bne.l error
4719
4720ea_84:
4721 addq.l &0x1,TESTCTR(%a6)
4722
4723 bra.b ea_84_next
4724ea_84_mem:
4725 long 0x00000002
4726ea_84_next:
4727 movm.l DEF_REGS(%pc),&0x3fff
4728
4729 clr.l %d2
4730 mov.l &0x00000002,%d3
4731 lea EAMEM(%a6),%a0
4732 mov.l &-0x10,%d4
4733
4734 mov.w &0x0000,ICCR(%a6)
4735 mov.w &0x0000,%cc
4736 movm.l &0xffff,IREGS(%a6)
4737
4738 mulu.l (ea_84_mem+0x10.b,%pc,%d4.l*1),%d2:%d3
4739
4740 mov.w %cc,SCCR(%a6)
4741 movm.l &0xffff,SREGS(%a6)
4742 mov.l &0x00000004,IREGS+0xc(%a6)
4743
4744 bsr.l chkregs
4745 tst.b %d0
4746 bne.l error
4747
4748ea_85:
4749 addq.l &0x1,TESTCTR(%a6)
4750
4751 bra.b ea_85_next
4752ea_85_mem:
4753 long 0x00000002
4754ea_85_next:
4755 movm.l DEF_REGS(%pc),&0x3fff
4756
4757 clr.l %d2
4758 mov.l &0x00000002,%d3
4759 lea EAMEM(%a6),%a0
4760 mov.l &-0x8,%d4
4761
4762 mov.w &0x0000,ICCR(%a6)
4763 mov.w &0x0000,%cc
4764 movm.l &0xffff,IREGS(%a6)
4765
4766 mulu.l (ea_85_mem+0x10.b,%pc,%d4.l*2),%d2:%d3
4767
4768 mov.w %cc,SCCR(%a6)
4769 movm.l &0xffff,SREGS(%a6)
4770 mov.l &0x00000004,IREGS+0xc(%a6)
4771
4772 bsr.l chkregs
4773 tst.b %d0
4774 bne.l error
4775
4776ea_86:
4777 addq.l &0x1,TESTCTR(%a6)
4778
4779 bra.b ea_86_next
4780ea_86_mem:
4781 long 0x00000002
4782ea_86_next:
4783 movm.l DEF_REGS(%pc),&0x3fff
4784
4785 clr.l %d2
4786 mov.l &0x00000002,%d3
4787 lea EAMEM(%a6),%a0
4788 mov.l &-0x4,%d4
4789
4790 mov.w &0x0000,ICCR(%a6)
4791 mov.w &0x0000,%cc
4792 movm.l &0xffff,IREGS(%a6)
4793
4794 mulu.l (ea_86_mem+0x10.b,%pc,%d4.l*4),%d2:%d3
4795
4796 mov.w %cc,SCCR(%a6)
4797 movm.l &0xffff,SREGS(%a6)
4798 mov.l &0x00000004,IREGS+0xc(%a6)
4799
4800 bsr.l chkregs
4801 tst.b %d0
4802 bne.l error
4803
4804ea_87:
4805 addq.l &0x1,TESTCTR(%a6)
4806
4807 bra.b ea_87_next
4808ea_87_mem:
4809 long 0x00000002
4810ea_87_next:
4811 movm.l DEF_REGS(%pc),&0x3fff
4812
4813 clr.l %d2
4814 mov.l &0x00000002,%d3
4815 lea EAMEM(%a6),%a0
4816 mov.l &-0x2,%d4
4817
4818 mov.w &0x0000,ICCR(%a6)
4819 mov.w &0x0000,%cc
4820 movm.l &0xffff,IREGS(%a6)
4821
4822 mulu.l (ea_87_mem+0x10.b,%pc,%d4.l*8),%d2:%d3
4823
4824 mov.w %cc,SCCR(%a6)
4825 movm.l &0xffff,SREGS(%a6)
4826 mov.l &0x00000004,IREGS+0xc(%a6)
4827
4828 bsr.l chkregs
4829 tst.b %d0
4830 bne.l error
4831
4832ea_88:
4833 addq.l &0x1,TESTCTR(%a6)
4834
4835 movm.l DEF_REGS(%pc),&0x3fff
4836
4837 clr.l %d2
4838 mov.l &0x00000002,%d3
4839 lea EAMEM(%a6),%a0
4840 mov.l &-0x2,%d4
4841
4842 mov.w &0x0000,ICCR(%a6)
4843 mov.w &0x0000,%cc
4844 movm.l &0xffff,IREGS(%a6)
4845
4846 mulu.l (ea_88_mem+0x10.b,%pc,%d4.l*8),%d2:%d3
4847
4848 mov.w %cc,SCCR(%a6)
4849 movm.l &0xffff,SREGS(%a6)
4850 mov.l &0x00000004,IREGS+0xc(%a6)
4851
4852 bra.b ea_88_next
4853ea_88_mem:
4854 long 0x00000002
4855ea_88_next:
4856
4857 bsr.l chkregs
4858 tst.b %d0
4859 bne.l error
4860
4861ea_89:
4862 addq.l &0x1,TESTCTR(%a6)
4863
4864 movm.l DEF_REGS(%pc),&0x3fff
4865
4866 clr.l %d2
4867 mov.l &0x00000002,%d3
4868 lea EAMEM-0x1000(%a6),%a3
4869 lea EASTORE(%a6),%a4
4870 mov.l %a3,(%a4)
4871 mov.l &-0x10,%d4
4872
4873 mov.w &0x0000,ICCR(%a6)
4874 mov.w &0x0000,%cc
4875 movm.l &0xffff,IREGS(%a6)
4876
4877 mulu.l ([0x10.w,%a4,%d4.w*1],0x1000.w),%d2:%d3
4878
4879 mov.w %cc,SCCR(%a6)
4880 movm.l &0xffff,SREGS(%a6)
4881 mov.l &0x00000004,IREGS+0xc(%a6)
4882
4883 bsr.l chkregs
4884 tst.b %d0
4885 bne.l error
4886
4887ea_90:
4888 addq.l &0x1,TESTCTR(%a6)
4889
4890 movm.l DEF_REGS(%pc),&0x3fff
4891
4892 clr.l %d2
4893 mov.l &0x00000002,%d3
4894 lea EAMEM-0x1000(%a6),%a3
4895 lea EASTORE(%a6),%a4
4896 mov.l %a3,(%a4)
4897 mov.l &-0x8,%d4
4898
4899 mov.w &0x0000,ICCR(%a6)
4900 mov.w &0x0000,%cc
4901 movm.l &0xffff,IREGS(%a6)
4902
4903 mulu.l ([0x10.w,%a4,%d4.w*2],0x1000.w),%d2:%d3
4904
4905 mov.w %cc,SCCR(%a6)
4906 movm.l &0xffff,SREGS(%a6)
4907 mov.l &0x00000004,IREGS+0xc(%a6)
4908
4909 bsr.l chkregs
4910 tst.b %d0
4911 bne.l error
4912
4913ea_91:
4914 addq.l &0x1,TESTCTR(%a6)
4915
4916 movm.l DEF_REGS(%pc),&0x3fff
4917
4918 clr.l %d2
4919 mov.l &0x00000002,%d3
4920 lea EAMEM-0x1000(%a6),%a3
4921 lea EASTORE(%a6),%a4
4922 mov.l %a3,(%a4)
4923 mov.l &-0x4,%d4
4924
4925 mov.w &0x0000,ICCR(%a6)
4926 mov.w &0x0000,%cc
4927 movm.l &0xffff,IREGS(%a6)
4928
4929 mulu.l ([0x10.w,%a4,%d4.w*4],0x1000.w),%d2:%d3
4930
4931 mov.w %cc,SCCR(%a6)
4932 movm.l &0xffff,SREGS(%a6)
4933 mov.l &0x00000004,IREGS+0xc(%a6)
4934
4935 bsr.l chkregs
4936 tst.b %d0
4937 bne.l error
4938
4939ea_92:
4940 addq.l &0x1,TESTCTR(%a6)
4941
4942 movm.l DEF_REGS(%pc),&0x3fff
4943
4944 clr.l %d2
4945 mov.l &0x00000002,%d3
4946 lea EAMEM-0x1000(%a6),%a3
4947 lea EASTORE(%a6),%a4
4948 mov.l %a3,(%a4)
4949 mov.l &-0x2,%d4
4950
4951 mov.w &0x0000,ICCR(%a6)
4952 mov.w &0x0000,%cc
4953 movm.l &0xffff,IREGS(%a6)
4954
4955 mulu.l ([0x10.w,%a4,%d4.w*8],0x1000.w),%d2:%d3
4956
4957 mov.w %cc,SCCR(%a6)
4958 movm.l &0xffff,SREGS(%a6)
4959 mov.l &0x00000004,IREGS+0xc(%a6)
4960
4961 bsr.l chkregs
4962 tst.b %d0
4963 bne.l error
4964
4965ea_93:
4966 addq.l &0x1,TESTCTR(%a6)
4967
4968 movm.l DEF_REGS(%pc),&0x3fff
4969
4970 clr.l %d2
4971 mov.l &0x00000002,%d3
4972 lea EAMEM-0x1000(%a6),%a3
4973 lea EASTORE(%a6),%a4
4974 mov.l %a3,(%a4)
4975 mov.l &-0x10,%d4
4976
4977 mov.w &0x0000,ICCR(%a6)
4978 mov.w &0x0000,%cc
4979 movm.l &0xffff,IREGS(%a6)
4980
4981 mulu.l ([0x10.w,%a4,%d4.l*1],0x1000.w),%d2:%d3
4982
4983 mov.w %cc,SCCR(%a6)
4984 movm.l &0xffff,SREGS(%a6)
4985 mov.l &0x00000004,IREGS+0xc(%a6)
4986
4987 bsr.l chkregs
4988 tst.b %d0
4989 bne.l error
4990
4991ea_94:
4992 addq.l &0x1,TESTCTR(%a6)
4993
4994 movm.l DEF_REGS(%pc),&0x3fff
4995
4996 clr.l %d2
4997 mov.l &0x00000002,%d3
4998 lea EAMEM-0x1000(%a6),%a3
4999 lea EASTORE(%a6),%a4
5000 mov.l %a3,(%a4)
5001 mov.l &-0x8,%d4
5002
5003 mov.w &0x0000,ICCR(%a6)
5004 mov.w &0x0000,%cc
5005 movm.l &0xffff,IREGS(%a6)
5006
5007 mulu.l ([0x10.w,%a4,%d4.l*2],0x1000.w),%d2:%d3
5008
5009 mov.w %cc,SCCR(%a6)
5010 movm.l &0xffff,SREGS(%a6)
5011 mov.l &0x00000004,IREGS+0xc(%a6)
5012
5013 bsr.l chkregs
5014 tst.b %d0
5015 bne.l error
5016
5017ea_95:
5018 addq.l &0x1,TESTCTR(%a6)
5019
5020 movm.l DEF_REGS(%pc),&0x3fff
5021
5022 clr.l %d2
5023 mov.l &0x00000002,%d3
5024 lea EAMEM-0x1000(%a6),%a3
5025 lea EASTORE(%a6),%a4
5026 mov.l %a3,(%a4)
5027 mov.l &-0x4,%d4
5028
5029 mov.w &0x0000,ICCR(%a6)
5030 mov.w &0x0000,%cc
5031 movm.l &0xffff,IREGS(%a6)
5032
5033 mulu.l ([0x10.w,%a4,%d4.l*4],0x1000.w),%d2:%d3
5034
5035 mov.w %cc,SCCR(%a6)
5036 movm.l &0xffff,SREGS(%a6)
5037 mov.l &0x00000004,IREGS+0xc(%a6)
5038
5039 bsr.l chkregs
5040 tst.b %d0
5041 bne.l error
5042
5043ea_96:
5044 addq.l &0x1,TESTCTR(%a6)
5045
5046 movm.l DEF_REGS(%pc),&0x3fff
5047
5048 clr.l %d2
5049 mov.l &0x00000002,%d3
5050 lea EAMEM-0x1000(%a6),%a3
5051 lea EASTORE(%a6),%a4
5052 mov.l %a3,(%a4)
5053 mov.l &-0x2,%d4
5054
5055 mov.w &0x0000,ICCR(%a6)
5056 mov.w &0x0000,%cc
5057 movm.l &0xffff,IREGS(%a6)
5058
5059 mulu.l ([0x10.w,%a4,%d4.l*8],0x1000.w),%d2:%d3
5060
5061 mov.w %cc,SCCR(%a6)
5062 movm.l &0xffff,SREGS(%a6)
5063 mov.l &0x00000004,IREGS+0xc(%a6)
5064
5065 bsr.l chkregs
5066 tst.b %d0
5067 bne.l error
5068
5069ea_97:
5070 addq.l &0x1,TESTCTR(%a6)
5071
5072 movm.l DEF_REGS(%pc),&0x3fff
5073
5074 clr.l %d2
5075 mov.l &0x00000002,%d3
5076 lea EAMEM-0x1000(%a6),%a3
5077 lea EASTORE(%a6),%a4
5078 mov.l %a3,(%a4)
5079 mov.l &-0x2,%d4
5080
5081 mov.w &0x0000,ICCR(%a6)
5082 mov.w &0x0000,%cc
5083 movm.l &0xffff,IREGS(%a6)
5084
5085 mulu.l ([0x10.l,%a4,%d4.l*8],0x1000.l),%d2:%d3
5086
5087 mov.w %cc,SCCR(%a6)
5088 movm.l &0xffff,SREGS(%a6)
5089 mov.l &0x00000004,IREGS+0xc(%a6)
5090
5091 bsr.l chkregs
5092 tst.b %d0
5093 bne.l error
5094
5095ea_98:
5096 addq.l &0x1,TESTCTR(%a6)
5097
5098 movm.l DEF_REGS(%pc),&0x3fff
5099
5100 clr.l %d2
5101 mov.l &0x00000002,%d3
5102 lea EAMEM-0x1000(%a6),%a3
5103 lea EASTORE(%a6),%a4
5104 mov.l %a3,(%a4)
5105 mov.l &-0x2,%d4
5106
5107 mov.w &0x0000,ICCR(%a6)
5108 mov.w &0x0000,%cc
5109 movm.l &0xffff,IREGS(%a6)
5110
5111 mulu.l ([0x00.l,%a4,%zd4.l*8],0x1000.l),%d2:%d3
5112
5113 mov.w %cc,SCCR(%a6)
5114 movm.l &0xffff,SREGS(%a6)
5115 mov.l &0x00000004,IREGS+0xc(%a6)
5116
5117 bsr.l chkregs
5118 tst.b %d0
5119 bne.l error
5120
5121ea_99:
5122 addq.l &0x1,TESTCTR(%a6)
5123
5124 movm.l DEF_REGS(%pc),&0x3fff
5125
5126 clr.l %d2
5127 mov.l &0x00000002,%d3
5128 lea EAMEM-0x1000(%a6),%a3
5129 lea EASTORE(%a6),%a4
5130 mov.l %a3,(%a4)
5131 mov.l &-0x2,%d4
5132
5133 mov.w &0x0000,ICCR(%a6)
5134 mov.w &0x0000,%cc
5135 movm.l &0xffff,IREGS(%a6)
5136
5137 mulu.l ([%a4,%zd4.l*8],0x1000.l),%d2:%d3
5138
5139 mov.w %cc,SCCR(%a6)
5140 movm.l &0xffff,SREGS(%a6)
5141 mov.l &0x00000004,IREGS+0xc(%a6)
5142
5143 bsr.l chkregs
5144 tst.b %d0
5145 bne.l error
5146
5147ea_100:
5148 addq.l &0x1,TESTCTR(%a6)
5149
5150 movm.l DEF_REGS(%pc),&0x3fff
5151
5152 clr.l %d2
5153 mov.l &0x00000002,%d3
5154 lea EAMEM-0x1000(%a6),%a3
5155 lea EASTORE(%a6),%a4
5156 mov.l %a3,(%a4)
5157 mov.l &-0x10,%d4
5158 add.l %a4,%d4
5159
5160 mov.w &0x0000,ICCR(%a6)
5161 mov.w &0x0000,%cc
5162 movm.l &0xffff,IREGS(%a6)
5163
5164 mulu.l ([0x10.l,%za4,%d4.l*1],0x1000.l),%d2:%d3
5165
5166 mov.w %cc,SCCR(%a6)
5167 movm.l &0xffff,SREGS(%a6)
5168 mov.l &0x00000004,IREGS+0xc(%a6)
5169
5170 bsr.l chkregs
5171 tst.b %d0
5172 bne.l error
5173
5174ea_101:
5175 addq.l &0x1,TESTCTR(%a6)
5176
5177# movm.l DEF_REGS(%pc),&0x3fff
5178
5179# clr.l %d2
5180# mov.l &0x00000002,%d3
5181# lea EAMEM(%a6),%a3
5182# lea EASTORE(%a6),%a4
5183# mov.l %a3,(%a4)
5184# mov.l &-0x10,%d4
5185
5186# mov.w &0x0000,ICCR(%a6)
5187# mov.w &0x0000,%cc
5188# movm.l &0xffff,IREGS(%a6)
5189
5190# mulu.l ([EASTORE.l,%za4,%zd4.l*1]),%d2:%d3
5191
5192# mov.w %cc,SCCR(%a6)
5193# movm.l &0xffff,SREGS(%a6)
5194# mov.l &0x00000004,IREGS+0xc(%a6)
5195
5196# bsr.l chkregs
5197# tst.b %d0
5198# bne.l error
5199
5200ea_102:
5201 addq.l &0x1,TESTCTR(%a6)
5202
5203 movm.l DEF_REGS(%pc),&0x3fff
5204
5205 mov.l %a6,%a1
5206
5207 clr.l %d2
5208 mov.l &0x00000002,%d3
5209 lea EAMEM+0x1000(%a1),%a3
5210 lea EASTORE(%a1),%a4
5211 mov.l %a3,(%a4)
5212 mov.l &-0x2,%a6
5213
5214 mov.w &0x0000,ICCR(%a1)
5215 mov.w &0x0000,%cc
5216 movm.l &0xffff,IREGS(%a1)
5217
5218 mulu.l ([0x10.w,%a4,%a6.l*8],-0x1000.w),%d2:%d3
5219
5220 mov.w %cc,SCCR(%a1)
5221 movm.l &0xffff,SREGS(%a1)
5222 mov.l &0x00000004,IREGS+0xc(%a1)
5223
5224 mov.l %a1,%a6
5225
5226 bsr.l chkregs
5227 tst.b %d0
5228 bne.l error
5229
5230ea_103:
5231 addq.l &0x1,TESTCTR(%a6)
5232
5233 movm.l DEF_REGS(%pc),&0x3fff
5234
5235 mov.l %a6,%a1
5236
5237 clr.l %d2
5238 mov.l &0x00000002,%d3
5239 lea EAMEM+0x1000(%a1),%a3
5240 lea EASTORE(%a1),%a4
5241 mov.l %a3,(%a4)
5242 mov.l &0x2,%a6
5243
5244 mov.w &0x0000,ICCR(%a1)
5245 mov.w &0x0000,%cc
5246 movm.l &0xffff,IREGS(%a1)
5247
5248 mulu.l ([-0x10.w,%a4,%a6.l*8],-0x1000.w),%d2:%d3
5249
5250 mov.w %cc,SCCR(%a1)
5251 movm.l &0xffff,SREGS(%a1)
5252 mov.l &0x00000004,IREGS+0xc(%a1)
5253
5254 mov.l %a1,%a6
5255
5256 bsr.l chkregs
5257 tst.b %d0
5258 bne.l error
5259
5260ea_104:
5261 addq.l &0x1,TESTCTR(%a6)
5262
5263 movm.l DEF_REGS(%pc),&0x3fff
5264
5265 clr.l %d2
5266 mov.l &0x00000002,%d3
5267 lea EAMEM-0x20(%a6),%a3
5268 lea EASTORE(%a6),%a4
5269 mov.l %a3,(%a4)
5270 sub.l &0x10,%a4
5271 mov.l &0x10,%d4
5272
5273 mov.w &0x0000,ICCR(%a6)
5274 mov.w &0x0000,%cc
5275 movm.l &0xffff,IREGS(%a6)
5276
5277 mulu.l ([0x10.w,%a4],%d4.w*1,0x10.w),%d2:%d3
5278
5279 mov.w %cc,SCCR(%a6)
5280 movm.l &0xffff,SREGS(%a6)
5281 mov.l &0x00000004,IREGS+0xc(%a6)
5282
5283 bsr.l chkregs
5284 tst.b %d0
5285 bne.l error
5286
5287ea_105:
5288 addq.l &0x1,TESTCTR(%a6)
5289
5290 movm.l DEF_REGS(%pc),&0x3fff
5291
5292 clr.l %d2
5293 mov.l &0x00000002,%d3
5294 lea EAMEM-0x20(%a6),%a3
5295 lea EASTORE(%a6),%a4
5296 mov.l %a3,(%a4)
5297 sub.l &0x10,%a4
5298 mov.l &0x8,%d4
5299
5300 mov.w &0x0000,ICCR(%a6)
5301 mov.w &0x0000,%cc
5302 movm.l &0xffff,IREGS(%a6)
5303
5304 mulu.l ([0x10.w,%a4],%d4.w*2,0x10.w),%d2:%d3
5305
5306 mov.w %cc,SCCR(%a6)
5307 movm.l &0xffff,SREGS(%a6)
5308 mov.l &0x00000004,IREGS+0xc(%a6)
5309
5310 bsr.l chkregs
5311 tst.b %d0
5312 bne.l error
5313
5314ea_106:
5315 addq.l &0x1,TESTCTR(%a6)
5316
5317 movm.l DEF_REGS(%pc),&0x3fff
5318
5319 clr.l %d2
5320 mov.l &0x00000002,%d3
5321 lea EAMEM-0x20(%a6),%a3
5322 lea EASTORE(%a6),%a4
5323 mov.l %a3,(%a4)
5324 sub.l &0x10,%a4
5325 mov.l &0x4,%d4
5326
5327 mov.w &0x0000,ICCR(%a6)
5328 mov.w &0x0000,%cc
5329 movm.l &0xffff,IREGS(%a6)
5330
5331 mulu.l ([0x10.w,%a4],%d4.w*4,0x10.w),%d2:%d3
5332
5333 mov.w %cc,SCCR(%a6)
5334 movm.l &0xffff,SREGS(%a6)
5335 mov.l &0x00000004,IREGS+0xc(%a6)
5336
5337 bsr.l chkregs
5338 tst.b %d0
5339 bne.l error
5340
5341ea_107:
5342 addq.l &0x1,TESTCTR(%a6)
5343
5344 movm.l DEF_REGS(%pc),&0x3fff
5345
5346 clr.l %d2
5347 mov.l &0x00000002,%d3
5348 lea EAMEM-0x20(%a6),%a3
5349 lea EASTORE(%a6),%a4
5350 mov.l %a3,(%a4)
5351 sub.l &0x10,%a4
5352 mov.l &0x2,%d4
5353
5354 mov.w &0x0000,ICCR(%a6)
5355 mov.w &0x0000,%cc
5356 movm.l &0xffff,IREGS(%a6)
5357
5358 mulu.l ([0x10.w,%a4],%d4.w*8,0x10.w),%d2:%d3
5359
5360 mov.w %cc,SCCR(%a6)
5361 movm.l &0xffff,SREGS(%a6)
5362 mov.l &0x00000004,IREGS+0xc(%a6)
5363
5364 bsr.l chkregs
5365 tst.b %d0
5366 bne.l error
5367
5368ea_108:
5369 addq.l &0x1,TESTCTR(%a6)
5370
5371 movm.l DEF_REGS(%pc),&0x3fff
5372
5373 clr.l %d2
5374 mov.l &0x00000002,%d3
5375 lea EAMEM-0x20(%a6),%a3
5376 lea EASTORE(%a6),%a4
5377 mov.l %a3,(%a4)
5378 sub.l &0x10,%a4
5379 mov.l &0x10,%d4
5380
5381 mov.w &0x0000,ICCR(%a6)
5382 mov.w &0x0000,%cc
5383 movm.l &0xffff,IREGS(%a6)
5384
5385 mulu.l ([0x10.w,%a4],%d4.l*1,0x10.w),%d2:%d3
5386
5387 mov.w %cc,SCCR(%a6)
5388 movm.l &0xffff,SREGS(%a6)
5389 mov.l &0x00000004,IREGS+0xc(%a6)
5390
5391 bsr.l chkregs
5392 tst.b %d0
5393 bne.l error
5394
5395ea_109:
5396 addq.l &0x1,TESTCTR(%a6)
5397
5398 movm.l DEF_REGS(%pc),&0x3fff
5399
5400 clr.l %d2
5401 mov.l &0x00000002,%d3
5402 lea EAMEM-0x20(%a6),%a3
5403 lea EASTORE(%a6),%a4
5404 mov.l %a3,(%a4)
5405 sub.l &0x10,%a4
5406 mov.l &0x8,%d4
5407
5408 mov.w &0x0000,ICCR(%a6)
5409 mov.w &0x0000,%cc
5410 movm.l &0xffff,IREGS(%a6)
5411
5412 mulu.l ([0x10.w,%a4],%d4.w*2,0x10.w),%d2:%d3
5413
5414 mov.w %cc,SCCR(%a6)
5415 movm.l &0xffff,SREGS(%a6)
5416 mov.l &0x00000004,IREGS+0xc(%a6)
5417
5418 bsr.l chkregs
5419 tst.b %d0
5420 bne.l error
5421
5422ea_110:
5423 addq.l &0x1,TESTCTR(%a6)
5424
5425 movm.l DEF_REGS(%pc),&0x3fff
5426
5427 clr.l %d2
5428 mov.l &0x00000002,%d3
5429 lea EAMEM-0x20(%a6),%a3
5430 lea EASTORE(%a6),%a4
5431 mov.l %a3,(%a4)
5432 sub.l &0x10,%a4
5433 mov.l &0x4,%d4
5434
5435 mov.w &0x0000,ICCR(%a6)
5436 mov.w &0x0000,%cc
5437 movm.l &0xffff,IREGS(%a6)
5438
5439 mulu.l ([0x10.w,%a4],%d4.l*4,0x10.w),%d2:%d3
5440
5441 mov.w %cc,SCCR(%a6)
5442 movm.l &0xffff,SREGS(%a6)
5443 mov.l &0x00000004,IREGS+0xc(%a6)
5444
5445 bsr.l chkregs
5446 tst.b %d0
5447 bne.l error
5448
5449ea_111:
5450 addq.l &0x1,TESTCTR(%a6)
5451
5452 movm.l DEF_REGS(%pc),&0x3fff
5453
5454 clr.l %d2
5455 mov.l &0x00000002,%d3
5456 lea EAMEM-0x20(%a6),%a3
5457 lea EASTORE(%a6),%a4
5458 mov.l %a3,(%a4)
5459 sub.l &0x10,%a4
5460 mov.l &0x2,%d4
5461
5462 mov.w &0x0000,ICCR(%a6)
5463 mov.w &0x0000,%cc
5464 movm.l &0xffff,IREGS(%a6)
5465
5466 mulu.l ([0x10.w,%a4],%d4.l*8,0x10.w),%d2:%d3
5467
5468 mov.w %cc,SCCR(%a6)
5469 movm.l &0xffff,SREGS(%a6)
5470 mov.l &0x00000004,IREGS+0xc(%a6)
5471
5472 bsr.l chkregs
5473 tst.b %d0
5474 bne.l error
5475
5476ea_112:
5477 addq.l &0x1,TESTCTR(%a6)
5478
5479 movm.l DEF_REGS(%pc),&0x3fff
5480
5481 clr.l %d2
5482 mov.l &0x00000002,%d3
5483 lea EAMEM-0x20(%a6),%a3
5484 lea EASTORE(%a6),%a4
5485 mov.l %a3,(%a4)
5486 sub.l &0x10,%a4
5487 mov.l &0x2,%d4
5488
5489 mov.w &0x0000,ICCR(%a6)
5490 mov.w &0x0000,%cc
5491 movm.l &0xffff,IREGS(%a6)
5492
5493 mulu.l ([0x10.l,%a4],%d4.l*8,0x10.l),%d2:%d3
5494
5495 mov.w %cc,SCCR(%a6)
5496 movm.l &0xffff,SREGS(%a6)
5497 mov.l &0x00000004,IREGS+0xc(%a6)
5498
5499 bsr.l chkregs
5500 tst.b %d0
5501 bne.l error
5502
5503ea_113:
5504 addq.l &0x1,TESTCTR(%a6)
5505
5506 movm.l DEF_REGS(%pc),&0x3fff
5507
5508 clr.l %d2
5509 mov.l &0x00000002,%d3
5510 lea EAMEM-0x20(%a6),%a3
5511 lea EASTORE(%a6),%a4
5512 mov.l %a3,(%a4)
5513 mov.l &0x2,%d4
5514
5515 mov.w &0x0000,ICCR(%a6)
5516 mov.w &0x0000,%cc
5517 movm.l &0xffff,IREGS(%a6)
5518
5519 mulu.l ([0x00.l,%a4],%zd4.l*8,0x20.l),%d2:%d3
5520
5521 mov.w %cc,SCCR(%a6)
5522 movm.l &0xffff,SREGS(%a6)
5523 mov.l &0x00000004,IREGS+0xc(%a6)
5524
5525 bsr.l chkregs
5526 tst.b %d0
5527 bne.l error
5528
5529ea_114:
5530 addq.l &0x1,TESTCTR(%a6)
5531
5532 movm.l DEF_REGS(%pc),&0x3fff
5533
5534 mov.l %a7,%a0
5535 clr.l %d2
5536 mov.l &0x00000002,%d3
5537 lea EAMEM-0x20(%a6),%a3
5538 lea EASTORE(%a6),%a7
5539 mov.l %a3,(%a7)
5540 mov.l &0x20,%d4
5541
5542 mov.w &0x0000,ICCR(%a6)
5543 mov.w &0x0000,%cc
5544 movm.l &0xffff,IREGS(%a6)
5545
5546 mulu.l ([%a7],%d4.l*1),%d2:%d3
5547
5548 mov.w %cc,SCCR(%a6)
5549 movm.l &0xffff,SREGS(%a6)
5550 mov.l &0x00000004,IREGS+0xc(%a6)
5551
5552 mov.l %a0,%a7
5553 bsr.l chkregs
5554 tst.b %d0
5555 bne.l error
5556
5557ea_115:
5558 addq.l &0x1,TESTCTR(%a6)
5559
5560# movm.l DEF_REGS(%pc),&0x3fff
5561
5562# clr.l %d2
5563# mov.l &0x00000002,%d3
5564# lea EAMEM-0x20(%pc),%a3
5565# lea EASTORE(%pc),%a4
5566# mov.l %a3,(%a4)
5567# mov.l &0x2,%d4
5568
5569# mov.w &0x0000,ICCR(%a6)
5570# mov.w &0x0000,%cc
5571# movm.l &0xffff,IREGS(%a6)
5572
5573# mulu.l ([EASTORE.l,%za4],%zd4.l*8,0x20.l),%d2:%d3
5574
5575# mov.w %cc,SCCR(%a6)
5576# movm.l &0xffff,SREGS(%a6)
5577# mov.l &0x00000004,IREGS+0xc(%a6)
5578
5579# bsr.l chkregs
5580# tst.b %d0
5581# bne.l error
5582
5583ea_116:
5584 addq.l &0x1,TESTCTR(%a6)
5585
5586 movm.l DEF_REGS(%pc),&0x3fff
5587
5588 mov.l %a6,%a1
5589
5590 clr.l %d2
5591 mov.l &0x00000002,%d3
5592 lea EAMEM(%a1),%a3
5593 lea EASTORE(%a1),%a6
5594 mov.l %a3,(%a6)
5595 add.l &0x10,%a6
5596 mov.l &-0x2,%a5
5597
5598 mov.w &0x0000,ICCR(%a1)
5599 mov.w &0x0000,%cc
5600 movm.l &0xffff,IREGS(%a1)
5601
5602 mulu.l ([-0x10.w,%a6],%a5.l*8,0x10.l),%d2:%d3
5603
5604 mov.w %cc,SCCR(%a1)
5605 movm.l &0xffff,SREGS(%a1)
5606 mov.l &0x00000004,IREGS+0xc(%a1)
5607
5608 mov.l %a1,%a6
5609
5610 bsr.l chkregs
5611 tst.b %d0
5612 bne.l error
5613
5614 mov.l TESTCTR(%a6),%d1
5615 clr.l %d0
5616 rts
5617
5618ea_117:
5619 addq.l &0x1,TESTCTR(%a6)
5620
5621 movm.l DEF_REGS(%pc),&0x3fff
5622
5623 clr.l %d2
5624 mov.l &0x00000002,%d3
5625 lea EAMEM-0x1000(%pc),%a3
5626 lea EASTORE(%pc),%a4
5627 mov.l %a3,(%a4)
5628 mov.l &-0x10,%d4
5629
5630 mov.w &0x0000,ICCR(%a6)
5631 mov.w &0x0000,%cc
5632 movm.l &0xffff,IREGS(%a6)
5633
5634 mulu.l ([EASTORE+0x10.w,%pc,%d4.w*1],0x1000.w),%d2:%d3
5635
5636 mov.w %cc,SCCR(%a6)
5637 movm.l &0xffff,SREGS(%a6)
5638 mov.l &0x00000004,IREGS+0xc(%a6)
5639
5640 bsr.l chkregs
5641 tst.b %d0
5642 bne.l error
5643
5644ea_118:
5645 addq.l &0x1,TESTCTR(%a6)
5646
5647 movm.l DEF_REGS(%pc),&0x3fff
5648
5649 clr.l %d2
5650 mov.l &0x00000002,%d3
5651 lea EAMEM-0x1000(%pc),%a3
5652 lea EASTORE(%pc),%a4
5653 mov.l %a3,(%a4)
5654 mov.l &-0x8,%d4
5655
5656 mov.w &0x0000,ICCR(%a6)
5657 mov.w &0x0000,%cc
5658 movm.l &0xffff,IREGS(%a6)
5659
5660 mulu.l ([EASTORE+0x10.w,%pc,%d4.w*2],0x1000.w),%d2:%d3
5661
5662 mov.w %cc,SCCR(%a6)
5663 movm.l &0xffff,SREGS(%a6)
5664 mov.l &0x00000004,IREGS+0xc(%a6)
5665
5666 bsr.l chkregs
5667 tst.b %d0
5668 bne.l error
5669
5670ea_119:
5671 addq.l &0x1,TESTCTR(%a6)
5672
5673 movm.l DEF_REGS(%pc),&0x3fff
5674
5675 clr.l %d2
5676 mov.l &0x00000002,%d3
5677 lea EAMEM-0x1000(%pc),%a3
5678 lea EASTORE(%pc),%a4
5679 mov.l %a3,(%a4)
5680 mov.l &-0x4,%d4
5681
5682 mov.w &0x0000,ICCR(%a6)
5683 mov.w &0x0000,%cc
5684 movm.l &0xffff,IREGS(%a6)
5685
5686 mulu.l ([EASTORE+0x10.w,%pc,%d4.w*4],0x1000.w),%d2:%d3
5687
5688 mov.w %cc,SCCR(%a6)
5689 movm.l &0xffff,SREGS(%a6)
5690 mov.l &0x00000004,IREGS+0xc(%a6)
5691
5692 bsr.l chkregs
5693 tst.b %d0
5694 bne.l error
5695
5696ea_120:
5697 addq.l &0x1,TESTCTR(%a6)
5698
5699 movm.l DEF_REGS(%pc),&0x3fff
5700
5701 clr.l %d2
5702 mov.l &0x00000002,%d3
5703 lea EAMEM-0x1000(%pc),%a3
5704 lea EASTORE(%pc),%a4
5705 mov.l %a3,(%a4)
5706 mov.l &-0x2,%d4
5707
5708 mov.w &0x0000,ICCR(%a6)
5709 mov.w &0x0000,%cc
5710 movm.l &0xffff,IREGS(%a6)
5711
5712 mulu.l ([EASTORE+0x10.w,%pc,%d4.w*8],0x1000.w),%d2:%d3
5713
5714 mov.w %cc,SCCR(%a6)
5715 movm.l &0xffff,SREGS(%a6)
5716 mov.l &0x00000004,IREGS+0xc(%a6)
5717
5718 bsr.l chkregs
5719 tst.b %d0
5720 bne.l error
5721
5722ea_121:
5723 addq.l &0x1,TESTCTR(%a6)
5724
5725 movm.l DEF_REGS(%pc),&0x3fff
5726
5727 clr.l %d2
5728 mov.l &0x00000002,%d3
5729 lea EAMEM-0x1000(%pc),%a3
5730 lea EASTORE(%pc),%a4
5731 mov.l %a3,(%a4)
5732 mov.l &-0x10,%d4
5733
5734 mov.w &0x0000,ICCR(%a6)
5735 mov.w &0x0000,%cc
5736 movm.l &0xffff,IREGS(%a6)
5737
5738 mulu.l ([EASTORE+0x10.w,%pc,%d4.l*1],0x1000.w),%d2:%d3
5739
5740 mov.w %cc,SCCR(%a6)
5741 movm.l &0xffff,SREGS(%a6)
5742 mov.l &0x00000004,IREGS+0xc(%a6)
5743
5744 bsr.l chkregs
5745 tst.b %d0
5746 bne.l error
5747
5748ea_122:
5749 addq.l &0x1,TESTCTR(%a6)
5750
5751 movm.l DEF_REGS(%pc),&0x3fff
5752
5753 clr.l %d2
5754 mov.l &0x00000002,%d3
5755 lea EAMEM-0x1000(%pc),%a3
5756 lea EASTORE(%pc),%a4
5757 mov.l %a3,(%a4)
5758 mov.l &-0x8,%d4
5759
5760 mov.w &0x0000,ICCR(%a6)
5761 mov.w &0x0000,%cc
5762 movm.l &0xffff,IREGS(%a6)
5763
5764 mulu.l ([EASTORE+0x10.w,%pc,%d4.l*2],0x1000.w),%d2:%d3
5765
5766 mov.w %cc,SCCR(%a6)
5767 movm.l &0xffff,SREGS(%a6)
5768 mov.l &0x00000004,IREGS+0xc(%a6)
5769
5770 bsr.l chkregs
5771 tst.b %d0
5772 bne.l error
5773
5774ea_123:
5775 addq.l &0x1,TESTCTR(%a6)
5776
5777 movm.l DEF_REGS(%pc),&0x3fff
5778
5779 clr.l %d2
5780 mov.l &0x00000002,%d3
5781 lea EAMEM-0x1000(%pc),%a3
5782 lea EASTORE(%pc),%a4
5783 mov.l %a3,(%a4)
5784 mov.l &-0x4,%d4
5785
5786 mov.w &0x0000,ICCR(%a6)
5787 mov.w &0x0000,%cc
5788 movm.l &0xffff,IREGS(%a6)
5789
5790 mulu.l ([EASTORE+0x10.w,%pc,%d4.l*4],0x1000.w),%d2:%d3
5791
5792 mov.w %cc,SCCR(%a6)
5793 movm.l &0xffff,SREGS(%a6)
5794 mov.l &0x00000004,IREGS+0xc(%a6)
5795
5796 bsr.l chkregs
5797 tst.b %d0
5798 bne.l error
5799
5800ea_124:
5801 addq.l &0x1,TESTCTR(%a6)
5802
5803 movm.l DEF_REGS(%pc),&0x3fff
5804
5805 clr.l %d2
5806 mov.l &0x00000002,%d3
5807 lea EAMEM-0x1000(%pc),%a3
5808 lea EASTORE(%pc),%a4
5809 mov.l %a3,(%a4)
5810 mov.l &-0x2,%d4
5811
5812 mov.w &0x0000,ICCR(%a6)
5813 mov.w &0x0000,%cc
5814 movm.l &0xffff,IREGS(%a6)
5815
5816 mulu.l ([EASTORE+0x10.w,%pc,%d4.l*8],0x1000.w),%d2:%d3
5817
5818 mov.w %cc,SCCR(%a6)
5819 movm.l &0xffff,SREGS(%a6)
5820 mov.l &0x00000004,IREGS+0xc(%a6)
5821
5822 bsr.l chkregs
5823 tst.b %d0
5824 bne.l error
5825
5826ea_125:
5827 addq.l &0x1,TESTCTR(%a6)
5828
5829 movm.l DEF_REGS(%pc),&0x3fff
5830
5831 clr.l %d2
5832 mov.l &0x00000002,%d3
5833 lea EAMEM-0x1000(%pc),%a3
5834 lea EASTORE(%pc),%a4
5835 mov.l %a3,(%a4)
5836 mov.l &-0x2,%d4
5837
5838 mov.w &0x0000,ICCR(%a6)
5839 mov.w &0x0000,%cc
5840 movm.l &0xffff,IREGS(%a6)
5841 mulu.l ([EASTORE+0x10.l,%pc,%d4.l*8],0x1000.l),%d2:%d3
5842
5843 mov.w %cc,SCCR(%a6)
5844 movm.l &0xffff,SREGS(%a6)
5845 mov.l &0x00000004,IREGS+0xc(%a6)
5846
5847 bsr.l chkregs
5848 tst.b %d0
5849 bne.l error
5850
5851ea_126:
5852 addq.l &0x1,TESTCTR(%a6)
5853
5854 movm.l DEF_REGS(%pc),&0x3fff
5855
5856 clr.l %d2
5857 mov.l &0x00000002,%d3
5858 lea EAMEM-0x1000(%pc),%a3
5859 lea EASTORE(%pc),%a4
5860 mov.l %a3,(%a4)
5861 mov.l &-0x2,%d4
5862
5863 mov.w &0x0000,ICCR(%a6)
5864 mov.w &0x0000,%cc
5865 movm.l &0xffff,IREGS(%a6)
5866
5867 mulu.l ([EASTORE+0x00.l,%pc,%zd4.l*8],0x1000.l),%d2:%d3
5868
5869 mov.w %cc,SCCR(%a6)
5870 movm.l &0xffff,SREGS(%a6)
5871 mov.l &0x00000004,IREGS+0xc(%a6)
5872
5873 bsr.l chkregs
5874 tst.b %d0
5875 bne.l error
5876
5877ea_127:
5878 addq.l &0x1,TESTCTR(%a6)
5879
5880 movm.l DEF_REGS(%pc),&0x3fff
5881
5882 clr.l %d2
5883 mov.l &0x00000002,%d3
5884 lea EAMEM-0x1000(%pc),%a3
5885 lea EASTORE(%pc),%a4
5886 mov.l %a3,(%a4)
5887 mov.l %a4,%d4
5888
5889 mov.w &0x0000,ICCR(%a6)
5890 mov.w &0x0000,%cc
5891 movm.l &0xffff,IREGS(%a6)
5892
5893 mulu.l ([%zpc,%d4.l*1],0x1000.l),%d2:%d3
5894
5895 mov.w %cc,SCCR(%a6)
5896 movm.l &0xffff,SREGS(%a6)
5897 mov.l &0x00000004,IREGS+0xc(%a6)
5898
5899 bsr.l chkregs
5900 tst.b %d0
5901 bne.l error
5902
5903ea_128:
5904 addq.l &0x1,TESTCTR(%a6)
5905
5906 movm.l DEF_REGS(%pc),&0x3fff
5907
5908 clr.l %d2
5909 mov.l &0x00000002,%d3
5910 lea EAMEM-0x1000(%pc),%a3
5911 lea EASTORE(%pc),%a4
5912 mov.l %a3,(%a4)
5913 mov.l &-0x10,%d4
5914 add.l %a4,%d4
5915
5916 mov.w &0x0000,ICCR(%a6)
5917 mov.w &0x0000,%cc
5918 movm.l &0xffff,IREGS(%a6)
5919
5920 mulu.l ([0x10.l,%zpc,%d4.l*1],0x1000.l),%d2:%d3
5921
5922 mov.w %cc,SCCR(%a6)
5923 movm.l &0xffff,SREGS(%a6)
5924 mov.l &0x00000004,IREGS+0xc(%a6)
5925
5926 bsr.l chkregs
5927 tst.b %d0
5928 bne.l error
5929
5930ea_129:
5931 addq.l &0x1,TESTCTR(%a6)
5932
5933 clr.l %d2
5934 mov.l &0x00000002,%d3
5935 lea EAMEM(%pc),%a3
5936 lea EASTORE(%pc),%a4
5937 mov.l %a3,(%a4)
5938 mov.l &-0x10,%d4
5939
5940 mov.w &0x0000,ICCR(%a6)
5941 mov.w &0x0000,%cc
5942 movm.l &0xffff,IREGS(%a6)
5943
5944 mulu.l ([EASTORE.l,%zpc,%zd4.l*1]),%d2:%d3
5945
5946 mov.w %cc,SCCR(%a6)
5947 movm.l &0xffff,SREGS(%a6)
5948 mov.l &0x00000004,IREGS+0xc(%a6)
5949
5950 bsr.l chkregs
5951 tst.b %d0
5952 bne.l error
5953
5954ea_130:
5955 addq.l &0x1,TESTCTR(%a6)
5956
5957 movm.l DEF_REGS(%pc),&0x3fff
5958
5959 clr.l %d2
5960 mov.l &0x00000002,%d3
5961 lea EAMEM+0x1000(%pc),%a3
5962 lea EASTORE(%pc),%a4
5963 mov.l %a3,(%a4)
5964 mov.l &0x2,%a6
5965
5966 mov.w &0x0000,ICCR(%a6)
5967 mov.w &0x0000,%cc
5968 movm.l &0xffff,IREGS(%a6)
5969
5970 mulu.l ([EASTORE-0x10.w,%pc,%a6.l*8],-0x1000.w),%d2:%d3
5971
5972 mov.w %cc,SCCR(%a6)
5973 movm.l &0xffff,SREGS(%a6)
5974 mov.l &0x00000004,IREGS+0xc(%a6)
5975
5976 bsr.l chkregs
5977 tst.b %d0
5978 bne.l error
5979
5980ea_131:
5981 addq.l &0x1,TESTCTR(%a6)
5982
5983 movm.l DEF_REGS(%pc),&0x3fff
5984
5985 mov.l %a7,%a0
5986 clr.l %d2
5987 mov.l &0x00000002,%d3
5988 lea EAMEM+0x1000(%pc),%a3
5989 lea EASTORE(%pc),%a4
5990 mov.l %a3,(%a4)
5991 mov.l &0x2,%a7
5992
5993 mov.w &0x0000,ICCR(%a6)
5994 mov.w &0x0000,%cc
5995 movm.l &0xffff,IREGS(%a6)
5996
5997 mulu.l ([EASTORE-0x10.w,%pc,%a7.l*8],-0x1000.w),%d2:%d3
5998
5999 mov.w %cc,SCCR(%a6)
6000 movm.l &0xffff,SREGS(%a6)
6001 mov.l &0x00000004,IREGS+0xc(%a6)
6002
6003 mov.l %a0,%a7
6004 bsr.l chkregs
6005 tst.b %d0
6006 bne.l error
6007
6008ea_132:
6009 addq.l &0x1,TESTCTR(%a6)
6010
6011 movm.l DEF_REGS(%pc),&0x3fff
6012
6013 clr.l %d2
6014 mov.l &0x00000002,%d3
6015 lea EAMEM-0x20(%pc),%a3
6016 lea EASTORE(%pc),%a4
6017 mov.l %a3,(%a4)
6018 sub.l &0x10,%a4
6019 mov.l &0x10,%d4
6020
6021 mov.w &0x0000,ICCR(%a6)
6022 mov.w &0x0000,%cc
6023 movm.l &0xffff,IREGS(%a6)
6024
6025 mulu.l ([EASTORE.w,%pc],%d4.w*1,0x10.w),%d2:%d3
6026
6027 mov.w %cc,SCCR(%a6)
6028 movm.l &0xffff,SREGS(%a6)
6029 mov.l &0x00000004,IREGS+0xc(%a6)
6030
6031 bsr.l chkregs
6032 tst.b %d0
6033 bne.l error
6034
6035ea_133:
6036 addq.l &0x1,TESTCTR(%a6)
6037
6038 movm.l DEF_REGS(%pc),&0x3fff
6039
6040 clr.l %d2
6041 mov.l &0x00000002,%d3
6042 lea EAMEM-0x20(%pc),%a3
6043 lea EASTORE(%pc),%a4
6044 mov.l %a3,(%a4)
6045 sub.l &0x10,%a4
6046 mov.l &0x8,%d4
6047
6048 mov.w &0x0000,ICCR(%a6)
6049 mov.w &0x0000,%cc
6050 movm.l &0xffff,IREGS(%a6)
6051
6052 mulu.l ([EASTORE.w,%pc],%d4.w*2,0x10.w),%d2:%d3
6053
6054 mov.w %cc,SCCR(%a6)
6055 movm.l &0xffff,SREGS(%a6)
6056 mov.l &0x00000004,IREGS+0xc(%a6)
6057
6058 bsr.l chkregs
6059 tst.b %d0
6060 bne.l error
6061
6062ea_134:
6063 addq.l &0x1,TESTCTR(%a6)
6064
6065 movm.l DEF_REGS(%pc),&0x3fff
6066
6067 clr.l %d2
6068 mov.l &0x00000002,%d3
6069 lea EAMEM-0x20(%pc),%a3
6070 lea EASTORE(%pc),%a4
6071 mov.l %a3,(%a4)
6072 sub.l &0x10,%a4
6073 mov.l &0x4,%d4
6074
6075 mov.w &0x0000,ICCR(%a6)
6076 mov.w &0x0000,%cc
6077 movm.l &0xffff,IREGS(%a6)
6078
6079 mulu.l ([EASTORE.w,%pc],%d4.w*4,0x10.w),%d2:%d3
6080
6081 mov.w %cc,SCCR(%a6)
6082 movm.l &0xffff,SREGS(%a6)
6083 mov.l &0x00000004,IREGS+0xc(%a6)
6084
6085 bsr.l chkregs
6086 tst.b %d0
6087 bne.l error
6088
6089ea_135:
6090 addq.l &0x1,TESTCTR(%a6)
6091
6092 movm.l DEF_REGS(%pc),&0x3fff
6093
6094 clr.l %d2
6095 mov.l &0x00000002,%d3
6096 lea EAMEM-0x20(%pc),%a3
6097 lea EASTORE(%pc),%a4
6098 mov.l %a3,(%a4)
6099 sub.l &0x10,%a4
6100 mov.l &0x2,%d4
6101
6102 mov.w &0x0000,ICCR(%a6)
6103 mov.w &0x0000,%cc
6104 movm.l &0xffff,IREGS(%a6)
6105
6106 mulu.l ([EASTORE.w,%pc],%d4.w*8,0x10.w),%d2:%d3
6107
6108 mov.w %cc,SCCR(%a6)
6109 movm.l &0xffff,SREGS(%a6)
6110 mov.l &0x00000004,IREGS+0xc(%a6)
6111
6112 bsr.l chkregs
6113 tst.b %d0
6114 bne.l error
6115
6116ea_136:
6117 addq.l &0x1,TESTCTR(%a6)
6118
6119 movm.l DEF_REGS(%pc),&0x3fff
6120
6121 clr.l %d2
6122 mov.l &0x00000002,%d3
6123 lea EAMEM-0x20(%pc),%a3
6124 lea EASTORE(%pc),%a4
6125 mov.l %a3,(%a4)
6126 sub.l &0x10,%a4
6127 mov.l &0x10,%d4
6128
6129 mov.w &0x0000,ICCR(%a6)
6130 mov.w &0x0000,%cc
6131 movm.l &0xffff,IREGS(%a6)
6132
6133 mulu.l ([EASTORE.w,%pc],%d4.l*1,0x10.w),%d2:%d3
6134
6135 mov.w %cc,SCCR(%a6)
6136 movm.l &0xffff,SREGS(%a6)
6137 mov.l &0x00000004,IREGS+0xc(%a6)
6138
6139 bsr.l chkregs
6140 tst.b %d0
6141 bne.l error
6142
6143ea_137:
6144 addq.l &0x1,TESTCTR(%a6)
6145
6146 movm.l DEF_REGS(%pc),&0x3fff
6147
6148 clr.l %d2
6149 mov.l &0x00000002,%d3
6150 lea EAMEM-0x20(%pc),%a3
6151 lea EASTORE(%pc),%a4
6152 mov.l %a3,(%a4)
6153 sub.l &0x10,%a4
6154 mov.l &0x8,%d4
6155
6156 mov.w &0x0000,ICCR(%a6)
6157 mov.w &0x0000,%cc
6158 movm.l &0xffff,IREGS(%a6)
6159
6160 mulu.l ([EASTORE.w,%pc],%d4.w*2,0x10.w),%d2:%d3
6161
6162 mov.w %cc,SCCR(%a6)
6163 movm.l &0xffff,SREGS(%a6)
6164 mov.l &0x00000004,IREGS+0xc(%a6)
6165
6166 bsr.l chkregs
6167 tst.b %d0
6168 bne.l error
6169
6170ea_138:
6171 addq.l &0x1,TESTCTR(%a6)
6172
6173 movm.l DEF_REGS(%pc),&0x3fff
6174
6175 clr.l %d2
6176 mov.l &0x00000002,%d3
6177 lea EAMEM-0x20(%pc),%a3
6178 lea EASTORE(%pc),%a4
6179 mov.l %a3,(%a4)
6180 sub.l &0x10,%a4
6181 mov.l &0x4,%d4
6182
6183 mov.w &0x0000,ICCR(%a6)
6184 mov.w &0x0000,%cc
6185 movm.l &0xffff,IREGS(%a6)
6186
6187 mulu.l ([EASTORE.w,%pc],%d4.l*4,0x10.w),%d2:%d3
6188
6189 mov.w %cc,SCCR(%a6)
6190 movm.l &0xffff,SREGS(%a6)
6191 mov.l &0x00000004,IREGS+0xc(%a6)
6192
6193 bsr.l chkregs
6194 tst.b %d0
6195 bne.l error
6196
6197ea_139:
6198 addq.l &0x1,TESTCTR(%a6)
6199
6200 movm.l DEF_REGS(%pc),&0x3fff
6201
6202 clr.l %d2
6203 mov.l &0x00000002,%d3
6204 lea EAMEM-0x20(%pc),%a3
6205 lea EASTORE(%pc),%a4
6206 mov.l %a3,(%a4)
6207 sub.l &0x10,%a4
6208 mov.l &0x2,%d4
6209
6210 mov.w &0x0000,ICCR(%a6)
6211 mov.w &0x0000,%cc
6212 movm.l &0xffff,IREGS(%a6)
6213
6214 mulu.l ([EASTORE.w,%pc],%d4.l*8,0x10.w),%d2:%d3
6215
6216 mov.w %cc,SCCR(%a6)
6217 movm.l &0xffff,SREGS(%a6)
6218 mov.l &0x00000004,IREGS+0xc(%a6)
6219
6220 bsr.l chkregs
6221 tst.b %d0
6222 bne.l error
6223
6224ea_140:
6225 addq.l &0x1,TESTCTR(%a6)
6226
6227 movm.l DEF_REGS(%pc),&0x3fff
6228
6229 clr.l %d2
6230 mov.l &0x00000002,%d3
6231 lea EAMEM-0x20(%pc),%a3
6232 lea EASTORE(%pc),%a4
6233 mov.l %a3,(%a4)
6234 sub.l &0x10,%a4
6235 mov.l &0x2,%d4
6236
6237 mov.w &0x0000,ICCR(%a6)
6238 mov.w &0x0000,%cc
6239 movm.l &0xffff,IREGS(%a6)
6240
6241 mulu.l ([EASTORE.l,%pc],%d4.l*8,0x10.l),%d2:%d3
6242
6243 mov.w %cc,SCCR(%a6)
6244 movm.l &0xffff,SREGS(%a6)
6245 mov.l &0x00000004,IREGS+0xc(%a6)
6246
6247 bsr.l chkregs
6248 tst.b %d0
6249 bne.l error
6250
6251ea_141:
6252 addq.l &0x1,TESTCTR(%a6)
6253
6254 movm.l DEF_REGS(%pc),&0x3fff
6255
6256 clr.l %d2
6257 mov.l &0x00000002,%d3
6258 lea EAMEM-0x20(%pc),%a3
6259 lea EASTORE(%pc),%a4
6260 mov.l %a3,(%a4)
6261 mov.l &0x2,%d4
6262
6263 mov.w &0x0000,ICCR(%a6)
6264 mov.w &0x0000,%cc
6265 movm.l &0xffff,IREGS(%a6)
6266
6267 mulu.l ([EASTORE.l,%pc],%zd4.l*8,0x20.l),%d2:%d3
6268
6269 mov.w %cc,SCCR(%a6)
6270 movm.l &0xffff,SREGS(%a6)
6271 mov.l &0x00000004,IREGS+0xc(%a6)
6272
6273 bsr.l chkregs
6274 tst.b %d0
6275 bne.l error
6276
6277ea_142:
6278 addq.l &0x1,TESTCTR(%a6)
6279
6280 movm.l DEF_REGS(%pc),&0x3fff
6281
6282 clr.l %d2
6283 mov.l &0x00000002,%d3
6284 lea EAMEM-0x20(%pc),%a3
6285 lea EASTORE(%pc),%a4
6286 mov.l %a3,(%a4)
6287 mov.l &0x4,%d4
6288
6289 mov.w &0x0000,ICCR(%a6)
6290 mov.w &0x0000,%cc
6291 movm.l &0xffff,IREGS(%a6)
6292
6293 mulu.l ([EASTORE.l,%zpc],%d4.l*8),%d2:%d3
6294
6295 mov.w %cc,SCCR(%a6)
6296 movm.l &0xffff,SREGS(%a6)
6297 mov.l &0x00000004,IREGS+0xc(%a6)
6298
6299 bsr.l chkregs
6300 tst.b %d0
6301 bne.l error
6302
6303ea_143:
6304 addq.l &0x1,TESTCTR(%a6)
6305
6306 movm.l DEF_REGS(%pc),&0x3fff
6307
6308 mov.l %a7,%a0
6309 clr.l %d2
6310 mov.l &0x00000002,%d3
6311 lea EAMEM(%pc),%a3
6312 lea EASTORE(%pc),%a6
6313 mov.l %a3,(%a6)
6314 add.l &0x10,%a6
6315 mov.l &-0x2,%a7
6316
6317 mov.w &0x0000,ICCR(%a6)
6318 mov.w &0x0000,%cc
6319 movm.l &0xffff,IREGS(%a6)
6320
6321 mulu.l ([EASTORE.w,%pc],%a7.l*8,0x10.l),%d2:%d3
6322
6323 mov.w %cc,SCCR(%a6)
6324 movm.l &0xffff,SREGS(%a6)
6325 mov.l &0x00000004,IREGS+0xc(%a6)
6326
6327 mov.l %a0,%a7
6328 bsr.l chkregs
6329 tst.b %d0
6330 bne.l error
6331
6332 clr.l %d0
6333 rts
6334
6335###########################################################
6336###########################################################
6337chkregs:
6338 lea IREGS(%a6),%a0
6339 lea SREGS(%a6),%a1
6340 mov.l &14,%d0
6341chkregs_loop:
6342 cmp.l (%a0)+,(%a1)+
6343 bne.l chkregs_error
6344 dbra.w %d0,chkregs_loop
6345
6346 mov.w ICCR(%a6),%d0
6347 mov.w SCCR(%a6),%d1
6348 cmp.w %d0,%d1
6349 bne.l chkregs_error
6350
6351 clr.l %d0
6352 rts
6353
6354chkregs_error:
6355 movq.l &0x1,%d0
6356 rts
6357
6358error:
6359 mov.l TESTCTR(%a6),%d1
6360 movq.l &0x1,%d0
6361 rts
6362
6363DEF_REGS:
6364 long 0xacacacac, 0xacacacac, 0xacacacac, 0xacacacac
6365 long 0xacacacac, 0xacacacac, 0xacacacac, 0xacacacac
6366
6367 long 0xacacacac, 0xacacacac, 0xacacacac, 0xacacacac
6368 long 0xacacacac, 0xacacacac, 0xacacacac, 0xacacacac
6369
6370############################################################
6371
6372_print_str:
6373 mov.l %d0,-(%sp)
6374 mov.l (TESTTOP-0x80+0x0,%pc),%d0
6375 pea (TESTTOP-0x80,%pc,%d0)
6376 mov.l 0x4(%sp),%d0
6377 rtd &0x4
6378
6379_print_num:
6380 mov.l %d0,-(%sp)
6381 mov.l (TESTTOP-0x80+0x4,%pc),%d0
6382 pea (TESTTOP-0x80,%pc,%d0)
6383 mov.l 0x4(%sp),%d0
6384 rtd &0x4
6385
6386############################################################
diff --git a/arch/m68k/ifpsp060/src/pfpsp.S b/arch/m68k/ifpsp060/src/pfpsp.S
new file mode 100644
index 000000000000..0c997c436beb
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/pfpsp.S
@@ -0,0 +1,14745 @@
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29# freal.s:
30# This file is appended to the top of the 060FPSP package
31# and contains the entry points into the package. The user, in
32# effect, branches to one of the branch table entries located
33# after _060FPSP_TABLE.
34# Also, subroutine stubs exist in this file (_fpsp_done for
35# example) that are referenced by the FPSP package itself in order
36# to call a given routine. The stub routine actually performs the
37# callout. The FPSP code does a "bsr" to the stub routine. This
38# extra layer of hierarchy adds a slight performance penalty but
39# it makes the FPSP code easier to read and more mainatinable.
40#
41
42set _off_bsun, 0x00
43set _off_snan, 0x04
44set _off_operr, 0x08
45set _off_ovfl, 0x0c
46set _off_unfl, 0x10
47set _off_dz, 0x14
48set _off_inex, 0x18
49set _off_fline, 0x1c
50set _off_fpu_dis, 0x20
51set _off_trap, 0x24
52set _off_trace, 0x28
53set _off_access, 0x2c
54set _off_done, 0x30
55
56set _off_imr, 0x40
57set _off_dmr, 0x44
58set _off_dmw, 0x48
59set _off_irw, 0x4c
60set _off_irl, 0x50
61set _off_drb, 0x54
62set _off_drw, 0x58
63set _off_drl, 0x5c
64set _off_dwb, 0x60
65set _off_dww, 0x64
66set _off_dwl, 0x68
67
68_060FPSP_TABLE:
69
70###############################################################
71
72# Here's the table of ENTRY POINTS for those linking the package.
73 bra.l _fpsp_snan
74 short 0x0000
75 bra.l _fpsp_operr
76 short 0x0000
77 bra.l _fpsp_ovfl
78 short 0x0000
79 bra.l _fpsp_unfl
80 short 0x0000
81 bra.l _fpsp_dz
82 short 0x0000
83 bra.l _fpsp_inex
84 short 0x0000
85 bra.l _fpsp_fline
86 short 0x0000
87 bra.l _fpsp_unsupp
88 short 0x0000
89 bra.l _fpsp_effadd
90 short 0x0000
91
92 space 56
93
94###############################################################
95 global _fpsp_done
96_fpsp_done:
97 mov.l %d0,-(%sp)
98 mov.l (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
99 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
100 mov.l 0x4(%sp),%d0
101 rtd &0x4
102
103 global _real_ovfl
104_real_ovfl:
105 mov.l %d0,-(%sp)
106 mov.l (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
107 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
108 mov.l 0x4(%sp),%d0
109 rtd &0x4
110
111 global _real_unfl
112_real_unfl:
113 mov.l %d0,-(%sp)
114 mov.l (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
115 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
116 mov.l 0x4(%sp),%d0
117 rtd &0x4
118
119 global _real_inex
120_real_inex:
121 mov.l %d0,-(%sp)
122 mov.l (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
123 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
124 mov.l 0x4(%sp),%d0
125 rtd &0x4
126
127 global _real_bsun
128_real_bsun:
129 mov.l %d0,-(%sp)
130 mov.l (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
131 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
132 mov.l 0x4(%sp),%d0
133 rtd &0x4
134
135 global _real_operr
136_real_operr:
137 mov.l %d0,-(%sp)
138 mov.l (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
139 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
140 mov.l 0x4(%sp),%d0
141 rtd &0x4
142
143 global _real_snan
144_real_snan:
145 mov.l %d0,-(%sp)
146 mov.l (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
147 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
148 mov.l 0x4(%sp),%d0
149 rtd &0x4
150
151 global _real_dz
152_real_dz:
153 mov.l %d0,-(%sp)
154 mov.l (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
155 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
156 mov.l 0x4(%sp),%d0
157 rtd &0x4
158
159 global _real_fline
160_real_fline:
161 mov.l %d0,-(%sp)
162 mov.l (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
163 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
164 mov.l 0x4(%sp),%d0
165 rtd &0x4
166
167 global _real_fpu_disabled
168_real_fpu_disabled:
169 mov.l %d0,-(%sp)
170 mov.l (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
171 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
172 mov.l 0x4(%sp),%d0
173 rtd &0x4
174
175 global _real_trap
176_real_trap:
177 mov.l %d0,-(%sp)
178 mov.l (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
179 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
180 mov.l 0x4(%sp),%d0
181 rtd &0x4
182
183 global _real_trace
184_real_trace:
185 mov.l %d0,-(%sp)
186 mov.l (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
187 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
188 mov.l 0x4(%sp),%d0
189 rtd &0x4
190
191 global _real_access
192_real_access:
193 mov.l %d0,-(%sp)
194 mov.l (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
195 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
196 mov.l 0x4(%sp),%d0
197 rtd &0x4
198
199#######################################
200
201 global _imem_read
202_imem_read:
203 mov.l %d0,-(%sp)
204 mov.l (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
205 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
206 mov.l 0x4(%sp),%d0
207 rtd &0x4
208
209 global _dmem_read
210_dmem_read:
211 mov.l %d0,-(%sp)
212 mov.l (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
213 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
214 mov.l 0x4(%sp),%d0
215 rtd &0x4
216
217 global _dmem_write
218_dmem_write:
219 mov.l %d0,-(%sp)
220 mov.l (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
221 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
222 mov.l 0x4(%sp),%d0
223 rtd &0x4
224
225 global _imem_read_word
226_imem_read_word:
227 mov.l %d0,-(%sp)
228 mov.l (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
229 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
230 mov.l 0x4(%sp),%d0
231 rtd &0x4
232
233 global _imem_read_long
234_imem_read_long:
235 mov.l %d0,-(%sp)
236 mov.l (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
237 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
238 mov.l 0x4(%sp),%d0
239 rtd &0x4
240
241 global _dmem_read_byte
242_dmem_read_byte:
243 mov.l %d0,-(%sp)
244 mov.l (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
245 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
246 mov.l 0x4(%sp),%d0
247 rtd &0x4
248
249 global _dmem_read_word
250_dmem_read_word:
251 mov.l %d0,-(%sp)
252 mov.l (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
253 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
254 mov.l 0x4(%sp),%d0
255 rtd &0x4
256
257 global _dmem_read_long
258_dmem_read_long:
259 mov.l %d0,-(%sp)
260 mov.l (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
261 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
262 mov.l 0x4(%sp),%d0
263 rtd &0x4
264
265 global _dmem_write_byte
266_dmem_write_byte:
267 mov.l %d0,-(%sp)
268 mov.l (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
269 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
270 mov.l 0x4(%sp),%d0
271 rtd &0x4
272
273 global _dmem_write_word
274_dmem_write_word:
275 mov.l %d0,-(%sp)
276 mov.l (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
277 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
278 mov.l 0x4(%sp),%d0
279 rtd &0x4
280
281 global _dmem_write_long
282_dmem_write_long:
283 mov.l %d0,-(%sp)
284 mov.l (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
285 pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
286 mov.l 0x4(%sp),%d0
287 rtd &0x4
288
289#
290# This file contains a set of define statements for constants
291# in order to promote readability within the corecode itself.
292#
293
294set LOCAL_SIZE, 192 # stack frame size(bytes)
295set LV, -LOCAL_SIZE # stack offset
296
297set EXC_SR, 0x4 # stack status register
298set EXC_PC, 0x6 # stack pc
299set EXC_VOFF, 0xa # stacked vector offset
300set EXC_EA, 0xc # stacked <ea>
301
302set EXC_FP, 0x0 # frame pointer
303
304set EXC_AREGS, -68 # offset of all address regs
305set EXC_DREGS, -100 # offset of all data regs
306set EXC_FPREGS, -36 # offset of all fp regs
307
308set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
309set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
310set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
311set EXC_A5, EXC_AREGS+(5*4)
312set EXC_A4, EXC_AREGS+(4*4)
313set EXC_A3, EXC_AREGS+(3*4)
314set EXC_A2, EXC_AREGS+(2*4)
315set EXC_A1, EXC_AREGS+(1*4)
316set EXC_A0, EXC_AREGS+(0*4)
317set EXC_D7, EXC_DREGS+(7*4)
318set EXC_D6, EXC_DREGS+(6*4)
319set EXC_D5, EXC_DREGS+(5*4)
320set EXC_D4, EXC_DREGS+(4*4)
321set EXC_D3, EXC_DREGS+(3*4)
322set EXC_D2, EXC_DREGS+(2*4)
323set EXC_D1, EXC_DREGS+(1*4)
324set EXC_D0, EXC_DREGS+(0*4)
325
326set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
327set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
328set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
329
330set FP_SCR1, LV+80 # fp scratch 1
331set FP_SCR1_EX, FP_SCR1+0
332set FP_SCR1_SGN, FP_SCR1+2
333set FP_SCR1_HI, FP_SCR1+4
334set FP_SCR1_LO, FP_SCR1+8
335
336set FP_SCR0, LV+68 # fp scratch 0
337set FP_SCR0_EX, FP_SCR0+0
338set FP_SCR0_SGN, FP_SCR0+2
339set FP_SCR0_HI, FP_SCR0+4
340set FP_SCR0_LO, FP_SCR0+8
341
342set FP_DST, LV+56 # fp destination operand
343set FP_DST_EX, FP_DST+0
344set FP_DST_SGN, FP_DST+2
345set FP_DST_HI, FP_DST+4
346set FP_DST_LO, FP_DST+8
347
348set FP_SRC, LV+44 # fp source operand
349set FP_SRC_EX, FP_SRC+0
350set FP_SRC_SGN, FP_SRC+2
351set FP_SRC_HI, FP_SRC+4
352set FP_SRC_LO, FP_SRC+8
353
354set USER_FPIAR, LV+40 # FP instr address register
355
356set USER_FPSR, LV+36 # FP status register
357set FPSR_CC, USER_FPSR+0 # FPSR condition codes
358set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
359set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
360set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
361
362set USER_FPCR, LV+32 # FP control register
363set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
364set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
365
366set L_SCR3, LV+28 # integer scratch 3
367set L_SCR2, LV+24 # integer scratch 2
368set L_SCR1, LV+20 # integer scratch 1
369
370set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
371
372set EXC_TEMP2, LV+24 # temporary space
373set EXC_TEMP, LV+16 # temporary space
374
375set DTAG, LV+15 # destination operand type
376set STAG, LV+14 # source operand type
377
378set SPCOND_FLG, LV+10 # flag: special case (see below)
379
380set EXC_CC, LV+8 # saved condition codes
381set EXC_EXTWPTR, LV+4 # saved current PC (active)
382set EXC_EXTWORD, LV+2 # saved extension word
383set EXC_CMDREG, LV+2 # saved extension word
384set EXC_OPWORD, LV+0 # saved operation word
385
386################################
387
388# Helpful macros
389
390set FTEMP, 0 # offsets within an
391set FTEMP_EX, 0 # extended precision
392set FTEMP_SGN, 2 # value saved in memory.
393set FTEMP_HI, 4
394set FTEMP_LO, 8
395set FTEMP_GRS, 12
396
397set LOCAL, 0 # offsets within an
398set LOCAL_EX, 0 # extended precision
399set LOCAL_SGN, 2 # value saved in memory.
400set LOCAL_HI, 4
401set LOCAL_LO, 8
402set LOCAL_GRS, 12
403
404set DST, 0 # offsets within an
405set DST_EX, 0 # extended precision
406set DST_HI, 4 # value saved in memory.
407set DST_LO, 8
408
409set SRC, 0 # offsets within an
410set SRC_EX, 0 # extended precision
411set SRC_HI, 4 # value saved in memory.
412set SRC_LO, 8
413
414set SGL_LO, 0x3f81 # min sgl prec exponent
415set SGL_HI, 0x407e # max sgl prec exponent
416set DBL_LO, 0x3c01 # min dbl prec exponent
417set DBL_HI, 0x43fe # max dbl prec exponent
418set EXT_LO, 0x0 # min ext prec exponent
419set EXT_HI, 0x7ffe # max ext prec exponent
420
421set EXT_BIAS, 0x3fff # extended precision bias
422set SGL_BIAS, 0x007f # single precision bias
423set DBL_BIAS, 0x03ff # double precision bias
424
425set NORM, 0x00 # operand type for STAG/DTAG
426set ZERO, 0x01 # operand type for STAG/DTAG
427set INF, 0x02 # operand type for STAG/DTAG
428set QNAN, 0x03 # operand type for STAG/DTAG
429set DENORM, 0x04 # operand type for STAG/DTAG
430set SNAN, 0x05 # operand type for STAG/DTAG
431set UNNORM, 0x06 # operand type for STAG/DTAG
432
433##################
434# FPSR/FPCR bits #
435##################
436set neg_bit, 0x3 # negative result
437set z_bit, 0x2 # zero result
438set inf_bit, 0x1 # infinite result
439set nan_bit, 0x0 # NAN result
440
441set q_sn_bit, 0x7 # sign bit of quotient byte
442
443set bsun_bit, 7 # branch on unordered
444set snan_bit, 6 # signalling NAN
445set operr_bit, 5 # operand error
446set ovfl_bit, 4 # overflow
447set unfl_bit, 3 # underflow
448set dz_bit, 2 # divide by zero
449set inex2_bit, 1 # inexact result 2
450set inex1_bit, 0 # inexact result 1
451
452set aiop_bit, 7 # accrued inexact operation bit
453set aovfl_bit, 6 # accrued overflow bit
454set aunfl_bit, 5 # accrued underflow bit
455set adz_bit, 4 # accrued dz bit
456set ainex_bit, 3 # accrued inexact bit
457
458#############################
459# FPSR individual bit masks #
460#############################
461set neg_mask, 0x08000000 # negative bit mask (lw)
462set inf_mask, 0x02000000 # infinity bit mask (lw)
463set z_mask, 0x04000000 # zero bit mask (lw)
464set nan_mask, 0x01000000 # nan bit mask (lw)
465
466set neg_bmask, 0x08 # negative bit mask (byte)
467set inf_bmask, 0x02 # infinity bit mask (byte)
468set z_bmask, 0x04 # zero bit mask (byte)
469set nan_bmask, 0x01 # nan bit mask (byte)
470
471set bsun_mask, 0x00008000 # bsun exception mask
472set snan_mask, 0x00004000 # snan exception mask
473set operr_mask, 0x00002000 # operr exception mask
474set ovfl_mask, 0x00001000 # overflow exception mask
475set unfl_mask, 0x00000800 # underflow exception mask
476set dz_mask, 0x00000400 # dz exception mask
477set inex2_mask, 0x00000200 # inex2 exception mask
478set inex1_mask, 0x00000100 # inex1 exception mask
479
480set aiop_mask, 0x00000080 # accrued illegal operation
481set aovfl_mask, 0x00000040 # accrued overflow
482set aunfl_mask, 0x00000020 # accrued underflow
483set adz_mask, 0x00000010 # accrued divide by zero
484set ainex_mask, 0x00000008 # accrued inexact
485
486######################################
487# FPSR combinations used in the FPSP #
488######################################
489set dzinf_mask, inf_mask+dz_mask+adz_mask
490set opnan_mask, nan_mask+operr_mask+aiop_mask
491set nzi_mask, 0x01ffffff #clears N, Z, and I
492set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
493set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
494set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
495set inx1a_mask, inex1_mask+ainex_mask
496set inx2a_mask, inex2_mask+ainex_mask
497set snaniop_mask, nan_mask+snan_mask+aiop_mask
498set snaniop2_mask, snan_mask+aiop_mask
499set naniop_mask, nan_mask+aiop_mask
500set neginf_mask, neg_mask+inf_mask
501set infaiop_mask, inf_mask+aiop_mask
502set negz_mask, neg_mask+z_mask
503set opaop_mask, operr_mask+aiop_mask
504set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
505set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
506
507#########
508# misc. #
509#########
510set rnd_stky_bit, 29 # stky bit pos in longword
511
512set sign_bit, 0x7 # sign bit
513set signan_bit, 0x6 # signalling nan bit
514
515set sgl_thresh, 0x3f81 # minimum sgl exponent
516set dbl_thresh, 0x3c01 # minimum dbl exponent
517
518set x_mode, 0x0 # extended precision
519set s_mode, 0x4 # single precision
520set d_mode, 0x8 # double precision
521
522set rn_mode, 0x0 # round-to-nearest
523set rz_mode, 0x1 # round-to-zero
524set rm_mode, 0x2 # round-tp-minus-infinity
525set rp_mode, 0x3 # round-to-plus-infinity
526
527set mantissalen, 64 # length of mantissa in bits
528
529set BYTE, 1 # len(byte) == 1 byte
530set WORD, 2 # len(word) == 2 bytes
531set LONG, 4 # len(longword) == 2 bytes
532
533set BSUN_VEC, 0xc0 # bsun vector offset
534set INEX_VEC, 0xc4 # inexact vector offset
535set DZ_VEC, 0xc8 # dz vector offset
536set UNFL_VEC, 0xcc # unfl vector offset
537set OPERR_VEC, 0xd0 # operr vector offset
538set OVFL_VEC, 0xd4 # ovfl vector offset
539set SNAN_VEC, 0xd8 # snan vector offset
540
541###########################
542# SPecial CONDition FLaGs #
543###########################
544set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
545set fbsun_flg, 0x02 # flag bit: bsun exception
546set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
547set mda7_flg, 0x08 # flag bit: -(a7) <ea>
548set fmovm_flg, 0x40 # flag bit: fmovm instruction
549set immed_flg, 0x80 # flag bit: &<data> <ea>
550
551set ftrapcc_bit, 0x0
552set fbsun_bit, 0x1
553set mia7_bit, 0x2
554set mda7_bit, 0x3
555set immed_bit, 0x7
556
557##################################
558# TRANSCENDENTAL "LAST-OP" FLAGS #
559##################################
560set FMUL_OP, 0x0 # fmul instr performed last
561set FDIV_OP, 0x1 # fdiv performed last
562set FADD_OP, 0x2 # fadd performed last
563set FMOV_OP, 0x3 # fmov performed last
564
565#############
566# CONSTANTS #
567#############
568T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
569T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
570
571PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
572PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
573
574TWOBYPI:
575 long 0x3FE45F30,0x6DC9C883
576
577#########################################################################
578# XDEF **************************************************************** #
579# _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception. #
580# #
581# This handler should be the first code executed upon taking the #
582# FP Overflow exception in an operating system. #
583# #
584# XREF **************************************************************** #
585# _imem_read_long() - read instruction longword #
586# fix_skewed_ops() - adjust src operand in fsave frame #
587# set_tag_x() - determine optype of src/dst operands #
588# store_fpreg() - store opclass 0 or 2 result to FP regfile #
589# unnorm_fix() - change UNNORM operands to NORM or ZERO #
590# load_fpn2() - load dst operand from FP regfile #
591# fout() - emulate an opclass 3 instruction #
592# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
593# _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
594# _real_ovfl() - "callout" for Overflow exception enabled code #
595# _real_inex() - "callout" for Inexact exception enabled code #
596# _real_trace() - "callout" for Trace exception code #
597# #
598# INPUT *************************************************************** #
599# - The system stack contains the FP Ovfl exception stack frame #
600# - The fsave frame contains the source operand #
601# #
602# OUTPUT ************************************************************** #
603# Overflow Exception enabled: #
604# - The system stack is unchanged #
605# - The fsave frame contains the adjusted src op for opclass 0,2 #
606# Overflow Exception disabled: #
607# - The system stack is unchanged #
608# - The "exception present" flag in the fsave frame is cleared #
609# #
610# ALGORITHM *********************************************************** #
611# On the 060, if an FP overflow is present as the result of any #
612# instruction, the 060 will take an overflow exception whether the #
613# exception is enabled or disabled in the FPCR. For the disabled case, #
614# This handler emulates the instruction to determine what the correct #
615# default result should be for the operation. This default result is #
616# then stored in either the FP regfile, data regfile, or memory. #
617# Finally, the handler exits through the "callout" _fpsp_done() #
618# denoting that no exceptional conditions exist within the machine. #
619# If the exception is enabled, then this handler must create the #
620# exceptional operand and plave it in the fsave state frame, and store #
621# the default result (only if the instruction is opclass 3). For #
622# exceptions enabled, this handler must exit through the "callout" #
623# _real_ovfl() so that the operating system enabled overflow handler #
624# can handle this case. #
625# Two other conditions exist. First, if overflow was disabled #
626# but the inexact exception was enabled, this handler must exit #
627# through the "callout" _real_inex() regardless of whether the result #
628# was inexact. #
629# Also, in the case of an opclass three instruction where #
630# overflow was disabled and the trace exception was enabled, this #
631# handler must exit through the "callout" _real_trace(). #
632# #
633#########################################################################
634
635 global _fpsp_ovfl
636_fpsp_ovfl:
637
638#$# sub.l &24,%sp # make room for src/dst
639
640 link.w %a6,&-LOCAL_SIZE # init stack frame
641
642 fsave FP_SRC(%a6) # grab the "busy" frame
643
644 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
645 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
646 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
647
648# the FPIAR holds the "current PC" of the faulting instruction
649 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
650 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
651 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
652 bsr.l _imem_read_long # fetch the instruction words
653 mov.l %d0,EXC_OPWORD(%a6)
654
655##############################################################################
656
657 btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
658 bne.w fovfl_out
659
660
661 lea FP_SRC(%a6),%a0 # pass: ptr to src op
662 bsr.l fix_skewed_ops # fix src op
663
664# since, I believe, only NORMs and DENORMs can come through here,
665# maybe we can avoid the subroutine call.
666 lea FP_SRC(%a6),%a0 # pass: ptr to src op
667 bsr.l set_tag_x # tag the operand type
668 mov.b %d0,STAG(%a6) # maybe NORM,DENORM
669
670# bit five of the fp extension word separates the monadic and dyadic operations
671# that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
672# will never take this exception.
673 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
674 beq.b fovfl_extract # monadic
675
676 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
677 bsr.l load_fpn2 # load dst into FP_DST
678
679 lea FP_DST(%a6),%a0 # pass: ptr to dst op
680 bsr.l set_tag_x # tag the operand type
681 cmpi.b %d0,&UNNORM # is operand an UNNORM?
682 bne.b fovfl_op2_done # no
683 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
684fovfl_op2_done:
685 mov.b %d0,DTAG(%a6) # save dst optype tag
686
687fovfl_extract:
688
689#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
690#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
691#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
692#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
693#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
694#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
695
696 clr.l %d0
697 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
698
699 mov.b 1+EXC_CMDREG(%a6),%d1
700 andi.w &0x007f,%d1 # extract extension
701
702 andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
703
704 fmov.l &0x0,%fpcr # zero current control regs
705 fmov.l &0x0,%fpsr
706
707 lea FP_SRC(%a6),%a0
708 lea FP_DST(%a6),%a1
709
710# maybe we can make these entry points ONLY the OVFL entry points of each routine.
711 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
712 jsr (tbl_unsupp.l,%pc,%d1.l*1)
713
714# the operation has been emulated. the result is in fp0.
715# the EXOP, if an exception occurred, is in fp1.
716# we must save the default result regardless of whether
717# traps are enabled or disabled.
718 bfextu EXC_CMDREG(%a6){&6:&3},%d0
719 bsr.l store_fpreg
720
721# the exceptional possibilities we have left ourselves with are ONLY overflow
722# and inexact. and, the inexact is such that overflow occurred and was disabled
723# but inexact was enabled.
724 btst &ovfl_bit,FPCR_ENABLE(%a6)
725 bne.b fovfl_ovfl_on
726
727 btst &inex2_bit,FPCR_ENABLE(%a6)
728 bne.b fovfl_inex_on
729
730 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
731 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
732 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
733
734 unlk %a6
735#$# add.l &24,%sp
736 bra.l _fpsp_done
737
738# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
739# in fp1. now, simply jump to _real_ovfl()!
740fovfl_ovfl_on:
741 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
742
743 mov.w &0xe005,2+FP_SRC(%a6) # save exc status
744
745 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
746 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
747 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
748
749 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
750
751 unlk %a6
752
753 bra.l _real_ovfl
754
755# overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
756# we must jump to real_inex().
757fovfl_inex_on:
758
759 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
760
761 mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
762 mov.w &0xe001,2+FP_SRC(%a6) # save exc status
763
764 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
765 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
766 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
767
768 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
769
770 unlk %a6
771
772 bra.l _real_inex
773
774########################################################################
775fovfl_out:
776
777
778#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
779#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
780#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
781
782# the src operand is definitely a NORM(!), so tag it as such
783 mov.b &NORM,STAG(%a6) # set src optype tag
784
785 clr.l %d0
786 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
787
788 and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
789
790 fmov.l &0x0,%fpcr # zero current control regs
791 fmov.l &0x0,%fpsr
792
793 lea FP_SRC(%a6),%a0 # pass ptr to src operand
794
795 bsr.l fout
796
797 btst &ovfl_bit,FPCR_ENABLE(%a6)
798 bne.w fovfl_ovfl_on
799
800 btst &inex2_bit,FPCR_ENABLE(%a6)
801 bne.w fovfl_inex_on
802
803 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
804 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
805 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
806
807 unlk %a6
808#$# add.l &24,%sp
809
810 btst &0x7,(%sp) # is trace on?
811 beq.l _fpsp_done # no
812
813 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
814 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
815 bra.l _real_trace
816
817#########################################################################
818# XDEF **************************************************************** #
819# _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. #
820# #
821# This handler should be the first code executed upon taking the #
822# FP Underflow exception in an operating system. #
823# #
824# XREF **************************************************************** #
825# _imem_read_long() - read instruction longword #
826# fix_skewed_ops() - adjust src operand in fsave frame #
827# set_tag_x() - determine optype of src/dst operands #
828# store_fpreg() - store opclass 0 or 2 result to FP regfile #
829# unnorm_fix() - change UNNORM operands to NORM or ZERO #
830# load_fpn2() - load dst operand from FP regfile #
831# fout() - emulate an opclass 3 instruction #
832# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
833# _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
834# _real_ovfl() - "callout" for Overflow exception enabled code #
835# _real_inex() - "callout" for Inexact exception enabled code #
836# _real_trace() - "callout" for Trace exception code #
837# #
838# INPUT *************************************************************** #
839# - The system stack contains the FP Unfl exception stack frame #
840# - The fsave frame contains the source operand #
841# #
842# OUTPUT ************************************************************** #
843# Underflow Exception enabled: #
844# - The system stack is unchanged #
845# - The fsave frame contains the adjusted src op for opclass 0,2 #
846# Underflow Exception disabled: #
847# - The system stack is unchanged #
848# - The "exception present" flag in the fsave frame is cleared #
849# #
850# ALGORITHM *********************************************************** #
851# On the 060, if an FP underflow is present as the result of any #
852# instruction, the 060 will take an underflow exception whether the #
853# exception is enabled or disabled in the FPCR. For the disabled case, #
854# This handler emulates the instruction to determine what the correct #
855# default result should be for the operation. This default result is #
856# then stored in either the FP regfile, data regfile, or memory. #
857# Finally, the handler exits through the "callout" _fpsp_done() #
858# denoting that no exceptional conditions exist within the machine. #
859# If the exception is enabled, then this handler must create the #
860# exceptional operand and plave it in the fsave state frame, and store #
861# the default result (only if the instruction is opclass 3). For #
862# exceptions enabled, this handler must exit through the "callout" #
863# _real_unfl() so that the operating system enabled overflow handler #
864# can handle this case. #
865# Two other conditions exist. First, if underflow was disabled #
866# but the inexact exception was enabled and the result was inexact, #
867# this handler must exit through the "callout" _real_inex(). #
868# was inexact. #
869# Also, in the case of an opclass three instruction where #
870# underflow was disabled and the trace exception was enabled, this #
871# handler must exit through the "callout" _real_trace(). #
872# #
873#########################################################################
874
875 global _fpsp_unfl
876_fpsp_unfl:
877
878#$# sub.l &24,%sp # make room for src/dst
879
880 link.w %a6,&-LOCAL_SIZE # init stack frame
881
882 fsave FP_SRC(%a6) # grab the "busy" frame
883
884 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
885 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
886 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
887
888# the FPIAR holds the "current PC" of the faulting instruction
889 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
890 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
891 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
892 bsr.l _imem_read_long # fetch the instruction words
893 mov.l %d0,EXC_OPWORD(%a6)
894
895##############################################################################
896
897 btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
898 bne.w funfl_out
899
900
901 lea FP_SRC(%a6),%a0 # pass: ptr to src op
902 bsr.l fix_skewed_ops # fix src op
903
904 lea FP_SRC(%a6),%a0 # pass: ptr to src op
905 bsr.l set_tag_x # tag the operand type
906 mov.b %d0,STAG(%a6) # maybe NORM,DENORM
907
908# bit five of the fp ext word separates the monadic and dyadic operations
909# that can pass through fpsp_unfl(). remember that fcmp, and ftst
910# will never take this exception.
911 btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic?
912 beq.b funfl_extract # monadic
913
914# now, what's left that's not dyadic is fsincos. we can distinguish it
915# from all dyadics by the '0110xxx pattern
916 btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos?
917 bne.b funfl_extract # yes
918
919 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
920 bsr.l load_fpn2 # load dst into FP_DST
921
922 lea FP_DST(%a6),%a0 # pass: ptr to dst op
923 bsr.l set_tag_x # tag the operand type
924 cmpi.b %d0,&UNNORM # is operand an UNNORM?
925 bne.b funfl_op2_done # no
926 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
927funfl_op2_done:
928 mov.b %d0,DTAG(%a6) # save dst optype tag
929
930funfl_extract:
931
932#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
933#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
934#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
935#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
936#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
937#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
938
939 clr.l %d0
940 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
941
942 mov.b 1+EXC_CMDREG(%a6),%d1
943 andi.w &0x007f,%d1 # extract extension
944
945 andi.l &0x00ff01ff,USER_FPSR(%a6)
946
947 fmov.l &0x0,%fpcr # zero current control regs
948 fmov.l &0x0,%fpsr
949
950 lea FP_SRC(%a6),%a0
951 lea FP_DST(%a6),%a1
952
953# maybe we can make these entry points ONLY the OVFL entry points of each routine.
954 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
955 jsr (tbl_unsupp.l,%pc,%d1.l*1)
956
957 bfextu EXC_CMDREG(%a6){&6:&3},%d0
958 bsr.l store_fpreg
959
960# The `060 FPU multiplier hardware is such that if the result of a
961# multiply operation is the smallest possible normalized number
962# (0x00000000_80000000_00000000), then the machine will take an
963# underflow exception. Since this is incorrect, we need to check
964# if our emulation, after re-doing the operation, decided that
965# no underflow was called for. We do these checks only in
966# funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
967# special case will simply exit gracefully with the correct result.
968
969# the exceptional possibilities we have left ourselves with are ONLY overflow
970# and inexact. and, the inexact is such that overflow occurred and was disabled
971# but inexact was enabled.
972 btst &unfl_bit,FPCR_ENABLE(%a6)
973 bne.b funfl_unfl_on
974
975funfl_chkinex:
976 btst &inex2_bit,FPCR_ENABLE(%a6)
977 bne.b funfl_inex_on
978
979funfl_exit:
980 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
981 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
982 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
983
984 unlk %a6
985#$# add.l &24,%sp
986 bra.l _fpsp_done
987
988# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
989# in fp1 (don't forget to save fp0). what to do now?
990# well, we simply have to get to go to _real_unfl()!
991funfl_unfl_on:
992
993# The `060 FPU multiplier hardware is such that if the result of a
994# multiply operation is the smallest possible normalized number
995# (0x00000000_80000000_00000000), then the machine will take an
996# underflow exception. Since this is incorrect, we check here to see
997# if our emulation, after re-doing the operation, decided that
998# no underflow was called for.
999 btst &unfl_bit,FPSR_EXCEPT(%a6)
1000 beq.w funfl_chkinex
1001
1002funfl_unfl_on2:
1003 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
1004
1005 mov.w &0xe003,2+FP_SRC(%a6) # save exc status
1006
1007 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1008 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1009 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1010
1011 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
1012
1013 unlk %a6
1014
1015 bra.l _real_unfl
1016
1017# undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
1018# we must jump to real_inex().
1019funfl_inex_on:
1020
1021# The `060 FPU multiplier hardware is such that if the result of a
1022# multiply operation is the smallest possible normalized number
1023# (0x00000000_80000000_00000000), then the machine will take an
1024# underflow exception.
1025# But, whether bogus or not, if inexact is enabled AND it occurred,
1026# then we have to branch to real_inex.
1027
1028 btst &inex2_bit,FPSR_EXCEPT(%a6)
1029 beq.w funfl_exit
1030
1031funfl_inex_on2:
1032
1033 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to stack
1034
1035 mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
1036 mov.w &0xe001,2+FP_SRC(%a6) # save exc status
1037
1038 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1039 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1040 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1041
1042 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
1043
1044 unlk %a6
1045
1046 bra.l _real_inex
1047
1048#######################################################################
1049funfl_out:
1050
1051
1052#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
1053#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
1054#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
1055
1056# the src operand is definitely a NORM(!), so tag it as such
1057 mov.b &NORM,STAG(%a6) # set src optype tag
1058
1059 clr.l %d0
1060 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
1061
1062 and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
1063
1064 fmov.l &0x0,%fpcr # zero current control regs
1065 fmov.l &0x0,%fpsr
1066
1067 lea FP_SRC(%a6),%a0 # pass ptr to src operand
1068
1069 bsr.l fout
1070
1071 btst &unfl_bit,FPCR_ENABLE(%a6)
1072 bne.w funfl_unfl_on2
1073
1074 btst &inex2_bit,FPCR_ENABLE(%a6)
1075 bne.w funfl_inex_on2
1076
1077 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1078 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1079 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1080
1081 unlk %a6
1082#$# add.l &24,%sp
1083
1084 btst &0x7,(%sp) # is trace on?
1085 beq.l _fpsp_done # no
1086
1087 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
1088 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
1089 bra.l _real_trace
1090
1091#########################################################################
1092# XDEF **************************************************************** #
1093# _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented #
1094# Data Type" exception. #
1095# #
1096# This handler should be the first code executed upon taking the #
1097# FP Unimplemented Data Type exception in an operating system. #
1098# #
1099# XREF **************************************************************** #
1100# _imem_read_{word,long}() - read instruction word/longword #
1101# fix_skewed_ops() - adjust src operand in fsave frame #
1102# set_tag_x() - determine optype of src/dst operands #
1103# store_fpreg() - store opclass 0 or 2 result to FP regfile #
1104# unnorm_fix() - change UNNORM operands to NORM or ZERO #
1105# load_fpn2() - load dst operand from FP regfile #
1106# load_fpn1() - load src operand from FP regfile #
1107# fout() - emulate an opclass 3 instruction #
1108# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
1109# _real_inex() - "callout" to operating system inexact handler #
1110# _fpsp_done() - "callout" for exit; work all done #
1111# _real_trace() - "callout" for Trace enabled exception #
1112# funimp_skew() - adjust fsave src ops to "incorrect" value #
1113# _real_snan() - "callout" for SNAN exception #
1114# _real_operr() - "callout" for OPERR exception #
1115# _real_ovfl() - "callout" for OVFL exception #
1116# _real_unfl() - "callout" for UNFL exception #
1117# get_packed() - fetch packed operand from memory #
1118# #
1119# INPUT *************************************************************** #
1120# - The system stack contains the "Unimp Data Type" stk frame #
1121# - The fsave frame contains the ssrc op (for UNNORM/DENORM) #
1122# #
1123# OUTPUT ************************************************************** #
1124# If Inexact exception (opclass 3): #
1125# - The system stack is changed to an Inexact exception stk frame #
1126# If SNAN exception (opclass 3): #
1127# - The system stack is changed to an SNAN exception stk frame #
1128# If OPERR exception (opclass 3): #
1129# - The system stack is changed to an OPERR exception stk frame #
1130# If OVFL exception (opclass 3): #
1131# - The system stack is changed to an OVFL exception stk frame #
1132# If UNFL exception (opclass 3): #
1133# - The system stack is changed to an UNFL exception stack frame #
1134# If Trace exception enabled: #
1135# - The system stack is changed to a Trace exception stack frame #
1136# Else: (normal case) #
1137# - Correct result has been stored as appropriate #
1138# #
1139# ALGORITHM *********************************************************** #
1140# Two main instruction types can enter here: (1) DENORM or UNNORM #
1141# unimplemented data types. These can be either opclass 0,2 or 3 #
1142# instructions, and (2) PACKED unimplemented data format instructions #
1143# also of opclasses 0,2, or 3. #
1144# For UNNORM/DENORM opclass 0 and 2, the handler fetches the src #
1145# operand from the fsave state frame and the dst operand (if dyadic) #
1146# from the FP register file. The instruction is then emulated by #
1147# choosing an emulation routine from a table of routines indexed by #
1148# instruction type. Once the instruction has been emulated and result #
1149# saved, then we check to see if any enabled exceptions resulted from #
1150# instruction emulation. If none, then we exit through the "callout" #
1151# _fpsp_done(). If there is an enabled FP exception, then we insert #
1152# this exception into the FPU in the fsave state frame and then exit #
1153# through _fpsp_done(). #
1154# PACKED opclass 0 and 2 is similar in how the instruction is #
1155# emulated and exceptions handled. The differences occur in how the #
1156# handler loads the packed op (by calling get_packed() routine) and #
1157# by the fact that a Trace exception could be pending for PACKED ops. #
1158# If a Trace exception is pending, then the current exception stack #
1159# frame is changed to a Trace exception stack frame and an exit is #
1160# made through _real_trace(). #
1161# For UNNORM/DENORM opclass 3, the actual move out to memory is #
1162# performed by calling the routine fout(). If no exception should occur #
1163# as the result of emulation, then an exit either occurs through #
1164# _fpsp_done() or through _real_trace() if a Trace exception is pending #
1165# (a Trace stack frame must be created here, too). If an FP exception #
1166# should occur, then we must create an exception stack frame of that #
1167# type and jump to either _real_snan(), _real_operr(), _real_inex(), #
1168# _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3 #
1169# emulation is performed in a similar manner. #
1170# #
1171#########################################################################
1172
1173#
1174# (1) DENORM and UNNORM (unimplemented) data types:
1175#
1176# post-instruction
1177# *****************
1178# * EA *
1179# pre-instruction * *
1180# ***************** *****************
1181# * 0x0 * 0x0dc * * 0x3 * 0x0dc *
1182# ***************** *****************
1183# * Next * * Next *
1184# * PC * * PC *
1185# ***************** *****************
1186# * SR * * SR *
1187# ***************** *****************
1188#
1189# (2) PACKED format (unsupported) opclasses two and three:
1190# *****************
1191# * EA *
1192# * *
1193# *****************
1194# * 0x2 * 0x0dc *
1195# *****************
1196# * Next *
1197# * PC *
1198# *****************
1199# * SR *
1200# *****************
1201#
1202 global _fpsp_unsupp
1203_fpsp_unsupp:
1204
1205 link.w %a6,&-LOCAL_SIZE # init stack frame
1206
1207 fsave FP_SRC(%a6) # save fp state
1208
1209 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1210 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
1211 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
1212
1213 btst &0x5,EXC_SR(%a6) # user or supervisor mode?
1214 bne.b fu_s
1215fu_u:
1216 mov.l %usp,%a0 # fetch user stack pointer
1217 mov.l %a0,EXC_A7(%a6) # save on stack
1218 bra.b fu_cont
1219# if the exception is an opclass zero or two unimplemented data type
1220# exception, then the a7' calculated here is wrong since it doesn't
1221# stack an ea. however, we don't need an a7' for this case anyways.
1222fu_s:
1223 lea 0x4+EXC_EA(%a6),%a0 # load old a7'
1224 mov.l %a0,EXC_A7(%a6) # save on stack
1225
1226fu_cont:
1227
1228# the FPIAR holds the "current PC" of the faulting instruction
1229# the FPIAR should be set correctly for ALL exceptions passing through
1230# this point.
1231 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
1232 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1233 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1234 bsr.l _imem_read_long # fetch the instruction words
1235 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
1236
1237############################
1238
1239 clr.b SPCOND_FLG(%a6) # clear special condition flag
1240
1241# Separate opclass three (fpn-to-mem) ops since they have a different
1242# stack frame and protocol.
1243 btst &0x5,EXC_CMDREG(%a6) # is it an fmove out?
1244 bne.w fu_out # yes
1245
1246# Separate packed opclass two instructions.
1247 bfextu EXC_CMDREG(%a6){&0:&6},%d0
1248 cmpi.b %d0,&0x13
1249 beq.w fu_in_pack
1250
1251
1252# I'm not sure at this point what FPSR bits are valid for this instruction.
1253# so, since the emulation routines re-create them anyways, zero exception field
1254 andi.l &0x00ff00ff,USER_FPSR(%a6) # zero exception field
1255
1256 fmov.l &0x0,%fpcr # zero current control regs
1257 fmov.l &0x0,%fpsr
1258
1259# Opclass two w/ memory-to-fpn operation will have an incorrect extended
1260# precision format if the src format was single or double and the
1261# source data type was an INF, NAN, DENORM, or UNNORM
1262 lea FP_SRC(%a6),%a0 # pass ptr to input
1263 bsr.l fix_skewed_ops
1264
1265# we don't know whether the src operand or the dst operand (or both) is the
1266# UNNORM or DENORM. call the function that tags the operand type. if the
1267# input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
1268 lea FP_SRC(%a6),%a0 # pass: ptr to src op
1269 bsr.l set_tag_x # tag the operand type
1270 cmpi.b %d0,&UNNORM # is operand an UNNORM?
1271 bne.b fu_op2 # no
1272 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1273
1274fu_op2:
1275 mov.b %d0,STAG(%a6) # save src optype tag
1276
1277 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1278
1279# bit five of the fp extension word separates the monadic and dyadic operations
1280# at this point
1281 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
1282 beq.b fu_extract # monadic
1283 cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
1284 beq.b fu_extract # yes, so it's monadic, too
1285
1286 bsr.l load_fpn2 # load dst into FP_DST
1287
1288 lea FP_DST(%a6),%a0 # pass: ptr to dst op
1289 bsr.l set_tag_x # tag the operand type
1290 cmpi.b %d0,&UNNORM # is operand an UNNORM?
1291 bne.b fu_op2_done # no
1292 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1293fu_op2_done:
1294 mov.b %d0,DTAG(%a6) # save dst optype tag
1295
1296fu_extract:
1297 clr.l %d0
1298 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1299
1300 bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1301
1302 lea FP_SRC(%a6),%a0
1303 lea FP_DST(%a6),%a1
1304
1305 mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1306 jsr (tbl_unsupp.l,%pc,%d1.l*1)
1307
1308#
1309# Exceptions in order of precedence:
1310# BSUN : none
1311# SNAN : all dyadic ops
1312# OPERR : fsqrt(-NORM)
1313# OVFL : all except ftst,fcmp
1314# UNFL : all except ftst,fcmp
1315# DZ : fdiv
1316# INEX2 : all except ftst,fcmp
1317# INEX1 : none (packed doesn't go through here)
1318#
1319
1320# we determine the highest priority exception(if any) set by the
1321# emulation routine that has also been enabled by the user.
1322 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions set
1323 bne.b fu_in_ena # some are enabled
1324
1325fu_in_cont:
1326# fcmp and ftst do not store any result.
1327 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
1328 andi.b &0x38,%d0 # extract bits 3-5
1329 cmpi.b %d0,&0x38 # is instr fcmp or ftst?
1330 beq.b fu_in_exit # yes
1331
1332 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1333 bsr.l store_fpreg # store the result
1334
1335fu_in_exit:
1336
1337 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1338 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1339 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1340
1341 unlk %a6
1342
1343 bra.l _fpsp_done
1344
1345fu_in_ena:
1346 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
1347 bfffo %d0{&24:&8},%d0 # find highest priority exception
1348 bne.b fu_in_exc # there is at least one set
1349
1350#
1351# No exceptions occurred that were also enabled. Now:
1352#
1353# if (OVFL && ovfl_disabled && inexact_enabled) {
1354# branch to _real_inex() (even if the result was exact!);
1355# } else {
1356# save the result in the proper fp reg (unless the op is fcmp or ftst);
1357# return;
1358# }
1359#
1360 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1361 beq.b fu_in_cont # no
1362
1363fu_in_ovflchk:
1364 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1365 beq.b fu_in_cont # no
1366 bra.w fu_in_exc_ovfl # go insert overflow frame
1367
1368#
1369# An exception occurred and that exception was enabled:
1370#
1371# shift enabled exception field into lo byte of d0;
1372# if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1373# ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1374# /*
1375# * this is the case where we must call _real_inex() now or else
1376# * there will be no other way to pass it the exceptional operand
1377# */
1378# call _real_inex();
1379# } else {
1380# restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1381# }
1382#
1383fu_in_exc:
1384 subi.l &24,%d0 # fix offset to be 0-8
1385 cmpi.b %d0,&0x6 # is exception INEX? (6)
1386 bne.b fu_in_exc_exit # no
1387
1388# the enabled exception was inexact
1389 btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1390 bne.w fu_in_exc_unfl # yes
1391 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1392 bne.w fu_in_exc_ovfl # yes
1393
1394# here, we insert the correct fsave status value into the fsave frame for the
1395# corresponding exception. the operand in the fsave frame should be the original
1396# src operand.
1397fu_in_exc_exit:
1398 mov.l %d0,-(%sp) # save d0
1399 bsr.l funimp_skew # skew sgl or dbl inputs
1400 mov.l (%sp)+,%d0 # restore d0
1401
1402 mov.w (tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
1403
1404 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1405 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1406 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1407
1408 frestore FP_SRC(%a6) # restore src op
1409
1410 unlk %a6
1411
1412 bra.l _fpsp_done
1413
1414tbl_except:
1415 short 0xe000,0xe006,0xe004,0xe005
1416 short 0xe003,0xe002,0xe001,0xe001
1417
1418fu_in_exc_unfl:
1419 mov.w &0x4,%d0
1420 bra.b fu_in_exc_exit
1421fu_in_exc_ovfl:
1422 mov.w &0x03,%d0
1423 bra.b fu_in_exc_exit
1424
1425# If the input operand to this operation was opclass two and a single
1426# or double precision denorm, inf, or nan, the operand needs to be
1427# "corrected" in order to have the proper equivalent extended precision
1428# number.
1429 global fix_skewed_ops
1430fix_skewed_ops:
1431 bfextu EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
1432 cmpi.b %d0,&0x11 # is class = 2 & fmt = sgl?
1433 beq.b fso_sgl # yes
1434 cmpi.b %d0,&0x15 # is class = 2 & fmt = dbl?
1435 beq.b fso_dbl # yes
1436 rts # no
1437
1438fso_sgl:
1439 mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
1440 andi.w &0x7fff,%d0 # strip sign
1441 cmpi.w %d0,&0x3f80 # is |exp| == $3f80?
1442 beq.b fso_sgl_dnrm_zero # yes
1443 cmpi.w %d0,&0x407f # no; is |exp| == $407f?
1444 beq.b fso_infnan # yes
1445 rts # no
1446
1447fso_sgl_dnrm_zero:
1448 andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1449 beq.b fso_zero # it's a skewed zero
1450fso_sgl_dnrm:
1451# here, we count on norm not to alter a0...
1452 bsr.l norm # normalize mantissa
1453 neg.w %d0 # -shft amt
1454 addi.w &0x3f81,%d0 # adjust new exponent
1455 andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
1456 or.w %d0,LOCAL_EX(%a0) # insert new exponent
1457 rts
1458
1459fso_zero:
1460 andi.w &0x8000,LOCAL_EX(%a0) # clear bogus exponent
1461 rts
1462
1463fso_infnan:
1464 andi.b &0x7f,LOCAL_HI(%a0) # clear j-bit
1465 ori.w &0x7fff,LOCAL_EX(%a0) # make exponent = $7fff
1466 rts
1467
1468fso_dbl:
1469 mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
1470 andi.w &0x7fff,%d0 # strip sign
1471 cmpi.w %d0,&0x3c00 # is |exp| == $3c00?
1472 beq.b fso_dbl_dnrm_zero # yes
1473 cmpi.w %d0,&0x43ff # no; is |exp| == $43ff?
1474 beq.b fso_infnan # yes
1475 rts # no
1476
1477fso_dbl_dnrm_zero:
1478 andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1479 bne.b fso_dbl_dnrm # it's a skewed denorm
1480 tst.l LOCAL_LO(%a0) # is it a zero?
1481 beq.b fso_zero # yes
1482fso_dbl_dnrm:
1483# here, we count on norm not to alter a0...
1484 bsr.l norm # normalize mantissa
1485 neg.w %d0 # -shft amt
1486 addi.w &0x3c01,%d0 # adjust new exponent
1487 andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
1488 or.w %d0,LOCAL_EX(%a0) # insert new exponent
1489 rts
1490
1491#################################################################
1492
1493# fmove out took an unimplemented data type exception.
1494# the src operand is in FP_SRC. Call _fout() to write out the result and
1495# to determine which exceptions, if any, to take.
1496fu_out:
1497
1498# Separate packed move outs from the UNNORM and DENORM move outs.
1499 bfextu EXC_CMDREG(%a6){&3:&3},%d0
1500 cmpi.b %d0,&0x3
1501 beq.w fu_out_pack
1502 cmpi.b %d0,&0x7
1503 beq.w fu_out_pack
1504
1505
1506# I'm not sure at this point what FPSR bits are valid for this instruction.
1507# so, since the emulation routines re-create them anyways, zero exception field.
1508# fmove out doesn't affect ccodes.
1509 and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
1510
1511 fmov.l &0x0,%fpcr # zero current control regs
1512 fmov.l &0x0,%fpsr
1513
1514# the src can ONLY be a DENORM or an UNNORM! so, don't make any big subroutine
1515# call here. just figure out what it is...
1516 mov.w FP_SRC_EX(%a6),%d0 # get exponent
1517 andi.w &0x7fff,%d0 # strip sign
1518 beq.b fu_out_denorm # it's a DENORM
1519
1520 lea FP_SRC(%a6),%a0
1521 bsr.l unnorm_fix # yes; fix it
1522
1523 mov.b %d0,STAG(%a6)
1524
1525 bra.b fu_out_cont
1526fu_out_denorm:
1527 mov.b &DENORM,STAG(%a6)
1528fu_out_cont:
1529
1530 clr.l %d0
1531 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1532
1533 lea FP_SRC(%a6),%a0 # pass ptr to src operand
1534
1535 mov.l (%a6),EXC_A6(%a6) # in case a6 changes
1536 bsr.l fout # call fmove out routine
1537
1538# Exceptions in order of precedence:
1539# BSUN : none
1540# SNAN : none
1541# OPERR : fmove.{b,w,l} out of large UNNORM
1542# OVFL : fmove.{s,d}
1543# UNFL : fmove.{s,d,x}
1544# DZ : none
1545# INEX2 : all
1546# INEX1 : none (packed doesn't travel through here)
1547
1548# determine the highest priority exception(if any) set by the
1549# emulation routine that has also been enabled by the user.
1550 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
1551 bne.w fu_out_ena # some are enabled
1552
1553fu_out_done:
1554
1555 mov.l EXC_A6(%a6),(%a6) # in case a6 changed
1556
1557# on extended precision opclass three instructions using pre-decrement or
1558# post-increment addressing mode, the address register is not updated. is the
1559# address register was the stack pointer used from user mode, then let's update
1560# it here. if it was used from supervisor mode, then we have to handle this
1561# as a special case.
1562 btst &0x5,EXC_SR(%a6)
1563 bne.b fu_out_done_s
1564
1565 mov.l EXC_A7(%a6),%a0 # restore a7
1566 mov.l %a0,%usp
1567
1568fu_out_done_cont:
1569 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1570 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1571 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1572
1573 unlk %a6
1574
1575 btst &0x7,(%sp) # is trace on?
1576 bne.b fu_out_trace # yes
1577
1578 bra.l _fpsp_done
1579
1580# is the ea mode pre-decrement of the stack pointer from supervisor mode?
1581# ("fmov.x fpm,-(a7)") if so,
1582fu_out_done_s:
1583 cmpi.b SPCOND_FLG(%a6),&mda7_flg
1584 bne.b fu_out_done_cont
1585
1586# the extended precision result is still in fp0. but, we need to save it
1587# somewhere on the stack until we can copy it to its final resting place.
1588# here, we're counting on the top of the stack to be the old place-holders
1589# for fp0/fp1 which have already been restored. that way, we can write
1590# over those destinations with the shifted stack frame.
1591 fmovm.x &0x80,FP_SRC(%a6) # put answer on stack
1592
1593 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1594 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1595 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1596
1597 mov.l (%a6),%a6 # restore frame pointer
1598
1599 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
1600 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
1601
1602# now, copy the result to the proper place on the stack
1603 mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
1604 mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
1605 mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
1606
1607 add.l &LOCAL_SIZE-0x8,%sp
1608
1609 btst &0x7,(%sp)
1610 bne.b fu_out_trace
1611
1612 bra.l _fpsp_done
1613
1614fu_out_ena:
1615 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
1616 bfffo %d0{&24:&8},%d0 # find highest priority exception
1617 bne.b fu_out_exc # there is at least one set
1618
1619# no exceptions were set.
1620# if a disabled overflow occurred and inexact was enabled but the result
1621# was exact, then a branch to _real_inex() is made.
1622 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1623 beq.w fu_out_done # no
1624
1625fu_out_ovflchk:
1626 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1627 beq.w fu_out_done # no
1628 bra.w fu_inex # yes
1629
1630#
1631# The fp move out that took the "Unimplemented Data Type" exception was
1632# being traced. Since the stack frames are similar, get the "current" PC
1633# from FPIAR and put it in the trace stack frame then jump to _real_trace().
1634#
1635# UNSUPP FRAME TRACE FRAME
1636# ***************** *****************
1637# * EA * * Current *
1638# * * * PC *
1639# ***************** *****************
1640# * 0x3 * 0x0dc * * 0x2 * 0x024 *
1641# ***************** *****************
1642# * Next * * Next *
1643# * PC * * PC *
1644# ***************** *****************
1645# * SR * * SR *
1646# ***************** *****************
1647#
1648fu_out_trace:
1649 mov.w &0x2024,0x6(%sp)
1650 fmov.l %fpiar,0x8(%sp)
1651 bra.l _real_trace
1652
1653# an exception occurred and that exception was enabled.
1654fu_out_exc:
1655 subi.l &24,%d0 # fix offset to be 0-8
1656
1657# we don't mess with the existing fsave frame. just re-insert it and
1658# jump to the "_real_{}()" handler...
1659 mov.w (tbl_fu_out.b,%pc,%d0.w*2),%d0
1660 jmp (tbl_fu_out.b,%pc,%d0.w*1)
1661
1662 swbeg &0x8
1663tbl_fu_out:
1664 short tbl_fu_out - tbl_fu_out # BSUN can't happen
1665 short tbl_fu_out - tbl_fu_out # SNAN can't happen
1666 short fu_operr - tbl_fu_out # OPERR
1667 short fu_ovfl - tbl_fu_out # OVFL
1668 short fu_unfl - tbl_fu_out # UNFL
1669 short tbl_fu_out - tbl_fu_out # DZ can't happen
1670 short fu_inex - tbl_fu_out # INEX2
1671 short tbl_fu_out - tbl_fu_out # INEX1 won't make it here
1672
1673# for snan,operr,ovfl,unfl, src op is still in FP_SRC so just
1674# frestore it.
1675fu_snan:
1676 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1677 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1678 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1679
1680 mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd8
1681 mov.w &0xe006,2+FP_SRC(%a6)
1682
1683 frestore FP_SRC(%a6)
1684
1685 unlk %a6
1686
1687
1688 bra.l _real_snan
1689
1690fu_operr:
1691 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1692 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1693 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1694
1695 mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0
1696 mov.w &0xe004,2+FP_SRC(%a6)
1697
1698 frestore FP_SRC(%a6)
1699
1700 unlk %a6
1701
1702
1703 bra.l _real_operr
1704
1705fu_ovfl:
1706 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1707
1708 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1709 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1710 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1711
1712 mov.w &0x30d4,EXC_VOFF(%a6) # vector offset = 0xd4
1713 mov.w &0xe005,2+FP_SRC(%a6)
1714
1715 frestore FP_SRC(%a6) # restore EXOP
1716
1717 unlk %a6
1718
1719 bra.l _real_ovfl
1720
1721# underflow can happen for extended precision. extended precision opclass
1722# three instruction exceptions don't update the stack pointer. so, if the
1723# exception occurred from user mode, then simply update a7 and exit normally.
1724# if the exception occurred from supervisor mode, check if
1725fu_unfl:
1726 mov.l EXC_A6(%a6),(%a6) # restore a6
1727
1728 btst &0x5,EXC_SR(%a6)
1729 bne.w fu_unfl_s
1730
1731 mov.l EXC_A7(%a6),%a0 # restore a7 whether we need
1732 mov.l %a0,%usp # to or not...
1733
1734fu_unfl_cont:
1735 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1736
1737 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1738 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1739 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1740
1741 mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc
1742 mov.w &0xe003,2+FP_SRC(%a6)
1743
1744 frestore FP_SRC(%a6) # restore EXOP
1745
1746 unlk %a6
1747
1748 bra.l _real_unfl
1749
1750fu_unfl_s:
1751 cmpi.b SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)?
1752 bne.b fu_unfl_cont
1753
1754# the extended precision result is still in fp0. but, we need to save it
1755# somewhere on the stack until we can copy it to its final resting place
1756# (where the exc frame is currently). make sure it's not at the top of the
1757# frame or it will get overwritten when the exc stack frame is shifted "down".
1758 fmovm.x &0x80,FP_SRC(%a6) # put answer on stack
1759 fmovm.x &0x40,FP_DST(%a6) # put EXOP on stack
1760
1761 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1762 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1763 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1764
1765 mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc
1766 mov.w &0xe003,2+FP_DST(%a6)
1767
1768 frestore FP_DST(%a6) # restore EXOP
1769
1770 mov.l (%a6),%a6 # restore frame pointer
1771
1772 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
1773 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
1774 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
1775
1776# now, copy the result to the proper place on the stack
1777 mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
1778 mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
1779 mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
1780
1781 add.l &LOCAL_SIZE-0x8,%sp
1782
1783 bra.l _real_unfl
1784
1785# fmove in and out enter here.
1786fu_inex:
1787 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1788
1789 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1790 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1791 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1792
1793 mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4
1794 mov.w &0xe001,2+FP_SRC(%a6)
1795
1796 frestore FP_SRC(%a6) # restore EXOP
1797
1798 unlk %a6
1799
1800
1801 bra.l _real_inex
1802
1803#########################################################################
1804#########################################################################
1805fu_in_pack:
1806
1807
1808# I'm not sure at this point what FPSR bits are valid for this instruction.
1809# so, since the emulation routines re-create them anyways, zero exception field
1810 andi.l &0x0ff00ff,USER_FPSR(%a6) # zero exception field
1811
1812 fmov.l &0x0,%fpcr # zero current control regs
1813 fmov.l &0x0,%fpsr
1814
1815 bsr.l get_packed # fetch packed src operand
1816
1817 lea FP_SRC(%a6),%a0 # pass ptr to src
1818 bsr.l set_tag_x # set src optype tag
1819
1820 mov.b %d0,STAG(%a6) # save src optype tag
1821
1822 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1823
1824# bit five of the fp extension word separates the monadic and dyadic operations
1825# at this point
1826 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
1827 beq.b fu_extract_p # monadic
1828 cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
1829 beq.b fu_extract_p # yes, so it's monadic, too
1830
1831 bsr.l load_fpn2 # load dst into FP_DST
1832
1833 lea FP_DST(%a6),%a0 # pass: ptr to dst op
1834 bsr.l set_tag_x # tag the operand type
1835 cmpi.b %d0,&UNNORM # is operand an UNNORM?
1836 bne.b fu_op2_done_p # no
1837 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1838fu_op2_done_p:
1839 mov.b %d0,DTAG(%a6) # save dst optype tag
1840
1841fu_extract_p:
1842 clr.l %d0
1843 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1844
1845 bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1846
1847 lea FP_SRC(%a6),%a0
1848 lea FP_DST(%a6),%a1
1849
1850 mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1851 jsr (tbl_unsupp.l,%pc,%d1.l*1)
1852
1853#
1854# Exceptions in order of precedence:
1855# BSUN : none
1856# SNAN : all dyadic ops
1857# OPERR : fsqrt(-NORM)
1858# OVFL : all except ftst,fcmp
1859# UNFL : all except ftst,fcmp
1860# DZ : fdiv
1861# INEX2 : all except ftst,fcmp
1862# INEX1 : all
1863#
1864
1865# we determine the highest priority exception(if any) set by the
1866# emulation routine that has also been enabled by the user.
1867 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
1868 bne.w fu_in_ena_p # some are enabled
1869
1870fu_in_cont_p:
1871# fcmp and ftst do not store any result.
1872 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
1873 andi.b &0x38,%d0 # extract bits 3-5
1874 cmpi.b %d0,&0x38 # is instr fcmp or ftst?
1875 beq.b fu_in_exit_p # yes
1876
1877 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1878 bsr.l store_fpreg # store the result
1879
1880fu_in_exit_p:
1881
1882 btst &0x5,EXC_SR(%a6) # user or supervisor?
1883 bne.w fu_in_exit_s_p # supervisor
1884
1885 mov.l EXC_A7(%a6),%a0 # update user a7
1886 mov.l %a0,%usp
1887
1888fu_in_exit_cont_p:
1889 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1890 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1891 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1892
1893 unlk %a6 # unravel stack frame
1894
1895 btst &0x7,(%sp) # is trace on?
1896 bne.w fu_trace_p # yes
1897
1898 bra.l _fpsp_done # exit to os
1899
1900# the exception occurred in supervisor mode. check to see if the
1901# addressing mode was (a7)+. if so, we'll need to shift the
1902# stack frame "up".
1903fu_in_exit_s_p:
1904 btst &mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+
1905 beq.b fu_in_exit_cont_p # no
1906
1907 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1908 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1909 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1910
1911 unlk %a6 # unravel stack frame
1912
1913# shift the stack frame "up". we don't really care about the <ea> field.
1914 mov.l 0x4(%sp),0x10(%sp)
1915 mov.l 0x0(%sp),0xc(%sp)
1916 add.l &0xc,%sp
1917
1918 btst &0x7,(%sp) # is trace on?
1919 bne.w fu_trace_p # yes
1920
1921 bra.l _fpsp_done # exit to os
1922
1923fu_in_ena_p:
1924 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled & set
1925 bfffo %d0{&24:&8},%d0 # find highest priority exception
1926 bne.b fu_in_exc_p # at least one was set
1927
1928#
1929# No exceptions occurred that were also enabled. Now:
1930#
1931# if (OVFL && ovfl_disabled && inexact_enabled) {
1932# branch to _real_inex() (even if the result was exact!);
1933# } else {
1934# save the result in the proper fp reg (unless the op is fcmp or ftst);
1935# return;
1936# }
1937#
1938 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1939 beq.w fu_in_cont_p # no
1940
1941fu_in_ovflchk_p:
1942 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1943 beq.w fu_in_cont_p # no
1944 bra.w fu_in_exc_ovfl_p # do _real_inex() now
1945
1946#
1947# An exception occurred and that exception was enabled:
1948#
1949# shift enabled exception field into lo byte of d0;
1950# if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1951# ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1952# /*
1953# * this is the case where we must call _real_inex() now or else
1954# * there will be no other way to pass it the exceptional operand
1955# */
1956# call _real_inex();
1957# } else {
1958# restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1959# }
1960#
1961fu_in_exc_p:
1962 subi.l &24,%d0 # fix offset to be 0-8
1963 cmpi.b %d0,&0x6 # is exception INEX? (6 or 7)
1964 blt.b fu_in_exc_exit_p # no
1965
1966# the enabled exception was inexact
1967 btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1968 bne.w fu_in_exc_unfl_p # yes
1969 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1970 bne.w fu_in_exc_ovfl_p # yes
1971
1972# here, we insert the correct fsave status value into the fsave frame for the
1973# corresponding exception. the operand in the fsave frame should be the original
1974# src operand.
1975# as a reminder for future predicted pain and agony, we are passing in fsave the
1976# "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs.
1977# this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!!
1978fu_in_exc_exit_p:
1979 btst &0x5,EXC_SR(%a6) # user or supervisor?
1980 bne.w fu_in_exc_exit_s_p # supervisor
1981
1982 mov.l EXC_A7(%a6),%a0 # update user a7
1983 mov.l %a0,%usp
1984
1985fu_in_exc_exit_cont_p:
1986 mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
1987
1988 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1989 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1990 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1991
1992 frestore FP_SRC(%a6) # restore src op
1993
1994 unlk %a6
1995
1996 btst &0x7,(%sp) # is trace enabled?
1997 bne.w fu_trace_p # yes
1998
1999 bra.l _fpsp_done
2000
2001tbl_except_p:
2002 short 0xe000,0xe006,0xe004,0xe005
2003 short 0xe003,0xe002,0xe001,0xe001
2004
2005fu_in_exc_ovfl_p:
2006 mov.w &0x3,%d0
2007 bra.w fu_in_exc_exit_p
2008
2009fu_in_exc_unfl_p:
2010 mov.w &0x4,%d0
2011 bra.w fu_in_exc_exit_p
2012
2013fu_in_exc_exit_s_p:
2014 btst &mia7_bit,SPCOND_FLG(%a6)
2015 beq.b fu_in_exc_exit_cont_p
2016
2017 mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
2018
2019 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2020 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2021 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2022
2023 frestore FP_SRC(%a6) # restore src op
2024
2025 unlk %a6 # unravel stack frame
2026
2027# shift stack frame "up". who cares about <ea> field.
2028 mov.l 0x4(%sp),0x10(%sp)
2029 mov.l 0x0(%sp),0xc(%sp)
2030 add.l &0xc,%sp
2031
2032 btst &0x7,(%sp) # is trace on?
2033 bne.b fu_trace_p # yes
2034
2035 bra.l _fpsp_done # exit to os
2036
2037#
2038# The opclass two PACKED instruction that took an "Unimplemented Data Type"
2039# exception was being traced. Make the "current" PC the FPIAR and put it in the
2040# trace stack frame then jump to _real_trace().
2041#
2042# UNSUPP FRAME TRACE FRAME
2043# ***************** *****************
2044# * EA * * Current *
2045# * * * PC *
2046# ***************** *****************
2047# * 0x2 * 0x0dc * * 0x2 * 0x024 *
2048# ***************** *****************
2049# * Next * * Next *
2050# * PC * * PC *
2051# ***************** *****************
2052# * SR * * SR *
2053# ***************** *****************
2054fu_trace_p:
2055 mov.w &0x2024,0x6(%sp)
2056 fmov.l %fpiar,0x8(%sp)
2057
2058 bra.l _real_trace
2059
2060#########################################################
2061#########################################################
2062fu_out_pack:
2063
2064
2065# I'm not sure at this point what FPSR bits are valid for this instruction.
2066# so, since the emulation routines re-create them anyways, zero exception field.
2067# fmove out doesn't affect ccodes.
2068 and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
2069
2070 fmov.l &0x0,%fpcr # zero current control regs
2071 fmov.l &0x0,%fpsr
2072
2073 bfextu EXC_CMDREG(%a6){&6:&3},%d0
2074 bsr.l load_fpn1
2075
2076# unlike other opclass 3, unimplemented data type exceptions, packed must be
2077# able to detect all operand types.
2078 lea FP_SRC(%a6),%a0
2079 bsr.l set_tag_x # tag the operand type
2080 cmpi.b %d0,&UNNORM # is operand an UNNORM?
2081 bne.b fu_op2_p # no
2082 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
2083
2084fu_op2_p:
2085 mov.b %d0,STAG(%a6) # save src optype tag
2086
2087 clr.l %d0
2088 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
2089
2090 lea FP_SRC(%a6),%a0 # pass ptr to src operand
2091
2092 mov.l (%a6),EXC_A6(%a6) # in case a6 changes
2093 bsr.l fout # call fmove out routine
2094
2095# Exceptions in order of precedence:
2096# BSUN : no
2097# SNAN : yes
2098# OPERR : if ((k_factor > +17) || (dec. exp exceeds 3 digits))
2099# OVFL : no
2100# UNFL : no
2101# DZ : no
2102# INEX2 : yes
2103# INEX1 : no
2104
2105# determine the highest priority exception(if any) set by the
2106# emulation routine that has also been enabled by the user.
2107 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
2108 bne.w fu_out_ena_p # some are enabled
2109
2110fu_out_exit_p:
2111 mov.l EXC_A6(%a6),(%a6) # restore a6
2112
2113 btst &0x5,EXC_SR(%a6) # user or supervisor?
2114 bne.b fu_out_exit_s_p # supervisor
2115
2116 mov.l EXC_A7(%a6),%a0 # update user a7
2117 mov.l %a0,%usp
2118
2119fu_out_exit_cont_p:
2120 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2121 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2122 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2123
2124 unlk %a6 # unravel stack frame
2125
2126 btst &0x7,(%sp) # is trace on?
2127 bne.w fu_trace_p # yes
2128
2129 bra.l _fpsp_done # exit to os
2130
2131# the exception occurred in supervisor mode. check to see if the
2132# addressing mode was -(a7). if so, we'll need to shift the
2133# stack frame "down".
2134fu_out_exit_s_p:
2135 btst &mda7_bit,SPCOND_FLG(%a6) # was ea mode -(a7)
2136 beq.b fu_out_exit_cont_p # no
2137
2138 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2139 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2140 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2141
2142 mov.l (%a6),%a6 # restore frame pointer
2143
2144 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2145 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2146
2147# now, copy the result to the proper place on the stack
2148 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
2149 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
2150 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
2151
2152 add.l &LOCAL_SIZE-0x8,%sp
2153
2154 btst &0x7,(%sp)
2155 bne.w fu_trace_p
2156
2157 bra.l _fpsp_done
2158
2159fu_out_ena_p:
2160 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
2161 bfffo %d0{&24:&8},%d0 # find highest priority exception
2162 beq.w fu_out_exit_p
2163
2164 mov.l EXC_A6(%a6),(%a6) # restore a6
2165
2166# an exception occurred and that exception was enabled.
2167# the only exception possible on packed move out are INEX, OPERR, and SNAN.
2168fu_out_exc_p:
2169 cmpi.b %d0,&0x1a
2170 bgt.w fu_inex_p2
2171 beq.w fu_operr_p
2172
2173fu_snan_p:
2174 btst &0x5,EXC_SR(%a6)
2175 bne.b fu_snan_s_p
2176
2177 mov.l EXC_A7(%a6),%a0
2178 mov.l %a0,%usp
2179 bra.w fu_snan
2180
2181fu_snan_s_p:
2182 cmpi.b SPCOND_FLG(%a6),&mda7_flg
2183 bne.w fu_snan
2184
2185# the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2186# the strategy is to move the exception frame "down" 12 bytes. then, we
2187# can store the default result where the exception frame was.
2188 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2189 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2190 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2191
2192 mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd0
2193 mov.w &0xe006,2+FP_SRC(%a6) # set fsave status
2194
2195 frestore FP_SRC(%a6) # restore src operand
2196
2197 mov.l (%a6),%a6 # restore frame pointer
2198
2199 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2200 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2201 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2202
2203# now, we copy the default result to its proper location
2204 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2205 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2206 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2207
2208 add.l &LOCAL_SIZE-0x8,%sp
2209
2210
2211 bra.l _real_snan
2212
2213fu_operr_p:
2214 btst &0x5,EXC_SR(%a6)
2215 bne.w fu_operr_p_s
2216
2217 mov.l EXC_A7(%a6),%a0
2218 mov.l %a0,%usp
2219 bra.w fu_operr
2220
2221fu_operr_p_s:
2222 cmpi.b SPCOND_FLG(%a6),&mda7_flg
2223 bne.w fu_operr
2224
2225# the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2226# the strategy is to move the exception frame "down" 12 bytes. then, we
2227# can store the default result where the exception frame was.
2228 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2229 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2230 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2231
2232 mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0
2233 mov.w &0xe004,2+FP_SRC(%a6) # set fsave status
2234
2235 frestore FP_SRC(%a6) # restore src operand
2236
2237 mov.l (%a6),%a6 # restore frame pointer
2238
2239 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2240 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2241 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2242
2243# now, we copy the default result to its proper location
2244 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2245 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2246 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2247
2248 add.l &LOCAL_SIZE-0x8,%sp
2249
2250
2251 bra.l _real_operr
2252
2253fu_inex_p2:
2254 btst &0x5,EXC_SR(%a6)
2255 bne.w fu_inex_s_p2
2256
2257 mov.l EXC_A7(%a6),%a0
2258 mov.l %a0,%usp
2259 bra.w fu_inex
2260
2261fu_inex_s_p2:
2262 cmpi.b SPCOND_FLG(%a6),&mda7_flg
2263 bne.w fu_inex
2264
2265# the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2266# the strategy is to move the exception frame "down" 12 bytes. then, we
2267# can store the default result where the exception frame was.
2268 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2269 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2270 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2271
2272 mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4
2273 mov.w &0xe001,2+FP_SRC(%a6) # set fsave status
2274
2275 frestore FP_SRC(%a6) # restore src operand
2276
2277 mov.l (%a6),%a6 # restore frame pointer
2278
2279 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2280 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2281 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2282
2283# now, we copy the default result to its proper location
2284 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2285 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2286 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2287
2288 add.l &LOCAL_SIZE-0x8,%sp
2289
2290
2291 bra.l _real_inex
2292
2293#########################################################################
2294
2295#
2296# if we're stuffing a source operand back into an fsave frame then we
2297# have to make sure that for single or double source operands that the
2298# format stuffed is as weird as the hardware usually makes it.
2299#
2300 global funimp_skew
2301funimp_skew:
2302 bfextu EXC_EXTWORD(%a6){&3:&3},%d0 # extract src specifier
2303 cmpi.b %d0,&0x1 # was src sgl?
2304 beq.b funimp_skew_sgl # yes
2305 cmpi.b %d0,&0x5 # was src dbl?
2306 beq.b funimp_skew_dbl # yes
2307 rts
2308
2309funimp_skew_sgl:
2310 mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent
2311 andi.w &0x7fff,%d0 # strip sign
2312 beq.b funimp_skew_sgl_not
2313 cmpi.w %d0,&0x3f80
2314 bgt.b funimp_skew_sgl_not
2315 neg.w %d0 # make exponent negative
2316 addi.w &0x3f81,%d0 # find amt to shift
2317 mov.l FP_SRC_HI(%a6),%d1 # fetch DENORM hi(man)
2318 lsr.l %d0,%d1 # shift it
2319 bset &31,%d1 # set j-bit
2320 mov.l %d1,FP_SRC_HI(%a6) # insert new hi(man)
2321 andi.w &0x8000,FP_SRC_EX(%a6) # clear old exponent
2322 ori.w &0x3f80,FP_SRC_EX(%a6) # insert new "skewed" exponent
2323funimp_skew_sgl_not:
2324 rts
2325
2326funimp_skew_dbl:
2327 mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent
2328 andi.w &0x7fff,%d0 # strip sign
2329 beq.b funimp_skew_dbl_not
2330 cmpi.w %d0,&0x3c00
2331 bgt.b funimp_skew_dbl_not
2332
2333 tst.b FP_SRC_EX(%a6) # make "internal format"
2334 smi.b 0x2+FP_SRC(%a6)
2335 mov.w %d0,FP_SRC_EX(%a6) # insert exponent with cleared sign
2336 clr.l %d0 # clear g,r,s
2337 lea FP_SRC(%a6),%a0 # pass ptr to src op
2338 mov.w &0x3c01,%d1 # pass denorm threshold
2339 bsr.l dnrm_lp # denorm it
2340 mov.w &0x3c00,%d0 # new exponent
2341 tst.b 0x2+FP_SRC(%a6) # is sign set?
2342 beq.b fss_dbl_denorm_done # no
2343 bset &15,%d0 # set sign
2344fss_dbl_denorm_done:
2345 bset &0x7,FP_SRC_HI(%a6) # set j-bit
2346 mov.w %d0,FP_SRC_EX(%a6) # insert new exponent
2347funimp_skew_dbl_not:
2348 rts
2349
2350#########################################################################
2351 global _mem_write2
2352_mem_write2:
2353 btst &0x5,EXC_SR(%a6)
2354 beq.l _dmem_write
2355 mov.l 0x0(%a0),FP_DST_EX(%a6)
2356 mov.l 0x4(%a0),FP_DST_HI(%a6)
2357 mov.l 0x8(%a0),FP_DST_LO(%a6)
2358 clr.l %d1
2359 rts
2360
2361#########################################################################
2362# XDEF **************************************************************** #
2363# _fpsp_effadd(): 060FPSP entry point for FP "Unimplemented #
2364# effective address" exception. #
2365# #
2366# This handler should be the first code executed upon taking the #
2367# FP Unimplemented Effective Address exception in an operating #
2368# system. #
2369# #
2370# XREF **************************************************************** #
2371# _imem_read_long() - read instruction longword #
2372# fix_skewed_ops() - adjust src operand in fsave frame #
2373# set_tag_x() - determine optype of src/dst operands #
2374# store_fpreg() - store opclass 0 or 2 result to FP regfile #
2375# unnorm_fix() - change UNNORM operands to NORM or ZERO #
2376# load_fpn2() - load dst operand from FP regfile #
2377# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
2378# decbin() - convert packed data to FP binary data #
2379# _real_fpu_disabled() - "callout" for "FPU disabled" exception #
2380# _real_access() - "callout" for access error exception #
2381# _mem_read() - read extended immediate operand from memory #
2382# _fpsp_done() - "callout" for exit; work all done #
2383# _real_trace() - "callout" for Trace enabled exception #
2384# fmovm_dynamic() - emulate dynamic fmovm instruction #
2385# fmovm_ctrl() - emulate fmovm control instruction #
2386# #
2387# INPUT *************************************************************** #
2388# - The system stack contains the "Unimplemented <ea>" stk frame #
2389# #
2390# OUTPUT ************************************************************** #
2391# If access error: #
2392# - The system stack is changed to an access error stack frame #
2393# If FPU disabled: #
2394# - The system stack is changed to an FPU disabled stack frame #
2395# If Trace exception enabled: #
2396# - The system stack is changed to a Trace exception stack frame #
2397# Else: (normal case) #
2398# - None (correct result has been stored as appropriate) #
2399# #
2400# ALGORITHM *********************************************************** #
2401# This exception handles 3 types of operations: #
2402# (1) FP Instructions using extended precision or packed immediate #
2403# addressing mode. #
2404# (2) The "fmovm.x" instruction w/ dynamic register specification. #
2405# (3) The "fmovm.l" instruction w/ 2 or 3 control registers. #
2406# #
2407# For immediate data operations, the data is read in w/ a #
2408# _mem_read() "callout", converted to FP binary (if packed), and used #
2409# as the source operand to the instruction specified by the instruction #
2410# word. If no FP exception should be reported ads a result of the #
2411# emulation, then the result is stored to the destination register and #
2412# the handler exits through _fpsp_done(). If an enabled exc has been #
2413# signalled as a result of emulation, then an fsave state frame #
2414# corresponding to the FP exception type must be entered into the 060 #
2415# FPU before exiting. In either the enabled or disabled cases, we #
2416# must also check if a Trace exception is pending, in which case, we #
2417# must create a Trace exception stack frame from the current exception #
2418# stack frame. If no Trace is pending, we simply exit through #
2419# _fpsp_done(). #
2420# For "fmovm.x", call the routine fmovm_dynamic() which will #
2421# decode and emulate the instruction. No FP exceptions can be pending #
2422# as a result of this operation emulation. A Trace exception can be #
2423# pending, though, which means the current stack frame must be changed #
2424# to a Trace stack frame and an exit made through _real_trace(). #
2425# For the case of "fmovm.x Dn,-(a7)", where the offending instruction #
2426# was executed from supervisor mode, this handler must store the FP #
2427# register file values to the system stack by itself since #
2428# fmovm_dynamic() can't handle this. A normal exit is made through #
2429# fpsp_done(). #
2430# For "fmovm.l", fmovm_ctrl() is used to emulate the instruction. #
2431# Again, a Trace exception may be pending and an exit made through #
2432# _real_trace(). Else, a normal exit is made through _fpsp_done(). #
2433# #
2434# Before any of the above is attempted, it must be checked to #
2435# see if the FPU is disabled. Since the "Unimp <ea>" exception is taken #
2436# before the "FPU disabled" exception, but the "FPU disabled" exception #
2437# has higher priority, we check the disabled bit in the PCR. If set, #
2438# then we must create an 8 word "FPU disabled" exception stack frame #
2439# from the current 4 word exception stack frame. This includes #
2440# reproducing the effective address of the instruction to put on the #
2441# new stack frame. #
2442# #
2443# In the process of all emulation work, if a _mem_read() #
2444# "callout" returns a failing result indicating an access error, then #
2445# we must create an access error stack frame from the current stack #
2446# frame. This information includes a faulting address and a fault- #
2447# status-longword. These are created within this handler. #
2448# #
2449#########################################################################
2450
2451 global _fpsp_effadd
2452_fpsp_effadd:
2453
2454# This exception type takes priority over the "Line F Emulator"
2455# exception. Therefore, the FPU could be disabled when entering here.
2456# So, we must check to see if it's disabled and handle that case separately.
2457 mov.l %d0,-(%sp) # save d0
2458 movc %pcr,%d0 # load proc cr
2459 btst &0x1,%d0 # is FPU disabled?
2460 bne.w iea_disabled # yes
2461 mov.l (%sp)+,%d0 # restore d0
2462
2463 link %a6,&-LOCAL_SIZE # init stack frame
2464
2465 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2466 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
2467 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
2468
2469# PC of instruction that took the exception is the PC in the frame
2470 mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
2471
2472 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
2473 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
2474 bsr.l _imem_read_long # fetch the instruction words
2475 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
2476
2477#########################################################################
2478
2479 tst.w %d0 # is operation fmovem?
2480 bmi.w iea_fmovm # yes
2481
2482#
2483# here, we will have:
2484# fabs fdabs fsabs facos fmod
2485# fadd fdadd fsadd fasin frem
2486# fcmp fatan fscale
2487# fdiv fddiv fsdiv fatanh fsin
2488# fint fcos fsincos
2489# fintrz fcosh fsinh
2490# fmove fdmove fsmove fetox ftan
2491# fmul fdmul fsmul fetoxm1 ftanh
2492# fneg fdneg fsneg fgetexp ftentox
2493# fsgldiv fgetman ftwotox
2494# fsglmul flog10
2495# fsqrt flog2
2496# fsub fdsub fssub flogn
2497# ftst flognp1
2498# which can all use f<op>.{x,p}
2499# so, now it's immediate data extended precision AND PACKED FORMAT!
2500#
2501iea_op:
2502 andi.l &0x00ff00ff,USER_FPSR(%a6)
2503
2504 btst &0xa,%d0 # is src fmt x or p?
2505 bne.b iea_op_pack # packed
2506
2507
2508 mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data>
2509 lea FP_SRC(%a6),%a1 # pass: ptr to super addr
2510 mov.l &0xc,%d0 # pass: 12 bytes
2511 bsr.l _imem_read # read extended immediate
2512
2513 tst.l %d1 # did ifetch fail?
2514 bne.w iea_iacc # yes
2515
2516 bra.b iea_op_setsrc
2517
2518iea_op_pack:
2519
2520 mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data>
2521 lea FP_SRC(%a6),%a1 # pass: ptr to super dst
2522 mov.l &0xc,%d0 # pass: 12 bytes
2523 bsr.l _imem_read # read packed operand
2524
2525 tst.l %d1 # did ifetch fail?
2526 bne.w iea_iacc # yes
2527
2528# The packed operand is an INF or a NAN if the exponent field is all ones.
2529 bfextu FP_SRC(%a6){&1:&15},%d0 # get exp
2530 cmpi.w %d0,&0x7fff # INF or NAN?
2531 beq.b iea_op_setsrc # operand is an INF or NAN
2532
2533# The packed operand is a zero if the mantissa is all zero, else it's
2534# a normal packed op.
2535 mov.b 3+FP_SRC(%a6),%d0 # get byte 4
2536 andi.b &0x0f,%d0 # clear all but last nybble
2537 bne.b iea_op_gp_not_spec # not a zero
2538 tst.l FP_SRC_HI(%a6) # is lw 2 zero?
2539 bne.b iea_op_gp_not_spec # not a zero
2540 tst.l FP_SRC_LO(%a6) # is lw 3 zero?
2541 beq.b iea_op_setsrc # operand is a ZERO
2542iea_op_gp_not_spec:
2543 lea FP_SRC(%a6),%a0 # pass: ptr to packed op
2544 bsr.l decbin # convert to extended
2545 fmovm.x &0x80,FP_SRC(%a6) # make this the srcop
2546
2547iea_op_setsrc:
2548 addi.l &0xc,EXC_EXTWPTR(%a6) # update extension word pointer
2549
2550# FP_SRC now holds the src operand.
2551 lea FP_SRC(%a6),%a0 # pass: ptr to src op
2552 bsr.l set_tag_x # tag the operand type
2553 mov.b %d0,STAG(%a6) # could be ANYTHING!!!
2554 cmpi.b %d0,&UNNORM # is operand an UNNORM?
2555 bne.b iea_op_getdst # no
2556 bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO
2557 mov.b %d0,STAG(%a6) # set new optype tag
2558iea_op_getdst:
2559 clr.b STORE_FLG(%a6) # clear "store result" boolean
2560
2561 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
2562 beq.b iea_op_extract # monadic
2563 btst &0x4,1+EXC_CMDREG(%a6) # is operation fsincos,ftst,fcmp?
2564 bne.b iea_op_spec # yes
2565
2566iea_op_loaddst:
2567 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
2568 bsr.l load_fpn2 # load dst operand
2569
2570 lea FP_DST(%a6),%a0 # pass: ptr to dst op
2571 bsr.l set_tag_x # tag the operand type
2572 mov.b %d0,DTAG(%a6) # could be ANYTHING!!!
2573 cmpi.b %d0,&UNNORM # is operand an UNNORM?
2574 bne.b iea_op_extract # no
2575 bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO
2576 mov.b %d0,DTAG(%a6) # set new optype tag
2577 bra.b iea_op_extract
2578
2579# the operation is fsincos, ftst, or fcmp. only fcmp is dyadic
2580iea_op_spec:
2581 btst &0x3,1+EXC_CMDREG(%a6) # is operation fsincos?
2582 beq.b iea_op_extract # yes
2583# now, we're left with ftst and fcmp. so, first let's tag them so that they don't
2584# store a result. then, only fcmp will branch back and pick up a dst operand.
2585 st STORE_FLG(%a6) # don't store a final result
2586 btst &0x1,1+EXC_CMDREG(%a6) # is operation fcmp?
2587 beq.b iea_op_loaddst # yes
2588
2589iea_op_extract:
2590 clr.l %d0
2591 mov.b FPCR_MODE(%a6),%d0 # pass: rnd mode,prec
2592
2593 mov.b 1+EXC_CMDREG(%a6),%d1
2594 andi.w &0x007f,%d1 # extract extension
2595
2596 fmov.l &0x0,%fpcr
2597 fmov.l &0x0,%fpsr
2598
2599 lea FP_SRC(%a6),%a0
2600 lea FP_DST(%a6),%a1
2601
2602 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
2603 jsr (tbl_unsupp.l,%pc,%d1.l*1)
2604
2605#
2606# Exceptions in order of precedence:
2607# BSUN : none
2608# SNAN : all operations
2609# OPERR : all reg-reg or mem-reg operations that can normally operr
2610# OVFL : same as OPERR
2611# UNFL : same as OPERR
2612# DZ : same as OPERR
2613# INEX2 : same as OPERR
2614# INEX1 : all packed immediate operations
2615#
2616
2617# we determine the highest priority exception(if any) set by the
2618# emulation routine that has also been enabled by the user.
2619 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
2620 bne.b iea_op_ena # some are enabled
2621
2622# now, we save the result, unless, of course, the operation was ftst or fcmp.
2623# these don't save results.
2624iea_op_save:
2625 tst.b STORE_FLG(%a6) # does this op store a result?
2626 bne.b iea_op_exit1 # exit with no frestore
2627
2628iea_op_store:
2629 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
2630 bsr.l store_fpreg # store the result
2631
2632iea_op_exit1:
2633 mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
2634 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
2635
2636 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2637 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2638 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2639
2640 unlk %a6 # unravel the frame
2641
2642 btst &0x7,(%sp) # is trace on?
2643 bne.w iea_op_trace # yes
2644
2645 bra.l _fpsp_done # exit to os
2646
2647iea_op_ena:
2648 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enable and set
2649 bfffo %d0{&24:&8},%d0 # find highest priority exception
2650 bne.b iea_op_exc # at least one was set
2651
2652# no exception occurred. now, did a disabled, exact overflow occur with inexact
2653# enabled? if so, then we have to stuff an overflow frame into the FPU.
2654 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
2655 beq.b iea_op_save
2656
2657iea_op_ovfl:
2658 btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
2659 beq.b iea_op_store # no
2660 bra.b iea_op_exc_ovfl # yes
2661
2662# an enabled exception occurred. we have to insert the exception type back into
2663# the machine.
2664iea_op_exc:
2665 subi.l &24,%d0 # fix offset to be 0-8
2666 cmpi.b %d0,&0x6 # is exception INEX?
2667 bne.b iea_op_exc_force # no
2668
2669# the enabled exception was inexact. so, if it occurs with an overflow
2670# or underflow that was disabled, then we have to force an overflow or
2671# underflow frame.
2672 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
2673 bne.b iea_op_exc_ovfl # yes
2674 btst &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
2675 bne.b iea_op_exc_unfl # yes
2676
2677iea_op_exc_force:
2678 mov.w (tbl_iea_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
2679 bra.b iea_op_exit2 # exit with frestore
2680
2681tbl_iea_except:
2682 short 0xe002, 0xe006, 0xe004, 0xe005
2683 short 0xe003, 0xe002, 0xe001, 0xe001
2684
2685iea_op_exc_ovfl:
2686 mov.w &0xe005,2+FP_SRC(%a6)
2687 bra.b iea_op_exit2
2688
2689iea_op_exc_unfl:
2690 mov.w &0xe003,2+FP_SRC(%a6)
2691
2692iea_op_exit2:
2693 mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
2694 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
2695
2696 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2697 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2698 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2699
2700 frestore FP_SRC(%a6) # restore exceptional state
2701
2702 unlk %a6 # unravel the frame
2703
2704 btst &0x7,(%sp) # is trace on?
2705 bne.b iea_op_trace # yes
2706
2707 bra.l _fpsp_done # exit to os
2708
2709#
2710# The opclass two instruction that took an "Unimplemented Effective Address"
2711# exception was being traced. Make the "current" PC the FPIAR and put it in
2712# the trace stack frame then jump to _real_trace().
2713#
2714# UNIMP EA FRAME TRACE FRAME
2715# ***************** *****************
2716# * 0x0 * 0x0f0 * * Current *
2717# ***************** * PC *
2718# * Current * *****************
2719# * PC * * 0x2 * 0x024 *
2720# ***************** *****************
2721# * SR * * Next *
2722# ***************** * PC *
2723# *****************
2724# * SR *
2725# *****************
2726iea_op_trace:
2727 mov.l (%sp),-(%sp) # shift stack frame "down"
2728 mov.w 0x8(%sp),0x4(%sp)
2729 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
2730 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
2731
2732 bra.l _real_trace
2733
2734#########################################################################
2735iea_fmovm:
2736 btst &14,%d0 # ctrl or data reg
2737 beq.w iea_fmovm_ctrl
2738
2739iea_fmovm_data:
2740
2741 btst &0x5,EXC_SR(%a6) # user or supervisor mode
2742 bne.b iea_fmovm_data_s
2743
2744iea_fmovm_data_u:
2745 mov.l %usp,%a0
2746 mov.l %a0,EXC_A7(%a6) # store current a7
2747 bsr.l fmovm_dynamic # do dynamic fmovm
2748 mov.l EXC_A7(%a6),%a0 # load possibly new a7
2749 mov.l %a0,%usp # update usp
2750 bra.w iea_fmovm_exit
2751
2752iea_fmovm_data_s:
2753 clr.b SPCOND_FLG(%a6)
2754 lea 0x2+EXC_VOFF(%a6),%a0
2755 mov.l %a0,EXC_A7(%a6)
2756 bsr.l fmovm_dynamic # do dynamic fmovm
2757
2758 cmpi.b SPCOND_FLG(%a6),&mda7_flg
2759 beq.w iea_fmovm_data_predec
2760 cmpi.b SPCOND_FLG(%a6),&mia7_flg
2761 bne.w iea_fmovm_exit
2762
2763# right now, d0 = the size.
2764# the data has been fetched from the supervisor stack, but we have not
2765# incremented the stack pointer by the appropriate number of bytes.
2766# do it here.
2767iea_fmovm_data_postinc:
2768 btst &0x7,EXC_SR(%a6)
2769 bne.b iea_fmovm_data_pi_trace
2770
2771 mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0)
2772 mov.l EXC_EXTWPTR(%a6),(EXC_PC,%a6,%d0)
2773 mov.w &0x00f0,(EXC_VOFF,%a6,%d0)
2774
2775 lea (EXC_SR,%a6,%d0),%a0
2776 mov.l %a0,EXC_SR(%a6)
2777
2778 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2779 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2780 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2781
2782 unlk %a6
2783 mov.l (%sp)+,%sp
2784 bra.l _fpsp_done
2785
2786iea_fmovm_data_pi_trace:
2787 mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
2788 mov.l EXC_EXTWPTR(%a6),(EXC_PC-0x4,%a6,%d0)
2789 mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0)
2790 mov.l EXC_PC(%a6),(EXC_VOFF+0x2-0x4,%a6,%d0)
2791
2792 lea (EXC_SR-0x4,%a6,%d0),%a0
2793 mov.l %a0,EXC_SR(%a6)
2794
2795 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2796 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2797 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2798
2799 unlk %a6
2800 mov.l (%sp)+,%sp
2801 bra.l _real_trace
2802
2803# right now, d1 = size and d0 = the strg.
2804iea_fmovm_data_predec:
2805 mov.b %d1,EXC_VOFF(%a6) # store strg
2806 mov.b %d0,0x1+EXC_VOFF(%a6) # store size
2807
2808 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2809 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2810 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2811
2812 mov.l (%a6),-(%sp) # make a copy of a6
2813 mov.l %d0,-(%sp) # save d0
2814 mov.l %d1,-(%sp) # save d1
2815 mov.l EXC_EXTWPTR(%a6),-(%sp) # make a copy of Next PC
2816
2817 clr.l %d0
2818 mov.b 0x1+EXC_VOFF(%a6),%d0 # fetch size
2819 neg.l %d0 # get negative of size
2820
2821 btst &0x7,EXC_SR(%a6) # is trace enabled?
2822 beq.b iea_fmovm_data_p2
2823
2824 mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
2825 mov.l EXC_PC(%a6),(EXC_VOFF-0x2,%a6,%d0)
2826 mov.l (%sp)+,(EXC_PC-0x4,%a6,%d0)
2827 mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0)
2828
2829 pea (%a6,%d0) # create final sp
2830 bra.b iea_fmovm_data_p3
2831
2832iea_fmovm_data_p2:
2833 mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0)
2834 mov.l (%sp)+,(EXC_PC,%a6,%d0)
2835 mov.w &0x00f0,(EXC_VOFF,%a6,%d0)
2836
2837 pea (0x4,%a6,%d0) # create final sp
2838
2839iea_fmovm_data_p3:
2840 clr.l %d1
2841 mov.b EXC_VOFF(%a6),%d1 # fetch strg
2842
2843 tst.b %d1
2844 bpl.b fm_1
2845 fmovm.x &0x80,(0x4+0x8,%a6,%d0)
2846 addi.l &0xc,%d0
2847fm_1:
2848 lsl.b &0x1,%d1
2849 bpl.b fm_2
2850 fmovm.x &0x40,(0x4+0x8,%a6,%d0)
2851 addi.l &0xc,%d0
2852fm_2:
2853 lsl.b &0x1,%d1
2854 bpl.b fm_3
2855 fmovm.x &0x20,(0x4+0x8,%a6,%d0)
2856 addi.l &0xc,%d0
2857fm_3:
2858 lsl.b &0x1,%d1
2859 bpl.b fm_4
2860 fmovm.x &0x10,(0x4+0x8,%a6,%d0)
2861 addi.l &0xc,%d0
2862fm_4:
2863 lsl.b &0x1,%d1
2864 bpl.b fm_5
2865 fmovm.x &0x08,(0x4+0x8,%a6,%d0)
2866 addi.l &0xc,%d0
2867fm_5:
2868 lsl.b &0x1,%d1
2869 bpl.b fm_6
2870 fmovm.x &0x04,(0x4+0x8,%a6,%d0)
2871 addi.l &0xc,%d0
2872fm_6:
2873 lsl.b &0x1,%d1
2874 bpl.b fm_7
2875 fmovm.x &0x02,(0x4+0x8,%a6,%d0)
2876 addi.l &0xc,%d0
2877fm_7:
2878 lsl.b &0x1,%d1
2879 bpl.b fm_end
2880 fmovm.x &0x01,(0x4+0x8,%a6,%d0)
2881fm_end:
2882 mov.l 0x4(%sp),%d1
2883 mov.l 0x8(%sp),%d0
2884 mov.l 0xc(%sp),%a6
2885 mov.l (%sp)+,%sp
2886
2887 btst &0x7,(%sp) # is trace enabled?
2888 beq.l _fpsp_done
2889 bra.l _real_trace
2890
2891#########################################################################
2892iea_fmovm_ctrl:
2893
2894 bsr.l fmovm_ctrl # load ctrl regs
2895
2896iea_fmovm_exit:
2897 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2898 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2899 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2900
2901 btst &0x7,EXC_SR(%a6) # is trace on?
2902 bne.b iea_fmovm_trace # yes
2903
2904 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set Next PC
2905
2906 unlk %a6 # unravel the frame
2907
2908 bra.l _fpsp_done # exit to os
2909
2910#
2911# The control reg instruction that took an "Unimplemented Effective Address"
2912# exception was being traced. The "Current PC" for the trace frame is the
2913# PC stacked for Unimp EA. The "Next PC" is in EXC_EXTWPTR.
2914# After fixing the stack frame, jump to _real_trace().
2915#
2916# UNIMP EA FRAME TRACE FRAME
2917# ***************** *****************
2918# * 0x0 * 0x0f0 * * Current *
2919# ***************** * PC *
2920# * Current * *****************
2921# * PC * * 0x2 * 0x024 *
2922# ***************** *****************
2923# * SR * * Next *
2924# ***************** * PC *
2925# *****************
2926# * SR *
2927# *****************
2928# this ain't a pretty solution, but it works:
2929# -restore a6 (not with unlk)
2930# -shift stack frame down over where old a6 used to be
2931# -add LOCAL_SIZE to stack pointer
2932iea_fmovm_trace:
2933 mov.l (%a6),%a6 # restore frame pointer
2934 mov.w EXC_SR+LOCAL_SIZE(%sp),0x0+LOCAL_SIZE(%sp)
2935 mov.l EXC_PC+LOCAL_SIZE(%sp),0x8+LOCAL_SIZE(%sp)
2936 mov.l EXC_EXTWPTR+LOCAL_SIZE(%sp),0x2+LOCAL_SIZE(%sp)
2937 mov.w &0x2024,0x6+LOCAL_SIZE(%sp) # stk fmt = 0x2; voff = 0x024
2938 add.l &LOCAL_SIZE,%sp # clear stack frame
2939
2940 bra.l _real_trace
2941
2942#########################################################################
2943# The FPU is disabled and so we should really have taken the "Line
2944# F Emulator" exception. So, here we create an 8-word stack frame
2945# from our 4-word stack frame. This means we must calculate the length
2946# the faulting instruction to get the "next PC". This is trivial for
2947# immediate operands but requires some extra work for fmovm dynamic
2948# which can use most addressing modes.
2949iea_disabled:
2950 mov.l (%sp)+,%d0 # restore d0
2951
2952 link %a6,&-LOCAL_SIZE # init stack frame
2953
2954 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2955
2956# PC of instruction that took the exception is the PC in the frame
2957 mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
2958 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
2959 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
2960 bsr.l _imem_read_long # fetch the instruction words
2961 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
2962
2963 tst.w %d0 # is instr fmovm?
2964 bmi.b iea_dis_fmovm # yes
2965# instruction is using an extended precision immediate operand. therefore,
2966# the total instruction length is 16 bytes.
2967iea_dis_immed:
2968 mov.l &0x10,%d0 # 16 bytes of instruction
2969 bra.b iea_dis_cont
2970iea_dis_fmovm:
2971 btst &0xe,%d0 # is instr fmovm ctrl
2972 bne.b iea_dis_fmovm_data # no
2973# the instruction is a fmovm.l with 2 or 3 registers.
2974 bfextu %d0{&19:&3},%d1
2975 mov.l &0xc,%d0
2976 cmpi.b %d1,&0x7 # move all regs?
2977 bne.b iea_dis_cont
2978 addq.l &0x4,%d0
2979 bra.b iea_dis_cont
2980# the instruction is an fmovm.x dynamic which can use many addressing
2981# modes and thus can have several different total instruction lengths.
2982# call fmovm_calc_ea which will go through the ea calc process and,
2983# as a by-product, will tell us how long the instruction is.
2984iea_dis_fmovm_data:
2985 clr.l %d0
2986 bsr.l fmovm_calc_ea
2987 mov.l EXC_EXTWPTR(%a6),%d0
2988 sub.l EXC_PC(%a6),%d0
2989iea_dis_cont:
2990 mov.w %d0,EXC_VOFF(%a6) # store stack shift value
2991
2992 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2993
2994 unlk %a6
2995
2996# here, we actually create the 8-word frame from the 4-word frame,
2997# with the "next PC" as additional info.
2998# the <ea> field is let as undefined.
2999 subq.l &0x8,%sp # make room for new stack
3000 mov.l %d0,-(%sp) # save d0
3001 mov.w 0xc(%sp),0x4(%sp) # move SR
3002 mov.l 0xe(%sp),0x6(%sp) # move Current PC
3003 clr.l %d0
3004 mov.w 0x12(%sp),%d0
3005 mov.l 0x6(%sp),0x10(%sp) # move Current PC
3006 add.l %d0,0x6(%sp) # make Next PC
3007 mov.w &0x402c,0xa(%sp) # insert offset,frame format
3008 mov.l (%sp)+,%d0 # restore d0
3009
3010 bra.l _real_fpu_disabled
3011
3012##########
3013
3014iea_iacc:
3015 movc %pcr,%d0
3016 btst &0x1,%d0
3017 bne.b iea_iacc_cont
3018 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3019 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack
3020iea_iacc_cont:
3021 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3022
3023 unlk %a6
3024
3025 subq.w &0x8,%sp # make stack frame bigger
3026 mov.l 0x8(%sp),(%sp) # store SR,hi(PC)
3027 mov.w 0xc(%sp),0x4(%sp) # store lo(PC)
3028 mov.w &0x4008,0x6(%sp) # store voff
3029 mov.l 0x2(%sp),0x8(%sp) # store ea
3030 mov.l &0x09428001,0xc(%sp) # store fslw
3031
3032iea_acc_done:
3033 btst &0x5,(%sp) # user or supervisor mode?
3034 beq.b iea_acc_done2 # user
3035 bset &0x2,0xd(%sp) # set supervisor TM bit
3036
3037iea_acc_done2:
3038 bra.l _real_access
3039
3040iea_dacc:
3041 lea -LOCAL_SIZE(%a6),%sp
3042
3043 movc %pcr,%d1
3044 btst &0x1,%d1
3045 bne.b iea_dacc_cont
3046 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack
3047 fmovm.l LOCAL_SIZE+USER_FPCR(%sp),%fpcr,%fpsr,%fpiar # restore ctrl regs
3048iea_dacc_cont:
3049 mov.l (%a6),%a6
3050
3051 mov.l 0x4+LOCAL_SIZE(%sp),-0x8+0x4+LOCAL_SIZE(%sp)
3052 mov.w 0x8+LOCAL_SIZE(%sp),-0x8+0x8+LOCAL_SIZE(%sp)
3053 mov.w &0x4008,-0x8+0xa+LOCAL_SIZE(%sp)
3054 mov.l %a0,-0x8+0xc+LOCAL_SIZE(%sp)
3055 mov.w %d0,-0x8+0x10+LOCAL_SIZE(%sp)
3056 mov.w &0x0001,-0x8+0x12+LOCAL_SIZE(%sp)
3057
3058 movm.l LOCAL_SIZE+EXC_DREGS(%sp),&0x0303 # restore d0-d1/a0-a1
3059 add.w &LOCAL_SIZE-0x4,%sp
3060
3061 bra.b iea_acc_done
3062
3063#########################################################################
3064# XDEF **************************************************************** #
3065# _fpsp_operr(): 060FPSP entry point for FP Operr exception. #
3066# #
3067# This handler should be the first code executed upon taking the #
3068# FP Operand Error exception in an operating system. #
3069# #
3070# XREF **************************************************************** #
3071# _imem_read_long() - read instruction longword #
3072# fix_skewed_ops() - adjust src operand in fsave frame #
3073# _real_operr() - "callout" to operating system operr handler #
3074# _dmem_write_{byte,word,long}() - store data to mem (opclass 3) #
3075# store_dreg_{b,w,l}() - store data to data regfile (opclass 3) #
3076# facc_out_{b,w,l}() - store to memory took access error (opcl 3) #
3077# #
3078# INPUT *************************************************************** #
3079# - The system stack contains the FP Operr exception frame #
3080# - The fsave frame contains the source operand #
3081# #
3082# OUTPUT ************************************************************** #
3083# No access error: #
3084# - The system stack is unchanged #
3085# - The fsave frame contains the adjusted src op for opclass 0,2 #
3086# #
3087# ALGORITHM *********************************************************** #
3088# In a system where the FP Operr exception is enabled, the goal #
3089# is to get to the handler specified at _real_operr(). But, on the 060, #
3090# for opclass zero and two instruction taking this exception, the #
3091# input operand in the fsave frame may be incorrect for some cases #
3092# and needs to be corrected. This handler calls fix_skewed_ops() to #
3093# do just this and then exits through _real_operr(). #
3094# For opclass 3 instructions, the 060 doesn't store the default #
3095# operr result out to memory or data register file as it should. #
3096# This code must emulate the move out before finally exiting through #
3097# _real_inex(). The move out, if to memory, is performed using #
3098# _mem_write() "callout" routines that may return a failing result. #
3099# In this special case, the handler must exit through facc_out() #
3100# which creates an access error stack frame from the current operr #
3101# stack frame. #
3102# #
3103#########################################################################
3104
3105 global _fpsp_operr
3106_fpsp_operr:
3107
3108 link.w %a6,&-LOCAL_SIZE # init stack frame
3109
3110 fsave FP_SRC(%a6) # grab the "busy" frame
3111
3112 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3113 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3114 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3115
3116# the FPIAR holds the "current PC" of the faulting instruction
3117 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3118
3119 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3120 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3121 bsr.l _imem_read_long # fetch the instruction words
3122 mov.l %d0,EXC_OPWORD(%a6)
3123
3124##############################################################################
3125
3126 btst &13,%d0 # is instr an fmove out?
3127 bne.b foperr_out # fmove out
3128
3129
3130# here, we simply see if the operand in the fsave frame needs to be "unskewed".
3131# this would be the case for opclass two operations with a source infinity or
3132# denorm operand in the sgl or dbl format. NANs also become skewed, but can't
3133# cause an operr so we don't need to check for them here.
3134 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3135 bsr.l fix_skewed_ops # fix src op
3136
3137foperr_exit:
3138 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3139 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3140 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3141
3142 frestore FP_SRC(%a6)
3143
3144 unlk %a6
3145 bra.l _real_operr
3146
3147########################################################################
3148
3149#
3150# the hardware does not save the default result to memory on enabled
3151# operand error exceptions. we do this here before passing control to
3152# the user operand error handler.
3153#
3154# byte, word, and long destination format operations can pass
3155# through here. we simply need to test the sign of the src
3156# operand and save the appropriate minimum or maximum integer value
3157# to the effective address as pointed to by the stacked effective address.
3158#
3159# although packed opclass three operations can take operand error
3160# exceptions, they won't pass through here since they are caught
3161# first by the unsupported data format exception handler. that handler
3162# sends them directly to _real_operr() if necessary.
3163#
3164foperr_out:
3165
3166 mov.w FP_SRC_EX(%a6),%d1 # fetch exponent
3167 andi.w &0x7fff,%d1
3168 cmpi.w %d1,&0x7fff
3169 bne.b foperr_out_not_qnan
3170# the operand is either an infinity or a QNAN.
3171 tst.l FP_SRC_LO(%a6)
3172 bne.b foperr_out_qnan
3173 mov.l FP_SRC_HI(%a6),%d1
3174 andi.l &0x7fffffff,%d1
3175 beq.b foperr_out_not_qnan
3176foperr_out_qnan:
3177 mov.l FP_SRC_HI(%a6),L_SCR1(%a6)
3178 bra.b foperr_out_jmp
3179
3180foperr_out_not_qnan:
3181 mov.l &0x7fffffff,%d1
3182 tst.b FP_SRC_EX(%a6)
3183 bpl.b foperr_out_not_qnan2
3184 addq.l &0x1,%d1
3185foperr_out_not_qnan2:
3186 mov.l %d1,L_SCR1(%a6)
3187
3188foperr_out_jmp:
3189 bfextu %d0{&19:&3},%d0 # extract dst format field
3190 mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg
3191 mov.w (tbl_operr.b,%pc,%d0.w*2),%a0
3192 jmp (tbl_operr.b,%pc,%a0)
3193
3194tbl_operr:
3195 short foperr_out_l - tbl_operr # long word integer
3196 short tbl_operr - tbl_operr # sgl prec shouldn't happen
3197 short tbl_operr - tbl_operr # ext prec shouldn't happen
3198 short foperr_exit - tbl_operr # packed won't enter here
3199 short foperr_out_w - tbl_operr # word integer
3200 short tbl_operr - tbl_operr # dbl prec shouldn't happen
3201 short foperr_out_b - tbl_operr # byte integer
3202 short tbl_operr - tbl_operr # packed won't enter here
3203
3204foperr_out_b:
3205 mov.b L_SCR1(%a6),%d0 # load positive default result
3206 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3207 ble.b foperr_out_b_save_dn # yes
3208 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3209 bsr.l _dmem_write_byte # write the default result
3210
3211 tst.l %d1 # did dstore fail?
3212 bne.l facc_out_b # yes
3213
3214 bra.w foperr_exit
3215foperr_out_b_save_dn:
3216 andi.w &0x0007,%d1
3217 bsr.l store_dreg_b # store result to regfile
3218 bra.w foperr_exit
3219
3220foperr_out_w:
3221 mov.w L_SCR1(%a6),%d0 # load positive default result
3222 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3223 ble.b foperr_out_w_save_dn # yes
3224 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3225 bsr.l _dmem_write_word # write the default result
3226
3227 tst.l %d1 # did dstore fail?
3228 bne.l facc_out_w # yes
3229
3230 bra.w foperr_exit
3231foperr_out_w_save_dn:
3232 andi.w &0x0007,%d1
3233 bsr.l store_dreg_w # store result to regfile
3234 bra.w foperr_exit
3235
3236foperr_out_l:
3237 mov.l L_SCR1(%a6),%d0 # load positive default result
3238 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3239 ble.b foperr_out_l_save_dn # yes
3240 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3241 bsr.l _dmem_write_long # write the default result
3242
3243 tst.l %d1 # did dstore fail?
3244 bne.l facc_out_l # yes
3245
3246 bra.w foperr_exit
3247foperr_out_l_save_dn:
3248 andi.w &0x0007,%d1
3249 bsr.l store_dreg_l # store result to regfile
3250 bra.w foperr_exit
3251
3252#########################################################################
3253# XDEF **************************************************************** #
3254# _fpsp_snan(): 060FPSP entry point for FP SNAN exception. #
3255# #
3256# This handler should be the first code executed upon taking the #
3257# FP Signalling NAN exception in an operating system. #
3258# #
3259# XREF **************************************************************** #
3260# _imem_read_long() - read instruction longword #
3261# fix_skewed_ops() - adjust src operand in fsave frame #
3262# _real_snan() - "callout" to operating system SNAN handler #
3263# _dmem_write_{byte,word,long}() - store data to mem (opclass 3) #
3264# store_dreg_{b,w,l}() - store data to data regfile (opclass 3) #
3265# facc_out_{b,w,l,d,x}() - store to mem took acc error (opcl 3) #
3266# _calc_ea_fout() - fix An if <ea> is -() or ()+; also get <ea> #
3267# #
3268# INPUT *************************************************************** #
3269# - The system stack contains the FP SNAN exception frame #
3270# - The fsave frame contains the source operand #
3271# #
3272# OUTPUT ************************************************************** #
3273# No access error: #
3274# - The system stack is unchanged #
3275# - The fsave frame contains the adjusted src op for opclass 0,2 #
3276# #
3277# ALGORITHM *********************************************************** #
3278# In a system where the FP SNAN exception is enabled, the goal #
3279# is to get to the handler specified at _real_snan(). But, on the 060, #
3280# for opclass zero and two instructions taking this exception, the #
3281# input operand in the fsave frame may be incorrect for some cases #
3282# and needs to be corrected. This handler calls fix_skewed_ops() to #
3283# do just this and then exits through _real_snan(). #
3284# For opclass 3 instructions, the 060 doesn't store the default #
3285# SNAN result out to memory or data register file as it should. #
3286# This code must emulate the move out before finally exiting through #
3287# _real_snan(). The move out, if to memory, is performed using #
3288# _mem_write() "callout" routines that may return a failing result. #
3289# In this special case, the handler must exit through facc_out() #
3290# which creates an access error stack frame from the current SNAN #
3291# stack frame. #
3292# For the case of an extended precision opclass 3 instruction, #
3293# if the effective addressing mode was -() or ()+, then the address #
3294# register must get updated by calling _calc_ea_fout(). If the <ea> #
3295# was -(a7) from supervisor mode, then the exception frame currently #
3296# on the system stack must be carefully moved "down" to make room #
3297# for the operand being moved. #
3298# #
3299#########################################################################
3300
3301 global _fpsp_snan
3302_fpsp_snan:
3303
3304 link.w %a6,&-LOCAL_SIZE # init stack frame
3305
3306 fsave FP_SRC(%a6) # grab the "busy" frame
3307
3308 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3309 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3310 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3311
3312# the FPIAR holds the "current PC" of the faulting instruction
3313 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3314
3315 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3316 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3317 bsr.l _imem_read_long # fetch the instruction words
3318 mov.l %d0,EXC_OPWORD(%a6)
3319
3320##############################################################################
3321
3322 btst &13,%d0 # is instr an fmove out?
3323 bne.w fsnan_out # fmove out
3324
3325
3326# here, we simply see if the operand in the fsave frame needs to be "unskewed".
3327# this would be the case for opclass two operations with a source infinity or
3328# denorm operand in the sgl or dbl format. NANs also become skewed and must be
3329# fixed here.
3330 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3331 bsr.l fix_skewed_ops # fix src op
3332
3333fsnan_exit:
3334 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3335 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3336 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3337
3338 frestore FP_SRC(%a6)
3339
3340 unlk %a6
3341 bra.l _real_snan
3342
3343########################################################################
3344
3345#
3346# the hardware does not save the default result to memory on enabled
3347# snan exceptions. we do this here before passing control to
3348# the user snan handler.
3349#
3350# byte, word, long, and packed destination format operations can pass
3351# through here. since packed format operations already were handled by
3352# fpsp_unsupp(), then we need to do nothing else for them here.
3353# for byte, word, and long, we simply need to test the sign of the src
3354# operand and save the appropriate minimum or maximum integer value
3355# to the effective address as pointed to by the stacked effective address.
3356#
3357fsnan_out:
3358
3359 bfextu %d0{&19:&3},%d0 # extract dst format field
3360 mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg
3361 mov.w (tbl_snan.b,%pc,%d0.w*2),%a0
3362 jmp (tbl_snan.b,%pc,%a0)
3363
3364tbl_snan:
3365 short fsnan_out_l - tbl_snan # long word integer
3366 short fsnan_out_s - tbl_snan # sgl prec shouldn't happen
3367 short fsnan_out_x - tbl_snan # ext prec shouldn't happen
3368 short tbl_snan - tbl_snan # packed needs no help
3369 short fsnan_out_w - tbl_snan # word integer
3370 short fsnan_out_d - tbl_snan # dbl prec shouldn't happen
3371 short fsnan_out_b - tbl_snan # byte integer
3372 short tbl_snan - tbl_snan # packed needs no help
3373
3374fsnan_out_b:
3375 mov.b FP_SRC_HI(%a6),%d0 # load upper byte of SNAN
3376 bset &6,%d0 # set SNAN bit
3377 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3378 ble.b fsnan_out_b_dn # yes
3379 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3380 bsr.l _dmem_write_byte # write the default result
3381
3382 tst.l %d1 # did dstore fail?
3383 bne.l facc_out_b # yes
3384
3385 bra.w fsnan_exit
3386fsnan_out_b_dn:
3387 andi.w &0x0007,%d1
3388 bsr.l store_dreg_b # store result to regfile
3389 bra.w fsnan_exit
3390
3391fsnan_out_w:
3392 mov.w FP_SRC_HI(%a6),%d0 # load upper word of SNAN
3393 bset &14,%d0 # set SNAN bit
3394 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3395 ble.b fsnan_out_w_dn # yes
3396 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3397 bsr.l _dmem_write_word # write the default result
3398
3399 tst.l %d1 # did dstore fail?
3400 bne.l facc_out_w # yes
3401
3402 bra.w fsnan_exit
3403fsnan_out_w_dn:
3404 andi.w &0x0007,%d1
3405 bsr.l store_dreg_w # store result to regfile
3406 bra.w fsnan_exit
3407
3408fsnan_out_l:
3409 mov.l FP_SRC_HI(%a6),%d0 # load upper longword of SNAN
3410 bset &30,%d0 # set SNAN bit
3411 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3412 ble.b fsnan_out_l_dn # yes
3413 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3414 bsr.l _dmem_write_long # write the default result
3415
3416 tst.l %d1 # did dstore fail?
3417 bne.l facc_out_l # yes
3418
3419 bra.w fsnan_exit
3420fsnan_out_l_dn:
3421 andi.w &0x0007,%d1
3422 bsr.l store_dreg_l # store result to regfile
3423 bra.w fsnan_exit
3424
3425fsnan_out_s:
3426 cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3427 ble.b fsnan_out_d_dn # yes
3428 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3429 andi.l &0x80000000,%d0 # keep sign
3430 ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit
3431 mov.l FP_SRC_HI(%a6),%d1 # load mantissa
3432 lsr.l &0x8,%d1 # shift mantissa for sgl
3433 or.l %d1,%d0 # create sgl SNAN
3434 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3435 bsr.l _dmem_write_long # write the default result
3436
3437 tst.l %d1 # did dstore fail?
3438 bne.l facc_out_l # yes
3439
3440 bra.w fsnan_exit
3441fsnan_out_d_dn:
3442 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3443 andi.l &0x80000000,%d0 # keep sign
3444 ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit
3445 mov.l %d1,-(%sp)
3446 mov.l FP_SRC_HI(%a6),%d1 # load mantissa
3447 lsr.l &0x8,%d1 # shift mantissa for sgl
3448 or.l %d1,%d0 # create sgl SNAN
3449 mov.l (%sp)+,%d1
3450 andi.w &0x0007,%d1
3451 bsr.l store_dreg_l # store result to regfile
3452 bra.w fsnan_exit
3453
3454fsnan_out_d:
3455 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3456 andi.l &0x80000000,%d0 # keep sign
3457 ori.l &0x7ff80000,%d0 # insert new exponent,SNAN bit
3458 mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa
3459 mov.l %d0,FP_SCR0_EX(%a6) # store to temp space
3460 mov.l &11,%d0 # load shift amt
3461 lsr.l %d0,%d1
3462 or.l %d1,FP_SCR0_EX(%a6) # create dbl hi
3463 mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa
3464 andi.l &0x000007ff,%d1
3465 ror.l %d0,%d1
3466 mov.l %d1,FP_SCR0_HI(%a6) # store to temp space
3467 mov.l FP_SRC_LO(%a6),%d1 # load lo mantissa
3468 lsr.l %d0,%d1
3469 or.l %d1,FP_SCR0_HI(%a6) # create dbl lo
3470 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
3471 mov.l EXC_EA(%a6),%a1 # pass: dst addr
3472 movq.l &0x8,%d0 # pass: size of 8 bytes
3473 bsr.l _dmem_write # write the default result
3474
3475 tst.l %d1 # did dstore fail?
3476 bne.l facc_out_d # yes
3477
3478 bra.w fsnan_exit
3479
3480# for extended precision, if the addressing mode is pre-decrement or
3481# post-increment, then the address register did not get updated.
3482# in addition, for pre-decrement, the stacked <ea> is incorrect.
3483fsnan_out_x:
3484 clr.b SPCOND_FLG(%a6) # clear special case flag
3485
3486 mov.w FP_SRC_EX(%a6),FP_SCR0_EX(%a6)
3487 clr.w 2+FP_SCR0(%a6)
3488 mov.l FP_SRC_HI(%a6),%d0
3489 bset &30,%d0
3490 mov.l %d0,FP_SCR0_HI(%a6)
3491 mov.l FP_SRC_LO(%a6),FP_SCR0_LO(%a6)
3492
3493 btst &0x5,EXC_SR(%a6) # supervisor mode exception?
3494 bne.b fsnan_out_x_s # yes
3495
3496 mov.l %usp,%a0 # fetch user stack pointer
3497 mov.l %a0,EXC_A7(%a6) # save on stack for calc_ea()
3498 mov.l (%a6),EXC_A6(%a6)
3499
3500 bsr.l _calc_ea_fout # find the correct ea,update An
3501 mov.l %a0,%a1
3502 mov.l %a0,EXC_EA(%a6) # stack correct <ea>
3503
3504 mov.l EXC_A7(%a6),%a0
3505 mov.l %a0,%usp # restore user stack pointer
3506 mov.l EXC_A6(%a6),(%a6)
3507
3508fsnan_out_x_save:
3509 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
3510 movq.l &0xc,%d0 # pass: size of extended
3511 bsr.l _dmem_write # write the default result
3512
3513 tst.l %d1 # did dstore fail?
3514 bne.l facc_out_x # yes
3515
3516 bra.w fsnan_exit
3517
3518fsnan_out_x_s:
3519 mov.l (%a6),EXC_A6(%a6)
3520
3521 bsr.l _calc_ea_fout # find the correct ea,update An
3522 mov.l %a0,%a1
3523 mov.l %a0,EXC_EA(%a6) # stack correct <ea>
3524
3525 mov.l EXC_A6(%a6),(%a6)
3526
3527 cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
3528 bne.b fsnan_out_x_save # no
3529
3530# the operation was "fmove.x SNAN,-(a7)" from supervisor mode.
3531 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3532 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3533 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3534
3535 frestore FP_SRC(%a6)
3536
3537 mov.l EXC_A6(%a6),%a6 # restore frame pointer
3538
3539 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
3540 mov.l LOCAL_SIZE+EXC_PC+0x2(%sp),LOCAL_SIZE+EXC_PC+0x2-0xc(%sp)
3541 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
3542
3543 mov.l LOCAL_SIZE+FP_SCR0_EX(%sp),LOCAL_SIZE+EXC_SR(%sp)
3544 mov.l LOCAL_SIZE+FP_SCR0_HI(%sp),LOCAL_SIZE+EXC_PC+0x2(%sp)
3545 mov.l LOCAL_SIZE+FP_SCR0_LO(%sp),LOCAL_SIZE+EXC_EA(%sp)
3546
3547 add.l &LOCAL_SIZE-0x8,%sp
3548
3549 bra.l _real_snan
3550
3551#########################################################################
3552# XDEF **************************************************************** #
3553# _fpsp_inex(): 060FPSP entry point for FP Inexact exception. #
3554# #
3555# This handler should be the first code executed upon taking the #
3556# FP Inexact exception in an operating system. #
3557# #
3558# XREF **************************************************************** #
3559# _imem_read_long() - read instruction longword #
3560# fix_skewed_ops() - adjust src operand in fsave frame #
3561# set_tag_x() - determine optype of src/dst operands #
3562# store_fpreg() - store opclass 0 or 2 result to FP regfile #
3563# unnorm_fix() - change UNNORM operands to NORM or ZERO #
3564# load_fpn2() - load dst operand from FP regfile #
3565# smovcr() - emulate an "fmovcr" instruction #
3566# fout() - emulate an opclass 3 instruction #
3567# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
3568# _real_inex() - "callout" to operating system inexact handler #
3569# #
3570# INPUT *************************************************************** #
3571# - The system stack contains the FP Inexact exception frame #
3572# - The fsave frame contains the source operand #
3573# #
3574# OUTPUT ************************************************************** #
3575# - The system stack is unchanged #
3576# - The fsave frame contains the adjusted src op for opclass 0,2 #
3577# #
3578# ALGORITHM *********************************************************** #
3579# In a system where the FP Inexact exception is enabled, the goal #
3580# is to get to the handler specified at _real_inex(). But, on the 060, #
3581# for opclass zero and two instruction taking this exception, the #
3582# hardware doesn't store the correct result to the destination FP #
3583# register as did the '040 and '881/2. This handler must emulate the #
3584# instruction in order to get this value and then store it to the #
3585# correct register before calling _real_inex(). #
3586# For opclass 3 instructions, the 060 doesn't store the default #
3587# inexact result out to memory or data register file as it should. #
3588# This code must emulate the move out by calling fout() before finally #
3589# exiting through _real_inex(). #
3590# #
3591#########################################################################
3592
3593 global _fpsp_inex
3594_fpsp_inex:
3595
3596 link.w %a6,&-LOCAL_SIZE # init stack frame
3597
3598 fsave FP_SRC(%a6) # grab the "busy" frame
3599
3600 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3601 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3602 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3603
3604# the FPIAR holds the "current PC" of the faulting instruction
3605 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3606
3607 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3608 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3609 bsr.l _imem_read_long # fetch the instruction words
3610 mov.l %d0,EXC_OPWORD(%a6)
3611
3612##############################################################################
3613
3614 btst &13,%d0 # is instr an fmove out?
3615 bne.w finex_out # fmove out
3616
3617
3618# the hardware, for "fabs" and "fneg" w/ a long source format, puts the
3619# longword integer directly into the upper longword of the mantissa along
3620# w/ an exponent value of 0x401e. we convert this to extended precision here.
3621 bfextu %d0{&19:&3},%d0 # fetch instr size
3622 bne.b finex_cont # instr size is not long
3623 cmpi.w FP_SRC_EX(%a6),&0x401e # is exponent 0x401e?
3624 bne.b finex_cont # no
3625 fmov.l &0x0,%fpcr
3626 fmov.l FP_SRC_HI(%a6),%fp0 # load integer src
3627 fmov.x %fp0,FP_SRC(%a6) # store integer as extended precision
3628 mov.w &0xe001,0x2+FP_SRC(%a6)
3629
3630finex_cont:
3631 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3632 bsr.l fix_skewed_ops # fix src op
3633
3634# Here, we zero the ccode and exception byte field since we're going to
3635# emulate the whole instruction. Notice, though, that we don't kill the
3636# INEX1 bit. This is because a packed op has long since been converted
3637# to extended before arriving here. Therefore, we need to retain the
3638# INEX1 bit from when the operand was first converted.
3639 andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
3640
3641 fmov.l &0x0,%fpcr # zero current control regs
3642 fmov.l &0x0,%fpsr
3643
3644 bfextu EXC_EXTWORD(%a6){&0:&6},%d1 # extract upper 6 of cmdreg
3645 cmpi.b %d1,&0x17 # is op an fmovecr?
3646 beq.w finex_fmovcr # yes
3647
3648 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3649 bsr.l set_tag_x # tag the operand type
3650 mov.b %d0,STAG(%a6) # maybe NORM,DENORM
3651
3652# bits four and five of the fp extension word separate the monadic and dyadic
3653# operations that can pass through fpsp_inex(). remember that fcmp and ftst
3654# will never take this exception, but fsincos will.
3655 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
3656 beq.b finex_extract # monadic
3657
3658 btst &0x4,1+EXC_CMDREG(%a6) # is operation an fsincos?
3659 bne.b finex_extract # yes
3660
3661 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
3662 bsr.l load_fpn2 # load dst into FP_DST
3663
3664 lea FP_DST(%a6),%a0 # pass: ptr to dst op
3665 bsr.l set_tag_x # tag the operand type
3666 cmpi.b %d0,&UNNORM # is operand an UNNORM?
3667 bne.b finex_op2_done # no
3668 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
3669finex_op2_done:
3670 mov.b %d0,DTAG(%a6) # save dst optype tag
3671
3672finex_extract:
3673 clr.l %d0
3674 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
3675
3676 mov.b 1+EXC_CMDREG(%a6),%d1
3677 andi.w &0x007f,%d1 # extract extension
3678
3679 lea FP_SRC(%a6),%a0
3680 lea FP_DST(%a6),%a1
3681
3682 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
3683 jsr (tbl_unsupp.l,%pc,%d1.l*1)
3684
3685# the operation has been emulated. the result is in fp0.
3686finex_save:
3687 bfextu EXC_CMDREG(%a6){&6:&3},%d0
3688 bsr.l store_fpreg
3689
3690finex_exit:
3691 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3692 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3693 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3694
3695 frestore FP_SRC(%a6)
3696
3697 unlk %a6
3698 bra.l _real_inex
3699
3700finex_fmovcr:
3701 clr.l %d0
3702 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode
3703 mov.b 1+EXC_CMDREG(%a6),%d1
3704 andi.l &0x0000007f,%d1 # pass rom offset
3705 bsr.l smovcr
3706 bra.b finex_save
3707
3708########################################################################
3709
3710#
3711# the hardware does not save the default result to memory on enabled
3712# inexact exceptions. we do this here before passing control to
3713# the user inexact handler.
3714#
3715# byte, word, and long destination format operations can pass
3716# through here. so can double and single precision.
3717# although packed opclass three operations can take inexact
3718# exceptions, they won't pass through here since they are caught
3719# first by the unsupported data format exception handler. that handler
3720# sends them directly to _real_inex() if necessary.
3721#
3722finex_out:
3723
3724 mov.b &NORM,STAG(%a6) # src is a NORM
3725
3726 clr.l %d0
3727 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode
3728
3729 andi.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
3730
3731 lea FP_SRC(%a6),%a0 # pass ptr to src operand
3732
3733 bsr.l fout # store the default result
3734
3735 bra.b finex_exit
3736
3737#########################################################################
3738# XDEF **************************************************************** #
3739# _fpsp_dz(): 060FPSP entry point for FP DZ exception. #
3740# #
3741# This handler should be the first code executed upon taking #
3742# the FP DZ exception in an operating system. #
3743# #
3744# XREF **************************************************************** #
3745# _imem_read_long() - read instruction longword from memory #
3746# fix_skewed_ops() - adjust fsave operand #
3747# _real_dz() - "callout" exit point from FP DZ handler #
3748# #
3749# INPUT *************************************************************** #
3750# - The system stack contains the FP DZ exception stack. #
3751# - The fsave frame contains the source operand. #
3752# #
3753# OUTPUT ************************************************************** #
3754# - The system stack contains the FP DZ exception stack. #
3755# - The fsave frame contains the adjusted source operand. #
3756# #
3757# ALGORITHM *********************************************************** #
3758# In a system where the DZ exception is enabled, the goal is to #
3759# get to the handler specified at _real_dz(). But, on the 060, when the #
3760# exception is taken, the input operand in the fsave state frame may #
3761# be incorrect for some cases and need to be adjusted. So, this package #
3762# adjusts the operand using fix_skewed_ops() and then branches to #
3763# _real_dz(). #
3764# #
3765#########################################################################
3766
3767 global _fpsp_dz
3768_fpsp_dz:
3769
3770 link.w %a6,&-LOCAL_SIZE # init stack frame
3771
3772 fsave FP_SRC(%a6) # grab the "busy" frame
3773
3774 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3775 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3776 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3777
3778# the FPIAR holds the "current PC" of the faulting instruction
3779 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3780
3781 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3782 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3783 bsr.l _imem_read_long # fetch the instruction words
3784 mov.l %d0,EXC_OPWORD(%a6)
3785
3786##############################################################################
3787
3788
3789# here, we simply see if the operand in the fsave frame needs to be "unskewed".
3790# this would be the case for opclass two operations with a source zero
3791# in the sgl or dbl format.
3792 lea FP_SRC(%a6),%a0 # pass: ptr to src op
3793 bsr.l fix_skewed_ops # fix src op
3794
3795fdz_exit:
3796 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3797 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3798 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3799
3800 frestore FP_SRC(%a6)
3801
3802 unlk %a6
3803 bra.l _real_dz
3804
3805#########################################################################
3806# XDEF **************************************************************** #
3807# _fpsp_fline(): 060FPSP entry point for "Line F emulator" #
3808# exception when the "reduced" version of the #
3809# FPSP is implemented that does not emulate #
3810# FP unimplemented instructions. #
3811# #
3812# This handler should be the first code executed upon taking a #
3813# "Line F Emulator" exception in an operating system integrating #
3814# the reduced version of 060FPSP. #
3815# #
3816# XREF **************************************************************** #
3817# _real_fpu_disabled() - Handle "FPU disabled" exceptions #
3818# _real_fline() - Handle all other cases (treated equally) #
3819# #
3820# INPUT *************************************************************** #
3821# - The system stack contains a "Line F Emulator" exception #
3822# stack frame. #
3823# #
3824# OUTPUT ************************************************************** #
3825# - The system stack is unchanged. #
3826# #
3827# ALGORITHM *********************************************************** #
3828# When a "Line F Emulator" exception occurs in a system where #
3829# "FPU Unimplemented" instructions will not be emulated, the exception #
3830# can occur because then FPU is disabled or the instruction is to be #
3831# classifed as "Line F". This module determines which case exists and #
3832# calls the appropriate "callout". #
3833# #
3834#########################################################################
3835
3836 global _fpsp_fline
3837_fpsp_fline:
3838
3839# check to see if the FPU is disabled. if so, jump to the OS entry
3840# point for that condition.
3841 cmpi.w 0x6(%sp),&0x402c
3842 beq.l _real_fpu_disabled
3843
3844 bra.l _real_fline
3845
3846#########################################################################
3847# XDEF **************************************************************** #
3848# _dcalc_ea(): calc correct <ea> from <ea> stacked on exception #
3849# #
3850# XREF **************************************************************** #
3851# inc_areg() - increment an address register #
3852# dec_areg() - decrement an address register #
3853# #
3854# INPUT *************************************************************** #
3855# d0 = number of bytes to adjust <ea> by #
3856# #
3857# OUTPUT ************************************************************** #
3858# None #
3859# #
3860# ALGORITHM *********************************************************** #
3861# "Dummy" CALCulate Effective Address: #
3862# The stacked <ea> for FP unimplemented instructions and opclass #
3863# two packed instructions is correct with the exception of... #
3864# #
3865# 1) -(An) : The register is not updated regardless of size. #
3866# Also, for extended precision and packed, the #
3867# stacked <ea> value is 8 bytes too big #
3868# 2) (An)+ : The register is not updated. #
3869# 3) #<data> : The upper longword of the immediate operand is #
3870# stacked b,w,l and s sizes are completely stacked. #
3871# d,x, and p are not. #
3872# #
3873#########################################################################
3874
3875 global _dcalc_ea
3876_dcalc_ea:
3877 mov.l %d0, %a0 # move # bytes to %a0
3878
3879 mov.b 1+EXC_OPWORD(%a6), %d0 # fetch opcode word
3880 mov.l %d0, %d1 # make a copy
3881
3882 andi.w &0x38, %d0 # extract mode field
3883 andi.l &0x7, %d1 # extract reg field
3884
3885 cmpi.b %d0,&0x18 # is mode (An)+ ?
3886 beq.b dcea_pi # yes
3887
3888 cmpi.b %d0,&0x20 # is mode -(An) ?
3889 beq.b dcea_pd # yes
3890
3891 or.w %d1,%d0 # concat mode,reg
3892 cmpi.b %d0,&0x3c # is mode #<data>?
3893
3894 beq.b dcea_imm # yes
3895
3896 mov.l EXC_EA(%a6),%a0 # return <ea>
3897 rts
3898
3899# need to set immediate data flag here since we'll need to do
3900# an imem_read to fetch this later.
3901dcea_imm:
3902 mov.b &immed_flg,SPCOND_FLG(%a6)
3903 lea ([USER_FPIAR,%a6],0x4),%a0 # no; return <ea>
3904 rts
3905
3906# here, the <ea> is stacked correctly. however, we must update the
3907# address register...
3908dcea_pi:
3909 mov.l %a0,%d0 # pass amt to inc by
3910 bsr.l inc_areg # inc addr register
3911
3912 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
3913 rts
3914
3915# the <ea> is stacked correctly for all but extended and packed which
3916# the <ea>s are 8 bytes too large.
3917# it would make no sense to have a pre-decrement to a7 in supervisor
3918# mode so we don't even worry about this tricky case here : )
3919dcea_pd:
3920 mov.l %a0,%d0 # pass amt to dec by
3921 bsr.l dec_areg # dec addr register
3922
3923 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
3924
3925 cmpi.b %d0,&0xc # is opsize ext or packed?
3926 beq.b dcea_pd2 # yes
3927 rts
3928dcea_pd2:
3929 sub.l &0x8,%a0 # correct <ea>
3930 mov.l %a0,EXC_EA(%a6) # put correct <ea> on stack
3931 rts
3932
3933#########################################################################
3934# XDEF **************************************************************** #
3935# _calc_ea_fout(): calculate correct stacked <ea> for extended #
3936# and packed data opclass 3 operations. #
3937# #
3938# XREF **************************************************************** #
3939# None #
3940# #
3941# INPUT *************************************************************** #
3942# None #
3943# #
3944# OUTPUT ************************************************************** #
3945# a0 = return correct effective address #
3946# #
3947# ALGORITHM *********************************************************** #
3948# For opclass 3 extended and packed data operations, the <ea> #
3949# stacked for the exception is incorrect for -(an) and (an)+ addressing #
3950# modes. Also, while we're at it, the index register itself must get #
3951# updated. #
3952# So, for -(an), we must subtract 8 off of the stacked <ea> value #
3953# and return that value as the correct <ea> and store that value in An. #
3954# For (an)+, the stacked <ea> is correct but we must adjust An by +12. #
3955# #
3956#########################################################################
3957
3958# This calc_ea is currently used to retrieve the correct <ea>
3959# for fmove outs of type extended and packed.
3960 global _calc_ea_fout
3961_calc_ea_fout:
3962 mov.b 1+EXC_OPWORD(%a6),%d0 # fetch opcode word
3963 mov.l %d0,%d1 # make a copy
3964
3965 andi.w &0x38,%d0 # extract mode field
3966 andi.l &0x7,%d1 # extract reg field
3967
3968 cmpi.b %d0,&0x18 # is mode (An)+ ?
3969 beq.b ceaf_pi # yes
3970
3971 cmpi.b %d0,&0x20 # is mode -(An) ?
3972 beq.w ceaf_pd # yes
3973
3974 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
3975 rts
3976
3977# (An)+ : extended and packed fmove out
3978# : stacked <ea> is correct
3979# : "An" not updated
3980ceaf_pi:
3981 mov.w (tbl_ceaf_pi.b,%pc,%d1.w*2),%d1
3982 mov.l EXC_EA(%a6),%a0
3983 jmp (tbl_ceaf_pi.b,%pc,%d1.w*1)
3984
3985 swbeg &0x8
3986tbl_ceaf_pi:
3987 short ceaf_pi0 - tbl_ceaf_pi
3988 short ceaf_pi1 - tbl_ceaf_pi
3989 short ceaf_pi2 - tbl_ceaf_pi
3990 short ceaf_pi3 - tbl_ceaf_pi
3991 short ceaf_pi4 - tbl_ceaf_pi
3992 short ceaf_pi5 - tbl_ceaf_pi
3993 short ceaf_pi6 - tbl_ceaf_pi
3994 short ceaf_pi7 - tbl_ceaf_pi
3995
3996ceaf_pi0:
3997 addi.l &0xc,EXC_DREGS+0x8(%a6)
3998 rts
3999ceaf_pi1:
4000 addi.l &0xc,EXC_DREGS+0xc(%a6)
4001 rts
4002ceaf_pi2:
4003 add.l &0xc,%a2
4004 rts
4005ceaf_pi3:
4006 add.l &0xc,%a3
4007 rts
4008ceaf_pi4:
4009 add.l &0xc,%a4
4010 rts
4011ceaf_pi5:
4012 add.l &0xc,%a5
4013 rts
4014ceaf_pi6:
4015 addi.l &0xc,EXC_A6(%a6)
4016 rts
4017ceaf_pi7:
4018 mov.b &mia7_flg,SPCOND_FLG(%a6)
4019 addi.l &0xc,EXC_A7(%a6)
4020 rts
4021
4022# -(An) : extended and packed fmove out
4023# : stacked <ea> = actual <ea> + 8
4024# : "An" not updated
4025ceaf_pd:
4026 mov.w (tbl_ceaf_pd.b,%pc,%d1.w*2),%d1
4027 mov.l EXC_EA(%a6),%a0
4028 sub.l &0x8,%a0
4029 sub.l &0x8,EXC_EA(%a6)
4030 jmp (tbl_ceaf_pd.b,%pc,%d1.w*1)
4031
4032 swbeg &0x8
4033tbl_ceaf_pd:
4034 short ceaf_pd0 - tbl_ceaf_pd
4035 short ceaf_pd1 - tbl_ceaf_pd
4036 short ceaf_pd2 - tbl_ceaf_pd
4037 short ceaf_pd3 - tbl_ceaf_pd
4038 short ceaf_pd4 - tbl_ceaf_pd
4039 short ceaf_pd5 - tbl_ceaf_pd
4040 short ceaf_pd6 - tbl_ceaf_pd
4041 short ceaf_pd7 - tbl_ceaf_pd
4042
4043ceaf_pd0:
4044 mov.l %a0,EXC_DREGS+0x8(%a6)
4045 rts
4046ceaf_pd1:
4047 mov.l %a0,EXC_DREGS+0xc(%a6)
4048 rts
4049ceaf_pd2:
4050 mov.l %a0,%a2
4051 rts
4052ceaf_pd3:
4053 mov.l %a0,%a3
4054 rts
4055ceaf_pd4:
4056 mov.l %a0,%a4
4057 rts
4058ceaf_pd5:
4059 mov.l %a0,%a5
4060 rts
4061ceaf_pd6:
4062 mov.l %a0,EXC_A6(%a6)
4063 rts
4064ceaf_pd7:
4065 mov.l %a0,EXC_A7(%a6)
4066 mov.b &mda7_flg,SPCOND_FLG(%a6)
4067 rts
4068
4069#
4070# This table holds the offsets of the emulation routines for each individual
4071# math operation relative to the address of this table. Included are
4072# routines like fadd/fmul/fabs. The transcendentals ARE NOT. This is because
4073# this table is for the version if the 060FPSP without transcendentals.
4074# The location within the table is determined by the extension bits of the
4075# operation longword.
4076#
4077
4078 swbeg &109
4079tbl_unsupp:
4080 long fin - tbl_unsupp # 00: fmove
4081 long fint - tbl_unsupp # 01: fint
4082 long tbl_unsupp - tbl_unsupp # 02: fsinh
4083 long fintrz - tbl_unsupp # 03: fintrz
4084 long fsqrt - tbl_unsupp # 04: fsqrt
4085 long tbl_unsupp - tbl_unsupp
4086 long tbl_unsupp - tbl_unsupp # 06: flognp1
4087 long tbl_unsupp - tbl_unsupp
4088 long tbl_unsupp - tbl_unsupp # 08: fetoxm1
4089 long tbl_unsupp - tbl_unsupp # 09: ftanh
4090 long tbl_unsupp - tbl_unsupp # 0a: fatan
4091 long tbl_unsupp - tbl_unsupp
4092 long tbl_unsupp - tbl_unsupp # 0c: fasin
4093 long tbl_unsupp - tbl_unsupp # 0d: fatanh
4094 long tbl_unsupp - tbl_unsupp # 0e: fsin
4095 long tbl_unsupp - tbl_unsupp # 0f: ftan
4096 long tbl_unsupp - tbl_unsupp # 10: fetox
4097 long tbl_unsupp - tbl_unsupp # 11: ftwotox
4098 long tbl_unsupp - tbl_unsupp # 12: ftentox
4099 long tbl_unsupp - tbl_unsupp
4100 long tbl_unsupp - tbl_unsupp # 14: flogn
4101 long tbl_unsupp - tbl_unsupp # 15: flog10
4102 long tbl_unsupp - tbl_unsupp # 16: flog2
4103 long tbl_unsupp - tbl_unsupp
4104 long fabs - tbl_unsupp # 18: fabs
4105 long tbl_unsupp - tbl_unsupp # 19: fcosh
4106 long fneg - tbl_unsupp # 1a: fneg
4107 long tbl_unsupp - tbl_unsupp
4108 long tbl_unsupp - tbl_unsupp # 1c: facos
4109 long tbl_unsupp - tbl_unsupp # 1d: fcos
4110 long tbl_unsupp - tbl_unsupp # 1e: fgetexp
4111 long tbl_unsupp - tbl_unsupp # 1f: fgetman
4112 long fdiv - tbl_unsupp # 20: fdiv
4113 long tbl_unsupp - tbl_unsupp # 21: fmod
4114 long fadd - tbl_unsupp # 22: fadd
4115 long fmul - tbl_unsupp # 23: fmul
4116 long fsgldiv - tbl_unsupp # 24: fsgldiv
4117 long tbl_unsupp - tbl_unsupp # 25: frem
4118 long tbl_unsupp - tbl_unsupp # 26: fscale
4119 long fsglmul - tbl_unsupp # 27: fsglmul
4120 long fsub - tbl_unsupp # 28: fsub
4121 long tbl_unsupp - tbl_unsupp
4122 long tbl_unsupp - tbl_unsupp
4123 long tbl_unsupp - tbl_unsupp
4124 long tbl_unsupp - tbl_unsupp
4125 long tbl_unsupp - tbl_unsupp
4126 long tbl_unsupp - tbl_unsupp
4127 long tbl_unsupp - tbl_unsupp
4128 long tbl_unsupp - tbl_unsupp # 30: fsincos
4129 long tbl_unsupp - tbl_unsupp # 31: fsincos
4130 long tbl_unsupp - tbl_unsupp # 32: fsincos
4131 long tbl_unsupp - tbl_unsupp # 33: fsincos
4132 long tbl_unsupp - tbl_unsupp # 34: fsincos
4133 long tbl_unsupp - tbl_unsupp # 35: fsincos
4134 long tbl_unsupp - tbl_unsupp # 36: fsincos
4135 long tbl_unsupp - tbl_unsupp # 37: fsincos
4136 long fcmp - tbl_unsupp # 38: fcmp
4137 long tbl_unsupp - tbl_unsupp
4138 long ftst - tbl_unsupp # 3a: ftst
4139 long tbl_unsupp - tbl_unsupp
4140 long tbl_unsupp - tbl_unsupp
4141 long tbl_unsupp - tbl_unsupp
4142 long tbl_unsupp - tbl_unsupp
4143 long tbl_unsupp - tbl_unsupp
4144 long fsin - tbl_unsupp # 40: fsmove
4145 long fssqrt - tbl_unsupp # 41: fssqrt
4146 long tbl_unsupp - tbl_unsupp
4147 long tbl_unsupp - tbl_unsupp
4148 long fdin - tbl_unsupp # 44: fdmove
4149 long fdsqrt - tbl_unsupp # 45: fdsqrt
4150 long tbl_unsupp - tbl_unsupp
4151 long tbl_unsupp - tbl_unsupp
4152 long tbl_unsupp - tbl_unsupp
4153 long tbl_unsupp - tbl_unsupp
4154 long tbl_unsupp - tbl_unsupp
4155 long tbl_unsupp - tbl_unsupp
4156 long tbl_unsupp - tbl_unsupp
4157 long tbl_unsupp - tbl_unsupp
4158 long tbl_unsupp - tbl_unsupp
4159 long tbl_unsupp - tbl_unsupp
4160 long tbl_unsupp - tbl_unsupp
4161 long tbl_unsupp - tbl_unsupp
4162 long tbl_unsupp - tbl_unsupp
4163 long tbl_unsupp - tbl_unsupp
4164 long tbl_unsupp - tbl_unsupp
4165 long tbl_unsupp - tbl_unsupp
4166 long tbl_unsupp - tbl_unsupp
4167 long tbl_unsupp - tbl_unsupp
4168 long fsabs - tbl_unsupp # 58: fsabs
4169 long tbl_unsupp - tbl_unsupp
4170 long fsneg - tbl_unsupp # 5a: fsneg
4171 long tbl_unsupp - tbl_unsupp
4172 long fdabs - tbl_unsupp # 5c: fdabs
4173 long tbl_unsupp - tbl_unsupp
4174 long fdneg - tbl_unsupp # 5e: fdneg
4175 long tbl_unsupp - tbl_unsupp
4176 long fsdiv - tbl_unsupp # 60: fsdiv
4177 long tbl_unsupp - tbl_unsupp
4178 long fsadd - tbl_unsupp # 62: fsadd
4179 long fsmul - tbl_unsupp # 63: fsmul
4180 long fddiv - tbl_unsupp # 64: fddiv
4181 long tbl_unsupp - tbl_unsupp
4182 long fdadd - tbl_unsupp # 66: fdadd
4183 long fdmul - tbl_unsupp # 67: fdmul
4184 long fssub - tbl_unsupp # 68: fssub
4185 long tbl_unsupp - tbl_unsupp
4186 long tbl_unsupp - tbl_unsupp
4187 long tbl_unsupp - tbl_unsupp
4188 long fdsub - tbl_unsupp # 6c: fdsub
4189
4190#################################################
4191# Add this here so non-fp modules can compile.
4192# (smovcr is called from fpsp_inex.)
4193 global smovcr
4194smovcr:
4195 bra.b smovcr
4196
4197#########################################################################
4198# XDEF **************************************************************** #
4199# fmovm_dynamic(): emulate "fmovm" dynamic instruction #
4200# #
4201# XREF **************************************************************** #
4202# fetch_dreg() - fetch data register #
4203# {i,d,}mem_read() - fetch data from memory #
4204# _mem_write() - write data to memory #
4205# iea_iacc() - instruction memory access error occurred #
4206# iea_dacc() - data memory access error occurred #
4207# restore() - restore An index regs if access error occurred #
4208# #
4209# INPUT *************************************************************** #
4210# None #
4211# #
4212# OUTPUT ************************************************************** #
4213# If instr is "fmovm Dn,-(A7)" from supervisor mode, #
4214# d0 = size of dump #
4215# d1 = Dn #
4216# Else if instruction access error, #
4217# d0 = FSLW #
4218# Else if data access error, #
4219# d0 = FSLW #
4220# a0 = address of fault #
4221# Else #
4222# none. #
4223# #
4224# ALGORITHM *********************************************************** #
4225# The effective address must be calculated since this is entered #
4226# from an "Unimplemented Effective Address" exception handler. So, we #
4227# have our own fcalc_ea() routine here. If an access error is flagged #
4228# by a _{i,d,}mem_read() call, we must exit through the special #
4229# handler. #
4230# The data register is determined and its value loaded to get the #
4231# string of FP registers affected. This value is used as an index into #
4232# a lookup table such that we can determine the number of bytes #
4233# involved. #
4234# If the instruction is "fmovm.x <ea>,Dn", a _mem_read() is used #
4235# to read in all FP values. Again, _mem_read() may fail and require a #
4236# special exit. #
4237# If the instruction is "fmovm.x DN,<ea>", a _mem_write() is used #
4238# to write all FP values. _mem_write() may also fail. #
4239# If the instruction is "fmovm.x DN,-(a7)" from supervisor mode, #
4240# then we return the size of the dump and the string to the caller #
4241# so that the move can occur outside of this routine. This special #
4242# case is required so that moves to the system stack are handled #
4243# correctly. #
4244# #
4245# DYNAMIC: #
4246# fmovm.x dn, <ea> #
4247# fmovm.x <ea>, dn #
4248# #
4249# <WORD 1> <WORD2> #
4250# 1111 0010 00 |<ea>| 11@& 1000 0$$$ 0000 #
4251# #
4252# & = (0): predecrement addressing mode #
4253# (1): postincrement or control addressing mode #
4254# @ = (0): move listed regs from memory to the FPU #
4255# (1): move listed regs from the FPU to memory #
4256# $$$ : index of data register holding reg select mask #
4257# #
4258# NOTES: #
4259# If the data register holds a zero, then the #
4260# instruction is a nop. #
4261# #
4262#########################################################################
4263
4264 global fmovm_dynamic
4265fmovm_dynamic:
4266
4267# extract the data register in which the bit string resides...
4268 mov.b 1+EXC_EXTWORD(%a6),%d1 # fetch extword
4269 andi.w &0x70,%d1 # extract reg bits
4270 lsr.b &0x4,%d1 # shift into lo bits
4271
4272# fetch the bit string into d0...
4273 bsr.l fetch_dreg # fetch reg string
4274
4275 andi.l &0x000000ff,%d0 # keep only lo byte
4276
4277 mov.l %d0,-(%sp) # save strg
4278 mov.b (tbl_fmovm_size.w,%pc,%d0),%d0
4279 mov.l %d0,-(%sp) # save size
4280 bsr.l fmovm_calc_ea # calculate <ea>
4281 mov.l (%sp)+,%d0 # restore size
4282 mov.l (%sp)+,%d1 # restore strg
4283
4284# if the bit string is a zero, then the operation is a no-op
4285# but, make sure that we've calculated ea and advanced the opword pointer
4286 beq.w fmovm_data_done
4287
4288# separate move ins from move outs...
4289 btst &0x5,EXC_EXTWORD(%a6) # is it a move in or out?
4290 beq.w fmovm_data_in # it's a move out
4291
4292#############
4293# MOVE OUT: #
4294#############
4295fmovm_data_out:
4296 btst &0x4,EXC_EXTWORD(%a6) # control or predecrement?
4297 bne.w fmovm_out_ctrl # control
4298
4299############################
4300fmovm_out_predec:
4301# for predecrement mode, the bit string is the opposite of both control
4302# operations and postincrement mode. (bit7 = FP7 ... bit0 = FP0)
4303# here, we convert it to be just like the others...
4304 mov.b (tbl_fmovm_convert.w,%pc,%d1.w*1),%d1
4305
4306 btst &0x5,EXC_SR(%a6) # user or supervisor mode?
4307 beq.b fmovm_out_ctrl # user
4308
4309fmovm_out_predec_s:
4310 cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
4311 bne.b fmovm_out_ctrl
4312
4313# the operation was unfortunately an: fmovm.x dn,-(sp)
4314# called from supervisor mode.
4315# we're also passing "size" and "strg" back to the calling routine
4316 rts
4317
4318############################
4319fmovm_out_ctrl:
4320 mov.l %a0,%a1 # move <ea> to a1
4321
4322 sub.l %d0,%sp # subtract size of dump
4323 lea (%sp),%a0
4324
4325 tst.b %d1 # should FP0 be moved?
4326 bpl.b fmovm_out_ctrl_fp1 # no
4327
4328 mov.l 0x0+EXC_FP0(%a6),(%a0)+ # yes
4329 mov.l 0x4+EXC_FP0(%a6),(%a0)+
4330 mov.l 0x8+EXC_FP0(%a6),(%a0)+
4331
4332fmovm_out_ctrl_fp1:
4333 lsl.b &0x1,%d1 # should FP1 be moved?
4334 bpl.b fmovm_out_ctrl_fp2 # no
4335
4336 mov.l 0x0+EXC_FP1(%a6),(%a0)+ # yes
4337 mov.l 0x4+EXC_FP1(%a6),(%a0)+
4338 mov.l 0x8+EXC_FP1(%a6),(%a0)+
4339
4340fmovm_out_ctrl_fp2:
4341 lsl.b &0x1,%d1 # should FP2 be moved?
4342 bpl.b fmovm_out_ctrl_fp3 # no
4343
4344 fmovm.x &0x20,(%a0) # yes
4345 add.l &0xc,%a0
4346
4347fmovm_out_ctrl_fp3:
4348 lsl.b &0x1,%d1 # should FP3 be moved?
4349 bpl.b fmovm_out_ctrl_fp4 # no
4350
4351 fmovm.x &0x10,(%a0) # yes
4352 add.l &0xc,%a0
4353
4354fmovm_out_ctrl_fp4:
4355 lsl.b &0x1,%d1 # should FP4 be moved?
4356 bpl.b fmovm_out_ctrl_fp5 # no
4357
4358 fmovm.x &0x08,(%a0) # yes
4359 add.l &0xc,%a0
4360
4361fmovm_out_ctrl_fp5:
4362 lsl.b &0x1,%d1 # should FP5 be moved?
4363 bpl.b fmovm_out_ctrl_fp6 # no
4364
4365 fmovm.x &0x04,(%a0) # yes
4366 add.l &0xc,%a0
4367
4368fmovm_out_ctrl_fp6:
4369 lsl.b &0x1,%d1 # should FP6 be moved?
4370 bpl.b fmovm_out_ctrl_fp7 # no
4371
4372 fmovm.x &0x02,(%a0) # yes
4373 add.l &0xc,%a0
4374
4375fmovm_out_ctrl_fp7:
4376 lsl.b &0x1,%d1 # should FP7 be moved?
4377 bpl.b fmovm_out_ctrl_done # no
4378
4379 fmovm.x &0x01,(%a0) # yes
4380 add.l &0xc,%a0
4381
4382fmovm_out_ctrl_done:
4383 mov.l %a1,L_SCR1(%a6)
4384
4385 lea (%sp),%a0 # pass: supervisor src
4386 mov.l %d0,-(%sp) # save size
4387 bsr.l _dmem_write # copy data to user mem
4388
4389 mov.l (%sp)+,%d0
4390 add.l %d0,%sp # clear fpreg data from stack
4391
4392 tst.l %d1 # did dstore err?
4393 bne.w fmovm_out_err # yes
4394
4395 rts
4396
4397############
4398# MOVE IN: #
4399############
4400fmovm_data_in:
4401 mov.l %a0,L_SCR1(%a6)
4402
4403 sub.l %d0,%sp # make room for fpregs
4404 lea (%sp),%a1
4405
4406 mov.l %d1,-(%sp) # save bit string for later
4407 mov.l %d0,-(%sp) # save # of bytes
4408
4409 bsr.l _dmem_read # copy data from user mem
4410
4411 mov.l (%sp)+,%d0 # retrieve # of bytes
4412
4413 tst.l %d1 # did dfetch fail?
4414 bne.w fmovm_in_err # yes
4415
4416 mov.l (%sp)+,%d1 # load bit string
4417
4418 lea (%sp),%a0 # addr of stack
4419
4420 tst.b %d1 # should FP0 be moved?
4421 bpl.b fmovm_data_in_fp1 # no
4422
4423 mov.l (%a0)+,0x0+EXC_FP0(%a6) # yes
4424 mov.l (%a0)+,0x4+EXC_FP0(%a6)
4425 mov.l (%a0)+,0x8+EXC_FP0(%a6)
4426
4427fmovm_data_in_fp1:
4428 lsl.b &0x1,%d1 # should FP1 be moved?
4429 bpl.b fmovm_data_in_fp2 # no
4430
4431 mov.l (%a0)+,0x0+EXC_FP1(%a6) # yes
4432 mov.l (%a0)+,0x4+EXC_FP1(%a6)
4433 mov.l (%a0)+,0x8+EXC_FP1(%a6)
4434
4435fmovm_data_in_fp2:
4436 lsl.b &0x1,%d1 # should FP2 be moved?
4437 bpl.b fmovm_data_in_fp3 # no
4438
4439 fmovm.x (%a0)+,&0x20 # yes
4440
4441fmovm_data_in_fp3:
4442 lsl.b &0x1,%d1 # should FP3 be moved?
4443 bpl.b fmovm_data_in_fp4 # no
4444
4445 fmovm.x (%a0)+,&0x10 # yes
4446
4447fmovm_data_in_fp4:
4448 lsl.b &0x1,%d1 # should FP4 be moved?
4449 bpl.b fmovm_data_in_fp5 # no
4450
4451 fmovm.x (%a0)+,&0x08 # yes
4452
4453fmovm_data_in_fp5:
4454 lsl.b &0x1,%d1 # should FP5 be moved?
4455 bpl.b fmovm_data_in_fp6 # no
4456
4457 fmovm.x (%a0)+,&0x04 # yes
4458
4459fmovm_data_in_fp6:
4460 lsl.b &0x1,%d1 # should FP6 be moved?
4461 bpl.b fmovm_data_in_fp7 # no
4462
4463 fmovm.x (%a0)+,&0x02 # yes
4464
4465fmovm_data_in_fp7:
4466 lsl.b &0x1,%d1 # should FP7 be moved?
4467 bpl.b fmovm_data_in_done # no
4468
4469 fmovm.x (%a0)+,&0x01 # yes
4470
4471fmovm_data_in_done:
4472 add.l %d0,%sp # remove fpregs from stack
4473 rts
4474
4475#####################################
4476
4477fmovm_data_done:
4478 rts
4479
4480##############################################################################
4481
4482#
4483# table indexed by the operation's bit string that gives the number
4484# of bytes that will be moved.
4485#
4486# number of bytes = (# of 1's in bit string) * 12(bytes/fpreg)
4487#
4488tbl_fmovm_size:
4489 byte 0x00,0x0c,0x0c,0x18,0x0c,0x18,0x18,0x24
4490 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4491 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4492 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4493 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4494 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4495 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4496 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4497 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4498 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4499 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4500 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4501 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4502 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4503 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4504 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4505 byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4506 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4507 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4508 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4509 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4510 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4511 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4512 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4513 byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4514 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4515 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4516 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4517 byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4518 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4519 byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4520 byte 0x3c,0x48,0x48,0x54,0x48,0x54,0x54,0x60
4521
4522#
4523# table to convert a pre-decrement bit string into a post-increment
4524# or control bit string.
4525# ex: 0x00 ==> 0x00
4526# 0x01 ==> 0x80
4527# 0x02 ==> 0x40
4528# .
4529# .
4530# 0xfd ==> 0xbf
4531# 0xfe ==> 0x7f
4532# 0xff ==> 0xff
4533#
4534tbl_fmovm_convert:
4535 byte 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0
4536 byte 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0
4537 byte 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8
4538 byte 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8
4539 byte 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4
4540 byte 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4
4541 byte 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec
4542 byte 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc
4543 byte 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2
4544 byte 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2
4545 byte 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea
4546 byte 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa
4547 byte 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6
4548 byte 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6
4549 byte 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee
4550 byte 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe
4551 byte 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1
4552 byte 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1
4553 byte 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9
4554 byte 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9
4555 byte 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5
4556 byte 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5
4557 byte 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed
4558 byte 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd
4559 byte 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3
4560 byte 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3
4561 byte 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb
4562 byte 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb
4563 byte 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7
4564 byte 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7
4565 byte 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef
4566 byte 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
4567
4568 global fmovm_calc_ea
4569###############################################
4570# _fmovm_calc_ea: calculate effective address #
4571###############################################
4572fmovm_calc_ea:
4573 mov.l %d0,%a0 # move # bytes to a0
4574
4575# currently, MODE and REG are taken from the EXC_OPWORD. this could be
4576# easily changed if they were inputs passed in registers.
4577 mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word
4578 mov.w %d0,%d1 # make a copy
4579
4580 andi.w &0x3f,%d0 # extract mode field
4581 andi.l &0x7,%d1 # extract reg field
4582
4583# jump to the corresponding function for each {MODE,REG} pair.
4584 mov.w (tbl_fea_mode.b,%pc,%d0.w*2),%d0 # fetch jmp distance
4585 jmp (tbl_fea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
4586
4587 swbeg &64
4588tbl_fea_mode:
4589 short tbl_fea_mode - tbl_fea_mode
4590 short tbl_fea_mode - tbl_fea_mode
4591 short tbl_fea_mode - tbl_fea_mode
4592 short tbl_fea_mode - tbl_fea_mode
4593 short tbl_fea_mode - tbl_fea_mode
4594 short tbl_fea_mode - tbl_fea_mode
4595 short tbl_fea_mode - tbl_fea_mode
4596 short tbl_fea_mode - tbl_fea_mode
4597
4598 short tbl_fea_mode - tbl_fea_mode
4599 short tbl_fea_mode - tbl_fea_mode
4600 short tbl_fea_mode - tbl_fea_mode
4601 short tbl_fea_mode - tbl_fea_mode
4602 short tbl_fea_mode - tbl_fea_mode
4603 short tbl_fea_mode - tbl_fea_mode
4604 short tbl_fea_mode - tbl_fea_mode
4605 short tbl_fea_mode - tbl_fea_mode
4606
4607 short faddr_ind_a0 - tbl_fea_mode
4608 short faddr_ind_a1 - tbl_fea_mode
4609 short faddr_ind_a2 - tbl_fea_mode
4610 short faddr_ind_a3 - tbl_fea_mode
4611 short faddr_ind_a4 - tbl_fea_mode
4612 short faddr_ind_a5 - tbl_fea_mode
4613 short faddr_ind_a6 - tbl_fea_mode
4614 short faddr_ind_a7 - tbl_fea_mode
4615
4616 short faddr_ind_p_a0 - tbl_fea_mode
4617 short faddr_ind_p_a1 - tbl_fea_mode
4618 short faddr_ind_p_a2 - tbl_fea_mode
4619 short faddr_ind_p_a3 - tbl_fea_mode
4620 short faddr_ind_p_a4 - tbl_fea_mode
4621 short faddr_ind_p_a5 - tbl_fea_mode
4622 short faddr_ind_p_a6 - tbl_fea_mode
4623 short faddr_ind_p_a7 - tbl_fea_mode
4624
4625 short faddr_ind_m_a0 - tbl_fea_mode
4626 short faddr_ind_m_a1 - tbl_fea_mode
4627 short faddr_ind_m_a2 - tbl_fea_mode
4628 short faddr_ind_m_a3 - tbl_fea_mode
4629 short faddr_ind_m_a4 - tbl_fea_mode
4630 short faddr_ind_m_a5 - tbl_fea_mode
4631 short faddr_ind_m_a6 - tbl_fea_mode
4632 short faddr_ind_m_a7 - tbl_fea_mode
4633
4634 short faddr_ind_disp_a0 - tbl_fea_mode
4635 short faddr_ind_disp_a1 - tbl_fea_mode
4636 short faddr_ind_disp_a2 - tbl_fea_mode
4637 short faddr_ind_disp_a3 - tbl_fea_mode
4638 short faddr_ind_disp_a4 - tbl_fea_mode
4639 short faddr_ind_disp_a5 - tbl_fea_mode
4640 short faddr_ind_disp_a6 - tbl_fea_mode
4641 short faddr_ind_disp_a7 - tbl_fea_mode
4642
4643 short faddr_ind_ext - tbl_fea_mode
4644 short faddr_ind_ext - tbl_fea_mode
4645 short faddr_ind_ext - tbl_fea_mode
4646 short faddr_ind_ext - tbl_fea_mode
4647 short faddr_ind_ext - tbl_fea_mode
4648 short faddr_ind_ext - tbl_fea_mode
4649 short faddr_ind_ext - tbl_fea_mode
4650 short faddr_ind_ext - tbl_fea_mode
4651
4652 short fabs_short - tbl_fea_mode
4653 short fabs_long - tbl_fea_mode
4654 short fpc_ind - tbl_fea_mode
4655 short fpc_ind_ext - tbl_fea_mode
4656 short tbl_fea_mode - tbl_fea_mode
4657 short tbl_fea_mode - tbl_fea_mode
4658 short tbl_fea_mode - tbl_fea_mode
4659 short tbl_fea_mode - tbl_fea_mode
4660
4661###################################
4662# Address register indirect: (An) #
4663###################################
4664faddr_ind_a0:
4665 mov.l EXC_DREGS+0x8(%a6),%a0 # Get current a0
4666 rts
4667
4668faddr_ind_a1:
4669 mov.l EXC_DREGS+0xc(%a6),%a0 # Get current a1
4670 rts
4671
4672faddr_ind_a2:
4673 mov.l %a2,%a0 # Get current a2
4674 rts
4675
4676faddr_ind_a3:
4677 mov.l %a3,%a0 # Get current a3
4678 rts
4679
4680faddr_ind_a4:
4681 mov.l %a4,%a0 # Get current a4
4682 rts
4683
4684faddr_ind_a5:
4685 mov.l %a5,%a0 # Get current a5
4686 rts
4687
4688faddr_ind_a6:
4689 mov.l (%a6),%a0 # Get current a6
4690 rts
4691
4692faddr_ind_a7:
4693 mov.l EXC_A7(%a6),%a0 # Get current a7
4694 rts
4695
4696#####################################################
4697# Address register indirect w/ postincrement: (An)+ #
4698#####################################################
4699faddr_ind_p_a0:
4700 mov.l EXC_DREGS+0x8(%a6),%d0 # Get current a0
4701 mov.l %d0,%d1
4702 add.l %a0,%d1 # Increment
4703 mov.l %d1,EXC_DREGS+0x8(%a6) # Save incr value
4704 mov.l %d0,%a0
4705 rts
4706
4707faddr_ind_p_a1:
4708 mov.l EXC_DREGS+0xc(%a6),%d0 # Get current a1
4709 mov.l %d0,%d1
4710 add.l %a0,%d1 # Increment
4711 mov.l %d1,EXC_DREGS+0xc(%a6) # Save incr value
4712 mov.l %d0,%a0
4713 rts
4714
4715faddr_ind_p_a2:
4716 mov.l %a2,%d0 # Get current a2
4717 mov.l %d0,%d1
4718 add.l %a0,%d1 # Increment
4719 mov.l %d1,%a2 # Save incr value
4720 mov.l %d0,%a0
4721 rts
4722
4723faddr_ind_p_a3:
4724 mov.l %a3,%d0 # Get current a3
4725 mov.l %d0,%d1
4726 add.l %a0,%d1 # Increment
4727 mov.l %d1,%a3 # Save incr value
4728 mov.l %d0,%a0
4729 rts
4730
4731faddr_ind_p_a4:
4732 mov.l %a4,%d0 # Get current a4
4733 mov.l %d0,%d1
4734 add.l %a0,%d1 # Increment
4735 mov.l %d1,%a4 # Save incr value
4736 mov.l %d0,%a0
4737 rts
4738
4739faddr_ind_p_a5:
4740 mov.l %a5,%d0 # Get current a5
4741 mov.l %d0,%d1
4742 add.l %a0,%d1 # Increment
4743 mov.l %d1,%a5 # Save incr value
4744 mov.l %d0,%a0
4745 rts
4746
4747faddr_ind_p_a6:
4748 mov.l (%a6),%d0 # Get current a6
4749 mov.l %d0,%d1
4750 add.l %a0,%d1 # Increment
4751 mov.l %d1,(%a6) # Save incr value
4752 mov.l %d0,%a0
4753 rts
4754
4755faddr_ind_p_a7:
4756 mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
4757
4758 mov.l EXC_A7(%a6),%d0 # Get current a7
4759 mov.l %d0,%d1
4760 add.l %a0,%d1 # Increment
4761 mov.l %d1,EXC_A7(%a6) # Save incr value
4762 mov.l %d0,%a0
4763 rts
4764
4765####################################################
4766# Address register indirect w/ predecrement: -(An) #
4767####################################################
4768faddr_ind_m_a0:
4769 mov.l EXC_DREGS+0x8(%a6),%d0 # Get current a0
4770 sub.l %a0,%d0 # Decrement
4771 mov.l %d0,EXC_DREGS+0x8(%a6) # Save decr value
4772 mov.l %d0,%a0
4773 rts
4774
4775faddr_ind_m_a1:
4776 mov.l EXC_DREGS+0xc(%a6),%d0 # Get current a1
4777 sub.l %a0,%d0 # Decrement
4778 mov.l %d0,EXC_DREGS+0xc(%a6) # Save decr value
4779 mov.l %d0,%a0
4780 rts
4781
4782faddr_ind_m_a2:
4783 mov.l %a2,%d0 # Get current a2
4784 sub.l %a0,%d0 # Decrement
4785 mov.l %d0,%a2 # Save decr value
4786 mov.l %d0,%a0
4787 rts
4788
4789faddr_ind_m_a3:
4790 mov.l %a3,%d0 # Get current a3
4791 sub.l %a0,%d0 # Decrement
4792 mov.l %d0,%a3 # Save decr value
4793 mov.l %d0,%a0
4794 rts
4795
4796faddr_ind_m_a4:
4797 mov.l %a4,%d0 # Get current a4
4798 sub.l %a0,%d0 # Decrement
4799 mov.l %d0,%a4 # Save decr value
4800 mov.l %d0,%a0
4801 rts
4802
4803faddr_ind_m_a5:
4804 mov.l %a5,%d0 # Get current a5
4805 sub.l %a0,%d0 # Decrement
4806 mov.l %d0,%a5 # Save decr value
4807 mov.l %d0,%a0
4808 rts
4809
4810faddr_ind_m_a6:
4811 mov.l (%a6),%d0 # Get current a6
4812 sub.l %a0,%d0 # Decrement
4813 mov.l %d0,(%a6) # Save decr value
4814 mov.l %d0,%a0
4815 rts
4816
4817faddr_ind_m_a7:
4818 mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
4819
4820 mov.l EXC_A7(%a6),%d0 # Get current a7
4821 sub.l %a0,%d0 # Decrement
4822 mov.l %d0,EXC_A7(%a6) # Save decr value
4823 mov.l %d0,%a0
4824 rts
4825
4826########################################################
4827# Address register indirect w/ displacement: (d16, An) #
4828########################################################
4829faddr_ind_disp_a0:
4830 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4831 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4832 bsr.l _imem_read_word
4833
4834 tst.l %d1 # did ifetch fail?
4835 bne.l iea_iacc # yes
4836
4837 mov.w %d0,%a0 # sign extend displacement
4838
4839 add.l EXC_DREGS+0x8(%a6),%a0 # a0 + d16
4840 rts
4841
4842faddr_ind_disp_a1:
4843 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4844 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4845 bsr.l _imem_read_word
4846
4847 tst.l %d1 # did ifetch fail?
4848 bne.l iea_iacc # yes
4849
4850 mov.w %d0,%a0 # sign extend displacement
4851
4852 add.l EXC_DREGS+0xc(%a6),%a0 # a1 + d16
4853 rts
4854
4855faddr_ind_disp_a2:
4856 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4857 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4858 bsr.l _imem_read_word
4859
4860 tst.l %d1 # did ifetch fail?
4861 bne.l iea_iacc # yes
4862
4863 mov.w %d0,%a0 # sign extend displacement
4864
4865 add.l %a2,%a0 # a2 + d16
4866 rts
4867
4868faddr_ind_disp_a3:
4869 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4870 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4871 bsr.l _imem_read_word
4872
4873 tst.l %d1 # did ifetch fail?
4874 bne.l iea_iacc # yes
4875
4876 mov.w %d0,%a0 # sign extend displacement
4877
4878 add.l %a3,%a0 # a3 + d16
4879 rts
4880
4881faddr_ind_disp_a4:
4882 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4883 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4884 bsr.l _imem_read_word
4885
4886 tst.l %d1 # did ifetch fail?
4887 bne.l iea_iacc # yes
4888
4889 mov.w %d0,%a0 # sign extend displacement
4890
4891 add.l %a4,%a0 # a4 + d16
4892 rts
4893
4894faddr_ind_disp_a5:
4895 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4896 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4897 bsr.l _imem_read_word
4898
4899 tst.l %d1 # did ifetch fail?
4900 bne.l iea_iacc # yes
4901
4902 mov.w %d0,%a0 # sign extend displacement
4903
4904 add.l %a5,%a0 # a5 + d16
4905 rts
4906
4907faddr_ind_disp_a6:
4908 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4909 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4910 bsr.l _imem_read_word
4911
4912 tst.l %d1 # did ifetch fail?
4913 bne.l iea_iacc # yes
4914
4915 mov.w %d0,%a0 # sign extend displacement
4916
4917 add.l (%a6),%a0 # a6 + d16
4918 rts
4919
4920faddr_ind_disp_a7:
4921 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4922 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4923 bsr.l _imem_read_word
4924
4925 tst.l %d1 # did ifetch fail?
4926 bne.l iea_iacc # yes
4927
4928 mov.w %d0,%a0 # sign extend displacement
4929
4930 add.l EXC_A7(%a6),%a0 # a7 + d16
4931 rts
4932
4933########################################################################
4934# Address register indirect w/ index(8-bit displacement): (d8, An, Xn) #
4935# " " " w/ " (base displacement): (bd, An, Xn) #
4936# Memory indirect postindexed: ([bd, An], Xn, od) #
4937# Memory indirect preindexed: ([bd, An, Xn], od) #
4938########################################################################
4939faddr_ind_ext:
4940 addq.l &0x8,%d1
4941 bsr.l fetch_dreg # fetch base areg
4942 mov.l %d0,-(%sp)
4943
4944 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4945 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4946 bsr.l _imem_read_word # fetch extword in d0
4947
4948 tst.l %d1 # did ifetch fail?
4949 bne.l iea_iacc # yes
4950
4951 mov.l (%sp)+,%a0
4952
4953 btst &0x8,%d0
4954 bne.w fcalc_mem_ind
4955
4956 mov.l %d0,L_SCR1(%a6) # hold opword
4957
4958 mov.l %d0,%d1
4959 rol.w &0x4,%d1
4960 andi.w &0xf,%d1 # extract index regno
4961
4962# count on fetch_dreg() not to alter a0...
4963 bsr.l fetch_dreg # fetch index
4964
4965 mov.l %d2,-(%sp) # save d2
4966 mov.l L_SCR1(%a6),%d2 # fetch opword
4967
4968 btst &0xb,%d2 # is it word or long?
4969 bne.b faii8_long
4970 ext.l %d0 # sign extend word index
4971faii8_long:
4972 mov.l %d2,%d1
4973 rol.w &0x7,%d1
4974 andi.l &0x3,%d1 # extract scale value
4975
4976 lsl.l %d1,%d0 # shift index by scale
4977
4978 extb.l %d2 # sign extend displacement
4979 add.l %d2,%d0 # index + disp
4980 add.l %d0,%a0 # An + (index + disp)
4981
4982 mov.l (%sp)+,%d2 # restore old d2
4983 rts
4984
4985###########################
4986# Absolute short: (XXX).W #
4987###########################
4988fabs_short:
4989 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4990 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4991 bsr.l _imem_read_word # fetch short address
4992
4993 tst.l %d1 # did ifetch fail?
4994 bne.l iea_iacc # yes
4995
4996 mov.w %d0,%a0 # return <ea> in a0
4997 rts
4998
4999##########################
5000# Absolute long: (XXX).L #
5001##########################
5002fabs_long:
5003 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5004 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5005 bsr.l _imem_read_long # fetch long address
5006
5007 tst.l %d1 # did ifetch fail?
5008 bne.l iea_iacc # yes
5009
5010 mov.l %d0,%a0 # return <ea> in a0
5011 rts
5012
5013#######################################################
5014# Program counter indirect w/ displacement: (d16, PC) #
5015#######################################################
5016fpc_ind:
5017 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5018 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5019 bsr.l _imem_read_word # fetch word displacement
5020
5021 tst.l %d1 # did ifetch fail?
5022 bne.l iea_iacc # yes
5023
5024 mov.w %d0,%a0 # sign extend displacement
5025
5026 add.l EXC_EXTWPTR(%a6),%a0 # pc + d16
5027
5028# _imem_read_word() increased the extwptr by 2. need to adjust here.
5029 subq.l &0x2,%a0 # adjust <ea>
5030 rts
5031
5032##########################################################
5033# PC indirect w/ index(8-bit displacement): (d8, PC, An) #
5034# " " w/ " (base displacement): (bd, PC, An) #
5035# PC memory indirect postindexed: ([bd, PC], Xn, od) #
5036# PC memory indirect preindexed: ([bd, PC, Xn], od) #
5037##########################################################
5038fpc_ind_ext:
5039 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5040 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5041 bsr.l _imem_read_word # fetch ext word
5042
5043 tst.l %d1 # did ifetch fail?
5044 bne.l iea_iacc # yes
5045
5046 mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0
5047 subq.l &0x2,%a0 # adjust base
5048
5049 btst &0x8,%d0 # is disp only 8 bits?
5050 bne.w fcalc_mem_ind # calc memory indirect
5051
5052 mov.l %d0,L_SCR1(%a6) # store opword
5053
5054 mov.l %d0,%d1 # make extword copy
5055 rol.w &0x4,%d1 # rotate reg num into place
5056 andi.w &0xf,%d1 # extract register number
5057
5058# count on fetch_dreg() not to alter a0...
5059 bsr.l fetch_dreg # fetch index
5060
5061 mov.l %d2,-(%sp) # save d2
5062 mov.l L_SCR1(%a6),%d2 # fetch opword
5063
5064 btst &0xb,%d2 # is index word or long?
5065 bne.b fpii8_long # long
5066 ext.l %d0 # sign extend word index
5067fpii8_long:
5068 mov.l %d2,%d1
5069 rol.w &0x7,%d1 # rotate scale value into place
5070 andi.l &0x3,%d1 # extract scale value
5071
5072 lsl.l %d1,%d0 # shift index by scale
5073
5074 extb.l %d2 # sign extend displacement
5075 add.l %d2,%d0 # disp + index
5076 add.l %d0,%a0 # An + (index + disp)
5077
5078 mov.l (%sp)+,%d2 # restore temp register
5079 rts
5080
5081# d2 = index
5082# d3 = base
5083# d4 = od
5084# d5 = extword
5085fcalc_mem_ind:
5086 btst &0x6,%d0 # is the index suppressed?
5087 beq.b fcalc_index
5088
5089 movm.l &0x3c00,-(%sp) # save d2-d5
5090
5091 mov.l %d0,%d5 # put extword in d5
5092 mov.l %a0,%d3 # put base in d3
5093
5094 clr.l %d2 # yes, so index = 0
5095 bra.b fbase_supp_ck
5096
5097# index:
5098fcalc_index:
5099 mov.l %d0,L_SCR1(%a6) # save d0 (opword)
5100 bfextu %d0{&16:&4},%d1 # fetch dreg index
5101 bsr.l fetch_dreg
5102
5103 movm.l &0x3c00,-(%sp) # save d2-d5
5104 mov.l %d0,%d2 # put index in d2
5105 mov.l L_SCR1(%a6),%d5
5106 mov.l %a0,%d3
5107
5108 btst &0xb,%d5 # is index word or long?
5109 bne.b fno_ext
5110 ext.l %d2
5111
5112fno_ext:
5113 bfextu %d5{&21:&2},%d0
5114 lsl.l %d0,%d2
5115
5116# base address (passed as parameter in d3):
5117# we clear the value here if it should actually be suppressed.
5118fbase_supp_ck:
5119 btst &0x7,%d5 # is the bd suppressed?
5120 beq.b fno_base_sup
5121 clr.l %d3
5122
5123# base displacement:
5124fno_base_sup:
5125 bfextu %d5{&26:&2},%d0 # get bd size
5126# beq.l fmovm_error # if (size == 0) it's reserved
5127
5128 cmpi.b %d0,&0x2
5129 blt.b fno_bd
5130 beq.b fget_word_bd
5131
5132 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5133 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5134 bsr.l _imem_read_long
5135
5136 tst.l %d1 # did ifetch fail?
5137 bne.l fcea_iacc # yes
5138
5139 bra.b fchk_ind
5140
5141fget_word_bd:
5142 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5143 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5144 bsr.l _imem_read_word
5145
5146 tst.l %d1 # did ifetch fail?
5147 bne.l fcea_iacc # yes
5148
5149 ext.l %d0 # sign extend bd
5150
5151fchk_ind:
5152 add.l %d0,%d3 # base += bd
5153
5154# outer displacement:
5155fno_bd:
5156 bfextu %d5{&30:&2},%d0 # is od suppressed?
5157 beq.w faii_bd
5158
5159 cmpi.b %d0,&0x2
5160 blt.b fnull_od
5161 beq.b fword_od
5162
5163 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5164 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5165 bsr.l _imem_read_long
5166
5167 tst.l %d1 # did ifetch fail?
5168 bne.l fcea_iacc # yes
5169
5170 bra.b fadd_them
5171
5172fword_od:
5173 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5174 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5175 bsr.l _imem_read_word
5176
5177 tst.l %d1 # did ifetch fail?
5178 bne.l fcea_iacc # yes
5179
5180 ext.l %d0 # sign extend od
5181 bra.b fadd_them
5182
5183fnull_od:
5184 clr.l %d0
5185
5186fadd_them:
5187 mov.l %d0,%d4
5188
5189 btst &0x2,%d5 # pre or post indexing?
5190 beq.b fpre_indexed
5191
5192 mov.l %d3,%a0
5193 bsr.l _dmem_read_long
5194
5195 tst.l %d1 # did dfetch fail?
5196 bne.w fcea_err # yes
5197
5198 add.l %d2,%d0 # <ea> += index
5199 add.l %d4,%d0 # <ea> += od
5200 bra.b fdone_ea
5201
5202fpre_indexed:
5203 add.l %d2,%d3 # preindexing
5204 mov.l %d3,%a0
5205 bsr.l _dmem_read_long
5206
5207 tst.l %d1 # did dfetch fail?
5208 bne.w fcea_err # yes
5209
5210 add.l %d4,%d0 # ea += od
5211 bra.b fdone_ea
5212
5213faii_bd:
5214 add.l %d2,%d3 # ea = (base + bd) + index
5215 mov.l %d3,%d0
5216fdone_ea:
5217 mov.l %d0,%a0
5218
5219 movm.l (%sp)+,&0x003c # restore d2-d5
5220 rts
5221
5222#########################################################
5223fcea_err:
5224 mov.l %d3,%a0
5225
5226 movm.l (%sp)+,&0x003c # restore d2-d5
5227 mov.w &0x0101,%d0
5228 bra.l iea_dacc
5229
5230fcea_iacc:
5231 movm.l (%sp)+,&0x003c # restore d2-d5
5232 bra.l iea_iacc
5233
5234fmovm_out_err:
5235 bsr.l restore
5236 mov.w &0x00e1,%d0
5237 bra.b fmovm_err
5238
5239fmovm_in_err:
5240 bsr.l restore
5241 mov.w &0x0161,%d0
5242
5243fmovm_err:
5244 mov.l L_SCR1(%a6),%a0
5245 bra.l iea_dacc
5246
5247#########################################################################
5248# XDEF **************************************************************** #
5249# fmovm_ctrl(): emulate fmovm.l of control registers instr #
5250# #
5251# XREF **************************************************************** #
5252# _imem_read_long() - read longword from memory #
5253# iea_iacc() - _imem_read_long() failed; error recovery #
5254# #
5255# INPUT *************************************************************** #
5256# None #
5257# #
5258# OUTPUT ************************************************************** #
5259# If _imem_read_long() doesn't fail: #
5260# USER_FPCR(a6) = new FPCR value #
5261# USER_FPSR(a6) = new FPSR value #
5262# USER_FPIAR(a6) = new FPIAR value #
5263# #
5264# ALGORITHM *********************************************************** #
5265# Decode the instruction type by looking at the extension word #
5266# in order to see how many control registers to fetch from memory. #
5267# Fetch them using _imem_read_long(). If this fetch fails, exit through #
5268# the special access error exit handler iea_iacc(). #
5269# #
5270# Instruction word decoding: #
5271# #
5272# fmovem.l #<data>, {FPIAR&|FPCR&|FPSR} #
5273# #
5274# WORD1 WORD2 #
5275# 1111 0010 00 111100 100$ $$00 0000 0000 #
5276# #
5277# $$$ (100): FPCR #
5278# (010): FPSR #
5279# (001): FPIAR #
5280# (000): FPIAR #
5281# #
5282#########################################################################
5283
5284 global fmovm_ctrl
5285fmovm_ctrl:
5286 mov.b EXC_EXTWORD(%a6),%d0 # fetch reg select bits
5287 cmpi.b %d0,&0x9c # fpcr & fpsr & fpiar ?
5288 beq.w fctrl_in_7 # yes
5289 cmpi.b %d0,&0x98 # fpcr & fpsr ?
5290 beq.w fctrl_in_6 # yes
5291 cmpi.b %d0,&0x94 # fpcr & fpiar ?
5292 beq.b fctrl_in_5 # yes
5293
5294# fmovem.l #<data>, fpsr/fpiar
5295fctrl_in_3:
5296 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5297 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5298 bsr.l _imem_read_long # fetch FPSR from mem
5299
5300 tst.l %d1 # did ifetch fail?
5301 bne.l iea_iacc # yes
5302
5303 mov.l %d0,USER_FPSR(%a6) # store new FPSR to stack
5304 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5305 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5306 bsr.l _imem_read_long # fetch FPIAR from mem
5307
5308 tst.l %d1 # did ifetch fail?
5309 bne.l iea_iacc # yes
5310
5311 mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to stack
5312 rts
5313
5314# fmovem.l #<data>, fpcr/fpiar
5315fctrl_in_5:
5316 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5317 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5318 bsr.l _imem_read_long # fetch FPCR from mem
5319
5320 tst.l %d1 # did ifetch fail?
5321 bne.l iea_iacc # yes
5322
5323 mov.l %d0,USER_FPCR(%a6) # store new FPCR to stack
5324 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5325 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5326 bsr.l _imem_read_long # fetch FPIAR from mem
5327
5328 tst.l %d1 # did ifetch fail?
5329 bne.l iea_iacc # yes
5330
5331 mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to stack
5332 rts
5333
5334# fmovem.l #<data>, fpcr/fpsr
5335fctrl_in_6:
5336 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5337 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5338 bsr.l _imem_read_long # fetch FPCR from mem
5339
5340 tst.l %d1 # did ifetch fail?
5341 bne.l iea_iacc # yes
5342
5343 mov.l %d0,USER_FPCR(%a6) # store new FPCR to mem
5344 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5345 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5346 bsr.l _imem_read_long # fetch FPSR from mem
5347
5348 tst.l %d1 # did ifetch fail?
5349 bne.l iea_iacc # yes
5350
5351 mov.l %d0,USER_FPSR(%a6) # store new FPSR to mem
5352 rts
5353
5354# fmovem.l #<data>, fpcr/fpsr/fpiar
5355fctrl_in_7:
5356 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5357 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5358 bsr.l _imem_read_long # fetch FPCR from mem
5359
5360 tst.l %d1 # did ifetch fail?
5361 bne.l iea_iacc # yes
5362
5363 mov.l %d0,USER_FPCR(%a6) # store new FPCR to mem
5364 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5365 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5366 bsr.l _imem_read_long # fetch FPSR from mem
5367
5368 tst.l %d1 # did ifetch fail?
5369 bne.l iea_iacc # yes
5370
5371 mov.l %d0,USER_FPSR(%a6) # store new FPSR to mem
5372 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5373 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5374 bsr.l _imem_read_long # fetch FPIAR from mem
5375
5376 tst.l %d1 # did ifetch fail?
5377 bne.l iea_iacc # yes
5378
5379 mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to mem
5380 rts
5381
5382##########################################################################
5383
5384#########################################################################
5385# XDEF **************************************************************** #
5386# addsub_scaler2(): scale inputs to fadd/fsub such that no #
5387# OVFL/UNFL exceptions will result #
5388# #
5389# XREF **************************************************************** #
5390# norm() - normalize mantissa after adjusting exponent #
5391# #
5392# INPUT *************************************************************** #
5393# FP_SRC(a6) = fp op1(src) #
5394# FP_DST(a6) = fp op2(dst) #
5395# #
5396# OUTPUT ************************************************************** #
5397# FP_SRC(a6) = fp op1 scaled(src) #
5398# FP_DST(a6) = fp op2 scaled(dst) #
5399# d0 = scale amount #
5400# #
5401# ALGORITHM *********************************************************** #
5402# If the DST exponent is > the SRC exponent, set the DST exponent #
5403# equal to 0x3fff and scale the SRC exponent by the value that the #
5404# DST exponent was scaled by. If the SRC exponent is greater or equal, #
5405# do the opposite. Return this scale factor in d0. #
5406# If the two exponents differ by > the number of mantissa bits #
5407# plus two, then set the smallest exponent to a very small value as a #
5408# quick shortcut. #
5409# #
5410#########################################################################
5411
5412 global addsub_scaler2
5413addsub_scaler2:
5414 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
5415 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
5416 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
5417 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
5418 mov.w SRC_EX(%a0),%d0
5419 mov.w DST_EX(%a1),%d1
5420 mov.w %d0,FP_SCR0_EX(%a6)
5421 mov.w %d1,FP_SCR1_EX(%a6)
5422
5423 andi.w &0x7fff,%d0
5424 andi.w &0x7fff,%d1
5425 mov.w %d0,L_SCR1(%a6) # store src exponent
5426 mov.w %d1,2+L_SCR1(%a6) # store dst exponent
5427
5428 cmp.w %d0, %d1 # is src exp >= dst exp?
5429 bge.l src_exp_ge2
5430
5431# dst exp is > src exp; scale dst to exp = 0x3fff
5432dst_exp_gt2:
5433 bsr.l scale_to_zero_dst
5434 mov.l %d0,-(%sp) # save scale factor
5435
5436 cmpi.b STAG(%a6),&DENORM # is dst denormalized?
5437 bne.b cmpexp12
5438
5439 lea FP_SCR0(%a6),%a0
5440 bsr.l norm # normalize the denorm; result is new exp
5441 neg.w %d0 # new exp = -(shft val)
5442 mov.w %d0,L_SCR1(%a6) # inset new exp
5443
5444cmpexp12:
5445 mov.w 2+L_SCR1(%a6),%d0
5446 subi.w &mantissalen+2,%d0 # subtract mantissalen+2 from larger exp
5447
5448 cmp.w %d0,L_SCR1(%a6) # is difference >= len(mantissa)+2?
5449 bge.b quick_scale12
5450
5451 mov.w L_SCR1(%a6),%d0
5452 add.w 0x2(%sp),%d0 # scale src exponent by scale factor
5453 mov.w FP_SCR0_EX(%a6),%d1
5454 and.w &0x8000,%d1
5455 or.w %d1,%d0 # concat {sgn,new exp}
5456 mov.w %d0,FP_SCR0_EX(%a6) # insert new dst exponent
5457
5458 mov.l (%sp)+,%d0 # return SCALE factor
5459 rts
5460
5461quick_scale12:
5462 andi.w &0x8000,FP_SCR0_EX(%a6) # zero src exponent
5463 bset &0x0,1+FP_SCR0_EX(%a6) # set exp = 1
5464
5465 mov.l (%sp)+,%d0 # return SCALE factor
5466 rts
5467
5468# src exp is >= dst exp; scale src to exp = 0x3fff
5469src_exp_ge2:
5470 bsr.l scale_to_zero_src
5471 mov.l %d0,-(%sp) # save scale factor
5472
5473 cmpi.b DTAG(%a6),&DENORM # is dst denormalized?
5474 bne.b cmpexp22
5475 lea FP_SCR1(%a6),%a0
5476 bsr.l norm # normalize the denorm; result is new exp
5477 neg.w %d0 # new exp = -(shft val)
5478 mov.w %d0,2+L_SCR1(%a6) # inset new exp
5479
5480cmpexp22:
5481 mov.w L_SCR1(%a6),%d0
5482 subi.w &mantissalen+2,%d0 # subtract mantissalen+2 from larger exp
5483
5484 cmp.w %d0,2+L_SCR1(%a6) # is difference >= len(mantissa)+2?
5485 bge.b quick_scale22
5486
5487 mov.w 2+L_SCR1(%a6),%d0
5488 add.w 0x2(%sp),%d0 # scale dst exponent by scale factor
5489 mov.w FP_SCR1_EX(%a6),%d1
5490 andi.w &0x8000,%d1
5491 or.w %d1,%d0 # concat {sgn,new exp}
5492 mov.w %d0,FP_SCR1_EX(%a6) # insert new dst exponent
5493
5494 mov.l (%sp)+,%d0 # return SCALE factor
5495 rts
5496
5497quick_scale22:
5498 andi.w &0x8000,FP_SCR1_EX(%a6) # zero dst exponent
5499 bset &0x0,1+FP_SCR1_EX(%a6) # set exp = 1
5500
5501 mov.l (%sp)+,%d0 # return SCALE factor
5502 rts
5503
5504##########################################################################
5505
5506#########################################################################
5507# XDEF **************************************************************** #
5508# scale_to_zero_src(): scale the exponent of extended precision #
5509# value at FP_SCR0(a6). #
5510# #
5511# XREF **************************************************************** #
5512# norm() - normalize the mantissa if the operand was a DENORM #
5513# #
5514# INPUT *************************************************************** #
5515# FP_SCR0(a6) = extended precision operand to be scaled #
5516# #
5517# OUTPUT ************************************************************** #
5518# FP_SCR0(a6) = scaled extended precision operand #
5519# d0 = scale value #
5520# #
5521# ALGORITHM *********************************************************** #
5522# Set the exponent of the input operand to 0x3fff. Save the value #
5523# of the difference between the original and new exponent. Then, #
5524# normalize the operand if it was a DENORM. Add this normalization #
5525# value to the previous value. Return the result. #
5526# #
5527#########################################################################
5528
5529 global scale_to_zero_src
5530scale_to_zero_src:
5531 mov.w FP_SCR0_EX(%a6),%d1 # extract operand's {sgn,exp}
5532 mov.w %d1,%d0 # make a copy
5533
5534 andi.l &0x7fff,%d1 # extract operand's exponent
5535
5536 andi.w &0x8000,%d0 # extract operand's sgn
5537 or.w &0x3fff,%d0 # insert new operand's exponent(=0)
5538
5539 mov.w %d0,FP_SCR0_EX(%a6) # insert biased exponent
5540
5541 cmpi.b STAG(%a6),&DENORM # is operand normalized?
5542 beq.b stzs_denorm # normalize the DENORM
5543
5544stzs_norm:
5545 mov.l &0x3fff,%d0
5546 sub.l %d1,%d0 # scale = BIAS + (-exp)
5547
5548 rts
5549
5550stzs_denorm:
5551 lea FP_SCR0(%a6),%a0 # pass ptr to src op
5552 bsr.l norm # normalize denorm
5553 neg.l %d0 # new exponent = -(shft val)
5554 mov.l %d0,%d1 # prepare for op_norm call
5555 bra.b stzs_norm # finish scaling
5556
5557###
5558
5559#########################################################################
5560# XDEF **************************************************************** #
5561# scale_sqrt(): scale the input operand exponent so a subsequent #
5562# fsqrt operation won't take an exception. #
5563# #
5564# XREF **************************************************************** #
5565# norm() - normalize the mantissa if the operand was a DENORM #
5566# #
5567# INPUT *************************************************************** #
5568# FP_SCR0(a6) = extended precision operand to be scaled #
5569# #
5570# OUTPUT ************************************************************** #
5571# FP_SCR0(a6) = scaled extended precision operand #
5572# d0 = scale value #
5573# #
5574# ALGORITHM *********************************************************** #
5575# If the input operand is a DENORM, normalize it. #
5576# If the exponent of the input operand is even, set the exponent #
5577# to 0x3ffe and return a scale factor of "(exp-0x3ffe)/2". If the #
5578# exponent of the input operand is off, set the exponent to ox3fff and #
5579# return a scale factor of "(exp-0x3fff)/2". #
5580# #
5581#########################################################################
5582
5583 global scale_sqrt
5584scale_sqrt:
5585 cmpi.b STAG(%a6),&DENORM # is operand normalized?
5586 beq.b ss_denorm # normalize the DENORM
5587
5588 mov.w FP_SCR0_EX(%a6),%d1 # extract operand's {sgn,exp}
5589 andi.l &0x7fff,%d1 # extract operand's exponent
5590
5591 andi.w &0x8000,FP_SCR0_EX(%a6) # extract operand's sgn
5592
5593 btst &0x0,%d1 # is exp even or odd?
5594 beq.b ss_norm_even
5595
5596 ori.w &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
5597
5598 mov.l &0x3fff,%d0
5599 sub.l %d1,%d0 # scale = BIAS + (-exp)
5600 asr.l &0x1,%d0 # divide scale factor by 2
5601 rts
5602
5603ss_norm_even:
5604 ori.w &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
5605
5606 mov.l &0x3ffe,%d0
5607 sub.l %d1,%d0 # scale = BIAS + (-exp)
5608 asr.l &0x1,%d0 # divide scale factor by 2
5609 rts
5610
5611ss_denorm:
5612 lea FP_SCR0(%a6),%a0 # pass ptr to src op
5613 bsr.l norm # normalize denorm
5614
5615 btst &0x0,%d0 # is exp even or odd?
5616 beq.b ss_denorm_even
5617
5618 ori.w &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
5619
5620 add.l &0x3fff,%d0
5621 asr.l &0x1,%d0 # divide scale factor by 2
5622 rts
5623
5624ss_denorm_even:
5625 ori.w &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
5626
5627 add.l &0x3ffe,%d0
5628 asr.l &0x1,%d0 # divide scale factor by 2
5629 rts
5630
5631###
5632
5633#########################################################################
5634# XDEF **************************************************************** #
5635# scale_to_zero_dst(): scale the exponent of extended precision #
5636# value at FP_SCR1(a6). #
5637# #
5638# XREF **************************************************************** #
5639# norm() - normalize the mantissa if the operand was a DENORM #
5640# #
5641# INPUT *************************************************************** #
5642# FP_SCR1(a6) = extended precision operand to be scaled #
5643# #
5644# OUTPUT ************************************************************** #
5645# FP_SCR1(a6) = scaled extended precision operand #
5646# d0 = scale value #
5647# #
5648# ALGORITHM *********************************************************** #
5649# Set the exponent of the input operand to 0x3fff. Save the value #
5650# of the difference between the original and new exponent. Then, #
5651# normalize the operand if it was a DENORM. Add this normalization #
5652# value to the previous value. Return the result. #
5653# #
5654#########################################################################
5655
5656 global scale_to_zero_dst
5657scale_to_zero_dst:
5658 mov.w FP_SCR1_EX(%a6),%d1 # extract operand's {sgn,exp}
5659 mov.w %d1,%d0 # make a copy
5660
5661 andi.l &0x7fff,%d1 # extract operand's exponent
5662
5663 andi.w &0x8000,%d0 # extract operand's sgn
5664 or.w &0x3fff,%d0 # insert new operand's exponent(=0)
5665
5666 mov.w %d0,FP_SCR1_EX(%a6) # insert biased exponent
5667
5668 cmpi.b DTAG(%a6),&DENORM # is operand normalized?
5669 beq.b stzd_denorm # normalize the DENORM
5670
5671stzd_norm:
5672 mov.l &0x3fff,%d0
5673 sub.l %d1,%d0 # scale = BIAS + (-exp)
5674 rts
5675
5676stzd_denorm:
5677 lea FP_SCR1(%a6),%a0 # pass ptr to dst op
5678 bsr.l norm # normalize denorm
5679 neg.l %d0 # new exponent = -(shft val)
5680 mov.l %d0,%d1 # prepare for op_norm call
5681 bra.b stzd_norm # finish scaling
5682
5683##########################################################################
5684
5685#########################################################################
5686# XDEF **************************************************************** #
5687# res_qnan(): return default result w/ QNAN operand for dyadic #
5688# res_snan(): return default result w/ SNAN operand for dyadic #
5689# res_qnan_1op(): return dflt result w/ QNAN operand for monadic #
5690# res_snan_1op(): return dflt result w/ SNAN operand for monadic #
5691# #
5692# XREF **************************************************************** #
5693# None #
5694# #
5695# INPUT *************************************************************** #
5696# FP_SRC(a6) = pointer to extended precision src operand #
5697# FP_DST(a6) = pointer to extended precision dst operand #
5698# #
5699# OUTPUT ************************************************************** #
5700# fp0 = default result #
5701# #
5702# ALGORITHM *********************************************************** #
5703# If either operand (but not both operands) of an operation is a #
5704# nonsignalling NAN, then that NAN is returned as the result. If both #
5705# operands are nonsignalling NANs, then the destination operand #
5706# nonsignalling NAN is returned as the result. #
5707# If either operand to an operation is a signalling NAN (SNAN), #
5708# then, the SNAN bit is set in the FPSR EXC byte. If the SNAN trap #
5709# enable bit is set in the FPCR, then the trap is taken and the #
5710# destination is not modified. If the SNAN trap enable bit is not set, #
5711# then the SNAN is converted to a nonsignalling NAN (by setting the #
5712# SNAN bit in the operand to one), and the operation continues as #
5713# described in the preceding paragraph, for nonsignalling NANs. #
5714# Make sure the appropriate FPSR bits are set before exiting. #
5715# #
5716#########################################################################
5717
5718 global res_qnan
5719 global res_snan
5720res_qnan:
5721res_snan:
5722 cmp.b DTAG(%a6), &SNAN # is the dst an SNAN?
5723 beq.b dst_snan2
5724 cmp.b DTAG(%a6), &QNAN # is the dst a QNAN?
5725 beq.b dst_qnan2
5726src_nan:
5727 cmp.b STAG(%a6), &QNAN
5728 beq.b src_qnan2
5729 global res_snan_1op
5730res_snan_1op:
5731src_snan2:
5732 bset &0x6, FP_SRC_HI(%a6) # set SNAN bit
5733 or.l &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
5734 lea FP_SRC(%a6), %a0
5735 bra.b nan_comp
5736 global res_qnan_1op
5737res_qnan_1op:
5738src_qnan2:
5739 or.l &nan_mask, USER_FPSR(%a6)
5740 lea FP_SRC(%a6), %a0
5741 bra.b nan_comp
5742dst_snan2:
5743 or.l &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
5744 bset &0x6, FP_DST_HI(%a6) # set SNAN bit
5745 lea FP_DST(%a6), %a0
5746 bra.b nan_comp
5747dst_qnan2:
5748 lea FP_DST(%a6), %a0
5749 cmp.b STAG(%a6), &SNAN
5750 bne nan_done
5751 or.l &aiop_mask+snan_mask, USER_FPSR(%a6)
5752nan_done:
5753 or.l &nan_mask, USER_FPSR(%a6)
5754nan_comp:
5755 btst &0x7, FTEMP_EX(%a0) # is NAN neg?
5756 beq.b nan_not_neg
5757 or.l &neg_mask, USER_FPSR(%a6)
5758nan_not_neg:
5759 fmovm.x (%a0), &0x80
5760 rts
5761
5762#########################################################################
5763# XDEF **************************************************************** #
5764# res_operr(): return default result during operand error #
5765# #
5766# XREF **************************************************************** #
5767# None #
5768# #
5769# INPUT *************************************************************** #
5770# None #
5771# #
5772# OUTPUT ************************************************************** #
5773# fp0 = default operand error result #
5774# #
5775# ALGORITHM *********************************************************** #
5776# An nonsignalling NAN is returned as the default result when #
5777# an operand error occurs for the following cases: #
5778# #
5779# Multiply: (Infinity x Zero) #
5780# Divide : (Zero / Zero) || (Infinity / Infinity) #
5781# #
5782#########################################################################
5783
5784 global res_operr
5785res_operr:
5786 or.l &nan_mask+operr_mask+aiop_mask, USER_FPSR(%a6)
5787 fmovm.x nan_return(%pc), &0x80
5788 rts
5789
5790nan_return:
5791 long 0x7fff0000, 0xffffffff, 0xffffffff
5792
5793#########################################################################
5794# XDEF **************************************************************** #
5795# _denorm(): denormalize an intermediate result #
5796# #
5797# XREF **************************************************************** #
5798# None #
5799# #
5800# INPUT *************************************************************** #
5801# a0 = points to the operand to be denormalized #
5802# (in the internal extended format) #
5803# #
5804# d0 = rounding precision #
5805# #
5806# OUTPUT ************************************************************** #
5807# a0 = pointer to the denormalized result #
5808# (in the internal extended format) #
5809# #
5810# d0 = guard,round,sticky #
5811# #
5812# ALGORITHM *********************************************************** #
5813# According to the exponent underflow threshold for the given #
5814# precision, shift the mantissa bits to the right in order raise the #
5815# exponent of the operand to the threshold value. While shifting the #
5816# mantissa bits right, maintain the value of the guard, round, and #
5817# sticky bits. #
5818# other notes: #
5819# (1) _denorm() is called by the underflow routines #
5820# (2) _denorm() does NOT affect the status register #
5821# #
5822#########################################################################
5823
5824#
5825# table of exponent threshold values for each precision
5826#
5827tbl_thresh:
5828 short 0x0
5829 short sgl_thresh
5830 short dbl_thresh
5831
5832 global _denorm
5833_denorm:
5834#
5835# Load the exponent threshold for the precision selected and check
5836# to see if (threshold - exponent) is > 65 in which case we can
5837# simply calculate the sticky bit and zero the mantissa. otherwise
5838# we have to call the denormalization routine.
5839#
5840 lsr.b &0x2, %d0 # shift prec to lo bits
5841 mov.w (tbl_thresh.b,%pc,%d0.w*2), %d1 # load prec threshold
5842 mov.w %d1, %d0 # copy d1 into d0
5843 sub.w FTEMP_EX(%a0), %d0 # diff = threshold - exp
5844 cmpi.w %d0, &66 # is diff > 65? (mant + g,r bits)
5845 bpl.b denorm_set_stky # yes; just calc sticky
5846
5847 clr.l %d0 # clear g,r,s
5848 btst &inex2_bit, FPSR_EXCEPT(%a6) # yes; was INEX2 set?
5849 beq.b denorm_call # no; don't change anything
5850 bset &29, %d0 # yes; set sticky bit
5851
5852denorm_call:
5853 bsr.l dnrm_lp # denormalize the number
5854 rts
5855
5856#
5857# all bit would have been shifted off during the denorm so simply
5858# calculate if the sticky should be set and clear the entire mantissa.
5859#
5860denorm_set_stky:
5861 mov.l &0x20000000, %d0 # set sticky bit in return value
5862 mov.w %d1, FTEMP_EX(%a0) # load exp with threshold
5863 clr.l FTEMP_HI(%a0) # set d1 = 0 (ms mantissa)
5864 clr.l FTEMP_LO(%a0) # set d2 = 0 (ms mantissa)
5865 rts
5866
5867# #
5868# dnrm_lp(): normalize exponent/mantissa to specified threshhold #
5869# #
5870# INPUT: #
5871# %a0 : points to the operand to be denormalized #
5872# %d0{31:29} : initial guard,round,sticky #
5873# %d1{15:0} : denormalization threshold #
5874# OUTPUT: #
5875# %a0 : points to the denormalized operand #
5876# %d0{31:29} : final guard,round,sticky #
5877# #
5878
5879# *** Local Equates *** #
5880set GRS, L_SCR2 # g,r,s temp storage
5881set FTEMP_LO2, L_SCR1 # FTEMP_LO copy
5882
5883 global dnrm_lp
5884dnrm_lp:
5885
5886#
5887# make a copy of FTEMP_LO and place the g,r,s bits directly after it
5888# in memory so as to make the bitfield extraction for denormalization easier.
5889#
5890 mov.l FTEMP_LO(%a0), FTEMP_LO2(%a6) # make FTEMP_LO copy
5891 mov.l %d0, GRS(%a6) # place g,r,s after it
5892
5893#
5894# check to see how much less than the underflow threshold the operand
5895# exponent is.
5896#
5897 mov.l %d1, %d0 # copy the denorm threshold
5898 sub.w FTEMP_EX(%a0), %d1 # d1 = threshold - uns exponent
5899 ble.b dnrm_no_lp # d1 <= 0
5900 cmpi.w %d1, &0x20 # is ( 0 <= d1 < 32) ?
5901 blt.b case_1 # yes
5902 cmpi.w %d1, &0x40 # is (32 <= d1 < 64) ?
5903 blt.b case_2 # yes
5904 bra.w case_3 # (d1 >= 64)
5905
5906#
5907# No normalization necessary
5908#
5909dnrm_no_lp:
5910 mov.l GRS(%a6), %d0 # restore original g,r,s
5911 rts
5912
5913#
5914# case (0<d1<32)
5915#
5916# %d0 = denorm threshold
5917# %d1 = "n" = amt to shift
5918#
5919# ---------------------------------------------------------
5920# | FTEMP_HI | FTEMP_LO |grs000.........000|
5921# ---------------------------------------------------------
5922# <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
5923# \ \ \ \
5924# \ \ \ \
5925# \ \ \ \
5926# \ \ \ \
5927# \ \ \ \
5928# \ \ \ \
5929# \ \ \ \
5930# \ \ \ \
5931# <-(n)-><-(32 - n)-><------(32)-------><------(32)------->
5932# ---------------------------------------------------------
5933# |0.....0| NEW_HI | NEW_FTEMP_LO |grs |
5934# ---------------------------------------------------------
5935#
5936case_1:
5937 mov.l %d2, -(%sp) # create temp storage
5938
5939 mov.w %d0, FTEMP_EX(%a0) # exponent = denorm threshold
5940 mov.l &32, %d0
5941 sub.w %d1, %d0 # %d0 = 32 - %d1
5942
5943 cmpi.w %d1, &29 # is shft amt >= 29
5944 blt.b case1_extract # no; no fix needed
5945 mov.b GRS(%a6), %d2
5946 or.b %d2, 3+FTEMP_LO2(%a6)
5947
5948case1_extract:
5949 bfextu FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_HI
5950 bfextu FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new FTEMP_LO
5951 bfextu FTEMP_LO2(%a6){%d0:&32}, %d0 # %d0 = new G,R,S
5952
5953 mov.l %d2, FTEMP_HI(%a0) # store new FTEMP_HI
5954 mov.l %d1, FTEMP_LO(%a0) # store new FTEMP_LO
5955
5956 bftst %d0{&2:&30} # were bits shifted off?
5957 beq.b case1_sticky_clear # no; go finish
5958 bset &rnd_stky_bit, %d0 # yes; set sticky bit
5959
5960case1_sticky_clear:
5961 and.l &0xe0000000, %d0 # clear all but G,R,S
5962 mov.l (%sp)+, %d2 # restore temp register
5963 rts
5964
5965#
5966# case (32<=d1<64)
5967#
5968# %d0 = denorm threshold
5969# %d1 = "n" = amt to shift
5970#
5971# ---------------------------------------------------------
5972# | FTEMP_HI | FTEMP_LO |grs000.........000|
5973# ---------------------------------------------------------
5974# <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
5975# \ \ \
5976# \ \ \
5977# \ \ -------------------
5978# \ -------------------- \
5979# ------------------- \ \
5980# \ \ \
5981# \ \ \
5982# \ \ \
5983# <-------(32)------><-(n)-><-(32 - n)-><------(32)------->
5984# ---------------------------------------------------------
5985# |0...............0|0....0| NEW_LO |grs |
5986# ---------------------------------------------------------
5987#
5988case_2:
5989 mov.l %d2, -(%sp) # create temp storage
5990
5991 mov.w %d0, FTEMP_EX(%a0) # exponent = denorm threshold
5992 subi.w &0x20, %d1 # %d1 now between 0 and 32
5993 mov.l &0x20, %d0
5994 sub.w %d1, %d0 # %d0 = 32 - %d1
5995
5996# subtle step here; or in the g,r,s at the bottom of FTEMP_LO to minimize
5997# the number of bits to check for the sticky detect.
5998# it only plays a role in shift amounts of 61-63.
5999 mov.b GRS(%a6), %d2
6000 or.b %d2, 3+FTEMP_LO2(%a6)
6001
6002 bfextu FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_LO
6003 bfextu FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new G,R,S
6004
6005 bftst %d1{&2:&30} # were any bits shifted off?
6006 bne.b case2_set_sticky # yes; set sticky bit
6007 bftst FTEMP_LO2(%a6){%d0:&31} # were any bits shifted off?
6008 bne.b case2_set_sticky # yes; set sticky bit
6009
6010 mov.l %d1, %d0 # move new G,R,S to %d0
6011 bra.b case2_end
6012
6013case2_set_sticky:
6014 mov.l %d1, %d0 # move new G,R,S to %d0
6015 bset &rnd_stky_bit, %d0 # set sticky bit
6016
6017case2_end:
6018 clr.l FTEMP_HI(%a0) # store FTEMP_HI = 0
6019 mov.l %d2, FTEMP_LO(%a0) # store FTEMP_LO
6020 and.l &0xe0000000, %d0 # clear all but G,R,S
6021
6022 mov.l (%sp)+,%d2 # restore temp register
6023 rts
6024
6025#
6026# case (d1>=64)
6027#
6028# %d0 = denorm threshold
6029# %d1 = amt to shift
6030#
6031case_3:
6032 mov.w %d0, FTEMP_EX(%a0) # insert denorm threshold
6033
6034 cmpi.w %d1, &65 # is shift amt > 65?
6035 blt.b case3_64 # no; it's == 64
6036 beq.b case3_65 # no; it's == 65
6037
6038#
6039# case (d1>65)
6040#
6041# Shift value is > 65 and out of range. All bits are shifted off.
6042# Return a zero mantissa with the sticky bit set
6043#
6044 clr.l FTEMP_HI(%a0) # clear hi(mantissa)
6045 clr.l FTEMP_LO(%a0) # clear lo(mantissa)
6046 mov.l &0x20000000, %d0 # set sticky bit
6047 rts
6048
6049#
6050# case (d1 == 64)
6051#
6052# ---------------------------------------------------------
6053# | FTEMP_HI | FTEMP_LO |grs000.........000|
6054# ---------------------------------------------------------
6055# <-------(32)------>
6056# \ \
6057# \ \
6058# \ \
6059# \ ------------------------------
6060# ------------------------------- \
6061# \ \
6062# \ \
6063# \ \
6064# <-------(32)------>
6065# ---------------------------------------------------------
6066# |0...............0|0................0|grs |
6067# ---------------------------------------------------------
6068#
6069case3_64:
6070 mov.l FTEMP_HI(%a0), %d0 # fetch hi(mantissa)
6071 mov.l %d0, %d1 # make a copy
6072 and.l &0xc0000000, %d0 # extract G,R
6073 and.l &0x3fffffff, %d1 # extract other bits
6074
6075 bra.b case3_complete
6076
6077#
6078# case (d1 == 65)
6079#
6080# ---------------------------------------------------------
6081# | FTEMP_HI | FTEMP_LO |grs000.........000|
6082# ---------------------------------------------------------
6083# <-------(32)------>
6084# \ \
6085# \ \
6086# \ \
6087# \ ------------------------------
6088# -------------------------------- \
6089# \ \
6090# \ \
6091# \ \
6092# <-------(31)----->
6093# ---------------------------------------------------------
6094# |0...............0|0................0|0rs |
6095# ---------------------------------------------------------
6096#
6097case3_65:
6098 mov.l FTEMP_HI(%a0), %d0 # fetch hi(mantissa)
6099 and.l &0x80000000, %d0 # extract R bit
6100 lsr.l &0x1, %d0 # shift high bit into R bit
6101 and.l &0x7fffffff, %d1 # extract other bits
6102
6103case3_complete:
6104# last operation done was an "and" of the bits shifted off so the condition
6105# codes are already set so branch accordingly.
6106 bne.b case3_set_sticky # yes; go set new sticky
6107 tst.l FTEMP_LO(%a0) # were any bits shifted off?
6108 bne.b case3_set_sticky # yes; go set new sticky
6109 tst.b GRS(%a6) # were any bits shifted off?
6110 bne.b case3_set_sticky # yes; go set new sticky
6111
6112#
6113# no bits were shifted off so don't set the sticky bit.
6114# the guard and
6115# the entire mantissa is zero.
6116#
6117 clr.l FTEMP_HI(%a0) # clear hi(mantissa)
6118 clr.l FTEMP_LO(%a0) # clear lo(mantissa)
6119 rts
6120
6121#
6122# some bits were shifted off so set the sticky bit.
6123# the entire mantissa is zero.
6124#
6125case3_set_sticky:
6126 bset &rnd_stky_bit,%d0 # set new sticky bit
6127 clr.l FTEMP_HI(%a0) # clear hi(mantissa)
6128 clr.l FTEMP_LO(%a0) # clear lo(mantissa)
6129 rts
6130
6131#########################################################################
6132# XDEF **************************************************************** #
6133# _round(): round result according to precision/mode #
6134# #
6135# XREF **************************************************************** #
6136# None #
6137# #
6138# INPUT *************************************************************** #
6139# a0 = ptr to input operand in internal extended format #
6140# d1(hi) = contains rounding precision: #
6141# ext = $0000xxxx #
6142# sgl = $0004xxxx #
6143# dbl = $0008xxxx #
6144# d1(lo) = contains rounding mode: #
6145# RN = $xxxx0000 #
6146# RZ = $xxxx0001 #
6147# RM = $xxxx0002 #
6148# RP = $xxxx0003 #
6149# d0{31:29} = contains the g,r,s bits (extended) #
6150# #
6151# OUTPUT ************************************************************** #
6152# a0 = pointer to rounded result #
6153# #
6154# ALGORITHM *********************************************************** #
6155# On return the value pointed to by a0 is correctly rounded, #
6156# a0 is preserved and the g-r-s bits in d0 are cleared. #
6157# The result is not typed - the tag field is invalid. The #
6158# result is still in the internal extended format. #
6159# #
6160# The INEX bit of USER_FPSR will be set if the rounded result was #
6161# inexact (i.e. if any of the g-r-s bits were set). #
6162# #
6163#########################################################################
6164
6165 global _round
6166_round:
6167#
6168# ext_grs() looks at the rounding precision and sets the appropriate
6169# G,R,S bits.
6170# If (G,R,S == 0) then result is exact and round is done, else set
6171# the inex flag in status reg and continue.
6172#
6173 bsr.l ext_grs # extract G,R,S
6174
6175 tst.l %d0 # are G,R,S zero?
6176 beq.w truncate # yes; round is complete
6177
6178 or.w &inx2a_mask, 2+USER_FPSR(%a6) # set inex2/ainex
6179
6180#
6181# Use rounding mode as an index into a jump table for these modes.
6182# All of the following assumes grs != 0.
6183#
6184 mov.w (tbl_mode.b,%pc,%d1.w*2), %a1 # load jump offset
6185 jmp (tbl_mode.b,%pc,%a1) # jmp to rnd mode handler
6186
6187tbl_mode:
6188 short rnd_near - tbl_mode
6189 short truncate - tbl_mode # RZ always truncates
6190 short rnd_mnus - tbl_mode
6191 short rnd_plus - tbl_mode
6192
6193#################################################################
6194# ROUND PLUS INFINITY #
6195# #
6196# If sign of fp number = 0 (positive), then add 1 to l. #
6197#################################################################
6198rnd_plus:
6199 tst.b FTEMP_SGN(%a0) # check for sign
6200 bmi.w truncate # if positive then truncate
6201
6202 mov.l &0xffffffff, %d0 # force g,r,s to be all f's
6203 swap %d1 # set up d1 for round prec.
6204
6205 cmpi.b %d1, &s_mode # is prec = sgl?
6206 beq.w add_sgl # yes
6207 bgt.w add_dbl # no; it's dbl
6208 bra.w add_ext # no; it's ext
6209
6210#################################################################
6211# ROUND MINUS INFINITY #
6212# #
6213# If sign of fp number = 1 (negative), then add 1 to l. #
6214#################################################################
6215rnd_mnus:
6216 tst.b FTEMP_SGN(%a0) # check for sign
6217 bpl.w truncate # if negative then truncate
6218
6219 mov.l &0xffffffff, %d0 # force g,r,s to be all f's
6220 swap %d1 # set up d1 for round prec.
6221
6222 cmpi.b %d1, &s_mode # is prec = sgl?
6223 beq.w add_sgl # yes
6224 bgt.w add_dbl # no; it's dbl
6225 bra.w add_ext # no; it's ext
6226
6227#################################################################
6228# ROUND NEAREST #
6229# #
6230# If (g=1), then add 1 to l and if (r=s=0), then clear l #
6231# Note that this will round to even in case of a tie. #
6232#################################################################
6233rnd_near:
6234 asl.l &0x1, %d0 # shift g-bit to c-bit
6235 bcc.w truncate # if (g=1) then
6236
6237 swap %d1 # set up d1 for round prec.
6238
6239 cmpi.b %d1, &s_mode # is prec = sgl?
6240 beq.w add_sgl # yes
6241 bgt.w add_dbl # no; it's dbl
6242 bra.w add_ext # no; it's ext
6243
6244# *** LOCAL EQUATES ***
6245set ad_1_sgl, 0x00000100 # constant to add 1 to l-bit in sgl prec
6246set ad_1_dbl, 0x00000800 # constant to add 1 to l-bit in dbl prec
6247
6248#########################
6249# ADD SINGLE #
6250#########################
6251add_sgl:
6252 add.l &ad_1_sgl, FTEMP_HI(%a0)
6253 bcc.b scc_clr # no mantissa overflow
6254 roxr.w FTEMP_HI(%a0) # shift v-bit back in
6255 roxr.w FTEMP_HI+2(%a0) # shift v-bit back in
6256 add.w &0x1, FTEMP_EX(%a0) # and incr exponent
6257scc_clr:
6258 tst.l %d0 # test for rs = 0
6259 bne.b sgl_done
6260 and.w &0xfe00, FTEMP_HI+2(%a0) # clear the l-bit
6261sgl_done:
6262 and.l &0xffffff00, FTEMP_HI(%a0) # truncate bits beyond sgl limit
6263 clr.l FTEMP_LO(%a0) # clear d2
6264 rts
6265
6266#########################
6267# ADD EXTENDED #
6268#########################
6269add_ext:
6270 addq.l &1,FTEMP_LO(%a0) # add 1 to l-bit
6271 bcc.b xcc_clr # test for carry out
6272 addq.l &1,FTEMP_HI(%a0) # propagate carry
6273 bcc.b xcc_clr
6274 roxr.w FTEMP_HI(%a0) # mant is 0 so restore v-bit
6275 roxr.w FTEMP_HI+2(%a0) # mant is 0 so restore v-bit
6276 roxr.w FTEMP_LO(%a0)
6277 roxr.w FTEMP_LO+2(%a0)
6278 add.w &0x1,FTEMP_EX(%a0) # and inc exp
6279xcc_clr:
6280 tst.l %d0 # test rs = 0
6281 bne.b add_ext_done
6282 and.b &0xfe,FTEMP_LO+3(%a0) # clear the l bit
6283add_ext_done:
6284 rts
6285
6286#########################
6287# ADD DOUBLE #
6288#########################
6289add_dbl:
6290 add.l &ad_1_dbl, FTEMP_LO(%a0) # add 1 to lsb
6291 bcc.b dcc_clr # no carry
6292 addq.l &0x1, FTEMP_HI(%a0) # propagate carry
6293 bcc.b dcc_clr # no carry
6294
6295 roxr.w FTEMP_HI(%a0) # mant is 0 so restore v-bit
6296 roxr.w FTEMP_HI+2(%a0) # mant is 0 so restore v-bit
6297 roxr.w FTEMP_LO(%a0)
6298 roxr.w FTEMP_LO+2(%a0)
6299 addq.w &0x1, FTEMP_EX(%a0) # incr exponent
6300dcc_clr:
6301 tst.l %d0 # test for rs = 0
6302 bne.b dbl_done
6303 and.w &0xf000, FTEMP_LO+2(%a0) # clear the l-bit
6304
6305dbl_done:
6306 and.l &0xfffff800,FTEMP_LO(%a0) # truncate bits beyond dbl limit
6307 rts
6308
6309###########################
6310# Truncate all other bits #
6311###########################
6312truncate:
6313 swap %d1 # select rnd prec
6314
6315 cmpi.b %d1, &s_mode # is prec sgl?
6316 beq.w sgl_done # yes
6317 bgt.b dbl_done # no; it's dbl
6318 rts # no; it's ext
6319
6320
6321#
6322# ext_grs(): extract guard, round and sticky bits according to
6323# rounding precision.
6324#
6325# INPUT
6326# d0 = extended precision g,r,s (in d0{31:29})
6327# d1 = {PREC,ROUND}
6328# OUTPUT
6329# d0{31:29} = guard, round, sticky
6330#
6331# The ext_grs extract the guard/round/sticky bits according to the
6332# selected rounding precision. It is called by the round subroutine
6333# only. All registers except d0 are kept intact. d0 becomes an
6334# updated guard,round,sticky in d0{31:29}
6335#
6336# Notes: the ext_grs uses the round PREC, and therefore has to swap d1
6337# prior to usage, and needs to restore d1 to original. this
6338# routine is tightly tied to the round routine and not meant to
6339# uphold standard subroutine calling practices.
6340#
6341
6342ext_grs:
6343 swap %d1 # have d1.w point to round precision
6344 tst.b %d1 # is rnd prec = extended?
6345 bne.b ext_grs_not_ext # no; go handle sgl or dbl
6346
6347#
6348# %d0 actually already hold g,r,s since _round() had it before calling
6349# this function. so, as long as we don't disturb it, we are "returning" it.
6350#
6351ext_grs_ext:
6352 swap %d1 # yes; return to correct positions
6353 rts
6354
6355ext_grs_not_ext:
6356 movm.l &0x3000, -(%sp) # make some temp registers {d2/d3}
6357
6358 cmpi.b %d1, &s_mode # is rnd prec = sgl?
6359 bne.b ext_grs_dbl # no; go handle dbl
6360
6361#
6362# sgl:
6363# 96 64 40 32 0
6364# -----------------------------------------------------
6365# | EXP |XXXXXXX| |xx | |grs|
6366# -----------------------------------------------------
6367# <--(24)--->nn\ /
6368# ee ---------------------
6369# ww |
6370# v
6371# gr new sticky
6372#
6373ext_grs_sgl:
6374 bfextu FTEMP_HI(%a0){&24:&2}, %d3 # sgl prec. g-r are 2 bits right
6375 mov.l &30, %d2 # of the sgl prec. limits
6376 lsl.l %d2, %d3 # shift g-r bits to MSB of d3
6377 mov.l FTEMP_HI(%a0), %d2 # get word 2 for s-bit test
6378 and.l &0x0000003f, %d2 # s bit is the or of all other
6379 bne.b ext_grs_st_stky # bits to the right of g-r
6380 tst.l FTEMP_LO(%a0) # test lower mantissa
6381 bne.b ext_grs_st_stky # if any are set, set sticky
6382 tst.l %d0 # test original g,r,s
6383 bne.b ext_grs_st_stky # if any are set, set sticky
6384 bra.b ext_grs_end_sd # if words 3 and 4 are clr, exit
6385
6386#
6387# dbl:
6388# 96 64 32 11 0
6389# -----------------------------------------------------
6390# | EXP |XXXXXXX| | |xx |grs|
6391# -----------------------------------------------------
6392# nn\ /
6393# ee -------
6394# ww |
6395# v
6396# gr new sticky
6397#
6398ext_grs_dbl:
6399 bfextu FTEMP_LO(%a0){&21:&2}, %d3 # dbl-prec. g-r are 2 bits right
6400 mov.l &30, %d2 # of the dbl prec. limits
6401 lsl.l %d2, %d3 # shift g-r bits to the MSB of d3
6402 mov.l FTEMP_LO(%a0), %d2 # get lower mantissa for s-bit test
6403 and.l &0x000001ff, %d2 # s bit is the or-ing of all
6404 bne.b ext_grs_st_stky # other bits to the right of g-r
6405 tst.l %d0 # test word original g,r,s
6406 bne.b ext_grs_st_stky # if any are set, set sticky
6407 bra.b ext_grs_end_sd # if clear, exit
6408
6409ext_grs_st_stky:
6410 bset &rnd_stky_bit, %d3 # set sticky bit
6411ext_grs_end_sd:
6412 mov.l %d3, %d0 # return grs to d0
6413
6414 movm.l (%sp)+, &0xc # restore scratch registers {d2/d3}
6415
6416 swap %d1 # restore d1 to original
6417 rts
6418
6419#########################################################################
6420# norm(): normalize the mantissa of an extended precision input. the #
6421# input operand should not be normalized already. #
6422# #
6423# XDEF **************************************************************** #
6424# norm() #
6425# #
6426# XREF **************************************************************** #
6427# none #
6428# #
6429# INPUT *************************************************************** #
6430# a0 = pointer fp extended precision operand to normalize #
6431# #
6432# OUTPUT ************************************************************** #
6433# d0 = number of bit positions the mantissa was shifted #
6434# a0 = the input operand's mantissa is normalized; the exponent #
6435# is unchanged. #
6436# #
6437#########################################################################
6438 global norm
6439norm:
6440 mov.l %d2, -(%sp) # create some temp regs
6441 mov.l %d3, -(%sp)
6442
6443 mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)
6444 mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)
6445
6446 bfffo %d0{&0:&32}, %d2 # how many places to shift?
6447 beq.b norm_lo # hi(man) is all zeroes!
6448
6449norm_hi:
6450 lsl.l %d2, %d0 # left shift hi(man)
6451 bfextu %d1{&0:%d2}, %d3 # extract lo bits
6452
6453 or.l %d3, %d0 # create hi(man)
6454 lsl.l %d2, %d1 # create lo(man)
6455
6456 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
6457 mov.l %d1, FTEMP_LO(%a0) # store new lo(man)
6458
6459 mov.l %d2, %d0 # return shift amount
6460
6461 mov.l (%sp)+, %d3 # restore temp regs
6462 mov.l (%sp)+, %d2
6463
6464 rts
6465
6466norm_lo:
6467 bfffo %d1{&0:&32}, %d2 # how many places to shift?
6468 lsl.l %d2, %d1 # shift lo(man)
6469 add.l &32, %d2 # add 32 to shft amount
6470
6471 mov.l %d1, FTEMP_HI(%a0) # store hi(man)
6472 clr.l FTEMP_LO(%a0) # lo(man) is now zero
6473
6474 mov.l %d2, %d0 # return shift amount
6475
6476 mov.l (%sp)+, %d3 # restore temp regs
6477 mov.l (%sp)+, %d2
6478
6479 rts
6480
6481#########################################################################
6482# unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #
6483# - returns corresponding optype tag #
6484# #
6485# XDEF **************************************************************** #
6486# unnorm_fix() #
6487# #
6488# XREF **************************************************************** #
6489# norm() - normalize the mantissa #
6490# #
6491# INPUT *************************************************************** #
6492# a0 = pointer to unnormalized extended precision number #
6493# #
6494# OUTPUT ************************************************************** #
6495# d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #
6496# a0 = input operand has been converted to a norm, denorm, or #
6497# zero; both the exponent and mantissa are changed. #
6498# #
6499#########################################################################
6500
6501 global unnorm_fix
6502unnorm_fix:
6503 bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
6504 bne.b unnorm_shift # hi(man) is not all zeroes
6505
6506#
6507# hi(man) is all zeroes so see if any bits in lo(man) are set
6508#
6509unnorm_chk_lo:
6510 bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
6511 beq.w unnorm_zero # yes
6512
6513 add.w &32, %d0 # no; fix shift distance
6514
6515#
6516# d0 = # shifts needed for complete normalization
6517#
6518unnorm_shift:
6519 clr.l %d1 # clear top word
6520 mov.w FTEMP_EX(%a0), %d1 # extract exponent
6521 and.w &0x7fff, %d1 # strip off sgn
6522
6523 cmp.w %d0, %d1 # will denorm push exp < 0?
6524 bgt.b unnorm_nrm_zero # yes; denorm only until exp = 0
6525
6526#
6527# exponent would not go < 0. therefore, number stays normalized
6528#
6529 sub.w %d0, %d1 # shift exponent value
6530 mov.w FTEMP_EX(%a0), %d0 # load old exponent
6531 and.w &0x8000, %d0 # save old sign
6532 or.w %d0, %d1 # {sgn,new exp}
6533 mov.w %d1, FTEMP_EX(%a0) # insert new exponent
6534
6535 bsr.l norm # normalize UNNORM
6536
6537 mov.b &NORM, %d0 # return new optype tag
6538 rts
6539
6540#
6541# exponent would go < 0, so only denormalize until exp = 0
6542#
6543unnorm_nrm_zero:
6544 cmp.b %d1, &32 # is exp <= 32?
6545 bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent
6546
6547 bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
6548 mov.l %d0, FTEMP_HI(%a0) # save new hi(man)
6549
6550 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
6551 lsl.l %d1, %d0 # extract new lo(man)
6552 mov.l %d0, FTEMP_LO(%a0) # save new lo(man)
6553
6554 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
6555
6556 mov.b &DENORM, %d0 # return new optype tag
6557 rts
6558
6559#
6560# only mantissa bits set are in lo(man)
6561#
6562unnorm_nrm_zero_lrg:
6563 sub.w &32, %d1 # adjust shft amt by 32
6564
6565 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
6566 lsl.l %d1, %d0 # left shift lo(man)
6567
6568 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
6569 clr.l FTEMP_LO(%a0) # lo(man) = 0
6570
6571 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
6572
6573 mov.b &DENORM, %d0 # return new optype tag
6574 rts
6575
6576#
6577# whole mantissa is zero so this UNNORM is actually a zero
6578#
6579unnorm_zero:
6580 and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero
6581
6582 mov.b &ZERO, %d0 # fix optype tag
6583 rts
6584
6585#########################################################################
6586# XDEF **************************************************************** #
6587# set_tag_x(): return the optype of the input ext fp number #
6588# #
6589# XREF **************************************************************** #
6590# None #
6591# #
6592# INPUT *************************************************************** #
6593# a0 = pointer to extended precision operand #
6594# #
6595# OUTPUT ************************************************************** #
6596# d0 = value of type tag #
6597# one of: NORM, INF, QNAN, SNAN, DENORM, UNNORM, ZERO #
6598# #
6599# ALGORITHM *********************************************************** #
6600# Simply test the exponent, j-bit, and mantissa values to #
6601# determine the type of operand. #
6602# If it's an unnormalized zero, alter the operand and force it #
6603# to be a normal zero. #
6604# #
6605#########################################################################
6606
6607 global set_tag_x
6608set_tag_x:
6609 mov.w FTEMP_EX(%a0), %d0 # extract exponent
6610 andi.w &0x7fff, %d0 # strip off sign
6611 cmpi.w %d0, &0x7fff # is (EXP == MAX)?
6612 beq.b inf_or_nan_x
6613not_inf_or_nan_x:
6614 btst &0x7,FTEMP_HI(%a0)
6615 beq.b not_norm_x
6616is_norm_x:
6617 mov.b &NORM, %d0
6618 rts
6619not_norm_x:
6620 tst.w %d0 # is exponent = 0?
6621 bne.b is_unnorm_x
6622not_unnorm_x:
6623 tst.l FTEMP_HI(%a0)
6624 bne.b is_denorm_x
6625 tst.l FTEMP_LO(%a0)
6626 bne.b is_denorm_x
6627is_zero_x:
6628 mov.b &ZERO, %d0
6629 rts
6630is_denorm_x:
6631 mov.b &DENORM, %d0
6632 rts
6633# must distinguish now "Unnormalized zeroes" which we
6634# must convert to zero.
6635is_unnorm_x:
6636 tst.l FTEMP_HI(%a0)
6637 bne.b is_unnorm_reg_x
6638 tst.l FTEMP_LO(%a0)
6639 bne.b is_unnorm_reg_x
6640# it's an "unnormalized zero". let's convert it to an actual zero...
6641 andi.w &0x8000,FTEMP_EX(%a0) # clear exponent
6642 mov.b &ZERO, %d0
6643 rts
6644is_unnorm_reg_x:
6645 mov.b &UNNORM, %d0
6646 rts
6647inf_or_nan_x:
6648 tst.l FTEMP_LO(%a0)
6649 bne.b is_nan_x
6650 mov.l FTEMP_HI(%a0), %d0
6651 and.l &0x7fffffff, %d0 # msb is a don't care!
6652 bne.b is_nan_x
6653is_inf_x:
6654 mov.b &INF, %d0
6655 rts
6656is_nan_x:
6657 btst &0x6, FTEMP_HI(%a0)
6658 beq.b is_snan_x
6659 mov.b &QNAN, %d0
6660 rts
6661is_snan_x:
6662 mov.b &SNAN, %d0
6663 rts
6664
6665#########################################################################
6666# XDEF **************************************************************** #
6667# set_tag_d(): return the optype of the input dbl fp number #
6668# #
6669# XREF **************************************************************** #
6670# None #
6671# #
6672# INPUT *************************************************************** #
6673# a0 = points to double precision operand #
6674# #
6675# OUTPUT ************************************************************** #
6676# d0 = value of type tag #
6677# one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
6678# #
6679# ALGORITHM *********************************************************** #
6680# Simply test the exponent, j-bit, and mantissa values to #
6681# determine the type of operand. #
6682# #
6683#########################################################################
6684
6685 global set_tag_d
6686set_tag_d:
6687 mov.l FTEMP(%a0), %d0
6688 mov.l %d0, %d1
6689
6690 andi.l &0x7ff00000, %d0
6691 beq.b zero_or_denorm_d
6692
6693 cmpi.l %d0, &0x7ff00000
6694 beq.b inf_or_nan_d
6695
6696is_norm_d:
6697 mov.b &NORM, %d0
6698 rts
6699zero_or_denorm_d:
6700 and.l &0x000fffff, %d1
6701 bne is_denorm_d
6702 tst.l 4+FTEMP(%a0)
6703 bne is_denorm_d
6704is_zero_d:
6705 mov.b &ZERO, %d0
6706 rts
6707is_denorm_d:
6708 mov.b &DENORM, %d0
6709 rts
6710inf_or_nan_d:
6711 and.l &0x000fffff, %d1
6712 bne is_nan_d
6713 tst.l 4+FTEMP(%a0)
6714 bne is_nan_d
6715is_inf_d:
6716 mov.b &INF, %d0
6717 rts
6718is_nan_d:
6719 btst &19, %d1
6720 bne is_qnan_d
6721is_snan_d:
6722 mov.b &SNAN, %d0
6723 rts
6724is_qnan_d:
6725 mov.b &QNAN, %d0
6726 rts
6727
6728#########################################################################
6729# XDEF **************************************************************** #
6730# set_tag_s(): return the optype of the input sgl fp number #
6731# #
6732# XREF **************************************************************** #
6733# None #
6734# #
6735# INPUT *************************************************************** #
6736# a0 = pointer to single precision operand #
6737# #
6738# OUTPUT ************************************************************** #
6739# d0 = value of type tag #
6740# one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
6741# #
6742# ALGORITHM *********************************************************** #
6743# Simply test the exponent, j-bit, and mantissa values to #
6744# determine the type of operand. #
6745# #
6746#########################################################################
6747
6748 global set_tag_s
6749set_tag_s:
6750 mov.l FTEMP(%a0), %d0
6751 mov.l %d0, %d1
6752
6753 andi.l &0x7f800000, %d0
6754 beq.b zero_or_denorm_s
6755
6756 cmpi.l %d0, &0x7f800000
6757 beq.b inf_or_nan_s
6758
6759is_norm_s:
6760 mov.b &NORM, %d0
6761 rts
6762zero_or_denorm_s:
6763 and.l &0x007fffff, %d1
6764 bne is_denorm_s
6765is_zero_s:
6766 mov.b &ZERO, %d0
6767 rts
6768is_denorm_s:
6769 mov.b &DENORM, %d0
6770 rts
6771inf_or_nan_s:
6772 and.l &0x007fffff, %d1
6773 bne is_nan_s
6774is_inf_s:
6775 mov.b &INF, %d0
6776 rts
6777is_nan_s:
6778 btst &22, %d1
6779 bne is_qnan_s
6780is_snan_s:
6781 mov.b &SNAN, %d0
6782 rts
6783is_qnan_s:
6784 mov.b &QNAN, %d0
6785 rts
6786
6787#########################################################################
6788# XDEF **************************************************************** #
6789# unf_res(): routine to produce default underflow result of a #
6790# scaled extended precision number; this is used by #
6791# fadd/fdiv/fmul/etc. emulation routines. #
6792# unf_res4(): same as above but for fsglmul/fsgldiv which use #
6793# single round prec and extended prec mode. #
6794# #
6795# XREF **************************************************************** #
6796# _denorm() - denormalize according to scale factor #
6797# _round() - round denormalized number according to rnd prec #
6798# #
6799# INPUT *************************************************************** #
6800# a0 = pointer to extended precison operand #
6801# d0 = scale factor #
6802# d1 = rounding precision/mode #
6803# #
6804# OUTPUT ************************************************************** #
6805# a0 = pointer to default underflow result in extended precision #
6806# d0.b = result FPSR_cc which caller may or may not want to save #
6807# #
6808# ALGORITHM *********************************************************** #
6809# Convert the input operand to "internal format" which means the #
6810# exponent is extended to 16 bits and the sign is stored in the unused #
6811# portion of the extended precison operand. Denormalize the number #
6812# according to the scale factor passed in d0. Then, round the #
6813# denormalized result. #
6814# Set the FPSR_exc bits as appropriate but return the cc bits in #
6815# d0 in case the caller doesn't want to save them (as is the case for #
6816# fmove out). #
6817# unf_res4() for fsglmul/fsgldiv forces the denorm to extended #
6818# precision and the rounding mode to single. #
6819# #
6820#########################################################################
6821 global unf_res
6822unf_res:
6823 mov.l %d1, -(%sp) # save rnd prec,mode on stack
6824
6825 btst &0x7, FTEMP_EX(%a0) # make "internal" format
6826 sne FTEMP_SGN(%a0)
6827
6828 mov.w FTEMP_EX(%a0), %d1 # extract exponent
6829 and.w &0x7fff, %d1
6830 sub.w %d0, %d1
6831 mov.w %d1, FTEMP_EX(%a0) # insert 16 bit exponent
6832
6833 mov.l %a0, -(%sp) # save operand ptr during calls
6834
6835 mov.l 0x4(%sp),%d0 # pass rnd prec.
6836 andi.w &0x00c0,%d0
6837 lsr.w &0x4,%d0
6838 bsr.l _denorm # denorm result
6839
6840 mov.l (%sp),%a0
6841 mov.w 0x6(%sp),%d1 # load prec:mode into %d1
6842 andi.w &0xc0,%d1 # extract rnd prec
6843 lsr.w &0x4,%d1
6844 swap %d1
6845 mov.w 0x6(%sp),%d1
6846 andi.w &0x30,%d1
6847 lsr.w &0x4,%d1
6848 bsr.l _round # round the denorm
6849
6850 mov.l (%sp)+, %a0
6851
6852# result is now rounded properly. convert back to normal format
6853 bclr &0x7, FTEMP_EX(%a0) # clear sgn first; may have residue
6854 tst.b FTEMP_SGN(%a0) # is "internal result" sign set?
6855 beq.b unf_res_chkifzero # no; result is positive
6856 bset &0x7, FTEMP_EX(%a0) # set result sgn
6857 clr.b FTEMP_SGN(%a0) # clear temp sign
6858
6859# the number may have become zero after rounding. set ccodes accordingly.
6860unf_res_chkifzero:
6861 clr.l %d0
6862 tst.l FTEMP_HI(%a0) # is value now a zero?
6863 bne.b unf_res_cont # no
6864 tst.l FTEMP_LO(%a0)
6865 bne.b unf_res_cont # no
6866# bset &z_bit, FPSR_CC(%a6) # yes; set zero ccode bit
6867 bset &z_bit, %d0 # yes; set zero ccode bit
6868
6869unf_res_cont:
6870
6871#
6872# can inex1 also be set along with unfl and inex2???
6873#
6874# we know that underflow has occurred. aunfl should be set if INEX2 is also set.
6875#
6876 btst &inex2_bit, FPSR_EXCEPT(%a6) # is INEX2 set?
6877 beq.b unf_res_end # no
6878 bset &aunfl_bit, FPSR_AEXCEPT(%a6) # yes; set aunfl
6879
6880unf_res_end:
6881 add.l &0x4, %sp # clear stack
6882 rts
6883
6884# unf_res() for fsglmul() and fsgldiv().
6885 global unf_res4
6886unf_res4:
6887 mov.l %d1,-(%sp) # save rnd prec,mode on stack
6888
6889 btst &0x7,FTEMP_EX(%a0) # make "internal" format
6890 sne FTEMP_SGN(%a0)
6891
6892 mov.w FTEMP_EX(%a0),%d1 # extract exponent
6893 and.w &0x7fff,%d1
6894 sub.w %d0,%d1
6895 mov.w %d1,FTEMP_EX(%a0) # insert 16 bit exponent
6896
6897 mov.l %a0,-(%sp) # save operand ptr during calls
6898
6899 clr.l %d0 # force rnd prec = ext
6900 bsr.l _denorm # denorm result
6901
6902 mov.l (%sp),%a0
6903 mov.w &s_mode,%d1 # force rnd prec = sgl
6904 swap %d1
6905 mov.w 0x6(%sp),%d1 # load rnd mode
6906 andi.w &0x30,%d1 # extract rnd prec
6907 lsr.w &0x4,%d1
6908 bsr.l _round # round the denorm
6909
6910 mov.l (%sp)+,%a0
6911
6912# result is now rounded properly. convert back to normal format
6913 bclr &0x7,FTEMP_EX(%a0) # clear sgn first; may have residue
6914 tst.b FTEMP_SGN(%a0) # is "internal result" sign set?
6915 beq.b unf_res4_chkifzero # no; result is positive
6916 bset &0x7,FTEMP_EX(%a0) # set result sgn
6917 clr.b FTEMP_SGN(%a0) # clear temp sign
6918
6919# the number may have become zero after rounding. set ccodes accordingly.
6920unf_res4_chkifzero:
6921 clr.l %d0
6922 tst.l FTEMP_HI(%a0) # is value now a zero?
6923 bne.b unf_res4_cont # no
6924 tst.l FTEMP_LO(%a0)
6925 bne.b unf_res4_cont # no
6926# bset &z_bit,FPSR_CC(%a6) # yes; set zero ccode bit
6927 bset &z_bit,%d0 # yes; set zero ccode bit
6928
6929unf_res4_cont:
6930
6931#
6932# can inex1 also be set along with unfl and inex2???
6933#
6934# we know that underflow has occurred. aunfl should be set if INEX2 is also set.
6935#
6936 btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
6937 beq.b unf_res4_end # no
6938 bset &aunfl_bit,FPSR_AEXCEPT(%a6) # yes; set aunfl
6939
6940unf_res4_end:
6941 add.l &0x4,%sp # clear stack
6942 rts
6943
6944#########################################################################
6945# XDEF **************************************************************** #
6946# ovf_res(): routine to produce the default overflow result of #
6947# an overflowing number. #
6948# ovf_res2(): same as above but the rnd mode/prec are passed #
6949# differently. #
6950# #
6951# XREF **************************************************************** #
6952# none #
6953# #
6954# INPUT *************************************************************** #
6955# d1.b = '-1' => (-); '0' => (+) #
6956# ovf_res(): #
6957# d0 = rnd mode/prec #
6958# ovf_res2(): #
6959# hi(d0) = rnd prec #
6960# lo(d0) = rnd mode #
6961# #
6962# OUTPUT ************************************************************** #
6963# a0 = points to extended precision result #
6964# d0.b = condition code bits #
6965# #
6966# ALGORITHM *********************************************************** #
6967# The default overflow result can be determined by the sign of #
6968# the result and the rounding mode/prec in effect. These bits are #
6969# concatenated together to create an index into the default result #
6970# table. A pointer to the correct result is returned in a0. The #
6971# resulting condition codes are returned in d0 in case the caller #
6972# doesn't want FPSR_cc altered (as is the case for fmove out). #
6973# #
6974#########################################################################
6975
6976 global ovf_res
6977ovf_res:
6978 andi.w &0x10,%d1 # keep result sign
6979 lsr.b &0x4,%d0 # shift prec/mode
6980 or.b %d0,%d1 # concat the two
6981 mov.w %d1,%d0 # make a copy
6982 lsl.b &0x1,%d1 # multiply d1 by 2
6983 bra.b ovf_res_load
6984
6985 global ovf_res2
6986ovf_res2:
6987 and.w &0x10, %d1 # keep result sign
6988 or.b %d0, %d1 # insert rnd mode
6989 swap %d0
6990 or.b %d0, %d1 # insert rnd prec
6991 mov.w %d1, %d0 # make a copy
6992 lsl.b &0x1, %d1 # shift left by 1
6993
6994#
6995# use the rounding mode, precision, and result sign as in index into the
6996# two tables below to fetch the default result and the result ccodes.
6997#
6998ovf_res_load:
6999 mov.b (tbl_ovfl_cc.b,%pc,%d0.w*1), %d0 # fetch result ccodes
7000 lea (tbl_ovfl_result.b,%pc,%d1.w*8), %a0 # return result ptr
7001
7002 rts
7003
7004tbl_ovfl_cc:
7005 byte 0x2, 0x0, 0x0, 0x2
7006 byte 0x2, 0x0, 0x0, 0x2
7007 byte 0x2, 0x0, 0x0, 0x2
7008 byte 0x0, 0x0, 0x0, 0x0
7009 byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
7010 byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
7011 byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
7012
7013tbl_ovfl_result:
7014 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
7015 long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RZ
7016 long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RM
7017 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
7018
7019 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
7020 long 0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RZ
7021 long 0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RM
7022 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
7023
7024 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
7025 long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RZ
7026 long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RM
7027 long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
7028
7029 long 0x00000000,0x00000000,0x00000000,0x00000000
7030 long 0x00000000,0x00000000,0x00000000,0x00000000
7031 long 0x00000000,0x00000000,0x00000000,0x00000000
7032 long 0x00000000,0x00000000,0x00000000,0x00000000
7033
7034 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
7035 long 0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RZ
7036 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
7037 long 0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RP
7038
7039 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
7040 long 0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RZ
7041 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
7042 long 0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RP
7043
7044 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
7045 long 0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RZ
7046 long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
7047 long 0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RP
7048
7049#########################################################################
7050# XDEF **************************************************************** #
7051# fout(): move from fp register to memory or data register #
7052# #
7053# XREF **************************************************************** #
7054# _round() - needed to create EXOP for sgl/dbl precision #
7055# norm() - needed to create EXOP for extended precision #
7056# ovf_res() - create default overflow result for sgl/dbl precision#
7057# unf_res() - create default underflow result for sgl/dbl prec. #
7058# dst_dbl() - create rounded dbl precision result. #
7059# dst_sgl() - create rounded sgl precision result. #
7060# fetch_dreg() - fetch dynamic k-factor reg for packed. #
7061# bindec() - convert FP binary number to packed number. #
7062# _mem_write() - write data to memory. #
7063# _mem_write2() - write data to memory unless supv mode -(a7) exc.#
7064# _dmem_write_{byte,word,long}() - write data to memory. #
7065# store_dreg_{b,w,l}() - store data to data register file. #
7066# facc_out_{b,w,l,d,x}() - data access error occurred. #
7067# #
7068# INPUT *************************************************************** #
7069# a0 = pointer to extended precision source operand #
7070# d0 = round prec,mode #
7071# #
7072# OUTPUT ************************************************************** #
7073# fp0 : intermediate underflow or overflow result if #
7074# OVFL/UNFL occurred for a sgl or dbl operand #
7075# #
7076# ALGORITHM *********************************************************** #
7077# This routine is accessed by many handlers that need to do an #
7078# opclass three move of an operand out to memory. #
7079# Decode an fmove out (opclass 3) instruction to determine if #
7080# it's b,w,l,s,d,x, or p in size. b,w,l can be stored to either a data #
7081# register or memory. The algorithm uses a standard "fmove" to create #
7082# the rounded result. Also, since exceptions are disabled, this also #
7083# create the correct OPERR default result if appropriate. #
7084# For sgl or dbl precision, overflow or underflow can occur. If #
7085# either occurs and is enabled, the EXOP. #
7086# For extended precision, the stacked <ea> must be fixed along #
7087# w/ the address index register as appropriate w/ _calc_ea_fout(). If #
7088# the source is a denorm and if underflow is enabled, an EXOP must be #
7089# created. #
7090# For packed, the k-factor must be fetched from the instruction #
7091# word or a data register. The <ea> must be fixed as w/ extended #
7092# precision. Then, bindec() is called to create the appropriate #
7093# packed result. #
7094# If at any time an access error is flagged by one of the move- #
7095# to-memory routines, then a special exit must be made so that the #
7096# access error can be handled properly. #
7097# #
7098#########################################################################
7099
7100 global fout
7101fout:
7102 bfextu EXC_CMDREG(%a6){&3:&3},%d1 # extract dst fmt
7103 mov.w (tbl_fout.b,%pc,%d1.w*2),%a1 # use as index
7104 jmp (tbl_fout.b,%pc,%a1) # jump to routine
7105
7106 swbeg &0x8
7107tbl_fout:
7108 short fout_long - tbl_fout
7109 short fout_sgl - tbl_fout
7110 short fout_ext - tbl_fout
7111 short fout_pack - tbl_fout
7112 short fout_word - tbl_fout
7113 short fout_dbl - tbl_fout
7114 short fout_byte - tbl_fout
7115 short fout_pack - tbl_fout
7116
7117#################################################################
7118# fmove.b out ###################################################
7119#################################################################
7120
7121# Only "Unimplemented Data Type" exceptions enter here. The operand
7122# is either a DENORM or a NORM.
7123fout_byte:
7124 tst.b STAG(%a6) # is operand normalized?
7125 bne.b fout_byte_denorm # no
7126
7127 fmovm.x SRC(%a0),&0x80 # load value
7128
7129fout_byte_norm:
7130 fmov.l %d0,%fpcr # insert rnd prec,mode
7131
7132 fmov.b %fp0,%d0 # exec move out w/ correct rnd mode
7133
7134 fmov.l &0x0,%fpcr # clear FPCR
7135 fmov.l %fpsr,%d1 # fetch FPSR
7136 or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
7137
7138 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7139 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7140 beq.b fout_byte_dn # must save to integer regfile
7141
7142 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7143 bsr.l _dmem_write_byte # write byte
7144
7145 tst.l %d1 # did dstore fail?
7146 bne.l facc_out_b # yes
7147
7148 rts
7149
7150fout_byte_dn:
7151 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7152 andi.w &0x7,%d1
7153 bsr.l store_dreg_b
7154 rts
7155
7156fout_byte_denorm:
7157 mov.l SRC_EX(%a0),%d1
7158 andi.l &0x80000000,%d1 # keep DENORM sign
7159 ori.l &0x00800000,%d1 # make smallest sgl
7160 fmov.s %d1,%fp0
7161 bra.b fout_byte_norm
7162
7163#################################################################
7164# fmove.w out ###################################################
7165#################################################################
7166
7167# Only "Unimplemented Data Type" exceptions enter here. The operand
7168# is either a DENORM or a NORM.
7169fout_word:
7170 tst.b STAG(%a6) # is operand normalized?
7171 bne.b fout_word_denorm # no
7172
7173 fmovm.x SRC(%a0),&0x80 # load value
7174
7175fout_word_norm:
7176 fmov.l %d0,%fpcr # insert rnd prec:mode
7177
7178 fmov.w %fp0,%d0 # exec move out w/ correct rnd mode
7179
7180 fmov.l &0x0,%fpcr # clear FPCR
7181 fmov.l %fpsr,%d1 # fetch FPSR
7182 or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
7183
7184 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7185 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7186 beq.b fout_word_dn # must save to integer regfile
7187
7188 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7189 bsr.l _dmem_write_word # write word
7190
7191 tst.l %d1 # did dstore fail?
7192 bne.l facc_out_w # yes
7193
7194 rts
7195
7196fout_word_dn:
7197 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7198 andi.w &0x7,%d1
7199 bsr.l store_dreg_w
7200 rts
7201
7202fout_word_denorm:
7203 mov.l SRC_EX(%a0),%d1
7204 andi.l &0x80000000,%d1 # keep DENORM sign
7205 ori.l &0x00800000,%d1 # make smallest sgl
7206 fmov.s %d1,%fp0
7207 bra.b fout_word_norm
7208
7209#################################################################
7210# fmove.l out ###################################################
7211#################################################################
7212
7213# Only "Unimplemented Data Type" exceptions enter here. The operand
7214# is either a DENORM or a NORM.
7215fout_long:
7216 tst.b STAG(%a6) # is operand normalized?
7217 bne.b fout_long_denorm # no
7218
7219 fmovm.x SRC(%a0),&0x80 # load value
7220
7221fout_long_norm:
7222 fmov.l %d0,%fpcr # insert rnd prec:mode
7223
7224 fmov.l %fp0,%d0 # exec move out w/ correct rnd mode
7225
7226 fmov.l &0x0,%fpcr # clear FPCR
7227 fmov.l %fpsr,%d1 # fetch FPSR
7228 or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
7229
7230fout_long_write:
7231 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7232 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7233 beq.b fout_long_dn # must save to integer regfile
7234
7235 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7236 bsr.l _dmem_write_long # write long
7237
7238 tst.l %d1 # did dstore fail?
7239 bne.l facc_out_l # yes
7240
7241 rts
7242
7243fout_long_dn:
7244 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7245 andi.w &0x7,%d1
7246 bsr.l store_dreg_l
7247 rts
7248
7249fout_long_denorm:
7250 mov.l SRC_EX(%a0),%d1
7251 andi.l &0x80000000,%d1 # keep DENORM sign
7252 ori.l &0x00800000,%d1 # make smallest sgl
7253 fmov.s %d1,%fp0
7254 bra.b fout_long_norm
7255
7256#################################################################
7257# fmove.x out ###################################################
7258#################################################################
7259
7260# Only "Unimplemented Data Type" exceptions enter here. The operand
7261# is either a DENORM or a NORM.
7262# The DENORM causes an Underflow exception.
7263fout_ext:
7264
7265# we copy the extended precision result to FP_SCR0 so that the reserved
7266# 16-bit field gets zeroed. we do this since we promise not to disturb
7267# what's at SRC(a0).
7268 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7269 clr.w 2+FP_SCR0_EX(%a6) # clear reserved field
7270 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7271 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7272
7273 fmovm.x SRC(%a0),&0x80 # return result
7274
7275 bsr.l _calc_ea_fout # fix stacked <ea>
7276
7277 mov.l %a0,%a1 # pass: dst addr
7278 lea FP_SCR0(%a6),%a0 # pass: src addr
7279 mov.l &0xc,%d0 # pass: opsize is 12 bytes
7280
7281# we must not yet write the extended precision data to the stack
7282# in the pre-decrement case from supervisor mode or else we'll corrupt
7283# the stack frame. so, leave it in FP_SRC for now and deal with it later...
7284 cmpi.b SPCOND_FLG(%a6),&mda7_flg
7285 beq.b fout_ext_a7
7286
7287 bsr.l _dmem_write # write ext prec number to memory
7288
7289 tst.l %d1 # did dstore fail?
7290 bne.w fout_ext_err # yes
7291
7292 tst.b STAG(%a6) # is operand normalized?
7293 bne.b fout_ext_denorm # no
7294 rts
7295
7296# the number is a DENORM. must set the underflow exception bit
7297fout_ext_denorm:
7298 bset &unfl_bit,FPSR_EXCEPT(%a6) # set underflow exc bit
7299
7300 mov.b FPCR_ENABLE(%a6),%d0
7301 andi.b &0x0a,%d0 # is UNFL or INEX enabled?
7302 bne.b fout_ext_exc # yes
7303 rts
7304
7305# we don't want to do the write if the exception occurred in supervisor mode
7306# so _mem_write2() handles this for us.
7307fout_ext_a7:
7308 bsr.l _mem_write2 # write ext prec number to memory
7309
7310 tst.l %d1 # did dstore fail?
7311 bne.w fout_ext_err # yes
7312
7313 tst.b STAG(%a6) # is operand normalized?
7314 bne.b fout_ext_denorm # no
7315 rts
7316
7317fout_ext_exc:
7318 lea FP_SCR0(%a6),%a0
7319 bsr.l norm # normalize the mantissa
7320 neg.w %d0 # new exp = -(shft amt)
7321 andi.w &0x7fff,%d0
7322 andi.w &0x8000,FP_SCR0_EX(%a6) # keep only old sign
7323 or.w %d0,FP_SCR0_EX(%a6) # insert new exponent
7324 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
7325 rts
7326
7327fout_ext_err:
7328 mov.l EXC_A6(%a6),(%a6) # fix stacked a6
7329 bra.l facc_out_x
7330
7331#########################################################################
7332# fmove.s out ###########################################################
7333#########################################################################
7334fout_sgl:
7335 andi.b &0x30,%d0 # clear rnd prec
7336 ori.b &s_mode*0x10,%d0 # insert sgl prec
7337 mov.l %d0,L_SCR3(%a6) # save rnd prec,mode on stack
7338
7339#
7340# operand is a normalized number. first, we check to see if the move out
7341# would cause either an underflow or overflow. these cases are handled
7342# separately. otherwise, set the FPCR to the proper rounding mode and
7343# execute the move.
7344#
7345 mov.w SRC_EX(%a0),%d0 # extract exponent
7346 andi.w &0x7fff,%d0 # strip sign
7347
7348 cmpi.w %d0,&SGL_HI # will operand overflow?
7349 bgt.w fout_sgl_ovfl # yes; go handle OVFL
7350 beq.w fout_sgl_may_ovfl # maybe; go handle possible OVFL
7351 cmpi.w %d0,&SGL_LO # will operand underflow?
7352 blt.w fout_sgl_unfl # yes; go handle underflow
7353
7354#
7355# NORMs(in range) can be stored out by a simple "fmov.s"
7356# Unnormalized inputs can come through this point.
7357#
7358fout_sgl_exg:
7359 fmovm.x SRC(%a0),&0x80 # fetch fop from stack
7360
7361 fmov.l L_SCR3(%a6),%fpcr # set FPCR
7362 fmov.l &0x0,%fpsr # clear FPSR
7363
7364 fmov.s %fp0,%d0 # store does convert and round
7365
7366 fmov.l &0x0,%fpcr # clear FPCR
7367 fmov.l %fpsr,%d1 # save FPSR
7368
7369 or.w %d1,2+USER_FPSR(%a6) # set possible inex2/ainex
7370
7371fout_sgl_exg_write:
7372 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7373 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7374 beq.b fout_sgl_exg_write_dn # must save to integer regfile
7375
7376 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7377 bsr.l _dmem_write_long # write long
7378
7379 tst.l %d1 # did dstore fail?
7380 bne.l facc_out_l # yes
7381
7382 rts
7383
7384fout_sgl_exg_write_dn:
7385 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7386 andi.w &0x7,%d1
7387 bsr.l store_dreg_l
7388 rts
7389
7390#
7391# here, we know that the operand would UNFL if moved out to single prec,
7392# so, denorm and round and then use generic store single routine to
7393# write the value to memory.
7394#
7395fout_sgl_unfl:
7396 bset &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
7397
7398 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7399 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7400 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7401 mov.l %a0,-(%sp)
7402
7403 clr.l %d0 # pass: S.F. = 0
7404
7405 cmpi.b STAG(%a6),&DENORM # fetch src optype tag
7406 bne.b fout_sgl_unfl_cont # let DENORMs fall through
7407
7408 lea FP_SCR0(%a6),%a0
7409 bsr.l norm # normalize the DENORM
7410
7411fout_sgl_unfl_cont:
7412 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
7413 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
7414 bsr.l unf_res # calc default underflow result
7415
7416 lea FP_SCR0(%a6),%a0 # pass: ptr to fop
7417 bsr.l dst_sgl # convert to single prec
7418
7419 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7420 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7421 beq.b fout_sgl_unfl_dn # must save to integer regfile
7422
7423 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7424 bsr.l _dmem_write_long # write long
7425
7426 tst.l %d1 # did dstore fail?
7427 bne.l facc_out_l # yes
7428
7429 bra.b fout_sgl_unfl_chkexc
7430
7431fout_sgl_unfl_dn:
7432 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7433 andi.w &0x7,%d1
7434 bsr.l store_dreg_l
7435
7436fout_sgl_unfl_chkexc:
7437 mov.b FPCR_ENABLE(%a6),%d1
7438 andi.b &0x0a,%d1 # is UNFL or INEX enabled?
7439 bne.w fout_sd_exc_unfl # yes
7440 addq.l &0x4,%sp
7441 rts
7442
7443#
7444# it's definitely an overflow so call ovf_res to get the correct answer
7445#
7446fout_sgl_ovfl:
7447 tst.b 3+SRC_HI(%a0) # is result inexact?
7448 bne.b fout_sgl_ovfl_inex2
7449 tst.l SRC_LO(%a0) # is result inexact?
7450 bne.b fout_sgl_ovfl_inex2
7451 ori.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
7452 bra.b fout_sgl_ovfl_cont
7453fout_sgl_ovfl_inex2:
7454 ori.w &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
7455
7456fout_sgl_ovfl_cont:
7457 mov.l %a0,-(%sp)
7458
7459# call ovf_res() w/ sgl prec and the correct rnd mode to create the default
7460# overflow result. DON'T save the returned ccodes from ovf_res() since
7461# fmove out doesn't alter them.
7462 tst.b SRC_EX(%a0) # is operand negative?
7463 smi %d1 # set if so
7464 mov.l L_SCR3(%a6),%d0 # pass: sgl prec,rnd mode
7465 bsr.l ovf_res # calc OVFL result
7466 fmovm.x (%a0),&0x80 # load default overflow result
7467 fmov.s %fp0,%d0 # store to single
7468
7469 mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7470 andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7471 beq.b fout_sgl_ovfl_dn # must save to integer regfile
7472
7473 mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7474 bsr.l _dmem_write_long # write long
7475
7476 tst.l %d1 # did dstore fail?
7477 bne.l facc_out_l # yes
7478
7479 bra.b fout_sgl_ovfl_chkexc
7480
7481fout_sgl_ovfl_dn:
7482 mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7483 andi.w &0x7,%d1
7484 bsr.l store_dreg_l
7485
7486fout_sgl_ovfl_chkexc:
7487 mov.b FPCR_ENABLE(%a6),%d1
7488 andi.b &0x0a,%d1 # is UNFL or INEX enabled?
7489 bne.w fout_sd_exc_ovfl # yes
7490 addq.l &0x4,%sp
7491 rts
7492
7493#
7494# move out MAY overflow:
7495# (1) force the exp to 0x3fff
7496# (2) do a move w/ appropriate rnd mode
7497# (3) if exp still equals zero, then insert original exponent
7498# for the correct result.
7499# if exp now equals one, then it overflowed so call ovf_res.
7500#
7501fout_sgl_may_ovfl:
7502 mov.w SRC_EX(%a0),%d1 # fetch current sign
7503 andi.w &0x8000,%d1 # keep it,clear exp
7504 ori.w &0x3fff,%d1 # insert exp = 0
7505 mov.w %d1,FP_SCR0_EX(%a6) # insert scaled exp
7506 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
7507 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
7508
7509 fmov.l L_SCR3(%a6),%fpcr # set FPCR
7510
7511 fmov.x FP_SCR0(%a6),%fp0 # force fop to be rounded
7512 fmov.l &0x0,%fpcr # clear FPCR
7513
7514 fabs.x %fp0 # need absolute value
7515 fcmp.b %fp0,&0x2 # did exponent increase?
7516 fblt.w fout_sgl_exg # no; go finish NORM
7517 bra.w fout_sgl_ovfl # yes; go handle overflow
7518
7519################
7520
7521fout_sd_exc_unfl:
7522 mov.l (%sp)+,%a0
7523
7524 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7525 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7526 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7527
7528 cmpi.b STAG(%a6),&DENORM # was src a DENORM?
7529 bne.b fout_sd_exc_cont # no
7530
7531 lea FP_SCR0(%a6),%a0
7532 bsr.l norm
7533 neg.l %d0
7534 andi.w &0x7fff,%d0
7535 bfins %d0,FP_SCR0_EX(%a6){&1:&15}
7536 bra.b fout_sd_exc_cont
7537
7538fout_sd_exc:
7539fout_sd_exc_ovfl:
7540 mov.l (%sp)+,%a0 # restore a0
7541
7542 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7543 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7544 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7545
7546fout_sd_exc_cont:
7547 bclr &0x7,FP_SCR0_EX(%a6) # clear sign bit
7548 sne.b 2+FP_SCR0_EX(%a6) # set internal sign bit
7549 lea FP_SCR0(%a6),%a0 # pass: ptr to DENORM
7550
7551 mov.b 3+L_SCR3(%a6),%d1
7552 lsr.b &0x4,%d1
7553 andi.w &0x0c,%d1
7554 swap %d1
7555 mov.b 3+L_SCR3(%a6),%d1
7556 lsr.b &0x4,%d1
7557 andi.w &0x03,%d1
7558 clr.l %d0 # pass: zero g,r,s
7559 bsr.l _round # round the DENORM
7560
7561 tst.b 2+FP_SCR0_EX(%a6) # is EXOP negative?
7562 beq.b fout_sd_exc_done # no
7563 bset &0x7,FP_SCR0_EX(%a6) # yes
7564
7565fout_sd_exc_done:
7566 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
7567 rts
7568
7569#################################################################
7570# fmove.d out ###################################################
7571#################################################################
7572fout_dbl:
7573 andi.b &0x30,%d0 # clear rnd prec
7574 ori.b &d_mode*0x10,%d0 # insert dbl prec
7575 mov.l %d0,L_SCR3(%a6) # save rnd prec,mode on stack
7576
7577#
7578# operand is a normalized number. first, we check to see if the move out
7579# would cause either an underflow or overflow. these cases are handled
7580# separately. otherwise, set the FPCR to the proper rounding mode and
7581# execute the move.
7582#
7583 mov.w SRC_EX(%a0),%d0 # extract exponent
7584 andi.w &0x7fff,%d0 # strip sign
7585
7586 cmpi.w %d0,&DBL_HI # will operand overflow?
7587 bgt.w fout_dbl_ovfl # yes; go handle OVFL
7588 beq.w fout_dbl_may_ovfl # maybe; go handle possible OVFL
7589 cmpi.w %d0,&DBL_LO # will operand underflow?
7590 blt.w fout_dbl_unfl # yes; go handle underflow
7591
7592#
7593# NORMs(in range) can be stored out by a simple "fmov.d"
7594# Unnormalized inputs can come through this point.
7595#
7596fout_dbl_exg:
7597 fmovm.x SRC(%a0),&0x80 # fetch fop from stack
7598
7599 fmov.l L_SCR3(%a6),%fpcr # set FPCR
7600 fmov.l &0x0,%fpsr # clear FPSR
7601
7602 fmov.d %fp0,L_SCR1(%a6) # store does convert and round
7603
7604 fmov.l &0x0,%fpcr # clear FPCR
7605 fmov.l %fpsr,%d0 # save FPSR
7606
7607 or.w %d0,2+USER_FPSR(%a6) # set possible inex2/ainex
7608
7609 mov.l EXC_EA(%a6),%a1 # pass: dst addr
7610 lea L_SCR1(%a6),%a0 # pass: src addr
7611 movq.l &0x8,%d0 # pass: opsize is 8 bytes
7612 bsr.l _dmem_write # store dbl fop to memory
7613
7614 tst.l %d1 # did dstore fail?
7615 bne.l facc_out_d # yes
7616
7617 rts # no; so we're finished
7618
7619#
7620# here, we know that the operand would UNFL if moved out to double prec,
7621# so, denorm and round and then use generic store double routine to
7622# write the value to memory.
7623#
7624fout_dbl_unfl:
7625 bset &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
7626
7627 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7628 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7629 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7630 mov.l %a0,-(%sp)
7631
7632 clr.l %d0 # pass: S.F. = 0
7633
7634 cmpi.b STAG(%a6),&DENORM # fetch src optype tag
7635 bne.b fout_dbl_unfl_cont # let DENORMs fall through
7636
7637 lea FP_SCR0(%a6),%a0
7638 bsr.l norm # normalize the DENORM
7639
7640fout_dbl_unfl_cont:
7641 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
7642 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
7643 bsr.l unf_res # calc default underflow result
7644
7645 lea FP_SCR0(%a6),%a0 # pass: ptr to fop
7646 bsr.l dst_dbl # convert to single prec
7647 mov.l %d0,L_SCR1(%a6)
7648 mov.l %d1,L_SCR2(%a6)
7649
7650 mov.l EXC_EA(%a6),%a1 # pass: dst addr
7651 lea L_SCR1(%a6),%a0 # pass: src addr
7652 movq.l &0x8,%d0 # pass: opsize is 8 bytes
7653 bsr.l _dmem_write # store dbl fop to memory
7654
7655 tst.l %d1 # did dstore fail?
7656 bne.l facc_out_d # yes
7657
7658 mov.b FPCR_ENABLE(%a6),%d1
7659 andi.b &0x0a,%d1 # is UNFL or INEX enabled?
7660 bne.w fout_sd_exc_unfl # yes
7661 addq.l &0x4,%sp
7662 rts
7663
7664#
7665# it's definitely an overflow so call ovf_res to get the correct answer
7666#
7667fout_dbl_ovfl:
7668 mov.w 2+SRC_LO(%a0),%d0
7669 andi.w &0x7ff,%d0
7670 bne.b fout_dbl_ovfl_inex2
7671
7672 ori.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
7673 bra.b fout_dbl_ovfl_cont
7674fout_dbl_ovfl_inex2:
7675 ori.w &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
7676
7677fout_dbl_ovfl_cont:
7678 mov.l %a0,-(%sp)
7679
7680# call ovf_res() w/ dbl prec and the correct rnd mode to create the default
7681# overflow result. DON'T save the returned ccodes from ovf_res() since
7682# fmove out doesn't alter them.
7683 tst.b SRC_EX(%a0) # is operand negative?
7684 smi %d1 # set if so
7685 mov.l L_SCR3(%a6),%d0 # pass: dbl prec,rnd mode
7686 bsr.l ovf_res # calc OVFL result
7687 fmovm.x (%a0),&0x80 # load default overflow result
7688 fmov.d %fp0,L_SCR1(%a6) # store to double
7689
7690 mov.l EXC_EA(%a6),%a1 # pass: dst addr
7691 lea L_SCR1(%a6),%a0 # pass: src addr
7692 movq.l &0x8,%d0 # pass: opsize is 8 bytes
7693 bsr.l _dmem_write # store dbl fop to memory
7694
7695 tst.l %d1 # did dstore fail?
7696 bne.l facc_out_d # yes
7697
7698 mov.b FPCR_ENABLE(%a6),%d1
7699 andi.b &0x0a,%d1 # is UNFL or INEX enabled?
7700 bne.w fout_sd_exc_ovfl # yes
7701 addq.l &0x4,%sp
7702 rts
7703
7704#
7705# move out MAY overflow:
7706# (1) force the exp to 0x3fff
7707# (2) do a move w/ appropriate rnd mode
7708# (3) if exp still equals zero, then insert original exponent
7709# for the correct result.
7710# if exp now equals one, then it overflowed so call ovf_res.
7711#
7712fout_dbl_may_ovfl:
7713 mov.w SRC_EX(%a0),%d1 # fetch current sign
7714 andi.w &0x8000,%d1 # keep it,clear exp
7715 ori.w &0x3fff,%d1 # insert exp = 0
7716 mov.w %d1,FP_SCR0_EX(%a6) # insert scaled exp
7717 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
7718 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
7719
7720 fmov.l L_SCR3(%a6),%fpcr # set FPCR
7721
7722 fmov.x FP_SCR0(%a6),%fp0 # force fop to be rounded
7723 fmov.l &0x0,%fpcr # clear FPCR
7724
7725 fabs.x %fp0 # need absolute value
7726 fcmp.b %fp0,&0x2 # did exponent increase?
7727 fblt.w fout_dbl_exg # no; go finish NORM
7728 bra.w fout_dbl_ovfl # yes; go handle overflow
7729
7730#########################################################################
7731# XDEF **************************************************************** #
7732# dst_dbl(): create double precision value from extended prec. #
7733# #
7734# XREF **************************************************************** #
7735# None #
7736# #
7737# INPUT *************************************************************** #
7738# a0 = pointer to source operand in extended precision #
7739# #
7740# OUTPUT ************************************************************** #
7741# d0 = hi(double precision result) #
7742# d1 = lo(double precision result) #
7743# #
7744# ALGORITHM *********************************************************** #
7745# #
7746# Changes extended precision to double precision. #
7747# Note: no attempt is made to round the extended value to double. #
7748# dbl_sign = ext_sign #
7749# dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias) #
7750# get rid of ext integer bit #
7751# dbl_mant = ext_mant{62:12} #
7752# #
7753# --------------- --------------- --------------- #
7754# extended -> |s| exp | |1| ms mant | | ls mant | #
7755# --------------- --------------- --------------- #
7756# 95 64 63 62 32 31 11 0 #
7757# | | #
7758# | | #
7759# | | #
7760# v v #
7761# --------------- --------------- #
7762# double -> |s|exp| mant | | mant | #
7763# --------------- --------------- #
7764# 63 51 32 31 0 #
7765# #
7766#########################################################################
7767
7768dst_dbl:
7769 clr.l %d0 # clear d0
7770 mov.w FTEMP_EX(%a0),%d0 # get exponent
7771 subi.w &EXT_BIAS,%d0 # subtract extended precision bias
7772 addi.w &DBL_BIAS,%d0 # add double precision bias
7773 tst.b FTEMP_HI(%a0) # is number a denorm?
7774 bmi.b dst_get_dupper # no
7775 subq.w &0x1,%d0 # yes; denorm bias = DBL_BIAS - 1
7776dst_get_dupper:
7777 swap %d0 # d0 now in upper word
7778 lsl.l &0x4,%d0 # d0 in proper place for dbl prec exp
7779 tst.b FTEMP_EX(%a0) # test sign
7780 bpl.b dst_get_dman # if postive, go process mantissa
7781 bset &0x1f,%d0 # if negative, set sign
7782dst_get_dman:
7783 mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
7784 bfextu %d1{&1:&20},%d1 # get upper 20 bits of ms
7785 or.l %d1,%d0 # put these bits in ms word of double
7786 mov.l %d0,L_SCR1(%a6) # put the new exp back on the stack
7787 mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
7788 mov.l &21,%d0 # load shift count
7789 lsl.l %d0,%d1 # put lower 11 bits in upper bits
7790 mov.l %d1,L_SCR2(%a6) # build lower lword in memory
7791 mov.l FTEMP_LO(%a0),%d1 # get ls mantissa
7792 bfextu %d1{&0:&21},%d0 # get ls 21 bits of double
7793 mov.l L_SCR2(%a6),%d1
7794 or.l %d0,%d1 # put them in double result
7795 mov.l L_SCR1(%a6),%d0
7796 rts
7797
7798#########################################################################
7799# XDEF **************************************************************** #
7800# dst_sgl(): create single precision value from extended prec #
7801# #
7802# XREF **************************************************************** #
7803# #
7804# INPUT *************************************************************** #
7805# a0 = pointer to source operand in extended precision #
7806# #
7807# OUTPUT ************************************************************** #
7808# d0 = single precision result #
7809# #
7810# ALGORITHM *********************************************************** #
7811# #
7812# Changes extended precision to single precision. #
7813# sgl_sign = ext_sign #
7814# sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias) #
7815# get rid of ext integer bit #
7816# sgl_mant = ext_mant{62:12} #
7817# #
7818# --------------- --------------- --------------- #
7819# extended -> |s| exp | |1| ms mant | | ls mant | #
7820# --------------- --------------- --------------- #
7821# 95 64 63 62 40 32 31 12 0 #
7822# | | #
7823# | | #
7824# | | #
7825# v v #
7826# --------------- #
7827# single -> |s|exp| mant | #
7828# --------------- #
7829# 31 22 0 #
7830# #
7831#########################################################################
7832
7833dst_sgl:
7834 clr.l %d0
7835 mov.w FTEMP_EX(%a0),%d0 # get exponent
7836 subi.w &EXT_BIAS,%d0 # subtract extended precision bias
7837 addi.w &SGL_BIAS,%d0 # add single precision bias
7838 tst.b FTEMP_HI(%a0) # is number a denorm?
7839 bmi.b dst_get_supper # no
7840 subq.w &0x1,%d0 # yes; denorm bias = SGL_BIAS - 1
7841dst_get_supper:
7842 swap %d0 # put exp in upper word of d0
7843 lsl.l &0x7,%d0 # shift it into single exp bits
7844 tst.b FTEMP_EX(%a0) # test sign
7845 bpl.b dst_get_sman # if positive, continue
7846 bset &0x1f,%d0 # if negative, put in sign first
7847dst_get_sman:
7848 mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
7849 andi.l &0x7fffff00,%d1 # get upper 23 bits of ms
7850 lsr.l &0x8,%d1 # and put them flush right
7851 or.l %d1,%d0 # put these bits in ms word of single
7852 rts
7853
7854##############################################################################
7855fout_pack:
7856 bsr.l _calc_ea_fout # fetch the <ea>
7857 mov.l %a0,-(%sp)
7858
7859 mov.b STAG(%a6),%d0 # fetch input type
7860 bne.w fout_pack_not_norm # input is not NORM
7861
7862fout_pack_norm:
7863 btst &0x4,EXC_CMDREG(%a6) # static or dynamic?
7864 beq.b fout_pack_s # static
7865
7866fout_pack_d:
7867 mov.b 1+EXC_CMDREG(%a6),%d1 # fetch dynamic reg
7868 lsr.b &0x4,%d1
7869 andi.w &0x7,%d1
7870
7871 bsr.l fetch_dreg # fetch Dn w/ k-factor
7872
7873 bra.b fout_pack_type
7874fout_pack_s:
7875 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch static field
7876
7877fout_pack_type:
7878 bfexts %d0{&25:&7},%d0 # extract k-factor
7879 mov.l %d0,-(%sp)
7880
7881 lea FP_SRC(%a6),%a0 # pass: ptr to input
7882
7883# bindec is currently scrambling FP_SRC for denorm inputs.
7884# we'll have to change this, but for now, tough luck!!!
7885 bsr.l bindec # convert xprec to packed
7886
7887# andi.l &0xcfff000f,FP_SCR0(%a6) # clear unused fields
7888 andi.l &0xcffff00f,FP_SCR0(%a6) # clear unused fields
7889
7890 mov.l (%sp)+,%d0
7891
7892 tst.b 3+FP_SCR0_EX(%a6)
7893 bne.b fout_pack_set
7894 tst.l FP_SCR0_HI(%a6)
7895 bne.b fout_pack_set
7896 tst.l FP_SCR0_LO(%a6)
7897 bne.b fout_pack_set
7898
7899# add the extra condition that only if the k-factor was zero, too, should
7900# we zero the exponent
7901 tst.l %d0
7902 bne.b fout_pack_set
7903# "mantissa" is all zero which means that the answer is zero. but, the '040
7904# algorithm allows the exponent to be non-zero. the 881/2 do not. therefore,
7905# if the mantissa is zero, I will zero the exponent, too.
7906# the question now is whether the exponents sign bit is allowed to be non-zero
7907# for a zero, also...
7908 andi.w &0xf000,FP_SCR0(%a6)
7909
7910fout_pack_set:
7911
7912 lea FP_SCR0(%a6),%a0 # pass: src addr
7913
7914fout_pack_write:
7915 mov.l (%sp)+,%a1 # pass: dst addr
7916 mov.l &0xc,%d0 # pass: opsize is 12 bytes
7917
7918 cmpi.b SPCOND_FLG(%a6),&mda7_flg
7919 beq.b fout_pack_a7
7920
7921 bsr.l _dmem_write # write ext prec number to memory
7922
7923 tst.l %d1 # did dstore fail?
7924 bne.w fout_ext_err # yes
7925
7926 rts
7927
7928# we don't want to do the write if the exception occurred in supervisor mode
7929# so _mem_write2() handles this for us.
7930fout_pack_a7:
7931 bsr.l _mem_write2 # write ext prec number to memory
7932
7933 tst.l %d1 # did dstore fail?
7934 bne.w fout_ext_err # yes
7935
7936 rts
7937
7938fout_pack_not_norm:
7939 cmpi.b %d0,&DENORM # is it a DENORM?
7940 beq.w fout_pack_norm # yes
7941 lea FP_SRC(%a6),%a0
7942 clr.w 2+FP_SRC_EX(%a6)
7943 cmpi.b %d0,&SNAN # is it an SNAN?
7944 beq.b fout_pack_snan # yes
7945 bra.b fout_pack_write # no
7946
7947fout_pack_snan:
7948 ori.w &snaniop2_mask,FPSR_EXCEPT(%a6) # set SNAN/AIOP
7949 bset &0x6,FP_SRC_HI(%a6) # set snan bit
7950 bra.b fout_pack_write
7951
7952#########################################################################
7953# XDEF **************************************************************** #
7954# fmul(): emulates the fmul instruction #
7955# fsmul(): emulates the fsmul instruction #
7956# fdmul(): emulates the fdmul instruction #
7957# #
7958# XREF **************************************************************** #
7959# scale_to_zero_src() - scale src exponent to zero #
7960# scale_to_zero_dst() - scale dst exponent to zero #
7961# unf_res() - return default underflow result #
7962# ovf_res() - return default overflow result #
7963# res_qnan() - return QNAN result #
7964# res_snan() - return SNAN result #
7965# #
7966# INPUT *************************************************************** #
7967# a0 = pointer to extended precision source operand #
7968# a1 = pointer to extended precision destination operand #
7969# d0 rnd prec,mode #
7970# #
7971# OUTPUT ************************************************************** #
7972# fp0 = result #
7973# fp1 = EXOP (if exception occurred) #
7974# #
7975# ALGORITHM *********************************************************** #
7976# Handle NANs, infinities, and zeroes as special cases. Divide #
7977# norms/denorms into ext/sgl/dbl precision. #
7978# For norms/denorms, scale the exponents such that a multiply #
7979# instruction won't cause an exception. Use the regular fmul to #
7980# compute a result. Check if the regular operands would have taken #
7981# an exception. If so, return the default overflow/underflow result #
7982# and return the EXOP if exceptions are enabled. Else, scale the #
7983# result operand to the proper exponent. #
7984# #
7985#########################################################################
7986
7987 align 0x10
7988tbl_fmul_ovfl:
7989 long 0x3fff - 0x7ffe # ext_max
7990 long 0x3fff - 0x407e # sgl_max
7991 long 0x3fff - 0x43fe # dbl_max
7992tbl_fmul_unfl:
7993 long 0x3fff + 0x0001 # ext_unfl
7994 long 0x3fff - 0x3f80 # sgl_unfl
7995 long 0x3fff - 0x3c00 # dbl_unfl
7996
7997 global fsmul
7998fsmul:
7999 andi.b &0x30,%d0 # clear rnd prec
8000 ori.b &s_mode*0x10,%d0 # insert sgl prec
8001 bra.b fmul
8002
8003 global fdmul
8004fdmul:
8005 andi.b &0x30,%d0
8006 ori.b &d_mode*0x10,%d0 # insert dbl prec
8007
8008 global fmul
8009fmul:
8010 mov.l %d0,L_SCR3(%a6) # store rnd info
8011
8012 clr.w %d1
8013 mov.b DTAG(%a6),%d1
8014 lsl.b &0x3,%d1
8015 or.b STAG(%a6),%d1 # combine src tags
8016 bne.w fmul_not_norm # optimize on non-norm input
8017
8018fmul_norm:
8019 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
8020 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
8021 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
8022
8023 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8024 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8025 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8026
8027 bsr.l scale_to_zero_src # scale src exponent
8028 mov.l %d0,-(%sp) # save scale factor 1
8029
8030 bsr.l scale_to_zero_dst # scale dst exponent
8031
8032 add.l %d0,(%sp) # SCALE_FACTOR = scale1 + scale2
8033
8034 mov.w 2+L_SCR3(%a6),%d1 # fetch precision
8035 lsr.b &0x6,%d1 # shift to lo bits
8036 mov.l (%sp)+,%d0 # load S.F.
8037 cmp.l %d0,(tbl_fmul_ovfl.w,%pc,%d1.w*4) # would result ovfl?
8038 beq.w fmul_may_ovfl # result may rnd to overflow
8039 blt.w fmul_ovfl # result will overflow
8040
8041 cmp.l %d0,(tbl_fmul_unfl.w,%pc,%d1.w*4) # would result unfl?
8042 beq.w fmul_may_unfl # result may rnd to no unfl
8043 bgt.w fmul_unfl # result will underflow
8044
8045#
8046# NORMAL:
8047# - the result of the multiply operation will neither overflow nor underflow.
8048# - do the multiply to the proper precision and rounding mode.
8049# - scale the result exponent using the scale factor. if both operands were
8050# normalized then we really don't need to go through this scaling. but for now,
8051# this will do.
8052#
8053fmul_normal:
8054 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8055
8056 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8057 fmov.l &0x0,%fpsr # clear FPSR
8058
8059 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8060
8061 fmov.l %fpsr,%d1 # save status
8062 fmov.l &0x0,%fpcr # clear FPCR
8063
8064 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8065
8066fmul_normal_exit:
8067 fmovm.x &0x80,FP_SCR0(%a6) # store out result
8068 mov.l %d2,-(%sp) # save d2
8069 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
8070 mov.l %d1,%d2 # make a copy
8071 andi.l &0x7fff,%d1 # strip sign
8072 andi.w &0x8000,%d2 # keep old sign
8073 sub.l %d0,%d1 # add scale factor
8074 or.w %d2,%d1 # concat old sign,new exp
8075 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8076 mov.l (%sp)+,%d2 # restore d2
8077 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
8078 rts
8079
8080#
8081# OVERFLOW:
8082# - the result of the multiply operation is an overflow.
8083# - do the multiply to the proper precision and rounding mode in order to
8084# set the inexact bits.
8085# - calculate the default result and return it in fp0.
8086# - if overflow or inexact is enabled, we need a multiply result rounded to
8087# extended precision. if the original operation was extended, then we have this
8088# result. if the original operation was single or double, we have to do another
8089# multiply using extended precision and the correct rounding mode. the result
8090# of this operation then has its exponent scaled by -0x6000 to create the
8091# exceptional operand.
8092#
8093fmul_ovfl:
8094 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8095
8096 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8097 fmov.l &0x0,%fpsr # clear FPSR
8098
8099 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8100
8101 fmov.l %fpsr,%d1 # save status
8102 fmov.l &0x0,%fpcr # clear FPCR
8103
8104 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8105
8106# save setting this until now because this is where fmul_may_ovfl may jump in
8107fmul_ovfl_tst:
8108 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
8109
8110 mov.b FPCR_ENABLE(%a6),%d1
8111 andi.b &0x13,%d1 # is OVFL or INEX enabled?
8112 bne.b fmul_ovfl_ena # yes
8113
8114# calculate the default result
8115fmul_ovfl_dis:
8116 btst &neg_bit,FPSR_CC(%a6) # is result negative?
8117 sne %d1 # set sign param accordingly
8118 mov.l L_SCR3(%a6),%d0 # pass rnd prec,mode
8119 bsr.l ovf_res # calculate default result
8120 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
8121 fmovm.x (%a0),&0x80 # return default result in fp0
8122 rts
8123
8124#
8125# OVFL is enabled; Create EXOP:
8126# - if precision is extended, then we have the EXOP. simply bias the exponent
8127# with an extra -0x6000. if the precision is single or double, we need to
8128# calculate a result rounded to extended precision.
8129#
8130fmul_ovfl_ena:
8131 mov.l L_SCR3(%a6),%d1
8132 andi.b &0xc0,%d1 # test the rnd prec
8133 bne.b fmul_ovfl_ena_sd # it's sgl or dbl
8134
8135fmul_ovfl_ena_cont:
8136 fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
8137
8138 mov.l %d2,-(%sp) # save d2
8139 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
8140 mov.w %d1,%d2 # make a copy
8141 andi.l &0x7fff,%d1 # strip sign
8142 sub.l %d0,%d1 # add scale factor
8143 subi.l &0x6000,%d1 # subtract bias
8144 andi.w &0x7fff,%d1 # clear sign bit
8145 andi.w &0x8000,%d2 # keep old sign
8146 or.w %d2,%d1 # concat old sign,new exp
8147 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8148 mov.l (%sp)+,%d2 # restore d2
8149 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8150 bra.b fmul_ovfl_dis
8151
8152fmul_ovfl_ena_sd:
8153 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8154
8155 mov.l L_SCR3(%a6),%d1
8156 andi.b &0x30,%d1 # keep rnd mode only
8157 fmov.l %d1,%fpcr # set FPCR
8158
8159 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8160
8161 fmov.l &0x0,%fpcr # clear FPCR
8162 bra.b fmul_ovfl_ena_cont
8163
8164#
8165# may OVERFLOW:
8166# - the result of the multiply operation MAY overflow.
8167# - do the multiply to the proper precision and rounding mode in order to
8168# set the inexact bits.
8169# - calculate the default result and return it in fp0.
8170#
8171fmul_may_ovfl:
8172 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
8173
8174 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8175 fmov.l &0x0,%fpsr # clear FPSR
8176
8177 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8178
8179 fmov.l %fpsr,%d1 # save status
8180 fmov.l &0x0,%fpcr # clear FPCR
8181
8182 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8183
8184 fabs.x %fp0,%fp1 # make a copy of result
8185 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
8186 fbge.w fmul_ovfl_tst # yes; overflow has occurred
8187
8188# no, it didn't overflow; we have correct result
8189 bra.w fmul_normal_exit
8190
8191#
8192# UNDERFLOW:
8193# - the result of the multiply operation is an underflow.
8194# - do the multiply to the proper precision and rounding mode in order to
8195# set the inexact bits.
8196# - calculate the default result and return it in fp0.
8197# - if overflow or inexact is enabled, we need a multiply result rounded to
8198# extended precision. if the original operation was extended, then we have this
8199# result. if the original operation was single or double, we have to do another
8200# multiply using extended precision and the correct rounding mode. the result
8201# of this operation then has its exponent scaled by -0x6000 to create the
8202# exceptional operand.
8203#
8204fmul_unfl:
8205 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
8206
8207# for fun, let's use only extended precision, round to zero. then, let
8208# the unf_res() routine figure out all the rest.
8209# will we get the correct answer.
8210 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8211
8212 fmov.l &rz_mode*0x10,%fpcr # set FPCR
8213 fmov.l &0x0,%fpsr # clear FPSR
8214
8215 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8216
8217 fmov.l %fpsr,%d1 # save status
8218 fmov.l &0x0,%fpcr # clear FPCR
8219
8220 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8221
8222 mov.b FPCR_ENABLE(%a6),%d1
8223 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
8224 bne.b fmul_unfl_ena # yes
8225
8226fmul_unfl_dis:
8227 fmovm.x &0x80,FP_SCR0(%a6) # store out result
8228
8229 lea FP_SCR0(%a6),%a0 # pass: result addr
8230 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
8231 bsr.l unf_res # calculate default result
8232 or.b %d0,FPSR_CC(%a6) # unf_res2 may have set 'Z'
8233 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
8234 rts
8235
8236#
8237# UNFL is enabled.
8238#
8239fmul_unfl_ena:
8240 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
8241
8242 mov.l L_SCR3(%a6),%d1
8243 andi.b &0xc0,%d1 # is precision extended?
8244 bne.b fmul_unfl_ena_sd # no, sgl or dbl
8245
8246# if the rnd mode is anything but RZ, then we have to re-do the above
8247# multiplication becuase we used RZ for all.
8248 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8249
8250fmul_unfl_ena_cont:
8251 fmov.l &0x0,%fpsr # clear FPSR
8252
8253 fmul.x FP_SCR0(%a6),%fp1 # execute multiply
8254
8255 fmov.l &0x0,%fpcr # clear FPCR
8256
8257 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
8258 mov.l %d2,-(%sp) # save d2
8259 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
8260 mov.l %d1,%d2 # make a copy
8261 andi.l &0x7fff,%d1 # strip sign
8262 andi.w &0x8000,%d2 # keep old sign
8263 sub.l %d0,%d1 # add scale factor
8264 addi.l &0x6000,%d1 # add bias
8265 andi.w &0x7fff,%d1
8266 or.w %d2,%d1 # concat old sign,new exp
8267 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8268 mov.l (%sp)+,%d2 # restore d2
8269 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8270 bra.w fmul_unfl_dis
8271
8272fmul_unfl_ena_sd:
8273 mov.l L_SCR3(%a6),%d1
8274 andi.b &0x30,%d1 # use only rnd mode
8275 fmov.l %d1,%fpcr # set FPCR
8276
8277 bra.b fmul_unfl_ena_cont
8278
8279# MAY UNDERFLOW:
8280# -use the correct rounding mode and precision. this code favors operations
8281# that do not underflow.
8282fmul_may_unfl:
8283 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8284
8285 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8286 fmov.l &0x0,%fpsr # clear FPSR
8287
8288 fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8289
8290 fmov.l %fpsr,%d1 # save status
8291 fmov.l &0x0,%fpcr # clear FPCR
8292
8293 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8294
8295 fabs.x %fp0,%fp1 # make a copy of result
8296 fcmp.b %fp1,&0x2 # is |result| > 2.b?
8297 fbgt.w fmul_normal_exit # no; no underflow occurred
8298 fblt.w fmul_unfl # yes; underflow occurred
8299
8300#
8301# we still don't know if underflow occurred. result is ~ equal to 2. but,
8302# we don't know if the result was an underflow that rounded up to a 2 or
8303# a normalized number that rounded down to a 2. so, redo the entire operation
8304# using RZ as the rounding mode to see what the pre-rounded result is.
8305# this case should be relatively rare.
8306#
8307 fmovm.x FP_SCR1(%a6),&0x40 # load dst operand
8308
8309 mov.l L_SCR3(%a6),%d1
8310 andi.b &0xc0,%d1 # keep rnd prec
8311 ori.b &rz_mode*0x10,%d1 # insert RZ
8312
8313 fmov.l %d1,%fpcr # set FPCR
8314 fmov.l &0x0,%fpsr # clear FPSR
8315
8316 fmul.x FP_SCR0(%a6),%fp1 # execute multiply
8317
8318 fmov.l &0x0,%fpcr # clear FPCR
8319 fabs.x %fp1 # make absolute value
8320 fcmp.b %fp1,&0x2 # is |result| < 2.b?
8321 fbge.w fmul_normal_exit # no; no underflow occurred
8322 bra.w fmul_unfl # yes, underflow occurred
8323
8324################################################################################
8325
8326#
8327# Multiply: inputs are not both normalized; what are they?
8328#
8329fmul_not_norm:
8330 mov.w (tbl_fmul_op.b,%pc,%d1.w*2),%d1
8331 jmp (tbl_fmul_op.b,%pc,%d1.w)
8332
8333 swbeg &48
8334tbl_fmul_op:
8335 short fmul_norm - tbl_fmul_op # NORM x NORM
8336 short fmul_zero - tbl_fmul_op # NORM x ZERO
8337 short fmul_inf_src - tbl_fmul_op # NORM x INF
8338 short fmul_res_qnan - tbl_fmul_op # NORM x QNAN
8339 short fmul_norm - tbl_fmul_op # NORM x DENORM
8340 short fmul_res_snan - tbl_fmul_op # NORM x SNAN
8341 short tbl_fmul_op - tbl_fmul_op #
8342 short tbl_fmul_op - tbl_fmul_op #
8343
8344 short fmul_zero - tbl_fmul_op # ZERO x NORM
8345 short fmul_zero - tbl_fmul_op # ZERO x ZERO
8346 short fmul_res_operr - tbl_fmul_op # ZERO x INF
8347 short fmul_res_qnan - tbl_fmul_op # ZERO x QNAN
8348 short fmul_zero - tbl_fmul_op # ZERO x DENORM
8349 short fmul_res_snan - tbl_fmul_op # ZERO x SNAN
8350 short tbl_fmul_op - tbl_fmul_op #
8351 short tbl_fmul_op - tbl_fmul_op #
8352
8353 short fmul_inf_dst - tbl_fmul_op # INF x NORM
8354 short fmul_res_operr - tbl_fmul_op # INF x ZERO
8355 short fmul_inf_dst - tbl_fmul_op # INF x INF
8356 short fmul_res_qnan - tbl_fmul_op # INF x QNAN
8357 short fmul_inf_dst - tbl_fmul_op # INF x DENORM
8358 short fmul_res_snan - tbl_fmul_op # INF x SNAN
8359 short tbl_fmul_op - tbl_fmul_op #
8360 short tbl_fmul_op - tbl_fmul_op #
8361
8362 short fmul_res_qnan - tbl_fmul_op # QNAN x NORM
8363 short fmul_res_qnan - tbl_fmul_op # QNAN x ZERO
8364 short fmul_res_qnan - tbl_fmul_op # QNAN x INF
8365 short fmul_res_qnan - tbl_fmul_op # QNAN x QNAN
8366 short fmul_res_qnan - tbl_fmul_op # QNAN x DENORM
8367 short fmul_res_snan - tbl_fmul_op # QNAN x SNAN
8368 short tbl_fmul_op - tbl_fmul_op #
8369 short tbl_fmul_op - tbl_fmul_op #
8370
8371 short fmul_norm - tbl_fmul_op # NORM x NORM
8372 short fmul_zero - tbl_fmul_op # NORM x ZERO
8373 short fmul_inf_src - tbl_fmul_op # NORM x INF
8374 short fmul_res_qnan - tbl_fmul_op # NORM x QNAN
8375 short fmul_norm - tbl_fmul_op # NORM x DENORM
8376 short fmul_res_snan - tbl_fmul_op # NORM x SNAN
8377 short tbl_fmul_op - tbl_fmul_op #
8378 short tbl_fmul_op - tbl_fmul_op #
8379
8380 short fmul_res_snan - tbl_fmul_op # SNAN x NORM
8381 short fmul_res_snan - tbl_fmul_op # SNAN x ZERO
8382 short fmul_res_snan - tbl_fmul_op # SNAN x INF
8383 short fmul_res_snan - tbl_fmul_op # SNAN x QNAN
8384 short fmul_res_snan - tbl_fmul_op # SNAN x DENORM
8385 short fmul_res_snan - tbl_fmul_op # SNAN x SNAN
8386 short tbl_fmul_op - tbl_fmul_op #
8387 short tbl_fmul_op - tbl_fmul_op #
8388
8389fmul_res_operr:
8390 bra.l res_operr
8391fmul_res_snan:
8392 bra.l res_snan
8393fmul_res_qnan:
8394 bra.l res_qnan
8395
8396#
8397# Multiply: (Zero x Zero) || (Zero x norm) || (Zero x denorm)
8398#
8399 global fmul_zero # global for fsglmul
8400fmul_zero:
8401 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
8402 mov.b DST_EX(%a1),%d1
8403 eor.b %d0,%d1
8404 bpl.b fmul_zero_p # result ZERO is pos.
8405fmul_zero_n:
8406 fmov.s &0x80000000,%fp0 # load -ZERO
8407 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
8408 rts
8409fmul_zero_p:
8410 fmov.s &0x00000000,%fp0 # load +ZERO
8411 mov.b &z_bmask,FPSR_CC(%a6) # set Z
8412 rts
8413
8414#
8415# Multiply: (inf x inf) || (inf x norm) || (inf x denorm)
8416#
8417# Note: The j-bit for an infinity is a don't-care. However, to be
8418# strictly compatible w/ the 68881/882, we make sure to return an
8419# INF w/ the j-bit set if the input INF j-bit was set. Destination
8420# INFs take priority.
8421#
8422 global fmul_inf_dst # global for fsglmul
8423fmul_inf_dst:
8424 fmovm.x DST(%a1),&0x80 # return INF result in fp0
8425 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
8426 mov.b DST_EX(%a1),%d1
8427 eor.b %d0,%d1
8428 bpl.b fmul_inf_dst_p # result INF is pos.
8429fmul_inf_dst_n:
8430 fabs.x %fp0 # clear result sign
8431 fneg.x %fp0 # set result sign
8432 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
8433 rts
8434fmul_inf_dst_p:
8435 fabs.x %fp0 # clear result sign
8436 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
8437 rts
8438
8439 global fmul_inf_src # global for fsglmul
8440fmul_inf_src:
8441 fmovm.x SRC(%a0),&0x80 # return INF result in fp0
8442 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
8443 mov.b DST_EX(%a1),%d1
8444 eor.b %d0,%d1
8445 bpl.b fmul_inf_dst_p # result INF is pos.
8446 bra.b fmul_inf_dst_n
8447
8448#########################################################################
8449# XDEF **************************************************************** #
8450# fin(): emulates the fmove instruction #
8451# fsin(): emulates the fsmove instruction #
8452# fdin(): emulates the fdmove instruction #
8453# #
8454# XREF **************************************************************** #
8455# norm() - normalize mantissa for EXOP on denorm #
8456# scale_to_zero_src() - scale src exponent to zero #
8457# ovf_res() - return default overflow result #
8458# unf_res() - return default underflow result #
8459# res_qnan_1op() - return QNAN result #
8460# res_snan_1op() - return SNAN result #
8461# #
8462# INPUT *************************************************************** #
8463# a0 = pointer to extended precision source operand #
8464# d0 = round prec/mode #
8465# #
8466# OUTPUT ************************************************************** #
8467# fp0 = result #
8468# fp1 = EXOP (if exception occurred) #
8469# #
8470# ALGORITHM *********************************************************** #
8471# Handle NANs, infinities, and zeroes as special cases. Divide #
8472# norms into extended, single, and double precision. #
8473# Norms can be emulated w/ a regular fmove instruction. For #
8474# sgl/dbl, must scale exponent and perform an "fmove". Check to see #
8475# if the result would have overflowed/underflowed. If so, use unf_res() #
8476# or ovf_res() to return the default result. Also return EXOP if #
8477# exception is enabled. If no exception, return the default result. #
8478# Unnorms don't pass through here. #
8479# #
8480#########################################################################
8481
8482 global fsin
8483fsin:
8484 andi.b &0x30,%d0 # clear rnd prec
8485 ori.b &s_mode*0x10,%d0 # insert sgl precision
8486 bra.b fin
8487
8488 global fdin
8489fdin:
8490 andi.b &0x30,%d0 # clear rnd prec
8491 ori.b &d_mode*0x10,%d0 # insert dbl precision
8492
8493 global fin
8494fin:
8495 mov.l %d0,L_SCR3(%a6) # store rnd info
8496
8497 mov.b STAG(%a6),%d1 # fetch src optype tag
8498 bne.w fin_not_norm # optimize on non-norm input
8499
8500#
8501# FP MOVE IN: NORMs and DENORMs ONLY!
8502#
8503fin_norm:
8504 andi.b &0xc0,%d0 # is precision extended?
8505 bne.w fin_not_ext # no, so go handle dbl or sgl
8506
8507#
8508# precision selected is extended. so...we cannot get an underflow
8509# or overflow because of rounding to the correct precision. so...
8510# skip the scaling and unscaling...
8511#
8512 tst.b SRC_EX(%a0) # is the operand negative?
8513 bpl.b fin_norm_done # no
8514 bset &neg_bit,FPSR_CC(%a6) # yes, so set 'N' ccode bit
8515fin_norm_done:
8516 fmovm.x SRC(%a0),&0x80 # return result in fp0
8517 rts
8518
8519#
8520# for an extended precision DENORM, the UNFL exception bit is set
8521# the accrued bit is NOT set in this instance(no inexactness!)
8522#
8523fin_denorm:
8524 andi.b &0xc0,%d0 # is precision extended?
8525 bne.w fin_not_ext # no, so go handle dbl or sgl
8526
8527 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
8528 tst.b SRC_EX(%a0) # is the operand negative?
8529 bpl.b fin_denorm_done # no
8530 bset &neg_bit,FPSR_CC(%a6) # yes, so set 'N' ccode bit
8531fin_denorm_done:
8532 fmovm.x SRC(%a0),&0x80 # return result in fp0
8533 btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
8534 bne.b fin_denorm_unfl_ena # yes
8535 rts
8536
8537#
8538# the input is an extended DENORM and underflow is enabled in the FPCR.
8539# normalize the mantissa and add the bias of 0x6000 to the resulting negative
8540# exponent and insert back into the operand.
8541#
8542fin_denorm_unfl_ena:
8543 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8544 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8545 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8546 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
8547 bsr.l norm # normalize result
8548 neg.w %d0 # new exponent = -(shft val)
8549 addi.w &0x6000,%d0 # add new bias to exponent
8550 mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
8551 andi.w &0x8000,%d1 # keep old sign
8552 andi.w &0x7fff,%d0 # clear sign position
8553 or.w %d1,%d0 # concat new exo,old sign
8554 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
8555 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8556 rts
8557
8558#
8559# operand is to be rounded to single or double precision
8560#
8561fin_not_ext:
8562 cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
8563 bne.b fin_dbl
8564
8565#
8566# operand is to be rounded to single precision
8567#
8568fin_sgl:
8569 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8570 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8571 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8572 bsr.l scale_to_zero_src # calculate scale factor
8573
8574 cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
8575 bge.w fin_sd_unfl # yes; go handle underflow
8576 cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
8577 beq.w fin_sd_may_ovfl # maybe; go check
8578 blt.w fin_sd_ovfl # yes; go handle overflow
8579
8580#
8581# operand will NOT overflow or underflow when moved into the fp reg file
8582#
8583fin_sd_normal:
8584 fmov.l &0x0,%fpsr # clear FPSR
8585 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8586
8587 fmov.x FP_SCR0(%a6),%fp0 # perform move
8588
8589 fmov.l %fpsr,%d1 # save FPSR
8590 fmov.l &0x0,%fpcr # clear FPCR
8591
8592 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8593
8594fin_sd_normal_exit:
8595 mov.l %d2,-(%sp) # save d2
8596 fmovm.x &0x80,FP_SCR0(%a6) # store out result
8597 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
8598 mov.w %d1,%d2 # make a copy
8599 andi.l &0x7fff,%d1 # strip sign
8600 sub.l %d0,%d1 # add scale factor
8601 andi.w &0x8000,%d2 # keep old sign
8602 or.w %d1,%d2 # concat old sign,new exponent
8603 mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
8604 mov.l (%sp)+,%d2 # restore d2
8605 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
8606 rts
8607
8608#
8609# operand is to be rounded to double precision
8610#
8611fin_dbl:
8612 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8613 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8614 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8615 bsr.l scale_to_zero_src # calculate scale factor
8616
8617 cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
8618 bge.w fin_sd_unfl # yes; go handle underflow
8619 cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
8620 beq.w fin_sd_may_ovfl # maybe; go check
8621 blt.w fin_sd_ovfl # yes; go handle overflow
8622 bra.w fin_sd_normal # no; ho handle normalized op
8623
8624#
8625# operand WILL underflow when moved in to the fp register file
8626#
8627fin_sd_unfl:
8628 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
8629
8630 tst.b FP_SCR0_EX(%a6) # is operand negative?
8631 bpl.b fin_sd_unfl_tst
8632 bset &neg_bit,FPSR_CC(%a6) # set 'N' ccode bit
8633
8634# if underflow or inexact is enabled, then go calculate the EXOP first.
8635fin_sd_unfl_tst:
8636 mov.b FPCR_ENABLE(%a6),%d1
8637 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
8638 bne.b fin_sd_unfl_ena # yes
8639
8640fin_sd_unfl_dis:
8641 lea FP_SCR0(%a6),%a0 # pass: result addr
8642 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
8643 bsr.l unf_res # calculate default result
8644 or.b %d0,FPSR_CC(%a6) # unf_res may have set 'Z'
8645 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
8646 rts
8647
8648#
8649# operand will underflow AND underflow or inexact is enabled.
8650# therefore, we must return the result rounded to extended precision.
8651#
8652fin_sd_unfl_ena:
8653 mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
8654 mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
8655 mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
8656
8657 mov.l %d2,-(%sp) # save d2
8658 mov.w %d1,%d2 # make a copy
8659 andi.l &0x7fff,%d1 # strip sign
8660 sub.l %d0,%d1 # subtract scale factor
8661 andi.w &0x8000,%d2 # extract old sign
8662 addi.l &0x6000,%d1 # add new bias
8663 andi.w &0x7fff,%d1
8664 or.w %d1,%d2 # concat old sign,new exp
8665 mov.w %d2,FP_SCR1_EX(%a6) # insert new exponent
8666 fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
8667 mov.l (%sp)+,%d2 # restore d2
8668 bra.b fin_sd_unfl_dis
8669
8670#
8671# operand WILL overflow.
8672#
8673fin_sd_ovfl:
8674 fmov.l &0x0,%fpsr # clear FPSR
8675 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8676
8677 fmov.x FP_SCR0(%a6),%fp0 # perform move
8678
8679 fmov.l &0x0,%fpcr # clear FPCR
8680 fmov.l %fpsr,%d1 # save FPSR
8681
8682 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8683
8684fin_sd_ovfl_tst:
8685 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
8686
8687 mov.b FPCR_ENABLE(%a6),%d1
8688 andi.b &0x13,%d1 # is OVFL or INEX enabled?
8689 bne.b fin_sd_ovfl_ena # yes
8690
8691#
8692# OVFL is not enabled; therefore, we must create the default result by
8693# calling ovf_res().
8694#
8695fin_sd_ovfl_dis:
8696 btst &neg_bit,FPSR_CC(%a6) # is result negative?
8697 sne %d1 # set sign param accordingly
8698 mov.l L_SCR3(%a6),%d0 # pass: prec,mode
8699 bsr.l ovf_res # calculate default result
8700 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
8701 fmovm.x (%a0),&0x80 # return default result in fp0
8702 rts
8703
8704#
8705# OVFL is enabled.
8706# the INEX2 bit has already been updated by the round to the correct precision.
8707# now, round to extended(and don't alter the FPSR).
8708#
8709fin_sd_ovfl_ena:
8710 mov.l %d2,-(%sp) # save d2
8711 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
8712 mov.l %d1,%d2 # make a copy
8713 andi.l &0x7fff,%d1 # strip sign
8714 andi.w &0x8000,%d2 # keep old sign
8715 sub.l %d0,%d1 # add scale factor
8716 sub.l &0x6000,%d1 # subtract bias
8717 andi.w &0x7fff,%d1
8718 or.w %d2,%d1
8719 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8720 mov.l (%sp)+,%d2 # restore d2
8721 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8722 bra.b fin_sd_ovfl_dis
8723
8724#
8725# the move in MAY overflow. so...
8726#
8727fin_sd_may_ovfl:
8728 fmov.l &0x0,%fpsr # clear FPSR
8729 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8730
8731 fmov.x FP_SCR0(%a6),%fp0 # perform the move
8732
8733 fmov.l %fpsr,%d1 # save status
8734 fmov.l &0x0,%fpcr # clear FPCR
8735
8736 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8737
8738 fabs.x %fp0,%fp1 # make a copy of result
8739 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
8740 fbge.w fin_sd_ovfl_tst # yes; overflow has occurred
8741
8742# no, it didn't overflow; we have correct result
8743 bra.w fin_sd_normal_exit
8744
8745##########################################################################
8746
8747#
8748# operand is not a NORM: check its optype and branch accordingly
8749#
8750fin_not_norm:
8751 cmpi.b %d1,&DENORM # weed out DENORM
8752 beq.w fin_denorm
8753 cmpi.b %d1,&SNAN # weed out SNANs
8754 beq.l res_snan_1op
8755 cmpi.b %d1,&QNAN # weed out QNANs
8756 beq.l res_qnan_1op
8757
8758#
8759# do the fmove in; at this point, only possible ops are ZERO and INF.
8760# use fmov to determine ccodes.
8761# prec:mode should be zero at this point but it won't affect answer anyways.
8762#
8763 fmov.x SRC(%a0),%fp0 # do fmove in
8764 fmov.l %fpsr,%d0 # no exceptions possible
8765 rol.l &0x8,%d0 # put ccodes in lo byte
8766 mov.b %d0,FPSR_CC(%a6) # insert correct ccodes
8767 rts
8768
8769#########################################################################
8770# XDEF **************************************************************** #
8771# fdiv(): emulates the fdiv instruction #
8772# fsdiv(): emulates the fsdiv instruction #
8773# fddiv(): emulates the fddiv instruction #
8774# #
8775# XREF **************************************************************** #
8776# scale_to_zero_src() - scale src exponent to zero #
8777# scale_to_zero_dst() - scale dst exponent to zero #
8778# unf_res() - return default underflow result #
8779# ovf_res() - return default overflow result #
8780# res_qnan() - return QNAN result #
8781# res_snan() - return SNAN result #
8782# #
8783# INPUT *************************************************************** #
8784# a0 = pointer to extended precision source operand #
8785# a1 = pointer to extended precision destination operand #
8786# d0 rnd prec,mode #
8787# #
8788# OUTPUT ************************************************************** #
8789# fp0 = result #
8790# fp1 = EXOP (if exception occurred) #
8791# #
8792# ALGORITHM *********************************************************** #
8793# Handle NANs, infinities, and zeroes as special cases. Divide #
8794# norms/denorms into ext/sgl/dbl precision. #
8795# For norms/denorms, scale the exponents such that a divide #
8796# instruction won't cause an exception. Use the regular fdiv to #
8797# compute a result. Check if the regular operands would have taken #
8798# an exception. If so, return the default overflow/underflow result #
8799# and return the EXOP if exceptions are enabled. Else, scale the #
8800# result operand to the proper exponent. #
8801# #
8802#########################################################################
8803
8804 align 0x10
8805tbl_fdiv_unfl:
8806 long 0x3fff - 0x0000 # ext_unfl
8807 long 0x3fff - 0x3f81 # sgl_unfl
8808 long 0x3fff - 0x3c01 # dbl_unfl
8809
8810tbl_fdiv_ovfl:
8811 long 0x3fff - 0x7ffe # ext overflow exponent
8812 long 0x3fff - 0x407e # sgl overflow exponent
8813 long 0x3fff - 0x43fe # dbl overflow exponent
8814
8815 global fsdiv
8816fsdiv:
8817 andi.b &0x30,%d0 # clear rnd prec
8818 ori.b &s_mode*0x10,%d0 # insert sgl prec
8819 bra.b fdiv
8820
8821 global fddiv
8822fddiv:
8823 andi.b &0x30,%d0 # clear rnd prec
8824 ori.b &d_mode*0x10,%d0 # insert dbl prec
8825
8826 global fdiv
8827fdiv:
8828 mov.l %d0,L_SCR3(%a6) # store rnd info
8829
8830 clr.w %d1
8831 mov.b DTAG(%a6),%d1
8832 lsl.b &0x3,%d1
8833 or.b STAG(%a6),%d1 # combine src tags
8834
8835 bne.w fdiv_not_norm # optimize on non-norm input
8836
8837#
8838# DIVIDE: NORMs and DENORMs ONLY!
8839#
8840fdiv_norm:
8841 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
8842 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
8843 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
8844
8845 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8846 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8847 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8848
8849 bsr.l scale_to_zero_src # scale src exponent
8850 mov.l %d0,-(%sp) # save scale factor 1
8851
8852 bsr.l scale_to_zero_dst # scale dst exponent
8853
8854 neg.l (%sp) # SCALE FACTOR = scale1 - scale2
8855 add.l %d0,(%sp)
8856
8857 mov.w 2+L_SCR3(%a6),%d1 # fetch precision
8858 lsr.b &0x6,%d1 # shift to lo bits
8859 mov.l (%sp)+,%d0 # load S.F.
8860 cmp.l %d0,(tbl_fdiv_ovfl.b,%pc,%d1.w*4) # will result overflow?
8861 ble.w fdiv_may_ovfl # result will overflow
8862
8863 cmp.l %d0,(tbl_fdiv_unfl.w,%pc,%d1.w*4) # will result underflow?
8864 beq.w fdiv_may_unfl # maybe
8865 bgt.w fdiv_unfl # yes; go handle underflow
8866
8867fdiv_normal:
8868 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
8869
8870 fmov.l L_SCR3(%a6),%fpcr # save FPCR
8871 fmov.l &0x0,%fpsr # clear FPSR
8872
8873 fdiv.x FP_SCR0(%a6),%fp0 # perform divide
8874
8875 fmov.l %fpsr,%d1 # save FPSR
8876 fmov.l &0x0,%fpcr # clear FPCR
8877
8878 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8879
8880fdiv_normal_exit:
8881 fmovm.x &0x80,FP_SCR0(%a6) # store result on stack
8882 mov.l %d2,-(%sp) # store d2
8883 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
8884 mov.l %d1,%d2 # make a copy
8885 andi.l &0x7fff,%d1 # strip sign
8886 andi.w &0x8000,%d2 # keep old sign
8887 sub.l %d0,%d1 # add scale factor
8888 or.w %d2,%d1 # concat old sign,new exp
8889 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8890 mov.l (%sp)+,%d2 # restore d2
8891 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
8892 rts
8893
8894tbl_fdiv_ovfl2:
8895 long 0x7fff
8896 long 0x407f
8897 long 0x43ff
8898
8899fdiv_no_ovfl:
8900 mov.l (%sp)+,%d0 # restore scale factor
8901 bra.b fdiv_normal_exit
8902
8903fdiv_may_ovfl:
8904 mov.l %d0,-(%sp) # save scale factor
8905
8906 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
8907
8908 fmov.l L_SCR3(%a6),%fpcr # set FPCR
8909 fmov.l &0x0,%fpsr # set FPSR
8910
8911 fdiv.x FP_SCR0(%a6),%fp0 # execute divide
8912
8913 fmov.l %fpsr,%d0
8914 fmov.l &0x0,%fpcr
8915
8916 or.l %d0,USER_FPSR(%a6) # save INEX,N
8917
8918 fmovm.x &0x01,-(%sp) # save result to stack
8919 mov.w (%sp),%d0 # fetch new exponent
8920 add.l &0xc,%sp # clear result from stack
8921 andi.l &0x7fff,%d0 # strip sign
8922 sub.l (%sp),%d0 # add scale factor
8923 cmp.l %d0,(tbl_fdiv_ovfl2.b,%pc,%d1.w*4)
8924 blt.b fdiv_no_ovfl
8925 mov.l (%sp)+,%d0
8926
8927fdiv_ovfl_tst:
8928 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
8929
8930 mov.b FPCR_ENABLE(%a6),%d1
8931 andi.b &0x13,%d1 # is OVFL or INEX enabled?
8932 bne.b fdiv_ovfl_ena # yes
8933
8934fdiv_ovfl_dis:
8935 btst &neg_bit,FPSR_CC(%a6) # is result negative?
8936 sne %d1 # set sign param accordingly
8937 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
8938 bsr.l ovf_res # calculate default result
8939 or.b %d0,FPSR_CC(%a6) # set INF if applicable
8940 fmovm.x (%a0),&0x80 # return default result in fp0
8941 rts
8942
8943fdiv_ovfl_ena:
8944 mov.l L_SCR3(%a6),%d1
8945 andi.b &0xc0,%d1 # is precision extended?
8946 bne.b fdiv_ovfl_ena_sd # no, do sgl or dbl
8947
8948fdiv_ovfl_ena_cont:
8949 fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
8950
8951 mov.l %d2,-(%sp) # save d2
8952 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
8953 mov.w %d1,%d2 # make a copy
8954 andi.l &0x7fff,%d1 # strip sign
8955 sub.l %d0,%d1 # add scale factor
8956 subi.l &0x6000,%d1 # subtract bias
8957 andi.w &0x7fff,%d1 # clear sign bit
8958 andi.w &0x8000,%d2 # keep old sign
8959 or.w %d2,%d1 # concat old sign,new exp
8960 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8961 mov.l (%sp)+,%d2 # restore d2
8962 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8963 bra.b fdiv_ovfl_dis
8964
8965fdiv_ovfl_ena_sd:
8966 fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8967
8968 mov.l L_SCR3(%a6),%d1
8969 andi.b &0x30,%d1 # keep rnd mode
8970 fmov.l %d1,%fpcr # set FPCR
8971
8972 fdiv.x FP_SCR0(%a6),%fp0 # execute divide
8973
8974 fmov.l &0x0,%fpcr # clear FPCR
8975 bra.b fdiv_ovfl_ena_cont
8976
8977fdiv_unfl:
8978 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
8979
8980 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
8981
8982 fmov.l &rz_mode*0x10,%fpcr # set FPCR
8983 fmov.l &0x0,%fpsr # clear FPSR
8984
8985 fdiv.x FP_SCR0(%a6),%fp0 # execute divide
8986
8987 fmov.l %fpsr,%d1 # save status
8988 fmov.l &0x0,%fpcr # clear FPCR
8989
8990 or.l %d1,USER_FPSR(%a6) # save INEX2,N
8991
8992 mov.b FPCR_ENABLE(%a6),%d1
8993 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
8994 bne.b fdiv_unfl_ena # yes
8995
8996fdiv_unfl_dis:
8997 fmovm.x &0x80,FP_SCR0(%a6) # store out result
8998
8999 lea FP_SCR0(%a6),%a0 # pass: result addr
9000 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
9001 bsr.l unf_res # calculate default result
9002 or.b %d0,FPSR_CC(%a6) # 'Z' may have been set
9003 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
9004 rts
9005
9006#
9007# UNFL is enabled.
9008#
9009fdiv_unfl_ena:
9010 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
9011
9012 mov.l L_SCR3(%a6),%d1
9013 andi.b &0xc0,%d1 # is precision extended?
9014 bne.b fdiv_unfl_ena_sd # no, sgl or dbl
9015
9016 fmov.l L_SCR3(%a6),%fpcr # set FPCR
9017
9018fdiv_unfl_ena_cont:
9019 fmov.l &0x0,%fpsr # clear FPSR
9020
9021 fdiv.x FP_SCR0(%a6),%fp1 # execute divide
9022
9023 fmov.l &0x0,%fpcr # clear FPCR
9024
9025 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
9026 mov.l %d2,-(%sp) # save d2
9027 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
9028 mov.l %d1,%d2 # make a copy
9029 andi.l &0x7fff,%d1 # strip sign
9030 andi.w &0x8000,%d2 # keep old sign
9031 sub.l %d0,%d1 # add scale factoer
9032 addi.l &0x6000,%d1 # add bias
9033 andi.w &0x7fff,%d1
9034 or.w %d2,%d1 # concat old sign,new exp
9035 mov.w %d1,FP_SCR0_EX(%a6) # insert new exp
9036 mov.l (%sp)+,%d2 # restore d2
9037 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
9038 bra.w fdiv_unfl_dis
9039
9040fdiv_unfl_ena_sd:
9041 mov.l L_SCR3(%a6),%d1
9042 andi.b &0x30,%d1 # use only rnd mode
9043 fmov.l %d1,%fpcr # set FPCR
9044
9045 bra.b fdiv_unfl_ena_cont
9046
9047#
9048# the divide operation MAY underflow:
9049#
9050fdiv_may_unfl:
9051 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
9052
9053 fmov.l L_SCR3(%a6),%fpcr # set FPCR
9054 fmov.l &0x0,%fpsr # clear FPSR
9055
9056 fdiv.x FP_SCR0(%a6),%fp0 # execute divide
9057
9058 fmov.l %fpsr,%d1 # save status
9059 fmov.l &0x0,%fpcr # clear FPCR
9060
9061 or.l %d1,USER_FPSR(%a6) # save INEX2,N
9062
9063 fabs.x %fp0,%fp1 # make a copy of result
9064 fcmp.b %fp1,&0x1 # is |result| > 1.b?
9065 fbgt.w fdiv_normal_exit # no; no underflow occurred
9066 fblt.w fdiv_unfl # yes; underflow occurred
9067
9068#
9069# we still don't know if underflow occurred. result is ~ equal to 1. but,
9070# we don't know if the result was an underflow that rounded up to a 1
9071# or a normalized number that rounded down to a 1. so, redo the entire
9072# operation using RZ as the rounding mode to see what the pre-rounded
9073# result is. this case should be relatively rare.
9074#
9075 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
9076
9077 mov.l L_SCR3(%a6),%d1
9078 andi.b &0xc0,%d1 # keep rnd prec
9079 ori.b &rz_mode*0x10,%d1 # insert RZ
9080
9081 fmov.l %d1,%fpcr # set FPCR
9082 fmov.l &0x0,%fpsr # clear FPSR
9083
9084 fdiv.x FP_SCR0(%a6),%fp1 # execute divide
9085
9086 fmov.l &0x0,%fpcr # clear FPCR
9087 fabs.x %fp1 # make absolute value
9088 fcmp.b %fp1,&0x1 # is |result| < 1.b?
9089 fbge.w fdiv_normal_exit # no; no underflow occurred
9090 bra.w fdiv_unfl # yes; underflow occurred
9091
9092############################################################################
9093
9094#
9095# Divide: inputs are not both normalized; what are they?
9096#
9097fdiv_not_norm:
9098 mov.w (tbl_fdiv_op.b,%pc,%d1.w*2),%d1
9099 jmp (tbl_fdiv_op.b,%pc,%d1.w*1)
9100
9101 swbeg &48
9102tbl_fdiv_op:
9103 short fdiv_norm - tbl_fdiv_op # NORM / NORM
9104 short fdiv_inf_load - tbl_fdiv_op # NORM / ZERO
9105 short fdiv_zero_load - tbl_fdiv_op # NORM / INF
9106 short fdiv_res_qnan - tbl_fdiv_op # NORM / QNAN
9107 short fdiv_norm - tbl_fdiv_op # NORM / DENORM
9108 short fdiv_res_snan - tbl_fdiv_op # NORM / SNAN
9109 short tbl_fdiv_op - tbl_fdiv_op #
9110 short tbl_fdiv_op - tbl_fdiv_op #
9111
9112 short fdiv_zero_load - tbl_fdiv_op # ZERO / NORM
9113 short fdiv_res_operr - tbl_fdiv_op # ZERO / ZERO
9114 short fdiv_zero_load - tbl_fdiv_op # ZERO / INF
9115 short fdiv_res_qnan - tbl_fdiv_op # ZERO / QNAN
9116 short fdiv_zero_load - tbl_fdiv_op # ZERO / DENORM
9117 short fdiv_res_snan - tbl_fdiv_op # ZERO / SNAN
9118 short tbl_fdiv_op - tbl_fdiv_op #
9119 short tbl_fdiv_op - tbl_fdiv_op #
9120
9121 short fdiv_inf_dst - tbl_fdiv_op # INF / NORM
9122 short fdiv_inf_dst - tbl_fdiv_op # INF / ZERO
9123 short fdiv_res_operr - tbl_fdiv_op # INF / INF
9124 short fdiv_res_qnan - tbl_fdiv_op # INF / QNAN
9125 short fdiv_inf_dst - tbl_fdiv_op # INF / DENORM
9126 short fdiv_res_snan - tbl_fdiv_op # INF / SNAN
9127 short tbl_fdiv_op - tbl_fdiv_op #
9128 short tbl_fdiv_op - tbl_fdiv_op #
9129
9130 short fdiv_res_qnan - tbl_fdiv_op # QNAN / NORM
9131 short fdiv_res_qnan - tbl_fdiv_op # QNAN / ZERO
9132 short fdiv_res_qnan - tbl_fdiv_op # QNAN / INF
9133 short fdiv_res_qnan - tbl_fdiv_op # QNAN / QNAN
9134 short fdiv_res_qnan - tbl_fdiv_op # QNAN / DENORM
9135 short fdiv_res_snan - tbl_fdiv_op # QNAN / SNAN
9136 short tbl_fdiv_op - tbl_fdiv_op #
9137 short tbl_fdiv_op - tbl_fdiv_op #
9138
9139 short fdiv_norm - tbl_fdiv_op # DENORM / NORM
9140 short fdiv_inf_load - tbl_fdiv_op # DENORM / ZERO
9141 short fdiv_zero_load - tbl_fdiv_op # DENORM / INF
9142 short fdiv_res_qnan - tbl_fdiv_op # DENORM / QNAN
9143 short fdiv_norm - tbl_fdiv_op # DENORM / DENORM
9144 short fdiv_res_snan - tbl_fdiv_op # DENORM / SNAN
9145 short tbl_fdiv_op - tbl_fdiv_op #
9146 short tbl_fdiv_op - tbl_fdiv_op #
9147
9148 short fdiv_res_snan - tbl_fdiv_op # SNAN / NORM
9149 short fdiv_res_snan - tbl_fdiv_op # SNAN / ZERO
9150 short fdiv_res_snan - tbl_fdiv_op # SNAN / INF
9151 short fdiv_res_snan - tbl_fdiv_op # SNAN / QNAN
9152 short fdiv_res_snan - tbl_fdiv_op # SNAN / DENORM
9153 short fdiv_res_snan - tbl_fdiv_op # SNAN / SNAN
9154 short tbl_fdiv_op - tbl_fdiv_op #
9155 short tbl_fdiv_op - tbl_fdiv_op #
9156
9157fdiv_res_qnan:
9158 bra.l res_qnan
9159fdiv_res_snan:
9160 bra.l res_snan
9161fdiv_res_operr:
9162 bra.l res_operr
9163
9164 global fdiv_zero_load # global for fsgldiv
9165fdiv_zero_load:
9166 mov.b SRC_EX(%a0),%d0 # result sign is exclusive
9167 mov.b DST_EX(%a1),%d1 # or of input signs.
9168 eor.b %d0,%d1
9169 bpl.b fdiv_zero_load_p # result is positive
9170 fmov.s &0x80000000,%fp0 # load a -ZERO
9171 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
9172 rts
9173fdiv_zero_load_p:
9174 fmov.s &0x00000000,%fp0 # load a +ZERO
9175 mov.b &z_bmask,FPSR_CC(%a6) # set Z
9176 rts
9177
9178#
9179# The destination was In Range and the source was a ZERO. The result,
9180# therefore, is an INF w/ the proper sign.
9181# So, determine the sign and return a new INF (w/ the j-bit cleared).
9182#
9183 global fdiv_inf_load # global for fsgldiv
9184fdiv_inf_load:
9185 ori.w &dz_mask+adz_mask,2+USER_FPSR(%a6) # no; set DZ/ADZ
9186 mov.b SRC_EX(%a0),%d0 # load both signs
9187 mov.b DST_EX(%a1),%d1
9188 eor.b %d0,%d1
9189 bpl.b fdiv_inf_load_p # result is positive
9190 fmov.s &0xff800000,%fp0 # make result -INF
9191 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
9192 rts
9193fdiv_inf_load_p:
9194 fmov.s &0x7f800000,%fp0 # make result +INF
9195 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
9196 rts
9197
9198#
9199# The destination was an INF w/ an In Range or ZERO source, the result is
9200# an INF w/ the proper sign.
9201# The 68881/882 returns the destination INF w/ the new sign(if the j-bit of the
9202# dst INF is set, then then j-bit of the result INF is also set).
9203#
9204 global fdiv_inf_dst # global for fsgldiv
9205fdiv_inf_dst:
9206 mov.b DST_EX(%a1),%d0 # load both signs
9207 mov.b SRC_EX(%a0),%d1
9208 eor.b %d0,%d1
9209 bpl.b fdiv_inf_dst_p # result is positive
9210
9211 fmovm.x DST(%a1),&0x80 # return result in fp0
9212 fabs.x %fp0 # clear sign bit
9213 fneg.x %fp0 # set sign bit
9214 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/NEG
9215 rts
9216
9217fdiv_inf_dst_p:
9218 fmovm.x DST(%a1),&0x80 # return result in fp0
9219 fabs.x %fp0 # return positive INF
9220 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
9221 rts
9222
9223#########################################################################
9224# XDEF **************************************************************** #
9225# fneg(): emulates the fneg instruction #
9226# fsneg(): emulates the fsneg instruction #
9227# fdneg(): emulates the fdneg instruction #
9228# #
9229# XREF **************************************************************** #
9230# norm() - normalize a denorm to provide EXOP #
9231# scale_to_zero_src() - scale sgl/dbl source exponent #
9232# ovf_res() - return default overflow result #
9233# unf_res() - return default underflow result #
9234# res_qnan_1op() - return QNAN result #
9235# res_snan_1op() - return SNAN result #
9236# #
9237# INPUT *************************************************************** #
9238# a0 = pointer to extended precision source operand #
9239# d0 = rnd prec,mode #
9240# #
9241# OUTPUT ************************************************************** #
9242# fp0 = result #
9243# fp1 = EXOP (if exception occurred) #
9244# #
9245# ALGORITHM *********************************************************** #
9246# Handle NANs, zeroes, and infinities as special cases. Separate #
9247# norms/denorms into ext/sgl/dbl precisions. Extended precision can be #
9248# emulated by simply setting sign bit. Sgl/dbl operands must be scaled #
9249# and an actual fneg performed to see if overflow/underflow would have #
9250# occurred. If so, return default underflow/overflow result. Else, #
9251# scale the result exponent and return result. FPSR gets set based on #
9252# the result value. #
9253# #
9254#########################################################################
9255
9256 global fsneg
9257fsneg:
9258 andi.b &0x30,%d0 # clear rnd prec
9259 ori.b &s_mode*0x10,%d0 # insert sgl precision
9260 bra.b fneg
9261
9262 global fdneg
9263fdneg:
9264 andi.b &0x30,%d0 # clear rnd prec
9265 ori.b &d_mode*0x10,%d0 # insert dbl prec
9266
9267 global fneg
9268fneg:
9269 mov.l %d0,L_SCR3(%a6) # store rnd info
9270 mov.b STAG(%a6),%d1
9271 bne.w fneg_not_norm # optimize on non-norm input
9272
9273#
9274# NEGATE SIGN : norms and denorms ONLY!
9275#
9276fneg_norm:
9277 andi.b &0xc0,%d0 # is precision extended?
9278 bne.w fneg_not_ext # no; go handle sgl or dbl
9279
9280#
9281# precision selected is extended. so...we can not get an underflow
9282# or overflow because of rounding to the correct precision. so...
9283# skip the scaling and unscaling...
9284#
9285 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9286 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9287 mov.w SRC_EX(%a0),%d0
9288 eori.w &0x8000,%d0 # negate sign
9289 bpl.b fneg_norm_load # sign is positive
9290 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
9291fneg_norm_load:
9292 mov.w %d0,FP_SCR0_EX(%a6)
9293 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
9294 rts
9295
9296#
9297# for an extended precision DENORM, the UNFL exception bit is set
9298# the accrued bit is NOT set in this instance(no inexactness!)
9299#
9300fneg_denorm:
9301 andi.b &0xc0,%d0 # is precision extended?
9302 bne.b fneg_not_ext # no; go handle sgl or dbl
9303
9304 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
9305
9306 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9307 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9308 mov.w SRC_EX(%a0),%d0
9309 eori.w &0x8000,%d0 # negate sign
9310 bpl.b fneg_denorm_done # no
9311 mov.b &neg_bmask,FPSR_CC(%a6) # yes, set 'N' ccode bit
9312fneg_denorm_done:
9313 mov.w %d0,FP_SCR0_EX(%a6)
9314 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
9315
9316 btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
9317 bne.b fneg_ext_unfl_ena # yes
9318 rts
9319
9320#
9321# the input is an extended DENORM and underflow is enabled in the FPCR.
9322# normalize the mantissa and add the bias of 0x6000 to the resulting negative
9323# exponent and insert back into the operand.
9324#
9325fneg_ext_unfl_ena:
9326 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
9327 bsr.l norm # normalize result
9328 neg.w %d0 # new exponent = -(shft val)
9329 addi.w &0x6000,%d0 # add new bias to exponent
9330 mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
9331 andi.w &0x8000,%d1 # keep old sign
9332 andi.w &0x7fff,%d0 # clear sign position
9333 or.w %d1,%d0 # concat old sign, new exponent
9334 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
9335 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
9336 rts
9337
9338#
9339# operand is either single or double
9340#
9341fneg_not_ext:
9342 cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
9343 bne.b fneg_dbl
9344
9345#
9346# operand is to be rounded to single precision
9347#
9348fneg_sgl:
9349 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
9350 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9351 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9352 bsr.l scale_to_zero_src # calculate scale factor
9353
9354 cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
9355 bge.w fneg_sd_unfl # yes; go handle underflow
9356 cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
9357 beq.w fneg_sd_may_ovfl # maybe; go check
9358 blt.w fneg_sd_ovfl # yes; go handle overflow
9359
9360#
9361# operand will NOT overflow or underflow when moved in to the fp reg file
9362#
9363fneg_sd_normal:
9364 fmov.l &0x0,%fpsr # clear FPSR
9365 fmov.l L_SCR3(%a6),%fpcr # set FPCR
9366
9367 fneg.x FP_SCR0(%a6),%fp0 # perform negation
9368
9369 fmov.l %fpsr,%d1 # save FPSR
9370 fmov.l &0x0,%fpcr # clear FPCR
9371
9372 or.l %d1,USER_FPSR(%a6) # save INEX2,N
9373
9374fneg_sd_normal_exit:
9375 mov.l %d2,-(%sp) # save d2
9376 fmovm.x &0x80,FP_SCR0(%a6) # store out result
9377 mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
9378 mov.w %d1,%d2 # make a copy
9379 andi.l &0x7fff,%d1 # strip sign
9380 sub.l %d0,%d1 # add scale factor
9381 andi.w &0x8000,%d2 # keep old sign
9382 or.w %d1,%d2 # concat old sign,new exp
9383 mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
9384 mov.l (%sp)+,%d2 # restore d2
9385 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
9386 rts
9387
9388#
9389# operand is to be rounded to double precision
9390#
9391fneg_dbl:
9392 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
9393 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9394 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9395 bsr.l scale_to_zero_src # calculate scale factor
9396
9397 cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
9398 bge.b fneg_sd_unfl # yes; go handle underflow
9399 cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
9400 beq.w fneg_sd_may_ovfl # maybe; go check
9401 blt.w fneg_sd_ovfl # yes; go handle overflow
9402 bra.w fneg_sd_normal # no; ho handle normalized op
9403
9404#
9405# operand WILL underflow when moved in to the fp register file
9406#
9407fneg_sd_unfl:
9408 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
9409
9410 eori.b &0x80,FP_SCR0_EX(%a6) # negate sign
9411 bpl.b fneg_sd_unfl_tst
9412 bset &neg_bit,FPSR_CC(%a6) # set 'N' ccode bit
9413
9414# if underflow or inexact is enabled, go calculate EXOP first.
9415fneg_sd_unfl_tst:
9416 mov.b FPCR_ENABLE(%a6),%d1
9417 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
9418 bne.b fneg_sd_unfl_ena # yes
9419
9420fneg_sd_unfl_dis:
9421 lea FP_SCR0(%a6),%a0 # pass: result addr
9422 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
9423 bsr.l unf_res # calculate default result
9424 or.b %d0,FPSR_CC(%a6) # unf_res may have set 'Z'
9425 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
9426 rts
9427
9428#
9429# operand will underflow AND underflow is enabled.
9430# therefore, we must return the result rounded to extended precision.
9431#
9432fneg_sd_unfl_ena:
9433 mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
9434 mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
9435 mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
9436
9437 mov.l %d2,-(%sp) # save d2
9438 mov.l %d1,%d2 # make a copy
9439 andi.l &0x7fff,%d1 # strip sign
9440 andi.w &0x8000,%d2 # keep old sign
9441 sub.l %d0,%d1 # subtract scale factor
9442 addi.l &0x6000,%d1 # add new bias
9443 andi.w &0x7fff,%d1
9444 or.w %d2,%d1 # concat new sign,new exp
9445 mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
9446 fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
9447 mov.l (%sp)+,%d2 # restore d2
9448 bra.b fneg_sd_unfl_dis
9449
9450#
9451# operand WILL overflow.
9452#
9453fneg_sd_ovfl:
9454 fmov.l &0x0,%fpsr # clear FPSR
9455 fmov.l L_SCR3(%a6),%fpcr # set FPCR
9456
9457 fneg.x FP_SCR0(%a6),%fp0 # perform negation
9458
9459 fmov.l &0x0,%fpcr # clear FPCR
9460 fmov.l %fpsr,%d1 # save FPSR
9461
9462 or.l %d1,USER_FPSR(%a6) # save INEX2,N
9463
9464fneg_sd_ovfl_tst:
9465 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
9466
9467 mov.b FPCR_ENABLE(%a6),%d1
9468 andi.b &0x13,%d1 # is OVFL or INEX enabled?
9469 bne.b fneg_sd_ovfl_ena # yes
9470
9471#
9472# OVFL is not enabled; therefore, we must create the default result by
9473# calling ovf_res().
9474#
9475fneg_sd_ovfl_dis:
9476 btst &neg_bit,FPSR_CC(%a6) # is result negative?
9477 sne %d1 # set sign param accordingly
9478 mov.l L_SCR3(%a6),%d0 # pass: prec,mode
9479 bsr.l ovf_res # calculate default result
9480 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
9481 fmovm.x (%a0),&0x80 # return default result in fp0
9482 rts
9483
9484#
9485# OVFL is enabled.
9486# the INEX2 bit has already been updated by the round to the correct precision.
9487# now, round to extended(and don't alter the FPSR).
9488#
9489fneg_sd_ovfl_ena:
9490 mov.l %d2,-(%sp) # save d2
9491 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
9492 mov.l %d1,%d2 # make a copy
9493 andi.l &0x7fff,%d1 # strip sign
9494 andi.w &0x8000,%d2 # keep old sign
9495 sub.l %d0,%d1 # add scale factor
9496 subi.l &0x6000,%d1 # subtract bias
9497 andi.w &0x7fff,%d1
9498 or.w %d2,%d1 # concat sign,exp
9499 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
9500 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
9501 mov.l (%sp)+,%d2 # restore d2
9502 bra.b fneg_sd_ovfl_dis
9503
9504#
9505# the move in MAY underflow. so...
9506#
9507fneg_sd_may_ovfl:
9508 fmov.l &0x0,%fpsr # clear FPSR
9509 fmov.l L_SCR3(%a6),%fpcr # set FPCR
9510
9511 fneg.x FP_SCR0(%a6),%fp0 # perform negation
9512
9513 fmov.l %fpsr,%d1 # save status
9514 fmov.l &0x0,%fpcr # clear FPCR
9515
9516 or.l %d1,USER_FPSR(%a6) # save INEX2,N
9517
9518 fabs.x %fp0,%fp1 # make a copy of result
9519 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
9520 fbge.w fneg_sd_ovfl_tst # yes; overflow has occurred
9521
9522# no, it didn't overflow; we have correct result
9523 bra.w fneg_sd_normal_exit
9524
9525##########################################################################
9526
9527#
9528# input is not normalized; what is it?
9529#
9530fneg_not_norm:
9531 cmpi.b %d1,&DENORM # weed out DENORM
9532 beq.w fneg_denorm
9533 cmpi.b %d1,&SNAN # weed out SNAN
9534 beq.l res_snan_1op
9535 cmpi.b %d1,&QNAN # weed out QNAN
9536 beq.l res_qnan_1op
9537
9538#
9539# do the fneg; at this point, only possible ops are ZERO and INF.
9540# use fneg to determine ccodes.
9541# prec:mode should be zero at this point but it won't affect answer anyways.
9542#
9543 fneg.x SRC_EX(%a0),%fp0 # do fneg
9544 fmov.l %fpsr,%d0
9545 rol.l &0x8,%d0 # put ccodes in lo byte
9546 mov.b %d0,FPSR_CC(%a6) # insert correct ccodes
9547 rts
9548
9549#########################################################################
9550# XDEF **************************************************************** #
9551# ftst(): emulates the ftest instruction #
9552# #
9553# XREF **************************************************************** #
9554# res{s,q}nan_1op() - set NAN result for monadic instruction #
9555# #
9556# INPUT *************************************************************** #
9557# a0 = pointer to extended precision source operand #
9558# #
9559# OUTPUT ************************************************************** #
9560# none #
9561# #
9562# ALGORITHM *********************************************************** #
9563# Check the source operand tag (STAG) and set the FPCR according #
9564# to the operand type and sign. #
9565# #
9566#########################################################################
9567
9568 global ftst
9569ftst:
9570 mov.b STAG(%a6),%d1
9571 bne.b ftst_not_norm # optimize on non-norm input
9572
9573#
9574# Norm:
9575#
9576ftst_norm:
9577 tst.b SRC_EX(%a0) # is operand negative?
9578 bmi.b ftst_norm_m # yes
9579 rts
9580ftst_norm_m:
9581 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
9582 rts
9583
9584#
9585# input is not normalized; what is it?
9586#
9587ftst_not_norm:
9588 cmpi.b %d1,&ZERO # weed out ZERO
9589 beq.b ftst_zero
9590 cmpi.b %d1,&INF # weed out INF
9591 beq.b ftst_inf
9592 cmpi.b %d1,&SNAN # weed out SNAN
9593 beq.l res_snan_1op
9594 cmpi.b %d1,&QNAN # weed out QNAN
9595 beq.l res_qnan_1op
9596
9597#
9598# Denorm:
9599#
9600ftst_denorm:
9601 tst.b SRC_EX(%a0) # is operand negative?
9602 bmi.b ftst_denorm_m # yes
9603 rts
9604ftst_denorm_m:
9605 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
9606 rts
9607
9608#
9609# Infinity:
9610#
9611ftst_inf:
9612 tst.b SRC_EX(%a0) # is operand negative?
9613 bmi.b ftst_inf_m # yes
9614ftst_inf_p:
9615 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
9616 rts
9617ftst_inf_m:
9618 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'I','N' ccode bits
9619 rts
9620
9621#
9622# Zero:
9623#
9624ftst_zero:
9625 tst.b SRC_EX(%a0) # is operand negative?
9626 bmi.b ftst_zero_m # yes
9627ftst_zero_p:
9628 mov.b &z_bmask,FPSR_CC(%a6) # set 'N' ccode bit
9629 rts
9630ftst_zero_m:
9631 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
9632 rts
9633
9634#########################################################################
9635# XDEF **************************************************************** #
9636# fint(): emulates the fint instruction #
9637# #
9638# XREF **************************************************************** #
9639# res_{s,q}nan_1op() - set NAN result for monadic operation #
9640# #
9641# INPUT *************************************************************** #
9642# a0 = pointer to extended precision source operand #
9643# d0 = round precision/mode #
9644# #
9645# OUTPUT ************************************************************** #
9646# fp0 = result #
9647# #
9648# ALGORITHM *********************************************************** #
9649# Separate according to operand type. Unnorms don't pass through #
9650# here. For norms, load the rounding mode/prec, execute a "fint", then #
9651# store the resulting FPSR bits. #
9652# For denorms, force the j-bit to a one and do the same as for #
9653# norms. Denorms are so low that the answer will either be a zero or a #
9654# one. #
9655# For zeroes/infs/NANs, return the same while setting the FPSR #
9656# as appropriate. #
9657# #
9658#########################################################################
9659
9660 global fint
9661fint:
9662 mov.b STAG(%a6),%d1
9663 bne.b fint_not_norm # optimize on non-norm input
9664
9665#
9666# Norm:
9667#
9668fint_norm:
9669 andi.b &0x30,%d0 # set prec = ext
9670
9671 fmov.l %d0,%fpcr # set FPCR
9672 fmov.l &0x0,%fpsr # clear FPSR
9673
9674 fint.x SRC(%a0),%fp0 # execute fint
9675
9676 fmov.l &0x0,%fpcr # clear FPCR
9677 fmov.l %fpsr,%d0 # save FPSR
9678 or.l %d0,USER_FPSR(%a6) # set exception bits
9679
9680 rts
9681
9682#
9683# input is not normalized; what is it?
9684#
9685fint_not_norm:
9686 cmpi.b %d1,&ZERO # weed out ZERO
9687 beq.b fint_zero
9688 cmpi.b %d1,&INF # weed out INF
9689 beq.b fint_inf
9690 cmpi.b %d1,&DENORM # weed out DENORM
9691 beq.b fint_denorm
9692 cmpi.b %d1,&SNAN # weed out SNAN
9693 beq.l res_snan_1op
9694 bra.l res_qnan_1op # weed out QNAN
9695
9696#
9697# Denorm:
9698#
9699# for DENORMs, the result will be either (+/-)ZERO or (+/-)1.
9700# also, the INEX2 and AINEX exception bits will be set.
9701# so, we could either set these manually or force the DENORM
9702# to a very small NORM and ship it to the NORM routine.
9703# I do the latter.
9704#
9705fint_denorm:
9706 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
9707 mov.b &0x80,FP_SCR0_HI(%a6) # force DENORM ==> small NORM
9708 lea FP_SCR0(%a6),%a0
9709 bra.b fint_norm
9710
9711#
9712# Zero:
9713#
9714fint_zero:
9715 tst.b SRC_EX(%a0) # is ZERO negative?
9716 bmi.b fint_zero_m # yes
9717fint_zero_p:
9718 fmov.s &0x00000000,%fp0 # return +ZERO in fp0
9719 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
9720 rts
9721fint_zero_m:
9722 fmov.s &0x80000000,%fp0 # return -ZERO in fp0
9723 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
9724 rts
9725
9726#
9727# Infinity:
9728#
9729fint_inf:
9730 fmovm.x SRC(%a0),&0x80 # return result in fp0
9731 tst.b SRC_EX(%a0) # is INF negative?
9732 bmi.b fint_inf_m # yes
9733fint_inf_p:
9734 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
9735 rts
9736fint_inf_m:
9737 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
9738 rts
9739
9740#########################################################################
9741# XDEF **************************************************************** #
9742# fintrz(): emulates the fintrz instruction #
9743# #
9744# XREF **************************************************************** #
9745# res_{s,q}nan_1op() - set NAN result for monadic operation #
9746# #
9747# INPUT *************************************************************** #
9748# a0 = pointer to extended precision source operand #
9749# d0 = round precision/mode #
9750# #
9751# OUTPUT ************************************************************** #
9752# fp0 = result #
9753# #
9754# ALGORITHM *********************************************************** #
9755# Separate according to operand type. Unnorms don't pass through #
9756# here. For norms, load the rounding mode/prec, execute a "fintrz", #
9757# then store the resulting FPSR bits. #
9758# For denorms, force the j-bit to a one and do the same as for #
9759# norms. Denorms are so low that the answer will either be a zero or a #
9760# one. #
9761# For zeroes/infs/NANs, return the same while setting the FPSR #
9762# as appropriate. #
9763# #
9764#########################################################################
9765
9766 global fintrz
9767fintrz:
9768 mov.b STAG(%a6),%d1
9769 bne.b fintrz_not_norm # optimize on non-norm input
9770
9771#
9772# Norm:
9773#
9774fintrz_norm:
9775 fmov.l &0x0,%fpsr # clear FPSR
9776
9777 fintrz.x SRC(%a0),%fp0 # execute fintrz
9778
9779 fmov.l %fpsr,%d0 # save FPSR
9780 or.l %d0,USER_FPSR(%a6) # set exception bits
9781
9782 rts
9783
9784#
9785# input is not normalized; what is it?
9786#
9787fintrz_not_norm:
9788 cmpi.b %d1,&ZERO # weed out ZERO
9789 beq.b fintrz_zero
9790 cmpi.b %d1,&INF # weed out INF
9791 beq.b fintrz_inf
9792 cmpi.b %d1,&DENORM # weed out DENORM
9793 beq.b fintrz_denorm
9794 cmpi.b %d1,&SNAN # weed out SNAN
9795 beq.l res_snan_1op
9796 bra.l res_qnan_1op # weed out QNAN
9797
9798#
9799# Denorm:
9800#
9801# for DENORMs, the result will be (+/-)ZERO.
9802# also, the INEX2 and AINEX exception bits will be set.
9803# so, we could either set these manually or force the DENORM
9804# to a very small NORM and ship it to the NORM routine.
9805# I do the latter.
9806#
9807fintrz_denorm:
9808 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
9809 mov.b &0x80,FP_SCR0_HI(%a6) # force DENORM ==> small NORM
9810 lea FP_SCR0(%a6),%a0
9811 bra.b fintrz_norm
9812
9813#
9814# Zero:
9815#
9816fintrz_zero:
9817 tst.b SRC_EX(%a0) # is ZERO negative?
9818 bmi.b fintrz_zero_m # yes
9819fintrz_zero_p:
9820 fmov.s &0x00000000,%fp0 # return +ZERO in fp0
9821 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
9822 rts
9823fintrz_zero_m:
9824 fmov.s &0x80000000,%fp0 # return -ZERO in fp0
9825 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
9826 rts
9827
9828#
9829# Infinity:
9830#
9831fintrz_inf:
9832 fmovm.x SRC(%a0),&0x80 # return result in fp0
9833 tst.b SRC_EX(%a0) # is INF negative?
9834 bmi.b fintrz_inf_m # yes
9835fintrz_inf_p:
9836 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
9837 rts
9838fintrz_inf_m:
9839 mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
9840 rts
9841
9842#########################################################################
9843# XDEF **************************************************************** #
9844# fabs(): emulates the fabs instruction #
9845# fsabs(): emulates the fsabs instruction #
9846# fdabs(): emulates the fdabs instruction #
9847# #
9848# XREF **************************************************************** #
9849# norm() - normalize denorm mantissa to provide EXOP #
9850# scale_to_zero_src() - make exponent. = 0; get scale factor #
9851# unf_res() - calculate underflow result #
9852# ovf_res() - calculate overflow result #
9853# res_{s,q}nan_1op() - set NAN result for monadic operation #
9854# #
9855# INPUT *************************************************************** #
9856# a0 = pointer to extended precision source operand #
9857# d0 = rnd precision/mode #
9858# #
9859# OUTPUT ************************************************************** #
9860# fp0 = result #
9861# fp1 = EXOP (if exception occurred) #
9862# #
9863# ALGORITHM *********************************************************** #
9864# Handle NANs, infinities, and zeroes as special cases. Divide #
9865# norms into extended, single, and double precision. #
9866# Simply clear sign for extended precision norm. Ext prec denorm #
9867# gets an EXOP created for it since it's an underflow. #
9868# Double and single precision can overflow and underflow. First, #
9869# scale the operand such that the exponent is zero. Perform an "fabs" #
9870# using the correct rnd mode/prec. Check to see if the original #
9871# exponent would take an exception. If so, use unf_res() or ovf_res() #
9872# to calculate the default result. Also, create the EXOP for the #
9873# exceptional case. If no exception should occur, insert the correct #
9874# result exponent and return. #
9875# Unnorms don't pass through here. #
9876# #
9877#########################################################################
9878
9879 global fsabs
9880fsabs:
9881 andi.b &0x30,%d0 # clear rnd prec
9882 ori.b &s_mode*0x10,%d0 # insert sgl precision
9883 bra.b fabs
9884
9885 global fdabs
9886fdabs:
9887 andi.b &0x30,%d0 # clear rnd prec
9888 ori.b &d_mode*0x10,%d0 # insert dbl precision
9889
9890 global fabs
9891fabs:
9892 mov.l %d0,L_SCR3(%a6) # store rnd info
9893 mov.b STAG(%a6),%d1
9894 bne.w fabs_not_norm # optimize on non-norm input
9895
9896#
9897# ABSOLUTE VALUE: norms and denorms ONLY!
9898#
9899fabs_norm:
9900 andi.b &0xc0,%d0 # is precision extended?
9901 bne.b fabs_not_ext # no; go handle sgl or dbl
9902
9903#
9904# precision selected is extended. so...we can not get an underflow
9905# or overflow because of rounding to the correct precision. so...
9906# skip the scaling and unscaling...
9907#
9908 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9909 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9910 mov.w SRC_EX(%a0),%d1
9911 bclr &15,%d1 # force absolute value
9912 mov.w %d1,FP_SCR0_EX(%a6) # insert exponent
9913 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
9914 rts
9915
9916#
9917# for an extended precision DENORM, the UNFL exception bit is set
9918# the accrued bit is NOT set in this instance(no inexactness!)
9919#
9920fabs_denorm:
9921 andi.b &0xc0,%d0 # is precision extended?
9922 bne.b fabs_not_ext # no
9923
9924 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
9925
9926 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9927 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9928 mov.w SRC_EX(%a0),%d0
9929 bclr &15,%d0 # clear sign
9930 mov.w %d0,FP_SCR0_EX(%a6) # insert exponent
9931
9932 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
9933
9934 btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
9935 bne.b fabs_ext_unfl_ena
9936 rts
9937
9938#
9939# the input is an extended DENORM and underflow is enabled in the FPCR.
9940# normalize the mantissa and add the bias of 0x6000 to the resulting negative
9941# exponent and insert back into the operand.
9942#
9943fabs_ext_unfl_ena:
9944 lea FP_SCR0(%a6),%a0 # pass: ptr to operand
9945 bsr.l norm # normalize result
9946 neg.w %d0 # new exponent = -(shft val)
9947 addi.w &0x6000,%d0 # add new bias to exponent
9948 mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
9949 andi.w &0x8000,%d1 # keep old sign
9950 andi.w &0x7fff,%d0 # clear sign position
9951 or.w %d1,%d0 # concat old sign, new exponent
9952 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
9953 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
9954 rts
9955
9956#
9957# operand is either single or double
9958#
9959fabs_not_ext:
9960 cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
9961 bne.b fabs_dbl
9962
9963#
9964# operand is to be rounded to single precision
9965#
9966fabs_sgl:
9967 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
9968 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9969 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9970 bsr.l scale_to_zero_src # calculate scale factor
9971
9972 cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
9973 bge.w fabs_sd_unfl # yes; go handle underflow
9974 cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
9975 beq.w fabs_sd_may_ovfl # maybe; go check
9976 blt.w fabs_sd_ovfl # yes; go handle overflow
9977
9978#
9979# operand will NOT overflow or underflow when moved in to the fp reg file
9980#
9981fabs_sd_normal:
9982 fmov.l &0x0,%fpsr # clear FPSR
9983 fmov.l L_SCR3(%a6),%fpcr # set FPCR
9984
9985 fabs.x FP_SCR0(%a6),%fp0 # perform absolute
9986
9987 fmov.l %fpsr,%d1 # save FPSR
9988 fmov.l &0x0,%fpcr # clear FPCR
9989
9990 or.l %d1,USER_FPSR(%a6) # save INEX2,N
9991
9992fabs_sd_normal_exit:
9993 mov.l %d2,-(%sp) # save d2
9994 fmovm.x &0x80,FP_SCR0(%a6) # store out result
9995 mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
9996 mov.l %d1,%d2 # make a copy
9997 andi.l &0x7fff,%d1 # strip sign
9998 sub.l %d0,%d1 # add scale factor
9999 andi.w &0x8000,%d2 # keep old sign
10000 or.w %d1,%d2 # concat old sign,new exp
10001 mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
10002 mov.l (%sp)+,%d2 # restore d2
10003 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
10004 rts
10005
10006#
10007# operand is to be rounded to double precision
10008#
10009fabs_dbl:
10010 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10011 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
10012 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10013 bsr.l scale_to_zero_src # calculate scale factor
10014
10015 cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
10016 bge.b fabs_sd_unfl # yes; go handle underflow
10017 cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
10018 beq.w fabs_sd_may_ovfl # maybe; go check
10019 blt.w fabs_sd_ovfl # yes; go handle overflow
10020 bra.w fabs_sd_normal # no; ho handle normalized op
10021
10022#
10023# operand WILL underflow when moved in to the fp register file
10024#
10025fabs_sd_unfl:
10026 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
10027
10028 bclr &0x7,FP_SCR0_EX(%a6) # force absolute value
10029
10030# if underflow or inexact is enabled, go calculate EXOP first.
10031 mov.b FPCR_ENABLE(%a6),%d1
10032 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
10033 bne.b fabs_sd_unfl_ena # yes
10034
10035fabs_sd_unfl_dis:
10036 lea FP_SCR0(%a6),%a0 # pass: result addr
10037 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
10038 bsr.l unf_res # calculate default result
10039 or.b %d0,FPSR_CC(%a6) # set possible 'Z' ccode
10040 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
10041 rts
10042
10043#
10044# operand will underflow AND underflow is enabled.
10045# therefore, we must return the result rounded to extended precision.
10046#
10047fabs_sd_unfl_ena:
10048 mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
10049 mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
10050 mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
10051
10052 mov.l %d2,-(%sp) # save d2
10053 mov.l %d1,%d2 # make a copy
10054 andi.l &0x7fff,%d1 # strip sign
10055 andi.w &0x8000,%d2 # keep old sign
10056 sub.l %d0,%d1 # subtract scale factor
10057 addi.l &0x6000,%d1 # add new bias
10058 andi.w &0x7fff,%d1
10059 or.w %d2,%d1 # concat new sign,new exp
10060 mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
10061 fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
10062 mov.l (%sp)+,%d2 # restore d2
10063 bra.b fabs_sd_unfl_dis
10064
10065#
10066# operand WILL overflow.
10067#
10068fabs_sd_ovfl:
10069 fmov.l &0x0,%fpsr # clear FPSR
10070 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10071
10072 fabs.x FP_SCR0(%a6),%fp0 # perform absolute
10073
10074 fmov.l &0x0,%fpcr # clear FPCR
10075 fmov.l %fpsr,%d1 # save FPSR
10076
10077 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10078
10079fabs_sd_ovfl_tst:
10080 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
10081
10082 mov.b FPCR_ENABLE(%a6),%d1
10083 andi.b &0x13,%d1 # is OVFL or INEX enabled?
10084 bne.b fabs_sd_ovfl_ena # yes
10085
10086#
10087# OVFL is not enabled; therefore, we must create the default result by
10088# calling ovf_res().
10089#
10090fabs_sd_ovfl_dis:
10091 btst &neg_bit,FPSR_CC(%a6) # is result negative?
10092 sne %d1 # set sign param accordingly
10093 mov.l L_SCR3(%a6),%d0 # pass: prec,mode
10094 bsr.l ovf_res # calculate default result
10095 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
10096 fmovm.x (%a0),&0x80 # return default result in fp0
10097 rts
10098
10099#
10100# OVFL is enabled.
10101# the INEX2 bit has already been updated by the round to the correct precision.
10102# now, round to extended(and don't alter the FPSR).
10103#
10104fabs_sd_ovfl_ena:
10105 mov.l %d2,-(%sp) # save d2
10106 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10107 mov.l %d1,%d2 # make a copy
10108 andi.l &0x7fff,%d1 # strip sign
10109 andi.w &0x8000,%d2 # keep old sign
10110 sub.l %d0,%d1 # add scale factor
10111 subi.l &0x6000,%d1 # subtract bias
10112 andi.w &0x7fff,%d1
10113 or.w %d2,%d1 # concat sign,exp
10114 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10115 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10116 mov.l (%sp)+,%d2 # restore d2
10117 bra.b fabs_sd_ovfl_dis
10118
10119#
10120# the move in MAY underflow. so...
10121#
10122fabs_sd_may_ovfl:
10123 fmov.l &0x0,%fpsr # clear FPSR
10124 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10125
10126 fabs.x FP_SCR0(%a6),%fp0 # perform absolute
10127
10128 fmov.l %fpsr,%d1 # save status
10129 fmov.l &0x0,%fpcr # clear FPCR
10130
10131 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10132
10133 fabs.x %fp0,%fp1 # make a copy of result
10134 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
10135 fbge.w fabs_sd_ovfl_tst # yes; overflow has occurred
10136
10137# no, it didn't overflow; we have correct result
10138 bra.w fabs_sd_normal_exit
10139
10140##########################################################################
10141
10142#
10143# input is not normalized; what is it?
10144#
10145fabs_not_norm:
10146 cmpi.b %d1,&DENORM # weed out DENORM
10147 beq.w fabs_denorm
10148 cmpi.b %d1,&SNAN # weed out SNAN
10149 beq.l res_snan_1op
10150 cmpi.b %d1,&QNAN # weed out QNAN
10151 beq.l res_qnan_1op
10152
10153 fabs.x SRC(%a0),%fp0 # force absolute value
10154
10155 cmpi.b %d1,&INF # weed out INF
10156 beq.b fabs_inf
10157fabs_zero:
10158 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10159 rts
10160fabs_inf:
10161 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
10162 rts
10163
10164#########################################################################
10165# XDEF **************************************************************** #
10166# fcmp(): fp compare op routine #
10167# #
10168# XREF **************************************************************** #
10169# res_qnan() - return QNAN result #
10170# res_snan() - return SNAN result #
10171# #
10172# INPUT *************************************************************** #
10173# a0 = pointer to extended precision source operand #
10174# a1 = pointer to extended precision destination operand #
10175# d0 = round prec/mode #
10176# #
10177# OUTPUT ************************************************************** #
10178# None #
10179# #
10180# ALGORITHM *********************************************************** #
10181# Handle NANs and denorms as special cases. For everything else, #
10182# just use the actual fcmp instruction to produce the correct condition #
10183# codes. #
10184# #
10185#########################################################################
10186
10187 global fcmp
10188fcmp:
10189 clr.w %d1
10190 mov.b DTAG(%a6),%d1
10191 lsl.b &0x3,%d1
10192 or.b STAG(%a6),%d1
10193 bne.b fcmp_not_norm # optimize on non-norm input
10194
10195#
10196# COMPARE FP OPs : NORMs, ZEROs, INFs, and "corrected" DENORMs
10197#
10198fcmp_norm:
10199 fmovm.x DST(%a1),&0x80 # load dst op
10200
10201 fcmp.x %fp0,SRC(%a0) # do compare
10202
10203 fmov.l %fpsr,%d0 # save FPSR
10204 rol.l &0x8,%d0 # extract ccode bits
10205 mov.b %d0,FPSR_CC(%a6) # set ccode bits(no exc bits are set)
10206
10207 rts
10208
10209#
10210# fcmp: inputs are not both normalized; what are they?
10211#
10212fcmp_not_norm:
10213 mov.w (tbl_fcmp_op.b,%pc,%d1.w*2),%d1
10214 jmp (tbl_fcmp_op.b,%pc,%d1.w*1)
10215
10216 swbeg &48
10217tbl_fcmp_op:
10218 short fcmp_norm - tbl_fcmp_op # NORM - NORM
10219 short fcmp_norm - tbl_fcmp_op # NORM - ZERO
10220 short fcmp_norm - tbl_fcmp_op # NORM - INF
10221 short fcmp_res_qnan - tbl_fcmp_op # NORM - QNAN
10222 short fcmp_nrm_dnrm - tbl_fcmp_op # NORM - DENORM
10223 short fcmp_res_snan - tbl_fcmp_op # NORM - SNAN
10224 short tbl_fcmp_op - tbl_fcmp_op #
10225 short tbl_fcmp_op - tbl_fcmp_op #
10226
10227 short fcmp_norm - tbl_fcmp_op # ZERO - NORM
10228 short fcmp_norm - tbl_fcmp_op # ZERO - ZERO
10229 short fcmp_norm - tbl_fcmp_op # ZERO - INF
10230 short fcmp_res_qnan - tbl_fcmp_op # ZERO - QNAN
10231 short fcmp_dnrm_s - tbl_fcmp_op # ZERO - DENORM
10232 short fcmp_res_snan - tbl_fcmp_op # ZERO - SNAN
10233 short tbl_fcmp_op - tbl_fcmp_op #
10234 short tbl_fcmp_op - tbl_fcmp_op #
10235
10236 short fcmp_norm - tbl_fcmp_op # INF - NORM
10237 short fcmp_norm - tbl_fcmp_op # INF - ZERO
10238 short fcmp_norm - tbl_fcmp_op # INF - INF
10239 short fcmp_res_qnan - tbl_fcmp_op # INF - QNAN
10240 short fcmp_dnrm_s - tbl_fcmp_op # INF - DENORM
10241 short fcmp_res_snan - tbl_fcmp_op # INF - SNAN
10242 short tbl_fcmp_op - tbl_fcmp_op #
10243 short tbl_fcmp_op - tbl_fcmp_op #
10244
10245 short fcmp_res_qnan - tbl_fcmp_op # QNAN - NORM
10246 short fcmp_res_qnan - tbl_fcmp_op # QNAN - ZERO
10247 short fcmp_res_qnan - tbl_fcmp_op # QNAN - INF
10248 short fcmp_res_qnan - tbl_fcmp_op # QNAN - QNAN
10249 short fcmp_res_qnan - tbl_fcmp_op # QNAN - DENORM
10250 short fcmp_res_snan - tbl_fcmp_op # QNAN - SNAN
10251 short tbl_fcmp_op - tbl_fcmp_op #
10252 short tbl_fcmp_op - tbl_fcmp_op #
10253
10254 short fcmp_dnrm_nrm - tbl_fcmp_op # DENORM - NORM
10255 short fcmp_dnrm_d - tbl_fcmp_op # DENORM - ZERO
10256 short fcmp_dnrm_d - tbl_fcmp_op # DENORM - INF
10257 short fcmp_res_qnan - tbl_fcmp_op # DENORM - QNAN
10258 short fcmp_dnrm_sd - tbl_fcmp_op # DENORM - DENORM
10259 short fcmp_res_snan - tbl_fcmp_op # DENORM - SNAN
10260 short tbl_fcmp_op - tbl_fcmp_op #
10261 short tbl_fcmp_op - tbl_fcmp_op #
10262
10263 short fcmp_res_snan - tbl_fcmp_op # SNAN - NORM
10264 short fcmp_res_snan - tbl_fcmp_op # SNAN - ZERO
10265 short fcmp_res_snan - tbl_fcmp_op # SNAN - INF
10266 short fcmp_res_snan - tbl_fcmp_op # SNAN - QNAN
10267 short fcmp_res_snan - tbl_fcmp_op # SNAN - DENORM
10268 short fcmp_res_snan - tbl_fcmp_op # SNAN - SNAN
10269 short tbl_fcmp_op - tbl_fcmp_op #
10270 short tbl_fcmp_op - tbl_fcmp_op #
10271
10272# unlike all other functions for QNAN and SNAN, fcmp does NOT set the
10273# 'N' bit for a negative QNAN or SNAN input so we must squelch it here.
10274fcmp_res_qnan:
10275 bsr.l res_qnan
10276 andi.b &0xf7,FPSR_CC(%a6)
10277 rts
10278fcmp_res_snan:
10279 bsr.l res_snan
10280 andi.b &0xf7,FPSR_CC(%a6)
10281 rts
10282
10283#
10284# DENORMs are a little more difficult.
10285# If you have a 2 DENORMs, then you can just force the j-bit to a one
10286# and use the fcmp_norm routine.
10287# If you have a DENORM and an INF or ZERO, just force the DENORM's j-bit to a one
10288# and use the fcmp_norm routine.
10289# If you have a DENORM and a NORM with opposite signs, then use fcmp_norm, also.
10290# But with a DENORM and a NORM of the same sign, the neg bit is set if the
10291# (1) signs are (+) and the DENORM is the dst or
10292# (2) signs are (-) and the DENORM is the src
10293#
10294
10295fcmp_dnrm_s:
10296 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10297 mov.l SRC_HI(%a0),%d0
10298 bset &31,%d0 # DENORM src; make into small norm
10299 mov.l %d0,FP_SCR0_HI(%a6)
10300 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10301 lea FP_SCR0(%a6),%a0
10302 bra.w fcmp_norm
10303
10304fcmp_dnrm_d:
10305 mov.l DST_EX(%a1),FP_SCR0_EX(%a6)
10306 mov.l DST_HI(%a1),%d0
10307 bset &31,%d0 # DENORM src; make into small norm
10308 mov.l %d0,FP_SCR0_HI(%a6)
10309 mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
10310 lea FP_SCR0(%a6),%a1
10311 bra.w fcmp_norm
10312
10313fcmp_dnrm_sd:
10314 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
10315 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10316 mov.l DST_HI(%a1),%d0
10317 bset &31,%d0 # DENORM dst; make into small norm
10318 mov.l %d0,FP_SCR1_HI(%a6)
10319 mov.l SRC_HI(%a0),%d0
10320 bset &31,%d0 # DENORM dst; make into small norm
10321 mov.l %d0,FP_SCR0_HI(%a6)
10322 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
10323 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10324 lea FP_SCR1(%a6),%a1
10325 lea FP_SCR0(%a6),%a0
10326 bra.w fcmp_norm
10327
10328fcmp_nrm_dnrm:
10329 mov.b SRC_EX(%a0),%d0 # determine if like signs
10330 mov.b DST_EX(%a1),%d1
10331 eor.b %d0,%d1
10332 bmi.w fcmp_dnrm_s
10333
10334# signs are the same, so must determine the answer ourselves.
10335 tst.b %d0 # is src op negative?
10336 bmi.b fcmp_nrm_dnrm_m # yes
10337 rts
10338fcmp_nrm_dnrm_m:
10339 mov.b &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10340 rts
10341
10342fcmp_dnrm_nrm:
10343 mov.b SRC_EX(%a0),%d0 # determine if like signs
10344 mov.b DST_EX(%a1),%d1
10345 eor.b %d0,%d1
10346 bmi.w fcmp_dnrm_d
10347
10348# signs are the same, so must determine the answer ourselves.
10349 tst.b %d0 # is src op negative?
10350 bpl.b fcmp_dnrm_nrm_m # no
10351 rts
10352fcmp_dnrm_nrm_m:
10353 mov.b &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10354 rts
10355
10356#########################################################################
10357# XDEF **************************************************************** #
10358# fsglmul(): emulates the fsglmul instruction #
10359# #
10360# XREF **************************************************************** #
10361# scale_to_zero_src() - scale src exponent to zero #
10362# scale_to_zero_dst() - scale dst exponent to zero #
10363# unf_res4() - return default underflow result for sglop #
10364# ovf_res() - return default overflow result #
10365# res_qnan() - return QNAN result #
10366# res_snan() - return SNAN result #
10367# #
10368# INPUT *************************************************************** #
10369# a0 = pointer to extended precision source operand #
10370# a1 = pointer to extended precision destination operand #
10371# d0 rnd prec,mode #
10372# #
10373# OUTPUT ************************************************************** #
10374# fp0 = result #
10375# fp1 = EXOP (if exception occurred) #
10376# #
10377# ALGORITHM *********************************************************** #
10378# Handle NANs, infinities, and zeroes as special cases. Divide #
10379# norms/denorms into ext/sgl/dbl precision. #
10380# For norms/denorms, scale the exponents such that a multiply #
10381# instruction won't cause an exception. Use the regular fsglmul to #
10382# compute a result. Check if the regular operands would have taken #
10383# an exception. If so, return the default overflow/underflow result #
10384# and return the EXOP if exceptions are enabled. Else, scale the #
10385# result operand to the proper exponent. #
10386# #
10387#########################################################################
10388
10389 global fsglmul
10390fsglmul:
10391 mov.l %d0,L_SCR3(%a6) # store rnd info
10392
10393 clr.w %d1
10394 mov.b DTAG(%a6),%d1
10395 lsl.b &0x3,%d1
10396 or.b STAG(%a6),%d1
10397
10398 bne.w fsglmul_not_norm # optimize on non-norm input
10399
10400fsglmul_norm:
10401 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
10402 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
10403 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
10404
10405 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10406 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
10407 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10408
10409 bsr.l scale_to_zero_src # scale exponent
10410 mov.l %d0,-(%sp) # save scale factor 1
10411
10412 bsr.l scale_to_zero_dst # scale dst exponent
10413
10414 add.l (%sp)+,%d0 # SCALE_FACTOR = scale1 + scale2
10415
10416 cmpi.l %d0,&0x3fff-0x7ffe # would result ovfl?
10417 beq.w fsglmul_may_ovfl # result may rnd to overflow
10418 blt.w fsglmul_ovfl # result will overflow
10419
10420 cmpi.l %d0,&0x3fff+0x0001 # would result unfl?
10421 beq.w fsglmul_may_unfl # result may rnd to no unfl
10422 bgt.w fsglmul_unfl # result will underflow
10423
10424fsglmul_normal:
10425 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10426
10427 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10428 fmov.l &0x0,%fpsr # clear FPSR
10429
10430 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10431
10432 fmov.l %fpsr,%d1 # save status
10433 fmov.l &0x0,%fpcr # clear FPCR
10434
10435 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10436
10437fsglmul_normal_exit:
10438 fmovm.x &0x80,FP_SCR0(%a6) # store out result
10439 mov.l %d2,-(%sp) # save d2
10440 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
10441 mov.l %d1,%d2 # make a copy
10442 andi.l &0x7fff,%d1 # strip sign
10443 andi.w &0x8000,%d2 # keep old sign
10444 sub.l %d0,%d1 # add scale factor
10445 or.w %d2,%d1 # concat old sign,new exp
10446 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10447 mov.l (%sp)+,%d2 # restore d2
10448 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
10449 rts
10450
10451fsglmul_ovfl:
10452 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10453
10454 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10455 fmov.l &0x0,%fpsr # clear FPSR
10456
10457 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10458
10459 fmov.l %fpsr,%d1 # save status
10460 fmov.l &0x0,%fpcr # clear FPCR
10461
10462 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10463
10464fsglmul_ovfl_tst:
10465
10466# save setting this until now because this is where fsglmul_may_ovfl may jump in
10467 or.l &ovfl_inx_mask, USER_FPSR(%a6) # set ovfl/aovfl/ainex
10468
10469 mov.b FPCR_ENABLE(%a6),%d1
10470 andi.b &0x13,%d1 # is OVFL or INEX enabled?
10471 bne.b fsglmul_ovfl_ena # yes
10472
10473fsglmul_ovfl_dis:
10474 btst &neg_bit,FPSR_CC(%a6) # is result negative?
10475 sne %d1 # set sign param accordingly
10476 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
10477 andi.b &0x30,%d0 # force prec = ext
10478 bsr.l ovf_res # calculate default result
10479 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
10480 fmovm.x (%a0),&0x80 # return default result in fp0
10481 rts
10482
10483fsglmul_ovfl_ena:
10484 fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
10485
10486 mov.l %d2,-(%sp) # save d2
10487 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10488 mov.l %d1,%d2 # make a copy
10489 andi.l &0x7fff,%d1 # strip sign
10490 sub.l %d0,%d1 # add scale factor
10491 subi.l &0x6000,%d1 # subtract bias
10492 andi.w &0x7fff,%d1
10493 andi.w &0x8000,%d2 # keep old sign
10494 or.w %d2,%d1 # concat old sign,new exp
10495 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10496 mov.l (%sp)+,%d2 # restore d2
10497 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10498 bra.b fsglmul_ovfl_dis
10499
10500fsglmul_may_ovfl:
10501 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10502
10503 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10504 fmov.l &0x0,%fpsr # clear FPSR
10505
10506 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10507
10508 fmov.l %fpsr,%d1 # save status
10509 fmov.l &0x0,%fpcr # clear FPCR
10510
10511 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10512
10513 fabs.x %fp0,%fp1 # make a copy of result
10514 fcmp.b %fp1,&0x2 # is |result| >= 2.b?
10515 fbge.w fsglmul_ovfl_tst # yes; overflow has occurred
10516
10517# no, it didn't overflow; we have correct result
10518 bra.w fsglmul_normal_exit
10519
10520fsglmul_unfl:
10521 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
10522
10523 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10524
10525 fmov.l &rz_mode*0x10,%fpcr # set FPCR
10526 fmov.l &0x0,%fpsr # clear FPSR
10527
10528 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10529
10530 fmov.l %fpsr,%d1 # save status
10531 fmov.l &0x0,%fpcr # clear FPCR
10532
10533 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10534
10535 mov.b FPCR_ENABLE(%a6),%d1
10536 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
10537 bne.b fsglmul_unfl_ena # yes
10538
10539fsglmul_unfl_dis:
10540 fmovm.x &0x80,FP_SCR0(%a6) # store out result
10541
10542 lea FP_SCR0(%a6),%a0 # pass: result addr
10543 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
10544 bsr.l unf_res4 # calculate default result
10545 or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
10546 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
10547 rts
10548
10549#
10550# UNFL is enabled.
10551#
10552fsglmul_unfl_ena:
10553 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
10554
10555 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10556 fmov.l &0x0,%fpsr # clear FPSR
10557
10558 fsglmul.x FP_SCR0(%a6),%fp1 # execute sgl multiply
10559
10560 fmov.l &0x0,%fpcr # clear FPCR
10561
10562 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
10563 mov.l %d2,-(%sp) # save d2
10564 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10565 mov.l %d1,%d2 # make a copy
10566 andi.l &0x7fff,%d1 # strip sign
10567 andi.w &0x8000,%d2 # keep old sign
10568 sub.l %d0,%d1 # add scale factor
10569 addi.l &0x6000,%d1 # add bias
10570 andi.w &0x7fff,%d1
10571 or.w %d2,%d1 # concat old sign,new exp
10572 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10573 mov.l (%sp)+,%d2 # restore d2
10574 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10575 bra.w fsglmul_unfl_dis
10576
10577fsglmul_may_unfl:
10578 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10579
10580 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10581 fmov.l &0x0,%fpsr # clear FPSR
10582
10583 fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10584
10585 fmov.l %fpsr,%d1 # save status
10586 fmov.l &0x0,%fpcr # clear FPCR
10587
10588 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10589
10590 fabs.x %fp0,%fp1 # make a copy of result
10591 fcmp.b %fp1,&0x2 # is |result| > 2.b?
10592 fbgt.w fsglmul_normal_exit # no; no underflow occurred
10593 fblt.w fsglmul_unfl # yes; underflow occurred
10594
10595#
10596# we still don't know if underflow occurred. result is ~ equal to 2. but,
10597# we don't know if the result was an underflow that rounded up to a 2 or
10598# a normalized number that rounded down to a 2. so, redo the entire operation
10599# using RZ as the rounding mode to see what the pre-rounded result is.
10600# this case should be relatively rare.
10601#
10602 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
10603
10604 mov.l L_SCR3(%a6),%d1
10605 andi.b &0xc0,%d1 # keep rnd prec
10606 ori.b &rz_mode*0x10,%d1 # insert RZ
10607
10608 fmov.l %d1,%fpcr # set FPCR
10609 fmov.l &0x0,%fpsr # clear FPSR
10610
10611 fsglmul.x FP_SCR0(%a6),%fp1 # execute sgl multiply
10612
10613 fmov.l &0x0,%fpcr # clear FPCR
10614 fabs.x %fp1 # make absolute value
10615 fcmp.b %fp1,&0x2 # is |result| < 2.b?
10616 fbge.w fsglmul_normal_exit # no; no underflow occurred
10617 bra.w fsglmul_unfl # yes, underflow occurred
10618
10619##############################################################################
10620
10621#
10622# Single Precision Multiply: inputs are not both normalized; what are they?
10623#
10624fsglmul_not_norm:
10625 mov.w (tbl_fsglmul_op.b,%pc,%d1.w*2),%d1
10626 jmp (tbl_fsglmul_op.b,%pc,%d1.w*1)
10627
10628 swbeg &48
10629tbl_fsglmul_op:
10630 short fsglmul_norm - tbl_fsglmul_op # NORM x NORM
10631 short fsglmul_zero - tbl_fsglmul_op # NORM x ZERO
10632 short fsglmul_inf_src - tbl_fsglmul_op # NORM x INF
10633 short fsglmul_res_qnan - tbl_fsglmul_op # NORM x QNAN
10634 short fsglmul_norm - tbl_fsglmul_op # NORM x DENORM
10635 short fsglmul_res_snan - tbl_fsglmul_op # NORM x SNAN
10636 short tbl_fsglmul_op - tbl_fsglmul_op #
10637 short tbl_fsglmul_op - tbl_fsglmul_op #
10638
10639 short fsglmul_zero - tbl_fsglmul_op # ZERO x NORM
10640 short fsglmul_zero - tbl_fsglmul_op # ZERO x ZERO
10641 short fsglmul_res_operr - tbl_fsglmul_op # ZERO x INF
10642 short fsglmul_res_qnan - tbl_fsglmul_op # ZERO x QNAN
10643 short fsglmul_zero - tbl_fsglmul_op # ZERO x DENORM
10644 short fsglmul_res_snan - tbl_fsglmul_op # ZERO x SNAN
10645 short tbl_fsglmul_op - tbl_fsglmul_op #
10646 short tbl_fsglmul_op - tbl_fsglmul_op #
10647
10648 short fsglmul_inf_dst - tbl_fsglmul_op # INF x NORM
10649 short fsglmul_res_operr - tbl_fsglmul_op # INF x ZERO
10650 short fsglmul_inf_dst - tbl_fsglmul_op # INF x INF
10651 short fsglmul_res_qnan - tbl_fsglmul_op # INF x QNAN
10652 short fsglmul_inf_dst - tbl_fsglmul_op # INF x DENORM
10653 short fsglmul_res_snan - tbl_fsglmul_op # INF x SNAN
10654 short tbl_fsglmul_op - tbl_fsglmul_op #
10655 short tbl_fsglmul_op - tbl_fsglmul_op #
10656
10657 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x NORM
10658 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x ZERO
10659 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x INF
10660 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x QNAN
10661 short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x DENORM
10662 short fsglmul_res_snan - tbl_fsglmul_op # QNAN x SNAN
10663 short tbl_fsglmul_op - tbl_fsglmul_op #
10664 short tbl_fsglmul_op - tbl_fsglmul_op #
10665
10666 short fsglmul_norm - tbl_fsglmul_op # NORM x NORM
10667 short fsglmul_zero - tbl_fsglmul_op # NORM x ZERO
10668 short fsglmul_inf_src - tbl_fsglmul_op # NORM x INF
10669 short fsglmul_res_qnan - tbl_fsglmul_op # NORM x QNAN
10670 short fsglmul_norm - tbl_fsglmul_op # NORM x DENORM
10671 short fsglmul_res_snan - tbl_fsglmul_op # NORM x SNAN
10672 short tbl_fsglmul_op - tbl_fsglmul_op #
10673 short tbl_fsglmul_op - tbl_fsglmul_op #
10674
10675 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x NORM
10676 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x ZERO
10677 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x INF
10678 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x QNAN
10679 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x DENORM
10680 short fsglmul_res_snan - tbl_fsglmul_op # SNAN x SNAN
10681 short tbl_fsglmul_op - tbl_fsglmul_op #
10682 short tbl_fsglmul_op - tbl_fsglmul_op #
10683
10684fsglmul_res_operr:
10685 bra.l res_operr
10686fsglmul_res_snan:
10687 bra.l res_snan
10688fsglmul_res_qnan:
10689 bra.l res_qnan
10690fsglmul_zero:
10691 bra.l fmul_zero
10692fsglmul_inf_src:
10693 bra.l fmul_inf_src
10694fsglmul_inf_dst:
10695 bra.l fmul_inf_dst
10696
10697#########################################################################
10698# XDEF **************************************************************** #
10699# fsgldiv(): emulates the fsgldiv instruction #
10700# #
10701# XREF **************************************************************** #
10702# scale_to_zero_src() - scale src exponent to zero #
10703# scale_to_zero_dst() - scale dst exponent to zero #
10704# unf_res4() - return default underflow result for sglop #
10705# ovf_res() - return default overflow result #
10706# res_qnan() - return QNAN result #
10707# res_snan() - return SNAN result #
10708# #
10709# INPUT *************************************************************** #
10710# a0 = pointer to extended precision source operand #
10711# a1 = pointer to extended precision destination operand #
10712# d0 rnd prec,mode #
10713# #
10714# OUTPUT ************************************************************** #
10715# fp0 = result #
10716# fp1 = EXOP (if exception occurred) #
10717# #
10718# ALGORITHM *********************************************************** #
10719# Handle NANs, infinities, and zeroes as special cases. Divide #
10720# norms/denorms into ext/sgl/dbl precision. #
10721# For norms/denorms, scale the exponents such that a divide #
10722# instruction won't cause an exception. Use the regular fsgldiv to #
10723# compute a result. Check if the regular operands would have taken #
10724# an exception. If so, return the default overflow/underflow result #
10725# and return the EXOP if exceptions are enabled. Else, scale the #
10726# result operand to the proper exponent. #
10727# #
10728#########################################################################
10729
10730 global fsgldiv
10731fsgldiv:
10732 mov.l %d0,L_SCR3(%a6) # store rnd info
10733
10734 clr.w %d1
10735 mov.b DTAG(%a6),%d1
10736 lsl.b &0x3,%d1
10737 or.b STAG(%a6),%d1 # combine src tags
10738
10739 bne.w fsgldiv_not_norm # optimize on non-norm input
10740
10741#
10742# DIVIDE: NORMs and DENORMs ONLY!
10743#
10744fsgldiv_norm:
10745 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
10746 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
10747 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
10748
10749 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10750 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
10751 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10752
10753 bsr.l scale_to_zero_src # calculate scale factor 1
10754 mov.l %d0,-(%sp) # save scale factor 1
10755
10756 bsr.l scale_to_zero_dst # calculate scale factor 2
10757
10758 neg.l (%sp) # S.F. = scale1 - scale2
10759 add.l %d0,(%sp)
10760
10761 mov.w 2+L_SCR3(%a6),%d1 # fetch precision,mode
10762 lsr.b &0x6,%d1
10763 mov.l (%sp)+,%d0
10764 cmpi.l %d0,&0x3fff-0x7ffe
10765 ble.w fsgldiv_may_ovfl
10766
10767 cmpi.l %d0,&0x3fff-0x0000 # will result underflow?
10768 beq.w fsgldiv_may_unfl # maybe
10769 bgt.w fsgldiv_unfl # yes; go handle underflow
10770
10771fsgldiv_normal:
10772 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10773
10774 fmov.l L_SCR3(%a6),%fpcr # save FPCR
10775 fmov.l &0x0,%fpsr # clear FPSR
10776
10777 fsgldiv.x FP_SCR0(%a6),%fp0 # perform sgl divide
10778
10779 fmov.l %fpsr,%d1 # save FPSR
10780 fmov.l &0x0,%fpcr # clear FPCR
10781
10782 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10783
10784fsgldiv_normal_exit:
10785 fmovm.x &0x80,FP_SCR0(%a6) # store result on stack
10786 mov.l %d2,-(%sp) # save d2
10787 mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
10788 mov.l %d1,%d2 # make a copy
10789 andi.l &0x7fff,%d1 # strip sign
10790 andi.w &0x8000,%d2 # keep old sign
10791 sub.l %d0,%d1 # add scale factor
10792 or.w %d2,%d1 # concat old sign,new exp
10793 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10794 mov.l (%sp)+,%d2 # restore d2
10795 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
10796 rts
10797
10798fsgldiv_may_ovfl:
10799 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10800
10801 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10802 fmov.l &0x0,%fpsr # set FPSR
10803
10804 fsgldiv.x FP_SCR0(%a6),%fp0 # execute divide
10805
10806 fmov.l %fpsr,%d1
10807 fmov.l &0x0,%fpcr
10808
10809 or.l %d1,USER_FPSR(%a6) # save INEX,N
10810
10811 fmovm.x &0x01,-(%sp) # save result to stack
10812 mov.w (%sp),%d1 # fetch new exponent
10813 add.l &0xc,%sp # clear result
10814 andi.l &0x7fff,%d1 # strip sign
10815 sub.l %d0,%d1 # add scale factor
10816 cmp.l %d1,&0x7fff # did divide overflow?
10817 blt.b fsgldiv_normal_exit
10818
10819fsgldiv_ovfl_tst:
10820 or.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
10821
10822 mov.b FPCR_ENABLE(%a6),%d1
10823 andi.b &0x13,%d1 # is OVFL or INEX enabled?
10824 bne.b fsgldiv_ovfl_ena # yes
10825
10826fsgldiv_ovfl_dis:
10827 btst &neg_bit,FPSR_CC(%a6) # is result negative
10828 sne %d1 # set sign param accordingly
10829 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
10830 andi.b &0x30,%d0 # kill precision
10831 bsr.l ovf_res # calculate default result
10832 or.b %d0,FPSR_CC(%a6) # set INF if applicable
10833 fmovm.x (%a0),&0x80 # return default result in fp0
10834 rts
10835
10836fsgldiv_ovfl_ena:
10837 fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
10838
10839 mov.l %d2,-(%sp) # save d2
10840 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10841 mov.l %d1,%d2 # make a copy
10842 andi.l &0x7fff,%d1 # strip sign
10843 andi.w &0x8000,%d2 # keep old sign
10844 sub.l %d0,%d1 # add scale factor
10845 subi.l &0x6000,%d1 # subtract new bias
10846 andi.w &0x7fff,%d1 # clear ms bit
10847 or.w %d2,%d1 # concat old sign,new exp
10848 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10849 mov.l (%sp)+,%d2 # restore d2
10850 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10851 bra.b fsgldiv_ovfl_dis
10852
10853fsgldiv_unfl:
10854 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
10855
10856 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10857
10858 fmov.l &rz_mode*0x10,%fpcr # set FPCR
10859 fmov.l &0x0,%fpsr # clear FPSR
10860
10861 fsgldiv.x FP_SCR0(%a6),%fp0 # execute sgl divide
10862
10863 fmov.l %fpsr,%d1 # save status
10864 fmov.l &0x0,%fpcr # clear FPCR
10865
10866 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10867
10868 mov.b FPCR_ENABLE(%a6),%d1
10869 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
10870 bne.b fsgldiv_unfl_ena # yes
10871
10872fsgldiv_unfl_dis:
10873 fmovm.x &0x80,FP_SCR0(%a6) # store out result
10874
10875 lea FP_SCR0(%a6),%a0 # pass: result addr
10876 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
10877 bsr.l unf_res4 # calculate default result
10878 or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
10879 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
10880 rts
10881
10882#
10883# UNFL is enabled.
10884#
10885fsgldiv_unfl_ena:
10886 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
10887
10888 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10889 fmov.l &0x0,%fpsr # clear FPSR
10890
10891 fsgldiv.x FP_SCR0(%a6),%fp1 # execute sgl divide
10892
10893 fmov.l &0x0,%fpcr # clear FPCR
10894
10895 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
10896 mov.l %d2,-(%sp) # save d2
10897 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10898 mov.l %d1,%d2 # make a copy
10899 andi.l &0x7fff,%d1 # strip sign
10900 andi.w &0x8000,%d2 # keep old sign
10901 sub.l %d0,%d1 # add scale factor
10902 addi.l &0x6000,%d1 # add bias
10903 andi.w &0x7fff,%d1 # clear top bit
10904 or.w %d2,%d1 # concat old sign, new exp
10905 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10906 mov.l (%sp)+,%d2 # restore d2
10907 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10908 bra.b fsgldiv_unfl_dis
10909
10910#
10911# the divide operation MAY underflow:
10912#
10913fsgldiv_may_unfl:
10914 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10915
10916 fmov.l L_SCR3(%a6),%fpcr # set FPCR
10917 fmov.l &0x0,%fpsr # clear FPSR
10918
10919 fsgldiv.x FP_SCR0(%a6),%fp0 # execute sgl divide
10920
10921 fmov.l %fpsr,%d1 # save status
10922 fmov.l &0x0,%fpcr # clear FPCR
10923
10924 or.l %d1,USER_FPSR(%a6) # save INEX2,N
10925
10926 fabs.x %fp0,%fp1 # make a copy of result
10927 fcmp.b %fp1,&0x1 # is |result| > 1.b?
10928 fbgt.w fsgldiv_normal_exit # no; no underflow occurred
10929 fblt.w fsgldiv_unfl # yes; underflow occurred
10930
10931#
10932# we still don't know if underflow occurred. result is ~ equal to 1. but,
10933# we don't know if the result was an underflow that rounded up to a 1
10934# or a normalized number that rounded down to a 1. so, redo the entire
10935# operation using RZ as the rounding mode to see what the pre-rounded
10936# result is. this case should be relatively rare.
10937#
10938 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into %fp1
10939
10940 clr.l %d1 # clear scratch register
10941 ori.b &rz_mode*0x10,%d1 # force RZ rnd mode
10942
10943 fmov.l %d1,%fpcr # set FPCR
10944 fmov.l &0x0,%fpsr # clear FPSR
10945
10946 fsgldiv.x FP_SCR0(%a6),%fp1 # execute sgl divide
10947
10948 fmov.l &0x0,%fpcr # clear FPCR
10949 fabs.x %fp1 # make absolute value
10950 fcmp.b %fp1,&0x1 # is |result| < 1.b?
10951 fbge.w fsgldiv_normal_exit # no; no underflow occurred
10952 bra.w fsgldiv_unfl # yes; underflow occurred
10953
10954############################################################################
10955
10956#
10957# Divide: inputs are not both normalized; what are they?
10958#
10959fsgldiv_not_norm:
10960 mov.w (tbl_fsgldiv_op.b,%pc,%d1.w*2),%d1
10961 jmp (tbl_fsgldiv_op.b,%pc,%d1.w*1)
10962
10963 swbeg &48
10964tbl_fsgldiv_op:
10965 short fsgldiv_norm - tbl_fsgldiv_op # NORM / NORM
10966 short fsgldiv_inf_load - tbl_fsgldiv_op # NORM / ZERO
10967 short fsgldiv_zero_load - tbl_fsgldiv_op # NORM / INF
10968 short fsgldiv_res_qnan - tbl_fsgldiv_op # NORM / QNAN
10969 short fsgldiv_norm - tbl_fsgldiv_op # NORM / DENORM
10970 short fsgldiv_res_snan - tbl_fsgldiv_op # NORM / SNAN
10971 short tbl_fsgldiv_op - tbl_fsgldiv_op #
10972 short tbl_fsgldiv_op - tbl_fsgldiv_op #
10973
10974 short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / NORM
10975 short fsgldiv_res_operr - tbl_fsgldiv_op # ZERO / ZERO
10976 short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / INF
10977 short fsgldiv_res_qnan - tbl_fsgldiv_op # ZERO / QNAN
10978 short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / DENORM
10979 short fsgldiv_res_snan - tbl_fsgldiv_op # ZERO / SNAN
10980 short tbl_fsgldiv_op - tbl_fsgldiv_op #
10981 short tbl_fsgldiv_op - tbl_fsgldiv_op #
10982
10983 short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / NORM
10984 short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / ZERO
10985 short fsgldiv_res_operr - tbl_fsgldiv_op # INF / INF
10986 short fsgldiv_res_qnan - tbl_fsgldiv_op # INF / QNAN
10987 short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / DENORM
10988 short fsgldiv_res_snan - tbl_fsgldiv_op # INF / SNAN
10989 short tbl_fsgldiv_op - tbl_fsgldiv_op #
10990 short tbl_fsgldiv_op - tbl_fsgldiv_op #
10991
10992 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / NORM
10993 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / ZERO
10994 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / INF
10995 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / QNAN
10996 short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / DENORM
10997 short fsgldiv_res_snan - tbl_fsgldiv_op # QNAN / SNAN
10998 short tbl_fsgldiv_op - tbl_fsgldiv_op #
10999 short tbl_fsgldiv_op - tbl_fsgldiv_op #
11000
11001 short fsgldiv_norm - tbl_fsgldiv_op # DENORM / NORM
11002 short fsgldiv_inf_load - tbl_fsgldiv_op # DENORM / ZERO
11003 short fsgldiv_zero_load - tbl_fsgldiv_op # DENORM / INF
11004 short fsgldiv_res_qnan - tbl_fsgldiv_op # DENORM / QNAN
11005 short fsgldiv_norm - tbl_fsgldiv_op # DENORM / DENORM
11006 short fsgldiv_res_snan - tbl_fsgldiv_op # DENORM / SNAN
11007 short tbl_fsgldiv_op - tbl_fsgldiv_op #
11008 short tbl_fsgldiv_op - tbl_fsgldiv_op #
11009
11010 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / NORM
11011 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / ZERO
11012 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / INF
11013 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / QNAN
11014 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / DENORM
11015 short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / SNAN
11016 short tbl_fsgldiv_op - tbl_fsgldiv_op #
11017 short tbl_fsgldiv_op - tbl_fsgldiv_op #
11018
11019fsgldiv_res_qnan:
11020 bra.l res_qnan
11021fsgldiv_res_snan:
11022 bra.l res_snan
11023fsgldiv_res_operr:
11024 bra.l res_operr
11025fsgldiv_inf_load:
11026 bra.l fdiv_inf_load
11027fsgldiv_zero_load:
11028 bra.l fdiv_zero_load
11029fsgldiv_inf_dst:
11030 bra.l fdiv_inf_dst
11031
11032#########################################################################
11033# XDEF **************************************************************** #
11034# fadd(): emulates the fadd instruction #
11035# fsadd(): emulates the fadd instruction #
11036# fdadd(): emulates the fdadd instruction #
11037# #
11038# XREF **************************************************************** #
11039# addsub_scaler2() - scale the operands so they won't take exc #
11040# ovf_res() - return default overflow result #
11041# unf_res() - return default underflow result #
11042# res_qnan() - set QNAN result #
11043# res_snan() - set SNAN result #
11044# res_operr() - set OPERR result #
11045# scale_to_zero_src() - set src operand exponent equal to zero #
11046# scale_to_zero_dst() - set dst operand exponent equal to zero #
11047# #
11048# INPUT *************************************************************** #
11049# a0 = pointer to extended precision source operand #
11050# a1 = pointer to extended precision destination operand #
11051# #
11052# OUTPUT ************************************************************** #
11053# fp0 = result #
11054# fp1 = EXOP (if exception occurred) #
11055# #
11056# ALGORITHM *********************************************************** #
11057# Handle NANs, infinities, and zeroes as special cases. Divide #
11058# norms into extended, single, and double precision. #
11059# Do addition after scaling exponents such that exception won't #
11060# occur. Then, check result exponent to see if exception would have #
11061# occurred. If so, return default result and maybe EXOP. Else, insert #
11062# the correct result exponent and return. Set FPSR bits as appropriate. #
11063# #
11064#########################################################################
11065
11066 global fsadd
11067fsadd:
11068 andi.b &0x30,%d0 # clear rnd prec
11069 ori.b &s_mode*0x10,%d0 # insert sgl prec
11070 bra.b fadd
11071
11072 global fdadd
11073fdadd:
11074 andi.b &0x30,%d0 # clear rnd prec
11075 ori.b &d_mode*0x10,%d0 # insert dbl prec
11076
11077 global fadd
11078fadd:
11079 mov.l %d0,L_SCR3(%a6) # store rnd info
11080
11081 clr.w %d1
11082 mov.b DTAG(%a6),%d1
11083 lsl.b &0x3,%d1
11084 or.b STAG(%a6),%d1 # combine src tags
11085
11086 bne.w fadd_not_norm # optimize on non-norm input
11087
11088#
11089# ADD: norms and denorms
11090#
11091fadd_norm:
11092 bsr.l addsub_scaler2 # scale exponents
11093
11094fadd_zero_entry:
11095 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11096
11097 fmov.l &0x0,%fpsr # clear FPSR
11098 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11099
11100 fadd.x FP_SCR0(%a6),%fp0 # execute add
11101
11102 fmov.l &0x0,%fpcr # clear FPCR
11103 fmov.l %fpsr,%d1 # fetch INEX2,N,Z
11104
11105 or.l %d1,USER_FPSR(%a6) # save exc and ccode bits
11106
11107 fbeq.w fadd_zero_exit # if result is zero, end now
11108
11109 mov.l %d2,-(%sp) # save d2
11110
11111 fmovm.x &0x01,-(%sp) # save result to stack
11112
11113 mov.w 2+L_SCR3(%a6),%d1
11114 lsr.b &0x6,%d1
11115
11116 mov.w (%sp),%d2 # fetch new sign, exp
11117 andi.l &0x7fff,%d2 # strip sign
11118 sub.l %d0,%d2 # add scale factor
11119
11120 cmp.l %d2,(tbl_fadd_ovfl.b,%pc,%d1.w*4) # is it an overflow?
11121 bge.b fadd_ovfl # yes
11122
11123 cmp.l %d2,(tbl_fadd_unfl.b,%pc,%d1.w*4) # is it an underflow?
11124 blt.w fadd_unfl # yes
11125 beq.w fadd_may_unfl # maybe; go find out
11126
11127fadd_normal:
11128 mov.w (%sp),%d1
11129 andi.w &0x8000,%d1 # keep sign
11130 or.w %d2,%d1 # concat sign,new exp
11131 mov.w %d1,(%sp) # insert new exponent
11132
11133 fmovm.x (%sp)+,&0x80 # return result in fp0
11134
11135 mov.l (%sp)+,%d2 # restore d2
11136 rts
11137
11138fadd_zero_exit:
11139# fmov.s &0x00000000,%fp0 # return zero in fp0
11140 rts
11141
11142tbl_fadd_ovfl:
11143 long 0x7fff # ext ovfl
11144 long 0x407f # sgl ovfl
11145 long 0x43ff # dbl ovfl
11146
11147tbl_fadd_unfl:
11148 long 0x0000 # ext unfl
11149 long 0x3f81 # sgl unfl
11150 long 0x3c01 # dbl unfl
11151
11152fadd_ovfl:
11153 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
11154
11155 mov.b FPCR_ENABLE(%a6),%d1
11156 andi.b &0x13,%d1 # is OVFL or INEX enabled?
11157 bne.b fadd_ovfl_ena # yes
11158
11159 add.l &0xc,%sp
11160fadd_ovfl_dis:
11161 btst &neg_bit,FPSR_CC(%a6) # is result negative?
11162 sne %d1 # set sign param accordingly
11163 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
11164 bsr.l ovf_res # calculate default result
11165 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
11166 fmovm.x (%a0),&0x80 # return default result in fp0
11167 mov.l (%sp)+,%d2 # restore d2
11168 rts
11169
11170fadd_ovfl_ena:
11171 mov.b L_SCR3(%a6),%d1
11172 andi.b &0xc0,%d1 # is precision extended?
11173 bne.b fadd_ovfl_ena_sd # no; prec = sgl or dbl
11174
11175fadd_ovfl_ena_cont:
11176 mov.w (%sp),%d1
11177 andi.w &0x8000,%d1 # keep sign
11178 subi.l &0x6000,%d2 # add extra bias
11179 andi.w &0x7fff,%d2
11180 or.w %d2,%d1 # concat sign,new exp
11181 mov.w %d1,(%sp) # insert new exponent
11182
11183 fmovm.x (%sp)+,&0x40 # return EXOP in fp1
11184 bra.b fadd_ovfl_dis
11185
11186fadd_ovfl_ena_sd:
11187 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11188
11189 mov.l L_SCR3(%a6),%d1
11190 andi.b &0x30,%d1 # keep rnd mode
11191 fmov.l %d1,%fpcr # set FPCR
11192
11193 fadd.x FP_SCR0(%a6),%fp0 # execute add
11194
11195 fmov.l &0x0,%fpcr # clear FPCR
11196
11197 add.l &0xc,%sp
11198 fmovm.x &0x01,-(%sp)
11199 bra.b fadd_ovfl_ena_cont
11200
11201fadd_unfl:
11202 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
11203
11204 add.l &0xc,%sp
11205
11206 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11207
11208 fmov.l &rz_mode*0x10,%fpcr # set FPCR
11209 fmov.l &0x0,%fpsr # clear FPSR
11210
11211 fadd.x FP_SCR0(%a6),%fp0 # execute add
11212
11213 fmov.l &0x0,%fpcr # clear FPCR
11214 fmov.l %fpsr,%d1 # save status
11215
11216 or.l %d1,USER_FPSR(%a6) # save INEX,N
11217
11218 mov.b FPCR_ENABLE(%a6),%d1
11219 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
11220 bne.b fadd_unfl_ena # yes
11221
11222fadd_unfl_dis:
11223 fmovm.x &0x80,FP_SCR0(%a6) # store out result
11224
11225 lea FP_SCR0(%a6),%a0 # pass: result addr
11226 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
11227 bsr.l unf_res # calculate default result
11228 or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
11229 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
11230 mov.l (%sp)+,%d2 # restore d2
11231 rts
11232
11233fadd_unfl_ena:
11234 fmovm.x FP_SCR1(%a6),&0x40 # load dst op
11235
11236 mov.l L_SCR3(%a6),%d1
11237 andi.b &0xc0,%d1 # is precision extended?
11238 bne.b fadd_unfl_ena_sd # no; sgl or dbl
11239
11240 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11241
11242fadd_unfl_ena_cont:
11243 fmov.l &0x0,%fpsr # clear FPSR
11244
11245 fadd.x FP_SCR0(%a6),%fp1 # execute multiply
11246
11247 fmov.l &0x0,%fpcr # clear FPCR
11248
11249 fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
11250 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
11251 mov.l %d1,%d2 # make a copy
11252 andi.l &0x7fff,%d1 # strip sign
11253 andi.w &0x8000,%d2 # keep old sign
11254 sub.l %d0,%d1 # add scale factor
11255 addi.l &0x6000,%d1 # add new bias
11256 andi.w &0x7fff,%d1 # clear top bit
11257 or.w %d2,%d1 # concat sign,new exp
11258 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
11259 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
11260 bra.w fadd_unfl_dis
11261
11262fadd_unfl_ena_sd:
11263 mov.l L_SCR3(%a6),%d1
11264 andi.b &0x30,%d1 # use only rnd mode
11265 fmov.l %d1,%fpcr # set FPCR
11266
11267 bra.b fadd_unfl_ena_cont
11268
11269#
11270# result is equal to the smallest normalized number in the selected precision
11271# if the precision is extended, this result could not have come from an
11272# underflow that rounded up.
11273#
11274fadd_may_unfl:
11275 mov.l L_SCR3(%a6),%d1
11276 andi.b &0xc0,%d1
11277 beq.w fadd_normal # yes; no underflow occurred
11278
11279 mov.l 0x4(%sp),%d1 # extract hi(man)
11280 cmpi.l %d1,&0x80000000 # is hi(man) = 0x80000000?
11281 bne.w fadd_normal # no; no underflow occurred
11282
11283 tst.l 0x8(%sp) # is lo(man) = 0x0?
11284 bne.w fadd_normal # no; no underflow occurred
11285
11286 btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
11287 beq.w fadd_normal # no; no underflow occurred
11288
11289#
11290# ok, so now the result has a exponent equal to the smallest normalized
11291# exponent for the selected precision. also, the mantissa is equal to
11292# 0x8000000000000000 and this mantissa is the result of rounding non-zero
11293# g,r,s.
11294# now, we must determine whether the pre-rounded result was an underflow
11295# rounded "up" or a normalized number rounded "down".
11296# so, we do this be re-executing the add using RZ as the rounding mode and
11297# seeing if the new result is smaller or equal to the current result.
11298#
11299 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
11300
11301 mov.l L_SCR3(%a6),%d1
11302 andi.b &0xc0,%d1 # keep rnd prec
11303 ori.b &rz_mode*0x10,%d1 # insert rnd mode
11304 fmov.l %d1,%fpcr # set FPCR
11305 fmov.l &0x0,%fpsr # clear FPSR
11306
11307 fadd.x FP_SCR0(%a6),%fp1 # execute add
11308
11309 fmov.l &0x0,%fpcr # clear FPCR
11310
11311 fabs.x %fp0 # compare absolute values
11312 fabs.x %fp1
11313 fcmp.x %fp0,%fp1 # is first result > second?
11314
11315 fbgt.w fadd_unfl # yes; it's an underflow
11316 bra.w fadd_normal # no; it's not an underflow
11317
11318##########################################################################
11319
11320#
11321# Add: inputs are not both normalized; what are they?
11322#
11323fadd_not_norm:
11324 mov.w (tbl_fadd_op.b,%pc,%d1.w*2),%d1
11325 jmp (tbl_fadd_op.b,%pc,%d1.w*1)
11326
11327 swbeg &48
11328tbl_fadd_op:
11329 short fadd_norm - tbl_fadd_op # NORM + NORM
11330 short fadd_zero_src - tbl_fadd_op # NORM + ZERO
11331 short fadd_inf_src - tbl_fadd_op # NORM + INF
11332 short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
11333 short fadd_norm - tbl_fadd_op # NORM + DENORM
11334 short fadd_res_snan - tbl_fadd_op # NORM + SNAN
11335 short tbl_fadd_op - tbl_fadd_op #
11336 short tbl_fadd_op - tbl_fadd_op #
11337
11338 short fadd_zero_dst - tbl_fadd_op # ZERO + NORM
11339 short fadd_zero_2 - tbl_fadd_op # ZERO + ZERO
11340 short fadd_inf_src - tbl_fadd_op # ZERO + INF
11341 short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
11342 short fadd_zero_dst - tbl_fadd_op # ZERO + DENORM
11343 short fadd_res_snan - tbl_fadd_op # NORM + SNAN
11344 short tbl_fadd_op - tbl_fadd_op #
11345 short tbl_fadd_op - tbl_fadd_op #
11346
11347 short fadd_inf_dst - tbl_fadd_op # INF + NORM
11348 short fadd_inf_dst - tbl_fadd_op # INF + ZERO
11349 short fadd_inf_2 - tbl_fadd_op # INF + INF
11350 short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
11351 short fadd_inf_dst - tbl_fadd_op # INF + DENORM
11352 short fadd_res_snan - tbl_fadd_op # NORM + SNAN
11353 short tbl_fadd_op - tbl_fadd_op #
11354 short tbl_fadd_op - tbl_fadd_op #
11355
11356 short fadd_res_qnan - tbl_fadd_op # QNAN + NORM
11357 short fadd_res_qnan - tbl_fadd_op # QNAN + ZERO
11358 short fadd_res_qnan - tbl_fadd_op # QNAN + INF
11359 short fadd_res_qnan - tbl_fadd_op # QNAN + QNAN
11360 short fadd_res_qnan - tbl_fadd_op # QNAN + DENORM
11361 short fadd_res_snan - tbl_fadd_op # QNAN + SNAN
11362 short tbl_fadd_op - tbl_fadd_op #
11363 short tbl_fadd_op - tbl_fadd_op #
11364
11365 short fadd_norm - tbl_fadd_op # DENORM + NORM
11366 short fadd_zero_src - tbl_fadd_op # DENORM + ZERO
11367 short fadd_inf_src - tbl_fadd_op # DENORM + INF
11368 short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
11369 short fadd_norm - tbl_fadd_op # DENORM + DENORM
11370 short fadd_res_snan - tbl_fadd_op # NORM + SNAN
11371 short tbl_fadd_op - tbl_fadd_op #
11372 short tbl_fadd_op - tbl_fadd_op #
11373
11374 short fadd_res_snan - tbl_fadd_op # SNAN + NORM
11375 short fadd_res_snan - tbl_fadd_op # SNAN + ZERO
11376 short fadd_res_snan - tbl_fadd_op # SNAN + INF
11377 short fadd_res_snan - tbl_fadd_op # SNAN + QNAN
11378 short fadd_res_snan - tbl_fadd_op # SNAN + DENORM
11379 short fadd_res_snan - tbl_fadd_op # SNAN + SNAN
11380 short tbl_fadd_op - tbl_fadd_op #
11381 short tbl_fadd_op - tbl_fadd_op #
11382
11383fadd_res_qnan:
11384 bra.l res_qnan
11385fadd_res_snan:
11386 bra.l res_snan
11387
11388#
11389# both operands are ZEROes
11390#
11391fadd_zero_2:
11392 mov.b SRC_EX(%a0),%d0 # are the signs opposite
11393 mov.b DST_EX(%a1),%d1
11394 eor.b %d0,%d1
11395 bmi.w fadd_zero_2_chk_rm # weed out (-ZERO)+(+ZERO)
11396
11397# the signs are the same. so determine whether they are positive or negative
11398# and return the appropriately signed zero.
11399 tst.b %d0 # are ZEROes positive or negative?
11400 bmi.b fadd_zero_rm # negative
11401 fmov.s &0x00000000,%fp0 # return +ZERO
11402 mov.b &z_bmask,FPSR_CC(%a6) # set Z
11403 rts
11404
11405#
11406# the ZEROes have opposite signs:
11407# - therefore, we return +ZERO if the rounding modes are RN,RZ, or RP.
11408# - -ZERO is returned in the case of RM.
11409#
11410fadd_zero_2_chk_rm:
11411 mov.b 3+L_SCR3(%a6),%d1
11412 andi.b &0x30,%d1 # extract rnd mode
11413 cmpi.b %d1,&rm_mode*0x10 # is rnd mode == RM?
11414 beq.b fadd_zero_rm # yes
11415 fmov.s &0x00000000,%fp0 # return +ZERO
11416 mov.b &z_bmask,FPSR_CC(%a6) # set Z
11417 rts
11418
11419fadd_zero_rm:
11420 fmov.s &0x80000000,%fp0 # return -ZERO
11421 mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set NEG/Z
11422 rts
11423
11424#
11425# one operand is a ZERO and the other is a DENORM or NORM. scale
11426# the DENORM or NORM and jump to the regular fadd routine.
11427#
11428fadd_zero_dst:
11429 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
11430 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
11431 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
11432 bsr.l scale_to_zero_src # scale the operand
11433 clr.w FP_SCR1_EX(%a6)
11434 clr.l FP_SCR1_HI(%a6)
11435 clr.l FP_SCR1_LO(%a6)
11436 bra.w fadd_zero_entry # go execute fadd
11437
11438fadd_zero_src:
11439 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
11440 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
11441 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
11442 bsr.l scale_to_zero_dst # scale the operand
11443 clr.w FP_SCR0_EX(%a6)
11444 clr.l FP_SCR0_HI(%a6)
11445 clr.l FP_SCR0_LO(%a6)
11446 bra.w fadd_zero_entry # go execute fadd
11447
11448#
11449# both operands are INFs. an OPERR will result if the INFs have
11450# different signs. else, an INF of the same sign is returned
11451#
11452fadd_inf_2:
11453 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
11454 mov.b DST_EX(%a1),%d1
11455 eor.b %d1,%d0
11456 bmi.l res_operr # weed out (-INF)+(+INF)
11457
11458# ok, so it's not an OPERR. but, we do have to remember to return the
11459# src INF since that's where the 881/882 gets the j-bit from...
11460
11461#
11462# operands are INF and one of {ZERO, INF, DENORM, NORM}
11463#
11464fadd_inf_src:
11465 fmovm.x SRC(%a0),&0x80 # return src INF
11466 tst.b SRC_EX(%a0) # is INF positive?
11467 bpl.b fadd_inf_done # yes; we're done
11468 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
11469 rts
11470
11471#
11472# operands are INF and one of {ZERO, INF, DENORM, NORM}
11473#
11474fadd_inf_dst:
11475 fmovm.x DST(%a1),&0x80 # return dst INF
11476 tst.b DST_EX(%a1) # is INF positive?
11477 bpl.b fadd_inf_done # yes; we're done
11478 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
11479 rts
11480
11481fadd_inf_done:
11482 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
11483 rts
11484
11485#########################################################################
11486# XDEF **************************************************************** #
11487# fsub(): emulates the fsub instruction #
11488# fssub(): emulates the fssub instruction #
11489# fdsub(): emulates the fdsub instruction #
11490# #
11491# XREF **************************************************************** #
11492# addsub_scaler2() - scale the operands so they won't take exc #
11493# ovf_res() - return default overflow result #
11494# unf_res() - return default underflow result #
11495# res_qnan() - set QNAN result #
11496# res_snan() - set SNAN result #
11497# res_operr() - set OPERR result #
11498# scale_to_zero_src() - set src operand exponent equal to zero #
11499# scale_to_zero_dst() - set dst operand exponent equal to zero #
11500# #
11501# INPUT *************************************************************** #
11502# a0 = pointer to extended precision source operand #
11503# a1 = pointer to extended precision destination operand #
11504# #
11505# OUTPUT ************************************************************** #
11506# fp0 = result #
11507# fp1 = EXOP (if exception occurred) #
11508# #
11509# ALGORITHM *********************************************************** #
11510# Handle NANs, infinities, and zeroes as special cases. Divide #
11511# norms into extended, single, and double precision. #
11512# Do subtraction after scaling exponents such that exception won't#
11513# occur. Then, check result exponent to see if exception would have #
11514# occurred. If so, return default result and maybe EXOP. Else, insert #
11515# the correct result exponent and return. Set FPSR bits as appropriate. #
11516# #
11517#########################################################################
11518
11519 global fssub
11520fssub:
11521 andi.b &0x30,%d0 # clear rnd prec
11522 ori.b &s_mode*0x10,%d0 # insert sgl prec
11523 bra.b fsub
11524
11525 global fdsub
11526fdsub:
11527 andi.b &0x30,%d0 # clear rnd prec
11528 ori.b &d_mode*0x10,%d0 # insert dbl prec
11529
11530 global fsub
11531fsub:
11532 mov.l %d0,L_SCR3(%a6) # store rnd info
11533
11534 clr.w %d1
11535 mov.b DTAG(%a6),%d1
11536 lsl.b &0x3,%d1
11537 or.b STAG(%a6),%d1 # combine src tags
11538
11539 bne.w fsub_not_norm # optimize on non-norm input
11540
11541#
11542# SUB: norms and denorms
11543#
11544fsub_norm:
11545 bsr.l addsub_scaler2 # scale exponents
11546
11547fsub_zero_entry:
11548 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11549
11550 fmov.l &0x0,%fpsr # clear FPSR
11551 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11552
11553 fsub.x FP_SCR0(%a6),%fp0 # execute subtract
11554
11555 fmov.l &0x0,%fpcr # clear FPCR
11556 fmov.l %fpsr,%d1 # fetch INEX2, N, Z
11557
11558 or.l %d1,USER_FPSR(%a6) # save exc and ccode bits
11559
11560 fbeq.w fsub_zero_exit # if result zero, end now
11561
11562 mov.l %d2,-(%sp) # save d2
11563
11564 fmovm.x &0x01,-(%sp) # save result to stack
11565
11566 mov.w 2+L_SCR3(%a6),%d1
11567 lsr.b &0x6,%d1
11568
11569 mov.w (%sp),%d2 # fetch new exponent
11570 andi.l &0x7fff,%d2 # strip sign
11571 sub.l %d0,%d2 # add scale factor
11572
11573 cmp.l %d2,(tbl_fsub_ovfl.b,%pc,%d1.w*4) # is it an overflow?
11574 bge.b fsub_ovfl # yes
11575
11576 cmp.l %d2,(tbl_fsub_unfl.b,%pc,%d1.w*4) # is it an underflow?
11577 blt.w fsub_unfl # yes
11578 beq.w fsub_may_unfl # maybe; go find out
11579
11580fsub_normal:
11581 mov.w (%sp),%d1
11582 andi.w &0x8000,%d1 # keep sign
11583 or.w %d2,%d1 # insert new exponent
11584 mov.w %d1,(%sp) # insert new exponent
11585
11586 fmovm.x (%sp)+,&0x80 # return result in fp0
11587
11588 mov.l (%sp)+,%d2 # restore d2
11589 rts
11590
11591fsub_zero_exit:
11592# fmov.s &0x00000000,%fp0 # return zero in fp0
11593 rts
11594
11595tbl_fsub_ovfl:
11596 long 0x7fff # ext ovfl
11597 long 0x407f # sgl ovfl
11598 long 0x43ff # dbl ovfl
11599
11600tbl_fsub_unfl:
11601 long 0x0000 # ext unfl
11602 long 0x3f81 # sgl unfl
11603 long 0x3c01 # dbl unfl
11604
11605fsub_ovfl:
11606 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
11607
11608 mov.b FPCR_ENABLE(%a6),%d1
11609 andi.b &0x13,%d1 # is OVFL or INEX enabled?
11610 bne.b fsub_ovfl_ena # yes
11611
11612 add.l &0xc,%sp
11613fsub_ovfl_dis:
11614 btst &neg_bit,FPSR_CC(%a6) # is result negative?
11615 sne %d1 # set sign param accordingly
11616 mov.l L_SCR3(%a6),%d0 # pass prec:rnd
11617 bsr.l ovf_res # calculate default result
11618 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
11619 fmovm.x (%a0),&0x80 # return default result in fp0
11620 mov.l (%sp)+,%d2 # restore d2
11621 rts
11622
11623fsub_ovfl_ena:
11624 mov.b L_SCR3(%a6),%d1
11625 andi.b &0xc0,%d1 # is precision extended?
11626 bne.b fsub_ovfl_ena_sd # no
11627
11628fsub_ovfl_ena_cont:
11629 mov.w (%sp),%d1 # fetch {sgn,exp}
11630 andi.w &0x8000,%d1 # keep sign
11631 subi.l &0x6000,%d2 # subtract new bias
11632 andi.w &0x7fff,%d2 # clear top bit
11633 or.w %d2,%d1 # concat sign,exp
11634 mov.w %d1,(%sp) # insert new exponent
11635
11636 fmovm.x (%sp)+,&0x40 # return EXOP in fp1
11637 bra.b fsub_ovfl_dis
11638
11639fsub_ovfl_ena_sd:
11640 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11641
11642 mov.l L_SCR3(%a6),%d1
11643 andi.b &0x30,%d1 # clear rnd prec
11644 fmov.l %d1,%fpcr # set FPCR
11645
11646 fsub.x FP_SCR0(%a6),%fp0 # execute subtract
11647
11648 fmov.l &0x0,%fpcr # clear FPCR
11649
11650 add.l &0xc,%sp
11651 fmovm.x &0x01,-(%sp)
11652 bra.b fsub_ovfl_ena_cont
11653
11654fsub_unfl:
11655 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
11656
11657 add.l &0xc,%sp
11658
11659 fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11660
11661 fmov.l &rz_mode*0x10,%fpcr # set FPCR
11662 fmov.l &0x0,%fpsr # clear FPSR
11663
11664 fsub.x FP_SCR0(%a6),%fp0 # execute subtract
11665
11666 fmov.l &0x0,%fpcr # clear FPCR
11667 fmov.l %fpsr,%d1 # save status
11668
11669 or.l %d1,USER_FPSR(%a6)
11670
11671 mov.b FPCR_ENABLE(%a6),%d1
11672 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
11673 bne.b fsub_unfl_ena # yes
11674
11675fsub_unfl_dis:
11676 fmovm.x &0x80,FP_SCR0(%a6) # store out result
11677
11678 lea FP_SCR0(%a6),%a0 # pass: result addr
11679 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
11680 bsr.l unf_res # calculate default result
11681 or.b %d0,FPSR_CC(%a6) # 'Z' may have been set
11682 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
11683 mov.l (%sp)+,%d2 # restore d2
11684 rts
11685
11686fsub_unfl_ena:
11687 fmovm.x FP_SCR1(%a6),&0x40
11688
11689 mov.l L_SCR3(%a6),%d1
11690 andi.b &0xc0,%d1 # is precision extended?
11691 bne.b fsub_unfl_ena_sd # no
11692
11693 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11694
11695fsub_unfl_ena_cont:
11696 fmov.l &0x0,%fpsr # clear FPSR
11697
11698 fsub.x FP_SCR0(%a6),%fp1 # execute subtract
11699
11700 fmov.l &0x0,%fpcr # clear FPCR
11701
11702 fmovm.x &0x40,FP_SCR0(%a6) # store result to stack
11703 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
11704 mov.l %d1,%d2 # make a copy
11705 andi.l &0x7fff,%d1 # strip sign
11706 andi.w &0x8000,%d2 # keep old sign
11707 sub.l %d0,%d1 # add scale factor
11708 addi.l &0x6000,%d1 # subtract new bias
11709 andi.w &0x7fff,%d1 # clear top bit
11710 or.w %d2,%d1 # concat sgn,exp
11711 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
11712 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
11713 bra.w fsub_unfl_dis
11714
11715fsub_unfl_ena_sd:
11716 mov.l L_SCR3(%a6),%d1
11717 andi.b &0x30,%d1 # clear rnd prec
11718 fmov.l %d1,%fpcr # set FPCR
11719
11720 bra.b fsub_unfl_ena_cont
11721
11722#
11723# result is equal to the smallest normalized number in the selected precision
11724# if the precision is extended, this result could not have come from an
11725# underflow that rounded up.
11726#
11727fsub_may_unfl:
11728 mov.l L_SCR3(%a6),%d1
11729 andi.b &0xc0,%d1 # fetch rnd prec
11730 beq.w fsub_normal # yes; no underflow occurred
11731
11732 mov.l 0x4(%sp),%d1
11733 cmpi.l %d1,&0x80000000 # is hi(man) = 0x80000000?
11734 bne.w fsub_normal # no; no underflow occurred
11735
11736 tst.l 0x8(%sp) # is lo(man) = 0x0?
11737 bne.w fsub_normal # no; no underflow occurred
11738
11739 btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
11740 beq.w fsub_normal # no; no underflow occurred
11741
11742#
11743# ok, so now the result has a exponent equal to the smallest normalized
11744# exponent for the selected precision. also, the mantissa is equal to
11745# 0x8000000000000000 and this mantissa is the result of rounding non-zero
11746# g,r,s.
11747# now, we must determine whether the pre-rounded result was an underflow
11748# rounded "up" or a normalized number rounded "down".
11749# so, we do this be re-executing the add using RZ as the rounding mode and
11750# seeing if the new result is smaller or equal to the current result.
11751#
11752 fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
11753
11754 mov.l L_SCR3(%a6),%d1
11755 andi.b &0xc0,%d1 # keep rnd prec
11756 ori.b &rz_mode*0x10,%d1 # insert rnd mode
11757 fmov.l %d1,%fpcr # set FPCR
11758 fmov.l &0x0,%fpsr # clear FPSR
11759
11760 fsub.x FP_SCR0(%a6),%fp1 # execute subtract
11761
11762 fmov.l &0x0,%fpcr # clear FPCR
11763
11764 fabs.x %fp0 # compare absolute values
11765 fabs.x %fp1
11766 fcmp.x %fp0,%fp1 # is first result > second?
11767
11768 fbgt.w fsub_unfl # yes; it's an underflow
11769 bra.w fsub_normal # no; it's not an underflow
11770
11771##########################################################################
11772
11773#
11774# Sub: inputs are not both normalized; what are they?
11775#
11776fsub_not_norm:
11777 mov.w (tbl_fsub_op.b,%pc,%d1.w*2),%d1
11778 jmp (tbl_fsub_op.b,%pc,%d1.w*1)
11779
11780 swbeg &48
11781tbl_fsub_op:
11782 short fsub_norm - tbl_fsub_op # NORM - NORM
11783 short fsub_zero_src - tbl_fsub_op # NORM - ZERO
11784 short fsub_inf_src - tbl_fsub_op # NORM - INF
11785 short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
11786 short fsub_norm - tbl_fsub_op # NORM - DENORM
11787 short fsub_res_snan - tbl_fsub_op # NORM - SNAN
11788 short tbl_fsub_op - tbl_fsub_op #
11789 short tbl_fsub_op - tbl_fsub_op #
11790
11791 short fsub_zero_dst - tbl_fsub_op # ZERO - NORM
11792 short fsub_zero_2 - tbl_fsub_op # ZERO - ZERO
11793 short fsub_inf_src - tbl_fsub_op # ZERO - INF
11794 short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
11795 short fsub_zero_dst - tbl_fsub_op # ZERO - DENORM
11796 short fsub_res_snan - tbl_fsub_op # NORM - SNAN
11797 short tbl_fsub_op - tbl_fsub_op #
11798 short tbl_fsub_op - tbl_fsub_op #
11799
11800 short fsub_inf_dst - tbl_fsub_op # INF - NORM
11801 short fsub_inf_dst - tbl_fsub_op # INF - ZERO
11802 short fsub_inf_2 - tbl_fsub_op # INF - INF
11803 short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
11804 short fsub_inf_dst - tbl_fsub_op # INF - DENORM
11805 short fsub_res_snan - tbl_fsub_op # NORM - SNAN
11806 short tbl_fsub_op - tbl_fsub_op #
11807 short tbl_fsub_op - tbl_fsub_op #
11808
11809 short fsub_res_qnan - tbl_fsub_op # QNAN - NORM
11810 short fsub_res_qnan - tbl_fsub_op # QNAN - ZERO
11811 short fsub_res_qnan - tbl_fsub_op # QNAN - INF
11812 short fsub_res_qnan - tbl_fsub_op # QNAN - QNAN
11813 short fsub_res_qnan - tbl_fsub_op # QNAN - DENORM
11814 short fsub_res_snan - tbl_fsub_op # QNAN - SNAN
11815 short tbl_fsub_op - tbl_fsub_op #
11816 short tbl_fsub_op - tbl_fsub_op #
11817
11818 short fsub_norm - tbl_fsub_op # DENORM - NORM
11819 short fsub_zero_src - tbl_fsub_op # DENORM - ZERO
11820 short fsub_inf_src - tbl_fsub_op # DENORM - INF
11821 short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
11822 short fsub_norm - tbl_fsub_op # DENORM - DENORM
11823 short fsub_res_snan - tbl_fsub_op # NORM - SNAN
11824 short tbl_fsub_op - tbl_fsub_op #
11825 short tbl_fsub_op - tbl_fsub_op #
11826
11827 short fsub_res_snan - tbl_fsub_op # SNAN - NORM
11828 short fsub_res_snan - tbl_fsub_op # SNAN - ZERO
11829 short fsub_res_snan - tbl_fsub_op # SNAN - INF
11830 short fsub_res_snan - tbl_fsub_op # SNAN - QNAN
11831 short fsub_res_snan - tbl_fsub_op # SNAN - DENORM
11832 short fsub_res_snan - tbl_fsub_op # SNAN - SNAN
11833 short tbl_fsub_op - tbl_fsub_op #
11834 short tbl_fsub_op - tbl_fsub_op #
11835
11836fsub_res_qnan:
11837 bra.l res_qnan
11838fsub_res_snan:
11839 bra.l res_snan
11840
11841#
11842# both operands are ZEROes
11843#
11844fsub_zero_2:
11845 mov.b SRC_EX(%a0),%d0
11846 mov.b DST_EX(%a1),%d1
11847 eor.b %d1,%d0
11848 bpl.b fsub_zero_2_chk_rm
11849
11850# the signs are opposite, so, return a ZERO w/ the sign of the dst ZERO
11851 tst.b %d0 # is dst negative?
11852 bmi.b fsub_zero_2_rm # yes
11853 fmov.s &0x00000000,%fp0 # no; return +ZERO
11854 mov.b &z_bmask,FPSR_CC(%a6) # set Z
11855 rts
11856
11857#
11858# the ZEROes have the same signs:
11859# - therefore, we return +ZERO if the rounding mode is RN,RZ, or RP
11860# - -ZERO is returned in the case of RM.
11861#
11862fsub_zero_2_chk_rm:
11863 mov.b 3+L_SCR3(%a6),%d1
11864 andi.b &0x30,%d1 # extract rnd mode
11865 cmpi.b %d1,&rm_mode*0x10 # is rnd mode = RM?
11866 beq.b fsub_zero_2_rm # yes
11867 fmov.s &0x00000000,%fp0 # no; return +ZERO
11868 mov.b &z_bmask,FPSR_CC(%a6) # set Z
11869 rts
11870
11871fsub_zero_2_rm:
11872 fmov.s &0x80000000,%fp0 # return -ZERO
11873 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/NEG
11874 rts
11875
11876#
11877# one operand is a ZERO and the other is a DENORM or a NORM.
11878# scale the DENORM or NORM and jump to the regular fsub routine.
11879#
11880fsub_zero_dst:
11881 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
11882 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
11883 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
11884 bsr.l scale_to_zero_src # scale the operand
11885 clr.w FP_SCR1_EX(%a6)
11886 clr.l FP_SCR1_HI(%a6)
11887 clr.l FP_SCR1_LO(%a6)
11888 bra.w fsub_zero_entry # go execute fsub
11889
11890fsub_zero_src:
11891 mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
11892 mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
11893 mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
11894 bsr.l scale_to_zero_dst # scale the operand
11895 clr.w FP_SCR0_EX(%a6)
11896 clr.l FP_SCR0_HI(%a6)
11897 clr.l FP_SCR0_LO(%a6)
11898 bra.w fsub_zero_entry # go execute fsub
11899
11900#
11901# both operands are INFs. an OPERR will result if the INFs have the
11902# same signs. else,
11903#
11904fsub_inf_2:
11905 mov.b SRC_EX(%a0),%d0 # exclusive or the signs
11906 mov.b DST_EX(%a1),%d1
11907 eor.b %d1,%d0
11908 bpl.l res_operr # weed out (-INF)+(+INF)
11909
11910# ok, so it's not an OPERR. but we do have to remember to return
11911# the src INF since that's where the 881/882 gets the j-bit.
11912
11913fsub_inf_src:
11914 fmovm.x SRC(%a0),&0x80 # return src INF
11915 fneg.x %fp0 # invert sign
11916 fbge.w fsub_inf_done # sign is now positive
11917 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
11918 rts
11919
11920fsub_inf_dst:
11921 fmovm.x DST(%a1),&0x80 # return dst INF
11922 tst.b DST_EX(%a1) # is INF negative?
11923 bpl.b fsub_inf_done # no
11924 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
11925 rts
11926
11927fsub_inf_done:
11928 mov.b &inf_bmask,FPSR_CC(%a6) # set INF
11929 rts
11930
11931#########################################################################
11932# XDEF **************************************************************** #
11933# fsqrt(): emulates the fsqrt instruction #
11934# fssqrt(): emulates the fssqrt instruction #
11935# fdsqrt(): emulates the fdsqrt instruction #
11936# #
11937# XREF **************************************************************** #
11938# scale_sqrt() - scale the source operand #
11939# unf_res() - return default underflow result #
11940# ovf_res() - return default overflow result #
11941# res_qnan_1op() - return QNAN result #
11942# res_snan_1op() - return SNAN result #
11943# #
11944# INPUT *************************************************************** #
11945# a0 = pointer to extended precision source operand #
11946# d0 rnd prec,mode #
11947# #
11948# OUTPUT ************************************************************** #
11949# fp0 = result #
11950# fp1 = EXOP (if exception occurred) #
11951# #
11952# ALGORITHM *********************************************************** #
11953# Handle NANs, infinities, and zeroes as special cases. Divide #
11954# norms/denorms into ext/sgl/dbl precision. #
11955# For norms/denorms, scale the exponents such that a sqrt #
11956# instruction won't cause an exception. Use the regular fsqrt to #
11957# compute a result. Check if the regular operands would have taken #
11958# an exception. If so, return the default overflow/underflow result #
11959# and return the EXOP if exceptions are enabled. Else, scale the #
11960# result operand to the proper exponent. #
11961# #
11962#########################################################################
11963
11964 global fssqrt
11965fssqrt:
11966 andi.b &0x30,%d0 # clear rnd prec
11967 ori.b &s_mode*0x10,%d0 # insert sgl precision
11968 bra.b fsqrt
11969
11970 global fdsqrt
11971fdsqrt:
11972 andi.b &0x30,%d0 # clear rnd prec
11973 ori.b &d_mode*0x10,%d0 # insert dbl precision
11974
11975 global fsqrt
11976fsqrt:
11977 mov.l %d0,L_SCR3(%a6) # store rnd info
11978 clr.w %d1
11979 mov.b STAG(%a6),%d1
11980 bne.w fsqrt_not_norm # optimize on non-norm input
11981
11982#
11983# SQUARE ROOT: norms and denorms ONLY!
11984#
11985fsqrt_norm:
11986 tst.b SRC_EX(%a0) # is operand negative?
11987 bmi.l res_operr # yes
11988
11989 andi.b &0xc0,%d0 # is precision extended?
11990 bne.b fsqrt_not_ext # no; go handle sgl or dbl
11991
11992 fmov.l L_SCR3(%a6),%fpcr # set FPCR
11993 fmov.l &0x0,%fpsr # clear FPSR
11994
11995 fsqrt.x (%a0),%fp0 # execute square root
11996
11997 fmov.l %fpsr,%d1
11998 or.l %d1,USER_FPSR(%a6) # set N,INEX
11999
12000 rts
12001
12002fsqrt_denorm:
12003 tst.b SRC_EX(%a0) # is operand negative?
12004 bmi.l res_operr # yes
12005
12006 andi.b &0xc0,%d0 # is precision extended?
12007 bne.b fsqrt_not_ext # no; go handle sgl or dbl
12008
12009 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12010 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12011 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12012
12013 bsr.l scale_sqrt # calculate scale factor
12014
12015 bra.w fsqrt_sd_normal
12016
12017#
12018# operand is either single or double
12019#
12020fsqrt_not_ext:
12021 cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
12022 bne.w fsqrt_dbl
12023
12024#
12025# operand is to be rounded to single precision
12026#
12027fsqrt_sgl:
12028 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12029 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12030 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12031
12032 bsr.l scale_sqrt # calculate scale factor
12033
12034 cmpi.l %d0,&0x3fff-0x3f81 # will move in underflow?
12035 beq.w fsqrt_sd_may_unfl
12036 bgt.w fsqrt_sd_unfl # yes; go handle underflow
12037 cmpi.l %d0,&0x3fff-0x407f # will move in overflow?
12038 beq.w fsqrt_sd_may_ovfl # maybe; go check
12039 blt.w fsqrt_sd_ovfl # yes; go handle overflow
12040
12041#
12042# operand will NOT overflow or underflow when moved in to the fp reg file
12043#
12044fsqrt_sd_normal:
12045 fmov.l &0x0,%fpsr # clear FPSR
12046 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12047
12048 fsqrt.x FP_SCR0(%a6),%fp0 # perform absolute
12049
12050 fmov.l %fpsr,%d1 # save FPSR
12051 fmov.l &0x0,%fpcr # clear FPCR
12052
12053 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12054
12055fsqrt_sd_normal_exit:
12056 mov.l %d2,-(%sp) # save d2
12057 fmovm.x &0x80,FP_SCR0(%a6) # store out result
12058 mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
12059 mov.l %d1,%d2 # make a copy
12060 andi.l &0x7fff,%d1 # strip sign
12061 sub.l %d0,%d1 # add scale factor
12062 andi.w &0x8000,%d2 # keep old sign
12063 or.w %d1,%d2 # concat old sign,new exp
12064 mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
12065 mov.l (%sp)+,%d2 # restore d2
12066 fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
12067 rts
12068
12069#
12070# operand is to be rounded to double precision
12071#
12072fsqrt_dbl:
12073 mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12074 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12075 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12076
12077 bsr.l scale_sqrt # calculate scale factor
12078
12079 cmpi.l %d0,&0x3fff-0x3c01 # will move in underflow?
12080 beq.w fsqrt_sd_may_unfl
12081 bgt.b fsqrt_sd_unfl # yes; go handle underflow
12082 cmpi.l %d0,&0x3fff-0x43ff # will move in overflow?
12083 beq.w fsqrt_sd_may_ovfl # maybe; go check
12084 blt.w fsqrt_sd_ovfl # yes; go handle overflow
12085 bra.w fsqrt_sd_normal # no; ho handle normalized op
12086
12087# we're on the line here and the distinguising characteristic is whether
12088# the exponent is 3fff or 3ffe. if it's 3ffe, then it's a safe number
12089# elsewise fall through to underflow.
12090fsqrt_sd_may_unfl:
12091 btst &0x0,1+FP_SCR0_EX(%a6) # is exponent 0x3fff?
12092 bne.w fsqrt_sd_normal # yes, so no underflow
12093
12094#
12095# operand WILL underflow when moved in to the fp register file
12096#
12097fsqrt_sd_unfl:
12098 bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
12099
12100 fmov.l &rz_mode*0x10,%fpcr # set FPCR
12101 fmov.l &0x0,%fpsr # clear FPSR
12102
12103 fsqrt.x FP_SCR0(%a6),%fp0 # execute square root
12104
12105 fmov.l %fpsr,%d1 # save status
12106 fmov.l &0x0,%fpcr # clear FPCR
12107
12108 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12109
12110# if underflow or inexact is enabled, go calculate EXOP first.
12111 mov.b FPCR_ENABLE(%a6),%d1
12112 andi.b &0x0b,%d1 # is UNFL or INEX enabled?
12113 bne.b fsqrt_sd_unfl_ena # yes
12114
12115fsqrt_sd_unfl_dis:
12116 fmovm.x &0x80,FP_SCR0(%a6) # store out result
12117
12118 lea FP_SCR0(%a6),%a0 # pass: result addr
12119 mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
12120 bsr.l unf_res # calculate default result
12121 or.b %d0,FPSR_CC(%a6) # set possible 'Z' ccode
12122 fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
12123 rts
12124
12125#
12126# operand will underflow AND underflow is enabled.
12127# therefore, we must return the result rounded to extended precision.
12128#
12129fsqrt_sd_unfl_ena:
12130 mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
12131 mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
12132 mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
12133
12134 mov.l %d2,-(%sp) # save d2
12135 mov.l %d1,%d2 # make a copy
12136 andi.l &0x7fff,%d1 # strip sign
12137 andi.w &0x8000,%d2 # keep old sign
12138 sub.l %d0,%d1 # subtract scale factor
12139 addi.l &0x6000,%d1 # add new bias
12140 andi.w &0x7fff,%d1
12141 or.w %d2,%d1 # concat new sign,new exp
12142 mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
12143 fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
12144 mov.l (%sp)+,%d2 # restore d2
12145 bra.b fsqrt_sd_unfl_dis
12146
12147#
12148# operand WILL overflow.
12149#
12150fsqrt_sd_ovfl:
12151 fmov.l &0x0,%fpsr # clear FPSR
12152 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12153
12154 fsqrt.x FP_SCR0(%a6),%fp0 # perform square root
12155
12156 fmov.l &0x0,%fpcr # clear FPCR
12157 fmov.l %fpsr,%d1 # save FPSR
12158
12159 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12160
12161fsqrt_sd_ovfl_tst:
12162 or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
12163
12164 mov.b FPCR_ENABLE(%a6),%d1
12165 andi.b &0x13,%d1 # is OVFL or INEX enabled?
12166 bne.b fsqrt_sd_ovfl_ena # yes
12167
12168#
12169# OVFL is not enabled; therefore, we must create the default result by
12170# calling ovf_res().
12171#
12172fsqrt_sd_ovfl_dis:
12173 btst &neg_bit,FPSR_CC(%a6) # is result negative?
12174 sne %d1 # set sign param accordingly
12175 mov.l L_SCR3(%a6),%d0 # pass: prec,mode
12176 bsr.l ovf_res # calculate default result
12177 or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
12178 fmovm.x (%a0),&0x80 # return default result in fp0
12179 rts
12180
12181#
12182# OVFL is enabled.
12183# the INEX2 bit has already been updated by the round to the correct precision.
12184# now, round to extended(and don't alter the FPSR).
12185#
12186fsqrt_sd_ovfl_ena:
12187 mov.l %d2,-(%sp) # save d2
12188 mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
12189 mov.l %d1,%d2 # make a copy
12190 andi.l &0x7fff,%d1 # strip sign
12191 andi.w &0x8000,%d2 # keep old sign
12192 sub.l %d0,%d1 # add scale factor
12193 subi.l &0x6000,%d1 # subtract bias
12194 andi.w &0x7fff,%d1
12195 or.w %d2,%d1 # concat sign,exp
12196 mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
12197 fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
12198 mov.l (%sp)+,%d2 # restore d2
12199 bra.b fsqrt_sd_ovfl_dis
12200
12201#
12202# the move in MAY underflow. so...
12203#
12204fsqrt_sd_may_ovfl:
12205 btst &0x0,1+FP_SCR0_EX(%a6) # is exponent 0x3fff?
12206 bne.w fsqrt_sd_ovfl # yes, so overflow
12207
12208 fmov.l &0x0,%fpsr # clear FPSR
12209 fmov.l L_SCR3(%a6),%fpcr # set FPCR
12210
12211 fsqrt.x FP_SCR0(%a6),%fp0 # perform absolute
12212
12213 fmov.l %fpsr,%d1 # save status
12214 fmov.l &0x0,%fpcr # clear FPCR
12215
12216 or.l %d1,USER_FPSR(%a6) # save INEX2,N
12217
12218 fmov.x %fp0,%fp1 # make a copy of result
12219 fcmp.b %fp1,&0x1 # is |result| >= 1.b?
12220 fbge.w fsqrt_sd_ovfl_tst # yes; overflow has occurred
12221
12222# no, it didn't overflow; we have correct result
12223 bra.w fsqrt_sd_normal_exit
12224
12225##########################################################################
12226
12227#
12228# input is not normalized; what is it?
12229#
12230fsqrt_not_norm:
12231 cmpi.b %d1,&DENORM # weed out DENORM
12232 beq.w fsqrt_denorm
12233 cmpi.b %d1,&ZERO # weed out ZERO
12234 beq.b fsqrt_zero
12235 cmpi.b %d1,&INF # weed out INF
12236 beq.b fsqrt_inf
12237 cmpi.b %d1,&SNAN # weed out SNAN
12238 beq.l res_snan_1op
12239 bra.l res_qnan_1op
12240
12241#
12242# fsqrt(+0) = +0
12243# fsqrt(-0) = -0
12244# fsqrt(+INF) = +INF
12245# fsqrt(-INF) = OPERR
12246#
12247fsqrt_zero:
12248 tst.b SRC_EX(%a0) # is ZERO positive or negative?
12249 bmi.b fsqrt_zero_m # negative
12250fsqrt_zero_p:
12251 fmov.s &0x00000000,%fp0 # return +ZERO
12252 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
12253 rts
12254fsqrt_zero_m:
12255 fmov.s &0x80000000,%fp0 # return -ZERO
12256 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
12257 rts
12258
12259fsqrt_inf:
12260 tst.b SRC_EX(%a0) # is INF positive or negative?
12261 bmi.l res_operr # negative
12262fsqrt_inf_p:
12263 fmovm.x SRC(%a0),&0x80 # return +INF in fp0
12264 mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
12265 rts
12266
12267#########################################################################
12268# XDEF **************************************************************** #
12269# fetch_dreg(): fetch register according to index in d1 #
12270# #
12271# XREF **************************************************************** #
12272# None #
12273# #
12274# INPUT *************************************************************** #
12275# d1 = index of register to fetch from #
12276# #
12277# OUTPUT ************************************************************** #
12278# d0 = value of register fetched #
12279# #
12280# ALGORITHM *********************************************************** #
12281# According to the index value in d1 which can range from zero #
12282# to fifteen, load the corresponding register file value (where #
12283# address register indexes start at 8). D0/D1/A0/A1/A6/A7 are on the #
12284# stack. The rest should still be in their original places. #
12285# #
12286#########################################################################
12287
12288# this routine leaves d1 intact for subsequent store_dreg calls.
12289 global fetch_dreg
12290fetch_dreg:
12291 mov.w (tbl_fdreg.b,%pc,%d1.w*2),%d0
12292 jmp (tbl_fdreg.b,%pc,%d0.w*1)
12293
12294tbl_fdreg:
12295 short fdreg0 - tbl_fdreg
12296 short fdreg1 - tbl_fdreg
12297 short fdreg2 - tbl_fdreg
12298 short fdreg3 - tbl_fdreg
12299 short fdreg4 - tbl_fdreg
12300 short fdreg5 - tbl_fdreg
12301 short fdreg6 - tbl_fdreg
12302 short fdreg7 - tbl_fdreg
12303 short fdreg8 - tbl_fdreg
12304 short fdreg9 - tbl_fdreg
12305 short fdrega - tbl_fdreg
12306 short fdregb - tbl_fdreg
12307 short fdregc - tbl_fdreg
12308 short fdregd - tbl_fdreg
12309 short fdrege - tbl_fdreg
12310 short fdregf - tbl_fdreg
12311
12312fdreg0:
12313 mov.l EXC_DREGS+0x0(%a6),%d0
12314 rts
12315fdreg1:
12316 mov.l EXC_DREGS+0x4(%a6),%d0
12317 rts
12318fdreg2:
12319 mov.l %d2,%d0
12320 rts
12321fdreg3:
12322 mov.l %d3,%d0
12323 rts
12324fdreg4:
12325 mov.l %d4,%d0
12326 rts
12327fdreg5:
12328 mov.l %d5,%d0
12329 rts
12330fdreg6:
12331 mov.l %d6,%d0
12332 rts
12333fdreg7:
12334 mov.l %d7,%d0
12335 rts
12336fdreg8:
12337 mov.l EXC_DREGS+0x8(%a6),%d0
12338 rts
12339fdreg9:
12340 mov.l EXC_DREGS+0xc(%a6),%d0
12341 rts
12342fdrega:
12343 mov.l %a2,%d0
12344 rts
12345fdregb:
12346 mov.l %a3,%d0
12347 rts
12348fdregc:
12349 mov.l %a4,%d0
12350 rts
12351fdregd:
12352 mov.l %a5,%d0
12353 rts
12354fdrege:
12355 mov.l (%a6),%d0
12356 rts
12357fdregf:
12358 mov.l EXC_A7(%a6),%d0
12359 rts
12360
12361#########################################################################
12362# XDEF **************************************************************** #
12363# store_dreg_l(): store longword to data register specified by d1 #
12364# #
12365# XREF **************************************************************** #
12366# None #
12367# #
12368# INPUT *************************************************************** #
12369# d0 = longowrd value to store #
12370# d1 = index of register to fetch from #
12371# #
12372# OUTPUT ************************************************************** #
12373# (data register is updated) #
12374# #
12375# ALGORITHM *********************************************************** #
12376# According to the index value in d1, store the longword value #
12377# in d0 to the corresponding data register. D0/D1 are on the stack #
12378# while the rest are in their initial places. #
12379# #
12380#########################################################################
12381
12382 global store_dreg_l
12383store_dreg_l:
12384 mov.w (tbl_sdregl.b,%pc,%d1.w*2),%d1
12385 jmp (tbl_sdregl.b,%pc,%d1.w*1)
12386
12387tbl_sdregl:
12388 short sdregl0 - tbl_sdregl
12389 short sdregl1 - tbl_sdregl
12390 short sdregl2 - tbl_sdregl
12391 short sdregl3 - tbl_sdregl
12392 short sdregl4 - tbl_sdregl
12393 short sdregl5 - tbl_sdregl
12394 short sdregl6 - tbl_sdregl
12395 short sdregl7 - tbl_sdregl
12396
12397sdregl0:
12398 mov.l %d0,EXC_DREGS+0x0(%a6)
12399 rts
12400sdregl1:
12401 mov.l %d0,EXC_DREGS+0x4(%a6)
12402 rts
12403sdregl2:
12404 mov.l %d0,%d2
12405 rts
12406sdregl3:
12407 mov.l %d0,%d3
12408 rts
12409sdregl4:
12410 mov.l %d0,%d4
12411 rts
12412sdregl5:
12413 mov.l %d0,%d5
12414 rts
12415sdregl6:
12416 mov.l %d0,%d6
12417 rts
12418sdregl7:
12419 mov.l %d0,%d7
12420 rts
12421
12422#########################################################################
12423# XDEF **************************************************************** #
12424# store_dreg_w(): store word to data register specified by d1 #
12425# #
12426# XREF **************************************************************** #
12427# None #
12428# #
12429# INPUT *************************************************************** #
12430# d0 = word value to store #
12431# d1 = index of register to fetch from #
12432# #
12433# OUTPUT ************************************************************** #
12434# (data register is updated) #
12435# #
12436# ALGORITHM *********************************************************** #
12437# According to the index value in d1, store the word value #
12438# in d0 to the corresponding data register. D0/D1 are on the stack #
12439# while the rest are in their initial places. #
12440# #
12441#########################################################################
12442
12443 global store_dreg_w
12444store_dreg_w:
12445 mov.w (tbl_sdregw.b,%pc,%d1.w*2),%d1
12446 jmp (tbl_sdregw.b,%pc,%d1.w*1)
12447
12448tbl_sdregw:
12449 short sdregw0 - tbl_sdregw
12450 short sdregw1 - tbl_sdregw
12451 short sdregw2 - tbl_sdregw
12452 short sdregw3 - tbl_sdregw
12453 short sdregw4 - tbl_sdregw
12454 short sdregw5 - tbl_sdregw
12455 short sdregw6 - tbl_sdregw
12456 short sdregw7 - tbl_sdregw
12457
12458sdregw0:
12459 mov.w %d0,2+EXC_DREGS+0x0(%a6)
12460 rts
12461sdregw1:
12462 mov.w %d0,2+EXC_DREGS+0x4(%a6)
12463 rts
12464sdregw2:
12465 mov.w %d0,%d2
12466 rts
12467sdregw3:
12468 mov.w %d0,%d3
12469 rts
12470sdregw4:
12471 mov.w %d0,%d4
12472 rts
12473sdregw5:
12474 mov.w %d0,%d5
12475 rts
12476sdregw6:
12477 mov.w %d0,%d6
12478 rts
12479sdregw7:
12480 mov.w %d0,%d7
12481 rts
12482
12483#########################################################################
12484# XDEF **************************************************************** #
12485# store_dreg_b(): store byte to data register specified by d1 #
12486# #
12487# XREF **************************************************************** #
12488# None #
12489# #
12490# INPUT *************************************************************** #
12491# d0 = byte value to store #
12492# d1 = index of register to fetch from #
12493# #
12494# OUTPUT ************************************************************** #
12495# (data register is updated) #
12496# #
12497# ALGORITHM *********************************************************** #
12498# According to the index value in d1, store the byte value #
12499# in d0 to the corresponding data register. D0/D1 are on the stack #
12500# while the rest are in their initial places. #
12501# #
12502#########################################################################
12503
12504 global store_dreg_b
12505store_dreg_b:
12506 mov.w (tbl_sdregb.b,%pc,%d1.w*2),%d1
12507 jmp (tbl_sdregb.b,%pc,%d1.w*1)
12508
12509tbl_sdregb:
12510 short sdregb0 - tbl_sdregb
12511 short sdregb1 - tbl_sdregb
12512 short sdregb2 - tbl_sdregb
12513 short sdregb3 - tbl_sdregb
12514 short sdregb4 - tbl_sdregb
12515 short sdregb5 - tbl_sdregb
12516 short sdregb6 - tbl_sdregb
12517 short sdregb7 - tbl_sdregb
12518
12519sdregb0:
12520 mov.b %d0,3+EXC_DREGS+0x0(%a6)
12521 rts
12522sdregb1:
12523 mov.b %d0,3+EXC_DREGS+0x4(%a6)
12524 rts
12525sdregb2:
12526 mov.b %d0,%d2
12527 rts
12528sdregb3:
12529 mov.b %d0,%d3
12530 rts
12531sdregb4:
12532 mov.b %d0,%d4
12533 rts
12534sdregb5:
12535 mov.b %d0,%d5
12536 rts
12537sdregb6:
12538 mov.b %d0,%d6
12539 rts
12540sdregb7:
12541 mov.b %d0,%d7
12542 rts
12543
12544#########################################################################
12545# XDEF **************************************************************** #
12546# inc_areg(): increment an address register by the value in d0 #
12547# #
12548# XREF **************************************************************** #
12549# None #
12550# #
12551# INPUT *************************************************************** #
12552# d0 = amount to increment by #
12553# d1 = index of address register to increment #
12554# #
12555# OUTPUT ************************************************************** #
12556# (address register is updated) #
12557# #
12558# ALGORITHM *********************************************************** #
12559# Typically used for an instruction w/ a post-increment <ea>, #
12560# this routine adds the increment value in d0 to the address register #
12561# specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside #
12562# in their original places. #
12563# For a7, if the increment amount is one, then we have to #
12564# increment by two. For any a7 update, set the mia7_flag so that if #
12565# an access error exception occurs later in emulation, this address #
12566# register update can be undone. #
12567# #
12568#########################################################################
12569
12570 global inc_areg
12571inc_areg:
12572 mov.w (tbl_iareg.b,%pc,%d1.w*2),%d1
12573 jmp (tbl_iareg.b,%pc,%d1.w*1)
12574
12575tbl_iareg:
12576 short iareg0 - tbl_iareg
12577 short iareg1 - tbl_iareg
12578 short iareg2 - tbl_iareg
12579 short iareg3 - tbl_iareg
12580 short iareg4 - tbl_iareg
12581 short iareg5 - tbl_iareg
12582 short iareg6 - tbl_iareg
12583 short iareg7 - tbl_iareg
12584
12585iareg0: add.l %d0,EXC_DREGS+0x8(%a6)
12586 rts
12587iareg1: add.l %d0,EXC_DREGS+0xc(%a6)
12588 rts
12589iareg2: add.l %d0,%a2
12590 rts
12591iareg3: add.l %d0,%a3
12592 rts
12593iareg4: add.l %d0,%a4
12594 rts
12595iareg5: add.l %d0,%a5
12596 rts
12597iareg6: add.l %d0,(%a6)
12598 rts
12599iareg7: mov.b &mia7_flg,SPCOND_FLG(%a6)
12600 cmpi.b %d0,&0x1
12601 beq.b iareg7b
12602 add.l %d0,EXC_A7(%a6)
12603 rts
12604iareg7b:
12605 addq.l &0x2,EXC_A7(%a6)
12606 rts
12607
12608#########################################################################
12609# XDEF **************************************************************** #
12610# dec_areg(): decrement an address register by the value in d0 #
12611# #
12612# XREF **************************************************************** #
12613# None #
12614# #
12615# INPUT *************************************************************** #
12616# d0 = amount to decrement by #
12617# d1 = index of address register to decrement #
12618# #
12619# OUTPUT ************************************************************** #
12620# (address register is updated) #
12621# #
12622# ALGORITHM *********************************************************** #
12623# Typically used for an instruction w/ a pre-decrement <ea>, #
12624# this routine adds the decrement value in d0 to the address register #
12625# specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside #
12626# in their original places. #
12627# For a7, if the decrement amount is one, then we have to #
12628# decrement by two. For any a7 update, set the mda7_flag so that if #
12629# an access error exception occurs later in emulation, this address #
12630# register update can be undone. #
12631# #
12632#########################################################################
12633
12634 global dec_areg
12635dec_areg:
12636 mov.w (tbl_dareg.b,%pc,%d1.w*2),%d1
12637 jmp (tbl_dareg.b,%pc,%d1.w*1)
12638
12639tbl_dareg:
12640 short dareg0 - tbl_dareg
12641 short dareg1 - tbl_dareg
12642 short dareg2 - tbl_dareg
12643 short dareg3 - tbl_dareg
12644 short dareg4 - tbl_dareg
12645 short dareg5 - tbl_dareg
12646 short dareg6 - tbl_dareg
12647 short dareg7 - tbl_dareg
12648
12649dareg0: sub.l %d0,EXC_DREGS+0x8(%a6)
12650 rts
12651dareg1: sub.l %d0,EXC_DREGS+0xc(%a6)
12652 rts
12653dareg2: sub.l %d0,%a2
12654 rts
12655dareg3: sub.l %d0,%a3
12656 rts
12657dareg4: sub.l %d0,%a4
12658 rts
12659dareg5: sub.l %d0,%a5
12660 rts
12661dareg6: sub.l %d0,(%a6)
12662 rts
12663dareg7: mov.b &mda7_flg,SPCOND_FLG(%a6)
12664 cmpi.b %d0,&0x1
12665 beq.b dareg7b
12666 sub.l %d0,EXC_A7(%a6)
12667 rts
12668dareg7b:
12669 subq.l &0x2,EXC_A7(%a6)
12670 rts
12671
12672##############################################################################
12673
12674#########################################################################
12675# XDEF **************************************************************** #
12676# load_fpn1(): load FP register value into FP_SRC(a6). #
12677# #
12678# XREF **************************************************************** #
12679# None #
12680# #
12681# INPUT *************************************************************** #
12682# d0 = index of FP register to load #
12683# #
12684# OUTPUT ************************************************************** #
12685# FP_SRC(a6) = value loaded from FP register file #
12686# #
12687# ALGORITHM *********************************************************** #
12688# Using the index in d0, load FP_SRC(a6) with a number from the #
12689# FP register file. #
12690# #
12691#########################################################################
12692
12693 global load_fpn1
12694load_fpn1:
12695 mov.w (tbl_load_fpn1.b,%pc,%d0.w*2), %d0
12696 jmp (tbl_load_fpn1.b,%pc,%d0.w*1)
12697
12698tbl_load_fpn1:
12699 short load_fpn1_0 - tbl_load_fpn1
12700 short load_fpn1_1 - tbl_load_fpn1
12701 short load_fpn1_2 - tbl_load_fpn1
12702 short load_fpn1_3 - tbl_load_fpn1
12703 short load_fpn1_4 - tbl_load_fpn1
12704 short load_fpn1_5 - tbl_load_fpn1
12705 short load_fpn1_6 - tbl_load_fpn1
12706 short load_fpn1_7 - tbl_load_fpn1
12707
12708load_fpn1_0:
12709 mov.l 0+EXC_FP0(%a6), 0+FP_SRC(%a6)
12710 mov.l 4+EXC_FP0(%a6), 4+FP_SRC(%a6)
12711 mov.l 8+EXC_FP0(%a6), 8+FP_SRC(%a6)
12712 lea FP_SRC(%a6), %a0
12713 rts
12714load_fpn1_1:
12715 mov.l 0+EXC_FP1(%a6), 0+FP_SRC(%a6)
12716 mov.l 4+EXC_FP1(%a6), 4+FP_SRC(%a6)
12717 mov.l 8+EXC_FP1(%a6), 8+FP_SRC(%a6)
12718 lea FP_SRC(%a6), %a0
12719 rts
12720load_fpn1_2:
12721 fmovm.x &0x20, FP_SRC(%a6)
12722 lea FP_SRC(%a6), %a0
12723 rts
12724load_fpn1_3:
12725 fmovm.x &0x10, FP_SRC(%a6)
12726 lea FP_SRC(%a6), %a0
12727 rts
12728load_fpn1_4:
12729 fmovm.x &0x08, FP_SRC(%a6)
12730 lea FP_SRC(%a6), %a0
12731 rts
12732load_fpn1_5:
12733 fmovm.x &0x04, FP_SRC(%a6)
12734 lea FP_SRC(%a6), %a0
12735 rts
12736load_fpn1_6:
12737 fmovm.x &0x02, FP_SRC(%a6)
12738 lea FP_SRC(%a6), %a0
12739 rts
12740load_fpn1_7:
12741 fmovm.x &0x01, FP_SRC(%a6)
12742 lea FP_SRC(%a6), %a0
12743 rts
12744
12745#############################################################################
12746
12747#########################################################################
12748# XDEF **************************************************************** #
12749# load_fpn2(): load FP register value into FP_DST(a6). #
12750# #
12751# XREF **************************************************************** #
12752# None #
12753# #
12754# INPUT *************************************************************** #
12755# d0 = index of FP register to load #
12756# #
12757# OUTPUT ************************************************************** #
12758# FP_DST(a6) = value loaded from FP register file #
12759# #
12760# ALGORITHM *********************************************************** #
12761# Using the index in d0, load FP_DST(a6) with a number from the #
12762# FP register file. #
12763# #
12764#########################################################################
12765
12766 global load_fpn2
12767load_fpn2:
12768 mov.w (tbl_load_fpn2.b,%pc,%d0.w*2), %d0
12769 jmp (tbl_load_fpn2.b,%pc,%d0.w*1)
12770
12771tbl_load_fpn2:
12772 short load_fpn2_0 - tbl_load_fpn2
12773 short load_fpn2_1 - tbl_load_fpn2
12774 short load_fpn2_2 - tbl_load_fpn2
12775 short load_fpn2_3 - tbl_load_fpn2
12776 short load_fpn2_4 - tbl_load_fpn2
12777 short load_fpn2_5 - tbl_load_fpn2
12778 short load_fpn2_6 - tbl_load_fpn2
12779 short load_fpn2_7 - tbl_load_fpn2
12780
12781load_fpn2_0:
12782 mov.l 0+EXC_FP0(%a6), 0+FP_DST(%a6)
12783 mov.l 4+EXC_FP0(%a6), 4+FP_DST(%a6)
12784 mov.l 8+EXC_FP0(%a6), 8+FP_DST(%a6)
12785 lea FP_DST(%a6), %a0
12786 rts
12787load_fpn2_1:
12788 mov.l 0+EXC_FP1(%a6), 0+FP_DST(%a6)
12789 mov.l 4+EXC_FP1(%a6), 4+FP_DST(%a6)
12790 mov.l 8+EXC_FP1(%a6), 8+FP_DST(%a6)
12791 lea FP_DST(%a6), %a0
12792 rts
12793load_fpn2_2:
12794 fmovm.x &0x20, FP_DST(%a6)
12795 lea FP_DST(%a6), %a0
12796 rts
12797load_fpn2_3:
12798 fmovm.x &0x10, FP_DST(%a6)
12799 lea FP_DST(%a6), %a0
12800 rts
12801load_fpn2_4:
12802 fmovm.x &0x08, FP_DST(%a6)
12803 lea FP_DST(%a6), %a0
12804 rts
12805load_fpn2_5:
12806 fmovm.x &0x04, FP_DST(%a6)
12807 lea FP_DST(%a6), %a0
12808 rts
12809load_fpn2_6:
12810 fmovm.x &0x02, FP_DST(%a6)
12811 lea FP_DST(%a6), %a0
12812 rts
12813load_fpn2_7:
12814 fmovm.x &0x01, FP_DST(%a6)
12815 lea FP_DST(%a6), %a0
12816 rts
12817
12818#############################################################################
12819
12820#########################################################################
12821# XDEF **************************************************************** #
12822# store_fpreg(): store an fp value to the fpreg designated d0. #
12823# #
12824# XREF **************************************************************** #
12825# None #
12826# #
12827# INPUT *************************************************************** #
12828# fp0 = extended precision value to store #
12829# d0 = index of floating-point register #
12830# #
12831# OUTPUT ************************************************************** #
12832# None #
12833# #
12834# ALGORITHM *********************************************************** #
12835# Store the value in fp0 to the FP register designated by the #
12836# value in d0. The FP number can be DENORM or SNAN so we have to be #
12837# careful that we don't take an exception here. #
12838# #
12839#########################################################################
12840
12841 global store_fpreg
12842store_fpreg:
12843 mov.w (tbl_store_fpreg.b,%pc,%d0.w*2), %d0
12844 jmp (tbl_store_fpreg.b,%pc,%d0.w*1)
12845
12846tbl_store_fpreg:
12847 short store_fpreg_0 - tbl_store_fpreg
12848 short store_fpreg_1 - tbl_store_fpreg
12849 short store_fpreg_2 - tbl_store_fpreg
12850 short store_fpreg_3 - tbl_store_fpreg
12851 short store_fpreg_4 - tbl_store_fpreg
12852 short store_fpreg_5 - tbl_store_fpreg
12853 short store_fpreg_6 - tbl_store_fpreg
12854 short store_fpreg_7 - tbl_store_fpreg
12855
12856store_fpreg_0:
12857 fmovm.x &0x80, EXC_FP0(%a6)
12858 rts
12859store_fpreg_1:
12860 fmovm.x &0x80, EXC_FP1(%a6)
12861 rts
12862store_fpreg_2:
12863 fmovm.x &0x01, -(%sp)
12864 fmovm.x (%sp)+, &0x20
12865 rts
12866store_fpreg_3:
12867 fmovm.x &0x01, -(%sp)
12868 fmovm.x (%sp)+, &0x10
12869 rts
12870store_fpreg_4:
12871 fmovm.x &0x01, -(%sp)
12872 fmovm.x (%sp)+, &0x08
12873 rts
12874store_fpreg_5:
12875 fmovm.x &0x01, -(%sp)
12876 fmovm.x (%sp)+, &0x04
12877 rts
12878store_fpreg_6:
12879 fmovm.x &0x01, -(%sp)
12880 fmovm.x (%sp)+, &0x02
12881 rts
12882store_fpreg_7:
12883 fmovm.x &0x01, -(%sp)
12884 fmovm.x (%sp)+, &0x01
12885 rts
12886
12887#########################################################################
12888# XDEF **************************************************************** #
12889# get_packed(): fetch a packed operand from memory and then #
12890# convert it to a floating-point binary number. #
12891# #
12892# XREF **************************************************************** #
12893# _dcalc_ea() - calculate the correct <ea> #
12894# _mem_read() - fetch the packed operand from memory #
12895# facc_in_x() - the fetch failed so jump to special exit code #
12896# decbin() - convert packed to binary extended precision #
12897# #
12898# INPUT *************************************************************** #
12899# None #
12900# #
12901# OUTPUT ************************************************************** #
12902# If no failure on _mem_read(): #
12903# FP_SRC(a6) = packed operand now as a binary FP number #
12904# #
12905# ALGORITHM *********************************************************** #
12906# Get the correct <ea> whihc is the value on the exception stack #
12907# frame w/ maybe a correction factor if the <ea> is -(an) or (an)+. #
12908# Then, fetch the operand from memory. If the fetch fails, exit #
12909# through facc_in_x(). #
12910# If the packed operand is a ZERO,NAN, or INF, convert it to #
12911# its binary representation here. Else, call decbin() which will #
12912# convert the packed value to an extended precision binary value. #
12913# #
12914#########################################################################
12915
12916# the stacked <ea> for packed is correct except for -(An).
12917# the base reg must be updated for both -(An) and (An)+.
12918 global get_packed
12919get_packed:
12920 mov.l &0xc,%d0 # packed is 12 bytes
12921 bsr.l _dcalc_ea # fetch <ea>; correct An
12922
12923 lea FP_SRC(%a6),%a1 # pass: ptr to super dst
12924 mov.l &0xc,%d0 # pass: 12 bytes
12925 bsr.l _dmem_read # read packed operand
12926
12927 tst.l %d1 # did dfetch fail?
12928 bne.l facc_in_x # yes
12929
12930# The packed operand is an INF or a NAN if the exponent field is all ones.
12931 bfextu FP_SRC(%a6){&1:&15},%d0 # get exp
12932 cmpi.w %d0,&0x7fff # INF or NAN?
12933 bne.b gp_try_zero # no
12934 rts # operand is an INF or NAN
12935
12936# The packed operand is a zero if the mantissa is all zero, else it's
12937# a normal packed op.
12938gp_try_zero:
12939 mov.b 3+FP_SRC(%a6),%d0 # get byte 4
12940 andi.b &0x0f,%d0 # clear all but last nybble
12941 bne.b gp_not_spec # not a zero
12942 tst.l FP_SRC_HI(%a6) # is lw 2 zero?
12943 bne.b gp_not_spec # not a zero
12944 tst.l FP_SRC_LO(%a6) # is lw 3 zero?
12945 bne.b gp_not_spec # not a zero
12946 rts # operand is a ZERO
12947gp_not_spec:
12948 lea FP_SRC(%a6),%a0 # pass: ptr to packed op
12949 bsr.l decbin # convert to extended
12950 fmovm.x &0x80,FP_SRC(%a6) # make this the srcop
12951 rts
12952
12953#########################################################################
12954# decbin(): Converts normalized packed bcd value pointed to by register #
12955# a0 to extended-precision value in fp0. #
12956# #
12957# INPUT *************************************************************** #
12958# a0 = pointer to normalized packed bcd value #
12959# #
12960# OUTPUT ************************************************************** #
12961# fp0 = exact fp representation of the packed bcd value. #
12962# #
12963# ALGORITHM *********************************************************** #
12964# Expected is a normal bcd (i.e. non-exceptional; all inf, zero, #
12965# and NaN operands are dispatched without entering this routine) #
12966# value in 68881/882 format at location (a0). #
12967# #
12968# A1. Convert the bcd exponent to binary by successive adds and #
12969# muls. Set the sign according to SE. Subtract 16 to compensate #
12970# for the mantissa which is to be interpreted as 17 integer #
12971# digits, rather than 1 integer and 16 fraction digits. #
12972# Note: this operation can never overflow. #
12973# #
12974# A2. Convert the bcd mantissa to binary by successive #
12975# adds and muls in FP0. Set the sign according to SM. #
12976# The mantissa digits will be converted with the decimal point #
12977# assumed following the least-significant digit. #
12978# Note: this operation can never overflow. #
12979# #
12980# A3. Count the number of leading/trailing zeros in the #
12981# bcd string. If SE is positive, count the leading zeros; #
12982# if negative, count the trailing zeros. Set the adjusted #
12983# exponent equal to the exponent from A1 and the zero count #
12984# added if SM = 1 and subtracted if SM = 0. Scale the #
12985# mantissa the equivalent of forcing in the bcd value: #
12986# #
12987# SM = 0 a non-zero digit in the integer position #
12988# SM = 1 a non-zero digit in Mant0, lsd of the fraction #
12989# #
12990# this will insure that any value, regardless of its #
12991# representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted #
12992# consistently. #
12993# #
12994# A4. Calculate the factor 10^exp in FP1 using a table of #
12995# 10^(2^n) values. To reduce the error in forming factors #
12996# greater than 10^27, a directed rounding scheme is used with #
12997# tables rounded to RN, RM, and RP, according to the table #
12998# in the comments of the pwrten section. #
12999# #
13000# A5. Form the final binary number by scaling the mantissa by #
13001# the exponent factor. This is done by multiplying the #
13002# mantissa in FP0 by the factor in FP1 if the adjusted #
13003# exponent sign is positive, and dividing FP0 by FP1 if #
13004# it is negative. #
13005# #
13006# Clean up and return. Check if the final mul or div was inexact. #
13007# If so, set INEX1 in USER_FPSR. #
13008# #
13009#########################################################################
13010
13011#
13012# PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded
13013# to nearest, minus, and plus, respectively. The tables include
13014# 10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}. No rounding
13015# is required until the power is greater than 27, however, all
13016# tables include the first 5 for ease of indexing.
13017#
13018RTABLE:
13019 byte 0,0,0,0
13020 byte 2,3,2,3
13021 byte 2,3,3,2
13022 byte 3,2,2,3
13023
13024 set FNIBS,7
13025 set FSTRT,0
13026
13027 set ESTRT,4
13028 set EDIGITS,2
13029
13030 global decbin
13031decbin:
13032 mov.l 0x0(%a0),FP_SCR0_EX(%a6) # make a copy of input
13033 mov.l 0x4(%a0),FP_SCR0_HI(%a6) # so we don't alter it
13034 mov.l 0x8(%a0),FP_SCR0_LO(%a6)
13035
13036 lea FP_SCR0(%a6),%a0
13037
13038 movm.l &0x3c00,-(%sp) # save d2-d5
13039 fmovm.x &0x1,-(%sp) # save fp1
13040#
13041# Calculate exponent:
13042# 1. Copy bcd value in memory for use as a working copy.
13043# 2. Calculate absolute value of exponent in d1 by mul and add.
13044# 3. Correct for exponent sign.
13045# 4. Subtract 16 to compensate for interpreting the mant as all integer digits.
13046# (i.e., all digits assumed left of the decimal point.)
13047#
13048# Register usage:
13049#
13050# calc_e:
13051# (*) d0: temp digit storage
13052# (*) d1: accumulator for binary exponent
13053# (*) d2: digit count
13054# (*) d3: offset pointer
13055# ( ) d4: first word of bcd
13056# ( ) a0: pointer to working bcd value
13057# ( ) a6: pointer to original bcd value
13058# (*) FP_SCR1: working copy of original bcd value
13059# (*) L_SCR1: copy of original exponent word
13060#
13061calc_e:
13062 mov.l &EDIGITS,%d2 # # of nibbles (digits) in fraction part
13063 mov.l &ESTRT,%d3 # counter to pick up digits
13064 mov.l (%a0),%d4 # get first word of bcd
13065 clr.l %d1 # zero d1 for accumulator
13066e_gd:
13067 mulu.l &0xa,%d1 # mul partial product by one digit place
13068 bfextu %d4{%d3:&4},%d0 # get the digit and zero extend into d0
13069 add.l %d0,%d1 # d1 = d1 + d0
13070 addq.b &4,%d3 # advance d3 to the next digit
13071 dbf.w %d2,e_gd # if we have used all 3 digits, exit loop
13072 btst &30,%d4 # get SE
13073 beq.b e_pos # don't negate if pos
13074 neg.l %d1 # negate before subtracting
13075e_pos:
13076 sub.l &16,%d1 # sub to compensate for shift of mant
13077 bge.b e_save # if still pos, do not neg
13078 neg.l %d1 # now negative, make pos and set SE
13079 or.l &0x40000000,%d4 # set SE in d4,
13080 or.l &0x40000000,(%a0) # and in working bcd
13081e_save:
13082 mov.l %d1,-(%sp) # save exp on stack
13083#
13084#
13085# Calculate mantissa:
13086# 1. Calculate absolute value of mantissa in fp0 by mul and add.
13087# 2. Correct for mantissa sign.
13088# (i.e., all digits assumed left of the decimal point.)
13089#
13090# Register usage:
13091#
13092# calc_m:
13093# (*) d0: temp digit storage
13094# (*) d1: lword counter
13095# (*) d2: digit count
13096# (*) d3: offset pointer
13097# ( ) d4: words 2 and 3 of bcd
13098# ( ) a0: pointer to working bcd value
13099# ( ) a6: pointer to original bcd value
13100# (*) fp0: mantissa accumulator
13101# ( ) FP_SCR1: working copy of original bcd value
13102# ( ) L_SCR1: copy of original exponent word
13103#
13104calc_m:
13105 mov.l &1,%d1 # word counter, init to 1
13106 fmov.s &0x00000000,%fp0 # accumulator
13107#
13108#
13109# Since the packed number has a long word between the first & second parts,
13110# get the integer digit then skip down & get the rest of the
13111# mantissa. We will unroll the loop once.
13112#
13113 bfextu (%a0){&28:&4},%d0 # integer part is ls digit in long word
13114 fadd.b %d0,%fp0 # add digit to sum in fp0
13115#
13116#
13117# Get the rest of the mantissa.
13118#
13119loadlw:
13120 mov.l (%a0,%d1.L*4),%d4 # load mantissa lonqword into d4
13121 mov.l &FSTRT,%d3 # counter to pick up digits
13122 mov.l &FNIBS,%d2 # reset number of digits per a0 ptr
13123md2b:
13124 fmul.s &0x41200000,%fp0 # fp0 = fp0 * 10
13125 bfextu %d4{%d3:&4},%d0 # get the digit and zero extend
13126 fadd.b %d0,%fp0 # fp0 = fp0 + digit
13127#
13128#
13129# If all the digits (8) in that long word have been converted (d2=0),
13130# then inc d1 (=2) to point to the next long word and reset d3 to 0
13131# to initialize the digit offset, and set d2 to 7 for the digit count;
13132# else continue with this long word.
13133#
13134 addq.b &4,%d3 # advance d3 to the next digit
13135 dbf.w %d2,md2b # check for last digit in this lw
13136nextlw:
13137 addq.l &1,%d1 # inc lw pointer in mantissa
13138 cmp.l %d1,&2 # test for last lw
13139 ble.b loadlw # if not, get last one
13140#
13141# Check the sign of the mant and make the value in fp0 the same sign.
13142#
13143m_sign:
13144 btst &31,(%a0) # test sign of the mantissa
13145 beq.b ap_st_z # if clear, go to append/strip zeros
13146 fneg.x %fp0 # if set, negate fp0
13147#
13148# Append/strip zeros:
13149#
13150# For adjusted exponents which have an absolute value greater than 27*,
13151# this routine calculates the amount needed to normalize the mantissa
13152# for the adjusted exponent. That number is subtracted from the exp
13153# if the exp was positive, and added if it was negative. The purpose
13154# of this is to reduce the value of the exponent and the possibility
13155# of error in calculation of pwrten.
13156#
13157# 1. Branch on the sign of the adjusted exponent.
13158# 2p.(positive exp)
13159# 2. Check M16 and the digits in lwords 2 and 3 in decending order.
13160# 3. Add one for each zero encountered until a non-zero digit.
13161# 4. Subtract the count from the exp.
13162# 5. Check if the exp has crossed zero in #3 above; make the exp abs
13163# and set SE.
13164# 6. Multiply the mantissa by 10**count.
13165# 2n.(negative exp)
13166# 2. Check the digits in lwords 3 and 2 in decending order.
13167# 3. Add one for each zero encountered until a non-zero digit.
13168# 4. Add the count to the exp.
13169# 5. Check if the exp has crossed zero in #3 above; clear SE.
13170# 6. Divide the mantissa by 10**count.
13171#
13172# *Why 27? If the adjusted exponent is within -28 < expA < 28, than
13173# any adjustment due to append/strip zeros will drive the resultane
13174# exponent towards zero. Since all pwrten constants with a power
13175# of 27 or less are exact, there is no need to use this routine to
13176# attempt to lessen the resultant exponent.
13177#
13178# Register usage:
13179#
13180# ap_st_z:
13181# (*) d0: temp digit storage
13182# (*) d1: zero count
13183# (*) d2: digit count
13184# (*) d3: offset pointer
13185# ( ) d4: first word of bcd
13186# (*) d5: lword counter
13187# ( ) a0: pointer to working bcd value
13188# ( ) FP_SCR1: working copy of original bcd value
13189# ( ) L_SCR1: copy of original exponent word
13190#
13191#
13192# First check the absolute value of the exponent to see if this
13193# routine is necessary. If so, then check the sign of the exponent
13194# and do append (+) or strip (-) zeros accordingly.
13195# This section handles a positive adjusted exponent.
13196#
13197ap_st_z:
13198 mov.l (%sp),%d1 # load expA for range test
13199 cmp.l %d1,&27 # test is with 27
13200 ble.w pwrten # if abs(expA) <28, skip ap/st zeros
13201 btst &30,(%a0) # check sign of exp
13202 bne.b ap_st_n # if neg, go to neg side
13203 clr.l %d1 # zero count reg
13204 mov.l (%a0),%d4 # load lword 1 to d4
13205 bfextu %d4{&28:&4},%d0 # get M16 in d0
13206 bne.b ap_p_fx # if M16 is non-zero, go fix exp
13207 addq.l &1,%d1 # inc zero count
13208 mov.l &1,%d5 # init lword counter
13209 mov.l (%a0,%d5.L*4),%d4 # get lword 2 to d4
13210 bne.b ap_p_cl # if lw 2 is zero, skip it
13211 addq.l &8,%d1 # and inc count by 8
13212 addq.l &1,%d5 # inc lword counter
13213 mov.l (%a0,%d5.L*4),%d4 # get lword 3 to d4
13214ap_p_cl:
13215 clr.l %d3 # init offset reg
13216 mov.l &7,%d2 # init digit counter
13217ap_p_gd:
13218 bfextu %d4{%d3:&4},%d0 # get digit
13219 bne.b ap_p_fx # if non-zero, go to fix exp
13220 addq.l &4,%d3 # point to next digit
13221 addq.l &1,%d1 # inc digit counter
13222 dbf.w %d2,ap_p_gd # get next digit
13223ap_p_fx:
13224 mov.l %d1,%d0 # copy counter to d2
13225 mov.l (%sp),%d1 # get adjusted exp from memory
13226 sub.l %d0,%d1 # subtract count from exp
13227 bge.b ap_p_fm # if still pos, go to pwrten
13228 neg.l %d1 # now its neg; get abs
13229 mov.l (%a0),%d4 # load lword 1 to d4
13230 or.l &0x40000000,%d4 # and set SE in d4
13231 or.l &0x40000000,(%a0) # and in memory
13232#
13233# Calculate the mantissa multiplier to compensate for the striping of
13234# zeros from the mantissa.
13235#
13236ap_p_fm:
13237 lea.l PTENRN(%pc),%a1 # get address of power-of-ten table
13238 clr.l %d3 # init table index
13239 fmov.s &0x3f800000,%fp1 # init fp1 to 1
13240 mov.l &3,%d2 # init d2 to count bits in counter
13241ap_p_el:
13242 asr.l &1,%d0 # shift lsb into carry
13243 bcc.b ap_p_en # if 1, mul fp1 by pwrten factor
13244 fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
13245ap_p_en:
13246 add.l &12,%d3 # inc d3 to next rtable entry
13247 tst.l %d0 # check if d0 is zero
13248 bne.b ap_p_el # if not, get next bit
13249 fmul.x %fp1,%fp0 # mul mantissa by 10**(no_bits_shifted)
13250 bra.b pwrten # go calc pwrten
13251#
13252# This section handles a negative adjusted exponent.
13253#
13254ap_st_n:
13255 clr.l %d1 # clr counter
13256 mov.l &2,%d5 # set up d5 to point to lword 3
13257 mov.l (%a0,%d5.L*4),%d4 # get lword 3
13258 bne.b ap_n_cl # if not zero, check digits
13259 sub.l &1,%d5 # dec d5 to point to lword 2
13260 addq.l &8,%d1 # inc counter by 8
13261 mov.l (%a0,%d5.L*4),%d4 # get lword 2
13262ap_n_cl:
13263 mov.l &28,%d3 # point to last digit
13264 mov.l &7,%d2 # init digit counter
13265ap_n_gd:
13266 bfextu %d4{%d3:&4},%d0 # get digit
13267 bne.b ap_n_fx # if non-zero, go to exp fix
13268 subq.l &4,%d3 # point to previous digit
13269 addq.l &1,%d1 # inc digit counter
13270 dbf.w %d2,ap_n_gd # get next digit
13271ap_n_fx:
13272 mov.l %d1,%d0 # copy counter to d0
13273 mov.l (%sp),%d1 # get adjusted exp from memory
13274 sub.l %d0,%d1 # subtract count from exp
13275 bgt.b ap_n_fm # if still pos, go fix mantissa
13276 neg.l %d1 # take abs of exp and clr SE
13277 mov.l (%a0),%d4 # load lword 1 to d4
13278 and.l &0xbfffffff,%d4 # and clr SE in d4
13279 and.l &0xbfffffff,(%a0) # and in memory
13280#
13281# Calculate the mantissa multiplier to compensate for the appending of
13282# zeros to the mantissa.
13283#
13284ap_n_fm:
13285 lea.l PTENRN(%pc),%a1 # get address of power-of-ten table
13286 clr.l %d3 # init table index
13287 fmov.s &0x3f800000,%fp1 # init fp1 to 1
13288 mov.l &3,%d2 # init d2 to count bits in counter
13289ap_n_el:
13290 asr.l &1,%d0 # shift lsb into carry
13291 bcc.b ap_n_en # if 1, mul fp1 by pwrten factor
13292 fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
13293ap_n_en:
13294 add.l &12,%d3 # inc d3 to next rtable entry
13295 tst.l %d0 # check if d0 is zero
13296 bne.b ap_n_el # if not, get next bit
13297 fdiv.x %fp1,%fp0 # div mantissa by 10**(no_bits_shifted)
13298#
13299#
13300# Calculate power-of-ten factor from adjusted and shifted exponent.
13301#
13302# Register usage:
13303#
13304# pwrten:
13305# (*) d0: temp
13306# ( ) d1: exponent
13307# (*) d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp
13308# (*) d3: FPCR work copy
13309# ( ) d4: first word of bcd
13310# (*) a1: RTABLE pointer
13311# calc_p:
13312# (*) d0: temp
13313# ( ) d1: exponent
13314# (*) d3: PWRTxx table index
13315# ( ) a0: pointer to working copy of bcd
13316# (*) a1: PWRTxx pointer
13317# (*) fp1: power-of-ten accumulator
13318#
13319# Pwrten calculates the exponent factor in the selected rounding mode
13320# according to the following table:
13321#
13322# Sign of Mant Sign of Exp Rounding Mode PWRTEN Rounding Mode
13323#
13324# ANY ANY RN RN
13325#
13326# + + RP RP
13327# - + RP RM
13328# + - RP RM
13329# - - RP RP
13330#
13331# + + RM RM
13332# - + RM RP
13333# + - RM RP
13334# - - RM RM
13335#
13336# + + RZ RM
13337# - + RZ RM
13338# + - RZ RP
13339# - - RZ RP
13340#
13341#
13342pwrten:
13343 mov.l USER_FPCR(%a6),%d3 # get user's FPCR
13344 bfextu %d3{&26:&2},%d2 # isolate rounding mode bits
13345 mov.l (%a0),%d4 # reload 1st bcd word to d4
13346 asl.l &2,%d2 # format d2 to be
13347 bfextu %d4{&0:&2},%d0 # {FPCR[6],FPCR[5],SM,SE}
13348 add.l %d0,%d2 # in d2 as index into RTABLE
13349 lea.l RTABLE(%pc),%a1 # load rtable base
13350 mov.b (%a1,%d2),%d0 # load new rounding bits from table
13351 clr.l %d3 # clear d3 to force no exc and extended
13352 bfins %d0,%d3{&26:&2} # stuff new rounding bits in FPCR
13353 fmov.l %d3,%fpcr # write new FPCR
13354 asr.l &1,%d0 # write correct PTENxx table
13355 bcc.b not_rp # to a1
13356 lea.l PTENRP(%pc),%a1 # it is RP
13357 bra.b calc_p # go to init section
13358not_rp:
13359 asr.l &1,%d0 # keep checking
13360 bcc.b not_rm
13361 lea.l PTENRM(%pc),%a1 # it is RM
13362 bra.b calc_p # go to init section
13363not_rm:
13364 lea.l PTENRN(%pc),%a1 # it is RN
13365calc_p:
13366 mov.l %d1,%d0 # copy exp to d0;use d0
13367 bpl.b no_neg # if exp is negative,
13368 neg.l %d0 # invert it
13369 or.l &0x40000000,(%a0) # and set SE bit
13370no_neg:
13371 clr.l %d3 # table index
13372 fmov.s &0x3f800000,%fp1 # init fp1 to 1
13373e_loop:
13374 asr.l &1,%d0 # shift next bit into carry
13375 bcc.b e_next # if zero, skip the mul
13376 fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
13377e_next:
13378 add.l &12,%d3 # inc d3 to next rtable entry
13379 tst.l %d0 # check if d0 is zero
13380 bne.b e_loop # not zero, continue shifting
13381#
13382#
13383# Check the sign of the adjusted exp and make the value in fp0 the
13384# same sign. If the exp was pos then multiply fp1*fp0;
13385# else divide fp0/fp1.
13386#
13387# Register Usage:
13388# norm:
13389# ( ) a0: pointer to working bcd value
13390# (*) fp0: mantissa accumulator
13391# ( ) fp1: scaling factor - 10**(abs(exp))
13392#
13393pnorm:
13394 btst &30,(%a0) # test the sign of the exponent
13395 beq.b mul # if clear, go to multiply
13396div:
13397 fdiv.x %fp1,%fp0 # exp is negative, so divide mant by exp
13398 bra.b end_dec
13399mul:
13400 fmul.x %fp1,%fp0 # exp is positive, so multiply by exp
13401#
13402#
13403# Clean up and return with result in fp0.
13404#
13405# If the final mul/div in decbin incurred an inex exception,
13406# it will be inex2, but will be reported as inex1 by get_op.
13407#
13408end_dec:
13409 fmov.l %fpsr,%d0 # get status register
13410 bclr &inex2_bit+8,%d0 # test for inex2 and clear it
13411 beq.b no_exc # skip this if no exc
13412 ori.w &inx1a_mask,2+USER_FPSR(%a6) # set INEX1/AINEX
13413no_exc:
13414 add.l &0x4,%sp # clear 1 lw param
13415 fmovm.x (%sp)+,&0x40 # restore fp1
13416 movm.l (%sp)+,&0x3c # restore d2-d5
13417 fmov.l &0x0,%fpcr
13418 fmov.l &0x0,%fpsr
13419 rts
13420
13421#########################################################################
13422# bindec(): Converts an input in extended precision format to bcd format#
13423# #
13424# INPUT *************************************************************** #
13425# a0 = pointer to the input extended precision value in memory. #
13426# the input may be either normalized, unnormalized, or #
13427# denormalized. #
13428# d0 = contains the k-factor sign-extended to 32-bits. #
13429# #
13430# OUTPUT ************************************************************** #
13431# FP_SCR0(a6) = bcd format result on the stack. #
13432# #
13433# ALGORITHM *********************************************************** #
13434# #
13435# A1. Set RM and size ext; Set SIGMA = sign of input. #
13436# The k-factor is saved for use in d7. Clear the #
13437# BINDEC_FLG for separating normalized/denormalized #
13438# input. If input is unnormalized or denormalized, #
13439# normalize it. #
13440# #
13441# A2. Set X = abs(input). #
13442# #
13443# A3. Compute ILOG. #
13444# ILOG is the log base 10 of the input value. It is #
13445# approximated by adding e + 0.f when the original #
13446# value is viewed as 2^^e * 1.f in extended precision. #
13447# This value is stored in d6. #
13448# #
13449# A4. Clr INEX bit. #
13450# The operation in A3 above may have set INEX2. #
13451# #
13452# A5. Set ICTR = 0; #
13453# ICTR is a flag used in A13. It must be set before the #
13454# loop entry A6. #
13455# #
13456# A6. Calculate LEN. #
13457# LEN is the number of digits to be displayed. The #
13458# k-factor can dictate either the total number of digits, #
13459# if it is a positive number, or the number of digits #
13460# after the decimal point which are to be included as #
13461# significant. See the 68882 manual for examples. #
13462# If LEN is computed to be greater than 17, set OPERR in #
13463# USER_FPSR. LEN is stored in d4. #
13464# #
13465# A7. Calculate SCALE. #
13466# SCALE is equal to 10^ISCALE, where ISCALE is the number #
13467# of decimal places needed to insure LEN integer digits #
13468# in the output before conversion to bcd. LAMBDA is the #
13469# sign of ISCALE, used in A9. Fp1 contains #
13470# 10^^(abs(ISCALE)) using a rounding mode which is a #
13471# function of the original rounding mode and the signs #
13472# of ISCALE and X. A table is given in the code. #
13473# #
13474# A8. Clr INEX; Force RZ. #
13475# The operation in A3 above may have set INEX2. #
13476# RZ mode is forced for the scaling operation to insure #
13477# only one rounding error. The grs bits are collected in #
13478# the INEX flag for use in A10. #
13479# #
13480# A9. Scale X -> Y. #
13481# The mantissa is scaled to the desired number of #
13482# significant digits. The excess digits are collected #
13483# in INEX2. #
13484# #
13485# A10. Or in INEX. #
13486# If INEX is set, round error occurred. This is #
13487# compensated for by 'or-ing' in the INEX2 flag to #
13488# the lsb of Y. #
13489# #
13490# A11. Restore original FPCR; set size ext. #
13491# Perform FINT operation in the user's rounding mode. #
13492# Keep the size to extended. #
13493# #
13494# A12. Calculate YINT = FINT(Y) according to user's rounding #
13495# mode. The FPSP routine sintd0 is used. The output #
13496# is in fp0. #
13497# #
13498# A13. Check for LEN digits. #
13499# If the int operation results in more than LEN digits, #
13500# or less than LEN -1 digits, adjust ILOG and repeat from #
13501# A6. This test occurs only on the first pass. If the #
13502# result is exactly 10^LEN, decrement ILOG and divide #
13503# the mantissa by 10. #
13504# #
13505# A14. Convert the mantissa to bcd. #
13506# The binstr routine is used to convert the LEN digit #
13507# mantissa to bcd in memory. The input to binstr is #
13508# to be a fraction; i.e. (mantissa)/10^LEN and adjusted #
13509# such that the decimal point is to the left of bit 63. #
13510# The bcd digits are stored in the correct position in #
13511# the final string area in memory. #
13512# #
13513# A15. Convert the exponent to bcd. #
13514# As in A14 above, the exp is converted to bcd and the #
13515# digits are stored in the final string. #
13516# Test the length of the final exponent string. If the #
13517# length is 4, set operr. #
13518# #
13519# A16. Write sign bits to final string. #
13520# #
13521#########################################################################
13522
13523set BINDEC_FLG, EXC_TEMP # DENORM flag
13524
13525# Constants in extended precision
13526PLOG2:
13527 long 0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000
13528PLOG2UP1:
13529 long 0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000
13530
13531# Constants in single precision
13532FONE:
13533 long 0x3F800000,0x00000000,0x00000000,0x00000000
13534FTWO:
13535 long 0x40000000,0x00000000,0x00000000,0x00000000
13536FTEN:
13537 long 0x41200000,0x00000000,0x00000000,0x00000000
13538F4933:
13539 long 0x459A2800,0x00000000,0x00000000,0x00000000
13540
13541RBDTBL:
13542 byte 0,0,0,0
13543 byte 3,3,2,2
13544 byte 3,2,2,3
13545 byte 2,3,3,2
13546
13547# Implementation Notes:
13548#
13549# The registers are used as follows:
13550#
13551# d0: scratch; LEN input to binstr
13552# d1: scratch
13553# d2: upper 32-bits of mantissa for binstr
13554# d3: scratch;lower 32-bits of mantissa for binstr
13555# d4: LEN
13556# d5: LAMBDA/ICTR
13557# d6: ILOG
13558# d7: k-factor
13559# a0: ptr for original operand/final result
13560# a1: scratch pointer
13561# a2: pointer to FP_X; abs(original value) in ext
13562# fp0: scratch
13563# fp1: scratch
13564# fp2: scratch
13565# F_SCR1:
13566# F_SCR2:
13567# L_SCR1:
13568# L_SCR2:
13569
13570 global bindec
13571bindec:
13572 movm.l &0x3f20,-(%sp) # {%d2-%d7/%a2}
13573 fmovm.x &0x7,-(%sp) # {%fp0-%fp2}
13574
13575# A1. Set RM and size ext. Set SIGMA = sign input;
13576# The k-factor is saved for use in d7. Clear BINDEC_FLG for
13577# separating normalized/denormalized input. If the input
13578# is a denormalized number, set the BINDEC_FLG memory word
13579# to signal denorm. If the input is unnormalized, normalize
13580# the input and test for denormalized result.
13581#
13582 fmov.l &rm_mode*0x10,%fpcr # set RM and ext
13583 mov.l (%a0),L_SCR2(%a6) # save exponent for sign check
13584 mov.l %d0,%d7 # move k-factor to d7
13585
13586 clr.b BINDEC_FLG(%a6) # clr norm/denorm flag
13587 cmpi.b STAG(%a6),&DENORM # is input a DENORM?
13588 bne.w A2_str # no; input is a NORM
13589
13590#
13591# Normalize the denorm
13592#
13593un_de_norm:
13594 mov.w (%a0),%d0
13595 and.w &0x7fff,%d0 # strip sign of normalized exp
13596 mov.l 4(%a0),%d1
13597 mov.l 8(%a0),%d2
13598norm_loop:
13599 sub.w &1,%d0
13600 lsl.l &1,%d2
13601 roxl.l &1,%d1
13602 tst.l %d1
13603 bge.b norm_loop
13604#
13605# Test if the normalized input is denormalized
13606#
13607 tst.w %d0
13608 bgt.b pos_exp # if greater than zero, it is a norm
13609 st BINDEC_FLG(%a6) # set flag for denorm
13610pos_exp:
13611 and.w &0x7fff,%d0 # strip sign of normalized exp
13612 mov.w %d0,(%a0)
13613 mov.l %d1,4(%a0)
13614 mov.l %d2,8(%a0)
13615
13616# A2. Set X = abs(input).
13617#
13618A2_str:
13619 mov.l (%a0),FP_SCR1(%a6) # move input to work space
13620 mov.l 4(%a0),FP_SCR1+4(%a6) # move input to work space
13621 mov.l 8(%a0),FP_SCR1+8(%a6) # move input to work space
13622 and.l &0x7fffffff,FP_SCR1(%a6) # create abs(X)
13623
13624# A3. Compute ILOG.
13625# ILOG is the log base 10 of the input value. It is approx-
13626# imated by adding e + 0.f when the original value is viewed
13627# as 2^^e * 1.f in extended precision. This value is stored
13628# in d6.
13629#
13630# Register usage:
13631# Input/Output
13632# d0: k-factor/exponent
13633# d2: x/x
13634# d3: x/x
13635# d4: x/x
13636# d5: x/x
13637# d6: x/ILOG
13638# d7: k-factor/Unchanged
13639# a0: ptr for original operand/final result
13640# a1: x/x
13641# a2: x/x
13642# fp0: x/float(ILOG)
13643# fp1: x/x
13644# fp2: x/x
13645# F_SCR1:x/x
13646# F_SCR2:Abs(X)/Abs(X) with $3fff exponent
13647# L_SCR1:x/x
13648# L_SCR2:first word of X packed/Unchanged
13649
13650 tst.b BINDEC_FLG(%a6) # check for denorm
13651 beq.b A3_cont # if clr, continue with norm
13652 mov.l &-4933,%d6 # force ILOG = -4933
13653 bra.b A4_str
13654A3_cont:
13655 mov.w FP_SCR1(%a6),%d0 # move exp to d0
13656 mov.w &0x3fff,FP_SCR1(%a6) # replace exponent with 0x3fff
13657 fmov.x FP_SCR1(%a6),%fp0 # now fp0 has 1.f
13658 sub.w &0x3fff,%d0 # strip off bias
13659 fadd.w %d0,%fp0 # add in exp
13660 fsub.s FONE(%pc),%fp0 # subtract off 1.0
13661 fbge.w pos_res # if pos, branch
13662 fmul.x PLOG2UP1(%pc),%fp0 # if neg, mul by LOG2UP1
13663 fmov.l %fp0,%d6 # put ILOG in d6 as a lword
13664 bra.b A4_str # go move out ILOG
13665pos_res:
13666 fmul.x PLOG2(%pc),%fp0 # if pos, mul by LOG2
13667 fmov.l %fp0,%d6 # put ILOG in d6 as a lword
13668
13669
13670# A4. Clr INEX bit.
13671# The operation in A3 above may have set INEX2.
13672
13673A4_str:
13674 fmov.l &0,%fpsr # zero all of fpsr - nothing needed
13675
13676
13677# A5. Set ICTR = 0;
13678# ICTR is a flag used in A13. It must be set before the
13679# loop entry A6. The lower word of d5 is used for ICTR.
13680
13681 clr.w %d5 # clear ICTR
13682
13683# A6. Calculate LEN.
13684# LEN is the number of digits to be displayed. The k-factor
13685# can dictate either the total number of digits, if it is
13686# a positive number, or the number of digits after the
13687# original decimal point which are to be included as
13688# significant. See the 68882 manual for examples.
13689# If LEN is computed to be greater than 17, set OPERR in
13690# USER_FPSR. LEN is stored in d4.
13691#
13692# Register usage:
13693# Input/Output
13694# d0: exponent/Unchanged
13695# d2: x/x/scratch
13696# d3: x/x
13697# d4: exc picture/LEN
13698# d5: ICTR/Unchanged
13699# d6: ILOG/Unchanged
13700# d7: k-factor/Unchanged
13701# a0: ptr for original operand/final result
13702# a1: x/x
13703# a2: x/x
13704# fp0: float(ILOG)/Unchanged
13705# fp1: x/x
13706# fp2: x/x
13707# F_SCR1:x/x
13708# F_SCR2:Abs(X) with $3fff exponent/Unchanged
13709# L_SCR1:x/x
13710# L_SCR2:first word of X packed/Unchanged
13711
13712A6_str:
13713 tst.l %d7 # branch on sign of k
13714 ble.b k_neg # if k <= 0, LEN = ILOG + 1 - k
13715 mov.l %d7,%d4 # if k > 0, LEN = k
13716 bra.b len_ck # skip to LEN check
13717k_neg:
13718 mov.l %d6,%d4 # first load ILOG to d4
13719 sub.l %d7,%d4 # subtract off k
13720 addq.l &1,%d4 # add in the 1
13721len_ck:
13722 tst.l %d4 # LEN check: branch on sign of LEN
13723 ble.b LEN_ng # if neg, set LEN = 1
13724 cmp.l %d4,&17 # test if LEN > 17
13725 ble.b A7_str # if not, forget it
13726 mov.l &17,%d4 # set max LEN = 17
13727 tst.l %d7 # if negative, never set OPERR
13728 ble.b A7_str # if positive, continue
13729 or.l &opaop_mask,USER_FPSR(%a6) # set OPERR & AIOP in USER_FPSR
13730 bra.b A7_str # finished here
13731LEN_ng:
13732 mov.l &1,%d4 # min LEN is 1
13733
13734
13735# A7. Calculate SCALE.
13736# SCALE is equal to 10^ISCALE, where ISCALE is the number
13737# of decimal places needed to insure LEN integer digits
13738# in the output before conversion to bcd. LAMBDA is the sign
13739# of ISCALE, used in A9. Fp1 contains 10^^(abs(ISCALE)) using
13740# the rounding mode as given in the following table (see
13741# Coonen, p. 7.23 as ref.; however, the SCALE variable is
13742# of opposite sign in bindec.sa from Coonen).
13743#
13744# Initial USE
13745# FPCR[6:5] LAMBDA SIGN(X) FPCR[6:5]
13746# ----------------------------------------------
13747# RN 00 0 0 00/0 RN
13748# RN 00 0 1 00/0 RN
13749# RN 00 1 0 00/0 RN
13750# RN 00 1 1 00/0 RN
13751# RZ 01 0 0 11/3 RP
13752# RZ 01 0 1 11/3 RP
13753# RZ 01 1 0 10/2 RM
13754# RZ 01 1 1 10/2 RM
13755# RM 10 0 0 11/3 RP
13756# RM 10 0 1 10/2 RM
13757# RM 10 1 0 10/2 RM
13758# RM 10 1 1 11/3 RP
13759# RP 11 0 0 10/2 RM
13760# RP 11 0 1 11/3 RP
13761# RP 11 1 0 11/3 RP
13762# RP 11 1 1 10/2 RM
13763#
13764# Register usage:
13765# Input/Output
13766# d0: exponent/scratch - final is 0
13767# d2: x/0 or 24 for A9
13768# d3: x/scratch - offset ptr into PTENRM array
13769# d4: LEN/Unchanged
13770# d5: 0/ICTR:LAMBDA
13771# d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
13772# d7: k-factor/Unchanged
13773# a0: ptr for original operand/final result
13774# a1: x/ptr to PTENRM array
13775# a2: x/x
13776# fp0: float(ILOG)/Unchanged
13777# fp1: x/10^ISCALE
13778# fp2: x/x
13779# F_SCR1:x/x
13780# F_SCR2:Abs(X) with $3fff exponent/Unchanged
13781# L_SCR1:x/x
13782# L_SCR2:first word of X packed/Unchanged
13783
13784A7_str:
13785 tst.l %d7 # test sign of k
13786 bgt.b k_pos # if pos and > 0, skip this
13787 cmp.l %d7,%d6 # test k - ILOG
13788 blt.b k_pos # if ILOG >= k, skip this
13789 mov.l %d7,%d6 # if ((k<0) & (ILOG < k)) ILOG = k
13790k_pos:
13791 mov.l %d6,%d0 # calc ILOG + 1 - LEN in d0
13792 addq.l &1,%d0 # add the 1
13793 sub.l %d4,%d0 # sub off LEN
13794 swap %d5 # use upper word of d5 for LAMBDA
13795 clr.w %d5 # set it zero initially
13796 clr.w %d2 # set up d2 for very small case
13797 tst.l %d0 # test sign of ISCALE
13798 bge.b iscale # if pos, skip next inst
13799 addq.w &1,%d5 # if neg, set LAMBDA true
13800 cmp.l %d0,&0xffffecd4 # test iscale <= -4908
13801 bgt.b no_inf # if false, skip rest
13802 add.l &24,%d0 # add in 24 to iscale
13803 mov.l &24,%d2 # put 24 in d2 for A9
13804no_inf:
13805 neg.l %d0 # and take abs of ISCALE
13806iscale:
13807 fmov.s FONE(%pc),%fp1 # init fp1 to 1
13808 bfextu USER_FPCR(%a6){&26:&2},%d1 # get initial rmode bits
13809 lsl.w &1,%d1 # put them in bits 2:1
13810 add.w %d5,%d1 # add in LAMBDA
13811 lsl.w &1,%d1 # put them in bits 3:1
13812 tst.l L_SCR2(%a6) # test sign of original x
13813 bge.b x_pos # if pos, don't set bit 0
13814 addq.l &1,%d1 # if neg, set bit 0
13815x_pos:
13816 lea.l RBDTBL(%pc),%a2 # load rbdtbl base
13817 mov.b (%a2,%d1),%d3 # load d3 with new rmode
13818 lsl.l &4,%d3 # put bits in proper position
13819 fmov.l %d3,%fpcr # load bits into fpu
13820 lsr.l &4,%d3 # put bits in proper position
13821 tst.b %d3 # decode new rmode for pten table
13822 bne.b not_rn # if zero, it is RN
13823 lea.l PTENRN(%pc),%a1 # load a1 with RN table base
13824 bra.b rmode # exit decode
13825not_rn:
13826 lsr.b &1,%d3 # get lsb in carry
13827 bcc.b not_rp2 # if carry clear, it is RM
13828 lea.l PTENRP(%pc),%a1 # load a1 with RP table base
13829 bra.b rmode # exit decode
13830not_rp2:
13831 lea.l PTENRM(%pc),%a1 # load a1 with RM table base
13832rmode:
13833 clr.l %d3 # clr table index
13834e_loop2:
13835 lsr.l &1,%d0 # shift next bit into carry
13836 bcc.b e_next2 # if zero, skip the mul
13837 fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
13838e_next2:
13839 add.l &12,%d3 # inc d3 to next pwrten table entry
13840 tst.l %d0 # test if ISCALE is zero
13841 bne.b e_loop2 # if not, loop
13842
13843# A8. Clr INEX; Force RZ.
13844# The operation in A3 above may have set INEX2.
13845# RZ mode is forced for the scaling operation to insure
13846# only one rounding error. The grs bits are collected in
13847# the INEX flag for use in A10.
13848#
13849# Register usage:
13850# Input/Output
13851
13852 fmov.l &0,%fpsr # clr INEX
13853 fmov.l &rz_mode*0x10,%fpcr # set RZ rounding mode
13854
13855# A9. Scale X -> Y.
13856# The mantissa is scaled to the desired number of significant
13857# digits. The excess digits are collected in INEX2. If mul,
13858# Check d2 for excess 10 exponential value. If not zero,
13859# the iscale value would have caused the pwrten calculation
13860# to overflow. Only a negative iscale can cause this, so
13861# multiply by 10^(d2), which is now only allowed to be 24,
13862# with a multiply by 10^8 and 10^16, which is exact since
13863# 10^24 is exact. If the input was denormalized, we must
13864# create a busy stack frame with the mul command and the
13865# two operands, and allow the fpu to complete the multiply.
13866#
13867# Register usage:
13868# Input/Output
13869# d0: FPCR with RZ mode/Unchanged
13870# d2: 0 or 24/unchanged
13871# d3: x/x
13872# d4: LEN/Unchanged
13873# d5: ICTR:LAMBDA
13874# d6: ILOG/Unchanged
13875# d7: k-factor/Unchanged
13876# a0: ptr for original operand/final result
13877# a1: ptr to PTENRM array/Unchanged
13878# a2: x/x
13879# fp0: float(ILOG)/X adjusted for SCALE (Y)
13880# fp1: 10^ISCALE/Unchanged
13881# fp2: x/x
13882# F_SCR1:x/x
13883# F_SCR2:Abs(X) with $3fff exponent/Unchanged
13884# L_SCR1:x/x
13885# L_SCR2:first word of X packed/Unchanged
13886
13887A9_str:
13888 fmov.x (%a0),%fp0 # load X from memory
13889 fabs.x %fp0 # use abs(X)
13890 tst.w %d5 # LAMBDA is in lower word of d5
13891 bne.b sc_mul # if neg (LAMBDA = 1), scale by mul
13892 fdiv.x %fp1,%fp0 # calculate X / SCALE -> Y to fp0
13893 bra.w A10_st # branch to A10
13894
13895sc_mul:
13896 tst.b BINDEC_FLG(%a6) # check for denorm
13897 beq.w A9_norm # if norm, continue with mul
13898
13899# for DENORM, we must calculate:
13900# fp0 = input_op * 10^ISCALE * 10^24
13901# since the input operand is a DENORM, we can't multiply it directly.
13902# so, we do the multiplication of the exponents and mantissas separately.
13903# in this way, we avoid underflow on intermediate stages of the
13904# multiplication and guarantee a result without exception.
13905 fmovm.x &0x2,-(%sp) # save 10^ISCALE to stack
13906
13907 mov.w (%sp),%d3 # grab exponent
13908 andi.w &0x7fff,%d3 # clear sign
13909 ori.w &0x8000,(%a0) # make DENORM exp negative
13910 add.w (%a0),%d3 # add DENORM exp to 10^ISCALE exp
13911 subi.w &0x3fff,%d3 # subtract BIAS
13912 add.w 36(%a1),%d3
13913 subi.w &0x3fff,%d3 # subtract BIAS
13914 add.w 48(%a1),%d3
13915 subi.w &0x3fff,%d3 # subtract BIAS
13916
13917 bmi.w sc_mul_err # is result is DENORM, punt!!!
13918
13919 andi.w &0x8000,(%sp) # keep sign
13920 or.w %d3,(%sp) # insert new exponent
13921 andi.w &0x7fff,(%a0) # clear sign bit on DENORM again
13922 mov.l 0x8(%a0),-(%sp) # put input op mantissa on stk
13923 mov.l 0x4(%a0),-(%sp)
13924 mov.l &0x3fff0000,-(%sp) # force exp to zero
13925 fmovm.x (%sp)+,&0x80 # load normalized DENORM into fp0
13926 fmul.x (%sp)+,%fp0
13927
13928# fmul.x 36(%a1),%fp0 # multiply fp0 by 10^8
13929# fmul.x 48(%a1),%fp0 # multiply fp0 by 10^16
13930 mov.l 36+8(%a1),-(%sp) # get 10^8 mantissa
13931 mov.l 36+4(%a1),-(%sp)
13932 mov.l &0x3fff0000,-(%sp) # force exp to zero
13933 mov.l 48+8(%a1),-(%sp) # get 10^16 mantissa
13934 mov.l 48+4(%a1),-(%sp)
13935 mov.l &0x3fff0000,-(%sp)# force exp to zero
13936 fmul.x (%sp)+,%fp0 # multiply fp0 by 10^8
13937 fmul.x (%sp)+,%fp0 # multiply fp0 by 10^16
13938 bra.b A10_st
13939
13940sc_mul_err:
13941 bra.b sc_mul_err
13942
13943A9_norm:
13944 tst.w %d2 # test for small exp case
13945 beq.b A9_con # if zero, continue as normal
13946 fmul.x 36(%a1),%fp0 # multiply fp0 by 10^8
13947 fmul.x 48(%a1),%fp0 # multiply fp0 by 10^16
13948A9_con:
13949 fmul.x %fp1,%fp0 # calculate X * SCALE -> Y to fp0
13950
13951# A10. Or in INEX.
13952# If INEX is set, round error occurred. This is compensated
13953# for by 'or-ing' in the INEX2 flag to the lsb of Y.
13954#
13955# Register usage:
13956# Input/Output
13957# d0: FPCR with RZ mode/FPSR with INEX2 isolated
13958# d2: x/x
13959# d3: x/x
13960# d4: LEN/Unchanged
13961# d5: ICTR:LAMBDA
13962# d6: ILOG/Unchanged
13963# d7: k-factor/Unchanged
13964# a0: ptr for original operand/final result
13965# a1: ptr to PTENxx array/Unchanged
13966# a2: x/ptr to FP_SCR1(a6)
13967# fp0: Y/Y with lsb adjusted
13968# fp1: 10^ISCALE/Unchanged
13969# fp2: x/x
13970
13971A10_st:
13972 fmov.l %fpsr,%d0 # get FPSR
13973 fmov.x %fp0,FP_SCR1(%a6) # move Y to memory
13974 lea.l FP_SCR1(%a6),%a2 # load a2 with ptr to FP_SCR1
13975 btst &9,%d0 # check if INEX2 set
13976 beq.b A11_st # if clear, skip rest
13977 or.l &1,8(%a2) # or in 1 to lsb of mantissa
13978 fmov.x FP_SCR1(%a6),%fp0 # write adjusted Y back to fpu
13979
13980
13981# A11. Restore original FPCR; set size ext.
13982# Perform FINT operation in the user's rounding mode. Keep
13983# the size to extended. The sintdo entry point in the sint
13984# routine expects the FPCR value to be in USER_FPCR for
13985# mode and precision. The original FPCR is saved in L_SCR1.
13986
13987A11_st:
13988 mov.l USER_FPCR(%a6),L_SCR1(%a6) # save it for later
13989 and.l &0x00000030,USER_FPCR(%a6) # set size to ext,
13990# ;block exceptions
13991
13992
13993# A12. Calculate YINT = FINT(Y) according to user's rounding mode.
13994# The FPSP routine sintd0 is used. The output is in fp0.
13995#
13996# Register usage:
13997# Input/Output
13998# d0: FPSR with AINEX cleared/FPCR with size set to ext
13999# d2: x/x/scratch
14000# d3: x/x
14001# d4: LEN/Unchanged
14002# d5: ICTR:LAMBDA/Unchanged
14003# d6: ILOG/Unchanged
14004# d7: k-factor/Unchanged
14005# a0: ptr for original operand/src ptr for sintdo
14006# a1: ptr to PTENxx array/Unchanged
14007# a2: ptr to FP_SCR1(a6)/Unchanged
14008# a6: temp pointer to FP_SCR1(a6) - orig value saved and restored
14009# fp0: Y/YINT
14010# fp1: 10^ISCALE/Unchanged
14011# fp2: x/x
14012# F_SCR1:x/x
14013# F_SCR2:Y adjusted for inex/Y with original exponent
14014# L_SCR1:x/original USER_FPCR
14015# L_SCR2:first word of X packed/Unchanged
14016
14017A12_st:
14018 movm.l &0xc0c0,-(%sp) # save regs used by sintd0 {%d0-%d1/%a0-%a1}
14019 mov.l L_SCR1(%a6),-(%sp)
14020 mov.l L_SCR2(%a6),-(%sp)
14021
14022 lea.l FP_SCR1(%a6),%a0 # a0 is ptr to FP_SCR1(a6)
14023 fmov.x %fp0,(%a0) # move Y to memory at FP_SCR1(a6)
14024 tst.l L_SCR2(%a6) # test sign of original operand
14025 bge.b do_fint12 # if pos, use Y
14026 or.l &0x80000000,(%a0) # if neg, use -Y
14027do_fint12:
14028 mov.l USER_FPSR(%a6),-(%sp)
14029# bsr sintdo # sint routine returns int in fp0
14030
14031 fmov.l USER_FPCR(%a6),%fpcr
14032 fmov.l &0x0,%fpsr # clear the AEXC bits!!!
14033## mov.l USER_FPCR(%a6),%d0 # ext prec/keep rnd mode
14034## andi.l &0x00000030,%d0
14035## fmov.l %d0,%fpcr
14036 fint.x FP_SCR1(%a6),%fp0 # do fint()
14037 fmov.l %fpsr,%d0
14038 or.w %d0,FPSR_EXCEPT(%a6)
14039## fmov.l &0x0,%fpcr
14040## fmov.l %fpsr,%d0 # don't keep ccodes
14041## or.w %d0,FPSR_EXCEPT(%a6)
14042
14043 mov.b (%sp),USER_FPSR(%a6)
14044 add.l &4,%sp
14045
14046 mov.l (%sp)+,L_SCR2(%a6)
14047 mov.l (%sp)+,L_SCR1(%a6)
14048 movm.l (%sp)+,&0x303 # restore regs used by sint {%d0-%d1/%a0-%a1}
14049
14050 mov.l L_SCR2(%a6),FP_SCR1(%a6) # restore original exponent
14051 mov.l L_SCR1(%a6),USER_FPCR(%a6) # restore user's FPCR
14052
14053# A13. Check for LEN digits.
14054# If the int operation results in more than LEN digits,
14055# or less than LEN -1 digits, adjust ILOG and repeat from
14056# A6. This test occurs only on the first pass. If the
14057# result is exactly 10^LEN, decrement ILOG and divide
14058# the mantissa by 10. The calculation of 10^LEN cannot
14059# be inexact, since all powers of ten upto 10^27 are exact
14060# in extended precision, so the use of a previous power-of-ten
14061# table will introduce no error.
14062#
14063#
14064# Register usage:
14065# Input/Output
14066# d0: FPCR with size set to ext/scratch final = 0
14067# d2: x/x
14068# d3: x/scratch final = x
14069# d4: LEN/LEN adjusted
14070# d5: ICTR:LAMBDA/LAMBDA:ICTR
14071# d6: ILOG/ILOG adjusted
14072# d7: k-factor/Unchanged
14073# a0: pointer into memory for packed bcd string formation
14074# a1: ptr to PTENxx array/Unchanged
14075# a2: ptr to FP_SCR1(a6)/Unchanged
14076# fp0: int portion of Y/abs(YINT) adjusted
14077# fp1: 10^ISCALE/Unchanged
14078# fp2: x/10^LEN
14079# F_SCR1:x/x
14080# F_SCR2:Y with original exponent/Unchanged
14081# L_SCR1:original USER_FPCR/Unchanged
14082# L_SCR2:first word of X packed/Unchanged
14083
14084A13_st:
14085 swap %d5 # put ICTR in lower word of d5
14086 tst.w %d5 # check if ICTR = 0
14087 bne not_zr # if non-zero, go to second test
14088#
14089# Compute 10^(LEN-1)
14090#
14091 fmov.s FONE(%pc),%fp2 # init fp2 to 1.0
14092 mov.l %d4,%d0 # put LEN in d0
14093 subq.l &1,%d0 # d0 = LEN -1
14094 clr.l %d3 # clr table index
14095l_loop:
14096 lsr.l &1,%d0 # shift next bit into carry
14097 bcc.b l_next # if zero, skip the mul
14098 fmul.x (%a1,%d3),%fp2 # mul by 10**(d3_bit_no)
14099l_next:
14100 add.l &12,%d3 # inc d3 to next pwrten table entry
14101 tst.l %d0 # test if LEN is zero
14102 bne.b l_loop # if not, loop
14103#
14104# 10^LEN-1 is computed for this test and A14. If the input was
14105# denormalized, check only the case in which YINT > 10^LEN.
14106#
14107 tst.b BINDEC_FLG(%a6) # check if input was norm
14108 beq.b A13_con # if norm, continue with checking
14109 fabs.x %fp0 # take abs of YINT
14110 bra test_2
14111#
14112# Compare abs(YINT) to 10^(LEN-1) and 10^LEN
14113#
14114A13_con:
14115 fabs.x %fp0 # take abs of YINT
14116 fcmp.x %fp0,%fp2 # compare abs(YINT) with 10^(LEN-1)
14117 fbge.w test_2 # if greater, do next test
14118 subq.l &1,%d6 # subtract 1 from ILOG
14119 mov.w &1,%d5 # set ICTR
14120 fmov.l &rm_mode*0x10,%fpcr # set rmode to RM
14121 fmul.s FTEN(%pc),%fp2 # compute 10^LEN
14122 bra.w A6_str # return to A6 and recompute YINT
14123test_2:
14124 fmul.s FTEN(%pc),%fp2 # compute 10^LEN
14125 fcmp.x %fp0,%fp2 # compare abs(YINT) with 10^LEN
14126 fblt.w A14_st # if less, all is ok, go to A14
14127 fbgt.w fix_ex # if greater, fix and redo
14128 fdiv.s FTEN(%pc),%fp0 # if equal, divide by 10
14129 addq.l &1,%d6 # and inc ILOG
14130 bra.b A14_st # and continue elsewhere
14131fix_ex:
14132 addq.l &1,%d6 # increment ILOG by 1
14133 mov.w &1,%d5 # set ICTR
14134 fmov.l &rm_mode*0x10,%fpcr # set rmode to RM
14135 bra.w A6_str # return to A6 and recompute YINT
14136#
14137# Since ICTR <> 0, we have already been through one adjustment,
14138# and shouldn't have another; this is to check if abs(YINT) = 10^LEN
14139# 10^LEN is again computed using whatever table is in a1 since the
14140# value calculated cannot be inexact.
14141#
14142not_zr:
14143 fmov.s FONE(%pc),%fp2 # init fp2 to 1.0
14144 mov.l %d4,%d0 # put LEN in d0
14145 clr.l %d3 # clr table index
14146z_loop:
14147 lsr.l &1,%d0 # shift next bit into carry
14148 bcc.b z_next # if zero, skip the mul
14149 fmul.x (%a1,%d3),%fp2 # mul by 10**(d3_bit_no)
14150z_next:
14151 add.l &12,%d3 # inc d3 to next pwrten table entry
14152 tst.l %d0 # test if LEN is zero
14153 bne.b z_loop # if not, loop
14154 fabs.x %fp0 # get abs(YINT)
14155 fcmp.x %fp0,%fp2 # check if abs(YINT) = 10^LEN
14156 fbneq.w A14_st # if not, skip this
14157 fdiv.s FTEN(%pc),%fp0 # divide abs(YINT) by 10
14158 addq.l &1,%d6 # and inc ILOG by 1
14159 addq.l &1,%d4 # and inc LEN
14160 fmul.s FTEN(%pc),%fp2 # if LEN++, the get 10^^LEN
14161
14162# A14. Convert the mantissa to bcd.
14163# The binstr routine is used to convert the LEN digit
14164# mantissa to bcd in memory. The input to binstr is
14165# to be a fraction; i.e. (mantissa)/10^LEN and adjusted
14166# such that the decimal point is to the left of bit 63.
14167# The bcd digits are stored in the correct position in
14168# the final string area in memory.
14169#
14170#
14171# Register usage:
14172# Input/Output
14173# d0: x/LEN call to binstr - final is 0
14174# d1: x/0
14175# d2: x/ms 32-bits of mant of abs(YINT)
14176# d3: x/ls 32-bits of mant of abs(YINT)
14177# d4: LEN/Unchanged
14178# d5: ICTR:LAMBDA/LAMBDA:ICTR
14179# d6: ILOG
14180# d7: k-factor/Unchanged
14181# a0: pointer into memory for packed bcd string formation
14182# /ptr to first mantissa byte in result string
14183# a1: ptr to PTENxx array/Unchanged
14184# a2: ptr to FP_SCR1(a6)/Unchanged
14185# fp0: int portion of Y/abs(YINT) adjusted
14186# fp1: 10^ISCALE/Unchanged
14187# fp2: 10^LEN/Unchanged
14188# F_SCR1:x/Work area for final result
14189# F_SCR2:Y with original exponent/Unchanged
14190# L_SCR1:original USER_FPCR/Unchanged
14191# L_SCR2:first word of X packed/Unchanged
14192
14193A14_st:
14194 fmov.l &rz_mode*0x10,%fpcr # force rz for conversion
14195 fdiv.x %fp2,%fp0 # divide abs(YINT) by 10^LEN
14196 lea.l FP_SCR0(%a6),%a0
14197 fmov.x %fp0,(%a0) # move abs(YINT)/10^LEN to memory
14198 mov.l 4(%a0),%d2 # move 2nd word of FP_RES to d2
14199 mov.l 8(%a0),%d3 # move 3rd word of FP_RES to d3
14200 clr.l 4(%a0) # zero word 2 of FP_RES
14201 clr.l 8(%a0) # zero word 3 of FP_RES
14202 mov.l (%a0),%d0 # move exponent to d0
14203 swap %d0 # put exponent in lower word
14204 beq.b no_sft # if zero, don't shift
14205 sub.l &0x3ffd,%d0 # sub bias less 2 to make fract
14206 tst.l %d0 # check if > 1
14207 bgt.b no_sft # if so, don't shift
14208 neg.l %d0 # make exp positive
14209m_loop:
14210 lsr.l &1,%d2 # shift d2:d3 right, add 0s
14211 roxr.l &1,%d3 # the number of places
14212 dbf.w %d0,m_loop # given in d0
14213no_sft:
14214 tst.l %d2 # check for mantissa of zero
14215 bne.b no_zr # if not, go on
14216 tst.l %d3 # continue zero check
14217 beq.b zer_m # if zero, go directly to binstr
14218no_zr:
14219 clr.l %d1 # put zero in d1 for addx
14220 add.l &0x00000080,%d3 # inc at bit 7
14221 addx.l %d1,%d2 # continue inc
14222 and.l &0xffffff80,%d3 # strip off lsb not used by 882
14223zer_m:
14224 mov.l %d4,%d0 # put LEN in d0 for binstr call
14225 addq.l &3,%a0 # a0 points to M16 byte in result
14226 bsr binstr # call binstr to convert mant
14227
14228
14229# A15. Convert the exponent to bcd.
14230# As in A14 above, the exp is converted to bcd and the
14231# digits are stored in the final string.
14232#
14233# Digits are stored in L_SCR1(a6) on return from BINDEC as:
14234#
14235# 32 16 15 0
14236# -----------------------------------------
14237# | 0 | e3 | e2 | e1 | e4 | X | X | X |
14238# -----------------------------------------
14239#
14240# And are moved into their proper places in FP_SCR0. If digit e4
14241# is non-zero, OPERR is signaled. In all cases, all 4 digits are
14242# written as specified in the 881/882 manual for packed decimal.
14243#
14244# Register usage:
14245# Input/Output
14246# d0: x/LEN call to binstr - final is 0
14247# d1: x/scratch (0);shift count for final exponent packing
14248# d2: x/ms 32-bits of exp fraction/scratch
14249# d3: x/ls 32-bits of exp fraction
14250# d4: LEN/Unchanged
14251# d5: ICTR:LAMBDA/LAMBDA:ICTR
14252# d6: ILOG
14253# d7: k-factor/Unchanged
14254# a0: ptr to result string/ptr to L_SCR1(a6)
14255# a1: ptr to PTENxx array/Unchanged
14256# a2: ptr to FP_SCR1(a6)/Unchanged
14257# fp0: abs(YINT) adjusted/float(ILOG)
14258# fp1: 10^ISCALE/Unchanged
14259# fp2: 10^LEN/Unchanged
14260# F_SCR1:Work area for final result/BCD result
14261# F_SCR2:Y with original exponent/ILOG/10^4
14262# L_SCR1:original USER_FPCR/Exponent digits on return from binstr
14263# L_SCR2:first word of X packed/Unchanged
14264
14265A15_st:
14266 tst.b BINDEC_FLG(%a6) # check for denorm
14267 beq.b not_denorm
14268 ftest.x %fp0 # test for zero
14269 fbeq.w den_zero # if zero, use k-factor or 4933
14270 fmov.l %d6,%fp0 # float ILOG
14271 fabs.x %fp0 # get abs of ILOG
14272 bra.b convrt
14273den_zero:
14274 tst.l %d7 # check sign of the k-factor
14275 blt.b use_ilog # if negative, use ILOG
14276 fmov.s F4933(%pc),%fp0 # force exponent to 4933
14277 bra.b convrt # do it
14278use_ilog:
14279 fmov.l %d6,%fp0 # float ILOG
14280 fabs.x %fp0 # get abs of ILOG
14281 bra.b convrt
14282not_denorm:
14283 ftest.x %fp0 # test for zero
14284 fbneq.w not_zero # if zero, force exponent
14285 fmov.s FONE(%pc),%fp0 # force exponent to 1
14286 bra.b convrt # do it
14287not_zero:
14288 fmov.l %d6,%fp0 # float ILOG
14289 fabs.x %fp0 # get abs of ILOG
14290convrt:
14291 fdiv.x 24(%a1),%fp0 # compute ILOG/10^4
14292 fmov.x %fp0,FP_SCR1(%a6) # store fp0 in memory
14293 mov.l 4(%a2),%d2 # move word 2 to d2
14294 mov.l 8(%a2),%d3 # move word 3 to d3
14295 mov.w (%a2),%d0 # move exp to d0
14296 beq.b x_loop_fin # if zero, skip the shift
14297 sub.w &0x3ffd,%d0 # subtract off bias
14298 neg.w %d0 # make exp positive
14299x_loop:
14300 lsr.l &1,%d2 # shift d2:d3 right
14301 roxr.l &1,%d3 # the number of places
14302 dbf.w %d0,x_loop # given in d0
14303x_loop_fin:
14304 clr.l %d1 # put zero in d1 for addx
14305 add.l &0x00000080,%d3 # inc at bit 6
14306 addx.l %d1,%d2 # continue inc
14307 and.l &0xffffff80,%d3 # strip off lsb not used by 882
14308 mov.l &4,%d0 # put 4 in d0 for binstr call
14309 lea.l L_SCR1(%a6),%a0 # a0 is ptr to L_SCR1 for exp digits
14310 bsr binstr # call binstr to convert exp
14311 mov.l L_SCR1(%a6),%d0 # load L_SCR1 lword to d0
14312 mov.l &12,%d1 # use d1 for shift count
14313 lsr.l %d1,%d0 # shift d0 right by 12
14314 bfins %d0,FP_SCR0(%a6){&4:&12} # put e3:e2:e1 in FP_SCR0
14315 lsr.l %d1,%d0 # shift d0 right by 12
14316 bfins %d0,FP_SCR0(%a6){&16:&4} # put e4 in FP_SCR0
14317 tst.b %d0 # check if e4 is zero
14318 beq.b A16_st # if zero, skip rest
14319 or.l &opaop_mask,USER_FPSR(%a6) # set OPERR & AIOP in USER_FPSR
14320
14321
14322# A16. Write sign bits to final string.
14323# Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
14324#
14325# Register usage:
14326# Input/Output
14327# d0: x/scratch - final is x
14328# d2: x/x
14329# d3: x/x
14330# d4: LEN/Unchanged
14331# d5: ICTR:LAMBDA/LAMBDA:ICTR
14332# d6: ILOG/ILOG adjusted
14333# d7: k-factor/Unchanged
14334# a0: ptr to L_SCR1(a6)/Unchanged
14335# a1: ptr to PTENxx array/Unchanged
14336# a2: ptr to FP_SCR1(a6)/Unchanged
14337# fp0: float(ILOG)/Unchanged
14338# fp1: 10^ISCALE/Unchanged
14339# fp2: 10^LEN/Unchanged
14340# F_SCR1:BCD result with correct signs
14341# F_SCR2:ILOG/10^4
14342# L_SCR1:Exponent digits on return from binstr
14343# L_SCR2:first word of X packed/Unchanged
14344
14345A16_st:
14346 clr.l %d0 # clr d0 for collection of signs
14347 and.b &0x0f,FP_SCR0(%a6) # clear first nibble of FP_SCR0
14348 tst.l L_SCR2(%a6) # check sign of original mantissa
14349 bge.b mant_p # if pos, don't set SM
14350 mov.l &2,%d0 # move 2 in to d0 for SM
14351mant_p:
14352 tst.l %d6 # check sign of ILOG
14353 bge.b wr_sgn # if pos, don't set SE
14354 addq.l &1,%d0 # set bit 0 in d0 for SE
14355wr_sgn:
14356 bfins %d0,FP_SCR0(%a6){&0:&2} # insert SM and SE into FP_SCR0
14357
14358# Clean up and restore all registers used.
14359
14360 fmov.l &0,%fpsr # clear possible inex2/ainex bits
14361 fmovm.x (%sp)+,&0xe0 # {%fp0-%fp2}
14362 movm.l (%sp)+,&0x4fc # {%d2-%d7/%a2}
14363 rts
14364
14365 global PTENRN
14366PTENRN:
14367 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
14368 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
14369 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
14370 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
14371 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
14372 long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
14373 long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
14374 long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
14375 long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
14376 long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
14377 long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
14378 long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
14379 long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
14380
14381 global PTENRP
14382PTENRP:
14383 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
14384 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
14385 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
14386 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
14387 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
14388 long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
14389 long 0x40D30000,0xC2781F49,0xFFCFA6D6 # 10 ^ 64
14390 long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
14391 long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
14392 long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
14393 long 0x4D480000,0xC9767586,0x81750C18 # 10 ^ 1024
14394 long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
14395 long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
14396
14397 global PTENRM
14398PTENRM:
14399 long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
14400 long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
14401 long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
14402 long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
14403 long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
14404 long 0x40690000,0x9DC5ADA8,0x2B70B59D # 10 ^ 32
14405 long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
14406 long 0x41A80000,0x93BA47C9,0x80E98CDF # 10 ^ 128
14407 long 0x43510000,0xAA7EEBFB,0x9DF9DE8D # 10 ^ 256
14408 long 0x46A30000,0xE319A0AE,0xA60E91C6 # 10 ^ 512
14409 long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
14410 long 0x5A920000,0x9E8B3B5D,0xC53D5DE4 # 10 ^ 2048
14411 long 0x75250000,0xC4605202,0x8A20979A # 10 ^ 4096
14412
14413#########################################################################
14414# binstr(): Converts a 64-bit binary integer to bcd. #
14415# #
14416# INPUT *************************************************************** #
14417# d2:d3 = 64-bit binary integer #
14418# d0 = desired length (LEN) #
14419# a0 = pointer to start in memory for bcd characters #
14420# (This pointer must point to byte 4 of the first #
14421# lword of the packed decimal memory string.) #
14422# #
14423# OUTPUT ************************************************************** #
14424# a0 = pointer to LEN bcd digits representing the 64-bit integer. #
14425# #
14426# ALGORITHM *********************************************************** #
14427# The 64-bit binary is assumed to have a decimal point before #
14428# bit 63. The fraction is multiplied by 10 using a mul by 2 #
14429# shift and a mul by 8 shift. The bits shifted out of the #
14430# msb form a decimal digit. This process is iterated until #
14431# LEN digits are formed. #
14432# #
14433# A1. Init d7 to 1. D7 is the byte digit counter, and if 1, the #
14434# digit formed will be assumed the least significant. This is #
14435# to force the first byte formed to have a 0 in the upper 4 bits. #
14436# #
14437# A2. Beginning of the loop: #
14438# Copy the fraction in d2:d3 to d4:d5. #
14439# #
14440# A3. Multiply the fraction in d2:d3 by 8 using bit-field #
14441# extracts and shifts. The three msbs from d2 will go into d1. #
14442# #
14443# A4. Multiply the fraction in d4:d5 by 2 using shifts. The msb #
14444# will be collected by the carry. #
14445# #
14446# A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5 #
14447# into d2:d3. D1 will contain the bcd digit formed. #
14448# #
14449# A6. Test d7. If zero, the digit formed is the ms digit. If non- #
14450# zero, it is the ls digit. Put the digit in its place in the #
14451# upper word of d0. If it is the ls digit, write the word #
14452# from d0 to memory. #
14453# #
14454# A7. Decrement d6 (LEN counter) and repeat the loop until zero. #
14455# #
14456#########################################################################
14457
14458# Implementation Notes:
14459#
14460# The registers are used as follows:
14461#
14462# d0: LEN counter
14463# d1: temp used to form the digit
14464# d2: upper 32-bits of fraction for mul by 8
14465# d3: lower 32-bits of fraction for mul by 8
14466# d4: upper 32-bits of fraction for mul by 2
14467# d5: lower 32-bits of fraction for mul by 2
14468# d6: temp for bit-field extracts
14469# d7: byte digit formation word;digit count {0,1}
14470# a0: pointer into memory for packed bcd string formation
14471#
14472
14473 global binstr
14474binstr:
14475 movm.l &0xff00,-(%sp) # {%d0-%d7}
14476
14477#
14478# A1: Init d7
14479#
14480 mov.l &1,%d7 # init d7 for second digit
14481 subq.l &1,%d0 # for dbf d0 would have LEN+1 passes
14482#
14483# A2. Copy d2:d3 to d4:d5. Start loop.
14484#
14485loop:
14486 mov.l %d2,%d4 # copy the fraction before muls
14487 mov.l %d3,%d5 # to d4:d5
14488#
14489# A3. Multiply d2:d3 by 8; extract msbs into d1.
14490#
14491 bfextu %d2{&0:&3},%d1 # copy 3 msbs of d2 into d1
14492 asl.l &3,%d2 # shift d2 left by 3 places
14493 bfextu %d3{&0:&3},%d6 # copy 3 msbs of d3 into d6
14494 asl.l &3,%d3 # shift d3 left by 3 places
14495 or.l %d6,%d2 # or in msbs from d3 into d2
14496#
14497# A4. Multiply d4:d5 by 2; add carry out to d1.
14498#
14499 asl.l &1,%d5 # mul d5 by 2
14500 roxl.l &1,%d4 # mul d4 by 2
14501 swap %d6 # put 0 in d6 lower word
14502 addx.w %d6,%d1 # add in extend from mul by 2
14503#
14504# A5. Add mul by 8 to mul by 2. D1 contains the digit formed.
14505#
14506 add.l %d5,%d3 # add lower 32 bits
14507 nop # ERRATA FIX #13 (Rev. 1.2 6/6/90)
14508 addx.l %d4,%d2 # add with extend upper 32 bits
14509 nop # ERRATA FIX #13 (Rev. 1.2 6/6/90)
14510 addx.w %d6,%d1 # add in extend from add to d1
14511 swap %d6 # with d6 = 0; put 0 in upper word
14512#
14513# A6. Test d7 and branch.
14514#
14515 tst.w %d7 # if zero, store digit & to loop
14516 beq.b first_d # if non-zero, form byte & write
14517sec_d:
14518 swap %d7 # bring first digit to word d7b
14519 asl.w &4,%d7 # first digit in upper 4 bits d7b
14520 add.w %d1,%d7 # add in ls digit to d7b
14521 mov.b %d7,(%a0)+ # store d7b byte in memory
14522 swap %d7 # put LEN counter in word d7a
14523 clr.w %d7 # set d7a to signal no digits done
14524 dbf.w %d0,loop # do loop some more!
14525 bra.b end_bstr # finished, so exit
14526first_d:
14527 swap %d7 # put digit word in d7b
14528 mov.w %d1,%d7 # put new digit in d7b
14529 swap %d7 # put LEN counter in word d7a
14530 addq.w &1,%d7 # set d7a to signal first digit done
14531 dbf.w %d0,loop # do loop some more!
14532 swap %d7 # put last digit in string
14533 lsl.w &4,%d7 # move it to upper 4 bits
14534 mov.b %d7,(%a0)+ # store it in memory string
14535#
14536# Clean up and return with result in fp0.
14537#
14538end_bstr:
14539 movm.l (%sp)+,&0xff # {%d0-%d7}
14540 rts
14541
14542#########################################################################
14543# XDEF **************************************************************** #
14544# facc_in_b(): dmem_read_byte failed #
14545# facc_in_w(): dmem_read_word failed #
14546# facc_in_l(): dmem_read_long failed #
14547# facc_in_d(): dmem_read of dbl prec failed #
14548# facc_in_x(): dmem_read of ext prec failed #
14549# #
14550# facc_out_b(): dmem_write_byte failed #
14551# facc_out_w(): dmem_write_word failed #
14552# facc_out_l(): dmem_write_long failed #
14553# facc_out_d(): dmem_write of dbl prec failed #
14554# facc_out_x(): dmem_write of ext prec failed #
14555# #
14556# XREF **************************************************************** #
14557# _real_access() - exit through access error handler #
14558# #
14559# INPUT *************************************************************** #
14560# None #
14561# #
14562# OUTPUT ************************************************************** #
14563# None #
14564# #
14565# ALGORITHM *********************************************************** #
14566# Flow jumps here when an FP data fetch call gets an error #
14567# result. This means the operating system wants an access error frame #
14568# made out of the current exception stack frame. #
14569# So, we first call restore() which makes sure that any updated #
14570# -(an)+ register gets returned to its pre-exception value and then #
14571# we change the stack to an access error stack frame. #
14572# #
14573#########################################################################
14574
14575facc_in_b:
14576 movq.l &0x1,%d0 # one byte
14577 bsr.w restore # fix An
14578
14579 mov.w &0x0121,EXC_VOFF(%a6) # set FSLW
14580 bra.w facc_finish
14581
14582facc_in_w:
14583 movq.l &0x2,%d0 # two bytes
14584 bsr.w restore # fix An
14585
14586 mov.w &0x0141,EXC_VOFF(%a6) # set FSLW
14587 bra.b facc_finish
14588
14589facc_in_l:
14590 movq.l &0x4,%d0 # four bytes
14591 bsr.w restore # fix An
14592
14593 mov.w &0x0101,EXC_VOFF(%a6) # set FSLW
14594 bra.b facc_finish
14595
14596facc_in_d:
14597 movq.l &0x8,%d0 # eight bytes
14598 bsr.w restore # fix An
14599
14600 mov.w &0x0161,EXC_VOFF(%a6) # set FSLW
14601 bra.b facc_finish
14602
14603facc_in_x:
14604 movq.l &0xc,%d0 # twelve bytes
14605 bsr.w restore # fix An
14606
14607 mov.w &0x0161,EXC_VOFF(%a6) # set FSLW
14608 bra.b facc_finish
14609
14610################################################################
14611
14612facc_out_b:
14613 movq.l &0x1,%d0 # one byte
14614 bsr.w restore # restore An
14615
14616 mov.w &0x00a1,EXC_VOFF(%a6) # set FSLW
14617 bra.b facc_finish
14618
14619facc_out_w:
14620 movq.l &0x2,%d0 # two bytes
14621 bsr.w restore # restore An
14622
14623 mov.w &0x00c1,EXC_VOFF(%a6) # set FSLW
14624 bra.b facc_finish
14625
14626facc_out_l:
14627 movq.l &0x4,%d0 # four bytes
14628 bsr.w restore # restore An
14629
14630 mov.w &0x0081,EXC_VOFF(%a6) # set FSLW
14631 bra.b facc_finish
14632
14633facc_out_d:
14634 movq.l &0x8,%d0 # eight bytes
14635 bsr.w restore # restore An
14636
14637 mov.w &0x00e1,EXC_VOFF(%a6) # set FSLW
14638 bra.b facc_finish
14639
14640facc_out_x:
14641 mov.l &0xc,%d0 # twelve bytes
14642 bsr.w restore # restore An
14643
14644 mov.w &0x00e1,EXC_VOFF(%a6) # set FSLW
14645
14646# here's where we actually create the access error frame from the
14647# current exception stack frame.
14648facc_finish:
14649 mov.l USER_FPIAR(%a6),EXC_PC(%a6) # store current PC
14650
14651 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
14652 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
14653 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
14654
14655 unlk %a6
14656
14657 mov.l (%sp),-(%sp) # store SR, hi(PC)
14658 mov.l 0x8(%sp),0x4(%sp) # store lo(PC)
14659 mov.l 0xc(%sp),0x8(%sp) # store EA
14660 mov.l &0x00000001,0xc(%sp) # store FSLW
14661 mov.w 0x6(%sp),0xc(%sp) # fix FSLW (size)
14662 mov.w &0x4008,0x6(%sp) # store voff
14663
14664 btst &0x5,(%sp) # supervisor or user mode?
14665 beq.b facc_out2 # user
14666 bset &0x2,0xd(%sp) # set supervisor TM bit
14667
14668facc_out2:
14669 bra.l _real_access
14670
14671##################################################################
14672
14673# if the effective addressing mode was predecrement or postincrement,
14674# the emulation has already changed its value to the correct post-
14675# instruction value. but since we're exiting to the access error
14676# handler, then AN must be returned to its pre-instruction value.
14677# we do that here.
14678restore:
14679 mov.b EXC_OPWORD+0x1(%a6),%d1
14680 andi.b &0x38,%d1 # extract opmode
14681 cmpi.b %d1,&0x18 # postinc?
14682 beq.w rest_inc
14683 cmpi.b %d1,&0x20 # predec?
14684 beq.w rest_dec
14685 rts
14686
14687rest_inc:
14688 mov.b EXC_OPWORD+0x1(%a6),%d1
14689 andi.w &0x0007,%d1 # fetch An
14690
14691 mov.w (tbl_rest_inc.b,%pc,%d1.w*2),%d1
14692 jmp (tbl_rest_inc.b,%pc,%d1.w*1)
14693
14694tbl_rest_inc:
14695 short ri_a0 - tbl_rest_inc
14696 short ri_a1 - tbl_rest_inc
14697 short ri_a2 - tbl_rest_inc
14698 short ri_a3 - tbl_rest_inc
14699 short ri_a4 - tbl_rest_inc
14700 short ri_a5 - tbl_rest_inc
14701 short ri_a6 - tbl_rest_inc
14702 short ri_a7 - tbl_rest_inc
14703
14704ri_a0:
14705 sub.l %d0,EXC_DREGS+0x8(%a6) # fix stacked a0
14706 rts
14707ri_a1:
14708 sub.l %d0,EXC_DREGS+0xc(%a6) # fix stacked a1
14709 rts
14710ri_a2:
14711 sub.l %d0,%a2 # fix a2
14712 rts
14713ri_a3:
14714 sub.l %d0,%a3 # fix a3
14715 rts
14716ri_a4:
14717 sub.l %d0,%a4 # fix a4
14718 rts
14719ri_a5:
14720 sub.l %d0,%a5 # fix a5
14721 rts
14722ri_a6:
14723 sub.l %d0,(%a6) # fix stacked a6
14724 rts
14725# if it's a fmove out instruction, we don't have to fix a7
14726# because we hadn't changed it yet. if it's an opclass two
14727# instruction (data moved in) and the exception was in supervisor
14728# mode, then also also wasn't updated. if it was user mode, then
14729# restore the correct a7 which is in the USP currently.
14730ri_a7:
14731 cmpi.b EXC_VOFF(%a6),&0x30 # move in or out?
14732 bne.b ri_a7_done # out
14733
14734 btst &0x5,EXC_SR(%a6) # user or supervisor?
14735 bne.b ri_a7_done # supervisor
14736 movc %usp,%a0 # restore USP
14737 sub.l %d0,%a0
14738 movc %a0,%usp
14739ri_a7_done:
14740 rts
14741
14742# need to invert adjustment value if the <ea> was predec
14743rest_dec:
14744 neg.l %d0
14745 bra.b rest_inc
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
new file mode 100644
index 000000000000..458925c471a1
--- /dev/null
+++ b/arch/m68k/kernel/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for the linux kernel.
3#
4
5ifndef CONFIG_SUN3
6 extra-y := head.o
7else
8 extra-y := sun3-head.o
9endif
10extra-y += vmlinux.lds
11
12obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \
13 sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
14
15obj-$(CONFIG_PCI) += bios32.o
16obj-$(CONFIG_MODULES) += module.o
17
18EXTRA_AFLAGS := -traditional
diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c
new file mode 100644
index 000000000000..cee3317b8665
--- /dev/null
+++ b/arch/m68k/kernel/asm-offsets.c
@@ -0,0 +1,109 @@
1/*
2 * This program is used to generate definitions needed by
3 * assembly language modules.
4 *
5 * We use the technique used in the OSF Mach kernel code:
6 * generate asm statements containing #defines,
7 * compile this file to assembler, and then extract the
8 * #defines from the assembly-language output.
9 */
10
11#include <linux/stddef.h>
12#include <linux/sched.h>
13#include <linux/kernel_stat.h>
14#include <asm/bootinfo.h>
15#include <asm/irq.h>
16#include <asm/amigahw.h>
17#include <linux/font.h>
18
19#define DEFINE(sym, val) \
20 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
21
22int main(void)
23{
24 /* offsets into the task struct */
25 DEFINE(TASK_STATE, offsetof(struct task_struct, state));
26 DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
27 DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
28 DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work));
29 DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched));
30 DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace));
31 DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending));
32 DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume));
33 DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
34 DEFINE(TASK_MM, offsetof(struct task_struct, mm));
35 DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
36
37 /* offsets into the thread struct */
38 DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
39 DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
40 DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
41 DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
42 DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
43 DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
44 DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
45 DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
46 DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
47
48 /* offsets into the pt_regs */
49 DEFINE(PT_D0, offsetof(struct pt_regs, d0));
50 DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
51 DEFINE(PT_D1, offsetof(struct pt_regs, d1));
52 DEFINE(PT_D2, offsetof(struct pt_regs, d2));
53 DEFINE(PT_D3, offsetof(struct pt_regs, d3));
54 DEFINE(PT_D4, offsetof(struct pt_regs, d4));
55 DEFINE(PT_D5, offsetof(struct pt_regs, d5));
56 DEFINE(PT_A0, offsetof(struct pt_regs, a0));
57 DEFINE(PT_A1, offsetof(struct pt_regs, a1));
58 DEFINE(PT_A2, offsetof(struct pt_regs, a2));
59 DEFINE(PT_PC, offsetof(struct pt_regs, pc));
60 DEFINE(PT_SR, offsetof(struct pt_regs, sr));
61 /* bitfields are a bit difficult */
62 DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
63
64 /* offsets into the irq_handler struct */
65 DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
66 DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
67 DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
68
69 /* offsets into the kernel_stat struct */
70 DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
71
72 /* offsets into the irq_cpustat_t struct */
73 DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
74
75 /* offsets into the bi_record struct */
76 DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
77 DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
78 DEFINE(BIR_DATA, offsetof(struct bi_record, data));
79
80 /* offsets into font_desc (drivers/video/console/font.h) */
81 DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
82 DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
83 DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
84 DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
85 DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
86 DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
87
88 /* signal defines */
89 DEFINE(SIGSEGV, SIGSEGV);
90 DEFINE(SEGV_MAPERR, SEGV_MAPERR);
91 DEFINE(SIGTRAP, SIGTRAP);
92 DEFINE(TRAP_TRACE, TRAP_TRACE);
93
94 /* offsets into the custom struct */
95 DEFINE(CUSTOMBASE, &custom);
96 DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
97 DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
98 DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
99 DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
100 DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
101 DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
102 DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
103 DEFINE(CIAABASE, &ciaa);
104 DEFINE(CIABBASE, &ciab);
105 DEFINE(C_PRA, offsetof(struct CIA, pra));
106 DEFINE(ZTWOBASE, zTwoBase);
107
108 return 0;
109}
diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c
new file mode 100644
index 000000000000..a901685eb6a9
--- /dev/null
+++ b/arch/m68k/kernel/bios32.c
@@ -0,0 +1,515 @@
1/*
2 * bios32.c - PCI BIOS functions for m68k systems.
3 *
4 * Written by Wout Klaren.
5 *
6 * Based on the DEC Alpha bios32.c by Dave Rusling and David Mosberger.
7 */
8
9#include <linux/config.h>
10#include <linux/init.h>
11#include <linux/kernel.h>
12
13#if 0
14# define DBG_DEVS(args) printk args
15#else
16# define DBG_DEVS(args)
17#endif
18
19#ifdef CONFIG_PCI
20
21/*
22 * PCI support for Linux/m68k. Currently only the Hades is supported.
23 *
24 * The support for PCI bridges in the DEC Alpha version has
25 * been removed in this version.
26 */
27
28#include <linux/pci.h>
29#include <linux/slab.h>
30#include <linux/mm.h>
31
32#include <asm/io.h>
33#include <asm/pci.h>
34#include <asm/uaccess.h>
35
36#define KB 1024
37#define MB (1024*KB)
38#define GB (1024*MB)
39
40#define MAJOR_REV 0
41#define MINOR_REV 5
42
43/*
44 * Align VAL to ALIGN, which must be a power of two.
45 */
46
47#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
48
49/*
50 * Offsets relative to the I/O and memory base addresses from where resources
51 * are allocated.
52 */
53
54#define IO_ALLOC_OFFSET 0x00004000
55#define MEM_ALLOC_OFFSET 0x04000000
56
57/*
58 * Declarations of hardware specific initialisation functions.
59 */
60
61extern struct pci_bus_info *init_hades_pci(void);
62
63/*
64 * Bus info structure of the PCI bus. A pointer to this structure is
65 * put in the sysdata member of the pci_bus structure.
66 */
67
68static struct pci_bus_info *bus_info;
69
70static int pci_modify = 1; /* If set, layout the PCI bus ourself. */
71static int skip_vga; /* If set do not modify base addresses
72 of vga cards.*/
73static int disable_pci_burst; /* If set do not allow PCI bursts. */
74
75static unsigned int io_base;
76static unsigned int mem_base;
77
78/*
79 * static void disable_dev(struct pci_dev *dev)
80 *
81 * Disable PCI device DEV so that it does not respond to I/O or memory
82 * accesses.
83 *
84 * Parameters:
85 *
86 * dev - device to disable.
87 */
88
89static void __init disable_dev(struct pci_dev *dev)
90{
91 unsigned short cmd;
92
93 if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
94 (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
95 (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
96 return;
97
98 pci_read_config_word(dev, PCI_COMMAND, &cmd);
99
100 cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
101 pci_write_config_word(dev, PCI_COMMAND, cmd);
102}
103
104/*
105 * static void layout_dev(struct pci_dev *dev)
106 *
107 * Layout memory and I/O for a device.
108 *
109 * Parameters:
110 *
111 * device - device to layout memory and I/O for.
112 */
113
114static void __init layout_dev(struct pci_dev *dev)
115{
116 unsigned short cmd;
117 unsigned int base, mask, size, reg;
118 unsigned int alignto;
119 int i;
120
121 /*
122 * Skip video cards if requested.
123 */
124
125 if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
126 (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
127 (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
128 return;
129
130 pci_read_config_word(dev, PCI_COMMAND, &cmd);
131
132 for (reg = PCI_BASE_ADDRESS_0, i = 0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++)
133 {
134 /*
135 * Figure out how much space and of what type this
136 * device wants.
137 */
138
139 pci_write_config_dword(dev, reg, 0xffffffff);
140 pci_read_config_dword(dev, reg, &base);
141
142 if (!base)
143 {
144 /* this base-address register is unused */
145 dev->resource[i].start = 0;
146 dev->resource[i].end = 0;
147 dev->resource[i].flags = 0;
148 continue;
149 }
150
151 /*
152 * We've read the base address register back after
153 * writing all ones and so now we must decode it.
154 */
155
156 if (base & PCI_BASE_ADDRESS_SPACE_IO)
157 {
158 /*
159 * I/O space base address register.
160 */
161
162 cmd |= PCI_COMMAND_IO;
163
164 base &= PCI_BASE_ADDRESS_IO_MASK;
165 mask = (~base << 1) | 0x1;
166 size = (mask & base) & 0xffffffff;
167
168 /*
169 * Align to multiple of size of minimum base.
170 */
171
172 alignto = max_t(unsigned int, 0x040, size);
173 base = ALIGN(io_base, alignto);
174 io_base = base + size;
175 pci_write_config_dword(dev, reg, base | PCI_BASE_ADDRESS_SPACE_IO);
176
177 dev->resource[i].start = base;
178 dev->resource[i].end = dev->resource[i].start + size - 1;
179 dev->resource[i].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
180
181 DBG_DEVS(("layout_dev: IO address: %lX\n", base));
182 }
183 else
184 {
185 unsigned int type;
186
187 /*
188 * Memory space base address register.
189 */
190
191 cmd |= PCI_COMMAND_MEMORY;
192 type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
193 base &= PCI_BASE_ADDRESS_MEM_MASK;
194 mask = (~base << 1) | 0x1;
195 size = (mask & base) & 0xffffffff;
196 switch (type)
197 {
198 case PCI_BASE_ADDRESS_MEM_TYPE_32:
199 case PCI_BASE_ADDRESS_MEM_TYPE_64:
200 break;
201
202 case PCI_BASE_ADDRESS_MEM_TYPE_1M:
203 printk("bios32 WARNING: slot %d, function %d "
204 "requests memory below 1MB---don't "
205 "know how to do that.\n",
206 PCI_SLOT(dev->devfn),
207 PCI_FUNC(dev->devfn));
208 continue;
209 }
210
211 /*
212 * Align to multiple of size of minimum base.
213 */
214
215 alignto = max_t(unsigned int, 0x1000, size);
216 base = ALIGN(mem_base, alignto);
217 mem_base = base + size;
218 pci_write_config_dword(dev, reg, base);
219
220 dev->resource[i].start = base;
221 dev->resource[i].end = dev->resource[i].start + size - 1;
222 dev->resource[i].flags = IORESOURCE_MEM;
223
224 if (type == PCI_BASE_ADDRESS_MEM_TYPE_64)
225 {
226 /*
227 * 64-bit address, set the highest 32 bits
228 * to zero.
229 */
230
231 reg += 4;
232 pci_write_config_dword(dev, reg, 0);
233
234 i++;
235 dev->resource[i].start = 0;
236 dev->resource[i].end = 0;
237 dev->resource[i].flags = 0;
238 }
239 }
240 }
241
242 /*
243 * Enable device:
244 */
245
246 if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
247 dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
248 dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
249 dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
250 {
251 /*
252 * All of these (may) have I/O scattered all around
253 * and may not use i/o-base address registers at all.
254 * So we just have to always enable I/O to these
255 * devices.
256 */
257 cmd |= PCI_COMMAND_IO;
258 }
259
260 pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
261
262 pci_write_config_byte(dev, PCI_LATENCY_TIMER, (disable_pci_burst) ? 0 : 32);
263
264 if (bus_info != NULL)
265 bus_info->conf_device(dev); /* Machine dependent configuration. */
266
267 DBG_DEVS(("layout_dev: bus %d slot 0x%x VID 0x%x DID 0x%x class 0x%x\n",
268 dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
269}
270
271/*
272 * static void layout_bus(struct pci_bus *bus)
273 *
274 * Layout memory and I/O for all devices on the given bus.
275 *
276 * Parameters:
277 *
278 * bus - bus.
279 */
280
281static void __init layout_bus(struct pci_bus *bus)
282{
283 unsigned int bio, bmem;
284 struct pci_dev *dev;
285
286 DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
287
288 if (!bus->devices && !bus->children)
289 return;
290
291 /*
292 * Align the current bases on appropriate boundaries (4K for
293 * IO and 1MB for memory).
294 */
295
296 bio = io_base = ALIGN(io_base, 4*KB);
297 bmem = mem_base = ALIGN(mem_base, 1*MB);
298
299 /*
300 * PCI devices might have been setup by a PCI BIOS emulation
301 * running under TOS. In these cases there is a
302 * window during which two devices may have an overlapping
303 * address range. To avoid this causing trouble, we first
304 * turn off the I/O and memory address decoders for all PCI
305 * devices. They'll be re-enabled only once all address
306 * decoders are programmed consistently.
307 */
308
309 DBG_DEVS(("layout_bus: disable_dev for bus %d\n", bus->number));
310
311 for (dev = bus->devices; dev; dev = dev->sibling)
312 {
313 if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
314 (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
315 disable_dev(dev);
316 }
317
318 /*
319 * Allocate space to each device:
320 */
321
322 DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number));
323
324 for (dev = bus->devices; dev; dev = dev->sibling)
325 {
326 if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
327 (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
328 layout_dev(dev);
329 }
330
331 DBG_DEVS(("layout_bus: bus %d finished\n", bus->number));
332}
333
334/*
335 * static void pcibios_fixup(void)
336 *
337 * Layout memory and I/O of all devices on the PCI bus if 'pci_modify' is
338 * true. This might be necessary because not every m68k machine with a PCI
339 * bus has a PCI BIOS. This function should be called right after
340 * pci_scan_bus() in pcibios_init().
341 */
342
343static void __init pcibios_fixup(void)
344{
345 if (pci_modify)
346 {
347 /*
348 * Set base addresses for allocation of I/O and memory space.
349 */
350
351 io_base = bus_info->io_space.start + IO_ALLOC_OFFSET;
352 mem_base = bus_info->mem_space.start + MEM_ALLOC_OFFSET;
353
354 /*
355 * Scan the tree, allocating PCI memory and I/O space.
356 */
357
358 layout_bus(pci_bus_b(pci_root.next));
359 }
360
361 /*
362 * Fix interrupt assignments, etc.
363 */
364
365 bus_info->fixup(pci_modify);
366}
367
368/*
369 * static void pcibios_claim_resources(struct pci_bus *bus)
370 *
371 * Claim all resources that are assigned to devices on the given bus.
372 *
373 * Parameters:
374 *
375 * bus - bus.
376 */
377
378static void __init pcibios_claim_resources(struct pci_bus *bus)
379{
380 struct pci_dev *dev;
381 int i;
382
383 while (bus)
384 {
385 for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
386 {
387 for (i = 0; i < PCI_NUM_RESOURCES; i++)
388 {
389 struct resource *r = &dev->resource[i];
390 struct resource *pr;
391 struct pci_bus_info *bus_info = (struct pci_bus_info *) dev->sysdata;
392
393 if ((r->start == 0) || (r->parent != NULL))
394 continue;
395#if 1
396 if (r->flags & IORESOURCE_IO)
397 pr = &bus_info->io_space;
398 else
399 pr = &bus_info->mem_space;
400#else
401 if (r->flags & IORESOURCE_IO)
402 pr = &ioport_resource;
403 else
404 pr = &iomem_resource;
405#endif
406 if (request_resource(pr, r) < 0)
407 {
408 printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", i, dev->name);
409 }
410 }
411 }
412
413 if (bus->children)
414 pcibios_claim_resources(bus->children);
415
416 bus = bus->next;
417 }
418}
419
420/*
421 * int pcibios_assign_resource(struct pci_dev *dev, int i)
422 *
423 * Assign a new address to a PCI resource.
424 *
425 * Parameters:
426 *
427 * dev - device.
428 * i - resource.
429 *
430 * Result: 0 if successful.
431 */
432
433int __init pcibios_assign_resource(struct pci_dev *dev, int i)
434{
435 struct resource *r = &dev->resource[i];
436 struct resource *pr = pci_find_parent_resource(dev, r);
437 unsigned long size = r->end + 1;
438
439 if (!pr)
440 return -EINVAL;
441
442 if (r->flags & IORESOURCE_IO)
443 {
444 if (size > 0x100)
445 return -EFBIG;
446
447 if (allocate_resource(pr, r, size, bus_info->io_space.start +
448 IO_ALLOC_OFFSET, bus_info->io_space.end, 1024))
449 return -EBUSY;
450 }
451 else
452 {
453 if (allocate_resource(pr, r, size, bus_info->mem_space.start +
454 MEM_ALLOC_OFFSET, bus_info->mem_space.end, size))
455 return -EBUSY;
456 }
457
458 if (i < 6)
459 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, r->start);
460
461 return 0;
462}
463
464void __init pcibios_fixup_bus(struct pci_bus *bus)
465{
466 struct pci_dev *dev;
467 void *sysdata;
468
469 sysdata = (bus->parent) ? bus->parent->sysdata : bus->sysdata;
470
471 for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
472 dev->sysdata = sysdata;
473}
474
475void __init pcibios_init(void)
476{
477 printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
478
479 bus_info = NULL;
480#ifdef CONFIG_HADES
481 if (MACH_IS_HADES)
482 bus_info = init_hades_pci();
483#endif
484 if (bus_info != NULL)
485 {
486 printk("PCI: Probing PCI hardware\n");
487 pci_scan_bus(0, bus_info->m68k_pci_ops, bus_info);
488 pcibios_fixup();
489 pcibios_claim_resources(pci_root);
490 }
491 else
492 printk("PCI: No PCI bus detected\n");
493}
494
495char * __init pcibios_setup(char *str)
496{
497 if (!strcmp(str, "nomodify"))
498 {
499 pci_modify = 0;
500 return NULL;
501 }
502 else if (!strcmp(str, "skipvga"))
503 {
504 skip_vga = 1;
505 return NULL;
506 }
507 else if (!strcmp(str, "noburst"))
508 {
509 disable_pci_burst = 1;
510 return NULL;
511 }
512
513 return str;
514}
515#endif /* CONFIG_PCI */
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
new file mode 100644
index 000000000000..e964015a31dc
--- /dev/null
+++ b/arch/m68k/kernel/entry.S
@@ -0,0 +1,712 @@
1/* -*- mode: asm -*-
2 *
3 * linux/arch/m68k/kernel/entry.S
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file README.legal in the main directory of this archive
9 * for more details.
10 *
11 * Linux/m68k support by Hamish Macdonald
12 *
13 * 68060 fixes by Jesper Skov
14 *
15 */
16
17/*
18 * entry.S contains the system-call and fault low-level handling routines.
19 * This also contains the timer-interrupt handler, as well as all interrupts
20 * and faults that can result in a task-switch.
21 *
22 * NOTE: This code handles signal-recognition, which happens every time
23 * after a timer-interrupt and after each system call.
24 *
25 */
26
27/*
28 * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
29 * all pointers that used to be 'current' are now entry
30 * number 0 in the 'current_set' list.
31 *
32 * 6/05/00 RZ: addedd writeback completion after return from sighandler
33 * for 68040
34 */
35
36#include <linux/config.h>
37#include <linux/linkage.h>
38#include <asm/entry.h>
39#include <asm/errno.h>
40#include <asm/setup.h>
41#include <asm/segment.h>
42#include <asm/traps.h>
43#include <asm/unistd.h>
44
45#include <asm/offsets.h>
46
47.globl system_call, buserr, trap
48.globl resume, ret_from_exception
49.globl ret_from_signal
50.globl inthandler, sys_call_table
51.globl sys_fork, sys_clone, sys_vfork
52.globl ret_from_interrupt, bad_interrupt
53
54.text
55ENTRY(buserr)
56 SAVE_ALL_INT
57 GET_CURRENT(%d0)
58 movel %sp,%sp@- | stack frame pointer argument
59 bsrl buserr_c
60 addql #4,%sp
61 jra ret_from_exception
62
63ENTRY(trap)
64 SAVE_ALL_INT
65 GET_CURRENT(%d0)
66 movel %sp,%sp@- | stack frame pointer argument
67 bsrl trap_c
68 addql #4,%sp
69 jra ret_from_exception
70
71 | After a fork we jump here directly from resume,
72 | so that %d1 contains the previous task
73 | schedule_tail now used regardless of CONFIG_SMP
74ENTRY(ret_from_fork)
75 movel %d1,%sp@-
76 jsr schedule_tail
77 addql #4,%sp
78 jra ret_from_exception
79
80badsys:
81 movel #-ENOSYS,%sp@(PT_D0)
82 jra ret_from_exception
83
84do_trace:
85 movel #-ENOSYS,%sp@(PT_D0) | needed for strace
86 subql #4,%sp
87 SAVE_SWITCH_STACK
88 jbsr syscall_trace
89 RESTORE_SWITCH_STACK
90 addql #4,%sp
91 movel %sp@(PT_ORIG_D0),%d1
92 movel #-ENOSYS,%d0
93 cmpl #NR_syscalls,%d1
94 jcc 1f
95 jbsr @(sys_call_table,%d1:l:4)@(0)
961: movel %d0,%sp@(PT_D0) | save the return value
97 subql #4,%sp | dummy return address
98 SAVE_SWITCH_STACK
99 jbsr syscall_trace
100
101ret_from_signal:
102 RESTORE_SWITCH_STACK
103 addql #4,%sp
104/* on 68040 complete pending writebacks if any */
105#ifdef CONFIG_M68040
106 bfextu %sp@(PT_VECTOR){#0,#4},%d0
107 subql #7,%d0 | bus error frame ?
108 jbne 1f
109 movel %sp,%sp@-
110 jbsr berr_040cleanup
111 addql #4,%sp
1121:
113#endif
114 jra ret_from_exception
115
116ENTRY(system_call)
117 SAVE_ALL_SYS
118
119 GET_CURRENT(%d1)
120 | save top of frame
121 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
122
123 tstb %curptr@(TASK_SYSCALL_TRACE)
124 jne do_trace
125 cmpl #NR_syscalls,%d0
126 jcc badsys
127 jbsr @(sys_call_table,%d0:l:4)@(0)
128 movel %d0,%sp@(PT_D0) | save the return value
129
130 |oriw #0x0700,%sr
131 movel %curptr@(TASK_WORK),%d0
132 jne syscall_exit_work
1331: RESTORE_ALL
134
135syscall_exit_work:
136 btst #5,%sp@(PT_SR) | check if returning to kernel
137 bnes 1b | if so, skip resched, signals
138 tstw %d0
139 jeq do_signal_return
140 tstb %d0
141 jne do_delayed_trace
142
143 pea resume_userspace
144 jmp schedule
145
146ret_from_exception:
147 btst #5,%sp@(PT_SR) | check if returning to kernel
148 bnes 1f | if so, skip resched, signals
149 | only allow interrupts when we are really the last one on the
150 | kernel stack, otherwise stack overflow can occur during
151 | heavy interrupt load
152 andw #ALLOWINT,%sr
153
154resume_userspace:
155 movel %curptr@(TASK_WORK),%d0
156 lsrl #8,%d0
157 jne exit_work
1581: RESTORE_ALL
159
160exit_work:
161 | save top of frame
162 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
163 tstb %d0
164 jeq do_signal_return
165
166 pea resume_userspace
167 jmp schedule
168
169do_signal_return:
170 |andw #ALLOWINT,%sr
171 subql #4,%sp | dummy return address
172 SAVE_SWITCH_STACK
173 pea %sp@(SWITCH_STACK_SIZE)
174 clrl %sp@-
175 bsrl do_signal
176 addql #8,%sp
177 RESTORE_SWITCH_STACK
178 addql #4,%sp
179 jbra resume_userspace
180
181do_delayed_trace:
182 bclr #7,%sp@(PT_SR) | clear trace bit in SR
183 pea 1 | send SIGTRAP
184 movel %curptr,%sp@-
185 pea LSIGTRAP
186 jbsr send_sig
187 addql #8,%sp
188 addql #4,%sp
189 jbra resume_userspace
190
191
192#if 0
193#ifdef CONFIG_AMIGA
194ami_inthandler:
195 addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT
196 SAVE_ALL_INT
197 GET_CURRENT(%d0)
198
199 bfextu %sp@(PT_VECTOR){#4,#12},%d0
200 movel %d0,%a0
201 addql #1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR))
202 movel %a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0
203
204| amiga vector int handler get the req mask instead of irq vector
205 lea CUSTOMBASE,%a1
206 movew %a1@(C_INTREQR),%d0
207 andw %a1@(C_INTENAR),%d0
208
209| prepare stack (push frame pointer, dev_id & req mask)
210 pea %sp@
211 movel %a0@(IRQ_DEVID),%sp@-
212 movel %d0,%sp@-
213 pea %pc@(ret_from_interrupt:w)
214 jbra @(IRQ_HANDLER,%a0)@(0)
215
216ENTRY(nmi_handler)
217 rte
218#endif
219#endif
220
221/*
222** This is the main interrupt handler, responsible for calling process_int()
223*/
224inthandler:
225 SAVE_ALL_INT
226 GET_CURRENT(%d0)
227 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
228 | put exception # in d0
229 bfextu %sp@(PT_VECTOR){#4,#10},%d0
230
231 movel %sp,%sp@-
232 movel %d0,%sp@- | put vector # on stack
233#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
234 btstb #4,0xff000000 | Q40 floppy needs very special treatment ...
235 jbeq 1f
236 btstb #3,0xff000004
237 jbeq 1f
238 jbsr floppy_hardint
239 jbra 3f
2401:
241#endif
242 jbsr process_int | process the IRQ
2433: addql #8,%sp | pop parameters off stack
244
245ret_from_interrupt:
246 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
247 jeq 1f
2482:
249 RESTORE_ALL
2501:
251 moveq #(~ALLOWINT>>8)&0xff,%d0
252 andb %sp@(PT_SR),%d0
253 jne 2b
254
255 /* check if we need to do software interrupts */
256 tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
257 jeq ret_from_exception
258 pea ret_from_exception
259 jra do_softirq
260
261
262/* Handler for uninitialized and spurious interrupts */
263
264bad_interrupt:
265 addql #1,num_spurious
266 rte
267
268ENTRY(sys_fork)
269 SAVE_SWITCH_STACK
270 pea %sp@(SWITCH_STACK_SIZE)
271 jbsr m68k_fork
272 addql #4,%sp
273 RESTORE_SWITCH_STACK
274 rts
275
276ENTRY(sys_clone)
277 SAVE_SWITCH_STACK
278 pea %sp@(SWITCH_STACK_SIZE)
279 jbsr m68k_clone
280 addql #4,%sp
281 RESTORE_SWITCH_STACK
282 rts
283
284ENTRY(sys_vfork)
285 SAVE_SWITCH_STACK
286 pea %sp@(SWITCH_STACK_SIZE)
287 jbsr m68k_vfork
288 addql #4,%sp
289 RESTORE_SWITCH_STACK
290 rts
291
292ENTRY(sys_sigsuspend)
293 SAVE_SWITCH_STACK
294 pea %sp@(SWITCH_STACK_SIZE)
295 jbsr do_sigsuspend
296 addql #4,%sp
297 RESTORE_SWITCH_STACK
298 rts
299
300ENTRY(sys_rt_sigsuspend)
301 SAVE_SWITCH_STACK
302 pea %sp@(SWITCH_STACK_SIZE)
303 jbsr do_rt_sigsuspend
304 addql #4,%sp
305 RESTORE_SWITCH_STACK
306 rts
307
308ENTRY(sys_sigreturn)
309 SAVE_SWITCH_STACK
310 jbsr do_sigreturn
311 RESTORE_SWITCH_STACK
312 rts
313
314ENTRY(sys_rt_sigreturn)
315 SAVE_SWITCH_STACK
316 jbsr do_rt_sigreturn
317 RESTORE_SWITCH_STACK
318 rts
319
320resume:
321 /*
322 * Beware - when entering resume, prev (the current task) is
323 * in a0, next (the new task) is in a1,so don't change these
324 * registers until their contents are no longer needed.
325 */
326
327 /* save sr */
328 movew %sr,%a0@(TASK_THREAD+THREAD_SR)
329
330 /* save fs (sfc,%dfc) (may be pointing to kernel memory) */
331 movec %sfc,%d0
332 movew %d0,%a0@(TASK_THREAD+THREAD_FS)
333
334 /* save usp */
335 /* it is better to use a movel here instead of a movew 8*) */
336 movec %usp,%d0
337 movel %d0,%a0@(TASK_THREAD+THREAD_USP)
338
339 /* save non-scratch registers on stack */
340 SAVE_SWITCH_STACK
341
342 /* save current kernel stack pointer */
343 movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
344
345 /* save floating point context */
346#ifndef CONFIG_M68KFPU_EMU_ONLY
347#ifdef CONFIG_M68KFPU_EMU
348 tstl m68k_fputype
349 jeq 3f
350#endif
351 fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
352
353#if defined(CONFIG_M68060)
354#if !defined(CPU_M68060_ONLY)
355 btst #3,m68k_cputype+3
356 beqs 1f
357#endif
358 /* The 060 FPU keeps status in bits 15-8 of the first longword */
359 tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
360 jeq 3f
361#if !defined(CPU_M68060_ONLY)
362 jra 2f
363#endif
364#endif /* CONFIG_M68060 */
365#if !defined(CPU_M68060_ONLY)
3661: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
367 jeq 3f
368#endif
3692: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
370 fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
3713:
372#endif /* CONFIG_M68KFPU_EMU_ONLY */
373 /* Return previous task in %d1 */
374 movel %curptr,%d1
375
376 /* switch to new task (a1 contains new task) */
377 movel %a1,%curptr
378
379 /* restore floating point context */
380#ifndef CONFIG_M68KFPU_EMU_ONLY
381#ifdef CONFIG_M68KFPU_EMU
382 tstl m68k_fputype
383 jeq 4f
384#endif
385#if defined(CONFIG_M68060)
386#if !defined(CPU_M68060_ONLY)
387 btst #3,m68k_cputype+3
388 beqs 1f
389#endif
390 /* The 060 FPU keeps status in bits 15-8 of the first longword */
391 tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
392 jeq 3f
393#if !defined(CPU_M68060_ONLY)
394 jra 2f
395#endif
396#endif /* CONFIG_M68060 */
397#if !defined(CPU_M68060_ONLY)
3981: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
399 jeq 3f
400#endif
4012: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
402 fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
4033: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
4044:
405#endif /* CONFIG_M68KFPU_EMU_ONLY */
406
407 /* restore the kernel stack pointer */
408 movel %a1@(TASK_THREAD+THREAD_KSP),%sp
409
410 /* restore non-scratch registers */
411 RESTORE_SWITCH_STACK
412
413 /* restore user stack pointer */
414 movel %a1@(TASK_THREAD+THREAD_USP),%a0
415 movel %a0,%usp
416
417 /* restore fs (sfc,%dfc) */
418 movew %a1@(TASK_THREAD+THREAD_FS),%a0
419 movec %a0,%sfc
420 movec %a0,%dfc
421
422 /* restore status register */
423 movew %a1@(TASK_THREAD+THREAD_SR),%sr
424
425 rts
426
427.data
428ALIGN
429sys_call_table:
430 .long sys_ni_syscall /* 0 - old "setup()" system call*/
431 .long sys_exit
432 .long sys_fork
433 .long sys_read
434 .long sys_write
435 .long sys_open /* 5 */
436 .long sys_close
437 .long sys_waitpid
438 .long sys_creat
439 .long sys_link
440 .long sys_unlink /* 10 */
441 .long sys_execve
442 .long sys_chdir
443 .long sys_time
444 .long sys_mknod
445 .long sys_chmod /* 15 */
446 .long sys_chown16
447 .long sys_ni_syscall /* old break syscall holder */
448 .long sys_stat
449 .long sys_lseek
450 .long sys_getpid /* 20 */
451 .long sys_mount
452 .long sys_oldumount
453 .long sys_setuid16
454 .long sys_getuid16
455 .long sys_stime /* 25 */
456 .long sys_ptrace
457 .long sys_alarm
458 .long sys_fstat
459 .long sys_pause
460 .long sys_utime /* 30 */
461 .long sys_ni_syscall /* old stty syscall holder */
462 .long sys_ni_syscall /* old gtty syscall holder */
463 .long sys_access
464 .long sys_nice
465 .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
466 .long sys_sync
467 .long sys_kill
468 .long sys_rename
469 .long sys_mkdir
470 .long sys_rmdir /* 40 */
471 .long sys_dup
472 .long sys_pipe
473 .long sys_times
474 .long sys_ni_syscall /* old prof syscall holder */
475 .long sys_brk /* 45 */
476 .long sys_setgid16
477 .long sys_getgid16
478 .long sys_signal
479 .long sys_geteuid16
480 .long sys_getegid16 /* 50 */
481 .long sys_acct
482 .long sys_umount /* recycled never used phys() */
483 .long sys_ni_syscall /* old lock syscall holder */
484 .long sys_ioctl
485 .long sys_fcntl /* 55 */
486 .long sys_ni_syscall /* old mpx syscall holder */
487 .long sys_setpgid
488 .long sys_ni_syscall /* old ulimit syscall holder */
489 .long sys_ni_syscall
490 .long sys_umask /* 60 */
491 .long sys_chroot
492 .long sys_ustat
493 .long sys_dup2
494 .long sys_getppid
495 .long sys_getpgrp /* 65 */
496 .long sys_setsid
497 .long sys_sigaction
498 .long sys_sgetmask
499 .long sys_ssetmask
500 .long sys_setreuid16 /* 70 */
501 .long sys_setregid16
502 .long sys_sigsuspend
503 .long sys_sigpending
504 .long sys_sethostname
505 .long sys_setrlimit /* 75 */
506 .long sys_old_getrlimit
507 .long sys_getrusage
508 .long sys_gettimeofday
509 .long sys_settimeofday
510 .long sys_getgroups16 /* 80 */
511 .long sys_setgroups16
512 .long old_select
513 .long sys_symlink
514 .long sys_lstat
515 .long sys_readlink /* 85 */
516 .long sys_uselib
517 .long sys_swapon
518 .long sys_reboot
519 .long old_readdir
520 .long old_mmap /* 90 */
521 .long sys_munmap
522 .long sys_truncate
523 .long sys_ftruncate
524 .long sys_fchmod
525 .long sys_fchown16 /* 95 */
526 .long sys_getpriority
527 .long sys_setpriority
528 .long sys_ni_syscall /* old profil syscall holder */
529 .long sys_statfs
530 .long sys_fstatfs /* 100 */
531 .long sys_ni_syscall /* ioperm for i386 */
532 .long sys_socketcall
533 .long sys_syslog
534 .long sys_setitimer
535 .long sys_getitimer /* 105 */
536 .long sys_newstat
537 .long sys_newlstat
538 .long sys_newfstat
539 .long sys_ni_syscall
540 .long sys_ni_syscall /* 110 */ /* iopl for i386 */
541 .long sys_vhangup
542 .long sys_ni_syscall /* obsolete idle() syscall */
543 .long sys_ni_syscall /* vm86old for i386 */
544 .long sys_wait4
545 .long sys_swapoff /* 115 */
546 .long sys_sysinfo
547 .long sys_ipc
548 .long sys_fsync
549 .long sys_sigreturn
550 .long sys_clone /* 120 */
551 .long sys_setdomainname
552 .long sys_newuname
553 .long sys_cacheflush /* modify_ldt for i386 */
554 .long sys_adjtimex
555 .long sys_mprotect /* 125 */
556 .long sys_sigprocmask
557 .long sys_ni_syscall /* old "create_module" */
558 .long sys_init_module
559 .long sys_delete_module
560 .long sys_ni_syscall /* 130 - old "get_kernel_syms" */
561 .long sys_quotactl
562 .long sys_getpgid
563 .long sys_fchdir
564 .long sys_bdflush
565 .long sys_sysfs /* 135 */
566 .long sys_personality
567 .long sys_ni_syscall /* for afs_syscall */
568 .long sys_setfsuid16
569 .long sys_setfsgid16
570 .long sys_llseek /* 140 */
571 .long sys_getdents
572 .long sys_select
573 .long sys_flock
574 .long sys_msync
575 .long sys_readv /* 145 */
576 .long sys_writev
577 .long sys_getsid
578 .long sys_fdatasync
579 .long sys_sysctl
580 .long sys_mlock /* 150 */
581 .long sys_munlock
582 .long sys_mlockall
583 .long sys_munlockall
584 .long sys_sched_setparam
585 .long sys_sched_getparam /* 155 */
586 .long sys_sched_setscheduler
587 .long sys_sched_getscheduler
588 .long sys_sched_yield
589 .long sys_sched_get_priority_max
590 .long sys_sched_get_priority_min /* 160 */
591 .long sys_sched_rr_get_interval
592 .long sys_nanosleep
593 .long sys_mremap
594 .long sys_setresuid16
595 .long sys_getresuid16 /* 165 */
596 .long sys_getpagesize
597 .long sys_ni_syscall /* old sys_query_module */
598 .long sys_poll
599 .long sys_nfsservctl
600 .long sys_setresgid16 /* 170 */
601 .long sys_getresgid16
602 .long sys_prctl
603 .long sys_rt_sigreturn
604 .long sys_rt_sigaction
605 .long sys_rt_sigprocmask /* 175 */
606 .long sys_rt_sigpending
607 .long sys_rt_sigtimedwait
608 .long sys_rt_sigqueueinfo
609 .long sys_rt_sigsuspend
610 .long sys_pread64 /* 180 */
611 .long sys_pwrite64
612 .long sys_lchown16;
613 .long sys_getcwd
614 .long sys_capget
615 .long sys_capset /* 185 */
616 .long sys_sigaltstack
617 .long sys_sendfile
618 .long sys_ni_syscall /* streams1 */
619 .long sys_ni_syscall /* streams2 */
620 .long sys_vfork /* 190 */
621 .long sys_getrlimit
622 .long sys_mmap2
623 .long sys_truncate64
624 .long sys_ftruncate64
625 .long sys_stat64 /* 195 */
626 .long sys_lstat64
627 .long sys_fstat64
628 .long sys_chown
629 .long sys_getuid
630 .long sys_getgid /* 200 */
631 .long sys_geteuid
632 .long sys_getegid
633 .long sys_setreuid
634 .long sys_setregid
635 .long sys_getgroups /* 205 */
636 .long sys_setgroups
637 .long sys_fchown
638 .long sys_setresuid
639 .long sys_getresuid
640 .long sys_setresgid /* 210 */
641 .long sys_getresgid
642 .long sys_lchown
643 .long sys_setuid
644 .long sys_setgid
645 .long sys_setfsuid /* 215 */
646 .long sys_setfsgid
647 .long sys_pivot_root
648 .long sys_ni_syscall
649 .long sys_ni_syscall
650 .long sys_getdents64 /* 220 */
651 .long sys_gettid
652 .long sys_tkill
653 .long sys_setxattr
654 .long sys_lsetxattr
655 .long sys_fsetxattr /* 225 */
656 .long sys_getxattr
657 .long sys_lgetxattr
658 .long sys_fgetxattr
659 .long sys_listxattr
660 .long sys_llistxattr /* 230 */
661 .long sys_flistxattr
662 .long sys_removexattr
663 .long sys_lremovexattr
664 .long sys_fremovexattr
665 .long sys_futex /* 235 */
666 .long sys_sendfile64
667 .long sys_mincore
668 .long sys_madvise
669 .long sys_fcntl64
670 .long sys_readahead /* 240 */
671 .long sys_io_setup
672 .long sys_io_destroy
673 .long sys_io_getevents
674 .long sys_io_submit
675 .long sys_io_cancel /* 245 */
676 .long sys_fadvise64
677 .long sys_exit_group
678 .long sys_lookup_dcookie
679 .long sys_epoll_create
680 .long sys_epoll_ctl /* 250 */
681 .long sys_epoll_wait
682 .long sys_remap_file_pages
683 .long sys_set_tid_address
684 .long sys_timer_create
685 .long sys_timer_settime /* 255 */
686 .long sys_timer_gettime
687 .long sys_timer_getoverrun
688 .long sys_timer_delete
689 .long sys_clock_settime
690 .long sys_clock_gettime /* 260 */
691 .long sys_clock_getres
692 .long sys_clock_nanosleep
693 .long sys_statfs64
694 .long sys_fstatfs64
695 .long sys_tgkill /* 265 */
696 .long sys_utimes
697 .long sys_fadvise64_64
698 .long sys_mbind
699 .long sys_get_mempolicy
700 .long sys_set_mempolicy /* 270 */
701 .long sys_mq_open
702 .long sys_mq_unlink
703 .long sys_mq_timedsend
704 .long sys_mq_timedreceive
705 .long sys_mq_notify /* 275 */
706 .long sys_mq_getsetattr
707 .long sys_waitid
708 .long sys_ni_syscall /* for sys_vserver */
709 .long sys_add_key
710 .long sys_request_key /* 280 */
711 .long sys_keyctl
712
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
new file mode 100644
index 000000000000..7cd6de17c20d
--- /dev/null
+++ b/arch/m68k/kernel/head.S
@@ -0,0 +1,3940 @@
1/* -*- mode: asm -*-
2**
3** head.S -- This file contains the initial boot code for the
4** Linux/68k kernel.
5**
6** Copyright 1993 by Hamish Macdonald
7**
8** 68040 fixes by Michael Rausch
9** 68060 fixes by Roman Hodek
10** MMU cleanup by Randy Thelen
11** Final MMU cleanup by Roman Zippel
12**
13** Atari support by Andreas Schwab, using ideas of Robert de Vries
14** and Bjoern Brauel
15** VME Support by Richard Hirst
16**
17** 94/11/14 Andreas Schwab: put kernel at PAGESIZE
18** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari
19** ++ Bjoern & Roman: ATARI-68040 support for the Medusa
20** 95/11/18 Richard Hirst: Added MVME166 support
21** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with
22** Magnum- and FX-alternate ram
23** 98/04/25 Phil Blundell: added HP300 support
24** 1998/08/30 David Kilzer: Added support for font_desc structures
25** for linux-2.1.115
26** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01)
27** 2004/05/13 Kars de Jong: Finalised HP300 support
28**
29** This file is subject to the terms and conditions of the GNU General Public
30** License. See the file README.legal in the main directory of this archive
31** for more details.
32**
33*/
34
35/*
36 * Linux startup code.
37 *
38 * At this point, the boot loader has:
39 * Disabled interrupts
40 * Disabled caches
41 * Put us in supervisor state.
42 *
43 * The kernel setup code takes the following steps:
44 * . Raise interrupt level
45 * . Set up initial kernel memory mapping.
46 * . This sets up a mapping of the 4M of memory the kernel is located in.
47 * . It also does a mapping of any initial machine specific areas.
48 * . Enable the MMU
49 * . Enable cache memories
50 * . Jump to kernel startup
51 *
52 * Much of the file restructuring was to accomplish:
53 * 1) Remove register dependency through-out the file.
54 * 2) Increase use of subroutines to perform functions
55 * 3) Increase readability of the code
56 *
57 * Of course, readability is a subjective issue, so it will never be
58 * argued that that goal was accomplished. It was merely a goal.
59 * A key way to help make code more readable is to give good
60 * documentation. So, the first thing you will find is exaustive
61 * write-ups on the structure of the file, and the features of the
62 * functional subroutines.
63 *
64 * General Structure:
65 * ------------------
66 * Without a doubt the single largest chunk of head.S is spent
67 * mapping the kernel and I/O physical space into the logical range
68 * for the kernel.
69 * There are new subroutines and data structures to make MMU
70 * support cleaner and easier to understand.
71 * First, you will find a routine call "mmu_map" which maps
72 * a logical to a physical region for some length given a cache
73 * type on behalf of the caller. This routine makes writing the
74 * actual per-machine specific code very simple.
75 * A central part of the code, but not a subroutine in itself,
76 * is the mmu_init code which is broken down into mapping the kernel
77 * (the same for all machines) and mapping machine-specific I/O
78 * regions.
79 * Also, there will be a description of engaging the MMU and
80 * caches.
81 * You will notice that there is a chunk of code which
82 * can emit the entire MMU mapping of the machine. This is present
83 * only in debug modes and can be very helpful.
84 * Further, there is a new console driver in head.S that is
85 * also only engaged in debug mode. Currently, it's only supported
86 * on the Macintosh class of machines. However, it is hoped that
87 * others will plug-in support for specific machines.
88 *
89 * ######################################################################
90 *
91 * mmu_map
92 * -------
93 * mmu_map was written for two key reasons. First, it was clear
94 * that it was very difficult to read the previous code for mapping
95 * regions of memory. Second, the Macintosh required such extensive
96 * memory allocations that it didn't make sense to propagate the
97 * existing code any further.
98 * mmu_map requires some parameters:
99 *
100 * mmu_map (logical, physical, length, cache_type)
101 *
102 * While this essentially describes the function in the abstract, you'll
103 * find more indepth description of other parameters at the implementation site.
104 *
105 * mmu_get_root_table_entry
106 * ------------------------
107 * mmu_get_ptr_table_entry
108 * -----------------------
109 * mmu_get_page_table_entry
110 * ------------------------
111 *
112 * These routines are used by other mmu routines to get a pointer into
113 * a table, if necessary a new table is allocated. These routines are working
114 * basically like pmd_alloc() and pte_alloc() in <asm/pgtable.h>. The root
115 * table needs of course only to be allocated once in mmu_get_root_table_entry,
116 * so that here also some mmu specific initialization is done. The second page
117 * at the start of the kernel (the first page is unmapped later) is used for
118 * the kernel_pg_dir. It must be at a position known at link time (as it's used
119 * to initialize the init task struct) and since it needs special cache
120 * settings, it's the easiest to use this page, the rest of the page is used
121 * for further pointer tables.
122 * mmu_get_page_table_entry allocates always a whole page for page tables, this
123 * means 1024 pages and so 4MB of memory can be mapped. It doesn't make sense
124 * to manage page tables in smaller pieces as nearly all mappings have that
125 * size.
126 *
127 * ######################################################################
128 *
129 *
130 * ######################################################################
131 *
132 * mmu_engage
133 * ----------
134 * Thanks to a small helping routine enabling the mmu got quite simple
135 * and there is only one way left. mmu_engage makes a complete a new mapping
136 * that only includes the absolute necessary to be able to jump to the final
137 * postion and to restore the original mapping.
138 * As this code doesn't need a transparent translation register anymore this
139 * means all registers are free to be used by machines that needs them for
140 * other purposes.
141 *
142 * ######################################################################
143 *
144 * mmu_print
145 * ---------
146 * This algorithm will print out the page tables of the system as
147 * appropriate for an 030 or an 040. This is useful for debugging purposes
148 * and as such is enclosed in #ifdef MMU_PRINT/#endif clauses.
149 *
150 * ######################################################################
151 *
152 * console_init
153 * ------------
154 * The console is also able to be turned off. The console in head.S
155 * is specifically for debugging and can be very useful. It is surrounded by
156 * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good
157 * kernels. It's basic algorithm is to determine the size of the screen
158 * (in height/width and bit depth) and then use that information for
159 * displaying an 8x8 font or an 8x16 (widthxheight). I prefer the 8x8 for
160 * debugging so I can see more good data. But it was trivial to add support
161 * for both fonts, so I included it.
162 * Also, the algorithm for plotting pixels is abstracted so that in
163 * theory other platforms could add support for different kinds of frame
164 * buffers. This could be very useful.
165 *
166 * console_put_penguin
167 * -------------------
168 * An important part of any Linux bring up is the penguin and there's
169 * nothing like getting the Penguin on the screen! This algorithm will work
170 * on any machine for which there is a console_plot_pixel.
171 *
172 * console_scroll
173 * --------------
174 * My hope is that the scroll algorithm does the right thing on the
175 * various platforms, but it wouldn't be hard to add the test conditions
176 * and new code if it doesn't.
177 *
178 * console_putc
179 * -------------
180 *
181 * ######################################################################
182 *
183 * Register usage has greatly simplified within head.S. Every subroutine
184 * saves and restores all registers that it modifies (except it returns a
185 * value in there of course). So the only register that needs to be initialized
186 * is the stack pointer.
187 * All other init code and data is now placed in the init section, so it will
188 * be automatically freed at the end of the kernel initialization.
189 *
190 * ######################################################################
191 *
192 * options
193 * -------
194 * There are many options available in a build of this file. I've
195 * taken the time to describe them here to save you the time of searching
196 * for them and trying to understand what they mean.
197 *
198 * CONFIG_xxx: These are the obvious machine configuration defines created
199 * during configuration. These are defined in include/linux/autoconf.h.
200 *
201 * CONSOLE: There is support for head.S console in this file. This
202 * console can talk to a Mac frame buffer, but could easily be extrapolated
203 * to extend it to support other platforms.
204 *
205 * TEST_MMU: This is a test harness for running on any given machine but
206 * getting an MMU dump for another class of machine. The classes of machines
207 * that can be tested are any of the makes (Atari, Amiga, Mac, VME, etc.)
208 * and any of the models (030, 040, 060, etc.).
209 *
210 * NOTE: TEST_MMU is NOT permanent! It is scheduled to be removed
211 * When head.S boots on Atari, Amiga, Macintosh, and VME
212 * machines. At that point the underlying logic will be
213 * believed to be solid enough to be trusted, and TEST_MMU
214 * can be dropped. Do note that that will clean up the
215 * head.S code significantly as large blocks of #if/#else
216 * clauses can be removed.
217 *
218 * MMU_NOCACHE_KERNEL: On the Macintosh platform there was an inquiry into
219 * determing why devices don't appear to work. A test case was to remove
220 * the cacheability of the kernel bits.
221 *
222 * MMU_PRINT: There is a routine built into head.S that can display the
223 * MMU data structures. It outputs its result through the serial_putc
224 * interface. So where ever that winds up driving data, that's where the
225 * mmu struct will appear. On the Macintosh that's typically the console.
226 *
227 * SERIAL_DEBUG: There are a series of putc() macro statements
228 * scattered through out the code to give progress of status to the
229 * person sitting at the console. This constant determines whether those
230 * are used.
231 *
232 * DEBUG: This is the standard DEBUG flag that can be set for building
233 * the kernel. It has the effect adding additional tests into
234 * the code.
235 *
236 * FONT_6x11:
237 * FONT_8x8:
238 * FONT_8x16:
239 * In theory these could be determined at run time or handed
240 * over by the booter. But, let's be real, it's a fine hard
241 * coded value. (But, you will notice the code is run-time
242 * flexible!) A pointer to the font's struct font_desc
243 * is kept locally in Lconsole_font. It is used to determine
244 * font size information dynamically.
245 *
246 * Atari constants:
247 * USE_PRINTER: Use the printer port for serial debug.
248 * USE_SCC_B: Use the SCC port A (Serial2) for serial debug.
249 * USE_SCC_A: Use the SCC port B (Modem2) for serial debug.
250 * USE_MFP: Use the ST-MFP port (Modem1) for serial debug.
251 *
252 * Macintosh constants:
253 * MAC_SERIAL_DEBUG: Turns on serial debug output for the Macintosh.
254 * MAC_USE_SCC_A: Use the SCC port A (modem) for serial debug.
255 * MAC_USE_SCC_B: Use the SCC port B (printer) for serial debug (default).
256 */
257
258#include <linux/config.h>
259#include <linux/linkage.h>
260#include <linux/init.h>
261#include <asm/bootinfo.h>
262#include <asm/setup.h>
263#include <asm/entry.h>
264#include <asm/pgtable.h>
265#include <asm/page.h>
266#include <asm/offsets.h>
267
268#ifdef CONFIG_MAC
269
270#include <asm/machw.h>
271
272/*
273 * Macintosh console support
274 */
275
276#define CONSOLE
277#define CONSOLE_PENGUIN
278
279/*
280 * Macintosh serial debug support; outputs boot info to the printer
281 * and/or modem serial ports
282 */
283#undef MAC_SERIAL_DEBUG
284
285/*
286 * Macintosh serial debug port selection; define one or both;
287 * requires MAC_SERIAL_DEBUG to be defined
288 */
289#define MAC_USE_SCC_A /* Macintosh modem serial port */
290#define MAC_USE_SCC_B /* Macintosh printer serial port */
291
292#endif /* CONFIG_MAC */
293
294#undef MMU_PRINT
295#undef MMU_NOCACHE_KERNEL
296#define SERIAL_DEBUG
297#undef DEBUG
298
299/*
300 * For the head.S console, there are three supported fonts, 6x11, 8x16 and 8x8.
301 * The 8x8 font is harder to read but fits more on the screen.
302 */
303#define FONT_8x8 /* default */
304/* #define FONT_8x16 */ /* 2nd choice */
305/* #define FONT_6x11 */ /* 3rd choice */
306
307.globl kernel_pg_dir
308.globl availmem
309.globl m68k_pgtable_cachemode
310.globl m68k_supervisor_cachemode
311#ifdef CONFIG_MVME16x
312.globl mvme_bdid
313#endif
314#ifdef CONFIG_Q40
315.globl q40_mem_cptr
316#endif
317
318CPUTYPE_040 = 1 /* indicates an 040 */
319CPUTYPE_060 = 2 /* indicates an 060 */
320CPUTYPE_0460 = 3 /* if either above are set, this is set */
321CPUTYPE_020 = 4 /* indicates an 020 */
322
323/* Translation control register */
324TC_ENABLE = 0x8000
325TC_PAGE8K = 0x4000
326TC_PAGE4K = 0x0000
327
328/* Transparent translation registers */
329TTR_ENABLE = 0x8000 /* enable transparent translation */
330TTR_ANYMODE = 0x4000 /* user and kernel mode access */
331TTR_KERNELMODE = 0x2000 /* only kernel mode access */
332TTR_USERMODE = 0x0000 /* only user mode access */
333TTR_CI = 0x0400 /* inhibit cache */
334TTR_RW = 0x0200 /* read/write mode */
335TTR_RWM = 0x0100 /* read/write mask */
336TTR_FCB2 = 0x0040 /* function code base bit 2 */
337TTR_FCB1 = 0x0020 /* function code base bit 1 */
338TTR_FCB0 = 0x0010 /* function code base bit 0 */
339TTR_FCM2 = 0x0004 /* function code mask bit 2 */
340TTR_FCM1 = 0x0002 /* function code mask bit 1 */
341TTR_FCM0 = 0x0001 /* function code mask bit 0 */
342
343/* Cache Control registers */
344CC6_ENABLE_D = 0x80000000 /* enable data cache (680[46]0) */
345CC6_FREEZE_D = 0x40000000 /* freeze data cache (68060) */
346CC6_ENABLE_SB = 0x20000000 /* enable store buffer (68060) */
347CC6_PUSH_DPI = 0x10000000 /* disable CPUSH invalidation (68060) */
348CC6_HALF_D = 0x08000000 /* half-cache mode for data cache (68060) */
349CC6_ENABLE_B = 0x00800000 /* enable branch cache (68060) */
350CC6_CLRA_B = 0x00400000 /* clear all entries in branch cache (68060) */
351CC6_CLRU_B = 0x00200000 /* clear user entries in branch cache (68060) */
352CC6_ENABLE_I = 0x00008000 /* enable instruction cache (680[46]0) */
353CC6_FREEZE_I = 0x00004000 /* freeze instruction cache (68060) */
354CC6_HALF_I = 0x00002000 /* half-cache mode for instruction cache (68060) */
355CC3_ALLOC_WRITE = 0x00002000 /* write allocate mode(68030) */
356CC3_ENABLE_DB = 0x00001000 /* enable data burst (68030) */
357CC3_CLR_D = 0x00000800 /* clear data cache (68030) */
358CC3_CLRE_D = 0x00000400 /* clear entry in data cache (68030) */
359CC3_FREEZE_D = 0x00000200 /* freeze data cache (68030) */
360CC3_ENABLE_D = 0x00000100 /* enable data cache (68030) */
361CC3_ENABLE_IB = 0x00000010 /* enable instruction burst (68030) */
362CC3_CLR_I = 0x00000008 /* clear instruction cache (68030) */
363CC3_CLRE_I = 0x00000004 /* clear entry in instruction cache (68030) */
364CC3_FREEZE_I = 0x00000002 /* freeze instruction cache (68030) */
365CC3_ENABLE_I = 0x00000001 /* enable instruction cache (68030) */
366
367/* Miscellaneous definitions */
368PAGESIZE = 4096
369PAGESHIFT = 12
370
371ROOT_TABLE_SIZE = 128
372PTR_TABLE_SIZE = 128
373PAGE_TABLE_SIZE = 64
374ROOT_INDEX_SHIFT = 25
375PTR_INDEX_SHIFT = 18
376PAGE_INDEX_SHIFT = 12
377
378#ifdef DEBUG
379/* When debugging use readable names for labels */
380#ifdef __STDC__
381#define L(name) .head.S.##name
382#else
383#define L(name) .head.S./**/name
384#endif
385#else
386#ifdef __STDC__
387#define L(name) .L##name
388#else
389#define L(name) .L/**/name
390#endif
391#endif
392
393/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
394#ifndef __INITDATA
395#define __INITDATA .data
396#define __FINIT .previous
397#endif
398
399/* Several macros to make the writing of subroutines easier:
400 * - func_start marks the beginning of the routine which setups the frame
401 * register and saves the registers, it also defines another macro
402 * to automatically restore the registers again.
403 * - func_return marks the end of the routine and simply calls the prepared
404 * macro to restore registers and jump back to the caller.
405 * - func_define generates another macro to automatically put arguments
406 * onto the stack call the subroutine and cleanup the stack again.
407 */
408
409/* Within subroutines these macros can be used to access the arguments
410 * on the stack. With STACK some allocated memory on the stack can be
411 * accessed and ARG0 points to the return address (used by mmu_engage).
412 */
413#define STACK %a6@(stackstart)
414#define ARG0 %a6@(4)
415#define ARG1 %a6@(8)
416#define ARG2 %a6@(12)
417#define ARG3 %a6@(16)
418#define ARG4 %a6@(20)
419
420.macro func_start name,saveregs,stack=0
421L(\name):
422 linkw %a6,#-\stack
423 moveml \saveregs,%sp@-
424.set stackstart,-\stack
425
426.macro func_return_\name
427 moveml %sp@+,\saveregs
428 unlk %a6
429 rts
430.endm
431.endm
432
433.macro func_return name
434 func_return_\name
435.endm
436
437.macro func_call name
438 jbsr L(\name)
439.endm
440
441.macro move_stack nr,arg1,arg2,arg3,arg4
442.if \nr
443 move_stack "(\nr-1)",\arg2,\arg3,\arg4
444 movel \arg1,%sp@-
445.endif
446.endm
447
448.macro func_define name,nr=0
449.macro \name arg1,arg2,arg3,arg4
450 move_stack \nr,\arg1,\arg2,\arg3,\arg4
451 func_call \name
452.if \nr
453 lea %sp@(\nr*4),%sp
454.endif
455.endm
456.endm
457
458func_define mmu_map,4
459func_define mmu_map_tt,4
460func_define mmu_fixup_page_mmu_cache,1
461func_define mmu_temp_map,2
462func_define mmu_engage
463func_define mmu_get_root_table_entry,1
464func_define mmu_get_ptr_table_entry,2
465func_define mmu_get_page_table_entry,2
466func_define mmu_print
467func_define get_new_page
468#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
469func_define set_leds
470#endif
471
472.macro mmu_map_eq arg1,arg2,arg3
473 mmu_map \arg1,\arg1,\arg2,\arg3
474.endm
475
476.macro get_bi_record record
477 pea \record
478 func_call get_bi_record
479 addql #4,%sp
480.endm
481
482func_define serial_putc,1
483func_define console_putc,1
484
485func_define console_init
486func_define console_put_stats
487func_define console_put_penguin
488func_define console_plot_pixel,3
489func_define console_scroll
490
491.macro putc ch
492#if defined(CONSOLE) || defined(SERIAL_DEBUG)
493 pea \ch
494#endif
495#ifdef CONSOLE
496 func_call console_putc
497#endif
498#ifdef SERIAL_DEBUG
499 func_call serial_putc
500#endif
501#if defined(CONSOLE) || defined(SERIAL_DEBUG)
502 addql #4,%sp
503#endif
504.endm
505
506.macro dputc ch
507#ifdef DEBUG
508 putc \ch
509#endif
510.endm
511
512func_define putn,1
513
514.macro dputn nr
515#ifdef DEBUG
516 putn \nr
517#endif
518.endm
519
520.macro puts string
521#if defined(CONSOLE) || defined(SERIAL_DEBUG)
522 __INITDATA
523.Lstr\@:
524 .string "\string"
525 __FINIT
526 pea %pc@(.Lstr\@)
527 func_call puts
528 addql #4,%sp
529#endif
530.endm
531
532.macro dputs string
533#ifdef DEBUG
534 puts "\string"
535#endif
536.endm
537
538#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab
539#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab
540#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab
541#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab
542#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab
543#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab
544#define is_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jeq lab
545#define is_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jeq lab
546#define is_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jeq lab
547#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab
548#define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab
549#define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab
550#define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab
551
552#define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \
553 jeq 42f; \
554 cmpl &MACH_APOLLO,%pc@(m68k_machtype); \
555 jne lab ;\
556 42:\
557
558#define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab
559#define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab
560#define is_040(lab) btst &CPUTYPE_040,%pc@(L(cputype)+3); jne lab
561#define is_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jne lab
562#define is_not_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jeq lab
563#define is_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jne lab
564#define is_not_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jeq lab
565
566/* On the HP300 we use the on-board LEDs for debug output before
567 the console is running. Writing a 1 bit turns the corresponding LED
568 _off_ - on the 340 bit 7 is towards the back panel of the machine. */
569.macro leds mask
570#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
571 hasnt_leds(.Lled\@)
572 pea \mask
573 func_call set_leds
574 addql #4,%sp
575.Lled\@:
576#endif
577.endm
578
579.text
580ENTRY(_stext)
581/*
582 * Version numbers of the bootinfo interface
583 * The area from _stext to _start will later be used as kernel pointer table
584 */
585 bras 1f /* Jump over bootinfo version numbers */
586
587 .long BOOTINFOV_MAGIC
588 .long MACH_AMIGA, AMIGA_BOOTI_VERSION
589 .long MACH_ATARI, ATARI_BOOTI_VERSION
590 .long MACH_MVME147, MVME147_BOOTI_VERSION
591 .long MACH_MVME16x, MVME16x_BOOTI_VERSION
592 .long MACH_BVME6000, BVME6000_BOOTI_VERSION
593 .long MACH_MAC, MAC_BOOTI_VERSION
594 .long MACH_Q40, Q40_BOOTI_VERSION
595 .long MACH_HP300, HP300_BOOTI_VERSION
596 .long 0
5971: jra __start
598
599.equ kernel_pg_dir,_stext
600
601.equ .,_stext+PAGESIZE
602
603ENTRY(_start)
604 jra __start
605__INIT
606ENTRY(__start)
607/*
608 * Setup initial stack pointer
609 */
610 lea %pc@(_stext),%sp
611
612/*
613 * Record the CPU and machine type.
614 */
615 get_bi_record BI_MACHTYPE
616 lea %pc@(m68k_machtype),%a1
617 movel %a0@,%a1@
618
619 get_bi_record BI_FPUTYPE
620 lea %pc@(m68k_fputype),%a1
621 movel %a0@,%a1@
622
623 get_bi_record BI_MMUTYPE
624 lea %pc@(m68k_mmutype),%a1
625 movel %a0@,%a1@
626
627 get_bi_record BI_CPUTYPE
628 lea %pc@(m68k_cputype),%a1
629 movel %a0@,%a1@
630
631 leds 0x1
632
633#ifdef CONFIG_MAC
634/*
635 * For Macintosh, we need to determine the display parameters early (at least
636 * while debugging it).
637 */
638
639 is_not_mac(L(test_notmac))
640
641 get_bi_record BI_MAC_VADDR
642 lea %pc@(L(mac_videobase)),%a1
643 movel %a0@,%a1@
644
645 get_bi_record BI_MAC_VDEPTH
646 lea %pc@(L(mac_videodepth)),%a1
647 movel %a0@,%a1@
648
649 get_bi_record BI_MAC_VDIM
650 lea %pc@(L(mac_dimensions)),%a1
651 movel %a0@,%a1@
652
653 get_bi_record BI_MAC_VROW
654 lea %pc@(L(mac_rowbytes)),%a1
655 movel %a0@,%a1@
656
657#ifdef MAC_SERIAL_DEBUG
658 get_bi_record BI_MAC_SCCBASE
659 lea %pc@(L(mac_sccbase)),%a1
660 movel %a0@,%a1@
661#endif /* MAC_SERIAL_DEBUG */
662
663#if 0
664 /*
665 * Clear the screen
666 */
667 lea %pc@(L(mac_videobase)),%a0
668 movel %a0@,%a1
669 lea %pc@(L(mac_dimensions)),%a0
670 movel %a0@,%d1
671 swap %d1 /* #rows is high bytes */
672 andl #0xFFFF,%d1 /* rows */
673 subl #10,%d1
674 lea %pc@(L(mac_rowbytes)),%a0
675loopy2:
676 movel %a0@,%d0
677 subql #1,%d0
678loopx2:
679 moveb #0x55, %a1@+
680 dbra %d0,loopx2
681 dbra %d1,loopy2
682#endif
683
684L(test_notmac):
685#endif /* CONFIG_MAC */
686
687
688/*
689 * There are ultimately two pieces of information we want for all kinds of
690 * processors CpuType and CacheBits. The CPUTYPE was passed in from booter
691 * and is converted here from a booter type definition to a separate bit
692 * number which allows for the standard is_0x0 macro tests.
693 */
694 movel %pc@(m68k_cputype),%d0
695 /*
696 * Assume it's an 030
697 */
698 clrl %d1
699
700 /*
701 * Test the BootInfo cputype for 060
702 */
703 btst #CPUB_68060,%d0
704 jeq 1f
705 bset #CPUTYPE_060,%d1
706 bset #CPUTYPE_0460,%d1
707 jra 3f
7081:
709 /*
710 * Test the BootInfo cputype for 040
711 */
712 btst #CPUB_68040,%d0
713 jeq 2f
714 bset #CPUTYPE_040,%d1
715 bset #CPUTYPE_0460,%d1
716 jra 3f
7172:
718 /*
719 * Test the BootInfo cputype for 020
720 */
721 btst #CPUB_68020,%d0
722 jeq 3f
723 bset #CPUTYPE_020,%d1
724 jra 3f
7253:
726 /*
727 * Record the cpu type
728 */
729 lea %pc@(L(cputype)),%a0
730 movel %d1,%a0@
731
732 /*
733 * NOTE:
734 *
735 * Now the macros are valid:
736 * is_040_or_060
737 * is_not_040_or_060
738 * is_040
739 * is_060
740 * is_not_060
741 */
742
743 /*
744 * Determine the cache mode for pages holding MMU tables
745 * and for supervisor mode, unused for '020 and '030
746 */
747 clrl %d0
748 clrl %d1
749
750 is_not_040_or_060(L(save_cachetype))
751
752 /*
753 * '040 or '060
754 * d1 := cacheable write-through
755 * NOTE: The 68040 manual strongly recommends non-cached for MMU tables,
756 * but we have been using write-through since at least 2.0.29 so I
757 * guess it is OK.
758 */
759#ifdef CONFIG_060_WRITETHROUGH
760 /*
761 * If this is a 68060 board using drivers with cache coherency
762 * problems, then supervisor memory accesses need to be write-through
763 * also; otherwise, we want copyback.
764 */
765
766 is_not_060(1f)
767 movel #_PAGE_CACHE040W,%d0
768 jra L(save_cachetype)
769#endif /* CONFIG_060_WRITETHROUGH */
7701:
771 movew #_PAGE_CACHE040,%d0
772
773 movel #_PAGE_CACHE040W,%d1
774
775L(save_cachetype):
776 /* Save cache mode for supervisor mode and page tables
777 */
778 lea %pc@(m68k_supervisor_cachemode),%a0
779 movel %d0,%a0@
780 lea %pc@(m68k_pgtable_cachemode),%a0
781 movel %d1,%a0@
782
783/*
784 * raise interrupt level
785 */
786 movew #0x2700,%sr
787
788/*
789 If running on an Atari, determine the I/O base of the
790 serial port and test if we are running on a Medusa or Hades.
791 This test is necessary here, because on the Hades the serial
792 port is only accessible in the high I/O memory area.
793
794 The test whether it is a Medusa is done by writing to the byte at
795 phys. 0x0. This should result in a bus error on all other machines.
796
797 ...should, but doesn't. The Afterburner040 for the Falcon has the
798 same behaviour (0x0..0x7 are no ROM shadow). So we have to do
799 another test to distinguish Medusa and AB040. This is a
800 read attempt for 0x00ff82fe phys. that should bus error on a Falcon
801 (+AB040), but is in the range where the Medusa always asserts DTACK.
802
803 The test for the Hades is done by reading address 0xb0000000. This
804 should give a bus error on the Medusa.
805 */
806
807#ifdef CONFIG_ATARI
808 is_not_atari(L(notypetest))
809
810 /* get special machine type (Medusa/Hades/AB40) */
811 moveq #0,%d3 /* default if tag doesn't exist */
812 get_bi_record BI_ATARI_MCH_TYPE
813 tstl %d0
814 jbmi 1f
815 movel %a0@,%d3
816 lea %pc@(atari_mch_type),%a0
817 movel %d3,%a0@
8181:
819 /* On the Hades, the iobase must be set up before opening the
820 * serial port. There are no I/O regs at 0x00ffxxxx at all. */
821 moveq #0,%d0
822 cmpl #ATARI_MACH_HADES,%d3
823 jbne 1f
824 movel #0xff000000,%d0 /* Hades I/O base addr: 0xff000000 */
8251: lea %pc@(L(iobase)),%a0
826 movel %d0,%a0@
827
828L(notypetest):
829#endif
830
831#ifdef CONFIG_VME
832 is_mvme147(L(getvmetype))
833 is_bvme6000(L(getvmetype))
834 is_not_mvme16x(L(gvtdone))
835
836 /* See if the loader has specified the BI_VME_TYPE tag. Recent
837 * versions of VMELILO and TFTPLILO do this. We have to do this
838 * early so we know how to handle console output. If the tag
839 * doesn't exist then we use the Bug for output on MVME16x.
840 */
841L(getvmetype):
842 get_bi_record BI_VME_TYPE
843 tstl %d0
844 jbmi 1f
845 movel %a0@,%d3
846 lea %pc@(vme_brdtype),%a0
847 movel %d3,%a0@
8481:
849#ifdef CONFIG_MVME16x
850 is_not_mvme16x(L(gvtdone))
851
852 /* Need to get the BRD_ID info to differentiate between 162, 167,
853 * etc. This is available as a BI_VME_BRDINFO tag with later
854 * versions of VMELILO and TFTPLILO, otherwise we call the Bug.
855 */
856 get_bi_record BI_VME_BRDINFO
857 tstl %d0
858 jpl 1f
859
860 /* Get pointer to board ID data from Bug */
861 movel %d2,%sp@-
862 trap #15
863 .word 0x70 /* trap 0x70 - .BRD_ID */
864 movel %sp@+,%a0
8651:
866 lea %pc@(mvme_bdid),%a1
867 /* Structure is 32 bytes long */
868 movel %a0@+,%a1@+
869 movel %a0@+,%a1@+
870 movel %a0@+,%a1@+
871 movel %a0@+,%a1@+
872 movel %a0@+,%a1@+
873 movel %a0@+,%a1@+
874 movel %a0@+,%a1@+
875 movel %a0@+,%a1@+
876#endif
877
878L(gvtdone):
879
880#endif
881
882#ifdef CONFIG_HP300
883 is_not_hp300(L(nothp))
884
885 /* Get the address of the UART for serial debugging */
886 get_bi_record BI_HP300_UART_ADDR
887 tstl %d0
888 jbmi 1f
889 movel %a0@,%d3
890 lea %pc@(L(uartbase)),%a0
891 movel %d3,%a0@
892 get_bi_record BI_HP300_UART_SCODE
893 tstl %d0
894 jbmi 1f
895 movel %a0@,%d3
896 lea %pc@(L(uart_scode)),%a0
897 movel %d3,%a0@
8981:
899L(nothp):
900#endif
901
902/*
903 * Initialize serial port
904 */
905 jbsr L(serial_init)
906
907/*
908 * Initialize console
909 */
910#ifdef CONFIG_MAC
911 is_not_mac(L(nocon))
912#ifdef CONSOLE
913 console_init
914#ifdef CONSOLE_PENGUIN
915 console_put_penguin
916#endif /* CONSOLE_PENGUIN */
917 console_put_stats
918#endif /* CONSOLE */
919L(nocon):
920#endif /* CONFIG_MAC */
921
922
923 putc '\n'
924 putc 'A'
925 leds 0x2
926 dputn %pc@(L(cputype))
927 dputn %pc@(m68k_supervisor_cachemode)
928 dputn %pc@(m68k_pgtable_cachemode)
929 dputc '\n'
930
931/*
932 * Save physical start address of kernel
933 */
934 lea %pc@(L(phys_kernel_start)),%a0
935 lea %pc@(_stext),%a1
936 subl #_stext,%a1
937 addl #PAGE_OFFSET,%a1
938 movel %a1,%a0@
939
940 putc 'B'
941
942 leds 0x4
943
944/*
945 * mmu_init
946 *
947 * This block of code does what's necessary to map in the various kinds
948 * of machines for execution of Linux.
949 * First map the first 4 MB of kernel code & data
950 */
951
952 mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),#4*1024*1024,\
953 %pc@(m68k_supervisor_cachemode)
954
955 putc 'C'
956
957#ifdef CONFIG_AMIGA
958
959L(mmu_init_amiga):
960
961 is_not_amiga(L(mmu_init_not_amiga))
962/*
963 * mmu_init_amiga
964 */
965
966 putc 'D'
967
968 is_not_040_or_060(1f)
969
970 /*
971 * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000
972 */
973 mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
974 /*
975 * Map the Zorro III I/O space with transparent translation
976 * for frame buffer memory etc.
977 */
978 mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S
979
980 jbra L(mmu_init_done)
981
9821:
983 /*
984 * 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000
985 */
986 mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
987 mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030
988
989 jbra L(mmu_init_done)
990
991L(mmu_init_not_amiga):
992#endif
993
994#ifdef CONFIG_ATARI
995
996L(mmu_init_atari):
997
998 is_not_atari(L(mmu_init_not_atari))
999
1000 putc 'E'
1001
1002/* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping
1003 the last 16 MB of virtual address space to the first 16 MB (i.e.
1004 0xffxxxxxx -> 0x00xxxxxx). For this, an additional pointer table is
1005 needed. I/O ranges are marked non-cachable.
1006
1007 For the Medusa it is better to map the I/O region transparently
1008 (i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are
1009 accessible only in the high area.
1010
1011 On the Hades all I/O registers are only accessible in the high
1012 area.
1013*/
1014
1015 /* I/O base addr for non-Medusa, non-Hades: 0x00000000 */
1016 moveq #0,%d0
1017 movel %pc@(atari_mch_type),%d3
1018 cmpl #ATARI_MACH_MEDUSA,%d3
1019 jbeq 2f
1020 cmpl #ATARI_MACH_HADES,%d3
1021 jbne 1f
10222: movel #0xff000000,%d0 /* Medusa/Hades base addr: 0xff000000 */
10231: movel %d0,%d3
1024
1025 is_040_or_060(L(spata68040))
1026
1027 /* Map everything non-cacheable, though not all parts really
1028 * need to disable caches (crucial only for 0xff8000..0xffffff
1029 * (standard I/O) and 0xf00000..0xf3ffff (IDE)). The remainder
1030 * isn't really used, except for sometimes peeking into the
1031 * ROMs (mirror at phys. 0x0), so caching isn't necessary for
1032 * this. */
1033 mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE030
1034
1035 jbra L(mmu_init_done)
1036
1037L(spata68040):
1038
1039 mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE_S
1040
1041 jbra L(mmu_init_done)
1042
1043L(mmu_init_not_atari):
1044#endif
1045
1046#ifdef CONFIG_Q40
1047 is_not_q40(L(notq40))
1048 /*
1049 * add transparent mapping for 0xff00 0000 - 0xffff ffff
1050 * non-cached serialized etc..
1051 * this includes master chip, DAC, RTC and ISA ports
1052 * 0xfe000000-0xfeffffff is for screen and ROM
1053 */
1054
1055 putc 'Q'
1056
1057 mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W
1058 mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S
1059
1060 jbra L(mmu_init_done)
1061
1062L(notq40):
1063#endif
1064
1065#ifdef CONFIG_HP300
1066 is_not_hp300(L(nothp300))
1067
1068 /* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx)
1069 * by mapping 32MB (on 020/030) or 16 MB (on 040) from 0xf0xxxxxx -> 0x00xxxxxx).
1070 * The ROM mapping is needed because the LEDs are mapped there too.
1071 */
1072
1073 is_040(1f)
1074
1075 /*
1076 * 030: Map the 32Meg range physical 0x0 upto logical 0xf000.0000
1077 */
1078 mmu_map #0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030
1079
1080 jbra L(mmu_init_done)
1081
10821:
1083 /*
1084 * 040: Map the 16Meg range physical 0x0 upto logical 0xf000.0000
1085 */
1086 mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S
1087
1088 jbra L(mmu_init_done)
1089
1090L(nothp300):
1091#endif /* CONFIG_HP300 */
1092
1093#ifdef CONFIG_MVME147
1094
1095 is_not_mvme147(L(not147))
1096
1097 /*
1098 * On MVME147 we have already created kernel page tables for
1099 * 4MB of RAM at address 0, so now need to do a transparent
1100 * mapping of the top of memory space. Make it 0.5GByte for now,
1101 * so we can access on-board i/o areas.
1102 */
1103
1104 mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030
1105
1106 jbra L(mmu_init_done)
1107
1108L(not147):
1109#endif /* CONFIG_MVME147 */
1110
1111#ifdef CONFIG_MVME16x
1112
1113 is_not_mvme16x(L(not16x))
1114
1115 /*
1116 * On MVME16x we have already created kernel page tables for
1117 * 4MB of RAM at address 0, so now need to do a transparent
1118 * mapping of the top of memory space. Make it 0.5GByte for now.
1119 * Supervisor only access, so transparent mapping doesn't
1120 * clash with User code virtual address space.
1121 * this covers IO devices, PROM and SRAM. The PROM and SRAM
1122 * mapping is needed to allow 167Bug to run.
1123 * IO is in the range 0xfff00000 to 0xfffeffff.
1124 * PROM is 0xff800000->0xffbfffff and SRAM is
1125 * 0xffe00000->0xffe1ffff.
1126 */
1127
1128 mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
1129
1130 jbra L(mmu_init_done)
1131
1132L(not16x):
1133#endif /* CONFIG_MVME162 | CONFIG_MVME167 */
1134
1135#ifdef CONFIG_BVME6000
1136
1137 is_not_bvme6000(L(not6000))
1138
1139 /*
1140 * On BVME6000 we have already created kernel page tables for
1141 * 4MB of RAM at address 0, so now need to do a transparent
1142 * mapping of the top of memory space. Make it 0.5GByte for now,
1143 * so we can access on-board i/o areas.
1144 * Supervisor only access, so transparent mapping doesn't
1145 * clash with User code virtual address space.
1146 */
1147
1148 mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
1149
1150 jbra L(mmu_init_done)
1151
1152L(not6000):
1153#endif /* CONFIG_BVME6000 */
1154
1155/*
1156 * mmu_init_mac
1157 *
1158 * The Macintosh mappings are less clear.
1159 *
1160 * Even as of this writing, it is unclear how the
1161 * Macintosh mappings will be done. However, as
1162 * the first author of this code I'm proposing the
1163 * following model:
1164 *
1165 * Map the kernel (that's already done),
1166 * Map the I/O (on most machines that's the
1167 * 0x5000.0000 ... 0x5300.0000 range,
1168 * Map the video frame buffer using as few pages
1169 * as absolutely (this requirement mostly stems from
1170 * the fact that when the frame buffer is at
1171 * 0x0000.0000 then we know there is valid RAM just
1172 * above the screen that we don't want to waste!).
1173 *
1174 * By the way, if the frame buffer is at 0x0000.0000
1175 * then the Macintosh is known as an RBV based Mac.
1176 *
1177 * By the way 2, the code currently maps in a bunch of
1178 * regions. But I'd like to cut that out. (And move most
1179 * of the mappings up into the kernel proper ... or only
1180 * map what's necessary.)
1181 */
1182
1183#ifdef CONFIG_MAC
1184
1185L(mmu_init_mac):
1186
1187 is_not_mac(L(mmu_init_not_mac))
1188
1189 putc 'F'
1190
1191 is_not_040_or_060(1f)
1192
1193 moveq #_PAGE_NOCACHE_S,%d3
1194 jbra 2f
11951:
1196 moveq #_PAGE_NOCACHE030,%d3
11972:
1198 /*
1199 * Mac Note: screen address of logical 0xF000.0000 -> <screen physical>
1200 * we simply map the 4MB that contains the videomem
1201 */
1202
1203 movel #VIDEOMEMMASK,%d0
1204 andl %pc@(L(mac_videobase)),%d0
1205
1206 mmu_map #VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d3
1207 /* ROM from 4000 0000 to 4200 0000 (only for mac_reset()) */
1208 mmu_map_eq #0x40000000,#0x02000000,%d3
1209 /* IO devices (incl. serial port) from 5000 0000 to 5300 0000 */
1210 mmu_map_eq #0x50000000,#0x03000000,%d3
1211 /* Nubus slot space (video at 0xF0000000, rom at 0xF0F80000) */
1212 mmu_map_tt #1,#0xf8000000,#0x08000000,%d3
1213
1214 jbra L(mmu_init_done)
1215
1216L(mmu_init_not_mac):
1217#endif
1218
1219#ifdef CONFIG_SUN3X
1220 is_not_sun3x(L(notsun3x))
1221
1222 /* oh, the pain.. We're gonna want the prom code after
1223 * starting the MMU, so we copy the mappings, translating
1224 * from 8k -> 4k pages as we go.
1225 */
1226
1227 /* copy maps from 0xfee00000 to 0xff000000 */
1228 movel #0xfee00000, %d0
1229 moveq #ROOT_INDEX_SHIFT, %d1
1230 lsrl %d1,%d0
1231 mmu_get_root_table_entry %d0
1232
1233 movel #0xfee00000, %d0
1234 moveq #PTR_INDEX_SHIFT, %d1
1235 lsrl %d1,%d0
1236 andl #PTR_TABLE_SIZE-1, %d0
1237 mmu_get_ptr_table_entry %a0,%d0
1238
1239 movel #0xfee00000, %d0
1240 moveq #PAGE_INDEX_SHIFT, %d1
1241 lsrl %d1,%d0
1242 andl #PAGE_TABLE_SIZE-1, %d0
1243 mmu_get_page_table_entry %a0,%d0
1244
1245 /* this is where the prom page table lives */
1246 movel 0xfefe00d4, %a1
1247 movel %a1@, %a1
1248
1249 movel #((0x200000 >> 13)-1), %d1
1250
12511:
1252 movel %a1@+, %d3
1253 movel %d3,%a0@+
1254 addl #0x1000,%d3
1255 movel %d3,%a0@+
1256
1257 dbra %d1,1b
1258
1259 /* setup tt1 for I/O */
1260 mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S
1261 jbra L(mmu_init_done)
1262
1263L(notsun3x):
1264#endif
1265
1266#ifdef CONFIG_APOLLO
1267 is_not_apollo(L(notapollo))
1268
1269 putc 'P'
1270 mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
1271
1272L(notapollo):
1273 jbra L(mmu_init_done)
1274#endif
1275
1276L(mmu_init_done):
1277
1278 putc 'G'
1279 leds 0x8
1280
1281/*
1282 * mmu_fixup
1283 *
1284 * On the 040 class machines, all pages that are used for the
1285 * mmu have to be fixed up. According to Motorola, pages holding mmu
1286 * tables should be non-cacheable on a '040 and write-through on a
1287 * '060. But analysis of the reasons for this, and practical
1288 * experience, showed that write-through also works on a '040.
1289 *
1290 * Allocated memory so far goes from kernel_end to memory_start that
1291 * is used for all kind of tables, for that the cache attributes
1292 * are now fixed.
1293 */
1294L(mmu_fixup):
1295
1296 is_not_040_or_060(L(mmu_fixup_done))
1297
1298#ifdef MMU_NOCACHE_KERNEL
1299 jbra L(mmu_fixup_done)
1300#endif
1301
1302 /* first fix the page at the start of the kernel, that
1303 * contains also kernel_pg_dir.
1304 */
1305 movel %pc@(L(phys_kernel_start)),%d0
1306 subl #PAGE_OFFSET,%d0
1307 lea %pc@(_stext),%a0
1308 subl %d0,%a0
1309 mmu_fixup_page_mmu_cache %a0
1310
1311 movel %pc@(L(kernel_end)),%a0
1312 subl %d0,%a0
1313 movel %pc@(L(memory_start)),%a1
1314 subl %d0,%a1
1315 bra 2f
13161:
1317 mmu_fixup_page_mmu_cache %a0
1318 addw #PAGESIZE,%a0
13192:
1320 cmpl %a0,%a1
1321 jgt 1b
1322
1323L(mmu_fixup_done):
1324
1325#ifdef MMU_PRINT
1326 mmu_print
1327#endif
1328
1329/*
1330 * mmu_engage
1331 *
1332 * This chunk of code performs the gruesome task of engaging the MMU.
1333 * The reason its gruesome is because when the MMU becomes engaged it
1334 * maps logical addresses to physical addresses. The Program Counter
1335 * register is then passed through the MMU before the next instruction
1336 * is fetched (the instruction following the engage MMU instruction).
1337 * This may mean one of two things:
1338 * 1. The Program Counter falls within the logical address space of
1339 * the kernel of which there are two sub-possibilities:
1340 * A. The PC maps to the correct instruction (logical PC == physical
1341 * code location), or
1342 * B. The PC does not map through and the processor will read some
1343 * data (or instruction) which is not the logically next instr.
1344 * As you can imagine, A is good and B is bad.
1345 * Alternatively,
1346 * 2. The Program Counter does not map through the MMU. The processor
1347 * will take a Bus Error.
1348 * Clearly, 2 is bad.
1349 * It doesn't take a wiz kid to figure you want 1.A.
1350 * This code creates that possibility.
1351 * There are two possible 1.A. states (we now ignore the other above states):
1352 * A. The kernel is located at physical memory addressed the same as
1353 * the logical memory for the kernel, i.e., 0x01000.
1354 * B. The kernel is located some where else. e.g., 0x0400.0000
1355 *
1356 * Under some conditions the Macintosh can look like A or B.
1357 * [A friend and I once noted that Apple hardware engineers should be
1358 * wacked twice each day: once when they show up at work (as in, Whack!,
1359 * "This is for the screwy hardware we know you're going to design today."),
1360 * and also at the end of the day (as in, Whack! "I don't know what
1361 * you designed today, but I'm sure it wasn't good."). -- rst]
1362 *
1363 * This code works on the following premise:
1364 * If the kernel start (%d5) is within the first 16 Meg of RAM,
1365 * then create a mapping for the kernel at logical 0x8000.0000 to
1366 * the physical location of the pc. And, create a transparent
1367 * translation register for the first 16 Meg. Then, after the MMU
1368 * is engaged, the PC can be moved up into the 0x8000.0000 range
1369 * and then the transparent translation can be turned off and then
1370 * the PC can jump to the correct logical location and it will be
1371 * home (finally). This is essentially the code that the Amiga used
1372 * to use. Now, it's generalized for all processors. Which means
1373 * that a fresh (but temporary) mapping has to be created. The mapping
1374 * is made in page 0 (an as of yet unused location -- except for the
1375 * stack!). This temporary mapping will only require 1 pointer table
1376 * and a single page table (it can map 256K).
1377 *
1378 * OK, alternatively, imagine that the Program Counter is not within
1379 * the first 16 Meg. Then, just use Transparent Translation registers
1380 * to do the right thing.
1381 *
1382 * Last, if _start is already at 0x01000, then there's nothing special
1383 * to do (in other words, in a degenerate case of the first case above,
1384 * do nothing).
1385 *
1386 * Let's do it.
1387 *
1388 *
1389 */
1390
1391 putc 'H'
1392
1393 mmu_engage
1394
1395/*
1396 * After this point no new memory is allocated and
1397 * the start of available memory is stored in availmem.
1398 * (The bootmem allocator requires now the physicall address.)
1399 */
1400
1401 movel L(memory_start),availmem
1402
1403#ifdef CONFIG_AMIGA
1404 is_not_amiga(1f)
1405 /* fixup the Amiga custom register location before printing */
1406 clrl L(custom)
14071:
1408#endif
1409
1410#ifdef CONFIG_ATARI
1411 is_not_atari(1f)
1412 /* fixup the Atari iobase register location before printing */
1413 movel #0xff000000,L(iobase)
14141:
1415#endif
1416
1417#ifdef CONFIG_MAC
1418 is_not_mac(1f)
1419 movel #~VIDEOMEMMASK,%d0
1420 andl L(mac_videobase),%d0
1421 addl #VIDEOMEMBASE,%d0
1422 movel %d0,L(mac_videobase)
1423#if defined(CONSOLE)
1424 movel %pc@(L(phys_kernel_start)),%d0
1425 subl #PAGE_OFFSET,%d0
1426 subl %d0,L(console_font)
1427 subl %d0,L(console_font_data)
1428#endif
1429#ifdef MAC_SERIAL_DEBUG
1430 orl #0x50000000,L(mac_sccbase)
1431#endif
14321:
1433#endif
1434
1435#ifdef CONFIG_HP300
1436 is_not_hp300(1f)
1437 /*
1438 * Fix up the iobase register to point to the new location of the LEDs.
1439 */
1440 movel #0xf0000000,L(iobase)
1441
1442 /*
1443 * Energise the FPU and caches.
1444 */
1445 is_040(1f)
1446 movel #0x60,0xf05f400c
1447 jbra 2f
1448
1449 /*
1450 * 040: slightly different, apparently.
1451 */
14521: movew #0,0xf05f400e
1453 movew #0x64,0xf05f400e
14542:
1455#endif
1456
1457#ifdef CONFIG_SUN3X
1458 is_not_sun3x(1f)
1459
1460 /* enable copro */
1461 oriw #0x4000,0x61000000
14621:
1463#endif
1464
1465#ifdef CONFIG_APOLLO
1466 is_not_apollo(1f)
1467
1468 /*
1469 * Fix up the iobase before printing
1470 */
1471 movel #0x80000000,L(iobase)
14721:
1473#endif
1474
1475 putc 'I'
1476 leds 0x10
1477
1478/*
1479 * Enable caches
1480 */
1481
1482 is_not_040_or_060(L(cache_not_680460))
1483
1484L(cache680460):
1485 .chip 68040
1486 nop
1487 cpusha %bc
1488 nop
1489
1490 is_060(L(cache68060))
1491
1492 movel #CC6_ENABLE_D+CC6_ENABLE_I,%d0
1493 /* MMU stuff works in copyback mode now, so enable the cache */
1494 movec %d0,%cacr
1495 jra L(cache_done)
1496
1497L(cache68060):
1498 movel #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0
1499 /* MMU stuff works in copyback mode now, so enable the cache */
1500 movec %d0,%cacr
1501 /* enable superscalar dispatch in PCR */
1502 moveq #1,%d0
1503 .chip 68060
1504 movec %d0,%pcr
1505
1506 jbra L(cache_done)
1507L(cache_not_680460):
1508L(cache68030):
1509 .chip 68030
1510 movel #CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0
1511 movec %d0,%cacr
1512
1513 jra L(cache_done)
1514 .chip 68k
1515L(cache_done):
1516
1517 putc 'J'
1518
1519/*
1520 * Setup initial stack pointer
1521 */
1522 lea init_task,%curptr
1523 lea init_thread_union+THREAD_SIZE,%sp
1524
1525 putc 'K'
1526
1527 subl %a6,%a6 /* clear a6 for gdb */
1528
1529/*
1530 * The new 64bit printf support requires an early exception initialization.
1531 */
1532 jbsr base_trap_init
1533
1534/* jump to the kernel start */
1535
1536 putc '\n'
1537 leds 0x55
1538
1539 jbsr start_kernel
1540
1541/*
1542 * Find a tag record in the bootinfo structure
1543 * The bootinfo structure is located right after the kernel bss
1544 * Returns: d0: size (-1 if not found)
1545 * a0: data pointer (end-of-records if not found)
1546 */
1547func_start get_bi_record,%d1
1548
1549 movel ARG1,%d0
1550 lea %pc@(_end),%a0
15511: tstw %a0@(BIR_TAG)
1552 jeq 3f
1553 cmpw %a0@(BIR_TAG),%d0
1554 jeq 2f
1555 addw %a0@(BIR_SIZE),%a0
1556 jra 1b
15572: moveq #0,%d0
1558 movew %a0@(BIR_SIZE),%d0
1559 lea %a0@(BIR_DATA),%a0
1560 jra 4f
15613: moveq #-1,%d0
1562 lea %a0@(BIR_SIZE),%a0
15634:
1564func_return get_bi_record
1565
1566
1567/*
1568 * MMU Initialization Begins Here
1569 *
1570 * The structure of the MMU tables on the 68k machines
1571 * is thus:
1572 * Root Table
1573 * Logical addresses are translated through
1574 * a hierarchical translation mechanism where the high-order
1575 * seven bits of the logical address (LA) are used as an
1576 * index into the "root table." Each entry in the root
1577 * table has a bit which specifies if it's a valid pointer to a
1578 * pointer table. Each entry defines a 32KMeg range of memory.
1579 * If an entry is invalid then that logical range of 32M is
1580 * invalid and references to that range of memory (when the MMU
1581 * is enabled) will fault. If the entry is valid, then it does
1582 * one of two things. On 040/060 class machines, it points to
1583 * a pointer table which then describes more finely the memory
1584 * within that 32M range. On 020/030 class machines, a technique
1585 * called "early terminating descriptors" are used. This technique
1586 * allows an entire 32Meg to be described by a single entry in the
1587 * root table. Thus, this entry in the root table, contains the
1588 * physical address of the memory or I/O at the logical address
1589 * which the entry represents and it also contains the necessary
1590 * cache bits for this region.
1591 *
1592 * Pointer Tables
1593 * Per the Root Table, there will be one or more
1594 * pointer tables. Each pointer table defines a 32M range.
1595 * Not all of the 32M range need be defined. Again, the next
1596 * seven bits of the logical address are used an index into
1597 * the pointer table to point to page tables (if the pointer
1598 * is valid). There will undoubtedly be more than one
1599 * pointer table for the kernel because each pointer table
1600 * defines a range of only 32M. Valid pointer table entries
1601 * point to page tables, or are early terminating entries
1602 * themselves.
1603 *
1604 * Page Tables
1605 * Per the Pointer Tables, each page table entry points
1606 * to the physical page in memory that supports the logical
1607 * address that translates to the particular index.
1608 *
1609 * In short, the Logical Address gets translated as follows:
1610 * bits 31..26 - index into the Root Table
1611 * bits 25..18 - index into the Pointer Table
1612 * bits 17..12 - index into the Page Table
1613 * bits 11..0 - offset into a particular 4K page
1614 *
1615 * The algorithms which follows do one thing: they abstract
1616 * the MMU hardware. For example, there are three kinds of
1617 * cache settings that are relevant. Either, memory is
1618 * being mapped in which case it is either Kernel Code (or
1619 * the RamDisk) or it is MMU data. On the 030, the MMU data
1620 * option also describes the kernel. Or, I/O is being mapped
1621 * in which case it has its own kind of cache bits. There
1622 * are constants which abstract these notions from the code that
1623 * actually makes the call to map some range of memory.
1624 *
1625 *
1626 *
1627 */
1628
1629#ifdef MMU_PRINT
1630/*
1631 * mmu_print
1632 *
1633 * This algorithm will print out the current MMU mappings.
1634 *
1635 * Input:
1636 * %a5 points to the root table. Everything else is calculated
1637 * from this.
1638 */
1639
1640#define mmu_next_valid 0
1641#define mmu_start_logical 4
1642#define mmu_next_logical 8
1643#define mmu_start_physical 12
1644#define mmu_next_physical 16
1645
1646#define MMU_PRINT_INVALID -1
1647#define MMU_PRINT_VALID 1
1648#define MMU_PRINT_UNINITED 0
1649
1650#define putZc(z,n) jbne 1f; putc z; jbra 2f; 1: putc n; 2:
1651
1652func_start mmu_print,%a0-%a6/%d0-%d7
1653
1654 movel %pc@(L(kernel_pgdir_ptr)),%a5
1655 lea %pc@(L(mmu_print_data)),%a0
1656 movel #MMU_PRINT_UNINITED,%a0@(mmu_next_valid)
1657
1658 is_not_040_or_060(mmu_030_print)
1659
1660mmu_040_print:
1661 puts "\nMMU040\n"
1662 puts "rp:"
1663 putn %a5
1664 putc '\n'
1665#if 0
1666 /*
1667 * The following #if/#endif block is a tight algorithm for dumping the 040
1668 * MMU Map in gory detail. It really isn't that practical unless the
1669 * MMU Map algorithm appears to go awry and you need to debug it at the
1670 * entry per entry level.
1671 */
1672 movel #ROOT_TABLE_SIZE,%d5
1673#if 0
1674 movel %a5@+,%d7 | Burn an entry to skip the kernel mappings,
1675 subql #1,%d5 | they (might) work
1676#endif
16771: tstl %d5
1678 jbeq mmu_print_done
1679 subq #1,%d5
1680 movel %a5@+,%d7
1681 btst #1,%d7
1682 jbeq 1b
1683
16842: putn %d7
1685 andil #0xFFFFFE00,%d7
1686 movel %d7,%a4
1687 movel #PTR_TABLE_SIZE,%d4
1688 putc ' '
16893: tstl %d4
1690 jbeq 11f
1691 subq #1,%d4
1692 movel %a4@+,%d7
1693 btst #1,%d7
1694 jbeq 3b
1695
16964: putn %d7
1697 andil #0xFFFFFF00,%d7
1698 movel %d7,%a3
1699 movel #PAGE_TABLE_SIZE,%d3
17005: movel #8,%d2
17016: tstl %d3
1702 jbeq 31f
1703 subq #1,%d3
1704 movel %a3@+,%d6
1705 btst #0,%d6
1706 jbeq 6b
17077: tstl %d2
1708 jbeq 8f
1709 subq #1,%d2
1710 putc ' '
1711 jbra 91f
17128: putc '\n'
1713 movel #8+1+8+1+1,%d2
17149: putc ' '
1715 dbra %d2,9b
1716 movel #7,%d2
171791: putn %d6
1718 jbra 6b
1719
172031: putc '\n'
1721 movel #8+1,%d2
172232: putc ' '
1723 dbra %d2,32b
1724 jbra 3b
1725
172611: putc '\n'
1727 jbra 1b
1728#endif /* MMU 040 Dumping code that's gory and detailed */
1729
1730 lea %pc@(kernel_pg_dir),%a5
1731 movel %a5,%a0 /* a0 has the address of the root table ptr */
1732 movel #0x00000000,%a4 /* logical address */
1733 moveql #0,%d0
173440:
1735 /* Increment the logical address and preserve in d5 */
1736 movel %a4,%d5
1737 addil #PAGESIZE<<13,%d5
1738 movel %a0@+,%d6
1739 btst #1,%d6
1740 jbne 41f
1741 jbsr mmu_print_tuple_invalidate
1742 jbra 48f
174341:
1744 movel #0,%d1
1745 andil #0xfffffe00,%d6
1746 movel %d6,%a1
174742:
1748 movel %a4,%d5
1749 addil #PAGESIZE<<6,%d5
1750 movel %a1@+,%d6
1751 btst #1,%d6
1752 jbne 43f
1753 jbsr mmu_print_tuple_invalidate
1754 jbra 47f
175543:
1756 movel #0,%d2
1757 andil #0xffffff00,%d6
1758 movel %d6,%a2
175944:
1760 movel %a4,%d5
1761 addil #PAGESIZE,%d5
1762 movel %a2@+,%d6
1763 btst #0,%d6
1764 jbne 45f
1765 jbsr mmu_print_tuple_invalidate
1766 jbra 46f
176745:
1768 moveml %d0-%d1,%sp@-
1769 movel %a4,%d0
1770 movel %d6,%d1
1771 andil #0xfffff4e0,%d1
1772 lea %pc@(mmu_040_print_flags),%a6
1773 jbsr mmu_print_tuple
1774 moveml %sp@+,%d0-%d1
177546:
1776 movel %d5,%a4
1777 addq #1,%d2
1778 cmpib #64,%d2
1779 jbne 44b
178047:
1781 movel %d5,%a4
1782 addq #1,%d1
1783 cmpib #128,%d1
1784 jbne 42b
178548:
1786 movel %d5,%a4 /* move to the next logical address */
1787 addq #1,%d0
1788 cmpib #128,%d0
1789 jbne 40b
1790
1791 .chip 68040
1792 movec %dtt1,%d0
1793 movel %d0,%d1
1794 andiw #0x8000,%d1 /* is it valid ? */
1795 jbeq 1f /* No, bail out */
1796
1797 movel %d0,%d1
1798 andil #0xff000000,%d1 /* Get the address */
1799 putn %d1
1800 puts "=="
1801 putn %d1
1802
1803 movel %d0,%d6
1804 jbsr mmu_040_print_flags_tt
18051:
1806 movec %dtt0,%d0
1807 movel %d0,%d1
1808 andiw #0x8000,%d1 /* is it valid ? */
1809 jbeq 1f /* No, bail out */
1810
1811 movel %d0,%d1
1812 andil #0xff000000,%d1 /* Get the address */
1813 putn %d1
1814 puts "=="
1815 putn %d1
1816
1817 movel %d0,%d6
1818 jbsr mmu_040_print_flags_tt
18191:
1820 .chip 68k
1821
1822 jbra mmu_print_done
1823
1824mmu_040_print_flags:
1825 btstl #10,%d6
1826 putZc(' ','G') /* global bit */
1827 btstl #7,%d6
1828 putZc(' ','S') /* supervisor bit */
1829mmu_040_print_flags_tt:
1830 btstl #6,%d6
1831 jbne 3f
1832 putc 'C'
1833 btstl #5,%d6
1834 putZc('w','c') /* write through or copy-back */
1835 jbra 4f
18363:
1837 putc 'N'
1838 btstl #5,%d6
1839 putZc('s',' ') /* serialized non-cacheable, or non-cacheable */
18404:
1841 rts
1842
1843mmu_030_print_flags:
1844 btstl #6,%d6
1845 putZc('C','I') /* write through or copy-back */
1846 rts
1847
1848mmu_030_print:
1849 puts "\nMMU030\n"
1850 puts "\nrp:"
1851 putn %a5
1852 putc '\n'
1853 movel %a5,%d0
1854 andil #0xfffffff0,%d0
1855 movel %d0,%a0
1856 movel #0x00000000,%a4 /* logical address */
1857 movel #0,%d0
185830:
1859 movel %a4,%d5
1860 addil #PAGESIZE<<13,%d5
1861 movel %a0@+,%d6
1862 btst #1,%d6 /* is it a table ptr? */
1863 jbne 31f /* yes */
1864 btst #0,%d6 /* is it early terminating? */
1865 jbeq 1f /* no */
1866 jbsr mmu_030_print_helper
1867 jbra 38f
18681:
1869 jbsr mmu_print_tuple_invalidate
1870 jbra 38f
187131:
1872 movel #0,%d1
1873 andil #0xfffffff0,%d6
1874 movel %d6,%a1
187532:
1876 movel %a4,%d5
1877 addil #PAGESIZE<<6,%d5
1878 movel %a1@+,%d6
1879 btst #1,%d6 /* is it a table ptr? */
1880 jbne 33f /* yes */
1881 btst #0,%d6 /* is it a page descriptor? */
1882 jbeq 1f /* no */
1883 jbsr mmu_030_print_helper
1884 jbra 37f
18851:
1886 jbsr mmu_print_tuple_invalidate
1887 jbra 37f
188833:
1889 movel #0,%d2
1890 andil #0xfffffff0,%d6
1891 movel %d6,%a2
189234:
1893 movel %a4,%d5
1894 addil #PAGESIZE,%d5
1895 movel %a2@+,%d6
1896 btst #0,%d6
1897 jbne 35f
1898 jbsr mmu_print_tuple_invalidate
1899 jbra 36f
190035:
1901 jbsr mmu_030_print_helper
190236:
1903 movel %d5,%a4
1904 addq #1,%d2
1905 cmpib #64,%d2
1906 jbne 34b
190737:
1908 movel %d5,%a4
1909 addq #1,%d1
1910 cmpib #128,%d1
1911 jbne 32b
191238:
1913 movel %d5,%a4 /* move to the next logical address */
1914 addq #1,%d0
1915 cmpib #128,%d0
1916 jbne 30b
1917
1918mmu_print_done:
1919 puts "\n\n"
1920
1921func_return mmu_print
1922
1923
1924mmu_030_print_helper:
1925 moveml %d0-%d1,%sp@-
1926 movel %a4,%d0
1927 movel %d6,%d1
1928 lea %pc@(mmu_030_print_flags),%a6
1929 jbsr mmu_print_tuple
1930 moveml %sp@+,%d0-%d1
1931 rts
1932
1933mmu_print_tuple_invalidate:
1934 moveml %a0/%d7,%sp@-
1935
1936 lea %pc@(L(mmu_print_data)),%a0
1937 tstl %a0@(mmu_next_valid)
1938 jbmi mmu_print_tuple_invalidate_exit
1939
1940 movel #MMU_PRINT_INVALID,%a0@(mmu_next_valid)
1941
1942 putn %a4
1943
1944 puts "##\n"
1945
1946mmu_print_tuple_invalidate_exit:
1947 moveml %sp@+,%a0/%d7
1948 rts
1949
1950
1951mmu_print_tuple:
1952 moveml %d0-%d7/%a0,%sp@-
1953
1954 lea %pc@(L(mmu_print_data)),%a0
1955
1956 tstl %a0@(mmu_next_valid)
1957 jble mmu_print_tuple_print
1958
1959 cmpl %a0@(mmu_next_physical),%d1
1960 jbeq mmu_print_tuple_increment
1961
1962mmu_print_tuple_print:
1963 putn %d0
1964 puts "->"
1965 putn %d1
1966
1967 movel %d1,%d6
1968 jbsr %a6@
1969
1970mmu_print_tuple_record:
1971 movel #MMU_PRINT_VALID,%a0@(mmu_next_valid)
1972
1973 movel %d1,%a0@(mmu_next_physical)
1974
1975mmu_print_tuple_increment:
1976 movel %d5,%d7
1977 subl %a4,%d7
1978 addl %d7,%a0@(mmu_next_physical)
1979
1980mmu_print_tuple_exit:
1981 moveml %sp@+,%d0-%d7/%a0
1982 rts
1983
1984mmu_print_machine_cpu_types:
1985 puts "machine: "
1986
1987 is_not_amiga(1f)
1988 puts "amiga"
1989 jbra 9f
19901:
1991 is_not_atari(2f)
1992 puts "atari"
1993 jbra 9f
19942:
1995 is_not_mac(3f)
1996 puts "macintosh"
1997 jbra 9f
19983: puts "unknown"
19999: putc '\n'
2000
2001 puts "cputype: 0"
2002 is_not_060(1f)
2003 putc '6'
2004 jbra 9f
20051:
2006 is_not_040_or_060(2f)
2007 putc '4'
2008 jbra 9f
20092: putc '3'
20109: putc '0'
2011 putc '\n'
2012
2013 rts
2014#endif /* MMU_PRINT */
2015
2016/*
2017 * mmu_map_tt
2018 *
2019 * This is a specific function which works on all 680x0 machines.
2020 * On 030, 040 & 060 it will attempt to use Transparent Translation
2021 * registers (tt1).
2022 * On 020 it will call the standard mmu_map which will use early
2023 * terminating descriptors.
2024 */
2025func_start mmu_map_tt,%d0/%d1/%a0,4
2026
2027 dputs "mmu_map_tt:"
2028 dputn ARG1
2029 dputn ARG2
2030 dputn ARG3
2031 dputn ARG4
2032 dputc '\n'
2033
2034 is_020(L(do_map))
2035
2036 /* Extract the highest bit set
2037 */
2038 bfffo ARG3{#0,#32},%d1
2039 cmpw #8,%d1
2040 jcc L(do_map)
2041
2042 /* And get the mask
2043 */
2044 moveq #-1,%d0
2045 lsrl %d1,%d0
2046 lsrl #1,%d0
2047
2048 /* Mask the address
2049 */
2050 movel %d0,%d1
2051 notl %d1
2052 andl ARG2,%d1
2053
2054 /* Generate the upper 16bit of the tt register
2055 */
2056 lsrl #8,%d0
2057 orl %d0,%d1
2058 clrw %d1
2059
2060 is_040_or_060(L(mmu_map_tt_040))
2061
2062 /* set 030 specific bits (read/write access for supervisor mode
2063 * (highest function code set, lower two bits masked))
2064 */
2065 orw #TTR_ENABLE+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d1
2066 movel ARG4,%d0
2067 btst #6,%d0
2068 jeq 1f
2069 orw #TTR_CI,%d1
2070
20711: lea STACK,%a0
2072 dputn %d1
2073 movel %d1,%a0@
2074 .chip 68030
2075 tstl ARG1
2076 jne 1f
2077 pmove %a0@,%tt0
2078 jra 2f
20791: pmove %a0@,%tt1
20802: .chip 68k
2081 jra L(mmu_map_tt_done)
2082
2083 /* set 040 specific bits
2084 */
2085L(mmu_map_tt_040):
2086 orw #TTR_ENABLE+TTR_KERNELMODE,%d1
2087 orl ARG4,%d1
2088 dputn %d1
2089
2090 .chip 68040
2091 tstl ARG1
2092 jne 1f
2093 movec %d1,%itt0
2094 movec %d1,%dtt0
2095 jra 2f
20961: movec %d1,%itt1
2097 movec %d1,%dtt1
20982: .chip 68k
2099
2100 jra L(mmu_map_tt_done)
2101
2102L(do_map):
2103 mmu_map_eq ARG2,ARG3,ARG4
2104
2105L(mmu_map_tt_done):
2106
2107func_return mmu_map_tt
2108
2109/*
2110 * mmu_map
2111 *
2112 * This routine will map a range of memory using a pointer
2113 * table and allocating the pages on the fly from the kernel.
2114 * The pointer table does not have to be already linked into
2115 * the root table, this routine will do that if necessary.
2116 *
2117 * NOTE
2118 * This routine will assert failure and use the serial_putc
2119 * routines in the case of a run-time error. For example,
2120 * if the address is already mapped.
2121 *
2122 * NOTE-2
2123 * This routine will use early terminating descriptors
2124 * where possible for the 68020+68851 and 68030 type
2125 * processors.
2126 */
2127func_start mmu_map,%d0-%d4/%a0-%a4
2128
2129 dputs "\nmmu_map:"
2130 dputn ARG1
2131 dputn ARG2
2132 dputn ARG3
2133 dputn ARG4
2134 dputc '\n'
2135
2136 /* Get logical address and round it down to 256KB
2137 */
2138 movel ARG1,%d0
2139 andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d0
2140 movel %d0,%a3
2141
2142 /* Get the end address
2143 */
2144 movel ARG1,%a4
2145 addl ARG3,%a4
2146 subql #1,%a4
2147
2148 /* Get physical address and round it down to 256KB
2149 */
2150 movel ARG2,%d0
2151 andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d0
2152 movel %d0,%a2
2153
2154 /* Add page attributes to the physical address
2155 */
2156 movel ARG4,%d0
2157 orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0
2158 addw %d0,%a2
2159
2160 dputn %a2
2161 dputn %a3
2162 dputn %a4
2163
2164 is_not_040_or_060(L(mmu_map_030))
2165
2166 addw #_PAGE_GLOBAL040,%a2
2167/*
2168 * MMU 040 & 060 Support
2169 *
2170 * The MMU usage for the 040 and 060 is different enough from
2171 * the 030 and 68851 that there is separate code. This comment
2172 * block describes the data structures and algorithms built by
2173 * this code.
2174 *
2175 * The 040 does not support early terminating descriptors, as
2176 * the 030 does. Therefore, a third level of table is needed
2177 * for the 040, and that would be the page table. In Linux,
2178 * page tables are allocated directly from the memory above the
2179 * kernel.
2180 *
2181 */
2182
2183L(mmu_map_040):
2184 /* Calculate the offset into the root table
2185 */
2186 movel %a3,%d0
2187 moveq #ROOT_INDEX_SHIFT,%d1
2188 lsrl %d1,%d0
2189 mmu_get_root_table_entry %d0
2190
2191 /* Calculate the offset into the pointer table
2192 */
2193 movel %a3,%d0
2194 moveq #PTR_INDEX_SHIFT,%d1
2195 lsrl %d1,%d0
2196 andl #PTR_TABLE_SIZE-1,%d0
2197 mmu_get_ptr_table_entry %a0,%d0
2198
2199 /* Calculate the offset into the page table
2200 */
2201 movel %a3,%d0
2202 moveq #PAGE_INDEX_SHIFT,%d1
2203 lsrl %d1,%d0
2204 andl #PAGE_TABLE_SIZE-1,%d0
2205 mmu_get_page_table_entry %a0,%d0
2206
2207 /* The page table entry must not no be busy
2208 */
2209 tstl %a0@
2210 jne L(mmu_map_error)
2211
2212 /* Do the mapping and advance the pointers
2213 */
2214 movel %a2,%a0@
22152:
2216 addw #PAGESIZE,%a2
2217 addw #PAGESIZE,%a3
2218
2219 /* Ready with mapping?
2220 */
2221 lea %a3@(-1),%a0
2222 cmpl %a0,%a4
2223 jhi L(mmu_map_040)
2224 jra L(mmu_map_done)
2225
2226L(mmu_map_030):
2227 /* Calculate the offset into the root table
2228 */
2229 movel %a3,%d0
2230 moveq #ROOT_INDEX_SHIFT,%d1
2231 lsrl %d1,%d0
2232 mmu_get_root_table_entry %d0
2233
2234 /* Check if logical address 32MB aligned,
2235 * so we can try to map it once
2236 */
2237 movel %a3,%d0
2238 andl #(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1)&(-ROOT_TABLE_SIZE),%d0
2239 jne 1f
2240
2241 /* Is there enough to map for 32MB at once
2242 */
2243 lea %a3@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1),%a1
2244 cmpl %a1,%a4
2245 jcs 1f
2246
2247 addql #1,%a1
2248
2249 /* The root table entry must not no be busy
2250 */
2251 tstl %a0@
2252 jne L(mmu_map_error)
2253
2254 /* Do the mapping and advance the pointers
2255 */
2256 dputs "early term1"
2257 dputn %a2
2258 dputn %a3
2259 dputn %a1
2260 dputc '\n'
2261 movel %a2,%a0@
2262
2263 movel %a1,%a3
2264 lea %a2@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE),%a2
2265 jra L(mmu_mapnext_030)
22661:
2267 /* Calculate the offset into the pointer table
2268 */
2269 movel %a3,%d0
2270 moveq #PTR_INDEX_SHIFT,%d1
2271 lsrl %d1,%d0
2272 andl #PTR_TABLE_SIZE-1,%d0
2273 mmu_get_ptr_table_entry %a0,%d0
2274
2275 /* The pointer table entry must not no be busy
2276 */
2277 tstl %a0@
2278 jne L(mmu_map_error)
2279
2280 /* Do the mapping and advance the pointers
2281 */
2282 dputs "early term2"
2283 dputn %a2
2284 dputn %a3
2285 dputc '\n'
2286 movel %a2,%a0@
2287
2288 addl #PAGE_TABLE_SIZE*PAGESIZE,%a2
2289 addl #PAGE_TABLE_SIZE*PAGESIZE,%a3
2290
2291L(mmu_mapnext_030):
2292 /* Ready with mapping?
2293 */
2294 lea %a3@(-1),%a0
2295 cmpl %a0,%a4
2296 jhi L(mmu_map_030)
2297 jra L(mmu_map_done)
2298
2299L(mmu_map_error):
2300
2301 dputs "mmu_map error:"
2302 dputn %a2
2303 dputn %a3
2304 dputc '\n'
2305
2306L(mmu_map_done):
2307
2308func_return mmu_map
2309
2310/*
2311 * mmu_fixup
2312 *
2313 * On the 040 class machines, all pages that are used for the
2314 * mmu have to be fixed up.
2315 */
2316
2317func_start mmu_fixup_page_mmu_cache,%d0/%a0
2318
2319 dputs "mmu_fixup_page_mmu_cache"
2320 dputn ARG1
2321
2322 /* Calculate the offset into the root table
2323 */
2324 movel ARG1,%d0
2325 moveq #ROOT_INDEX_SHIFT,%d1
2326 lsrl %d1,%d0
2327 mmu_get_root_table_entry %d0
2328
2329 /* Calculate the offset into the pointer table
2330 */
2331 movel ARG1,%d0
2332 moveq #PTR_INDEX_SHIFT,%d1
2333 lsrl %d1,%d0
2334 andl #PTR_TABLE_SIZE-1,%d0
2335 mmu_get_ptr_table_entry %a0,%d0
2336
2337 /* Calculate the offset into the page table
2338 */
2339 movel ARG1,%d0
2340 moveq #PAGE_INDEX_SHIFT,%d1
2341 lsrl %d1,%d0
2342 andl #PAGE_TABLE_SIZE-1,%d0
2343 mmu_get_page_table_entry %a0,%d0
2344
2345 movel %a0@,%d0
2346 andil #_CACHEMASK040,%d0
2347 orl %pc@(m68k_pgtable_cachemode),%d0
2348 movel %d0,%a0@
2349
2350 dputc '\n'
2351
2352func_return mmu_fixup_page_mmu_cache
2353
2354/*
2355 * mmu_temp_map
2356 *
2357 * create a temporary mapping to enable the mmu,
2358 * this we don't need any transparation translation tricks.
2359 */
2360
2361func_start mmu_temp_map,%d0/%d1/%a0/%a1
2362
2363 dputs "mmu_temp_map"
2364 dputn ARG1
2365 dputn ARG2
2366 dputc '\n'
2367
2368 lea %pc@(L(temp_mmap_mem)),%a1
2369
2370 /* Calculate the offset in the root table
2371 */
2372 movel ARG2,%d0
2373 moveq #ROOT_INDEX_SHIFT,%d1
2374 lsrl %d1,%d0
2375 mmu_get_root_table_entry %d0
2376
2377 /* Check if the table is temporary allocated, so we have to reuse it
2378 */
2379 movel %a0@,%d0
2380 cmpl %pc@(L(memory_start)),%d0
2381 jcc 1f
2382
2383 /* Temporary allocate a ptr table and insert it into the root table
2384 */
2385 movel %a1@,%d0
2386 addl #PTR_TABLE_SIZE*4,%a1@
2387 orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
2388 movel %d0,%a0@
2389 dputs " (new)"
23901:
2391 dputn %d0
2392 /* Mask the root table entry for the ptr table
2393 */
2394 andw #-ROOT_TABLE_SIZE,%d0
2395 movel %d0,%a0
2396
2397 /* Calculate the offset into the pointer table
2398 */
2399 movel ARG2,%d0
2400 moveq #PTR_INDEX_SHIFT,%d1
2401 lsrl %d1,%d0
2402 andl #PTR_TABLE_SIZE-1,%d0
2403 lea %a0@(%d0*4),%a0
2404 dputn %a0
2405
2406 /* Check if a temporary page table is already allocated
2407 */
2408 movel %a0@,%d0
2409 jne 1f
2410
2411 /* Temporary allocate a page table and insert it into the ptr table
2412 */
2413 movel %a1@,%d0
2414 /* The 512 should be PAGE_TABLE_SIZE*4, but that violates the
2415 alignment restriction for pointer tables on the '0[46]0. */
2416 addl #512,%a1@
2417 orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
2418 movel %d0,%a0@
2419 dputs " (new)"
24201:
2421 dputn %d0
2422 /* Mask the ptr table entry for the page table
2423 */
2424 andw #-PTR_TABLE_SIZE,%d0
2425 movel %d0,%a0
2426
2427 /* Calculate the offset into the page table
2428 */
2429 movel ARG2,%d0
2430 moveq #PAGE_INDEX_SHIFT,%d1
2431 lsrl %d1,%d0
2432 andl #PAGE_TABLE_SIZE-1,%d0
2433 lea %a0@(%d0*4),%a0
2434 dputn %a0
2435
2436 /* Insert the address into the page table
2437 */
2438 movel ARG1,%d0
2439 andw #-PAGESIZE,%d0
2440 orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0
2441 movel %d0,%a0@
2442 dputn %d0
2443
2444 dputc '\n'
2445
2446func_return mmu_temp_map
2447
2448func_start mmu_engage,%d0-%d2/%a0-%a3
2449
2450 moveq #ROOT_TABLE_SIZE-1,%d0
2451 /* Temporarily use a different root table. */
2452 lea %pc@(L(kernel_pgdir_ptr)),%a0
2453 movel %a0@,%a2
2454 movel %pc@(L(memory_start)),%a1
2455 movel %a1,%a0@
2456 movel %a2,%a0
24571:
2458 movel %a0@+,%a1@+
2459 dbra %d0,1b
2460
2461 lea %pc@(L(temp_mmap_mem)),%a0
2462 movel %a1,%a0@
2463
2464 movew #PAGESIZE-1,%d0
24651:
2466 clrl %a1@+
2467 dbra %d0,1b
2468
2469 lea %pc@(1b),%a0
2470 movel #1b,%a1
2471 /* Skip temp mappings if phys == virt */
2472 cmpl %a0,%a1
2473 jeq 1f
2474
2475 mmu_temp_map %a0,%a0
2476 mmu_temp_map %a0,%a1
2477
2478 addw #PAGESIZE,%a0
2479 addw #PAGESIZE,%a1
2480 mmu_temp_map %a0,%a0
2481 mmu_temp_map %a0,%a1
24821:
2483 movel %pc@(L(memory_start)),%a3
2484 movel %pc@(L(phys_kernel_start)),%d2
2485
2486 is_not_040_or_060(L(mmu_engage_030))
2487
2488L(mmu_engage_040):
2489 .chip 68040
2490 nop
2491 cinva %bc
2492 nop
2493 pflusha
2494 nop
2495 movec %a3,%srp
2496 movel #TC_ENABLE+TC_PAGE4K,%d0
2497 movec %d0,%tc /* enable the MMU */
2498 jmp 1f:l
24991: nop
2500 movec %a2,%srp
2501 nop
2502 cinva %bc
2503 nop
2504 pflusha
2505 .chip 68k
2506 jra L(mmu_engage_cleanup)
2507
2508L(mmu_engage_030_temp):
2509 .space 12
2510L(mmu_engage_030):
2511 .chip 68030
2512 lea %pc@(L(mmu_engage_030_temp)),%a0
2513 movel #0x80000002,%a0@
2514 movel %a3,%a0@(4)
2515 movel #0x0808,%d0
2516 movec %d0,%cacr
2517 pmove %a0@,%srp
2518 pflusha
2519 /*
2520 * enable,super root enable,4096 byte pages,7 bit root index,
2521 * 7 bit pointer index, 6 bit page table index.
2522 */
2523 movel #0x82c07760,%a0@(8)
2524 pmove %a0@(8),%tc /* enable the MMU */
2525 jmp 1f:l
25261: movel %a2,%a0@(4)
2527 movel #0x0808,%d0
2528 movec %d0,%cacr
2529 pmove %a0@,%srp
2530 pflusha
2531 .chip 68k
2532
2533L(mmu_engage_cleanup):
2534 subl #PAGE_OFFSET,%d2
2535 subl %d2,%a2
2536 movel %a2,L(kernel_pgdir_ptr)
2537 subl %d2,%fp
2538 subl %d2,%sp
2539 subl %d2,ARG0
2540
2541func_return mmu_engage
2542
2543func_start mmu_get_root_table_entry,%d0/%a1
2544
2545#if 0
2546 dputs "mmu_get_root_table_entry:"
2547 dputn ARG1
2548 dputs " ="
2549#endif
2550
2551 movel %pc@(L(kernel_pgdir_ptr)),%a0
2552 tstl %a0
2553 jne 2f
2554
2555 dputs "\nmmu_init:"
2556
2557 /* Find the start of free memory, get_bi_record does this for us,
2558 * as the bootinfo structure is located directly behind the kernel
2559 * and and we simply search for the last entry.
2560 */
2561 get_bi_record BI_LAST
2562 addw #PAGESIZE-1,%a0
2563 movel %a0,%d0
2564 andw #-PAGESIZE,%d0
2565
2566 dputn %d0
2567
2568 lea %pc@(L(memory_start)),%a0
2569 movel %d0,%a0@
2570 lea %pc@(L(kernel_end)),%a0
2571 movel %d0,%a0@
2572
2573 /* we have to return the first page at _stext since the init code
2574 * in mm/init.c simply expects kernel_pg_dir there, the rest of
2575 * page is used for further ptr tables in get_ptr_table.
2576 */
2577 lea %pc@(_stext),%a0
2578 lea %pc@(L(mmu_cached_pointer_tables)),%a1
2579 movel %a0,%a1@
2580 addl #ROOT_TABLE_SIZE*4,%a1@
2581
2582 lea %pc@(L(mmu_num_pointer_tables)),%a1
2583 addql #1,%a1@
2584
2585 /* clear the page
2586 */
2587 movel %a0,%a1
2588 movew #PAGESIZE/4-1,%d0
25891:
2590 clrl %a1@+
2591 dbra %d0,1b
2592
2593 lea %pc@(L(kernel_pgdir_ptr)),%a1
2594 movel %a0,%a1@
2595
2596 dputn %a0
2597 dputc '\n'
25982:
2599 movel ARG1,%d0
2600 lea %a0@(%d0*4),%a0
2601
2602#if 0
2603 dputn %a0
2604 dputc '\n'
2605#endif
2606
2607func_return mmu_get_root_table_entry
2608
2609
2610
2611func_start mmu_get_ptr_table_entry,%d0/%a1
2612
2613#if 0
2614 dputs "mmu_get_ptr_table_entry:"
2615 dputn ARG1
2616 dputn ARG2
2617 dputs " ="
2618#endif
2619
2620 movel ARG1,%a0
2621 movel %a0@,%d0
2622 jne 2f
2623
2624 /* Keep track of the number of pointer tables we use
2625 */
2626 dputs "\nmmu_get_new_ptr_table:"
2627 lea %pc@(L(mmu_num_pointer_tables)),%a0
2628 movel %a0@,%d0
2629 addql #1,%a0@
2630
2631 /* See if there is a free pointer table in our cache of pointer tables
2632 */
2633 lea %pc@(L(mmu_cached_pointer_tables)),%a1
2634 andw #7,%d0
2635 jne 1f
2636
2637 /* Get a new pointer table page from above the kernel memory
2638 */
2639 get_new_page
2640 movel %a0,%a1@
26411:
2642 /* There is an unused pointer table in our cache... use it
2643 */
2644 movel %a1@,%d0
2645 addl #PTR_TABLE_SIZE*4,%a1@
2646
2647 dputn %d0
2648 dputc '\n'
2649
2650 /* Insert the new pointer table into the root table
2651 */
2652 movel ARG1,%a0
2653 orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
2654 movel %d0,%a0@
26552:
2656 /* Extract the pointer table entry
2657 */
2658 andw #-PTR_TABLE_SIZE,%d0
2659 movel %d0,%a0
2660 movel ARG2,%d0
2661 lea %a0@(%d0*4),%a0
2662
2663#if 0
2664 dputn %a0
2665 dputc '\n'
2666#endif
2667
2668func_return mmu_get_ptr_table_entry
2669
2670
2671func_start mmu_get_page_table_entry,%d0/%a1
2672
2673#if 0
2674 dputs "mmu_get_page_table_entry:"
2675 dputn ARG1
2676 dputn ARG2
2677 dputs " ="
2678#endif
2679
2680 movel ARG1,%a0
2681 movel %a0@,%d0
2682 jne 2f
2683
2684 /* If the page table entry doesn't exist, we allocate a complete new
2685 * page and use it as one continues big page table which can cover
2686 * 4MB of memory, nearly almost all mappings have that alignment.
2687 */
2688 get_new_page
2689 addw #_PAGE_TABLE+_PAGE_ACCESSED,%a0
2690
2691 /* align pointer table entry for a page of page tables
2692 */
2693 movel ARG1,%d0
2694 andw #-(PAGESIZE/PAGE_TABLE_SIZE),%d0
2695 movel %d0,%a1
2696
2697 /* Insert the page tables into the pointer entries
2698 */
2699 moveq #PAGESIZE/PAGE_TABLE_SIZE/4-1,%d0
27001:
2701 movel %a0,%a1@+
2702 lea %a0@(PAGE_TABLE_SIZE*4),%a0
2703 dbra %d0,1b
2704
2705 /* Now we can get the initialized pointer table entry
2706 */
2707 movel ARG1,%a0
2708 movel %a0@,%d0
27092:
2710 /* Extract the page table entry
2711 */
2712 andw #-PAGE_TABLE_SIZE,%d0
2713 movel %d0,%a0
2714 movel ARG2,%d0
2715 lea %a0@(%d0*4),%a0
2716
2717#if 0
2718 dputn %a0
2719 dputc '\n'
2720#endif
2721
2722func_return mmu_get_page_table_entry
2723
2724/*
2725 * get_new_page
2726 *
2727 * Return a new page from the memory start and clear it.
2728 */
2729func_start get_new_page,%d0/%a1
2730
2731 dputs "\nget_new_page:"
2732
2733 /* allocate the page and adjust memory_start
2734 */
2735 lea %pc@(L(memory_start)),%a0
2736 movel %a0@,%a1
2737 addl #PAGESIZE,%a0@
2738
2739 /* clear the new page
2740 */
2741 movel %a1,%a0
2742 movew #PAGESIZE/4-1,%d0
27431:
2744 clrl %a1@+
2745 dbra %d0,1b
2746
2747 dputn %a0
2748 dputc '\n'
2749
2750func_return get_new_page
2751
2752
2753
2754/*
2755 * Debug output support
2756 * Atarians have a choice between the parallel port, the serial port
2757 * from the MFP or a serial port of the SCC
2758 */
2759
2760#ifdef CONFIG_MAC
2761
2762L(scc_initable_mac):
2763 .byte 9,12 /* Reset */
2764 .byte 4,0x44 /* x16, 1 stopbit, no parity */
2765 .byte 3,0xc0 /* receiver: 8 bpc */
2766 .byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */
2767 .byte 9,0 /* no interrupts */
2768 .byte 10,0 /* NRZ */
2769 .byte 11,0x50 /* use baud rate generator */
2770 .byte 12,10,13,0 /* 9600 baud */
2771 .byte 14,1 /* Baud rate generator enable */
2772 .byte 3,0xc1 /* enable receiver */
2773 .byte 5,0xea /* enable transmitter */
2774 .byte -1
2775 .even
2776#endif
2777
2778#ifdef CONFIG_ATARI
2779/* #define USE_PRINTER */
2780/* #define USE_SCC_B */
2781/* #define USE_SCC_A */
2782#define USE_MFP
2783
2784#if defined(USE_SCC_A) || defined(USE_SCC_B)
2785#define USE_SCC
2786/* Initialisation table for SCC */
2787L(scc_initable):
2788 .byte 9,12 /* Reset */
2789 .byte 4,0x44 /* x16, 1 stopbit, no parity */
2790 .byte 3,0xc0 /* receiver: 8 bpc */
2791 .byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */
2792 .byte 9,0 /* no interrupts */
2793 .byte 10,0 /* NRZ */
2794 .byte 11,0x50 /* use baud rate generator */
2795 .byte 12,24,13,0 /* 9600 baud */
2796 .byte 14,2,14,3 /* use master clock for BRG, enable */
2797 .byte 3,0xc1 /* enable receiver */
2798 .byte 5,0xea /* enable transmitter */
2799 .byte -1
2800 .even
2801#endif
2802
2803#ifdef USE_PRINTER
2804
2805LPSG_SELECT = 0xff8800
2806LPSG_READ = 0xff8800
2807LPSG_WRITE = 0xff8802
2808LPSG_IO_A = 14
2809LPSG_IO_B = 15
2810LPSG_CONTROL = 7
2811LSTMFP_GPIP = 0xfffa01
2812LSTMFP_DDR = 0xfffa05
2813LSTMFP_IERB = 0xfffa09
2814
2815#elif defined(USE_SCC_B)
2816
2817LSCC_CTRL = 0xff8c85
2818LSCC_DATA = 0xff8c87
2819
2820#elif defined(USE_SCC_A)
2821
2822LSCC_CTRL = 0xff8c81
2823LSCC_DATA = 0xff8c83
2824
2825#elif defined(USE_MFP)
2826
2827LMFP_UCR = 0xfffa29
2828LMFP_TDCDR = 0xfffa1d
2829LMFP_TDDR = 0xfffa25
2830LMFP_TSR = 0xfffa2d
2831LMFP_UDR = 0xfffa2f
2832
2833#endif
2834#endif /* CONFIG_ATARI */
2835
2836/*
2837 * Serial port output support.
2838 */
2839
2840/*
2841 * Initialize serial port hardware for 9600/8/1
2842 */
2843func_start serial_init,%d0/%d1/%a0/%a1
2844 /*
2845 * Some of the register usage that follows
2846 * CONFIG_AMIGA
2847 * a0 = pointer to boot info record
2848 * d0 = boot info offset
2849 * CONFIG_ATARI
2850 * a0 = address of SCC
2851 * a1 = Liobase address/address of scc_initable
2852 * d0 = init data for serial port
2853 * CONFIG_MAC
2854 * a0 = address of SCC
2855 * a1 = address of scc_initable_mac
2856 * d0 = init data for serial port
2857 */
2858
2859#ifdef CONFIG_AMIGA
2860#define SERIAL_DTR 7
2861#define SERIAL_CNTRL CIABBASE+C_PRA
2862
2863 is_not_amiga(1f)
2864 lea %pc@(L(custom)),%a0
2865 movel #-ZTWOBASE,%a0@
2866 bclr #SERIAL_DTR,SERIAL_CNTRL-ZTWOBASE
2867 get_bi_record BI_AMIGA_SERPER
2868 movew %a0@,CUSTOMBASE+C_SERPER-ZTWOBASE
2869| movew #61,CUSTOMBASE+C_SERPER-ZTWOBASE
28701:
2871#endif
2872#ifdef CONFIG_ATARI
2873 is_not_atari(4f)
2874 movel %pc@(L(iobase)),%a1
2875#if defined(USE_PRINTER)
2876 bclr #0,%a1@(LSTMFP_IERB)
2877 bclr #0,%a1@(LSTMFP_DDR)
2878 moveb #LPSG_CONTROL,%a1@(LPSG_SELECT)
2879 moveb #0xff,%a1@(LPSG_WRITE)
2880 moveb #LPSG_IO_B,%a1@(LPSG_SELECT)
2881 clrb %a1@(LPSG_WRITE)
2882 moveb #LPSG_IO_A,%a1@(LPSG_SELECT)
2883 moveb %a1@(LPSG_READ),%d0
2884 bset #5,%d0
2885 moveb %d0,%a1@(LPSG_WRITE)
2886#elif defined(USE_SCC)
2887 lea %a1@(LSCC_CTRL),%a0
2888 lea %pc@(L(scc_initable)),%a1
28892: moveb %a1@+,%d0
2890 jmi 3f
2891 moveb %d0,%a0@
2892 moveb %a1@+,%a0@
2893 jra 2b
28943: clrb %a0@
2895#elif defined(USE_MFP)
2896 bclr #1,%a1@(LMFP_TSR)
2897 moveb #0x88,%a1@(LMFP_UCR)
2898 andb #0x70,%a1@(LMFP_TDCDR)
2899 moveb #2,%a1@(LMFP_TDDR)
2900 orb #1,%a1@(LMFP_TDCDR)
2901 bset #1,%a1@(LMFP_TSR)
2902#endif
2903 jra L(serial_init_done)
29044:
2905#endif
2906#ifdef CONFIG_MAC
2907 is_not_mac(L(serial_init_not_mac))
2908#ifdef MAC_SERIAL_DEBUG
2909#if !defined(MAC_USE_SCC_A) && !defined(MAC_USE_SCC_B)
2910#define MAC_USE_SCC_B
2911#endif
2912#define mac_scc_cha_b_ctrl_offset 0x0
2913#define mac_scc_cha_a_ctrl_offset 0x2
2914#define mac_scc_cha_b_data_offset 0x4
2915#define mac_scc_cha_a_data_offset 0x6
2916
2917#ifdef MAC_USE_SCC_A
2918 /* Initialize channel A */
2919 movel %pc@(L(mac_sccbase)),%a0
2920 lea %pc@(L(scc_initable_mac)),%a1
29215: moveb %a1@+,%d0
2922 jmi 6f
2923 moveb %d0,%a0@(mac_scc_cha_a_ctrl_offset)
2924 moveb %a1@+,%a0@(mac_scc_cha_a_ctrl_offset)
2925 jra 5b
29266:
2927#endif /* MAC_USE_SCC_A */
2928
2929#ifdef MAC_USE_SCC_B
2930 /* Initialize channel B */
2931#ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */
2932 movel %pc@(L(mac_sccbase)),%a0
2933#endif /* MAC_USE_SCC_A */
2934 lea %pc@(L(scc_initable_mac)),%a1
29357: moveb %a1@+,%d0
2936 jmi 8f
2937 moveb %d0,%a0@(mac_scc_cha_b_ctrl_offset)
2938 moveb %a1@+,%a0@(mac_scc_cha_b_ctrl_offset)
2939 jra 7b
29408:
2941#endif /* MAC_USE_SCC_B */
2942#endif /* MAC_SERIAL_DEBUG */
2943
2944 jra L(serial_init_done)
2945L(serial_init_not_mac):
2946#endif /* CONFIG_MAC */
2947
2948#ifdef CONFIG_Q40
2949 is_not_q40(2f)
2950/* debug output goes into SRAM, so we don't do it unless requested
2951 - check for '%LX$' signature in SRAM */
2952 lea %pc@(q40_mem_cptr),%a1
2953 move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */
2954 move.l #0xff020000,%a1
2955 cmp.b #'%',%a1@
2956 bne 2f /*nodbg*/
2957 addq.w #4,%a1
2958 cmp.b #'L',%a1@
2959 bne 2f /*nodbg*/
2960 addq.w #4,%a1
2961 cmp.b #'X',%a1@
2962 bne 2f /*nodbg*/
2963 addq.w #4,%a1
2964 cmp.b #'$',%a1@
2965 bne 2f /*nodbg*/
2966 /* signature OK */
2967 lea %pc@(L(q40_do_debug)),%a1
2968 tas %a1@
2969/*nodbg: q40_do_debug is 0 by default*/
29702:
2971#endif
2972
2973#ifdef CONFIG_APOLLO
2974/* We count on the PROM initializing SIO1 */
2975#endif
2976
2977#ifdef CONFIG_HP300
2978/* We count on the boot loader initialising the UART */
2979#endif
2980
2981L(serial_init_done):
2982func_return serial_init
2983
2984/*
2985 * Output character on serial port.
2986 */
2987func_start serial_putc,%d0/%d1/%a0/%a1
2988
2989 movel ARG1,%d0
2990 cmpib #'\n',%d0
2991 jbne 1f
2992
2993 /* A little safe recursion is good for the soul */
2994 serial_putc #'\r'
29951:
2996
2997#ifdef CONFIG_AMIGA
2998 is_not_amiga(2f)
2999 andw #0x00ff,%d0
3000 oriw #0x0100,%d0
3001 movel %pc@(L(custom)),%a0
3002 movew %d0,%a0@(CUSTOMBASE+C_SERDAT)
30031: movew %a0@(CUSTOMBASE+C_SERDATR),%d0
3004 andw #0x2000,%d0
3005 jeq 1b
3006 jra L(serial_putc_done)
30072:
3008#endif
3009
3010#ifdef CONFIG_MAC
3011 is_not_mac(5f)
3012
3013#ifdef MAC_SERIAL_DEBUG
3014
3015#ifdef MAC_USE_SCC_A
3016 movel %pc@(L(mac_sccbase)),%a1
30173: btst #2,%a1@(mac_scc_cha_a_ctrl_offset)
3018 jeq 3b
3019 moveb %d0,%a1@(mac_scc_cha_a_data_offset)
3020#endif /* MAC_USE_SCC_A */
3021
3022#ifdef MAC_USE_SCC_B
3023#ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */
3024 movel %pc@(L(mac_sccbase)),%a1
3025#endif /* MAC_USE_SCC_A */
30264: btst #2,%a1@(mac_scc_cha_b_ctrl_offset)
3027 jeq 4b
3028 moveb %d0,%a1@(mac_scc_cha_b_data_offset)
3029#endif /* MAC_USE_SCC_B */
3030
3031#endif /* MAC_SERIAL_DEBUG */
3032
3033 jra L(serial_putc_done)
30345:
3035#endif /* CONFIG_MAC */
3036
3037#ifdef CONFIG_ATARI
3038 is_not_atari(4f)
3039 movel %pc@(L(iobase)),%a1
3040#if defined(USE_PRINTER)
30413: btst #0,%a1@(LSTMFP_GPIP)
3042 jne 3b
3043 moveb #LPSG_IO_B,%a1@(LPSG_SELECT)
3044 moveb %d0,%a1@(LPSG_WRITE)
3045 moveb #LPSG_IO_A,%a1@(LPSG_SELECT)
3046 moveb %a1@(LPSG_READ),%d0
3047 bclr #5,%d0
3048 moveb %d0,%a1@(LPSG_WRITE)
3049 nop
3050 nop
3051 bset #5,%d0
3052 moveb %d0,%a1@(LPSG_WRITE)
3053#elif defined(USE_SCC)
30543: btst #2,%a1@(LSCC_CTRL)
3055 jeq 3b
3056 moveb %d0,%a1@(LSCC_DATA)
3057#elif defined(USE_MFP)
30583: btst #7,%a1@(LMFP_TSR)
3059 jeq 3b
3060 moveb %d0,%a1@(LMFP_UDR)
3061#endif
3062 jra L(serial_putc_done)
30634:
3064#endif /* CONFIG_ATARI */
3065
3066#ifdef CONFIG_MVME147
3067 is_not_mvme147(2f)
30681: btst #2,M147_SCC_CTRL_A
3069 jeq 1b
3070 moveb %d0,M147_SCC_DATA_A
3071 jbra L(serial_putc_done)
30722:
3073#endif
3074
3075#ifdef CONFIG_MVME16x
3076 is_not_mvme16x(2f)
3077 /*
3078 * If the loader gave us a board type then we can use that to
3079 * select an appropriate output routine; otherwise we just use
3080 * the Bug code. If we haev to use the Bug that means the Bug
3081 * workspace has to be valid, which means the Bug has to use
3082 * the SRAM, which is non-standard.
3083 */
3084 moveml %d0-%d7/%a2-%a6,%sp@-
3085 movel vme_brdtype,%d1
3086 jeq 1f | No tag - use the Bug
3087 cmpi #VME_TYPE_MVME162,%d1
3088 jeq 6f
3089 cmpi #VME_TYPE_MVME172,%d1
3090 jne 5f
3091 /* 162/172; it's an SCC */
30926: btst #2,M162_SCC_CTRL_A
3093 nop
3094 nop
3095 nop
3096 jeq 6b
3097 moveb #8,M162_SCC_CTRL_A
3098 nop
3099 nop
3100 nop
3101 moveb %d0,M162_SCC_CTRL_A
3102 jra 3f
31035:
3104 /* 166/167/177; it's a CD2401 */
3105 moveb #0,M167_CYCAR
3106 moveb M167_CYIER,%d2
3107 moveb #0x02,M167_CYIER
31087:
3109 btst #5,M167_PCSCCTICR
3110 jeq 7b
3111 moveb M167_PCTPIACKR,%d1
3112 moveb M167_CYLICR,%d1
3113 jeq 8f
3114 moveb #0x08,M167_CYTEOIR
3115 jra 7b
31168:
3117 moveb %d0,M167_CYTDR
3118 moveb #0,M167_CYTEOIR
3119 moveb %d2,M167_CYIER
3120 jra 3f
31211:
3122 moveb %d0,%sp@-
3123 trap #15
3124 .word 0x0020 /* TRAP 0x020 */
31253:
3126 moveml %sp@+,%d0-%d7/%a2-%a6
3127 jbra L(serial_putc_done)
31282:
3129#endif /* CONFIG_MVME16x */
3130
3131#ifdef CONFIG_BVME6000
3132 is_not_bvme6000(2f)
3133 /*
3134 * The BVME6000 machine has a serial port ...
3135 */
31361: btst #2,BVME_SCC_CTRL_A
3137 jeq 1b
3138 moveb %d0,BVME_SCC_DATA_A
3139 jbra L(serial_putc_done)
31402:
3141#endif
3142
3143#ifdef CONFIG_SUN3X
3144 is_not_sun3x(2f)
3145 movel %d0,-(%sp)
3146 movel 0xFEFE0018,%a1
3147 jbsr (%a1)
3148 addq #4,%sp
3149 jbra L(serial_putc_done)
31502:
3151#endif
3152
3153#ifdef CONFIG_Q40
3154 is_not_q40(2f)
3155 tst.l %pc@(L(q40_do_debug)) /* only debug if requested */
3156 beq 2f
3157 lea %pc@(q40_mem_cptr),%a1
3158 move.l %a1@,%a0
3159 move.b %d0,%a0@
3160 addq.l #4,%a0
3161 move.l %a0,%a1@
3162 jbra L(serial_putc_done)
31632:
3164#endif
3165
3166#ifdef CONFIG_APOLLO
3167 is_not_apollo(2f)
3168 movl %pc@(L(iobase)),%a1
3169 moveb %d0,%a1@(LTHRB0)
31701: moveb %a1@(LSRB0),%d0
3171 andb #0x4,%d0
3172 beq 1b
3173 jbra L(serial_putc_done)
31742:
3175#endif
3176
3177#ifdef CONFIG_HP300
3178 is_not_hp300(3f)
3179 movl %pc@(L(iobase)),%a1
3180 addl %pc@(L(uartbase)),%a1
3181 movel %pc@(L(uart_scode)),%d1 /* Check the scode */
3182 jmi 3f /* Unset? Exit */
3183 cmpi #256,%d1 /* APCI scode? */
3184 jeq 2f
31851: moveb %a1@(DCALSR),%d1 /* Output to DCA */
3186 andb #0x20,%d1
3187 beq 1b
3188 moveb %d0,%a1@(DCADATA)
3189 jbra L(serial_putc_done)
31902: moveb %a1@(APCILSR),%d1 /* Output to APCI */
3191 andb #0x20,%d1
3192 beq 2b
3193 moveb %d0,%a1@(APCIDATA)
3194 jbra L(serial_putc_done)
31953:
3196#endif
3197
3198L(serial_putc_done):
3199func_return serial_putc
3200
3201/*
3202 * Output a string.
3203 */
3204func_start puts,%d0/%a0
3205
3206 movel ARG1,%a0
3207 jra 2f
32081:
3209#ifdef CONSOLE
3210 console_putc %d0
3211#endif
3212#ifdef SERIAL_DEBUG
3213 serial_putc %d0
3214#endif
32152: moveb %a0@+,%d0
3216 jne 1b
3217
3218func_return puts
3219
3220/*
3221 * Output number in hex notation.
3222 */
3223
3224func_start putn,%d0-%d2
3225
3226 putc ' '
3227
3228 movel ARG1,%d0
3229 moveq #7,%d1
32301: roll #4,%d0
3231 move %d0,%d2
3232 andb #0x0f,%d2
3233 addb #'0',%d2
3234 cmpb #'9',%d2
3235 jls 2f
3236 addb #'A'-('9'+1),%d2
32372:
3238#ifdef CONSOLE
3239 console_putc %d2
3240#endif
3241#ifdef SERIAL_DEBUG
3242 serial_putc %d2
3243#endif
3244 dbra %d1,1b
3245
3246func_return putn
3247
3248#ifdef CONFIG_MAC
3249/*
3250 * mac_serial_print
3251 *
3252 * This routine takes its parameters on the stack. It then
3253 * turns around and calls the internal routine. This routine
3254 * is used until the Linux console driver initializes itself.
3255 *
3256 * The calling parameters are:
3257 * void mac_serial_print(const char *str);
3258 *
3259 * This routine does NOT understand variable arguments only
3260 * simple strings!
3261 */
3262ENTRY(mac_serial_print)
3263 moveml %d0/%a0,%sp@-
3264#if 1
3265 move %sr,%sp@-
3266 ori #0x0700,%sr
3267#endif
3268 movel %sp@(10),%a0 /* fetch parameter */
3269 jra 2f
32701: serial_putc %d0
32712: moveb %a0@+,%d0
3272 jne 1b
3273#if 1
3274 move %sp@+,%sr
3275#endif
3276 moveml %sp@+,%d0/%a0
3277 rts
3278#endif /* CONFIG_MAC */
3279
3280#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
3281func_start set_leds,%d0/%a0
3282 movel ARG1,%d0
3283#ifdef CONFIG_HP300
3284 is_not_hp300(1f)
3285 movel %pc@(L(iobase)),%a0
3286 moveb %d0,%a0@(0x1ffff)
3287 jra 2f
3288#endif
32891:
3290#ifdef CONFIG_APOLLO
3291 movel %pc@(L(iobase)),%a0
3292 lsll #8,%d0
3293 eorw #0xff00,%d0
3294 moveb %d0,%a0@(LCPUCTRL)
3295#endif
32962:
3297func_return set_leds
3298#endif
3299
3300#ifdef CONSOLE
3301/*
3302 * For continuity, see the data alignment
3303 * to which this structure is tied.
3304 */
3305#define Lconsole_struct_cur_column 0
3306#define Lconsole_struct_cur_row 4
3307#define Lconsole_struct_num_columns 8
3308#define Lconsole_struct_num_rows 12
3309#define Lconsole_struct_left_edge 16
3310#define Lconsole_struct_penguin_putc 20
3311
3312func_start console_init,%a0-%a4/%d0-%d7
3313 /*
3314 * Some of the register usage that follows
3315 * a0 = pointer to boot_info
3316 * a1 = pointer to screen
3317 * a2 = pointer to Lconsole_globals
3318 * d3 = pixel width of screen
3319 * d4 = pixel height of screen
3320 * (d3,d4) ~= (x,y) of a point just below
3321 * and to the right of the screen
3322 * NOT on the screen!
3323 * d5 = number of bytes per scan line
3324 * d6 = number of bytes on the entire screen
3325 */
3326
3327 lea %pc@(L(console_globals)),%a2
3328 movel %pc@(L(mac_videobase)),%a1
3329 movel %pc@(L(mac_rowbytes)),%d5
3330 movel %pc@(L(mac_dimensions)),%d3 /* -> low byte */
3331 movel %d3,%d4
3332 swap %d4 /* -> high byte */
3333 andl #0xffff,%d3 /* d3 = screen width in pixels */
3334 andl #0xffff,%d4 /* d4 = screen height in pixels */
3335
3336 movel %d5,%d6
3337| subl #20,%d6
3338 mulul %d4,%d6 /* scan line bytes x num scan lines */
3339 divul #8,%d6 /* we'll clear 8 bytes at a time */
3340 moveq #-1,%d0 /* Mac_black */
3341 subq #1,%d6
3342
3343L(console_clear_loop):
3344 movel %d0,%a1@+
3345 movel %d0,%a1@+
3346 dbra %d6,L(console_clear_loop)
3347
3348 /* Calculate font size */
3349
3350#if defined(FONT_8x8) && defined(CONFIG_FONT_8x8)
3351 lea %pc@(font_vga_8x8),%a0
3352#elif defined(FONT_8x16) && defined(CONFIG_FONT_8x16)
3353 lea %pc@(font_vga_8x16),%a0
3354#elif defined(FONT_6x11) && defined(CONFIG_FONT_6x11)
3355 lea %pc@(font_vga_6x11),%a0
3356#elif defined(CONFIG_FONT_8x8) /* default */
3357 lea %pc@(font_vga_8x8),%a0
3358#else /* no compiled-in font */
3359 lea 0,%a0
3360#endif
3361
3362 /*
3363 * At this point we make a shift in register usage
3364 * a1 = address of console_font pointer
3365 */
3366 lea %pc@(L(console_font)),%a1
3367 movel %a0,%a1@ /* store pointer to struct fbcon_font_desc in console_font */
3368 tstl %a0
3369 jeq 1f
3370 lea %pc@(L(console_font_data)),%a4
3371 movel %a0@(FONT_DESC_DATA),%d0
3372 subl #L(console_font),%a1
3373 addl %a1,%d0
3374 movel %d0,%a4@
3375
3376 /*
3377 * Calculate global maxs
3378 * Note - we can use either an
3379 * 8 x 16 or 8 x 8 character font
3380 * 6 x 11 also supported
3381 */
3382 /* ASSERT: a0 = contents of Lconsole_font */
3383 movel %d3,%d0 /* screen width in pixels */
3384 divul %a0@(FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */
3385
3386 movel %d4,%d1 /* screen height in pixels */
3387 divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */
3388
3389 movel %d0,%a2@(Lconsole_struct_num_columns)
3390 movel %d1,%a2@(Lconsole_struct_num_rows)
3391
3392 /*
3393 * Clear the current row and column
3394 */
3395 clrl %a2@(Lconsole_struct_cur_column)
3396 clrl %a2@(Lconsole_struct_cur_row)
3397 clrl %a2@(Lconsole_struct_left_edge)
3398
3399 /*
3400 * Initialization is complete
3401 */
34021:
3403func_return console_init
3404
3405func_start console_put_stats,%a0/%d7
3406 /*
3407 * Some of the register usage that follows
3408 * a0 = pointer to boot_info
3409 * d7 = value of boot_info fields
3410 */
3411 puts "\nMacLinux\n\n"
3412
3413#ifdef SERIAL_DEBUG
3414 puts " vidaddr:"
3415 putn %pc@(L(mac_videobase)) /* video addr. */
3416
3417 puts "\n _stext:"
3418 lea %pc@(_stext),%a0
3419 putn %a0
3420
3421 puts "\nbootinfo:"
3422 lea %pc@(_end),%a0
3423 putn %a0
3424
3425 puts "\ncpuid:"
3426 putn %pc@(L(cputype))
3427 putc '\n'
3428
3429#ifdef MAC_SERIAL_DEBUG
3430 putn %pc@(L(mac_sccbase))
3431 putc '\n'
3432#endif
3433# if defined(MMU_PRINT)
3434 jbsr mmu_print_machine_cpu_types
3435# endif /* MMU_PRINT */
3436#endif /* SERIAL_DEBUG */
3437
3438func_return console_put_stats
3439
3440#ifdef CONSOLE_PENGUIN
3441func_start console_put_penguin,%a0-%a1/%d0-%d7
3442 /*
3443 * Get 'that_penguin' onto the screen in the upper right corner
3444 * penguin is 64 x 74 pixels, align against right edge of screen
3445 */
3446 lea %pc@(L(mac_dimensions)),%a0
3447 movel %a0@,%d0
3448 andil #0xffff,%d0
3449 subil #64,%d0 /* snug up against the right edge */
3450 clrl %d1 /* start at the top */
3451 movel #73,%d7
3452 lea %pc@(L(that_penguin)),%a1
3453L(console_penguin_row):
3454 movel #31,%d6
3455L(console_penguin_pixel_pair):
3456 moveb %a1@,%d2
3457 lsrb #4,%d2
3458 console_plot_pixel %d0,%d1,%d2
3459 addq #1,%d0
3460 moveb %a1@+,%d2
3461 console_plot_pixel %d0,%d1,%d2
3462 addq #1,%d0
3463 dbra %d6,L(console_penguin_pixel_pair)
3464
3465 subil #64,%d0
3466 addq #1,%d1
3467 dbra %d7,L(console_penguin_row)
3468
3469func_return console_put_penguin
3470
3471/* include penguin bitmap */
3472L(that_penguin):
3473#include "../mac/mac_penguin.S"
3474#endif
3475
3476 /*
3477 * Calculate source and destination addresses
3478 * output a1 = dest
3479 * a2 = source
3480 */
3481
3482func_start console_scroll,%a0-%a4/%d0-%d7
3483 lea %pc@(L(mac_videobase)),%a0
3484 movel %a0@,%a1
3485 movel %a1,%a2
3486 lea %pc@(L(mac_rowbytes)),%a0
3487 movel %a0@,%d5
3488 movel %pc@(L(console_font)),%a0
3489 tstl %a0
3490 jeq 1f
3491 mulul %a0@(FONT_DESC_HEIGHT),%d5 /* account for # scan lines per character */
3492 addal %d5,%a2
3493
3494 /*
3495 * Get dimensions
3496 */
3497 lea %pc@(L(mac_dimensions)),%a0
3498 movel %a0@,%d3
3499 movel %d3,%d4
3500 swap %d4
3501 andl #0xffff,%d3 /* d3 = screen width in pixels */
3502 andl #0xffff,%d4 /* d4 = screen height in pixels */
3503
3504 /*
3505 * Calculate number of bytes to move
3506 */
3507 lea %pc@(L(mac_rowbytes)),%a0
3508 movel %a0@,%d6
3509 movel %pc@(L(console_font)),%a0
3510 subl %a0@(FONT_DESC_HEIGHT),%d4 /* we're not scrolling the top row! */
3511 mulul %d4,%d6 /* scan line bytes x num scan lines */
3512 divul #32,%d6 /* we'll move 8 longs at a time */
3513 subq #1,%d6
3514
3515L(console_scroll_loop):
3516 movel %a2@+,%a1@+
3517 movel %a2@+,%a1@+
3518 movel %a2@+,%a1@+
3519 movel %a2@+,%a1@+
3520 movel %a2@+,%a1@+
3521 movel %a2@+,%a1@+
3522 movel %a2@+,%a1@+
3523 movel %a2@+,%a1@+
3524 dbra %d6,L(console_scroll_loop)
3525
3526 lea %pc@(L(mac_rowbytes)),%a0
3527 movel %a0@,%d6
3528 movel %pc@(L(console_font)),%a0
3529 mulul %a0@(FONT_DESC_HEIGHT),%d6 /* scan line bytes x font height */
3530 divul #32,%d6 /* we'll move 8 words at a time */
3531 subq #1,%d6
3532
3533 moveq #-1,%d0
3534L(console_scroll_clear_loop):
3535 movel %d0,%a1@+
3536 movel %d0,%a1@+
3537 movel %d0,%a1@+
3538 movel %d0,%a1@+
3539 movel %d0,%a1@+
3540 movel %d0,%a1@+
3541 movel %d0,%a1@+
3542 movel %d0,%a1@+
3543 dbra %d6,L(console_scroll_clear_loop)
3544
35451:
3546func_return console_scroll
3547
3548
3549func_start console_putc,%a0/%a1/%d0-%d7
3550
3551 is_not_mac(L(console_exit))
3552 tstl %pc@(L(console_font))
3553 jeq L(console_exit)
3554
3555 /* Output character in d7 on console.
3556 */
3557 movel ARG1,%d7
3558 cmpib #'\n',%d7
3559 jbne 1f
3560
3561 /* A little safe recursion is good for the soul */
3562 console_putc #'\r'
35631:
3564 lea %pc@(L(console_globals)),%a0
3565
3566 cmpib #10,%d7
3567 jne L(console_not_lf)
3568 movel %a0@(Lconsole_struct_cur_row),%d0
3569 addil #1,%d0
3570 movel %d0,%a0@(Lconsole_struct_cur_row)
3571 movel %a0@(Lconsole_struct_num_rows),%d1
3572 cmpl %d1,%d0
3573 jcs 1f
3574 subil #1,%d0
3575 movel %d0,%a0@(Lconsole_struct_cur_row)
3576 console_scroll
35771:
3578 jra L(console_exit)
3579
3580L(console_not_lf):
3581 cmpib #13,%d7
3582 jne L(console_not_cr)
3583 clrl %a0@(Lconsole_struct_cur_column)
3584 jra L(console_exit)
3585
3586L(console_not_cr):
3587 cmpib #1,%d7
3588 jne L(console_not_home)
3589 clrl %a0@(Lconsole_struct_cur_row)
3590 clrl %a0@(Lconsole_struct_cur_column)
3591 jra L(console_exit)
3592
3593/*
3594 * At this point we know that the %d7 character is going to be
3595 * rendered on the screen. Register usage is -
3596 * a0 = pointer to console globals
3597 * a1 = font data
3598 * d0 = cursor column
3599 * d1 = cursor row to draw the character
3600 * d7 = character number
3601 */
3602L(console_not_home):
3603 movel %a0@(Lconsole_struct_cur_column),%d0
3604 addql #1,%a0@(Lconsole_struct_cur_column)
3605 movel %a0@(Lconsole_struct_num_columns),%d1
3606 cmpl %d1,%d0
3607 jcs 1f
3608 console_putc #'\n' /* recursion is OK! */
36091:
3610 movel %a0@(Lconsole_struct_cur_row),%d1
3611
3612 /*
3613 * At this point we make a shift in register usage
3614 * a0 = address of pointer to font data (fbcon_font_desc)
3615 */
3616 movel %pc@(L(console_font)),%a0
3617 movel %pc@(L(console_font_data)),%a1 /* Load fbcon_font_desc.data into a1 */
3618 andl #0x000000ff,%d7
3619 /* ASSERT: a0 = contents of Lconsole_font */
3620 mulul %a0@(FONT_DESC_HEIGHT),%d7 /* d7 = index into font data */
3621 addl %d7,%a1 /* a1 = points to char image */
3622
3623 /*
3624 * At this point we make a shift in register usage
3625 * d0 = pixel coordinate, x
3626 * d1 = pixel coordinate, y
3627 * d2 = (bit 0) 1/0 for white/black (!) pixel on screen
3628 * d3 = font scan line data (8 pixels)
3629 * d6 = count down for the font's pixel width (8)
3630 * d7 = count down for the font's pixel count in height
3631 */
3632 /* ASSERT: a0 = contents of Lconsole_font */
3633 mulul %a0@(FONT_DESC_WIDTH),%d0
3634 mulul %a0@(FONT_DESC_HEIGHT),%d1
3635 movel %a0@(FONT_DESC_HEIGHT),%d7 /* Load fbcon_font_desc.height into d7 */
3636 subq #1,%d7
3637L(console_read_char_scanline):
3638 moveb %a1@+,%d3
3639
3640 /* ASSERT: a0 = contents of Lconsole_font */
3641 movel %a0@(FONT_DESC_WIDTH),%d6 /* Load fbcon_font_desc.width into d6 */
3642 subql #1,%d6
3643
3644L(console_do_font_scanline):
3645 lslb #1,%d3
3646 scsb %d2 /* convert 1 bit into a byte */
3647 console_plot_pixel %d0,%d1,%d2
3648 addq #1,%d0
3649 dbra %d6,L(console_do_font_scanline)
3650
3651 /* ASSERT: a0 = contents of Lconsole_font */
3652 subl %a0@(FONT_DESC_WIDTH),%d0
3653 addq #1,%d1
3654 dbra %d7,L(console_read_char_scanline)
3655
3656L(console_exit):
3657func_return console_putc
3658
3659 /*
3660 * Input:
3661 * d0 = x coordinate
3662 * d1 = y coordinate
3663 * d2 = (bit 0) 1/0 for white/black (!)
3664 * All registers are preserved
3665 */
3666func_start console_plot_pixel,%a0-%a1/%d0-%d4
3667
3668 movel %pc@(L(mac_videobase)),%a1
3669 movel %pc@(L(mac_videodepth)),%d3
3670 movel ARG1,%d0
3671 movel ARG2,%d1
3672 mulul %pc@(L(mac_rowbytes)),%d1
3673 movel ARG3,%d2
3674
3675 /*
3676 * Register usage:
3677 * d0 = x coord becomes byte offset into frame buffer
3678 * d1 = y coord
3679 * d2 = black or white (0/1)
3680 * d3 = video depth
3681 * d4 = temp of x (d0) for many bit depths
3682 */
3683L(test_1bit):
3684 cmpb #1,%d3
3685 jbne L(test_2bit)
3686 movel %d0,%d4 /* we need the low order 3 bits! */
3687 divul #8,%d0
3688 addal %d0,%a1
3689 addal %d1,%a1
3690 andb #7,%d4
3691 eorb #7,%d4 /* reverse the x-coordinate w/ screen-bit # */
3692 andb #1,%d2
3693 jbne L(white_1)
3694 bsetb %d4,%a1@
3695 jbra L(console_plot_pixel_exit)
3696L(white_1):
3697 bclrb %d4,%a1@
3698 jbra L(console_plot_pixel_exit)
3699
3700L(test_2bit):
3701 cmpb #2,%d3
3702 jbne L(test_4bit)
3703 movel %d0,%d4 /* we need the low order 2 bits! */
3704 divul #4,%d0
3705 addal %d0,%a1
3706 addal %d1,%a1
3707 andb #3,%d4
3708 eorb #3,%d4 /* reverse the x-coordinate w/ screen-bit # */
3709 lsll #1,%d4 /* ! */
3710 andb #1,%d2
3711 jbne L(white_2)
3712 bsetb %d4,%a1@
3713 addq #1,%d4
3714 bsetb %d4,%a1@
3715 jbra L(console_plot_pixel_exit)
3716L(white_2):
3717 bclrb %d4,%a1@
3718 addq #1,%d4
3719 bclrb %d4,%a1@
3720 jbra L(console_plot_pixel_exit)
3721
3722L(test_4bit):
3723 cmpb #4,%d3
3724 jbne L(test_8bit)
3725 movel %d0,%d4 /* we need the low order bit! */
3726 divul #2,%d0
3727 addal %d0,%a1
3728 addal %d1,%a1
3729 andb #1,%d4
3730 eorb #1,%d4
3731 lsll #2,%d4 /* ! */
3732 andb #1,%d2
3733 jbne L(white_4)
3734 bsetb %d4,%a1@
3735 addq #1,%d4
3736 bsetb %d4,%a1@
3737 addq #1,%d4
3738 bsetb %d4,%a1@
3739 addq #1,%d4
3740 bsetb %d4,%a1@
3741 jbra L(console_plot_pixel_exit)
3742L(white_4):
3743 bclrb %d4,%a1@
3744 addq #1,%d4
3745 bclrb %d4,%a1@
3746 addq #1,%d4
3747 bclrb %d4,%a1@
3748 addq #1,%d4
3749 bclrb %d4,%a1@
3750 jbra L(console_plot_pixel_exit)
3751
3752L(test_8bit):
3753 cmpb #8,%d3
3754 jbne L(test_16bit)
3755 addal %d0,%a1
3756 addal %d1,%a1
3757 andb #1,%d2
3758 jbne L(white_8)
3759 moveb #0xff,%a1@
3760 jbra L(console_plot_pixel_exit)
3761L(white_8):
3762 clrb %a1@
3763 jbra L(console_plot_pixel_exit)
3764
3765L(test_16bit):
3766 cmpb #16,%d3
3767 jbne L(console_plot_pixel_exit)
3768 addal %d0,%a1
3769 addal %d0,%a1
3770 addal %d1,%a1
3771 andb #1,%d2
3772 jbne L(white_16)
3773 clrw %a1@
3774 jbra L(console_plot_pixel_exit)
3775L(white_16):
3776 movew #0x0fff,%a1@
3777 jbra L(console_plot_pixel_exit)
3778
3779L(console_plot_pixel_exit):
3780func_return console_plot_pixel
3781#endif /* CONSOLE */
3782
3783#if 0
3784/*
3785 * This is some old code lying around. I don't believe
3786 * it's used or important anymore. My guess is it contributed
3787 * to getting to this point, but it's done for now.
3788 * It was still in the 2.1.77 head.S, so it's still here.
3789 * (And still not used!)
3790 */
3791L(showtest):
3792 moveml %a0/%d7,%sp@-
3793 puts "A="
3794 putn %a1
3795
3796 .long 0xf0119f15 | ptestr #5,%a1@,#7,%a0
3797
3798 puts "DA="
3799 putn %a0
3800
3801 puts "D="
3802 putn %a0@
3803
3804 puts "S="
3805 lea %pc@(L(mmu)),%a0
3806 .long 0xf0106200 | pmove %psr,%a0@
3807 clrl %d7
3808 movew %a0@,%d7
3809 putn %d7
3810
3811 putc '\n'
3812 moveml %sp@+,%a0/%d7
3813 rts
3814#endif /* 0 */
3815
3816__INITDATA
3817 .align 4
3818
3819#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \
3820 defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
3821L(custom):
3822L(iobase):
3823 .long 0
3824#endif
3825
3826#if defined(CONSOLE)
3827L(console_globals):
3828 .long 0 /* cursor column */
3829 .long 0 /* cursor row */
3830 .long 0 /* max num columns */
3831 .long 0 /* max num rows */
3832 .long 0 /* left edge */
3833 .long 0 /* mac putc */
3834L(console_font):
3835 .long 0 /* pointer to console font (struct font_desc) */
3836L(console_font_data):
3837 .long 0 /* pointer to console font data */
3838#endif /* CONSOLE */
3839
3840#if defined(MMU_PRINT)
3841L(mmu_print_data):
3842 .long 0 /* valid flag */
3843 .long 0 /* start logical */
3844 .long 0 /* next logical */
3845 .long 0 /* start physical */
3846 .long 0 /* next physical */
3847#endif /* MMU_PRINT */
3848
3849L(cputype):
3850 .long 0
3851L(mmu_cached_pointer_tables):
3852 .long 0
3853L(mmu_num_pointer_tables):
3854 .long 0
3855L(phys_kernel_start):
3856 .long 0
3857L(kernel_end):
3858 .long 0
3859L(memory_start):
3860 .long 0
3861L(kernel_pgdir_ptr):
3862 .long 0
3863L(temp_mmap_mem):
3864 .long 0
3865
3866#if defined (CONFIG_MVME147)
3867M147_SCC_CTRL_A = 0xfffe3002
3868M147_SCC_DATA_A = 0xfffe3003
3869#endif
3870
3871#if defined (CONFIG_MVME16x)
3872M162_SCC_CTRL_A = 0xfff45005
3873M167_CYCAR = 0xfff450ee
3874M167_CYIER = 0xfff45011
3875M167_CYLICR = 0xfff45026
3876M167_CYTEOIR = 0xfff45085
3877M167_CYTDR = 0xfff450f8
3878M167_PCSCCTICR = 0xfff4201e
3879M167_PCTPIACKR = 0xfff42025
3880#endif
3881
3882#if defined (CONFIG_BVME6000)
3883BVME_SCC_CTRL_A = 0xffb0000b
3884BVME_SCC_DATA_A = 0xffb0000f
3885#endif
3886
3887#if defined(CONFIG_MAC)
3888L(mac_booter_data):
3889 .long 0
3890L(mac_videobase):
3891 .long 0
3892L(mac_videodepth):
3893 .long 0
3894L(mac_dimensions):
3895 .long 0
3896L(mac_rowbytes):
3897 .long 0
3898#ifdef MAC_SERIAL_DEBUG
3899L(mac_sccbase):
3900 .long 0
3901#endif /* MAC_SERIAL_DEBUG */
3902#endif
3903
3904#if defined (CONFIG_APOLLO)
3905LSRB0 = 0x10412
3906LTHRB0 = 0x10416
3907LCPUCTRL = 0x10100
3908#endif
3909
3910#if defined(CONFIG_HP300)
3911DCADATA = 0x11
3912DCALSR = 0x1b
3913APCIDATA = 0x00
3914APCILSR = 0x14
3915L(uartbase):
3916 .long 0
3917L(uart_scode):
3918 .long -1
3919#endif
3920
3921__FINIT
3922 .data
3923 .align 4
3924
3925availmem:
3926 .long 0
3927m68k_pgtable_cachemode:
3928 .long 0
3929m68k_supervisor_cachemode:
3930 .long 0
3931#if defined(CONFIG_MVME16x)
3932mvme_bdid:
3933 .long 0,0,0,0,0,0,0,0
3934#endif
3935#if defined(CONFIG_Q40)
3936q40_mem_cptr:
3937 .long 0
3938L(q40_do_debug):
3939 .long 0
3940#endif
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
new file mode 100644
index 000000000000..514d323ad536
--- /dev/null
+++ b/arch/m68k/kernel/ints.c
@@ -0,0 +1,281 @@
1/*
2 * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive
6 * for more details.
7 *
8 * 07/03/96: Timer initialization, and thus mach_sched_init(),
9 * removed from request_irq() and moved to init_time().
10 * We should therefore consider renaming our add_isr() and
11 * remove_isr() to request_irq() and free_irq()
12 * respectively, so they are compliant with the other
13 * architectures. /Jes
14 * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
15 * Removed irq list support, if any machine needs an irq server
16 * it must implement this itself (as it's already done), instead
17 * only default handler are used with mach_default_handler.
18 * request_irq got some flags different from other architectures:
19 * - IRQ_FLG_REPLACE : Replace an existing handler (the default one
20 * can be replaced without this flag)
21 * - IRQ_FLG_LOCK : handler can't be replaced
22 * There are other machine depending flags, see there
23 * If you want to replace a default handler you should know what
24 * you're doing, since it might handle different other irq sources
25 * which must be served /Roman Zippel
26 */
27
28#include <linux/config.h>
29#include <linux/module.h>
30#include <linux/types.h>
31#include <linux/sched.h>
32#include <linux/kernel_stat.h>
33#include <linux/errno.h>
34#include <linux/init.h>
35
36#include <asm/setup.h>
37#include <asm/system.h>
38#include <asm/irq.h>
39#include <asm/traps.h>
40#include <asm/page.h>
41#include <asm/machdep.h>
42
43#ifdef CONFIG_Q40
44#include <asm/q40ints.h>
45#endif
46
47/* table for system interrupt handlers */
48static irq_handler_t irq_list[SYS_IRQS];
49
50static const char *default_names[SYS_IRQS] = {
51 [0] = "spurious int",
52 [1] = "int1 handler",
53 [2] = "int2 handler",
54 [3] = "int3 handler",
55 [4] = "int4 handler",
56 [5] = "int5 handler",
57 [6] = "int6 handler",
58 [7] = "int7 handler"
59};
60
61/* The number of spurious interrupts */
62volatile unsigned int num_spurious;
63
64#define NUM_IRQ_NODES 100
65static irq_node_t nodes[NUM_IRQ_NODES];
66
67static void dummy_enable_irq(unsigned int irq);
68static void dummy_disable_irq(unsigned int irq);
69static int dummy_request_irq(unsigned int irq,
70 irqreturn_t (*handler) (int, void *, struct pt_regs *),
71 unsigned long flags, const char *devname, void *dev_id);
72static void dummy_free_irq(unsigned int irq, void *dev_id);
73
74void (*enable_irq) (unsigned int) = dummy_enable_irq;
75void (*disable_irq) (unsigned int) = dummy_disable_irq;
76
77int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *),
78 unsigned long, const char *, void *) = dummy_request_irq;
79void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
80
81void init_irq_proc(void);
82
83/*
84 * void init_IRQ(void)
85 *
86 * Parameters: None
87 *
88 * Returns: Nothing
89 *
90 * This function should be called during kernel startup to initialize
91 * the IRQ handling routines.
92 */
93
94void __init init_IRQ(void)
95{
96 int i;
97
98 for (i = 0; i < SYS_IRQS; i++) {
99 if (mach_default_handler)
100 irq_list[i].handler = (*mach_default_handler)[i];
101 irq_list[i].flags = 0;
102 irq_list[i].dev_id = NULL;
103 irq_list[i].devname = default_names[i];
104 }
105
106 for (i = 0; i < NUM_IRQ_NODES; i++)
107 nodes[i].handler = NULL;
108
109 mach_init_IRQ ();
110}
111
112irq_node_t *new_irq_node(void)
113{
114 irq_node_t *node;
115 short i;
116
117 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
118 if (!node->handler)
119 return node;
120
121 printk ("new_irq_node: out of nodes\n");
122 return NULL;
123}
124
125/*
126 * We will keep these functions until I have convinced Linus to move
127 * the declaration of them from include/linux/sched.h to
128 * include/asm/irq.h.
129 */
130int request_irq(unsigned int irq,
131 irqreturn_t (*handler) (int, void *, struct pt_regs *),
132 unsigned long flags, const char *devname, void *dev_id)
133{
134 return mach_request_irq(irq, handler, flags, devname, dev_id);
135}
136
137EXPORT_SYMBOL(request_irq);
138
139void free_irq(unsigned int irq, void *dev_id)
140{
141 mach_free_irq(irq, dev_id);
142}
143
144EXPORT_SYMBOL(free_irq);
145
146int cpu_request_irq(unsigned int irq,
147 irqreturn_t (*handler)(int, void *, struct pt_regs *),
148 unsigned long flags, const char *devname, void *dev_id)
149{
150 if (irq < IRQ1 || irq > IRQ7) {
151 printk("%s: Incorrect IRQ %d from %s\n",
152 __FUNCTION__, irq, devname);
153 return -ENXIO;
154 }
155
156#if 0
157 if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
158 if (irq_list[irq].flags & IRQ_FLG_LOCK) {
159 printk("%s: IRQ %d from %s is not replaceable\n",
160 __FUNCTION__, irq, irq_list[irq].devname);
161 return -EBUSY;
162 }
163 if (!(flags & IRQ_FLG_REPLACE)) {
164 printk("%s: %s can't replace IRQ %d from %s\n",
165 __FUNCTION__, devname, irq, irq_list[irq].devname);
166 return -EBUSY;
167 }
168 }
169#endif
170
171 irq_list[irq].handler = handler;
172 irq_list[irq].flags = flags;
173 irq_list[irq].dev_id = dev_id;
174 irq_list[irq].devname = devname;
175 return 0;
176}
177
178void cpu_free_irq(unsigned int irq, void *dev_id)
179{
180 if (irq < IRQ1 || irq > IRQ7) {
181 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
182 return;
183 }
184
185 if (irq_list[irq].dev_id != dev_id)
186 printk("%s: Removing probably wrong IRQ %d from %s\n",
187 __FUNCTION__, irq, irq_list[irq].devname);
188
189 irq_list[irq].handler = (*mach_default_handler)[irq];
190 irq_list[irq].flags = 0;
191 irq_list[irq].dev_id = NULL;
192 irq_list[irq].devname = default_names[irq];
193}
194
195/*
196 * Do we need these probe functions on the m68k?
197 *
198 * ... may be useful with ISA devices
199 */
200unsigned long probe_irq_on (void)
201{
202#ifdef CONFIG_Q40
203 if (MACH_IS_Q40)
204 return q40_probe_irq_on();
205#endif
206 return 0;
207}
208
209EXPORT_SYMBOL(probe_irq_on);
210
211int probe_irq_off (unsigned long irqs)
212{
213#ifdef CONFIG_Q40
214 if (MACH_IS_Q40)
215 return q40_probe_irq_off(irqs);
216#endif
217 return 0;
218}
219
220EXPORT_SYMBOL(probe_irq_off);
221
222static void dummy_enable_irq(unsigned int irq)
223{
224 printk("calling uninitialized enable_irq()\n");
225}
226
227static void dummy_disable_irq(unsigned int irq)
228{
229 printk("calling uninitialized disable_irq()\n");
230}
231
232static int dummy_request_irq(unsigned int irq,
233 irqreturn_t (*handler) (int, void *, struct pt_regs *),
234 unsigned long flags, const char *devname, void *dev_id)
235{
236 printk("calling uninitialized request_irq()\n");
237 return 0;
238}
239
240static void dummy_free_irq(unsigned int irq, void *dev_id)
241{
242 printk("calling uninitialized disable_irq()\n");
243}
244
245asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
246{
247 if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
248 vec -= VEC_SPUR;
249 kstat_cpu(0).irqs[vec]++;
250 irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
251 } else {
252 if (mach_process_int)
253 mach_process_int(vec, fp);
254 else
255 panic("Can't process interrupt vector %ld\n", vec);
256 return;
257 }
258}
259
260int show_interrupts(struct seq_file *p, void *v)
261{
262 int i = *(loff_t *) v;
263
264 /* autovector interrupts */
265 if (i < SYS_IRQS) {
266 if (mach_default_handler) {
267 seq_printf(p, "auto %2d: %10u ", i,
268 i ? kstat_cpu(0).irqs[i] : num_spurious);
269 seq_puts(p, " ");
270 seq_printf(p, "%s\n", irq_list[i].devname);
271 }
272 } else if (i == SYS_IRQS)
273 mach_get_irq_list(p, v);
274 return 0;
275}
276
277void init_irq_proc(void)
278{
279 /* Insert /proc/irq driver here */
280}
281
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
new file mode 100644
index 000000000000..fe837e31afbf
--- /dev/null
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -0,0 +1,88 @@
1#include <linux/module.h>
2#include <linux/linkage.h>
3#include <linux/sched.h>
4#include <linux/string.h>
5#include <linux/mm.h>
6#include <linux/user.h>
7#include <linux/elfcore.h>
8#include <linux/in6.h>
9#include <linux/interrupt.h>
10#include <linux/config.h>
11
12#include <asm/setup.h>
13#include <asm/machdep.h>
14#include <asm/pgalloc.h>
15#include <asm/irq.h>
16#include <asm/io.h>
17#include <asm/semaphore.h>
18#include <asm/checksum.h>
19
20asmlinkage long long __ashldi3 (long long, int);
21asmlinkage long long __ashrdi3 (long long, int);
22asmlinkage long long __lshrdi3 (long long, int);
23asmlinkage long long __muldi3 (long long, long long);
24extern char m68k_debug_device[];
25
26extern void dump_thread(struct pt_regs *, struct user *);
27
28/* platform dependent support */
29
30EXPORT_SYMBOL(m68k_machtype);
31EXPORT_SYMBOL(m68k_cputype);
32EXPORT_SYMBOL(m68k_is040or060);
33EXPORT_SYMBOL(m68k_realnum_memory);
34EXPORT_SYMBOL(m68k_memory);
35#ifndef CONFIG_SUN3
36EXPORT_SYMBOL(cache_push);
37EXPORT_SYMBOL(cache_clear);
38#ifndef CONFIG_SINGLE_MEMORY_CHUNK
39EXPORT_SYMBOL(mm_vtop);
40EXPORT_SYMBOL(mm_ptov);
41EXPORT_SYMBOL(mm_end_of_chunk);
42#else
43EXPORT_SYMBOL(m68k_memoffset);
44#endif /* !CONFIG_SINGLE_MEMORY_CHUNK */
45EXPORT_SYMBOL(__ioremap);
46EXPORT_SYMBOL(iounmap);
47EXPORT_SYMBOL(kernel_set_cachemode);
48#endif /* !CONFIG_SUN3 */
49EXPORT_SYMBOL(m68k_debug_device);
50EXPORT_SYMBOL(mach_hwclk);
51EXPORT_SYMBOL(mach_get_ss);
52EXPORT_SYMBOL(mach_get_rtc_pll);
53EXPORT_SYMBOL(mach_set_rtc_pll);
54#ifdef CONFIG_INPUT_M68K_BEEP_MODULE
55EXPORT_SYMBOL(mach_beep);
56#endif
57EXPORT_SYMBOL(dump_fpu);
58EXPORT_SYMBOL(dump_thread);
59EXPORT_SYMBOL(strnlen);
60EXPORT_SYMBOL(strrchr);
61EXPORT_SYMBOL(strstr);
62EXPORT_SYMBOL(strpbrk);
63EXPORT_SYMBOL(enable_irq);
64EXPORT_SYMBOL(disable_irq);
65EXPORT_SYMBOL(kernel_thread);
66#ifdef CONFIG_VME
67EXPORT_SYMBOL(vme_brdtype);
68#endif
69
70/* The following are special because they're not called
71 explicitly (the C compiler generates them). Fortunately,
72 their interface isn't gonna change any time soon now, so
73 it's OK to leave it out of version control. */
74EXPORT_SYMBOL(__ashldi3);
75EXPORT_SYMBOL(__ashrdi3);
76EXPORT_SYMBOL(__lshrdi3);
77EXPORT_SYMBOL(memcpy);
78EXPORT_SYMBOL(memset);
79EXPORT_SYMBOL(memcmp);
80EXPORT_SYMBOL(memscan);
81EXPORT_SYMBOL(__muldi3);
82
83EXPORT_SYMBOL(__down_failed);
84EXPORT_SYMBOL(__down_failed_interruptible);
85EXPORT_SYMBOL(__down_failed_trylock);
86EXPORT_SYMBOL(__up_wakeup);
87
88EXPORT_SYMBOL(get_wchan);
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c
new file mode 100644
index 000000000000..3b1a2ff61ddc
--- /dev/null
+++ b/arch/m68k/kernel/module.c
@@ -0,0 +1,128 @@
1#include <linux/moduleloader.h>
2#include <linux/elf.h>
3#include <linux/vmalloc.h>
4#include <linux/fs.h>
5#include <linux/string.h>
6#include <linux/kernel.h>
7
8#if 0
9#define DEBUGP printk
10#else
11#define DEBUGP(fmt...)
12#endif
13
14void *module_alloc(unsigned long size)
15{
16 if (size == 0)
17 return NULL;
18 return vmalloc(size);
19}
20
21
22/* Free memory returned from module_alloc */
23void module_free(struct module *mod, void *module_region)
24{
25 vfree(module_region);
26 /* FIXME: If module_region == mod->init_region, trim exception
27 table entries. */
28}
29
30/* We don't need anything special. */
31int module_frob_arch_sections(Elf_Ehdr *hdr,
32 Elf_Shdr *sechdrs,
33 char *secstrings,
34 struct module *mod)
35{
36 return 0;
37}
38
39int apply_relocate(Elf32_Shdr *sechdrs,
40 const char *strtab,
41 unsigned int symindex,
42 unsigned int relsec,
43 struct module *me)
44{
45 unsigned int i;
46 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
47 Elf32_Sym *sym;
48 uint32_t *location;
49
50 DEBUGP("Applying relocate section %u to %u\n", relsec,
51 sechdrs[relsec].sh_info);
52 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
53 /* This is where to make the change */
54 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
55 + rel[i].r_offset;
56 /* This is the symbol it is referring to. Note that all
57 undefined symbols have been resolved. */
58 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
59 + ELF32_R_SYM(rel[i].r_info);
60
61 switch (ELF32_R_TYPE(rel[i].r_info)) {
62 case R_68K_32:
63 /* We add the value into the location given */
64 *location += sym->st_value;
65 break;
66 case R_68K_PC32:
67 /* Add the value, subtract its postition */
68 *location += sym->st_value - (uint32_t)location;
69 break;
70 default:
71 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
72 me->name, ELF32_R_TYPE(rel[i].r_info));
73 return -ENOEXEC;
74 }
75 }
76 return 0;
77}
78
79int apply_relocate_add(Elf32_Shdr *sechdrs,
80 const char *strtab,
81 unsigned int symindex,
82 unsigned int relsec,
83 struct module *me)
84{
85 unsigned int i;
86 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
87 Elf32_Sym *sym;
88 uint32_t *location;
89
90 DEBUGP("Applying relocate_add section %u to %u\n", relsec,
91 sechdrs[relsec].sh_info);
92 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
93 /* This is where to make the change */
94 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
95 + rel[i].r_offset;
96 /* This is the symbol it is referring to. Note that all
97 undefined symbols have been resolved. */
98 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
99 + ELF32_R_SYM(rel[i].r_info);
100
101 switch (ELF32_R_TYPE(rel[i].r_info)) {
102 case R_68K_32:
103 /* We add the value into the location given */
104 *location = rel[i].r_addend + sym->st_value;
105 break;
106 case R_68K_PC32:
107 /* Add the value, subtract its postition */
108 *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
109 break;
110 default:
111 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
112 me->name, ELF32_R_TYPE(rel[i].r_info));
113 return -ENOEXEC;
114 }
115 }
116 return 0;
117}
118
119int module_finalize(const Elf_Ehdr *hdr,
120 const Elf_Shdr *sechdrs,
121 struct module *me)
122{
123 return 0;
124}
125
126void module_arch_cleanup(struct module *mod)
127{
128}
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
new file mode 100644
index 000000000000..93b043e2a435
--- /dev/null
+++ b/arch/m68k/kernel/process.c
@@ -0,0 +1,405 @@
1/*
2 * linux/arch/m68k/kernel/process.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 *
6 * 68060 fixes by Jesper Skov
7 */
8
9/*
10 * This file handles the architecture-dependent parts of process handling..
11 */
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/mm.h>
19#include <linux/smp.h>
20#include <linux/smp_lock.h>
21#include <linux/stddef.h>
22#include <linux/unistd.h>
23#include <linux/ptrace.h>
24#include <linux/slab.h>
25#include <linux/user.h>
26#include <linux/a.out.h>
27#include <linux/reboot.h>
28#include <linux/init_task.h>
29#include <linux/mqueue.h>
30
31#include <asm/uaccess.h>
32#include <asm/system.h>
33#include <asm/traps.h>
34#include <asm/machdep.h>
35#include <asm/setup.h>
36#include <asm/pgtable.h>
37
38/*
39 * Initial task/thread structure. Make this a per-architecture thing,
40 * because different architectures tend to have different
41 * alignment requirements and potentially different initial
42 * setup.
43 */
44static struct fs_struct init_fs = INIT_FS;
45static struct files_struct init_files = INIT_FILES;
46static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
47static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
48struct mm_struct init_mm = INIT_MM(init_mm);
49
50EXPORT_SYMBOL(init_mm);
51
52union thread_union init_thread_union
53__attribute__((section(".data.init_task"), aligned(THREAD_SIZE)))
54 = { INIT_THREAD_INFO(init_task) };
55
56/* initial task structure */
57struct task_struct init_task = INIT_TASK(init_task);
58
59EXPORT_SYMBOL(init_task);
60
61asmlinkage void ret_from_fork(void);
62
63
64/*
65 * Return saved PC from a blocked thread
66 */
67unsigned long thread_saved_pc(struct task_struct *tsk)
68{
69 struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
70 /* Check whether the thread is blocked in resume() */
71 if (in_sched_functions(sw->retpc))
72 return ((unsigned long *)sw->a6)[1];
73 else
74 return sw->retpc;
75}
76
77/*
78 * The idle loop on an m68k..
79 */
80void default_idle(void)
81{
82 if (!need_resched())
83#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
84 /* block out HSYNC on the atari (falcon) */
85 __asm__("stop #0x2200" : : : "cc");
86#else
87 __asm__("stop #0x2000" : : : "cc");
88#endif
89}
90
91void (*idle)(void) = default_idle;
92
93/*
94 * The idle thread. There's no useful work to be
95 * done, so just try to conserve power and have a
96 * low exit latency (ie sit in a loop waiting for
97 * somebody to say that they'd like to reschedule)
98 */
99void cpu_idle(void)
100{
101 /* endless idle loop with no priority at all */
102 while (1) {
103 while (!need_resched())
104 idle();
105 schedule();
106 }
107}
108
109void machine_restart(char * __unused)
110{
111 if (mach_reset)
112 mach_reset();
113 for (;;);
114}
115
116EXPORT_SYMBOL(machine_restart);
117
118void machine_halt(void)
119{
120 if (mach_halt)
121 mach_halt();
122 for (;;);
123}
124
125EXPORT_SYMBOL(machine_halt);
126
127void machine_power_off(void)
128{
129 if (mach_power_off)
130 mach_power_off();
131 for (;;);
132}
133
134EXPORT_SYMBOL(machine_power_off);
135
136void show_regs(struct pt_regs * regs)
137{
138 printk("\n");
139 printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n",
140 regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
141 printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n",
142 regs->orig_d0, regs->d0, regs->a2, regs->a1);
143 printk("A0: %08lx D5: %08lx D4: %08lx\n",
144 regs->a0, regs->d5, regs->d4);
145 printk("D3: %08lx D2: %08lx D1: %08lx\n",
146 regs->d3, regs->d2, regs->d1);
147 if (!(regs->sr & PS_S))
148 printk("USP: %08lx\n", rdusp());
149}
150
151/*
152 * Create a kernel thread
153 */
154int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
155{
156 int pid;
157 mm_segment_t fs;
158
159 fs = get_fs();
160 set_fs (KERNEL_DS);
161
162 {
163 register long retval __asm__ ("d0");
164 register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
165
166 retval = __NR_clone;
167 __asm__ __volatile__
168 ("clrl %%d2\n\t"
169 "trap #0\n\t" /* Linux/m68k system call */
170 "tstl %0\n\t" /* child or parent */
171 "jne 1f\n\t" /* parent - jump */
172 "lea %%sp@(%c7),%6\n\t" /* reload current */
173 "movel %6@,%6\n\t"
174 "movel %3,%%sp@-\n\t" /* push argument */
175 "jsr %4@\n\t" /* call fn */
176 "movel %0,%%d1\n\t" /* pass exit value */
177 "movel %2,%%d0\n\t" /* exit */
178 "trap #0\n"
179 "1:"
180 : "+d" (retval)
181 : "i" (__NR_clone), "i" (__NR_exit),
182 "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
183 "i" (-THREAD_SIZE)
184 : "d2");
185
186 pid = retval;
187 }
188
189 set_fs (fs);
190 return pid;
191}
192
193void flush_thread(void)
194{
195 unsigned long zero = 0;
196 set_fs(USER_DS);
197 current->thread.fs = __USER_DS;
198 if (!FPU_IS_EMU)
199 asm volatile (".chip 68k/68881\n\t"
200 "frestore %0@\n\t"
201 ".chip 68k" : : "a" (&zero));
202}
203
204/*
205 * "m68k_fork()".. By the time we get here, the
206 * non-volatile registers have also been saved on the
207 * stack. We do some ugly pointer stuff here.. (see
208 * also copy_thread)
209 */
210
211asmlinkage int m68k_fork(struct pt_regs *regs)
212{
213 return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
214}
215
216asmlinkage int m68k_vfork(struct pt_regs *regs)
217{
218 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
219 NULL, NULL);
220}
221
222asmlinkage int m68k_clone(struct pt_regs *regs)
223{
224 unsigned long clone_flags;
225 unsigned long newsp;
226 int *parent_tidptr, *child_tidptr;
227
228 /* syscall2 puts clone_flags in d1 and usp in d2 */
229 clone_flags = regs->d1;
230 newsp = regs->d2;
231 parent_tidptr = (int *)regs->d3;
232 child_tidptr = (int *)regs->d4;
233 if (!newsp)
234 newsp = rdusp();
235 return do_fork(clone_flags, newsp, regs, 0,
236 parent_tidptr, child_tidptr);
237}
238
239int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
240 unsigned long unused,
241 struct task_struct * p, struct pt_regs * regs)
242{
243 struct pt_regs * childregs;
244 struct switch_stack * childstack, *stack;
245 unsigned long stack_offset, *retp;
246
247 stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
248 childregs = (struct pt_regs *) ((unsigned long) (p->thread_info) + stack_offset);
249
250 *childregs = *regs;
251 childregs->d0 = 0;
252
253 retp = ((unsigned long *) regs);
254 stack = ((struct switch_stack *) retp) - 1;
255
256 childstack = ((struct switch_stack *) childregs) - 1;
257 *childstack = *stack;
258 childstack->retpc = (unsigned long)ret_from_fork;
259
260 p->thread.usp = usp;
261 p->thread.ksp = (unsigned long)childstack;
262 /*
263 * Must save the current SFC/DFC value, NOT the value when
264 * the parent was last descheduled - RGH 10-08-96
265 */
266 p->thread.fs = get_fs().seg;
267
268 if (!FPU_IS_EMU) {
269 /* Copy the current fpu state */
270 asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
271
272 if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
273 asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
274 "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
275 : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
276 : "memory");
277 /* Restore the state in case the fpu was busy */
278 asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
279 }
280
281 return 0;
282}
283
284/* Fill in the fpu structure for a core dump. */
285
286int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
287{
288 char fpustate[216];
289
290 if (FPU_IS_EMU) {
291 int i;
292
293 memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
294 memcpy(fpu->fpregs, current->thread.fp, 96);
295 /* Convert internal fpu reg representation
296 * into long double format
297 */
298 for (i = 0; i < 24; i += 3)
299 fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
300 ((fpu->fpregs[i] & 0x0000ffff) << 16);
301 return 1;
302 }
303
304 /* First dump the fpu context to avoid protocol violation. */
305 asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
306 if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
307 return 0;
308
309 asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
310 :: "m" (fpu->fpcntl[0])
311 : "memory");
312 asm volatile ("fmovemx %/fp0-%/fp7,%0"
313 :: "m" (fpu->fpregs[0])
314 : "memory");
315 return 1;
316}
317
318/*
319 * fill in the user structure for a core dump..
320 */
321void dump_thread(struct pt_regs * regs, struct user * dump)
322{
323 struct switch_stack *sw;
324
325/* changed the size calculations - should hopefully work better. lbt */
326 dump->magic = CMAGIC;
327 dump->start_code = 0;
328 dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
329 dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
330 dump->u_dsize = ((unsigned long) (current->mm->brk +
331 (PAGE_SIZE-1))) >> PAGE_SHIFT;
332 dump->u_dsize -= dump->u_tsize;
333 dump->u_ssize = 0;
334
335 if (dump->start_stack < TASK_SIZE)
336 dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
337
338 dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
339 sw = ((struct switch_stack *)regs) - 1;
340 dump->regs.d1 = regs->d1;
341 dump->regs.d2 = regs->d2;
342 dump->regs.d3 = regs->d3;
343 dump->regs.d4 = regs->d4;
344 dump->regs.d5 = regs->d5;
345 dump->regs.d6 = sw->d6;
346 dump->regs.d7 = sw->d7;
347 dump->regs.a0 = regs->a0;
348 dump->regs.a1 = regs->a1;
349 dump->regs.a2 = regs->a2;
350 dump->regs.a3 = sw->a3;
351 dump->regs.a4 = sw->a4;
352 dump->regs.a5 = sw->a5;
353 dump->regs.a6 = sw->a6;
354 dump->regs.d0 = regs->d0;
355 dump->regs.orig_d0 = regs->orig_d0;
356 dump->regs.stkadj = regs->stkadj;
357 dump->regs.sr = regs->sr;
358 dump->regs.pc = regs->pc;
359 dump->regs.fmtvec = (regs->format << 12) | regs->vector;
360 /* dump floating point stuff */
361 dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
362}
363
364/*
365 * sys_execve() executes a new program.
366 */
367asmlinkage int sys_execve(char *name, char **argv, char **envp)
368{
369 int error;
370 char * filename;
371 struct pt_regs *regs = (struct pt_regs *) &name;
372
373 lock_kernel();
374 filename = getname(name);
375 error = PTR_ERR(filename);
376 if (IS_ERR(filename))
377 goto out;
378 error = do_execve(filename, argv, envp, regs);
379 putname(filename);
380out:
381 unlock_kernel();
382 return error;
383}
384
385unsigned long get_wchan(struct task_struct *p)
386{
387 unsigned long fp, pc;
388 unsigned long stack_page;
389 int count = 0;
390 if (!p || p == current || p->state == TASK_RUNNING)
391 return 0;
392
393 stack_page = (unsigned long)(p->thread_info);
394 fp = ((struct switch_stack *)p->thread.ksp)->a6;
395 do {
396 if (fp < stack_page+sizeof(struct thread_info) ||
397 fp >= 8184+stack_page)
398 return 0;
399 pc = ((unsigned long *)fp)[1];
400 if (!in_sched_functions(pc))
401 return pc;
402 fp = *(unsigned long *) fp;
403 } while (count++ < 16);
404 return 0;
405}
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
new file mode 100644
index 000000000000..0beb53333ba3
--- /dev/null
+++ b/arch/m68k/kernel/ptrace.c
@@ -0,0 +1,393 @@
1/*
2 * linux/arch/m68k/kernel/ptrace.c
3 *
4 * Copyright (C) 1994 by Hamish Macdonald
5 * Taken from linux/kernel/ptrace.c and modified for M680x0.
6 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of
10 * this archive for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
17#include <linux/smp_lock.h>
18#include <linux/errno.h>
19#include <linux/ptrace.h>
20#include <linux/user.h>
21#include <linux/config.h>
22
23#include <asm/uaccess.h>
24#include <asm/page.h>
25#include <asm/pgtable.h>
26#include <asm/system.h>
27#include <asm/processor.h>
28
29/*
30 * does not yet catch signals sent when the child dies.
31 * in exit.c or in signal.c.
32 */
33
34/* determines which bits in the SR the user has access to. */
35/* 1 = access 0 = no access */
36#define SR_MASK 0x001f
37
38/* sets the trace bits. */
39#define TRACE_BITS 0x8000
40
41/* Find the stack offset for a register, relative to thread.esp0. */
42#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
43#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
44 - sizeof(struct switch_stack))
45/* Mapping from PT_xxx to the stack offset at which the register is
46 saved. Notice that usp has no stack-slot and needs to be treated
47 specially (see get_reg/put_reg below). */
48static int regoff[] = {
49 [0] = PT_REG(d1),
50 [1] = PT_REG(d2),
51 [2] = PT_REG(d3),
52 [3] = PT_REG(d4),
53 [4] = PT_REG(d5),
54 [5] = SW_REG(d6),
55 [6] = SW_REG(d7),
56 [7] = PT_REG(a0),
57 [8] = PT_REG(a1),
58 [9] = PT_REG(a2),
59 [10] = SW_REG(a3),
60 [11] = SW_REG(a4),
61 [12] = SW_REG(a5),
62 [13] = SW_REG(a6),
63 [14] = PT_REG(d0),
64 [15] = -1,
65 [16] = PT_REG(orig_d0),
66 [17] = PT_REG(sr),
67 [18] = PT_REG(pc),
68};
69
70/*
71 * Get contents of register REGNO in task TASK.
72 */
73static inline long get_reg(struct task_struct *task, int regno)
74{
75 unsigned long *addr;
76
77 if (regno == PT_USP)
78 addr = &task->thread.usp;
79 else if (regno < sizeof(regoff)/sizeof(regoff[0]))
80 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
81 else
82 return 0;
83 return *addr;
84}
85
86/*
87 * Write contents of register REGNO in task TASK.
88 */
89static inline int put_reg(struct task_struct *task, int regno,
90 unsigned long data)
91{
92 unsigned long *addr;
93
94 if (regno == PT_USP)
95 addr = &task->thread.usp;
96 else if (regno < sizeof(regoff)/sizeof(regoff[0]))
97 addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
98 else
99 return -1;
100 *addr = data;
101 return 0;
102}
103
104/*
105 * Called by kernel/ptrace.c when detaching..
106 *
107 * Make sure the single step bit is not set.
108 */
109void ptrace_disable(struct task_struct *child)
110{
111 unsigned long tmp;
112 /* make sure the single step bit is not set. */
113 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
114 put_reg(child, PT_SR, tmp);
115 child->thread.work.delayed_trace = 0;
116 child->thread.work.syscall_trace = 0;
117}
118
119asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
120{
121 struct task_struct *child;
122 int ret;
123
124 lock_kernel();
125 ret = -EPERM;
126 if (request == PTRACE_TRACEME) {
127 /* are we already being traced? */
128 if (current->ptrace & PT_PTRACED)
129 goto out;
130 /* set the ptrace bit in the process flags. */
131 current->ptrace |= PT_PTRACED;
132 ret = 0;
133 goto out;
134 }
135 ret = -ESRCH;
136 read_lock(&tasklist_lock);
137 child = find_task_by_pid(pid);
138 if (child)
139 get_task_struct(child);
140 read_unlock(&tasklist_lock);
141 if (!child)
142 goto out;
143
144 ret = -EPERM;
145 if (pid == 1) /* you may not mess with init */
146 goto out_tsk;
147
148 if (request == PTRACE_ATTACH) {
149 ret = ptrace_attach(child);
150 goto out_tsk;
151 }
152
153 ret = ptrace_check_attach(child, request == PTRACE_KILL);
154 if (ret < 0)
155 goto out_tsk;
156
157 switch (request) {
158 /* when I and D space are separate, these will need to be fixed. */
159 case PTRACE_PEEKTEXT: /* read word at location addr. */
160 case PTRACE_PEEKDATA: {
161 unsigned long tmp;
162 int copied;
163
164 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
165 ret = -EIO;
166 if (copied != sizeof(tmp))
167 break;
168 ret = put_user(tmp,(unsigned long *) data);
169 break;
170 }
171
172 /* read the word at location addr in the USER area. */
173 case PTRACE_PEEKUSR: {
174 unsigned long tmp;
175
176 ret = -EIO;
177 if ((addr & 3) || addr < 0 ||
178 addr > sizeof(struct user) - 3)
179 break;
180
181 tmp = 0; /* Default return condition */
182 addr = addr >> 2; /* temporary hack. */
183 ret = -EIO;
184 if (addr < 19) {
185 tmp = get_reg(child, addr);
186 if (addr == PT_SR)
187 tmp >>= 16;
188 } else if (addr >= 21 && addr < 49) {
189 tmp = child->thread.fp[addr - 21];
190#ifdef CONFIG_M68KFPU_EMU
191 /* Convert internal fpu reg representation
192 * into long double format
193 */
194 if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
195 tmp = ((tmp & 0xffff0000) << 15) |
196 ((tmp & 0x0000ffff) << 16);
197#endif
198 } else
199 break;
200 ret = put_user(tmp,(unsigned long *) data);
201 break;
202 }
203
204 /* when I and D space are separate, this will have to be fixed. */
205 case PTRACE_POKETEXT: /* write the word at location addr. */
206 case PTRACE_POKEDATA:
207 ret = 0;
208 if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
209 break;
210 ret = -EIO;
211 break;
212
213 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
214 ret = -EIO;
215 if ((addr & 3) || addr < 0 ||
216 addr > sizeof(struct user) - 3)
217 break;
218
219 addr = addr >> 2; /* temporary hack. */
220
221 if (addr == PT_SR) {
222 data &= SR_MASK;
223 data <<= 16;
224 data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
225 }
226 if (addr < 19) {
227 if (put_reg(child, addr, data))
228 break;
229 ret = 0;
230 break;
231 }
232 if (addr >= 21 && addr < 48)
233 {
234#ifdef CONFIG_M68KFPU_EMU
235 /* Convert long double format
236 * into internal fpu reg representation
237 */
238 if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
239 data = (unsigned long)data << 15;
240 data = (data & 0xffff0000) |
241 ((data & 0x0000ffff) >> 1);
242 }
243#endif
244 child->thread.fp[addr - 21] = data;
245 ret = 0;
246 }
247 break;
248
249 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
250 case PTRACE_CONT: { /* restart after signal. */
251 long tmp;
252
253 ret = -EIO;
254 if ((unsigned long) data > _NSIG)
255 break;
256 if (request == PTRACE_SYSCALL) {
257 child->thread.work.syscall_trace = ~0;
258 } else {
259 child->thread.work.syscall_trace = 0;
260 }
261 child->exit_code = data;
262 /* make sure the single step bit is not set. */
263 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
264 put_reg(child, PT_SR, tmp);
265 child->thread.work.delayed_trace = 0;
266 wake_up_process(child);
267 ret = 0;
268 break;
269 }
270
271/*
272 * make the child exit. Best I can do is send it a sigkill.
273 * perhaps it should be put in the status that it wants to
274 * exit.
275 */
276 case PTRACE_KILL: {
277 long tmp;
278
279 ret = 0;
280 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
281 break;
282 child->exit_code = SIGKILL;
283 /* make sure the single step bit is not set. */
284 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
285 put_reg(child, PT_SR, tmp);
286 child->thread.work.delayed_trace = 0;
287 wake_up_process(child);
288 break;
289 }
290
291 case PTRACE_SINGLESTEP: { /* set the trap flag. */
292 long tmp;
293
294 ret = -EIO;
295 if ((unsigned long) data > _NSIG)
296 break;
297 child->thread.work.syscall_trace = 0;
298 tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
299 put_reg(child, PT_SR, tmp);
300 child->thread.work.delayed_trace = 1;
301
302 child->exit_code = data;
303 /* give it a chance to run. */
304 wake_up_process(child);
305 ret = 0;
306 break;
307 }
308
309 case PTRACE_DETACH: /* detach a process that was attached. */
310 ret = ptrace_detach(child, data);
311 break;
312
313 case PTRACE_GETREGS: { /* Get all gp regs from the child. */
314 int i;
315 unsigned long tmp;
316 for (i = 0; i < 19; i++) {
317 tmp = get_reg(child, i);
318 if (i == PT_SR)
319 tmp >>= 16;
320 if (put_user(tmp, (unsigned long *) data)) {
321 ret = -EFAULT;
322 break;
323 }
324 data += sizeof(long);
325 }
326 ret = 0;
327 break;
328 }
329
330 case PTRACE_SETREGS: { /* Set all gp regs in the child. */
331 int i;
332 unsigned long tmp;
333 for (i = 0; i < 19; i++) {
334 if (get_user(tmp, (unsigned long *) data)) {
335 ret = -EFAULT;
336 break;
337 }
338 if (i == PT_SR) {
339 tmp &= SR_MASK;
340 tmp <<= 16;
341 tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
342 }
343 put_reg(child, i, tmp);
344 data += sizeof(long);
345 }
346 ret = 0;
347 break;
348 }
349
350 case PTRACE_GETFPREGS: { /* Get the child FPU state. */
351 ret = 0;
352 if (copy_to_user((void *)data, &child->thread.fp,
353 sizeof(struct user_m68kfp_struct)))
354 ret = -EFAULT;
355 break;
356 }
357
358 case PTRACE_SETFPREGS: { /* Set the child FPU state. */
359 ret = 0;
360 if (copy_from_user(&child->thread.fp, (void *)data,
361 sizeof(struct user_m68kfp_struct)))
362 ret = -EFAULT;
363 break;
364 }
365
366 default:
367 ret = ptrace_request(child, request, addr, data);
368 break;
369 }
370out_tsk:
371 put_task_struct(child);
372out:
373 unlock_kernel();
374 return ret;
375}
376
377asmlinkage void syscall_trace(void)
378{
379 if (!current->thread.work.delayed_trace &&
380 !current->thread.work.syscall_trace)
381 return;
382 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
383 ? 0x80 : 0));
384 /*
385 * this isn't the same as continuing with a signal, but it will do
386 * for normal use. strace only continues with a signal if the
387 * stopping signal is not SIGTRAP. -brl
388 */
389 if (current->exit_code) {
390 send_sig(current->exit_code, current, 1);
391 current->exit_code = 0;
392 }
393}
diff --git a/arch/m68k/kernel/semaphore.c b/arch/m68k/kernel/semaphore.c
new file mode 100644
index 000000000000..1ebb79baaa8c
--- /dev/null
+++ b/arch/m68k/kernel/semaphore.c
@@ -0,0 +1,133 @@
1/*
2 * Generic semaphore code. Buyer beware. Do your own
3 * specific changes in <asm/semaphore-helper.h>
4 */
5
6#include <linux/config.h>
7#include <linux/sched.h>
8#include <linux/init.h>
9#include <asm/semaphore-helper.h>
10
11#ifndef CONFIG_RMW_INSNS
12spinlock_t semaphore_wake_lock;
13#endif
14
15/*
16 * Semaphores are implemented using a two-way counter:
17 * The "count" variable is decremented for each process
18 * that tries to sleep, while the "waking" variable is
19 * incremented when the "up()" code goes to wake up waiting
20 * processes.
21 *
22 * Notably, the inline "up()" and "down()" functions can
23 * efficiently test if they need to do any extra work (up
24 * needs to do something only if count was negative before
25 * the increment operation.
26 *
27 * waking_non_zero() (from asm/semaphore.h) must execute
28 * atomically.
29 *
30 * When __up() is called, the count was negative before
31 * incrementing it, and we need to wake up somebody.
32 *
33 * This routine adds one to the count of processes that need to
34 * wake up and exit. ALL waiting processes actually wake up but
35 * only the one that gets to the "waking" field first will gate
36 * through and acquire the semaphore. The others will go back
37 * to sleep.
38 *
39 * Note that these functions are only called when there is
40 * contention on the lock, and as such all this is the
41 * "non-critical" part of the whole semaphore business. The
42 * critical part is the inline stuff in <asm/semaphore.h>
43 * where we want to avoid any extra jumps and calls.
44 */
45void __up(struct semaphore *sem)
46{
47 wake_one_more(sem);
48 wake_up(&sem->wait);
49}
50
51/*
52 * Perform the "down" function. Return zero for semaphore acquired,
53 * return negative for signalled out of the function.
54 *
55 * If called from __down, the return is ignored and the wait loop is
56 * not interruptible. This means that a task waiting on a semaphore
57 * using "down()" cannot be killed until someone does an "up()" on
58 * the semaphore.
59 *
60 * If called from __down_interruptible, the return value gets checked
61 * upon return. If the return value is negative then the task continues
62 * with the negative value in the return register (it can be tested by
63 * the caller).
64 *
65 * Either form may be used in conjunction with "up()".
66 *
67 */
68
69
70#define DOWN_HEAD(task_state) \
71 \
72 \
73 current->state = (task_state); \
74 add_wait_queue(&sem->wait, &wait); \
75 \
76 /* \
77 * Ok, we're set up. sem->count is known to be less than zero \
78 * so we must wait. \
79 * \
80 * We can let go the lock for purposes of waiting. \
81 * We re-acquire it after awaking so as to protect \
82 * all semaphore operations. \
83 * \
84 * If "up()" is called before we call waking_non_zero() then \
85 * we will catch it right away. If it is called later then \
86 * we will have to go through a wakeup cycle to catch it. \
87 * \
88 * Multiple waiters contend for the semaphore lock to see \
89 * who gets to gate through and who has to wait some more. \
90 */ \
91 for (;;) {
92
93#define DOWN_TAIL(task_state) \
94 current->state = (task_state); \
95 } \
96 current->state = TASK_RUNNING; \
97 remove_wait_queue(&sem->wait, &wait);
98
99void __sched __down(struct semaphore * sem)
100{
101 DECLARE_WAITQUEUE(wait, current);
102
103 DOWN_HEAD(TASK_UNINTERRUPTIBLE)
104 if (waking_non_zero(sem))
105 break;
106 schedule();
107 DOWN_TAIL(TASK_UNINTERRUPTIBLE)
108}
109
110int __sched __down_interruptible(struct semaphore * sem)
111{
112 DECLARE_WAITQUEUE(wait, current);
113 int ret = 0;
114
115 DOWN_HEAD(TASK_INTERRUPTIBLE)
116
117 ret = waking_non_zero_interruptible(sem, current);
118 if (ret)
119 {
120 if (ret == 1)
121 /* ret != 0 only if we get interrupted -arca */
122 ret = 0;
123 break;
124 }
125 schedule();
126 DOWN_TAIL(TASK_INTERRUPTIBLE)
127 return ret;
128}
129
130int __down_trylock(struct semaphore * sem)
131{
132 return waking_non_zero_trylock(sem);
133}
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
new file mode 100644
index 000000000000..d6ca99242e5a
--- /dev/null
+++ b/arch/m68k/kernel/setup.c
@@ -0,0 +1,545 @@
1/*
2 * linux/arch/m68k/kernel/setup.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 */
6
7/*
8 * This file handles the architecture-dependent parts of system setup
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <linux/fs.h>
18#include <linux/console.h>
19#include <linux/genhd.h>
20#include <linux/errno.h>
21#include <linux/string.h>
22#include <linux/init.h>
23#include <linux/bootmem.h>
24#include <linux/seq_file.h>
25#include <linux/module.h>
26#include <linux/initrd.h>
27
28#include <asm/bootinfo.h>
29#include <asm/setup.h>
30#include <asm/irq.h>
31#include <asm/io.h>
32#include <asm/machdep.h>
33#ifdef CONFIG_AMIGA
34#include <asm/amigahw.h>
35#endif
36#ifdef CONFIG_ATARI
37#include <asm/atarihw.h>
38#include <asm/atari_stram.h>
39#endif
40#ifdef CONFIG_SUN3X
41#include <asm/dvma.h>
42#endif
43
44unsigned long m68k_machtype;
45unsigned long m68k_cputype;
46unsigned long m68k_fputype;
47unsigned long m68k_mmutype;
48#ifdef CONFIG_VME
49unsigned long vme_brdtype;
50#endif
51
52int m68k_is040or060;
53
54extern int end;
55extern unsigned long availmem;
56
57int m68k_num_memory;
58int m68k_realnum_memory;
59unsigned long m68k_memoffset;
60struct mem_info m68k_memory[NUM_MEMINFO];
61
62static struct mem_info m68k_ramdisk;
63
64static char m68k_command_line[CL_SIZE];
65
66char m68k_debug_device[6] = "";
67
68void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
69/* machine dependent irq functions */
70void (*mach_init_IRQ) (void) __initdata = NULL;
71irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
72void (*mach_get_model) (char *model);
73int (*mach_get_hardware_list) (char *buffer);
74int (*mach_get_irq_list) (struct seq_file *, void *);
75irqreturn_t (*mach_process_int) (int, struct pt_regs *);
76/* machine dependent timer functions */
77unsigned long (*mach_gettimeoffset) (void);
78int (*mach_hwclk) (int, struct rtc_time*);
79int (*mach_set_clock_mmss) (unsigned long);
80unsigned int (*mach_get_ss)(void);
81int (*mach_get_rtc_pll)(struct rtc_pll_info *);
82int (*mach_set_rtc_pll)(struct rtc_pll_info *);
83void (*mach_reset)( void );
84void (*mach_halt)( void );
85void (*mach_power_off)( void );
86long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
87#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
88void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
89#endif
90#ifdef CONFIG_HEARTBEAT
91void (*mach_heartbeat) (int);
92EXPORT_SYMBOL(mach_heartbeat);
93#endif
94#ifdef CONFIG_M68K_L2_CACHE
95void (*mach_l2_flush) (int);
96#endif
97#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
98void (*mach_beep)(unsigned int, unsigned int);
99#endif
100#if defined(CONFIG_ISA) && defined(MULTI_ISA)
101int isa_type;
102int isa_sex;
103#endif
104
105extern int amiga_parse_bootinfo(const struct bi_record *);
106extern int atari_parse_bootinfo(const struct bi_record *);
107extern int mac_parse_bootinfo(const struct bi_record *);
108extern int q40_parse_bootinfo(const struct bi_record *);
109extern int bvme6000_parse_bootinfo(const struct bi_record *);
110extern int mvme16x_parse_bootinfo(const struct bi_record *);
111extern int mvme147_parse_bootinfo(const struct bi_record *);
112extern int hp300_parse_bootinfo(const struct bi_record *);
113
114extern void config_amiga(void);
115extern void config_atari(void);
116extern void config_mac(void);
117extern void config_sun3(void);
118extern void config_apollo(void);
119extern void config_mvme147(void);
120extern void config_mvme16x(void);
121extern void config_bvme6000(void);
122extern void config_hp300(void);
123extern void config_q40(void);
124extern void config_sun3x(void);
125
126extern void mac_debugging_short (int, short);
127extern void mac_debugging_long (int, long);
128
129#define MASK_256K 0xfffc0000
130
131extern void paging_init(void);
132
133static void __init m68k_parse_bootinfo(const struct bi_record *record)
134{
135 while (record->tag != BI_LAST) {
136 int unknown = 0;
137 const unsigned long *data = record->data;
138 switch (record->tag) {
139 case BI_MACHTYPE:
140 case BI_CPUTYPE:
141 case BI_FPUTYPE:
142 case BI_MMUTYPE:
143 /* Already set up by head.S */
144 break;
145
146 case BI_MEMCHUNK:
147 if (m68k_num_memory < NUM_MEMINFO) {
148 m68k_memory[m68k_num_memory].addr = data[0];
149 m68k_memory[m68k_num_memory].size = data[1];
150 m68k_num_memory++;
151 } else
152 printk("m68k_parse_bootinfo: too many memory chunks\n");
153 break;
154
155 case BI_RAMDISK:
156 m68k_ramdisk.addr = data[0];
157 m68k_ramdisk.size = data[1];
158 break;
159
160 case BI_COMMAND_LINE:
161 strlcpy(m68k_command_line, (const char *)data, sizeof(m68k_command_line));
162 break;
163
164 default:
165 if (MACH_IS_AMIGA)
166 unknown = amiga_parse_bootinfo(record);
167 else if (MACH_IS_ATARI)
168 unknown = atari_parse_bootinfo(record);
169 else if (MACH_IS_MAC)
170 unknown = mac_parse_bootinfo(record);
171 else if (MACH_IS_Q40)
172 unknown = q40_parse_bootinfo(record);
173 else if (MACH_IS_BVME6000)
174 unknown = bvme6000_parse_bootinfo(record);
175 else if (MACH_IS_MVME16x)
176 unknown = mvme16x_parse_bootinfo(record);
177 else if (MACH_IS_MVME147)
178 unknown = mvme147_parse_bootinfo(record);
179 else if (MACH_IS_HP300)
180 unknown = hp300_parse_bootinfo(record);
181 else
182 unknown = 1;
183 }
184 if (unknown)
185 printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
186 record->tag);
187 record = (struct bi_record *)((unsigned long)record+record->size);
188 }
189
190 m68k_realnum_memory = m68k_num_memory;
191#ifdef CONFIG_SINGLE_MEMORY_CHUNK
192 if (m68k_num_memory > 1) {
193 printk("Ignoring last %i chunks of physical memory\n",
194 (m68k_num_memory - 1));
195 m68k_num_memory = 1;
196 }
197 m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
198#endif
199}
200
201void __init setup_arch(char **cmdline_p)
202{
203 extern int _etext, _edata, _end;
204#ifndef CONFIG_SUN3
205 unsigned long endmem, startmem;
206#endif
207 int i;
208 char *p, *q;
209
210 /* The bootinfo is located right after the kernel bss */
211 m68k_parse_bootinfo((const struct bi_record *)&_end);
212
213 if (CPU_IS_040)
214 m68k_is040or060 = 4;
215 else if (CPU_IS_060)
216 m68k_is040or060 = 6;
217
218 /* FIXME: m68k_fputype is passed in by Penguin booter, which can
219 * be confused by software FPU emulation. BEWARE.
220 * We should really do our own FPU check at startup.
221 * [what do we do with buggy 68LC040s? if we have problems
222 * with them, we should add a test to check_bugs() below] */
223#ifndef CONFIG_M68KFPU_EMU_ONLY
224 /* clear the fpu if we have one */
225 if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
226 volatile int zero = 0;
227 asm __volatile__ ("frestore %0" : : "m" (zero));
228 }
229#endif
230
231 if (CPU_IS_060) {
232 u32 pcr;
233
234 asm (".chip 68060; movec %%pcr,%0; .chip 68k"
235 : "=d" (pcr));
236 if (((pcr >> 8) & 0xff) <= 5) {
237 printk("Enabling workaround for errata I14\n");
238 asm (".chip 68060; movec %0,%%pcr; .chip 68k"
239 : : "d" (pcr | 0x20));
240 }
241 }
242
243 init_mm.start_code = PAGE_OFFSET;
244 init_mm.end_code = (unsigned long) &_etext;
245 init_mm.end_data = (unsigned long) &_edata;
246 init_mm.brk = (unsigned long) &_end;
247
248 *cmdline_p = m68k_command_line;
249 memcpy(saved_command_line, *cmdline_p, CL_SIZE);
250
251 /* Parse the command line for arch-specific options.
252 * For the m68k, this is currently only "debug=xxx" to enable printing
253 * certain kernel messages to some machine-specific device.
254 */
255 for( p = *cmdline_p; p && *p; ) {
256 i = 0;
257 if (!strncmp( p, "debug=", 6 )) {
258 strlcpy( m68k_debug_device, p+6, sizeof(m68k_debug_device) );
259 if ((q = strchr( m68k_debug_device, ' ' ))) *q = 0;
260 i = 1;
261 }
262#ifdef CONFIG_ATARI
263 /* This option must be parsed very early */
264 if (!strncmp( p, "switches=", 9 )) {
265 extern void atari_switches_setup( const char *, int );
266 atari_switches_setup( p+9, (q = strchr( p+9, ' ' )) ?
267 (q - (p+9)) : strlen(p+9) );
268 i = 1;
269 }
270#endif
271
272 if (i) {
273 /* option processed, delete it */
274 if ((q = strchr( p, ' ' )))
275 strcpy( p, q+1 );
276 else
277 *p = 0;
278 } else {
279 if ((p = strchr( p, ' ' ))) ++p;
280 }
281 }
282
283 switch (m68k_machtype) {
284#ifdef CONFIG_AMIGA
285 case MACH_AMIGA:
286 config_amiga();
287 break;
288#endif
289#ifdef CONFIG_ATARI
290 case MACH_ATARI:
291 config_atari();
292 break;
293#endif
294#ifdef CONFIG_MAC
295 case MACH_MAC:
296 config_mac();
297 break;
298#endif
299#ifdef CONFIG_SUN3
300 case MACH_SUN3:
301 config_sun3();
302 break;
303#endif
304#ifdef CONFIG_APOLLO
305 case MACH_APOLLO:
306 config_apollo();
307 break;
308#endif
309#ifdef CONFIG_MVME147
310 case MACH_MVME147:
311 config_mvme147();
312 break;
313#endif
314#ifdef CONFIG_MVME16x
315 case MACH_MVME16x:
316 config_mvme16x();
317 break;
318#endif
319#ifdef CONFIG_BVME6000
320 case MACH_BVME6000:
321 config_bvme6000();
322 break;
323#endif
324#ifdef CONFIG_HP300
325 case MACH_HP300:
326 config_hp300();
327 break;
328#endif
329#ifdef CONFIG_Q40
330 case MACH_Q40:
331 config_q40();
332 break;
333#endif
334#ifdef CONFIG_SUN3X
335 case MACH_SUN3X:
336 config_sun3x();
337 break;
338#endif
339 default:
340 panic ("No configuration setup");
341 }
342
343#ifndef CONFIG_SUN3
344 startmem= m68k_memory[0].addr;
345 endmem = startmem + m68k_memory[0].size;
346 high_memory = (void *)PAGE_OFFSET;
347 for (i = 0; i < m68k_num_memory; i++) {
348 m68k_memory[i].size &= MASK_256K;
349 if (m68k_memory[i].addr < startmem)
350 startmem = m68k_memory[i].addr;
351 if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
352 endmem = m68k_memory[i].addr+m68k_memory[i].size;
353 high_memory += m68k_memory[i].size;
354 }
355
356 availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
357 startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);
358
359 for (i = 0; i < m68k_num_memory; i++)
360 free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);
361
362 reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
363
364#ifdef CONFIG_BLK_DEV_INITRD
365 if (m68k_ramdisk.size) {
366 reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
367 initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
368 initrd_end = initrd_start + m68k_ramdisk.size;
369 printk ("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
370 }
371#endif
372
373#ifdef CONFIG_ATARI
374 if (MACH_IS_ATARI)
375 atari_stram_reserve_pages((void *)availmem);
376#endif
377#ifdef CONFIG_SUN3X
378 if (MACH_IS_SUN3X) {
379 dvma_init();
380 }
381#endif
382
383#endif /* !CONFIG_SUN3 */
384
385 paging_init();
386
387/* set ISA defs early as possible */
388#if defined(CONFIG_ISA) && defined(MULTI_ISA)
389#if defined(CONFIG_Q40)
390 if (MACH_IS_Q40) {
391 isa_type = Q40_ISA;
392 isa_sex = 0;
393 }
394#elif defined(CONFIG_GG2)
395 if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){
396 isa_type = GG2_ISA;
397 isa_sex = 0;
398 }
399#elif defined(CONFIG_AMIGA_PCMCIA)
400 if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){
401 isa_type = AG_ISA;
402 isa_sex = 1;
403 }
404#endif
405#endif
406}
407
408static int show_cpuinfo(struct seq_file *m, void *v)
409{
410 const char *cpu, *mmu, *fpu;
411 unsigned long clockfreq, clockfactor;
412
413#define LOOP_CYCLES_68020 (8)
414#define LOOP_CYCLES_68030 (8)
415#define LOOP_CYCLES_68040 (3)
416#define LOOP_CYCLES_68060 (1)
417
418 if (CPU_IS_020) {
419 cpu = "68020";
420 clockfactor = LOOP_CYCLES_68020;
421 } else if (CPU_IS_030) {
422 cpu = "68030";
423 clockfactor = LOOP_CYCLES_68030;
424 } else if (CPU_IS_040) {
425 cpu = "68040";
426 clockfactor = LOOP_CYCLES_68040;
427 } else if (CPU_IS_060) {
428 cpu = "68060";
429 clockfactor = LOOP_CYCLES_68060;
430 } else {
431 cpu = "680x0";
432 clockfactor = 0;
433 }
434
435#ifdef CONFIG_M68KFPU_EMU_ONLY
436 fpu="none(soft float)";
437#else
438 if (m68k_fputype & FPU_68881)
439 fpu = "68881";
440 else if (m68k_fputype & FPU_68882)
441 fpu = "68882";
442 else if (m68k_fputype & FPU_68040)
443 fpu = "68040";
444 else if (m68k_fputype & FPU_68060)
445 fpu = "68060";
446 else if (m68k_fputype & FPU_SUNFPA)
447 fpu = "Sun FPA";
448 else
449 fpu = "none";
450#endif
451
452 if (m68k_mmutype & MMU_68851)
453 mmu = "68851";
454 else if (m68k_mmutype & MMU_68030)
455 mmu = "68030";
456 else if (m68k_mmutype & MMU_68040)
457 mmu = "68040";
458 else if (m68k_mmutype & MMU_68060)
459 mmu = "68060";
460 else if (m68k_mmutype & MMU_SUN3)
461 mmu = "Sun-3";
462 else if (m68k_mmutype & MMU_APOLLO)
463 mmu = "Apollo";
464 else
465 mmu = "unknown";
466
467 clockfreq = loops_per_jiffy*HZ*clockfactor;
468
469 seq_printf(m, "CPU:\t\t%s\n"
470 "MMU:\t\t%s\n"
471 "FPU:\t\t%s\n"
472 "Clocking:\t%lu.%1luMHz\n"
473 "BogoMips:\t%lu.%02lu\n"
474 "Calibration:\t%lu loops\n",
475 cpu, mmu, fpu,
476 clockfreq/1000000,(clockfreq/100000)%10,
477 loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
478 loops_per_jiffy);
479 return 0;
480}
481
482static void *c_start(struct seq_file *m, loff_t *pos)
483{
484 return *pos < 1 ? (void *)1 : NULL;
485}
486static void *c_next(struct seq_file *m, void *v, loff_t *pos)
487{
488 ++*pos;
489 return NULL;
490}
491static void c_stop(struct seq_file *m, void *v)
492{
493}
494struct seq_operations cpuinfo_op = {
495 .start = c_start,
496 .next = c_next,
497 .stop = c_stop,
498 .show = show_cpuinfo,
499};
500
501int get_hardware_list(char *buffer)
502{
503 int len = 0;
504 char model[80];
505 unsigned long mem;
506 int i;
507
508 if (mach_get_model)
509 mach_get_model(model);
510 else
511 strcpy(model, "Unknown m68k");
512
513 len += sprintf(buffer+len, "Model:\t\t%s\n", model);
514 for (mem = 0, i = 0; i < m68k_num_memory; i++)
515 mem += m68k_memory[i].size;
516 len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
517
518 if (mach_get_hardware_list)
519 len += mach_get_hardware_list(buffer+len);
520
521 return(len);
522}
523
524
525#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
526void __init floppy_setup(char *str, int *ints)
527{
528 if (mach_floppy_setup)
529 mach_floppy_setup (str, ints);
530}
531
532#endif
533
534void check_bugs(void)
535{
536#ifndef CONFIG_M68KFPU_EMU
537 if (m68k_fputype == 0) {
538 printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
539 "WHICH IS REQUIRED BY LINUX/M68K ***\n" );
540 printk( KERN_EMERG "Upgrade your hardware or join the FPU "
541 "emulation project\n" );
542 panic( "no FPU" );
543 }
544#endif /* !CONFIG_M68KFPU_EMU */
545}
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
new file mode 100644
index 000000000000..9c636a4c238d
--- /dev/null
+++ b/arch/m68k/kernel/signal.c
@@ -0,0 +1,1025 @@
1/*
2 * linux/arch/m68k/kernel/signal.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11/*
12 * Linux/m68k support by Hamish Macdonald
13 *
14 * 68060 fixes by Jesper Skov
15 *
16 * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
17 *
18 * mathemu support by Roman Zippel
19 * (Note: fpstate in the signal context is completely ignored for the emulator
20 * and the internal floating point format is put on stack)
21 */
22
23/*
24 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
25 * Atari :-) Current limitation: Only one sigstack can be active at one time.
26 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
27 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
28 * signal handlers!
29 */
30
31#include <linux/sched.h>
32#include <linux/mm.h>
33#include <linux/kernel.h>
34#include <linux/signal.h>
35#include <linux/syscalls.h>
36#include <linux/errno.h>
37#include <linux/wait.h>
38#include <linux/ptrace.h>
39#include <linux/unistd.h>
40#include <linux/stddef.h>
41#include <linux/highuid.h>
42#include <linux/personality.h>
43#include <linux/tty.h>
44#include <linux/binfmts.h>
45
46#include <asm/setup.h>
47#include <asm/uaccess.h>
48#include <asm/pgtable.h>
49#include <asm/traps.h>
50#include <asm/ucontext.h>
51
52#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
53
54asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
55
56const int frame_extra_sizes[16] = {
57 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
58 [2] = sizeof(((struct frame *)0)->un.fmt2),
59 [3] = sizeof(((struct frame *)0)->un.fmt3),
60 [4] = sizeof(((struct frame *)0)->un.fmt4),
61 [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */
62 [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */
63 [7] = sizeof(((struct frame *)0)->un.fmt7),
64 [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */
65 [9] = sizeof(((struct frame *)0)->un.fmt9),
66 [10] = sizeof(((struct frame *)0)->un.fmta),
67 [11] = sizeof(((struct frame *)0)->un.fmtb),
68 [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */
69 [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */
70 [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */
71 [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
72};
73
74/*
75 * Atomically swap in the new signal mask, and wait for a signal.
76 */
77asmlinkage int do_sigsuspend(struct pt_regs *regs)
78{
79 old_sigset_t mask = regs->d3;
80 sigset_t saveset;
81
82 mask &= _BLOCKABLE;
83 saveset = current->blocked;
84 siginitset(&current->blocked, mask);
85 recalc_sigpending();
86
87 regs->d0 = -EINTR;
88 while (1) {
89 current->state = TASK_INTERRUPTIBLE;
90 schedule();
91 if (do_signal(&saveset, regs))
92 return -EINTR;
93 }
94}
95
96asmlinkage int
97do_rt_sigsuspend(struct pt_regs *regs)
98{
99 sigset_t *unewset = (sigset_t *)regs->d1;
100 size_t sigsetsize = (size_t)regs->d2;
101 sigset_t saveset, newset;
102
103 /* XXX: Don't preclude handling different sized sigset_t's. */
104 if (sigsetsize != sizeof(sigset_t))
105 return -EINVAL;
106
107 if (copy_from_user(&newset, unewset, sizeof(newset)))
108 return -EFAULT;
109 sigdelsetmask(&newset, ~_BLOCKABLE);
110
111 saveset = current->blocked;
112 current->blocked = newset;
113 recalc_sigpending();
114
115 regs->d0 = -EINTR;
116 while (1) {
117 current->state = TASK_INTERRUPTIBLE;
118 schedule();
119 if (do_signal(&saveset, regs))
120 return -EINTR;
121 }
122}
123
124asmlinkage int
125sys_sigaction(int sig, const struct old_sigaction *act,
126 struct old_sigaction *oact)
127{
128 struct k_sigaction new_ka, old_ka;
129 int ret;
130
131 if (act) {
132 old_sigset_t mask;
133 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
134 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
135 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
136 return -EFAULT;
137 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
138 __get_user(mask, &act->sa_mask);
139 siginitset(&new_ka.sa.sa_mask, mask);
140 }
141
142 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
143
144 if (!ret && oact) {
145 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
146 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
147 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
148 return -EFAULT;
149 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
150 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
151 }
152
153 return ret;
154}
155
156asmlinkage int
157sys_sigaltstack(const stack_t *uss, stack_t *uoss)
158{
159 return do_sigaltstack(uss, uoss, rdusp());
160}
161
162
163/*
164 * Do a signal return; undo the signal stack.
165 *
166 * Keep the return code on the stack quadword aligned!
167 * That makes the cache flush below easier.
168 */
169
170struct sigframe
171{
172 char *pretcode;
173 int sig;
174 int code;
175 struct sigcontext *psc;
176 char retcode[8];
177 unsigned long extramask[_NSIG_WORDS-1];
178 struct sigcontext sc;
179};
180
181struct rt_sigframe
182{
183 char *pretcode;
184 int sig;
185 struct siginfo *pinfo;
186 void *puc;
187 char retcode[8];
188 struct siginfo info;
189 struct ucontext uc;
190};
191
192
193static unsigned char fpu_version; /* version number of fpu, set by setup_frame */
194
195static inline int restore_fpu_state(struct sigcontext *sc)
196{
197 int err = 1;
198
199 if (FPU_IS_EMU) {
200 /* restore registers */
201 memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
202 memcpy(current->thread.fp, sc->sc_fpregs, 24);
203 return 0;
204 }
205
206 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
207 /* Verify the frame format. */
208 if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
209 goto out;
210 if (CPU_IS_020_OR_030) {
211 if (m68k_fputype & FPU_68881 &&
212 !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
213 goto out;
214 if (m68k_fputype & FPU_68882 &&
215 !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
216 goto out;
217 } else if (CPU_IS_040) {
218 if (!(sc->sc_fpstate[1] == 0x00 ||
219 sc->sc_fpstate[1] == 0x28 ||
220 sc->sc_fpstate[1] == 0x60))
221 goto out;
222 } else if (CPU_IS_060) {
223 if (!(sc->sc_fpstate[3] == 0x00 ||
224 sc->sc_fpstate[3] == 0x60 ||
225 sc->sc_fpstate[3] == 0xe0))
226 goto out;
227 } else
228 goto out;
229
230 __asm__ volatile (".chip 68k/68881\n\t"
231 "fmovemx %0,%%fp0-%%fp1\n\t"
232 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
233 ".chip 68k"
234 : /* no outputs */
235 : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
236 }
237 __asm__ volatile (".chip 68k/68881\n\t"
238 "frestore %0\n\t"
239 ".chip 68k" : : "m" (*sc->sc_fpstate));
240 err = 0;
241
242out:
243 return err;
244}
245
246#define FPCONTEXT_SIZE 216
247#define uc_fpstate uc_filler[0]
248#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
249#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
250
251static inline int rt_restore_fpu_state(struct ucontext *uc)
252{
253 unsigned char fpstate[FPCONTEXT_SIZE];
254 int context_size = CPU_IS_060 ? 8 : 0;
255 fpregset_t fpregs;
256 int err = 1;
257
258 if (FPU_IS_EMU) {
259 /* restore fpu control register */
260 if (__copy_from_user(current->thread.fpcntl,
261 uc->uc_mcontext.fpregs.f_fpcntl, 12))
262 goto out;
263 /* restore all other fpu register */
264 if (__copy_from_user(current->thread.fp,
265 uc->uc_mcontext.fpregs.f_fpregs, 96))
266 goto out;
267 return 0;
268 }
269
270 if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
271 goto out;
272 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
273 if (!CPU_IS_060)
274 context_size = fpstate[1];
275 /* Verify the frame format. */
276 if (!CPU_IS_060 && (fpstate[0] != fpu_version))
277 goto out;
278 if (CPU_IS_020_OR_030) {
279 if (m68k_fputype & FPU_68881 &&
280 !(context_size == 0x18 || context_size == 0xb4))
281 goto out;
282 if (m68k_fputype & FPU_68882 &&
283 !(context_size == 0x38 || context_size == 0xd4))
284 goto out;
285 } else if (CPU_IS_040) {
286 if (!(context_size == 0x00 ||
287 context_size == 0x28 ||
288 context_size == 0x60))
289 goto out;
290 } else if (CPU_IS_060) {
291 if (!(fpstate[3] == 0x00 ||
292 fpstate[3] == 0x60 ||
293 fpstate[3] == 0xe0))
294 goto out;
295 } else
296 goto out;
297 if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
298 sizeof(fpregs)))
299 goto out;
300 __asm__ volatile (".chip 68k/68881\n\t"
301 "fmovemx %0,%%fp0-%%fp7\n\t"
302 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
303 ".chip 68k"
304 : /* no outputs */
305 : "m" (*fpregs.f_fpregs),
306 "m" (*fpregs.f_fpcntl));
307 }
308 if (context_size &&
309 __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
310 context_size))
311 goto out;
312 __asm__ volatile (".chip 68k/68881\n\t"
313 "frestore %0\n\t"
314 ".chip 68k" : : "m" (*fpstate));
315 err = 0;
316
317out:
318 return err;
319}
320
321static inline int
322restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
323 int *pd0)
324{
325 int fsize, formatvec;
326 struct sigcontext context;
327 int err;
328
329 /* get previous context */
330 if (copy_from_user(&context, usc, sizeof(context)))
331 goto badframe;
332
333 /* restore passed registers */
334 regs->d1 = context.sc_d1;
335 regs->a0 = context.sc_a0;
336 regs->a1 = context.sc_a1;
337 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
338 regs->pc = context.sc_pc;
339 regs->orig_d0 = -1; /* disable syscall checks */
340 wrusp(context.sc_usp);
341 formatvec = context.sc_formatvec;
342 regs->format = formatvec >> 12;
343 regs->vector = formatvec & 0xfff;
344
345 err = restore_fpu_state(&context);
346
347 fsize = frame_extra_sizes[regs->format];
348 if (fsize < 0) {
349 /*
350 * user process trying to return with weird frame format
351 */
352#ifdef DEBUG
353 printk("user process returning with weird frame format\n");
354#endif
355 goto badframe;
356 }
357
358 /* OK. Make room on the supervisor stack for the extra junk,
359 * if necessary.
360 */
361
362 if (fsize) {
363 struct switch_stack *sw = (struct switch_stack *)regs - 1;
364 regs->d0 = context.sc_d0;
365#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
366 __asm__ __volatile__
367 (" movel %0,%/a0\n\t"
368 " subl %1,%/a0\n\t" /* make room on stack */
369 " movel %/a0,%/sp\n\t" /* set stack pointer */
370 /* move switch_stack and pt_regs */
371 "1: movel %0@+,%/a0@+\n\t"
372 " dbra %2,1b\n\t"
373 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
374 " lsrl #2,%1\n\t"
375 " subql #1,%1\n\t"
376 "2: movesl %4@+,%2\n\t"
377 "3: movel %2,%/a0@+\n\t"
378 " dbra %1,2b\n\t"
379 " bral ret_from_signal\n"
380 "4:\n"
381 ".section __ex_table,\"a\"\n"
382 " .align 4\n"
383 " .long 2b,4b\n"
384 " .long 3b,4b\n"
385 ".previous"
386 : /* no outputs, it doesn't ever return */
387 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
388 "n" (frame_offset), "a" (fp)
389 : "a0");
390#undef frame_offset
391 /*
392 * If we ever get here an exception occurred while
393 * building the above stack-frame.
394 */
395 goto badframe;
396 }
397
398 *pd0 = context.sc_d0;
399 return err;
400
401badframe:
402 return 1;
403}
404
405static inline int
406rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
407 struct ucontext *uc, int *pd0)
408{
409 int fsize, temp;
410 greg_t *gregs = uc->uc_mcontext.gregs;
411 unsigned long usp;
412 int err;
413
414 err = __get_user(temp, &uc->uc_mcontext.version);
415 if (temp != MCONTEXT_VERSION)
416 goto badframe;
417 /* restore passed registers */
418 err |= __get_user(regs->d0, &gregs[0]);
419 err |= __get_user(regs->d1, &gregs[1]);
420 err |= __get_user(regs->d2, &gregs[2]);
421 err |= __get_user(regs->d3, &gregs[3]);
422 err |= __get_user(regs->d4, &gregs[4]);
423 err |= __get_user(regs->d5, &gregs[5]);
424 err |= __get_user(sw->d6, &gregs[6]);
425 err |= __get_user(sw->d7, &gregs[7]);
426 err |= __get_user(regs->a0, &gregs[8]);
427 err |= __get_user(regs->a1, &gregs[9]);
428 err |= __get_user(regs->a2, &gregs[10]);
429 err |= __get_user(sw->a3, &gregs[11]);
430 err |= __get_user(sw->a4, &gregs[12]);
431 err |= __get_user(sw->a5, &gregs[13]);
432 err |= __get_user(sw->a6, &gregs[14]);
433 err |= __get_user(usp, &gregs[15]);
434 wrusp(usp);
435 err |= __get_user(regs->pc, &gregs[16]);
436 err |= __get_user(temp, &gregs[17]);
437 regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
438 regs->orig_d0 = -1; /* disable syscall checks */
439 err |= __get_user(temp, &uc->uc_formatvec);
440 regs->format = temp >> 12;
441 regs->vector = temp & 0xfff;
442
443 err |= rt_restore_fpu_state(uc);
444
445 if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
446 goto badframe;
447
448 fsize = frame_extra_sizes[regs->format];
449 if (fsize < 0) {
450 /*
451 * user process trying to return with weird frame format
452 */
453#ifdef DEBUG
454 printk("user process returning with weird frame format\n");
455#endif
456 goto badframe;
457 }
458
459 /* OK. Make room on the supervisor stack for the extra junk,
460 * if necessary.
461 */
462
463 if (fsize) {
464#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
465 __asm__ __volatile__
466 (" movel %0,%/a0\n\t"
467 " subl %1,%/a0\n\t" /* make room on stack */
468 " movel %/a0,%/sp\n\t" /* set stack pointer */
469 /* move switch_stack and pt_regs */
470 "1: movel %0@+,%/a0@+\n\t"
471 " dbra %2,1b\n\t"
472 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
473 " lsrl #2,%1\n\t"
474 " subql #1,%1\n\t"
475 "2: movesl %4@+,%2\n\t"
476 "3: movel %2,%/a0@+\n\t"
477 " dbra %1,2b\n\t"
478 " bral ret_from_signal\n"
479 "4:\n"
480 ".section __ex_table,\"a\"\n"
481 " .align 4\n"
482 " .long 2b,4b\n"
483 " .long 3b,4b\n"
484 ".previous"
485 : /* no outputs, it doesn't ever return */
486 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
487 "n" (frame_offset), "a" (&uc->uc_extra)
488 : "a0");
489#undef frame_offset
490 /*
491 * If we ever get here an exception occurred while
492 * building the above stack-frame.
493 */
494 goto badframe;
495 }
496
497 *pd0 = regs->d0;
498 return err;
499
500badframe:
501 return 1;
502}
503
504asmlinkage int do_sigreturn(unsigned long __unused)
505{
506 struct switch_stack *sw = (struct switch_stack *) &__unused;
507 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
508 unsigned long usp = rdusp();
509 struct sigframe *frame = (struct sigframe *)(usp - 4);
510 sigset_t set;
511 int d0;
512
513 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
514 goto badframe;
515 if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
516 (_NSIG_WORDS > 1 &&
517 __copy_from_user(&set.sig[1], &frame->extramask,
518 sizeof(frame->extramask))))
519 goto badframe;
520
521 sigdelsetmask(&set, ~_BLOCKABLE);
522 current->blocked = set;
523 recalc_sigpending();
524
525 if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
526 goto badframe;
527 return d0;
528
529badframe:
530 force_sig(SIGSEGV, current);
531 return 0;
532}
533
534asmlinkage int do_rt_sigreturn(unsigned long __unused)
535{
536 struct switch_stack *sw = (struct switch_stack *) &__unused;
537 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
538 unsigned long usp = rdusp();
539 struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
540 sigset_t set;
541 int d0;
542
543 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
544 goto badframe;
545 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
546 goto badframe;
547
548 sigdelsetmask(&set, ~_BLOCKABLE);
549 current->blocked = set;
550 recalc_sigpending();
551
552 if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
553 goto badframe;
554 return d0;
555
556badframe:
557 force_sig(SIGSEGV, current);
558 return 0;
559}
560
561/*
562 * Set up a signal frame.
563 */
564
565static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
566{
567 if (FPU_IS_EMU) {
568 /* save registers */
569 memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
570 memcpy(sc->sc_fpregs, current->thread.fp, 24);
571 return;
572 }
573
574 __asm__ volatile (".chip 68k/68881\n\t"
575 "fsave %0\n\t"
576 ".chip 68k"
577 : : "m" (*sc->sc_fpstate) : "memory");
578
579 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
580 fpu_version = sc->sc_fpstate[0];
581 if (CPU_IS_020_OR_030 &&
582 regs->vector >= (VEC_FPBRUC * 4) &&
583 regs->vector <= (VEC_FPNAN * 4)) {
584 /* Clear pending exception in 68882 idle frame */
585 if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
586 sc->sc_fpstate[0x38] |= 1 << 3;
587 }
588 __asm__ volatile (".chip 68k/68881\n\t"
589 "fmovemx %%fp0-%%fp1,%0\n\t"
590 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
591 ".chip 68k"
592 : "=m" (*sc->sc_fpregs),
593 "=m" (*sc->sc_fpcntl)
594 : /* no inputs */
595 : "memory");
596 }
597}
598
599static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
600{
601 unsigned char fpstate[FPCONTEXT_SIZE];
602 int context_size = CPU_IS_060 ? 8 : 0;
603 int err = 0;
604
605 if (FPU_IS_EMU) {
606 /* save fpu control register */
607 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
608 current->thread.fpcntl, 12);
609 /* save all other fpu register */
610 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
611 current->thread.fp, 96);
612 return err;
613 }
614
615 __asm__ volatile (".chip 68k/68881\n\t"
616 "fsave %0\n\t"
617 ".chip 68k"
618 : : "m" (*fpstate) : "memory");
619
620 err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
621 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
622 fpregset_t fpregs;
623 if (!CPU_IS_060)
624 context_size = fpstate[1];
625 fpu_version = fpstate[0];
626 if (CPU_IS_020_OR_030 &&
627 regs->vector >= (VEC_FPBRUC * 4) &&
628 regs->vector <= (VEC_FPNAN * 4)) {
629 /* Clear pending exception in 68882 idle frame */
630 if (*(unsigned short *) fpstate == 0x1f38)
631 fpstate[0x38] |= 1 << 3;
632 }
633 __asm__ volatile (".chip 68k/68881\n\t"
634 "fmovemx %%fp0-%%fp7,%0\n\t"
635 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
636 ".chip 68k"
637 : "=m" (*fpregs.f_fpregs),
638 "=m" (*fpregs.f_fpcntl)
639 : /* no inputs */
640 : "memory");
641 err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
642 sizeof(fpregs));
643 }
644 if (context_size)
645 err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
646 context_size);
647 return err;
648}
649
650static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
651 unsigned long mask)
652{
653 sc->sc_mask = mask;
654 sc->sc_usp = rdusp();
655 sc->sc_d0 = regs->d0;
656 sc->sc_d1 = regs->d1;
657 sc->sc_a0 = regs->a0;
658 sc->sc_a1 = regs->a1;
659 sc->sc_sr = regs->sr;
660 sc->sc_pc = regs->pc;
661 sc->sc_formatvec = regs->format << 12 | regs->vector;
662 save_fpu_state(sc, regs);
663}
664
665static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
666{
667 struct switch_stack *sw = (struct switch_stack *)regs - 1;
668 greg_t *gregs = uc->uc_mcontext.gregs;
669 int err = 0;
670
671 err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
672 err |= __put_user(regs->d0, &gregs[0]);
673 err |= __put_user(regs->d1, &gregs[1]);
674 err |= __put_user(regs->d2, &gregs[2]);
675 err |= __put_user(regs->d3, &gregs[3]);
676 err |= __put_user(regs->d4, &gregs[4]);
677 err |= __put_user(regs->d5, &gregs[5]);
678 err |= __put_user(sw->d6, &gregs[6]);
679 err |= __put_user(sw->d7, &gregs[7]);
680 err |= __put_user(regs->a0, &gregs[8]);
681 err |= __put_user(regs->a1, &gregs[9]);
682 err |= __put_user(regs->a2, &gregs[10]);
683 err |= __put_user(sw->a3, &gregs[11]);
684 err |= __put_user(sw->a4, &gregs[12]);
685 err |= __put_user(sw->a5, &gregs[13]);
686 err |= __put_user(sw->a6, &gregs[14]);
687 err |= __put_user(rdusp(), &gregs[15]);
688 err |= __put_user(regs->pc, &gregs[16]);
689 err |= __put_user(regs->sr, &gregs[17]);
690 err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
691 err |= rt_save_fpu_state(uc, regs);
692 return err;
693}
694
695static inline void push_cache (unsigned long vaddr)
696{
697 /*
698 * Using the old cache_push_v() was really a big waste.
699 *
700 * What we are trying to do is to flush 8 bytes to ram.
701 * Flushing 2 cache lines of 16 bytes is much cheaper than
702 * flushing 1 or 2 pages, as previously done in
703 * cache_push_v().
704 * Jes
705 */
706 if (CPU_IS_040) {
707 unsigned long temp;
708
709 __asm__ __volatile__ (".chip 68040\n\t"
710 "nop\n\t"
711 "ptestr (%1)\n\t"
712 "movec %%mmusr,%0\n\t"
713 ".chip 68k"
714 : "=r" (temp)
715 : "a" (vaddr));
716
717 temp &= PAGE_MASK;
718 temp |= vaddr & ~PAGE_MASK;
719
720 __asm__ __volatile__ (".chip 68040\n\t"
721 "nop\n\t"
722 "cpushl %%bc,(%0)\n\t"
723 ".chip 68k"
724 : : "a" (temp));
725 }
726 else if (CPU_IS_060) {
727 unsigned long temp;
728 __asm__ __volatile__ (".chip 68060\n\t"
729 "plpar (%0)\n\t"
730 ".chip 68k"
731 : "=a" (temp)
732 : "0" (vaddr));
733 __asm__ __volatile__ (".chip 68060\n\t"
734 "cpushl %%bc,(%0)\n\t"
735 ".chip 68k"
736 : : "a" (temp));
737 }
738 else {
739 /*
740 * 68030/68020 have no writeback cache;
741 * still need to clear icache.
742 * Note that vaddr is guaranteed to be long word aligned.
743 */
744 unsigned long temp;
745 asm volatile ("movec %%cacr,%0" : "=r" (temp));
746 temp += 4;
747 asm volatile ("movec %0,%%caar\n\t"
748 "movec %1,%%cacr"
749 : : "r" (vaddr), "r" (temp));
750 asm volatile ("movec %0,%%caar\n\t"
751 "movec %1,%%cacr"
752 : : "r" (vaddr + 4), "r" (temp));
753 }
754}
755
756static inline void *
757get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
758{
759 unsigned long usp;
760
761 /* Default to using normal stack. */
762 usp = rdusp();
763
764 /* This is the X/Open sanctioned signal stack switching. */
765 if (ka->sa.sa_flags & SA_ONSTACK) {
766 if (!on_sig_stack(usp))
767 usp = current->sas_ss_sp + current->sas_ss_size;
768 }
769 return (void *)((usp - frame_size) & -8UL);
770}
771
772static void setup_frame (int sig, struct k_sigaction *ka,
773 sigset_t *set, struct pt_regs *regs)
774{
775 struct sigframe *frame;
776 int fsize = frame_extra_sizes[regs->format];
777 struct sigcontext context;
778 int err = 0;
779
780 if (fsize < 0) {
781#ifdef DEBUG
782 printk ("setup_frame: Unknown frame format %#x\n",
783 regs->format);
784#endif
785 goto give_sigsegv;
786 }
787
788 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
789
790 if (fsize) {
791 err |= copy_to_user (frame + 1, regs + 1, fsize);
792 regs->stkadj = fsize;
793 }
794
795 err |= __put_user((current_thread_info()->exec_domain
796 && current_thread_info()->exec_domain->signal_invmap
797 && sig < 32
798 ? current_thread_info()->exec_domain->signal_invmap[sig]
799 : sig),
800 &frame->sig);
801
802 err |= __put_user(regs->vector, &frame->code);
803 err |= __put_user(&frame->sc, &frame->psc);
804
805 if (_NSIG_WORDS > 1)
806 err |= copy_to_user(frame->extramask, &set->sig[1],
807 sizeof(frame->extramask));
808
809 setup_sigcontext(&context, regs, set->sig[0]);
810 err |= copy_to_user (&frame->sc, &context, sizeof(context));
811
812 /* Set up to return from userspace. */
813 err |= __put_user(frame->retcode, &frame->pretcode);
814 /* moveq #,d0; trap #0 */
815 err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
816 (long *)(frame->retcode));
817
818 if (err)
819 goto give_sigsegv;
820
821 push_cache ((unsigned long) &frame->retcode);
822
823 /* Set up registers for signal handler */
824 wrusp ((unsigned long) frame);
825 regs->pc = (unsigned long) ka->sa.sa_handler;
826
827adjust_stack:
828 /* Prepare to skip over the extra stuff in the exception frame. */
829 if (regs->stkadj) {
830 struct pt_regs *tregs =
831 (struct pt_regs *)((ulong)regs + regs->stkadj);
832#ifdef DEBUG
833 printk("Performing stackadjust=%04x\n", regs->stkadj);
834#endif
835 /* This must be copied with decreasing addresses to
836 handle overlaps. */
837 tregs->vector = 0;
838 tregs->format = 0;
839 tregs->pc = regs->pc;
840 tregs->sr = regs->sr;
841 }
842 return;
843
844give_sigsegv:
845 force_sigsegv(sig, current);
846 goto adjust_stack;
847}
848
849static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
850 sigset_t *set, struct pt_regs *regs)
851{
852 struct rt_sigframe *frame;
853 int fsize = frame_extra_sizes[regs->format];
854 int err = 0;
855
856 if (fsize < 0) {
857#ifdef DEBUG
858 printk ("setup_frame: Unknown frame format %#x\n",
859 regs->format);
860#endif
861 goto give_sigsegv;
862 }
863
864 frame = get_sigframe(ka, regs, sizeof(*frame));
865
866 if (fsize) {
867 err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
868 regs->stkadj = fsize;
869 }
870
871 err |= __put_user((current_thread_info()->exec_domain
872 && current_thread_info()->exec_domain->signal_invmap
873 && sig < 32
874 ? current_thread_info()->exec_domain->signal_invmap[sig]
875 : sig),
876 &frame->sig);
877 err |= __put_user(&frame->info, &frame->pinfo);
878 err |= __put_user(&frame->uc, &frame->puc);
879 err |= copy_siginfo_to_user(&frame->info, info);
880
881 /* Create the ucontext. */
882 err |= __put_user(0, &frame->uc.uc_flags);
883 err |= __put_user(0, &frame->uc.uc_link);
884 err |= __put_user((void *)current->sas_ss_sp,
885 &frame->uc.uc_stack.ss_sp);
886 err |= __put_user(sas_ss_flags(rdusp()),
887 &frame->uc.uc_stack.ss_flags);
888 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
889 err |= rt_setup_ucontext(&frame->uc, regs);
890 err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
891
892 /* Set up to return from userspace. */
893 err |= __put_user(frame->retcode, &frame->pretcode);
894 /* moveq #,d0; notb d0; trap #0 */
895 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
896 (long *)(frame->retcode + 0));
897 err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
898
899 if (err)
900 goto give_sigsegv;
901
902 push_cache ((unsigned long) &frame->retcode);
903
904 /* Set up registers for signal handler */
905 wrusp ((unsigned long) frame);
906 regs->pc = (unsigned long) ka->sa.sa_handler;
907
908adjust_stack:
909 /* Prepare to skip over the extra stuff in the exception frame. */
910 if (regs->stkadj) {
911 struct pt_regs *tregs =
912 (struct pt_regs *)((ulong)regs + regs->stkadj);
913#ifdef DEBUG
914 printk("Performing stackadjust=%04x\n", regs->stkadj);
915#endif
916 /* This must be copied with decreasing addresses to
917 handle overlaps. */
918 tregs->vector = 0;
919 tregs->format = 0;
920 tregs->pc = regs->pc;
921 tregs->sr = regs->sr;
922 }
923 return;
924
925give_sigsegv:
926 force_sigsegv(sig, current);
927 goto adjust_stack;
928}
929
930static inline void
931handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
932{
933 switch (regs->d0) {
934 case -ERESTARTNOHAND:
935 if (!has_handler)
936 goto do_restart;
937 regs->d0 = -EINTR;
938 break;
939
940 case -ERESTARTSYS:
941 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
942 regs->d0 = -EINTR;
943 break;
944 }
945 /* fallthrough */
946 case -ERESTARTNOINTR:
947 do_restart:
948 regs->d0 = regs->orig_d0;
949 regs->pc -= 2;
950 break;
951 }
952}
953
954void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
955{
956 if (regs->orig_d0 < 0)
957 return;
958 switch (regs->d0) {
959 case -ERESTARTNOHAND:
960 case -ERESTARTSYS:
961 case -ERESTARTNOINTR:
962 regs->d0 = regs->orig_d0;
963 regs->orig_d0 = -1;
964 regs->pc -= 2;
965 break;
966 }
967}
968
969/*
970 * OK, we're invoking a handler
971 */
972static void
973handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
974 sigset_t *oldset, struct pt_regs *regs)
975{
976 /* are we from a system call? */
977 if (regs->orig_d0 >= 0)
978 /* If so, check system call restarting.. */
979 handle_restart(regs, ka, 1);
980
981 /* set up the stack frame */
982 if (ka->sa.sa_flags & SA_SIGINFO)
983 setup_rt_frame(sig, ka, info, oldset, regs);
984 else
985 setup_frame(sig, ka, oldset, regs);
986
987 if (ka->sa.sa_flags & SA_ONESHOT)
988 ka->sa.sa_handler = SIG_DFL;
989
990 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
991 if (!(ka->sa.sa_flags & SA_NODEFER))
992 sigaddset(&current->blocked,sig);
993 recalc_sigpending();
994}
995
996/*
997 * Note that 'init' is a special process: it doesn't get signals it doesn't
998 * want to handle. Thus you cannot kill init even with a SIGKILL even by
999 * mistake.
1000 */
1001asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
1002{
1003 siginfo_t info;
1004 struct k_sigaction ka;
1005 int signr;
1006
1007 current->thread.esp0 = (unsigned long) regs;
1008
1009 if (!oldset)
1010 oldset = &current->blocked;
1011
1012 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
1013 if (signr > 0) {
1014 /* Whee! Actually deliver the signal. */
1015 handle_signal(signr, &ka, &info, oldset, regs);
1016 return 1;
1017 }
1018
1019 /* Did we come from a system call? */
1020 if (regs->orig_d0 >= 0)
1021 /* Restart the system call - no handlers present */
1022 handle_restart(regs, NULL, 0);
1023
1024 return 0;
1025}
diff --git a/arch/m68k/kernel/sun3-head.S b/arch/m68k/kernel/sun3-head.S
new file mode 100644
index 000000000000..bffd69a4a1ab
--- /dev/null
+++ b/arch/m68k/kernel/sun3-head.S
@@ -0,0 +1,104 @@
1#include <linux/linkage.h>
2
3#include <asm/entry.h>
4#include <asm/page.h>
5#include <asm/contregs.h>
6#include <asm/sun3-head.h>
7
8PSL_HIGHIPL = 0x2700
9NBSG = 0x20000
10ICACHE_ONLY = 0x00000009
11CACHES_OFF = 0x00000008 | actually a clear and disable --m
12#define MAS_STACK INT_STACK
13ROOT_TABLE_SIZE = 128
14PAGESIZE = 8192
15SUN3_INVALID_PMEG = 255
16.globl bootup_user_stack
17.globl bootup_kernel_stack
18.globl pg0
19.globl swapper_pg_dir
20.globl kernel_pmd_table
21.globl availmem
22.global m68k_pgtable_cachemode
23.global kpt
24| todo: all these should be in bss!
25swapper_pg_dir: .skip 0x2000
26pg0: .skip 0x2000
27kernel_pmd_table: .skip 0x2000
28
29.globl kernel_pg_dir
30.equ kernel_pg_dir,kernel_pmd_table
31
32 .section .head
33ENTRY(_stext)
34ENTRY(_start)
35
36/* Firstly, disable interrupts and set up function codes. */
37 movew #PSL_HIGHIPL, %sr
38 moveq #FC_CONTROL, %d0
39 movec %d0, %sfc
40 movec %d0, %dfc
41
42/* Make sure we're in context zero. */
43 moveq #0, %d0
44 movsb %d0, AC_CONTEXT
45
46/* map everything the bootloader left us into high memory, clean up the
47 excess later */
48 lea (AC_SEGMAP+0),%a0
49 lea (AC_SEGMAP+KERNBASE),%a1
501:
51 movsb %a0@, %d1
52 movsb %d1, %a1@
53 cmpib #SUN3_INVALID_PMEG, %d1
54 beq 2f
55 addl #NBSG,%a0
56 addl #NBSG,%a1
57 jmp 1b
58
592:
60
61/* Disable caches and jump to high code. */
62 moveq #ICACHE_ONLY,%d0 | Cache disabled until we're ready to enable it
63 movc %d0, %cacr | is this the right value? (yes --m)
64 jmp 1f:l
65
66/* Following code executes at high addresses (0xE000xxx). */
671: lea init_task,%curptr | get initial thread...
68 lea init_thread_union+THREAD_SIZE,%sp | ...and its stack.
69
70/* copy bootinfo records from the loader to _end */
71 lea _end, %a1
72 lea BI_START, %a0
73 /* number of longs to copy */
74 movel %a0@, %d0
751: addl #4, %a0
76 movel %a0@, %a1@
77 addl #4, %a1
78 dbf %d0, 1b
79
80/* Point MSP at an invalid page to trap if it's used. --m */
81 movl #(PAGESIZE),%d0
82 movc %d0,%msp
83 moveq #-1,%d0
84 movsb %d0,(AC_SEGMAP+0x0)
85
86 jbsr sun3_init
87
88 jbsr base_trap_init
89
90 jbsr start_kernel
91 trap #15
92
93 .data
94 .even
95kpt:
96 .long 0
97availmem:
98 .long 0
99| todo: remove next two. --m
100is_medusa:
101 .long 0
102m68k_pgtable_cachemode:
103 .long 0
104
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
new file mode 100644
index 000000000000..2ed7b783f654
--- /dev/null
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -0,0 +1,671 @@
1/*
2 * linux/arch/m68k/kernel/sys_m68k.c
3 *
4 * This file contains various random system calls that
5 * have a non-standard calling sequence on the Linux/m68k
6 * platform.
7 */
8
9#include <linux/errno.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/sem.h>
15#include <linux/msg.h>
16#include <linux/shm.h>
17#include <linux/stat.h>
18#include <linux/syscalls.h>
19#include <linux/mman.h>
20#include <linux/file.h>
21#include <linux/utsname.h>
22
23#include <asm/setup.h>
24#include <asm/uaccess.h>
25#include <asm/cachectl.h>
26#include <asm/traps.h>
27#include <asm/ipc.h>
28#include <asm/page.h>
29
30/*
31 * sys_pipe() is the normal C calling standard for creating
32 * a pipe. It's not the way unix traditionally does this, though.
33 */
34asmlinkage int sys_pipe(unsigned long * fildes)
35{
36 int fd[2];
37 int error;
38
39 error = do_pipe(fd);
40 if (!error) {
41 if (copy_to_user(fildes, fd, 2*sizeof(int)))
42 error = -EFAULT;
43 }
44 return error;
45}
46
47/* common code for old and new mmaps */
48static inline long do_mmap2(
49 unsigned long addr, unsigned long len,
50 unsigned long prot, unsigned long flags,
51 unsigned long fd, unsigned long pgoff)
52{
53 int error = -EBADF;
54 struct file * file = NULL;
55
56 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
57 if (!(flags & MAP_ANONYMOUS)) {
58 file = fget(fd);
59 if (!file)
60 goto out;
61 }
62
63 down_write(&current->mm->mmap_sem);
64 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
65 up_write(&current->mm->mmap_sem);
66
67 if (file)
68 fput(file);
69out:
70 return error;
71}
72
73asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
74 unsigned long prot, unsigned long flags,
75 unsigned long fd, unsigned long pgoff)
76{
77 return do_mmap2(addr, len, prot, flags, fd, pgoff);
78}
79
80/*
81 * Perform the select(nd, in, out, ex, tv) and mmap() system
82 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
83 * handle more than 4 system call parameters, so these system calls
84 * used a memory block for parameter passing..
85 */
86
87struct mmap_arg_struct {
88 unsigned long addr;
89 unsigned long len;
90 unsigned long prot;
91 unsigned long flags;
92 unsigned long fd;
93 unsigned long offset;
94};
95
96asmlinkage int old_mmap(struct mmap_arg_struct *arg)
97{
98 struct mmap_arg_struct a;
99 int error = -EFAULT;
100
101 if (copy_from_user(&a, arg, sizeof(a)))
102 goto out;
103
104 error = -EINVAL;
105 if (a.offset & ~PAGE_MASK)
106 goto out;
107
108 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
109
110 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
111out:
112 return error;
113}
114
115#if 0
116struct mmap_arg_struct64 {
117 __u32 addr;
118 __u32 len;
119 __u32 prot;
120 __u32 flags;
121 __u64 offset; /* 64 bits */
122 __u32 fd;
123};
124
125asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
126{
127 int error = -EFAULT;
128 struct file * file = NULL;
129 struct mmap_arg_struct64 a;
130 unsigned long pgoff;
131
132 if (copy_from_user(&a, arg, sizeof(a)))
133 return -EFAULT;
134
135 if ((long)a.offset & ~PAGE_MASK)
136 return -EINVAL;
137
138 pgoff = a.offset >> PAGE_SHIFT;
139 if ((a.offset >> PAGE_SHIFT) != pgoff)
140 return -EINVAL;
141
142 if (!(a.flags & MAP_ANONYMOUS)) {
143 error = -EBADF;
144 file = fget(a.fd);
145 if (!file)
146 goto out;
147 }
148 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
149
150 down_write(&current->mm->mmap_sem);
151 error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
152 up_write(&current->mm->mmap_sem);
153 if (file)
154 fput(file);
155out:
156 return error;
157}
158#endif
159
160struct sel_arg_struct {
161 unsigned long n;
162 fd_set *inp, *outp, *exp;
163 struct timeval *tvp;
164};
165
166asmlinkage int old_select(struct sel_arg_struct *arg)
167{
168 struct sel_arg_struct a;
169
170 if (copy_from_user(&a, arg, sizeof(a)))
171 return -EFAULT;
172 /* sys_select() does the appropriate kernel locking */
173 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
174}
175
176/*
177 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
178 *
179 * This is really horribly ugly.
180 */
181asmlinkage int sys_ipc (uint call, int first, int second,
182 int third, void *ptr, long fifth)
183{
184 int version, ret;
185
186 version = call >> 16; /* hack for backward compatibility */
187 call &= 0xffff;
188
189 if (call <= SEMCTL)
190 switch (call) {
191 case SEMOP:
192 return sys_semop (first, (struct sembuf *)ptr, second);
193 case SEMGET:
194 return sys_semget (first, second, third);
195 case SEMCTL: {
196 union semun fourth;
197 if (!ptr)
198 return -EINVAL;
199 if (get_user(fourth.__pad, (void **) ptr))
200 return -EFAULT;
201 return sys_semctl (first, second, third, fourth);
202 }
203 default:
204 return -ENOSYS;
205 }
206 if (call <= MSGCTL)
207 switch (call) {
208 case MSGSND:
209 return sys_msgsnd (first, (struct msgbuf *) ptr,
210 second, third);
211 case MSGRCV:
212 switch (version) {
213 case 0: {
214 struct ipc_kludge tmp;
215 if (!ptr)
216 return -EINVAL;
217 if (copy_from_user (&tmp,
218 (struct ipc_kludge *)ptr,
219 sizeof (tmp)))
220 return -EFAULT;
221 return sys_msgrcv (first, tmp.msgp, second,
222 tmp.msgtyp, third);
223 }
224 default:
225 return sys_msgrcv (first,
226 (struct msgbuf *) ptr,
227 second, fifth, third);
228 }
229 case MSGGET:
230 return sys_msgget ((key_t) first, second);
231 case MSGCTL:
232 return sys_msgctl (first, second,
233 (struct msqid_ds *) ptr);
234 default:
235 return -ENOSYS;
236 }
237 if (call <= SHMCTL)
238 switch (call) {
239 case SHMAT:
240 switch (version) {
241 default: {
242 ulong raddr;
243 ret = do_shmat (first, (char *) ptr,
244 second, &raddr);
245 if (ret)
246 return ret;
247 return put_user (raddr, (ulong *) third);
248 }
249 }
250 case SHMDT:
251 return sys_shmdt ((char *)ptr);
252 case SHMGET:
253 return sys_shmget (first, second, third);
254 case SHMCTL:
255 return sys_shmctl (first, second,
256 (struct shmid_ds *) ptr);
257 default:
258 return -ENOSYS;
259 }
260
261 return -EINVAL;
262}
263
264/* Convert virtual (user) address VADDR to physical address PADDR */
265#define virt_to_phys_040(vaddr) \
266({ \
267 unsigned long _mmusr, _paddr; \
268 \
269 __asm__ __volatile__ (".chip 68040\n\t" \
270 "ptestr (%1)\n\t" \
271 "movec %%mmusr,%0\n\t" \
272 ".chip 68k" \
273 : "=r" (_mmusr) \
274 : "a" (vaddr)); \
275 _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \
276 _paddr; \
277})
278
279static inline int
280cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
281{
282 unsigned long paddr, i;
283
284 switch (scope)
285 {
286 case FLUSH_SCOPE_ALL:
287 switch (cache)
288 {
289 case FLUSH_CACHE_DATA:
290 /* This nop is needed for some broken versions of the 68040. */
291 __asm__ __volatile__ ("nop\n\t"
292 ".chip 68040\n\t"
293 "cpusha %dc\n\t"
294 ".chip 68k");
295 break;
296 case FLUSH_CACHE_INSN:
297 __asm__ __volatile__ ("nop\n\t"
298 ".chip 68040\n\t"
299 "cpusha %ic\n\t"
300 ".chip 68k");
301 break;
302 default:
303 case FLUSH_CACHE_BOTH:
304 __asm__ __volatile__ ("nop\n\t"
305 ".chip 68040\n\t"
306 "cpusha %bc\n\t"
307 ".chip 68k");
308 break;
309 }
310 break;
311
312 case FLUSH_SCOPE_LINE:
313 /* Find the physical address of the first mapped page in the
314 address range. */
315 if ((paddr = virt_to_phys_040(addr))) {
316 paddr += addr & ~(PAGE_MASK | 15);
317 len = (len + (addr & 15) + 15) >> 4;
318 } else {
319 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
320
321 if (len <= tmp)
322 return 0;
323 addr += tmp;
324 len -= tmp;
325 tmp = PAGE_SIZE;
326 for (;;)
327 {
328 if ((paddr = virt_to_phys_040(addr)))
329 break;
330 if (len <= tmp)
331 return 0;
332 addr += tmp;
333 len -= tmp;
334 }
335 len = (len + 15) >> 4;
336 }
337 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
338 while (len--)
339 {
340 switch (cache)
341 {
342 case FLUSH_CACHE_DATA:
343 __asm__ __volatile__ ("nop\n\t"
344 ".chip 68040\n\t"
345 "cpushl %%dc,(%0)\n\t"
346 ".chip 68k"
347 : : "a" (paddr));
348 break;
349 case FLUSH_CACHE_INSN:
350 __asm__ __volatile__ ("nop\n\t"
351 ".chip 68040\n\t"
352 "cpushl %%ic,(%0)\n\t"
353 ".chip 68k"
354 : : "a" (paddr));
355 break;
356 default:
357 case FLUSH_CACHE_BOTH:
358 __asm__ __volatile__ ("nop\n\t"
359 ".chip 68040\n\t"
360 "cpushl %%bc,(%0)\n\t"
361 ".chip 68k"
362 : : "a" (paddr));
363 break;
364 }
365 if (!--i && len)
366 {
367 /*
368 * No need to page align here since it is done by
369 * virt_to_phys_040().
370 */
371 addr += PAGE_SIZE;
372 i = PAGE_SIZE / 16;
373 /* Recompute physical address when crossing a page
374 boundary. */
375 for (;;)
376 {
377 if ((paddr = virt_to_phys_040(addr)))
378 break;
379 if (len <= i)
380 return 0;
381 len -= i;
382 addr += PAGE_SIZE;
383 }
384 }
385 else
386 paddr += 16;
387 }
388 break;
389
390 default:
391 case FLUSH_SCOPE_PAGE:
392 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
393 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
394 {
395 if (!(paddr = virt_to_phys_040(addr)))
396 continue;
397 switch (cache)
398 {
399 case FLUSH_CACHE_DATA:
400 __asm__ __volatile__ ("nop\n\t"
401 ".chip 68040\n\t"
402 "cpushp %%dc,(%0)\n\t"
403 ".chip 68k"
404 : : "a" (paddr));
405 break;
406 case FLUSH_CACHE_INSN:
407 __asm__ __volatile__ ("nop\n\t"
408 ".chip 68040\n\t"
409 "cpushp %%ic,(%0)\n\t"
410 ".chip 68k"
411 : : "a" (paddr));
412 break;
413 default:
414 case FLUSH_CACHE_BOTH:
415 __asm__ __volatile__ ("nop\n\t"
416 ".chip 68040\n\t"
417 "cpushp %%bc,(%0)\n\t"
418 ".chip 68k"
419 : : "a" (paddr));
420 break;
421 }
422 }
423 break;
424 }
425 return 0;
426}
427
428#define virt_to_phys_060(vaddr) \
429({ \
430 unsigned long paddr; \
431 __asm__ __volatile__ (".chip 68060\n\t" \
432 "plpar (%0)\n\t" \
433 ".chip 68k" \
434 : "=a" (paddr) \
435 : "0" (vaddr)); \
436 (paddr); /* XXX */ \
437})
438
439static inline int
440cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
441{
442 unsigned long paddr, i;
443
444 /*
445 * 68060 manual says:
446 * cpush %dc : flush DC, remains valid (with our %cacr setup)
447 * cpush %ic : invalidate IC
448 * cpush %bc : flush DC + invalidate IC
449 */
450 switch (scope)
451 {
452 case FLUSH_SCOPE_ALL:
453 switch (cache)
454 {
455 case FLUSH_CACHE_DATA:
456 __asm__ __volatile__ (".chip 68060\n\t"
457 "cpusha %dc\n\t"
458 ".chip 68k");
459 break;
460 case FLUSH_CACHE_INSN:
461 __asm__ __volatile__ (".chip 68060\n\t"
462 "cpusha %ic\n\t"
463 ".chip 68k");
464 break;
465 default:
466 case FLUSH_CACHE_BOTH:
467 __asm__ __volatile__ (".chip 68060\n\t"
468 "cpusha %bc\n\t"
469 ".chip 68k");
470 break;
471 }
472 break;
473
474 case FLUSH_SCOPE_LINE:
475 /* Find the physical address of the first mapped page in the
476 address range. */
477 len += addr & 15;
478 addr &= -16;
479 if (!(paddr = virt_to_phys_060(addr))) {
480 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
481
482 if (len <= tmp)
483 return 0;
484 addr += tmp;
485 len -= tmp;
486 tmp = PAGE_SIZE;
487 for (;;)
488 {
489 if ((paddr = virt_to_phys_060(addr)))
490 break;
491 if (len <= tmp)
492 return 0;
493 addr += tmp;
494 len -= tmp;
495 }
496 }
497 len = (len + 15) >> 4;
498 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
499 while (len--)
500 {
501 switch (cache)
502 {
503 case FLUSH_CACHE_DATA:
504 __asm__ __volatile__ (".chip 68060\n\t"
505 "cpushl %%dc,(%0)\n\t"
506 ".chip 68k"
507 : : "a" (paddr));
508 break;
509 case FLUSH_CACHE_INSN:
510 __asm__ __volatile__ (".chip 68060\n\t"
511 "cpushl %%ic,(%0)\n\t"
512 ".chip 68k"
513 : : "a" (paddr));
514 break;
515 default:
516 case FLUSH_CACHE_BOTH:
517 __asm__ __volatile__ (".chip 68060\n\t"
518 "cpushl %%bc,(%0)\n\t"
519 ".chip 68k"
520 : : "a" (paddr));
521 break;
522 }
523 if (!--i && len)
524 {
525
526 /*
527 * We just want to jump to the first cache line
528 * in the next page.
529 */
530 addr += PAGE_SIZE;
531 addr &= PAGE_MASK;
532
533 i = PAGE_SIZE / 16;
534 /* Recompute physical address when crossing a page
535 boundary. */
536 for (;;)
537 {
538 if ((paddr = virt_to_phys_060(addr)))
539 break;
540 if (len <= i)
541 return 0;
542 len -= i;
543 addr += PAGE_SIZE;
544 }
545 }
546 else
547 paddr += 16;
548 }
549 break;
550
551 default:
552 case FLUSH_SCOPE_PAGE:
553 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
554 addr &= PAGE_MASK; /* Workaround for bug in some
555 revisions of the 68060 */
556 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
557 {
558 if (!(paddr = virt_to_phys_060(addr)))
559 continue;
560 switch (cache)
561 {
562 case FLUSH_CACHE_DATA:
563 __asm__ __volatile__ (".chip 68060\n\t"
564 "cpushp %%dc,(%0)\n\t"
565 ".chip 68k"
566 : : "a" (paddr));
567 break;
568 case FLUSH_CACHE_INSN:
569 __asm__ __volatile__ (".chip 68060\n\t"
570 "cpushp %%ic,(%0)\n\t"
571 ".chip 68k"
572 : : "a" (paddr));
573 break;
574 default:
575 case FLUSH_CACHE_BOTH:
576 __asm__ __volatile__ (".chip 68060\n\t"
577 "cpushp %%bc,(%0)\n\t"
578 ".chip 68k"
579 : : "a" (paddr));
580 break;
581 }
582 }
583 break;
584 }
585 return 0;
586}
587
588/* sys_cacheflush -- flush (part of) the processor cache. */
589asmlinkage int
590sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
591{
592 struct vm_area_struct *vma;
593 int ret = -EINVAL;
594
595 lock_kernel();
596 if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
597 cache & ~FLUSH_CACHE_BOTH)
598 goto out;
599
600 if (scope == FLUSH_SCOPE_ALL) {
601 /* Only the superuser may explicitly flush the whole cache. */
602 ret = -EPERM;
603 if (!capable(CAP_SYS_ADMIN))
604 goto out;
605 } else {
606 /*
607 * Verify that the specified address region actually belongs
608 * to this process.
609 */
610 vma = find_vma (current->mm, addr);
611 ret = -EINVAL;
612 /* Check for overflow. */
613 if (addr + len < addr)
614 goto out;
615 if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
616 goto out;
617 }
618
619 if (CPU_IS_020_OR_030) {
620 if (scope == FLUSH_SCOPE_LINE && len < 256) {
621 unsigned long cacr;
622 __asm__ ("movec %%cacr, %0" : "=r" (cacr));
623 if (cache & FLUSH_CACHE_INSN)
624 cacr |= 4;
625 if (cache & FLUSH_CACHE_DATA)
626 cacr |= 0x400;
627 len >>= 2;
628 while (len--) {
629 __asm__ __volatile__ ("movec %1, %%caar\n\t"
630 "movec %0, %%cacr"
631 : /* no outputs */
632 : "r" (cacr), "r" (addr));
633 addr += 4;
634 }
635 } else {
636 /* Flush the whole cache, even if page granularity requested. */
637 unsigned long cacr;
638 __asm__ ("movec %%cacr, %0" : "=r" (cacr));
639 if (cache & FLUSH_CACHE_INSN)
640 cacr |= 8;
641 if (cache & FLUSH_CACHE_DATA)
642 cacr |= 0x800;
643 __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
644 }
645 ret = 0;
646 goto out;
647 } else {
648 /*
649 * 040 or 060: don't blindly trust 'scope', someone could
650 * try to flush a few megs of memory.
651 */
652
653 if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
654 scope=FLUSH_SCOPE_PAGE;
655 if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
656 scope=FLUSH_SCOPE_ALL;
657 if (CPU_IS_040) {
658 ret = cache_flush_040 (addr, scope, cache, len);
659 } else if (CPU_IS_060) {
660 ret = cache_flush_060 (addr, scope, cache, len);
661 }
662 }
663out:
664 unlock_kernel();
665 return ret;
666}
667
668asmlinkage int sys_getpagesize(void)
669{
670 return PAGE_SIZE;
671}
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
new file mode 100644
index 000000000000..e47e19588525
--- /dev/null
+++ b/arch/m68k/kernel/time.c
@@ -0,0 +1,187 @@
1/*
2 * linux/arch/m68k/kernel/time.c
3 *
4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
5 *
6 * This file contains the m68k-specific time handling details.
7 * Most of the stuff is located in the machine specific files.
8 *
9 * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
10 * "A Kernel Model for Precision Timekeeping" by Dave Mills
11 */
12
13#include <linux/config.h> /* CONFIG_HEARTBEAT */
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/rtc.h>
22
23#include <asm/machdep.h>
24#include <asm/io.h>
25
26#include <linux/time.h>
27#include <linux/timex.h>
28#include <linux/profile.h>
29
30u64 jiffies_64 = INITIAL_JIFFIES;
31
32EXPORT_SYMBOL(jiffies_64);
33
34static inline int set_rtc_mmss(unsigned long nowtime)
35{
36 if (mach_set_clock_mmss)
37 return mach_set_clock_mmss (nowtime);
38 return -1;
39}
40
41/*
42 * timer_interrupt() needs to keep up the real-time clock,
43 * as well as call the "do_timer()" routine every clocktick
44 */
45static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
46{
47 do_timer(regs);
48#ifndef CONFIG_SMP
49 update_process_times(user_mode(regs));
50#endif
51 profile_tick(CPU_PROFILING, regs);
52
53#ifdef CONFIG_HEARTBEAT
54 /* use power LED as a heartbeat instead -- much more useful
55 for debugging -- based on the version for PReP by Cort */
56 /* acts like an actual heart beat -- ie thump-thump-pause... */
57 if (mach_heartbeat) {
58 static unsigned cnt = 0, period = 0, dist = 0;
59
60 if (cnt == 0 || cnt == dist)
61 mach_heartbeat( 1 );
62 else if (cnt == 7 || cnt == dist+7)
63 mach_heartbeat( 0 );
64
65 if (++cnt > period) {
66 cnt = 0;
67 /* The hyperbolic function below modifies the heartbeat period
68 * length in dependency of the current (5min) load. It goes
69 * through the points f(0)=126, f(1)=86, f(5)=51,
70 * f(inf)->30. */
71 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
72 dist = period / 4;
73 }
74 }
75#endif /* CONFIG_HEARTBEAT */
76 return IRQ_HANDLED;
77}
78
79void time_init(void)
80{
81 struct rtc_time time;
82
83 if (mach_hwclk) {
84 mach_hwclk(0, &time);
85
86 if ((time.tm_year += 1900) < 1970)
87 time.tm_year += 100;
88 xtime.tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
89 time.tm_hour, time.tm_min, time.tm_sec);
90 xtime.tv_nsec = 0;
91 }
92 wall_to_monotonic.tv_sec = -xtime.tv_sec;
93
94 mach_sched_init(timer_interrupt);
95}
96
97/*
98 * This version of gettimeofday has near microsecond resolution.
99 */
100void do_gettimeofday(struct timeval *tv)
101{
102 unsigned long flags;
103 extern unsigned long wall_jiffies;
104 unsigned long seq;
105 unsigned long usec, sec, lost;
106 unsigned long max_ntp_tick = tick_usec - tickadj;
107
108 do {
109 seq = read_seqbegin_irqsave(&xtime_lock, flags);
110
111 usec = mach_gettimeoffset();
112 lost = jiffies - wall_jiffies;
113
114 /*
115 * If time_adjust is negative then NTP is slowing the clock
116 * so make sure not to go into next possible interval.
117 * Better to lose some accuracy than have time go backwards..
118 */
119 if (unlikely(time_adjust < 0)) {
120 usec = min(usec, max_ntp_tick);
121
122 if (lost)
123 usec += lost * max_ntp_tick;
124 }
125 else if (unlikely(lost))
126 usec += lost * tick_usec;
127
128 sec = xtime.tv_sec;
129 usec += xtime.tv_nsec/1000;
130 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
131
132
133 while (usec >= 1000000) {
134 usec -= 1000000;
135 sec++;
136 }
137
138 tv->tv_sec = sec;
139 tv->tv_usec = usec;
140}
141
142EXPORT_SYMBOL(do_gettimeofday);
143
144int do_settimeofday(struct timespec *tv)
145{
146 time_t wtm_sec, sec = tv->tv_sec;
147 long wtm_nsec, nsec = tv->tv_nsec;
148 extern unsigned long wall_jiffies;
149
150 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
151 return -EINVAL;
152
153 write_seqlock_irq(&xtime_lock);
154 /* This is revolting. We need to set the xtime.tv_nsec
155 * correctly. However, the value in this location is
156 * is value at the last tick.
157 * Discover what correction gettimeofday
158 * would have done, and then undo it!
159 */
160 nsec -= 1000 * (mach_gettimeoffset() +
161 (jiffies - wall_jiffies) * (1000000 / HZ));
162
163 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
164 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
165
166 set_normalized_timespec(&xtime, sec, nsec);
167 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
168
169 time_adjust = 0; /* stop active adjtime() */
170 time_status |= STA_UNSYNC;
171 time_maxerror = NTP_PHASE_LIMIT;
172 time_esterror = NTP_PHASE_LIMIT;
173 write_sequnlock_irq(&xtime_lock);
174 clock_was_set();
175 return 0;
176}
177
178EXPORT_SYMBOL(do_settimeofday);
179
180/*
181 * Scheduler clock - returns current time in ns units.
182 */
183unsigned long long sched_clock(void)
184{
185 return (unsigned long long)jiffies*(1000000000/HZ);
186}
187
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
new file mode 100644
index 000000000000..deb36e8b04a2
--- /dev/null
+++ b/arch/m68k/kernel/traps.c
@@ -0,0 +1,1227 @@
1/*
2 * linux/arch/m68k/kernel/traps.c
3 *
4 * Copyright (C) 1993, 1994 by Hamish Macdonald
5 *
6 * 68040 fixes by Michael Rausch
7 * 68040 fixes by Martin Apel
8 * 68040 fixes and writeback by Richard Zidlicky
9 * 68060 fixes by Roman Hodek
10 * 68060 fixes by Jesper Skov
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file COPYING in the main directory of this archive
14 * for more details.
15 */
16
17/*
18 * Sets up all exception vectors
19 */
20
21#include <linux/config.h>
22#include <linux/sched.h>
23#include <linux/signal.h>
24#include <linux/kernel.h>
25#include <linux/mm.h>
26#include <linux/module.h>
27#include <linux/a.out.h>
28#include <linux/user.h>
29#include <linux/string.h>
30#include <linux/linkage.h>
31#include <linux/init.h>
32#include <linux/ptrace.h>
33#include <linux/kallsyms.h>
34
35#include <asm/setup.h>
36#include <asm/fpu.h>
37#include <asm/system.h>
38#include <asm/uaccess.h>
39#include <asm/traps.h>
40#include <asm/pgalloc.h>
41#include <asm/machdep.h>
42#include <asm/siginfo.h>
43
44/* assembler routines */
45asmlinkage void system_call(void);
46asmlinkage void buserr(void);
47asmlinkage void trap(void);
48asmlinkage void inthandler(void);
49asmlinkage void nmihandler(void);
50#ifdef CONFIG_M68KFPU_EMU
51asmlinkage void fpu_emu(void);
52#endif
53
54e_vector vectors[256] = {
55 [VEC_BUSERR] = buserr,
56 [VEC_ADDRERR] = trap,
57 [VEC_ILLEGAL] = trap,
58 [VEC_ZERODIV] = trap,
59 [VEC_CHK] = trap,
60 [VEC_TRAP] = trap,
61 [VEC_PRIV] = trap,
62 [VEC_TRACE] = trap,
63 [VEC_LINE10] = trap,
64 [VEC_LINE11] = trap,
65 [VEC_RESV12] = trap,
66 [VEC_COPROC] = trap,
67 [VEC_FORMAT] = trap,
68 [VEC_UNINT] = trap,
69 [VEC_RESV16] = trap,
70 [VEC_RESV17] = trap,
71 [VEC_RESV18] = trap,
72 [VEC_RESV19] = trap,
73 [VEC_RESV20] = trap,
74 [VEC_RESV21] = trap,
75 [VEC_RESV22] = trap,
76 [VEC_RESV23] = trap,
77 [VEC_SPUR] = inthandler,
78 [VEC_INT1] = inthandler,
79 [VEC_INT2] = inthandler,
80 [VEC_INT3] = inthandler,
81 [VEC_INT4] = inthandler,
82 [VEC_INT5] = inthandler,
83 [VEC_INT6] = inthandler,
84 [VEC_INT7] = inthandler,
85 [VEC_SYS] = system_call,
86 [VEC_TRAP1] = trap,
87 [VEC_TRAP2] = trap,
88 [VEC_TRAP3] = trap,
89 [VEC_TRAP4] = trap,
90 [VEC_TRAP5] = trap,
91 [VEC_TRAP6] = trap,
92 [VEC_TRAP7] = trap,
93 [VEC_TRAP8] = trap,
94 [VEC_TRAP9] = trap,
95 [VEC_TRAP10] = trap,
96 [VEC_TRAP11] = trap,
97 [VEC_TRAP12] = trap,
98 [VEC_TRAP13] = trap,
99 [VEC_TRAP14] = trap,
100 [VEC_TRAP15] = trap,
101};
102
103/* nmi handler for the Amiga */
104asm(".text\n"
105 __ALIGN_STR "\n"
106 "nmihandler: rte");
107
108/*
109 * this must be called very early as the kernel might
110 * use some instruction that are emulated on the 060
111 */
112void __init base_trap_init(void)
113{
114 if(MACH_IS_SUN3X) {
115 extern e_vector *sun3x_prom_vbr;
116
117 __asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr));
118 }
119
120 /* setup the exception vector table */
121 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
122
123 if (CPU_IS_060) {
124 /* set up ISP entry points */
125 asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
126
127 vectors[VEC_UNIMPII] = unimp_vec;
128 }
129}
130
131void __init trap_init (void)
132{
133 int i;
134
135 for (i = 48; i < 64; i++)
136 if (!vectors[i])
137 vectors[i] = trap;
138
139 for (i = 64; i < 256; i++)
140 vectors[i] = inthandler;
141
142#ifdef CONFIG_M68KFPU_EMU
143 if (FPU_IS_EMU)
144 vectors[VEC_LINE11] = fpu_emu;
145#endif
146
147 if (CPU_IS_040 && !FPU_IS_EMU) {
148 /* set up FPSP entry points */
149 asmlinkage void dz_vec(void) asm ("dz");
150 asmlinkage void inex_vec(void) asm ("inex");
151 asmlinkage void ovfl_vec(void) asm ("ovfl");
152 asmlinkage void unfl_vec(void) asm ("unfl");
153 asmlinkage void snan_vec(void) asm ("snan");
154 asmlinkage void operr_vec(void) asm ("operr");
155 asmlinkage void bsun_vec(void) asm ("bsun");
156 asmlinkage void fline_vec(void) asm ("fline");
157 asmlinkage void unsupp_vec(void) asm ("unsupp");
158
159 vectors[VEC_FPDIVZ] = dz_vec;
160 vectors[VEC_FPIR] = inex_vec;
161 vectors[VEC_FPOVER] = ovfl_vec;
162 vectors[VEC_FPUNDER] = unfl_vec;
163 vectors[VEC_FPNAN] = snan_vec;
164 vectors[VEC_FPOE] = operr_vec;
165 vectors[VEC_FPBRUC] = bsun_vec;
166 vectors[VEC_LINE11] = fline_vec;
167 vectors[VEC_FPUNSUP] = unsupp_vec;
168 }
169
170 if (CPU_IS_060 && !FPU_IS_EMU) {
171 /* set up IFPSP entry points */
172 asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
173 asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
174 asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl");
175 asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl");
176 asmlinkage void dz_vec(void) asm ("_060_fpsp_dz");
177 asmlinkage void inex_vec(void) asm ("_060_fpsp_inex");
178 asmlinkage void fline_vec(void) asm ("_060_fpsp_fline");
179 asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
180 asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
181
182 vectors[VEC_FPNAN] = snan_vec;
183 vectors[VEC_FPOE] = operr_vec;
184 vectors[VEC_FPOVER] = ovfl_vec;
185 vectors[VEC_FPUNDER] = unfl_vec;
186 vectors[VEC_FPDIVZ] = dz_vec;
187 vectors[VEC_FPIR] = inex_vec;
188 vectors[VEC_LINE11] = fline_vec;
189 vectors[VEC_FPUNSUP] = unsupp_vec;
190 vectors[VEC_UNIMPEA] = effadd_vec;
191 }
192
193 /* if running on an amiga, make the NMI interrupt do nothing */
194 if (MACH_IS_AMIGA) {
195 vectors[VEC_INT7] = nmihandler;
196 }
197}
198
199
200static const char *vec_names[] = {
201 [VEC_RESETSP] = "RESET SP",
202 [VEC_RESETPC] = "RESET PC",
203 [VEC_BUSERR] = "BUS ERROR",
204 [VEC_ADDRERR] = "ADDRESS ERROR",
205 [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION",
206 [VEC_ZERODIV] = "ZERO DIVIDE",
207 [VEC_CHK] = "CHK",
208 [VEC_TRAP] = "TRAPcc",
209 [VEC_PRIV] = "PRIVILEGE VIOLATION",
210 [VEC_TRACE] = "TRACE",
211 [VEC_LINE10] = "LINE 1010",
212 [VEC_LINE11] = "LINE 1111",
213 [VEC_RESV12] = "UNASSIGNED RESERVED 12",
214 [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION",
215 [VEC_FORMAT] = "FORMAT ERROR",
216 [VEC_UNINT] = "UNINITIALIZED INTERRUPT",
217 [VEC_RESV16] = "UNASSIGNED RESERVED 16",
218 [VEC_RESV17] = "UNASSIGNED RESERVED 17",
219 [VEC_RESV18] = "UNASSIGNED RESERVED 18",
220 [VEC_RESV19] = "UNASSIGNED RESERVED 19",
221 [VEC_RESV20] = "UNASSIGNED RESERVED 20",
222 [VEC_RESV21] = "UNASSIGNED RESERVED 21",
223 [VEC_RESV22] = "UNASSIGNED RESERVED 22",
224 [VEC_RESV23] = "UNASSIGNED RESERVED 23",
225 [VEC_SPUR] = "SPURIOUS INTERRUPT",
226 [VEC_INT1] = "LEVEL 1 INT",
227 [VEC_INT2] = "LEVEL 2 INT",
228 [VEC_INT3] = "LEVEL 3 INT",
229 [VEC_INT4] = "LEVEL 4 INT",
230 [VEC_INT5] = "LEVEL 5 INT",
231 [VEC_INT6] = "LEVEL 6 INT",
232 [VEC_INT7] = "LEVEL 7 INT",
233 [VEC_SYS] = "SYSCALL",
234 [VEC_TRAP1] = "TRAP #1",
235 [VEC_TRAP2] = "TRAP #2",
236 [VEC_TRAP3] = "TRAP #3",
237 [VEC_TRAP4] = "TRAP #4",
238 [VEC_TRAP5] = "TRAP #5",
239 [VEC_TRAP6] = "TRAP #6",
240 [VEC_TRAP7] = "TRAP #7",
241 [VEC_TRAP8] = "TRAP #8",
242 [VEC_TRAP9] = "TRAP #9",
243 [VEC_TRAP10] = "TRAP #10",
244 [VEC_TRAP11] = "TRAP #11",
245 [VEC_TRAP12] = "TRAP #12",
246 [VEC_TRAP13] = "TRAP #13",
247 [VEC_TRAP14] = "TRAP #14",
248 [VEC_TRAP15] = "TRAP #15",
249 [VEC_FPBRUC] = "FPCP BSUN",
250 [VEC_FPIR] = "FPCP INEXACT",
251 [VEC_FPDIVZ] = "FPCP DIV BY 0",
252 [VEC_FPUNDER] = "FPCP UNDERFLOW",
253 [VEC_FPOE] = "FPCP OPERAND ERROR",
254 [VEC_FPOVER] = "FPCP OVERFLOW",
255 [VEC_FPNAN] = "FPCP SNAN",
256 [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION",
257 [VEC_MMUCFG] = "MMU CONFIGURATION ERROR",
258 [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR",
259 [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR",
260 [VEC_RESV59] = "UNASSIGNED RESERVED 59",
261 [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60",
262 [VEC_UNIMPII] = "UNASSIGNED RESERVED 61",
263 [VEC_RESV62] = "UNASSIGNED RESERVED 62",
264 [VEC_RESV63] = "UNASSIGNED RESERVED 63",
265};
266
267static const char *space_names[] = {
268 [0] = "Space 0",
269 [USER_DATA] = "User Data",
270 [USER_PROGRAM] = "User Program",
271#ifndef CONFIG_SUN3
272 [3] = "Space 3",
273#else
274 [FC_CONTROL] = "Control",
275#endif
276 [4] = "Space 4",
277 [SUPER_DATA] = "Super Data",
278 [SUPER_PROGRAM] = "Super Program",
279 [CPU_SPACE] = "CPU"
280};
281
282void die_if_kernel(char *,struct pt_regs *,int);
283asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
284 unsigned long error_code);
285int send_fault_sig(struct pt_regs *regs);
286
287asmlinkage void trap_c(struct frame *fp);
288
289#if defined (CONFIG_M68060)
290static inline void access_error060 (struct frame *fp)
291{
292 unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
293
294#ifdef DEBUG
295 printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
296#endif
297
298 if (fslw & MMU060_BPE) {
299 /* branch prediction error -> clear branch cache */
300 __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
301 "orl #0x00400000,%/d0\n\t"
302 "movec %/d0,%/cacr"
303 : : : "d0" );
304 /* return if there's no other error */
305 if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
306 return;
307 }
308
309 if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
310 unsigned long errorcode;
311 unsigned long addr = fp->un.fmt4.effaddr;
312
313 if (fslw & MMU060_MA)
314 addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
315
316 errorcode = 1;
317 if (fslw & MMU060_DESC_ERR) {
318 __flush_tlb040_one(addr);
319 errorcode = 0;
320 }
321 if (fslw & MMU060_W)
322 errorcode |= 2;
323#ifdef DEBUG
324 printk("errorcode = %d\n", errorcode );
325#endif
326 do_page_fault(&fp->ptregs, addr, errorcode);
327 } else if (fslw & (MMU060_SEE)){
328 /* Software Emulation Error.
329 * fault during mem_read/mem_write in ifpsp060/os.S
330 */
331 send_fault_sig(&fp->ptregs);
332 } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
333 send_fault_sig(&fp->ptregs) > 0) {
334 printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
335 printk( "68060 access error, fslw=%lx\n", fslw );
336 trap_c( fp );
337 }
338}
339#endif /* CONFIG_M68060 */
340
341#if defined (CONFIG_M68040)
342static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
343{
344 unsigned long mmusr;
345 mm_segment_t old_fs = get_fs();
346
347 set_fs(MAKE_MM_SEG(wbs));
348
349 if (iswrite)
350 asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
351 else
352 asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
353
354 asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
355
356 set_fs(old_fs);
357
358 return mmusr;
359}
360
361static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
362 unsigned long wbd)
363{
364 int res = 0;
365 mm_segment_t old_fs = get_fs();
366
367 /* set_fs can not be moved, otherwise put_user() may oops */
368 set_fs(MAKE_MM_SEG(wbs));
369
370 switch (wbs & WBSIZ_040) {
371 case BA_SIZE_BYTE:
372 res = put_user(wbd & 0xff, (char *)wba);
373 break;
374 case BA_SIZE_WORD:
375 res = put_user(wbd & 0xffff, (short *)wba);
376 break;
377 case BA_SIZE_LONG:
378 res = put_user(wbd, (int *)wba);
379 break;
380 }
381
382 /* set_fs can not be moved, otherwise put_user() may oops */
383 set_fs(old_fs);
384
385
386#ifdef DEBUG
387 printk("do_040writeback1, res=%d\n",res);
388#endif
389
390 return res;
391}
392
393/* after an exception in a writeback the stack frame corresponding
394 * to that exception is discarded, set a few bits in the old frame
395 * to simulate what it should look like
396 */
397static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
398{
399 fp->un.fmt7.faddr = wba;
400 fp->un.fmt7.ssw = wbs & 0xff;
401 if (wba != current->thread.faddr)
402 fp->un.fmt7.ssw |= MA_040;
403}
404
405static inline void do_040writebacks(struct frame *fp)
406{
407 int res = 0;
408#if 0
409 if (fp->un.fmt7.wb1s & WBV_040)
410 printk("access_error040: cannot handle 1st writeback. oops.\n");
411#endif
412
413 if ((fp->un.fmt7.wb2s & WBV_040) &&
414 !(fp->un.fmt7.wb2s & WBTT_040)) {
415 res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
416 fp->un.fmt7.wb2d);
417 if (res)
418 fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
419 else
420 fp->un.fmt7.wb2s = 0;
421 }
422
423 /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
424 if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
425 res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
426 fp->un.fmt7.wb3d);
427 if (res)
428 {
429 fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
430
431 fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
432 fp->un.fmt7.wb3s &= (~WBV_040);
433 fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
434 fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
435 }
436 else
437 fp->un.fmt7.wb3s = 0;
438 }
439
440 if (res)
441 send_fault_sig(&fp->ptregs);
442}
443
444/*
445 * called from sigreturn(), must ensure userspace code didn't
446 * manipulate exception frame to circumvent protection, then complete
447 * pending writebacks
448 * we just clear TM2 to turn it into an userspace access
449 */
450asmlinkage void berr_040cleanup(struct frame *fp)
451{
452 fp->un.fmt7.wb2s &= ~4;
453 fp->un.fmt7.wb3s &= ~4;
454
455 do_040writebacks(fp);
456}
457
458static inline void access_error040(struct frame *fp)
459{
460 unsigned short ssw = fp->un.fmt7.ssw;
461 unsigned long mmusr;
462
463#ifdef DEBUG
464 printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
465 printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
466 fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
467 printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
468 fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
469 fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
470#endif
471
472 if (ssw & ATC_040) {
473 unsigned long addr = fp->un.fmt7.faddr;
474 unsigned long errorcode;
475
476 /*
477 * The MMU status has to be determined AFTER the address
478 * has been corrected if there was a misaligned access (MA).
479 */
480 if (ssw & MA_040)
481 addr = (addr + 7) & -8;
482
483 /* MMU error, get the MMUSR info for this access */
484 mmusr = probe040(!(ssw & RW_040), addr, ssw);
485#ifdef DEBUG
486 printk("mmusr = %lx\n", mmusr);
487#endif
488 errorcode = 1;
489 if (!(mmusr & MMU_R_040)) {
490 /* clear the invalid atc entry */
491 __flush_tlb040_one(addr);
492 errorcode = 0;
493 }
494
495 /* despite what documentation seems to say, RMW
496 * accesses have always both the LK and RW bits set */
497 if (!(ssw & RW_040) || (ssw & LK_040))
498 errorcode |= 2;
499
500 if (do_page_fault(&fp->ptregs, addr, errorcode)) {
501#ifdef DEBUG
502 printk("do_page_fault() !=0 \n");
503#endif
504 if (user_mode(&fp->ptregs)){
505 /* delay writebacks after signal delivery */
506#ifdef DEBUG
507 printk(".. was usermode - return\n");
508#endif
509 return;
510 }
511 /* disable writeback into user space from kernel
512 * (if do_page_fault didn't fix the mapping,
513 * the writeback won't do good)
514 */
515#ifdef DEBUG
516 printk(".. disabling wb2\n");
517#endif
518 if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
519 fp->un.fmt7.wb2s &= ~WBV_040;
520 }
521 } else if (send_fault_sig(&fp->ptregs) > 0) {
522 printk("68040 access error, ssw=%x\n", ssw);
523 trap_c(fp);
524 }
525
526 do_040writebacks(fp);
527}
528#endif /* CONFIG_M68040 */
529
530#if defined(CONFIG_SUN3)
531#include <asm/sun3mmu.h>
532
533extern int mmu_emu_handle_fault (unsigned long, int, int);
534
535/* sun3 version of bus_error030 */
536
537static inline void bus_error030 (struct frame *fp)
538{
539 unsigned char buserr_type = sun3_get_buserr ();
540 unsigned long addr, errorcode;
541 unsigned short ssw = fp->un.fmtb.ssw;
542 extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
543
544#ifdef DEBUG
545 if (ssw & (FC | FB))
546 printk ("Instruction fault at %#010lx\n",
547 ssw & FC ?
548 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
549 :
550 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
551 if (ssw & DF)
552 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
553 ssw & RW ? "read" : "write",
554 fp->un.fmtb.daddr,
555 space_names[ssw & DFC], fp->ptregs.pc);
556#endif
557
558 /*
559 * Check if this page should be demand-mapped. This needs to go before
560 * the testing for a bad kernel-space access (demand-mapping applies
561 * to kernel accesses too).
562 */
563
564 if ((ssw & DF)
565 && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
566 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
567 return;
568 }
569
570 /* Check for kernel-space pagefault (BAD). */
571 if (fp->ptregs.sr & PS_S) {
572 /* kernel fault must be a data fault to user space */
573 if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
574 // try checking the kernel mappings before surrender
575 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
576 return;
577 /* instruction fault or kernel data fault! */
578 if (ssw & (FC | FB))
579 printk ("Instruction fault at %#010lx\n",
580 fp->ptregs.pc);
581 if (ssw & DF) {
582 /* was this fault incurred testing bus mappings? */
583 if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
584 (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
585 send_fault_sig(&fp->ptregs);
586 return;
587 }
588
589 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
590 ssw & RW ? "read" : "write",
591 fp->un.fmtb.daddr,
592 space_names[ssw & DFC], fp->ptregs.pc);
593 }
594 printk ("BAD KERNEL BUSERR\n");
595
596 die_if_kernel("Oops", &fp->ptregs,0);
597 force_sig(SIGKILL, current);
598 return;
599 }
600 } else {
601 /* user fault */
602 if (!(ssw & (FC | FB)) && !(ssw & DF))
603 /* not an instruction fault or data fault! BAD */
604 panic ("USER BUSERR w/o instruction or data fault");
605 }
606
607
608 /* First handle the data fault, if any. */
609 if (ssw & DF) {
610 addr = fp->un.fmtb.daddr;
611
612// errorcode bit 0: 0 -> no page 1 -> protection fault
613// errorcode bit 1: 0 -> read fault 1 -> write fault
614
615// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
616// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
617
618 if (buserr_type & SUN3_BUSERR_PROTERR)
619 errorcode = 0x01;
620 else if (buserr_type & SUN3_BUSERR_INVALID)
621 errorcode = 0x00;
622 else {
623#ifdef DEBUG
624 printk ("*** unexpected busfault type=%#04x\n", buserr_type);
625 printk ("invalid %s access at %#lx from pc %#lx\n",
626 !(ssw & RW) ? "write" : "read", addr,
627 fp->ptregs.pc);
628#endif
629 die_if_kernel ("Oops", &fp->ptregs, buserr_type);
630 force_sig (SIGBUS, current);
631 return;
632 }
633
634//todo: wtf is RM bit? --m
635 if (!(ssw & RW) || ssw & RM)
636 errorcode |= 0x02;
637
638 /* Handle page fault. */
639 do_page_fault (&fp->ptregs, addr, errorcode);
640
641 /* Retry the data fault now. */
642 return;
643 }
644
645 /* Now handle the instruction fault. */
646
647 /* Get the fault address. */
648 if (fp->ptregs.format == 0xA)
649 addr = fp->ptregs.pc + 4;
650 else
651 addr = fp->un.fmtb.baddr;
652 if (ssw & FC)
653 addr -= 2;
654
655 if (buserr_type & SUN3_BUSERR_INVALID) {
656 if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
657 do_page_fault (&fp->ptregs, addr, 0);
658 } else {
659#ifdef DEBUG
660 printk ("protection fault on insn access (segv).\n");
661#endif
662 force_sig (SIGSEGV, current);
663 }
664}
665#else
666#if defined(CPU_M68020_OR_M68030)
667static inline void bus_error030 (struct frame *fp)
668{
669 volatile unsigned short temp;
670 unsigned short mmusr;
671 unsigned long addr, errorcode;
672 unsigned short ssw = fp->un.fmtb.ssw;
673#ifdef DEBUG
674 unsigned long desc;
675
676 printk ("pid = %x ", current->pid);
677 printk ("SSW=%#06x ", ssw);
678
679 if (ssw & (FC | FB))
680 printk ("Instruction fault at %#010lx\n",
681 ssw & FC ?
682 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
683 :
684 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
685 if (ssw & DF)
686 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
687 ssw & RW ? "read" : "write",
688 fp->un.fmtb.daddr,
689 space_names[ssw & DFC], fp->ptregs.pc);
690#endif
691
692 /* ++andreas: If a data fault and an instruction fault happen
693 at the same time map in both pages. */
694
695 /* First handle the data fault, if any. */
696 if (ssw & DF) {
697 addr = fp->un.fmtb.daddr;
698
699#ifdef DEBUG
700 asm volatile ("ptestr %3,%2@,#7,%0\n\t"
701 "pmove %%psr,%1@"
702 : "=a&" (desc)
703 : "a" (&temp), "a" (addr), "d" (ssw));
704#else
705 asm volatile ("ptestr %2,%1@,#7\n\t"
706 "pmove %%psr,%0@"
707 : : "a" (&temp), "a" (addr), "d" (ssw));
708#endif
709 mmusr = temp;
710
711#ifdef DEBUG
712 printk("mmusr is %#x for addr %#lx in task %p\n",
713 mmusr, addr, current);
714 printk("descriptor address is %#lx, contents %#lx\n",
715 __va(desc), *(unsigned long *)__va(desc));
716#endif
717
718 errorcode = (mmusr & MMU_I) ? 0 : 1;
719 if (!(ssw & RW) || (ssw & RM))
720 errorcode |= 2;
721
722 if (mmusr & (MMU_I | MMU_WP)) {
723 if (ssw & 4) {
724 printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
725 ssw & RW ? "read" : "write",
726 fp->un.fmtb.daddr,
727 space_names[ssw & DFC], fp->ptregs.pc);
728 goto buserr;
729 }
730 /* Don't try to do anything further if an exception was
731 handled. */
732 if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
733 return;
734 } else if (!(mmusr & MMU_I)) {
735 /* probably a 020 cas fault */
736 if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
737 printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
738 } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
739 printk("invalid %s access at %#lx from pc %#lx\n",
740 !(ssw & RW) ? "write" : "read", addr,
741 fp->ptregs.pc);
742 die_if_kernel("Oops",&fp->ptregs,mmusr);
743 force_sig(SIGSEGV, current);
744 return;
745 } else {
746#if 0
747 static volatile long tlong;
748#endif
749
750 printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
751 !(ssw & RW) ? "write" : "read", addr,
752 fp->ptregs.pc, ssw);
753 asm volatile ("ptestr #1,%1@,#0\n\t"
754 "pmove %%psr,%0@"
755 : /* no outputs */
756 : "a" (&temp), "a" (addr));
757 mmusr = temp;
758
759 printk ("level 0 mmusr is %#x\n", mmusr);
760#if 0
761 asm volatile ("pmove %%tt0,%0@"
762 : /* no outputs */
763 : "a" (&tlong));
764 printk("tt0 is %#lx, ", tlong);
765 asm volatile ("pmove %%tt1,%0@"
766 : /* no outputs */
767 : "a" (&tlong));
768 printk("tt1 is %#lx\n", tlong);
769#endif
770#ifdef DEBUG
771 printk("Unknown SIGSEGV - 1\n");
772#endif
773 die_if_kernel("Oops",&fp->ptregs,mmusr);
774 force_sig(SIGSEGV, current);
775 return;
776 }
777
778 /* setup an ATC entry for the access about to be retried */
779 if (!(ssw & RW) || (ssw & RM))
780 asm volatile ("ploadw %1,%0@" : /* no outputs */
781 : "a" (addr), "d" (ssw));
782 else
783 asm volatile ("ploadr %1,%0@" : /* no outputs */
784 : "a" (addr), "d" (ssw));
785 }
786
787 /* Now handle the instruction fault. */
788
789 if (!(ssw & (FC|FB)))
790 return;
791
792 if (fp->ptregs.sr & PS_S) {
793 printk("Instruction fault at %#010lx\n",
794 fp->ptregs.pc);
795 buserr:
796 printk ("BAD KERNEL BUSERR\n");
797 die_if_kernel("Oops",&fp->ptregs,0);
798 force_sig(SIGKILL, current);
799 return;
800 }
801
802 /* get the fault address */
803 if (fp->ptregs.format == 10)
804 addr = fp->ptregs.pc + 4;
805 else
806 addr = fp->un.fmtb.baddr;
807 if (ssw & FC)
808 addr -= 2;
809
810 if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
811 /* Insn fault on same page as data fault. But we
812 should still create the ATC entry. */
813 goto create_atc_entry;
814
815#ifdef DEBUG
816 asm volatile ("ptestr #1,%2@,#7,%0\n\t"
817 "pmove %%psr,%1@"
818 : "=a&" (desc)
819 : "a" (&temp), "a" (addr));
820#else
821 asm volatile ("ptestr #1,%1@,#7\n\t"
822 "pmove %%psr,%0@"
823 : : "a" (&temp), "a" (addr));
824#endif
825 mmusr = temp;
826
827#ifdef DEBUG
828 printk ("mmusr is %#x for addr %#lx in task %p\n",
829 mmusr, addr, current);
830 printk ("descriptor address is %#lx, contents %#lx\n",
831 __va(desc), *(unsigned long *)__va(desc));
832#endif
833
834 if (mmusr & MMU_I)
835 do_page_fault (&fp->ptregs, addr, 0);
836 else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
837 printk ("invalid insn access at %#lx from pc %#lx\n",
838 addr, fp->ptregs.pc);
839#ifdef DEBUG
840 printk("Unknown SIGSEGV - 2\n");
841#endif
842 die_if_kernel("Oops",&fp->ptregs,mmusr);
843 force_sig(SIGSEGV, current);
844 return;
845 }
846
847create_atc_entry:
848 /* setup an ATC entry for the access about to be retried */
849 asm volatile ("ploadr #2,%0@" : /* no outputs */
850 : "a" (addr));
851}
852#endif /* CPU_M68020_OR_M68030 */
853#endif /* !CONFIG_SUN3 */
854
855asmlinkage void buserr_c(struct frame *fp)
856{
857 /* Only set esp0 if coming from user mode */
858 if (user_mode(&fp->ptregs))
859 current->thread.esp0 = (unsigned long) fp;
860
861#ifdef DEBUG
862 printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
863#endif
864
865 switch (fp->ptregs.format) {
866#if defined (CONFIG_M68060)
867 case 4: /* 68060 access error */
868 access_error060 (fp);
869 break;
870#endif
871#if defined (CONFIG_M68040)
872 case 0x7: /* 68040 access error */
873 access_error040 (fp);
874 break;
875#endif
876#if defined (CPU_M68020_OR_M68030)
877 case 0xa:
878 case 0xb:
879 bus_error030 (fp);
880 break;
881#endif
882 default:
883 die_if_kernel("bad frame format",&fp->ptregs,0);
884#ifdef DEBUG
885 printk("Unknown SIGSEGV - 4\n");
886#endif
887 force_sig(SIGSEGV, current);
888 }
889}
890
891
892static int kstack_depth_to_print = 48;
893
894void show_trace(unsigned long *stack)
895{
896 unsigned long *endstack;
897 unsigned long addr;
898 int i;
899
900 printk("Call Trace:");
901 addr = (unsigned long)stack + THREAD_SIZE - 1;
902 endstack = (unsigned long *)(addr & -THREAD_SIZE);
903 i = 0;
904 while (stack + 1 <= endstack) {
905 addr = *stack++;
906 /*
907 * If the address is either in the text segment of the
908 * kernel, or in the region which contains vmalloc'ed
909 * memory, it *may* be the address of a calling
910 * routine; if so, print it so that someone tracing
911 * down the cause of the crash will be able to figure
912 * out the call path that was taken.
913 */
914 if (__kernel_text_address(addr)) {
915#ifndef CONFIG_KALLSYMS
916 if (i % 5 == 0)
917 printk("\n ");
918#endif
919 printk(" [<%08lx>]", addr);
920 print_symbol(" %s\n", addr);
921 i++;
922 }
923 }
924 printk("\n");
925}
926
927void show_registers(struct pt_regs *regs)
928{
929 struct frame *fp = (struct frame *)regs;
930 unsigned long addr;
931 int i;
932
933 addr = (unsigned long)&fp->un;
934 printk("Frame format=%X ", fp->ptregs.format);
935 switch (fp->ptregs.format) {
936 case 0x2:
937 printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
938 addr += sizeof(fp->un.fmt2);
939 break;
940 case 0x3:
941 printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
942 addr += sizeof(fp->un.fmt3);
943 break;
944 case 0x4:
945 printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
946 : "eff addr=%08lx pc=%08lx\n"),
947 fp->un.fmt4.effaddr, fp->un.fmt4.pc);
948 addr += sizeof(fp->un.fmt4);
949 break;
950 case 0x7:
951 printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
952 fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
953 printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
954 fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
955 printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
956 fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
957 printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
958 fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
959 printk("push data: %08lx %08lx %08lx %08lx\n",
960 fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
961 fp->un.fmt7.pd3);
962 addr += sizeof(fp->un.fmt7);
963 break;
964 case 0x9:
965 printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
966 addr += sizeof(fp->un.fmt9);
967 break;
968 case 0xa:
969 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
970 fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
971 fp->un.fmta.daddr, fp->un.fmta.dobuf);
972 addr += sizeof(fp->un.fmta);
973 break;
974 case 0xb:
975 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
976 fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
977 fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
978 printk("baddr=%08lx dibuf=%08lx ver=%x\n",
979 fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
980 addr += sizeof(fp->un.fmtb);
981 break;
982 default:
983 printk("\n");
984 }
985 show_stack(NULL, (unsigned long *)addr);
986
987 printk("Code: ");
988 for (i = 0; i < 10; i++)
989 printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
990 printk ("\n");
991}
992
993void show_stack(struct task_struct *task, unsigned long *stack)
994{
995 unsigned long *endstack;
996 int i;
997
998 if (!stack) {
999 if (task)
1000 stack = (unsigned long *)task->thread.esp0;
1001 else
1002 stack = (unsigned long *)&stack;
1003 }
1004 endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
1005
1006 printk("Stack from %08lx:", (unsigned long)stack);
1007 for (i = 0; i < kstack_depth_to_print; i++) {
1008 if (stack + 1 > endstack)
1009 break;
1010 if (i % 8 == 0)
1011 printk("\n ");
1012 printk(" %08lx", *stack++);
1013 }
1014 printk("\n");
1015 show_trace(stack);
1016}
1017
1018/*
1019 * The architecture-independent backtrace generator
1020 */
1021void dump_stack(void)
1022{
1023 unsigned long stack;
1024
1025 show_trace(&stack);
1026}
1027
1028EXPORT_SYMBOL(dump_stack);
1029
1030void bad_super_trap (struct frame *fp)
1031{
1032 console_verbose();
1033 if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
1034 printk ("*** %s *** FORMAT=%X\n",
1035 vec_names[(fp->ptregs.vector) >> 2],
1036 fp->ptregs.format);
1037 else
1038 printk ("*** Exception %d *** FORMAT=%X\n",
1039 (fp->ptregs.vector) >> 2,
1040 fp->ptregs.format);
1041 if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
1042 unsigned short ssw = fp->un.fmtb.ssw;
1043
1044 printk ("SSW=%#06x ", ssw);
1045
1046 if (ssw & RC)
1047 printk ("Pipe stage C instruction fault at %#010lx\n",
1048 (fp->ptregs.format) == 0xA ?
1049 fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
1050 if (ssw & RB)
1051 printk ("Pipe stage B instruction fault at %#010lx\n",
1052 (fp->ptregs.format) == 0xA ?
1053 fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
1054 if (ssw & DF)
1055 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
1056 ssw & RW ? "read" : "write",
1057 fp->un.fmtb.daddr, space_names[ssw & DFC],
1058 fp->ptregs.pc);
1059 }
1060 printk ("Current process id is %d\n", current->pid);
1061 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
1062}
1063
1064asmlinkage void trap_c(struct frame *fp)
1065{
1066 int sig;
1067 siginfo_t info;
1068
1069 if (fp->ptregs.sr & PS_S) {
1070 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
1071 /* traced a trapping instruction */
1072 current->ptrace |= PT_DTRACE;
1073 } else
1074 bad_super_trap(fp);
1075 return;
1076 }
1077
1078 /* send the appropriate signal to the user program */
1079 switch ((fp->ptregs.vector) >> 2) {
1080 case VEC_ADDRERR:
1081 info.si_code = BUS_ADRALN;
1082 sig = SIGBUS;
1083 break;
1084 case VEC_ILLEGAL:
1085 case VEC_LINE10:
1086 case VEC_LINE11:
1087 info.si_code = ILL_ILLOPC;
1088 sig = SIGILL;
1089 break;
1090 case VEC_PRIV:
1091 info.si_code = ILL_PRVOPC;
1092 sig = SIGILL;
1093 break;
1094 case VEC_COPROC:
1095 info.si_code = ILL_COPROC;
1096 sig = SIGILL;
1097 break;
1098 case VEC_TRAP1:
1099 case VEC_TRAP2:
1100 case VEC_TRAP3:
1101 case VEC_TRAP4:
1102 case VEC_TRAP5:
1103 case VEC_TRAP6:
1104 case VEC_TRAP7:
1105 case VEC_TRAP8:
1106 case VEC_TRAP9:
1107 case VEC_TRAP10:
1108 case VEC_TRAP11:
1109 case VEC_TRAP12:
1110 case VEC_TRAP13:
1111 case VEC_TRAP14:
1112 info.si_code = ILL_ILLTRP;
1113 sig = SIGILL;
1114 break;
1115 case VEC_FPBRUC:
1116 case VEC_FPOE:
1117 case VEC_FPNAN:
1118 info.si_code = FPE_FLTINV;
1119 sig = SIGFPE;
1120 break;
1121 case VEC_FPIR:
1122 info.si_code = FPE_FLTRES;
1123 sig = SIGFPE;
1124 break;
1125 case VEC_FPDIVZ:
1126 info.si_code = FPE_FLTDIV;
1127 sig = SIGFPE;
1128 break;
1129 case VEC_FPUNDER:
1130 info.si_code = FPE_FLTUND;
1131 sig = SIGFPE;
1132 break;
1133 case VEC_FPOVER:
1134 info.si_code = FPE_FLTOVF;
1135 sig = SIGFPE;
1136 break;
1137 case VEC_ZERODIV:
1138 info.si_code = FPE_INTDIV;
1139 sig = SIGFPE;
1140 break;
1141 case VEC_CHK:
1142 case VEC_TRAP:
1143 info.si_code = FPE_INTOVF;
1144 sig = SIGFPE;
1145 break;
1146 case VEC_TRACE: /* ptrace single step */
1147 info.si_code = TRAP_TRACE;
1148 sig = SIGTRAP;
1149 break;
1150 case VEC_TRAP15: /* breakpoint */
1151 info.si_code = TRAP_BRKPT;
1152 sig = SIGTRAP;
1153 break;
1154 default:
1155 info.si_code = ILL_ILLOPC;
1156 sig = SIGILL;
1157 break;
1158 }
1159 info.si_signo = sig;
1160 info.si_errno = 0;
1161 switch (fp->ptregs.format) {
1162 default:
1163 info.si_addr = (void *) fp->ptregs.pc;
1164 break;
1165 case 2:
1166 info.si_addr = (void *) fp->un.fmt2.iaddr;
1167 break;
1168 case 7:
1169 info.si_addr = (void *) fp->un.fmt7.effaddr;
1170 break;
1171 case 9:
1172 info.si_addr = (void *) fp->un.fmt9.iaddr;
1173 break;
1174 case 10:
1175 info.si_addr = (void *) fp->un.fmta.daddr;
1176 break;
1177 case 11:
1178 info.si_addr = (void *) fp->un.fmtb.daddr;
1179 break;
1180 }
1181 force_sig_info (sig, &info, current);
1182}
1183
1184void die_if_kernel (char *str, struct pt_regs *fp, int nr)
1185{
1186 if (!(fp->sr & PS_S))
1187 return;
1188
1189 console_verbose();
1190 printk("%s: %08x\n",str,nr);
1191 print_modules();
1192 printk("PC: [<%08lx>]",fp->pc);
1193 print_symbol(" %s\n", fp->pc);
1194 printk("\nSR: %04x SP: %p a2: %08lx\n",
1195 fp->sr, fp, fp->a2);
1196 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
1197 fp->d0, fp->d1, fp->d2, fp->d3);
1198 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
1199 fp->d4, fp->d5, fp->a0, fp->a1);
1200
1201 printk("Process %s (pid: %d, stackpage=%08lx)\n",
1202 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
1203 show_stack(NULL, (unsigned long *)fp);
1204 do_exit(SIGSEGV);
1205}
1206
1207/*
1208 * This function is called if an error occur while accessing
1209 * user-space from the fpsp040 code.
1210 */
1211asmlinkage void fpsp040_die(void)
1212{
1213 do_exit(SIGSEGV);
1214}
1215
1216#ifdef CONFIG_M68KFPU_EMU
1217asmlinkage void fpemu_signal(int signal, int code, void *addr)
1218{
1219 siginfo_t info;
1220
1221 info.si_signo = signal;
1222 info.si_errno = 0;
1223 info.si_code = code;
1224 info.si_addr = addr;
1225 force_sig_info(signal, &info, current);
1226}
1227#endif
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
new file mode 100644
index 000000000000..e58654f3f8dd
--- /dev/null
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -0,0 +1,95 @@
1/* ld script to make m68k Linux kernel */
2
3#include <asm-generic/vmlinux.lds.h>
4
5OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
6OUTPUT_ARCH(m68k)
7ENTRY(_start)
8jiffies = jiffies_64 + 4;
9SECTIONS
10{
11 . = 0x1000;
12 _text = .; /* Text and read-only data */
13 .text : {
14 *(.text)
15 SCHED_TEXT
16 *(.fixup)
17 *(.gnu.warning)
18 } :text = 0x4e75
19
20 . = ALIGN(16); /* Exception table */
21 __start___ex_table = .;
22 __ex_table : { *(__ex_table) }
23 __stop___ex_table = .;
24
25 RODATA
26
27 _etext = .; /* End of text section */
28
29 .data : { /* Data */
30 *(.data)
31 CONSTRUCTORS
32 }
33
34 .bss : { *(.bss) } /* BSS */
35
36 . = ALIGN(16);
37 .data.cacheline_aligned : { *(.data.cacheline_aligned) } :data
38
39 _edata = .; /* End of data section */
40
41 /* will be freed after init */
42 . = ALIGN(4096); /* Init code and data */
43 __init_begin = .;
44 .init.text : {
45 _sinittext = .;
46 *(.init.text)
47 _einittext = .;
48 }
49 .init.data : { *(.init.data) }
50 . = ALIGN(16);
51 __setup_start = .;
52 .init.setup : { *(.init.setup) }
53 __setup_end = .;
54 __initcall_start = .;
55 .initcall.init : {
56 *(.initcall1.init)
57 *(.initcall2.init)
58 *(.initcall3.init)
59 *(.initcall4.init)
60 *(.initcall5.init)
61 *(.initcall6.init)
62 *(.initcall7.init)
63 }
64 __initcall_end = .;
65 __con_initcall_start = .;
66 .con_initcall.init : { *(.con_initcall.init) }
67 __con_initcall_end = .;
68 SECURITY_INIT
69 . = ALIGN(8192);
70 __initramfs_start = .;
71 .init.ramfs : { *(.init.ramfs) }
72 __initramfs_end = .;
73 . = ALIGN(8192);
74 __init_end = .;
75
76 .data.init_task : { *(.data.init_task) } /* The initial task and kernel stack */
77
78 _end = . ;
79
80 /* Sections to be discarded */
81 /DISCARD/ : {
82 *(.exit.text)
83 *(.exit.data)
84 *(.exitcall.exit)
85 }
86
87 /* Stabs debugging sections. */
88 .stab 0 : { *(.stab) }
89 .stabstr 0 : { *(.stabstr) }
90 .stab.excl 0 : { *(.stab.excl) }
91 .stab.exclstr 0 : { *(.stab.exclstr) }
92 .stab.index 0 : { *(.stab.index) }
93 .stab.indexstr 0 : { *(.stab.indexstr) }
94 .comment 0 : { *(.comment) }
95}
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
new file mode 100644
index 000000000000..cc37e8d3c1e2
--- /dev/null
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -0,0 +1,95 @@
1/* ld script to make m68k Linux kernel */
2
3#include <asm-generic/vmlinux.lds.h>
4
5OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
6OUTPUT_ARCH(m68k)
7ENTRY(_start)
8jiffies = jiffies_64 + 4;
9SECTIONS
10{
11 . = 0xE004000;
12 _text = .; /* Text and read-only data */
13 .text : {
14 *(.head)
15 *(.text)
16 SCHED_TEXT
17 *(.fixup)
18 *(.gnu.warning)
19 } :text = 0x4e75
20 RODATA
21
22 _etext = .; /* End of text section */
23
24 .data : { /* Data */
25 *(.data)
26 CONSTRUCTORS
27 . = ALIGN(16); /* Exception table */
28 __start___ex_table = .;
29 *(__ex_table)
30 __stop___ex_table = .;
31 } :data
32 /* End of data goes *here* so that freeing init code works properly. */
33 _edata = .;
34
35 /* will be freed after init */
36 . = ALIGN(8192); /* Init code and data */
37__init_begin = .;
38 .init.text : {
39 _sinittext = .;
40 *(.init.text)
41 _einittext = .;
42 }
43 .init.data : { *(.init.data) }
44 . = ALIGN(16);
45 __setup_start = .;
46 .init.setup : { *(.init.setup) }
47 __setup_end = .;
48 __initcall_start = .;
49 .initcall.init : {
50 *(.initcall1.init)
51 *(.initcall2.init)
52 *(.initcall3.init)
53 *(.initcall4.init)
54 *(.initcall5.init)
55 *(.initcall6.init)
56 *(.initcall7.init)
57 }
58 __initcall_end = .;
59 __con_initcall_start = .;
60 .con_initcall.init : { *(.con_initcall.init) }
61 __con_initcall_end = .;
62 SECURITY_INIT
63 . = ALIGN(8192);
64 __initramfs_start = .;
65 .init.ramfs : { *(.init.ramfs) }
66 __initramfs_end = .;
67 . = ALIGN(8192);
68 __init_end = .;
69 .init.task : { *(init_task) }
70
71
72 .bss : { *(.bss) } /* BSS */
73
74 _end = . ;
75
76 /* Sections to be discarded */
77 /DISCARD/ : {
78 *(.exit.text)
79 *(.exit.data)
80 *(.exitcall.exit)
81 }
82
83 .crap : {
84 /* Stabs debugging sections. */
85 *(.stab)
86 *(.stabstr)
87 *(.stab.excl)
88 *(.stab.exclstr)
89 *(.stab.index)
90 *(.stab.indexstr)
91 *(.comment)
92 *(.note)
93 }
94
95}
diff --git a/arch/m68k/kernel/vmlinux.lds.S b/arch/m68k/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..497b924f3c86
--- /dev/null
+++ b/arch/m68k/kernel/vmlinux.lds.S
@@ -0,0 +1,11 @@
1#include <linux/config.h>
2PHDRS
3{
4 text PT_LOAD FILEHDR PHDRS FLAGS (7);
5 data PT_LOAD FLAGS (7);
6}
7#ifdef CONFIG_SUN3
8#include "vmlinux-sun3.lds"
9#else
10#include "vmlinux-std.lds"
11#endif
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
new file mode 100644
index 000000000000..34b6dbc29c85
--- /dev/null
+++ b/arch/m68k/lib/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for m68k-specific library files..
3#
4
5EXTRA_AFLAGS := -traditional
6
7lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
8 checksum.o memcmp.o memcpy.o memset.o semaphore.o
diff --git a/arch/m68k/lib/ashldi3.c b/arch/m68k/lib/ashldi3.c
new file mode 100644
index 000000000000..7729f33878d1
--- /dev/null
+++ b/arch/m68k/lib/ashldi3.c
@@ -0,0 +1,62 @@
1/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__)));
27
28struct DIstruct {SItype high, low;};
29
30typedef union
31{
32 struct DIstruct s;
33 DItype ll;
34} DIunion;
35
36DItype
37__ashldi3 (DItype u, word_type b)
38{
39 DIunion w;
40 word_type bm;
41 DIunion uu;
42
43 if (b == 0)
44 return u;
45
46 uu.ll = u;
47
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 w.s.low = 0;
52 w.s.high = (USItype)uu.s.low << -bm;
53 }
54 else
55 {
56 USItype carries = (USItype)uu.s.low >> bm;
57 w.s.low = (USItype)uu.s.low << b;
58 w.s.high = ((USItype)uu.s.high << b) | carries;
59 }
60
61 return w.ll;
62}
diff --git a/arch/m68k/lib/ashrdi3.c b/arch/m68k/lib/ashrdi3.c
new file mode 100644
index 000000000000..18ea5f7ed921
--- /dev/null
+++ b/arch/m68k/lib/ashrdi3.c
@@ -0,0 +1,63 @@
1/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__)));
27
28struct DIstruct {SItype high, low;};
29
30typedef union
31{
32 struct DIstruct s;
33 DItype ll;
34} DIunion;
35
36DItype
37__ashrdi3 (DItype u, word_type b)
38{
39 DIunion w;
40 word_type bm;
41 DIunion uu;
42
43 if (b == 0)
44 return u;
45
46 uu.ll = u;
47
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 /* w.s.high = 1..1 or 0..0 */
52 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
53 w.s.low = uu.s.high >> -bm;
54 }
55 else
56 {
57 USItype carries = (USItype)uu.s.high << bm;
58 w.s.high = uu.s.high >> b;
59 w.s.low = ((USItype)uu.s.low >> b) | carries;
60 }
61
62 return w.ll;
63}
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
new file mode 100644
index 000000000000..4a5c5445c610
--- /dev/null
+++ b/arch/m68k/lib/checksum.c
@@ -0,0 +1,422 @@
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 * IP/TCP/UDP checksumming routines
7 *
8 * Authors: Jorge Cwik, <jorge@laser.satlink.net>
9 * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
10 * Tom May, <ftom@netcom.com>
11 * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
12 * Lots of code moved from tcp.c and ip.c; see those files
13 * for more names.
14 *
15 * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
16 * Fixed some nasty bugs, causing some horrible crashes.
17 * A: At some points, the sum (%0) was used as
18 * length-counter instead of the length counter
19 * (%1). Thanks to Roman Hodek for pointing this out.
20 * B: GCC seems to mess up if one uses too many
21 * data-registers to hold input values and one tries to
22 * specify d0 and d1 as scratch registers. Letting gcc
23 * choose these registers itself solves the problem.
24 *
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version
28 * 2 of the License, or (at your option) any later version.
29 *
30 * 1998/8/31 Andreas Schwab:
31 * Zero out rest of buffer on exception in
32 * csum_partial_copy_from_user.
33 */
34
35#include <linux/module.h>
36#include <net/checksum.h>
37
38/*
39 * computes a partial checksum, e.g. for TCP/UDP fragments
40 */
41
42unsigned int
43csum_partial (const unsigned char *buff, int len, unsigned int sum)
44{
45 unsigned long tmp1, tmp2;
46 /*
47 * Experiments with ethernet and slip connections show that buff
48 * is aligned on either a 2-byte or 4-byte boundary.
49 */
50 __asm__("movel %2,%3\n\t"
51 "btst #1,%3\n\t" /* Check alignment */
52 "jeq 2f\n\t"
53 "subql #2,%1\n\t" /* buff%4==2: treat first word */
54 "jgt 1f\n\t"
55 "addql #2,%1\n\t" /* len was == 2, treat only rest */
56 "jra 4f\n"
57 "1:\t"
58 "addw %2@+,%0\n\t" /* add first word to sum */
59 "clrl %3\n\t"
60 "addxl %3,%0\n" /* add X bit */
61 "2:\t"
62 /* unrolled loop for the main part: do 8 longs at once */
63 "movel %1,%3\n\t" /* save len in tmp1 */
64 "lsrl #5,%1\n\t" /* len/32 */
65 "jeq 2f\n\t" /* not enough... */
66 "subql #1,%1\n"
67 "1:\t"
68 "movel %2@+,%4\n\t"
69 "addxl %4,%0\n\t"
70 "movel %2@+,%4\n\t"
71 "addxl %4,%0\n\t"
72 "movel %2@+,%4\n\t"
73 "addxl %4,%0\n\t"
74 "movel %2@+,%4\n\t"
75 "addxl %4,%0\n\t"
76 "movel %2@+,%4\n\t"
77 "addxl %4,%0\n\t"
78 "movel %2@+,%4\n\t"
79 "addxl %4,%0\n\t"
80 "movel %2@+,%4\n\t"
81 "addxl %4,%0\n\t"
82 "movel %2@+,%4\n\t"
83 "addxl %4,%0\n\t"
84 "dbra %1,1b\n\t"
85 "clrl %4\n\t"
86 "addxl %4,%0\n\t" /* add X bit */
87 "clrw %1\n\t"
88 "subql #1,%1\n\t"
89 "jcc 1b\n"
90 "2:\t"
91 "movel %3,%1\n\t" /* restore len from tmp1 */
92 "andw #0x1c,%3\n\t" /* number of rest longs */
93 "jeq 4f\n\t"
94 "lsrw #2,%3\n\t"
95 "subqw #1,%3\n"
96 "3:\t"
97 /* loop for rest longs */
98 "movel %2@+,%4\n\t"
99 "addxl %4,%0\n\t"
100 "dbra %3,3b\n\t"
101 "clrl %4\n\t"
102 "addxl %4,%0\n" /* add X bit */
103 "4:\t"
104 /* now check for rest bytes that do not fit into longs */
105 "andw #3,%1\n\t"
106 "jeq 7f\n\t"
107 "clrl %4\n\t" /* clear tmp2 for rest bytes */
108 "subqw #2,%1\n\t"
109 "jlt 5f\n\t"
110 "movew %2@+,%4\n\t" /* have rest >= 2: get word */
111 "swap %4\n\t" /* into bits 16..31 */
112 "tstw %1\n\t" /* another byte? */
113 "jeq 6f\n"
114 "5:\t"
115 "moveb %2@,%4\n\t" /* have odd rest: get byte */
116 "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */
117 "6:\t"
118 "addl %4,%0\n\t" /* now add rest long to sum */
119 "clrl %4\n\t"
120 "addxl %4,%0\n" /* add X bit */
121 "7:\t"
122 : "=d" (sum), "=d" (len), "=a" (buff),
123 "=&d" (tmp1), "=&d" (tmp2)
124 : "0" (sum), "1" (len), "2" (buff)
125 );
126 return(sum);
127}
128
129EXPORT_SYMBOL(csum_partial);
130
131
132/*
133 * copy from user space while checksumming, with exception handling.
134 */
135
136unsigned int
137csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
138 int len, int sum, int *csum_err)
139{
140 /*
141 * GCC doesn't like more than 10 operands for the asm
142 * statements so we have to use tmp2 for the error
143 * code.
144 */
145 unsigned long tmp1, tmp2;
146
147 __asm__("movel %2,%4\n\t"
148 "btst #1,%4\n\t" /* Check alignment */
149 "jeq 2f\n\t"
150 "subql #2,%1\n\t" /* buff%4==2: treat first word */
151 "jgt 1f\n\t"
152 "addql #2,%1\n\t" /* len was == 2, treat only rest */
153 "jra 4f\n"
154 "1:\n"
155 "10:\t"
156 "movesw %2@+,%4\n\t" /* add first word to sum */
157 "addw %4,%0\n\t"
158 "movew %4,%3@+\n\t"
159 "clrl %4\n\t"
160 "addxl %4,%0\n" /* add X bit */
161 "2:\t"
162 /* unrolled loop for the main part: do 8 longs at once */
163 "movel %1,%4\n\t" /* save len in tmp1 */
164 "lsrl #5,%1\n\t" /* len/32 */
165 "jeq 2f\n\t" /* not enough... */
166 "subql #1,%1\n"
167 "1:\n"
168 "11:\t"
169 "movesl %2@+,%5\n\t"
170 "addxl %5,%0\n\t"
171 "movel %5,%3@+\n\t"
172 "12:\t"
173 "movesl %2@+,%5\n\t"
174 "addxl %5,%0\n\t"
175 "movel %5,%3@+\n\t"
176 "13:\t"
177 "movesl %2@+,%5\n\t"
178 "addxl %5,%0\n\t"
179 "movel %5,%3@+\n\t"
180 "14:\t"
181 "movesl %2@+,%5\n\t"
182 "addxl %5,%0\n\t"
183 "movel %5,%3@+\n\t"
184 "15:\t"
185 "movesl %2@+,%5\n\t"
186 "addxl %5,%0\n\t"
187 "movel %5,%3@+\n\t"
188 "16:\t"
189 "movesl %2@+,%5\n\t"
190 "addxl %5,%0\n\t"
191 "movel %5,%3@+\n\t"
192 "17:\t"
193 "movesl %2@+,%5\n\t"
194 "addxl %5,%0\n\t"
195 "movel %5,%3@+\n\t"
196 "18:\t"
197 "movesl %2@+,%5\n\t"
198 "addxl %5,%0\n\t"
199 "movel %5,%3@+\n\t"
200 "dbra %1,1b\n\t"
201 "clrl %5\n\t"
202 "addxl %5,%0\n\t" /* add X bit */
203 "clrw %1\n\t"
204 "subql #1,%1\n\t"
205 "jcc 1b\n"
206 "2:\t"
207 "movel %4,%1\n\t" /* restore len from tmp1 */
208 "andw #0x1c,%4\n\t" /* number of rest longs */
209 "jeq 4f\n\t"
210 "lsrw #2,%4\n\t"
211 "subqw #1,%4\n"
212 "3:\n"
213 /* loop for rest longs */
214 "19:\t"
215 "movesl %2@+,%5\n\t"
216 "addxl %5,%0\n\t"
217 "movel %5,%3@+\n\t"
218 "dbra %4,3b\n\t"
219 "clrl %5\n\t"
220 "addxl %5,%0\n" /* add X bit */
221 "4:\t"
222 /* now check for rest bytes that do not fit into longs */
223 "andw #3,%1\n\t"
224 "jeq 7f\n\t"
225 "clrl %5\n\t" /* clear tmp2 for rest bytes */
226 "subqw #2,%1\n\t"
227 "jlt 5f\n\t"
228 "20:\t"
229 "movesw %2@+,%5\n\t" /* have rest >= 2: get word */
230 "movew %5,%3@+\n\t"
231 "swap %5\n\t" /* into bits 16..31 */
232 "tstw %1\n\t" /* another byte? */
233 "jeq 6f\n"
234 "5:\n"
235 "21:\t"
236 "movesb %2@,%5\n\t" /* have odd rest: get byte */
237 "moveb %5,%3@+\n\t"
238 "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */
239 "6:\t"
240 "addl %5,%0\n\t" /* now add rest long to sum */
241 "clrl %5\n\t"
242 "addxl %5,%0\n\t" /* add X bit */
243 "7:\t"
244 "clrl %5\n" /* no error - clear return value */
245 "8:\n"
246 ".section .fixup,\"ax\"\n"
247 ".even\n"
248 /* If any exception occurs zero out the rest.
249 Similarities with the code above are intentional :-) */
250 "90:\t"
251 "clrw %3@+\n\t"
252 "movel %1,%4\n\t"
253 "lsrl #5,%1\n\t"
254 "jeq 1f\n\t"
255 "subql #1,%1\n"
256 "91:\t"
257 "clrl %3@+\n"
258 "92:\t"
259 "clrl %3@+\n"
260 "93:\t"
261 "clrl %3@+\n"
262 "94:\t"
263 "clrl %3@+\n"
264 "95:\t"
265 "clrl %3@+\n"
266 "96:\t"
267 "clrl %3@+\n"
268 "97:\t"
269 "clrl %3@+\n"
270 "98:\t"
271 "clrl %3@+\n\t"
272 "dbra %1,91b\n\t"
273 "clrw %1\n\t"
274 "subql #1,%1\n\t"
275 "jcc 91b\n"
276 "1:\t"
277 "movel %4,%1\n\t"
278 "andw #0x1c,%4\n\t"
279 "jeq 1f\n\t"
280 "lsrw #2,%4\n\t"
281 "subqw #1,%4\n"
282 "99:\t"
283 "clrl %3@+\n\t"
284 "dbra %4,99b\n\t"
285 "1:\t"
286 "andw #3,%1\n\t"
287 "jeq 9f\n"
288 "100:\t"
289 "clrw %3@+\n\t"
290 "tstw %1\n\t"
291 "jeq 9f\n"
292 "101:\t"
293 "clrb %3@+\n"
294 "9:\t"
295#define STR(X) STR1(X)
296#define STR1(X) #X
297 "moveq #-" STR(EFAULT) ",%5\n\t"
298 "jra 8b\n"
299 ".previous\n"
300 ".section __ex_table,\"a\"\n"
301 ".long 10b,90b\n"
302 ".long 11b,91b\n"
303 ".long 12b,92b\n"
304 ".long 13b,93b\n"
305 ".long 14b,94b\n"
306 ".long 15b,95b\n"
307 ".long 16b,96b\n"
308 ".long 17b,97b\n"
309 ".long 18b,98b\n"
310 ".long 19b,99b\n"
311 ".long 20b,100b\n"
312 ".long 21b,101b\n"
313 ".previous"
314 : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
315 "=&d" (tmp1), "=d" (tmp2)
316 : "0" (sum), "1" (len), "2" (src), "3" (dst)
317 );
318
319 *csum_err = tmp2;
320
321 return(sum);
322}
323
324/*
325 * copy from kernel space while checksumming, otherwise like csum_partial
326 */
327
328unsigned int
329csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst, int len, int sum)
330{
331 unsigned long tmp1, tmp2;
332 __asm__("movel %2,%4\n\t"
333 "btst #1,%4\n\t" /* Check alignment */
334 "jeq 2f\n\t"
335 "subql #2,%1\n\t" /* buff%4==2: treat first word */
336 "jgt 1f\n\t"
337 "addql #2,%1\n\t" /* len was == 2, treat only rest */
338 "jra 4f\n"
339 "1:\t"
340 "movew %2@+,%4\n\t" /* add first word to sum */
341 "addw %4,%0\n\t"
342 "movew %4,%3@+\n\t"
343 "clrl %4\n\t"
344 "addxl %4,%0\n" /* add X bit */
345 "2:\t"
346 /* unrolled loop for the main part: do 8 longs at once */
347 "movel %1,%4\n\t" /* save len in tmp1 */
348 "lsrl #5,%1\n\t" /* len/32 */
349 "jeq 2f\n\t" /* not enough... */
350 "subql #1,%1\n"
351 "1:\t"
352 "movel %2@+,%5\n\t"
353 "addxl %5,%0\n\t"
354 "movel %5,%3@+\n\t"
355 "movel %2@+,%5\n\t"
356 "addxl %5,%0\n\t"
357 "movel %5,%3@+\n\t"
358 "movel %2@+,%5\n\t"
359 "addxl %5,%0\n\t"
360 "movel %5,%3@+\n\t"
361 "movel %2@+,%5\n\t"
362 "addxl %5,%0\n\t"
363 "movel %5,%3@+\n\t"
364 "movel %2@+,%5\n\t"
365 "addxl %5,%0\n\t"
366 "movel %5,%3@+\n\t"
367 "movel %2@+,%5\n\t"
368 "addxl %5,%0\n\t"
369 "movel %5,%3@+\n\t"
370 "movel %2@+,%5\n\t"
371 "addxl %5,%0\n\t"
372 "movel %5,%3@+\n\t"
373 "movel %2@+,%5\n\t"
374 "addxl %5,%0\n\t"
375 "movel %5,%3@+\n\t"
376 "dbra %1,1b\n\t"
377 "clrl %5\n\t"
378 "addxl %5,%0\n\t" /* add X bit */
379 "clrw %1\n\t"
380 "subql #1,%1\n\t"
381 "jcc 1b\n"
382 "2:\t"
383 "movel %4,%1\n\t" /* restore len from tmp1 */
384 "andw #0x1c,%4\n\t" /* number of rest longs */
385 "jeq 4f\n\t"
386 "lsrw #2,%4\n\t"
387 "subqw #1,%4\n"
388 "3:\t"
389 /* loop for rest longs */
390 "movel %2@+,%5\n\t"
391 "addxl %5,%0\n\t"
392 "movel %5,%3@+\n\t"
393 "dbra %4,3b\n\t"
394 "clrl %5\n\t"
395 "addxl %5,%0\n" /* add X bit */
396 "4:\t"
397 /* now check for rest bytes that do not fit into longs */
398 "andw #3,%1\n\t"
399 "jeq 7f\n\t"
400 "clrl %5\n\t" /* clear tmp2 for rest bytes */
401 "subqw #2,%1\n\t"
402 "jlt 5f\n\t"
403 "movew %2@+,%5\n\t" /* have rest >= 2: get word */
404 "movew %5,%3@+\n\t"
405 "swap %5\n\t" /* into bits 16..31 */
406 "tstw %1\n\t" /* another byte? */
407 "jeq 6f\n"
408 "5:\t"
409 "moveb %2@,%5\n\t" /* have odd rest: get byte */
410 "moveb %5,%3@+\n\t"
411 "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */
412 "6:\t"
413 "addl %5,%0\n\t" /* now add rest long to sum */
414 "clrl %5\n\t"
415 "addxl %5,%0\n" /* add X bit */
416 "7:\t"
417 : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
418 "=&d" (tmp1), "=&d" (tmp2)
419 : "0" (sum), "1" (len), "2" (src), "3" (dst)
420 );
421 return(sum);
422}
diff --git a/arch/m68k/lib/lshrdi3.c b/arch/m68k/lib/lshrdi3.c
new file mode 100644
index 000000000000..d06442d3a328
--- /dev/null
+++ b/arch/m68k/lib/lshrdi3.c
@@ -0,0 +1,62 @@
1/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__)));
27
28struct DIstruct {SItype high, low;};
29
30typedef union
31{
32 struct DIstruct s;
33 DItype ll;
34} DIunion;
35
36DItype
37__lshrdi3 (DItype u, word_type b)
38{
39 DIunion w;
40 word_type bm;
41 DIunion uu;
42
43 if (b == 0)
44 return u;
45
46 uu.ll = u;
47
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 w.s.high = 0;
52 w.s.low = (USItype)uu.s.high >> -bm;
53 }
54 else
55 {
56 USItype carries = (USItype)uu.s.high << bm;
57 w.s.high = (USItype)uu.s.high >> b;
58 w.s.low = ((USItype)uu.s.low >> b) | carries;
59 }
60
61 return w.ll;
62}
diff --git a/arch/m68k/lib/memcmp.c b/arch/m68k/lib/memcmp.c
new file mode 100644
index 000000000000..f4796febb773
--- /dev/null
+++ b/arch/m68k/lib/memcmp.c
@@ -0,0 +1,11 @@
1#include <linux/types.h>
2
3int memcmp(const void * cs,const void * ct,size_t count)
4{
5 const unsigned char *su1, *su2;
6
7 for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
8 if (*su1 != *su2)
9 return((*su1 < *su2) ? -1 : +1);
10 return(0);
11}
diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c
new file mode 100644
index 000000000000..73e181823d9b
--- /dev/null
+++ b/arch/m68k/lib/memcpy.c
@@ -0,0 +1,75 @@
1#include <linux/types.h>
2
3void * memcpy(void * to, const void * from, size_t n)
4{
5 void *xto = to;
6 size_t temp, temp1;
7
8 if (!n)
9 return xto;
10 if ((long) to & 1)
11 {
12 char *cto = to;
13 const char *cfrom = from;
14 *cto++ = *cfrom++;
15 to = cto;
16 from = cfrom;
17 n--;
18 }
19 if (n > 2 && (long) to & 2)
20 {
21 short *sto = to;
22 const short *sfrom = from;
23 *sto++ = *sfrom++;
24 to = sto;
25 from = sfrom;
26 n -= 2;
27 }
28 temp = n >> 2;
29 if (temp)
30 {
31 long *lto = to;
32 const long *lfrom = from;
33
34 __asm__ __volatile__("movel %2,%3\n\t"
35 "andw #7,%3\n\t"
36 "lsrl #3,%2\n\t"
37 "negw %3\n\t"
38 "jmp %%pc@(1f,%3:w:2)\n\t"
39 "4:\t"
40 "movel %0@+,%1@+\n\t"
41 "movel %0@+,%1@+\n\t"
42 "movel %0@+,%1@+\n\t"
43 "movel %0@+,%1@+\n\t"
44 "movel %0@+,%1@+\n\t"
45 "movel %0@+,%1@+\n\t"
46 "movel %0@+,%1@+\n\t"
47 "movel %0@+,%1@+\n\t"
48 "1:\t"
49 "dbra %2,4b\n\t"
50 "clrw %2\n\t"
51 "subql #1,%2\n\t"
52 "jpl 4b\n\t"
53 : "=a" (lfrom), "=a" (lto), "=d" (temp),
54 "=&d" (temp1)
55 : "0" (lfrom), "1" (lto), "2" (temp)
56 );
57 to = lto;
58 from = lfrom;
59 }
60 if (n & 2)
61 {
62 short *sto = to;
63 const short *sfrom = from;
64 *sto++ = *sfrom++;
65 to = sto;
66 from = sfrom;
67 }
68 if (n & 1)
69 {
70 char *cto = to;
71 const char *cfrom = from;
72 *cto = *cfrom;
73 }
74 return xto;
75}
diff --git a/arch/m68k/lib/memset.c b/arch/m68k/lib/memset.c
new file mode 100644
index 000000000000..d55fdb2ee9d3
--- /dev/null
+++ b/arch/m68k/lib/memset.c
@@ -0,0 +1,68 @@
1#include <linux/types.h>
2
3void * memset(void * s, int c, size_t count)
4{
5 void *xs = s;
6 size_t temp, temp1;
7
8 if (!count)
9 return xs;
10 c &= 0xff;
11 c |= c << 8;
12 c |= c << 16;
13 if ((long) s & 1)
14 {
15 char *cs = s;
16 *cs++ = c;
17 s = cs;
18 count--;
19 }
20 if (count > 2 && (long) s & 2)
21 {
22 short *ss = s;
23 *ss++ = c;
24 s = ss;
25 count -= 2;
26 }
27 temp = count >> 2;
28 if (temp)
29 {
30 long *ls = s;
31
32 __asm__ __volatile__("movel %1,%2\n\t"
33 "andw #7,%2\n\t"
34 "lsrl #3,%1\n\t"
35 "negw %2\n\t"
36 "jmp %%pc@(2f,%2:w:2)\n\t"
37 "1:\t"
38 "movel %3,%0@+\n\t"
39 "movel %3,%0@+\n\t"
40 "movel %3,%0@+\n\t"
41 "movel %3,%0@+\n\t"
42 "movel %3,%0@+\n\t"
43 "movel %3,%0@+\n\t"
44 "movel %3,%0@+\n\t"
45 "movel %3,%0@+\n\t"
46 "2:\t"
47 "dbra %1,1b\n\t"
48 "clrw %1\n\t"
49 "subql #1,%1\n\t"
50 "jpl 1b\n\t"
51 : "=a" (ls), "=d" (temp), "=&d" (temp1)
52 : "d" (c), "0" (ls), "1" (temp)
53 );
54 s = ls;
55 }
56 if (count & 2)
57 {
58 short *ss = s;
59 *ss++ = c;
60 s = ss;
61 }
62 if (count & 1)
63 {
64 char *cs = s;
65 *cs = c;
66 }
67 return xs;
68}
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
new file mode 100644
index 000000000000..be4f275649e3
--- /dev/null
+++ b/arch/m68k/lib/muldi3.c
@@ -0,0 +1,63 @@
1/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
2 gcc-2.7.2.3/longlong.h which is: */
3/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#define BITS_PER_UNIT 8
23
24#define umul_ppmm(w1, w0, u, v) \
25 __asm__ ("mulu%.l %3,%1:%0" \
26 : "=d" ((USItype)(w0)), \
27 "=d" ((USItype)(w1)) \
28 : "%0" ((USItype)(u)), \
29 "dmi" ((USItype)(v)))
30
31#define __umulsidi3(u, v) \
32 ({DIunion __w; \
33 umul_ppmm (__w.s.high, __w.s.low, u, v); \
34 __w.ll; })
35
36typedef int SItype __attribute__ ((mode (SI)));
37typedef unsigned int USItype __attribute__ ((mode (SI)));
38typedef int DItype __attribute__ ((mode (DI)));
39typedef int word_type __attribute__ ((mode (__word__)));
40
41struct DIstruct {SItype high, low;};
42
43typedef union
44{
45 struct DIstruct s;
46 DItype ll;
47} DIunion;
48
49DItype
50__muldi3 (DItype u, DItype v)
51{
52 DIunion w;
53 DIunion uu, vv;
54
55 uu.ll = u,
56 vv.ll = v;
57
58 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
59 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
60 + (USItype) uu.s.high * (USItype) vv.s.low);
61
62 return w.ll;
63}
diff --git a/arch/m68k/lib/semaphore.S b/arch/m68k/lib/semaphore.S
new file mode 100644
index 000000000000..0215624c1602
--- /dev/null
+++ b/arch/m68k/lib/semaphore.S
@@ -0,0 +1,53 @@
1/*
2 * linux/arch/m68k/lib/semaphore.S
3 *
4 * Copyright (C) 1996 Linus Torvalds
5 *
6 * m68k version by Andreas Schwab
7 */
8
9#include <linux/linkage.h>
10#include <asm/semaphore.h>
11
12/*
13 * The semaphore operations have a special calling sequence that
14 * allow us to do a simpler in-line version of them. These routines
15 * need to convert that sequence back into the C sequence when
16 * there is contention on the semaphore.
17 */
18ENTRY(__down_failed)
19 moveml %a0/%d0/%d1,-(%sp)
20 movel %a1,-(%sp)
21 jbsr __down
22 movel (%sp)+,%a1
23 moveml (%sp)+,%a0/%d0/%d1
24 rts
25
26ENTRY(__down_failed_interruptible)
27 movel %a0,-(%sp)
28 movel %d1,-(%sp)
29 movel %a1,-(%sp)
30 jbsr __down_interruptible
31 movel (%sp)+,%a1
32 movel (%sp)+,%d1
33 movel (%sp)+,%a0
34 rts
35
36ENTRY(__down_failed_trylock)
37 movel %a0,-(%sp)
38 movel %d1,-(%sp)
39 movel %a1,-(%sp)
40 jbsr __down_trylock
41 movel (%sp)+,%a1
42 movel (%sp)+,%d1
43 movel (%sp)+,%a0
44 rts
45
46ENTRY(__up_wakeup)
47 moveml %a0/%d0/%d1,-(%sp)
48 movel %a1,-(%sp)
49 jbsr __up
50 movel (%sp)+,%a1
51 moveml (%sp)+,%a0/%d0/%d1
52 rts
53
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
new file mode 100644
index 000000000000..995a09d912f5
--- /dev/null
+++ b/arch/m68k/mac/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for Linux arch/m68k/mac source directory
3#
4
5obj-y := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
6 baboon.o macboing.o debug.o misc.o mac_ksyms.o
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
new file mode 100644
index 000000000000..b19b7dd9bd21
--- /dev/null
+++ b/arch/m68k/mac/baboon.c
@@ -0,0 +1,126 @@
1/*
2 * Baboon Custom IC Management
3 *
4 * The Baboon custom IC controls the IDE, PCMCIA and media bay on the
5 * PowerBook 190. It multiplexes multiple interrupt sources onto the
6 * Nubus slot $C interrupt.
7 */
8
9#include <linux/types.h>
10#include <linux/kernel.h>
11#include <linux/mm.h>
12#include <linux/delay.h>
13#include <linux/init.h>
14#include <linux/ide.h>
15
16#include <asm/traps.h>
17#include <asm/bootinfo.h>
18#include <asm/macintosh.h>
19#include <asm/macints.h>
20#include <asm/mac_baboon.h>
21
22/* #define DEBUG_BABOON */
23/* #define DEBUG_IRQS */
24
25int baboon_present,baboon_active;
26volatile struct baboon *baboon;
27
28irqreturn_t baboon_irq(int, void *, struct pt_regs *);
29
30#if 0
31extern int macide_ack_intr(struct ata_channel *);
32#endif
33
34/*
35 * Baboon initialization.
36 */
37
38void __init baboon_init(void)
39{
40 if (macintosh_config->ident != MAC_MODEL_PB190) {
41 baboon = NULL;
42 baboon_present = 0;
43 return;
44 }
45
46 baboon = (struct baboon *) BABOON_BASE;
47 baboon_present = 1;
48 baboon_active = 0;
49
50 printk("Baboon detected at %p\n", baboon);
51}
52
53/*
54 * Register the Baboon interrupt dispatcher on nubus slot $C.
55 */
56
57void __init baboon_register_interrupts(void)
58{
59 request_irq(IRQ_NUBUS_C, baboon_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
60 "baboon", (void *) baboon);
61}
62
63/*
64 * Baboon interrupt handler. This works a lot like a VIA.
65 */
66
67irqreturn_t baboon_irq(int irq, void *dev_id, struct pt_regs *regs)
68{
69 int irq_bit,i;
70 unsigned char events;
71
72#ifdef DEBUG_IRQS
73 printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X active %02X\n",
74 (uint) baboon->mb_control, (uint) baboon->mb_ifr,
75 (uint) baboon->mb_status, baboon_active);
76#endif
77
78 if (!(events = baboon->mb_ifr & 0x07))
79 return IRQ_NONE;
80
81 for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
82 if (events & irq_bit/* & baboon_active*/) {
83 baboon_active &= ~irq_bit;
84 mac_do_irq_list(IRQ_BABOON_0 + i, regs);
85 baboon_active |= irq_bit;
86 baboon->mb_ifr &= ~irq_bit;
87 }
88 }
89#if 0
90 if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
91 /* for now we need to smash all interrupts */
92 baboon->mb_ifr &= ~events;
93#endif
94 return IRQ_HANDLED;
95}
96
97void baboon_irq_enable(int irq) {
98 int irq_idx = IRQ_IDX(irq);
99
100#ifdef DEBUG_IRQUSE
101 printk("baboon_irq_enable(%d)\n", irq);
102#endif
103 baboon_active |= (1 << irq_idx);
104}
105
106void baboon_irq_disable(int irq) {
107 int irq_idx = IRQ_IDX(irq);
108
109#ifdef DEBUG_IRQUSE
110 printk("baboon_irq_disable(%d)\n", irq);
111#endif
112 baboon_active &= ~(1 << irq_idx);
113}
114
115void baboon_irq_clear(int irq) {
116 int irq_idx = IRQ_IDX(irq);
117
118 baboon->mb_ifr &= ~(1 << irq_idx);
119}
120
121int baboon_irq_pending(int irq)
122{
123 int irq_idx = IRQ_IDX(irq);
124
125 return baboon->mb_ifr & (1 << irq_idx);
126}
diff --git a/arch/m68k/mac/bootparse.c b/arch/m68k/mac/bootparse.c
new file mode 100644
index 000000000000..36d223609823
--- /dev/null
+++ b/arch/m68k/mac/bootparse.c
@@ -0,0 +1,122 @@
1#include <linux/string.h>
2#include <linux/kernel.h>
3#include <linux/sched.h>
4#include <asm/irq.h>
5#include <asm/setup.h>
6#include <asm/bootinfo.h>
7#include <asm/macintosh.h>
8
9/*
10 * Booter vars
11 */
12
13int boothowto;
14int _boothowto;
15
16/*
17 * Called early to parse the environment (passed to us from the booter)
18 * into a bootinfo struct. Will die as soon as we have our own booter
19 */
20
21#define atol(x) simple_strtoul(x,NULL,0)
22
23void parse_booter(char *env)
24{
25 char *name;
26 char *value;
27#if 0
28 while(0 && *env)
29#else
30 while(*env)
31#endif
32 {
33 name=env;
34 value=name;
35 while(*value!='='&&*value)
36 value++;
37 if(*value=='=')
38 *value++=0;
39 env=value;
40 while(*env)
41 env++;
42 env++;
43#if 0
44 if(strcmp(name,"VIDEO_ADDR")==0)
45 mac_mch.videoaddr=atol(value);
46 if(strcmp(name,"ROW_BYTES")==0)
47 mac_mch.videorow=atol(value);
48 if(strcmp(name,"SCREEN_DEPTH")==0)
49 mac_mch.videodepth=atol(value);
50 if(strcmp(name,"DIMENSIONS")==0)
51 mac_mch.dimensions=atol(value);
52#endif
53 if(strcmp(name,"BOOTTIME")==0)
54 mac_bi_data.boottime=atol(value);
55 if(strcmp(name,"GMTBIAS")==0)
56 mac_bi_data.gmtbias=atol(value);
57 if(strcmp(name,"BOOTERVER")==0)
58 mac_bi_data.bootver=atol(value);
59 if(strcmp(name,"MACOS_VIDEO")==0)
60 mac_bi_data.videological=atol(value);
61 if(strcmp(name,"MACOS_SCC")==0)
62 mac_bi_data.sccbase=atol(value);
63 if(strcmp(name,"MACHINEID")==0)
64 mac_bi_data.id=atol(value);
65 if(strcmp(name,"MEMSIZE")==0)
66 mac_bi_data.memsize=atol(value);
67 if(strcmp(name,"SERIAL_MODEM_FLAGS")==0)
68 mac_bi_data.serialmf=atol(value);
69 if(strcmp(name,"SERIAL_MODEM_HSKICLK")==0)
70 mac_bi_data.serialhsk=atol(value);
71 if(strcmp(name,"SERIAL_MODEM_GPICLK")==0)
72 mac_bi_data.serialgpi=atol(value);
73 if(strcmp(name,"SERIAL_PRINT_FLAGS")==0)
74 mac_bi_data.printmf=atol(value);
75 if(strcmp(name,"SERIAL_PRINT_HSKICLK")==0)
76 mac_bi_data.printhsk=atol(value);
77 if(strcmp(name,"SERIAL_PRINT_GPICLK")==0)
78 mac_bi_data.printgpi=atol(value);
79 if(strcmp(name,"PROCESSOR")==0)
80 mac_bi_data.cpuid=atol(value);
81 if(strcmp(name,"ROMBASE")==0)
82 mac_bi_data.rombase=atol(value);
83 if(strcmp(name,"TIMEDBRA")==0)
84 mac_bi_data.timedbra=atol(value);
85 if(strcmp(name,"ADBDELAY")==0)
86 mac_bi_data.adbdelay=atol(value);
87 }
88#if 0 /* XXX: TODO with m68k_mach_* */
89 /* Fill in the base stuff */
90 boot_info.machtype=MACH_MAC;
91 /* Read this from the macinfo we got ! */
92/* boot_info.cputype=CPU_68020|FPUB_68881;*/
93/* boot_info.memory[0].addr=0;*/
94/* boot_info.memory[0].size=((mac_bi_data.id>>7)&31)<<20;*/
95 boot_info.num_memory=1; /* On a MacII */
96 boot_info.ramdisk_size=0; /* For now */
97 *boot_info.command_line=0;
98#endif
99 }
100
101
102void print_booter(char *env)
103{
104 char *name;
105 char *value;
106 while(*env)
107 {
108 name=env;
109 value=name;
110 while(*value!='='&&*value)
111 value++;
112 if(*value=='=')
113 *value++=0;
114 env=value;
115 while(*env)
116 env++;
117 env++;
118 printk("%s=%s\n", name,value);
119 }
120 }
121
122
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
new file mode 100644
index 000000000000..cd19cbb213e8
--- /dev/null
+++ b/arch/m68k/mac/config.c
@@ -0,0 +1,902 @@
1/*
2 * linux/arch/m68k/mac/config.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive
6 * for more details.
7 */
8
9/*
10 * Miscellaneous linux stuff
11 */
12
13#include <linux/config.h>
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/mm.h>
17#include <linux/tty.h>
18#include <linux/console.h>
19#include <linux/interrupt.h>
20/* keyb */
21#include <linux/random.h>
22#include <linux/delay.h>
23/* keyb */
24#include <linux/init.h>
25#include <linux/vt_kern.h>
26
27#define BOOTINFO_COMPAT_1_0
28#include <asm/setup.h>
29#include <asm/bootinfo.h>
30
31#include <asm/system.h>
32#include <asm/io.h>
33#include <asm/irq.h>
34#include <asm/pgtable.h>
35#include <asm/rtc.h>
36#include <asm/machdep.h>
37
38#include <asm/macintosh.h>
39#include <asm/macints.h>
40#include <asm/machw.h>
41
42#include <asm/mac_iop.h>
43#include <asm/mac_via.h>
44#include <asm/mac_oss.h>
45#include <asm/mac_psc.h>
46
47/* Mac bootinfo struct */
48
49struct mac_booter_data mac_bi_data;
50int mac_bisize = sizeof mac_bi_data;
51
52struct mac_hw_present mac_hw_present;
53
54/* New m68k bootinfo stuff and videobase */
55
56extern int m68k_num_memory;
57extern struct mem_info m68k_memory[NUM_MEMINFO];
58
59extern struct mem_info m68k_ramdisk;
60
61extern char m68k_command_line[CL_SIZE];
62
63void *mac_env; /* Loaded by the boot asm */
64
65/* The phys. video addr. - might be bogus on some machines */
66unsigned long mac_orig_videoaddr;
67
68/* Mac specific timer functions */
69extern unsigned long mac_gettimeoffset (void);
70extern int mac_hwclk (int, struct rtc_time *);
71extern int mac_set_clock_mmss (unsigned long);
72extern int show_mac_interrupts(struct seq_file *, void *);
73extern void iop_preinit(void);
74extern void iop_init(void);
75extern void via_init(void);
76extern void via_init_clock(irqreturn_t (*func)(int, void *, struct pt_regs *));
77extern void via_flush_cache(void);
78extern void oss_init(void);
79extern void psc_init(void);
80extern void baboon_init(void);
81
82extern void mac_mksound(unsigned int, unsigned int);
83
84extern void nubus_sweep_video(void);
85
86/* Mac specific debug functions (in debug.c) */
87extern void mac_debug_init(void);
88extern void mac_debugging_long(int, long);
89
90static void mac_get_model(char *str);
91
92void mac_bang(int irq, void *vector, struct pt_regs *p)
93{
94 printk(KERN_INFO "Resetting ...\n");
95 mac_reset();
96}
97
98static void mac_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
99{
100 via_init_clock(vector);
101}
102
103#if 0
104void mac_waitbut (void)
105{
106 ;
107}
108#endif
109
110extern irqreturn_t mac_default_handler(int, void *, struct pt_regs *);
111
112irqreturn_t (*mac_handlers[8])(int, void *, struct pt_regs *)=
113{
114 mac_default_handler,
115 mac_default_handler,
116 mac_default_handler,
117 mac_default_handler,
118 mac_default_handler,
119 mac_default_handler,
120 mac_default_handler,
121 mac_default_handler
122};
123
124/*
125 * Parse a Macintosh-specific record in the bootinfo
126 */
127
128int __init mac_parse_bootinfo(const struct bi_record *record)
129{
130 int unknown = 0;
131 const u_long *data = record->data;
132
133 switch (record->tag) {
134 case BI_MAC_MODEL:
135 mac_bi_data.id = *data;
136 break;
137 case BI_MAC_VADDR:
138 mac_bi_data.videoaddr = *data;
139 break;
140 case BI_MAC_VDEPTH:
141 mac_bi_data.videodepth = *data;
142 break;
143 case BI_MAC_VROW:
144 mac_bi_data.videorow = *data;
145 break;
146 case BI_MAC_VDIM:
147 mac_bi_data.dimensions = *data;
148 break;
149 case BI_MAC_VLOGICAL:
150 mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
151 mac_orig_videoaddr = *data;
152 break;
153 case BI_MAC_SCCBASE:
154 mac_bi_data.sccbase = *data;
155 break;
156 case BI_MAC_BTIME:
157 mac_bi_data.boottime = *data;
158 break;
159 case BI_MAC_GMTBIAS:
160 mac_bi_data.gmtbias = *data;
161 break;
162 case BI_MAC_MEMSIZE:
163 mac_bi_data.memsize = *data;
164 break;
165 case BI_MAC_CPUID:
166 mac_bi_data.cpuid = *data;
167 break;
168 case BI_MAC_ROMBASE:
169 mac_bi_data.rombase = *data;
170 break;
171 default:
172 unknown = 1;
173 }
174 return(unknown);
175}
176
177/*
178 * Flip into 24bit mode for an instant - flushes the L2 cache card. We
179 * have to disable interrupts for this. Our IRQ handlers will crap
180 * themselves if they take an IRQ in 24bit mode!
181 */
182
183static void mac_cache_card_flush(int writeback)
184{
185 unsigned long flags;
186 local_irq_save(flags);
187 via_flush_cache();
188 local_irq_restore(flags);
189}
190
191void __init config_mac(void)
192{
193 if (!MACH_IS_MAC) {
194 printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
195 }
196
197 mach_sched_init = mac_sched_init;
198 mach_init_IRQ = mac_init_IRQ;
199 mach_request_irq = mac_request_irq;
200 mach_free_irq = mac_free_irq;
201 enable_irq = mac_enable_irq;
202 disable_irq = mac_disable_irq;
203 mach_get_model = mac_get_model;
204 mach_default_handler = &mac_handlers;
205 mach_get_irq_list = show_mac_interrupts;
206 mach_gettimeoffset = mac_gettimeoffset;
207#warning move to adb/via init
208#if 0
209 mach_hwclk = mac_hwclk;
210#endif
211 mach_set_clock_mmss = mac_set_clock_mmss;
212 mach_reset = mac_reset;
213 mach_halt = mac_poweroff;
214 mach_power_off = mac_poweroff;
215#ifdef CONFIG_DUMMY_CONSOLE
216 conswitchp = &dummy_con;
217#endif
218 mach_max_dma_address = 0xffffffff;
219#if 0
220 mach_debug_init = mac_debug_init;
221#endif
222#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
223 mach_beep = mac_mksound;
224#endif
225#ifdef CONFIG_HEARTBEAT
226#if 0
227 mach_heartbeat = mac_heartbeat;
228 mach_heartbeat_irq = IRQ_MAC_TIMER;
229#endif
230#endif
231
232 /*
233 * Determine hardware present
234 */
235
236 mac_identify();
237 mac_report_hardware();
238
239 /* AFAIK only the IIci takes a cache card. The IIfx has onboard
240 cache ... someone needs to figure out how to tell if it's on or
241 not. */
242
243 if (macintosh_config->ident == MAC_MODEL_IICI
244 || macintosh_config->ident == MAC_MODEL_IIFX) {
245 mach_l2_flush = mac_cache_card_flush;
246 }
247
248 /*
249 * Check for machine specific fixups.
250 */
251
252#ifdef OLD_NUBUS_CODE
253 nubus_sweep_video();
254#endif
255}
256
257
258/*
259 * Macintosh Table: hardcoded model configuration data.
260 *
261 * Much of this was defined by Alan, based on who knows what docs.
262 * I've added a lot more, and some of that was pure guesswork based
263 * on hardware pages present on the Mac web site. Possibly wildly
264 * inaccurate, so look here if a new Mac model won't run. Example: if
265 * a Mac crashes immediately after the VIA1 registers have been dumped
266 * to the screen, it probably died attempting to read DirB on a RBV.
267 * Meaning it should have MAC_VIA_IIci here :-)
268 */
269
270struct mac_model *macintosh_config;
271EXPORT_SYMBOL(macintosh_config);
272
273static struct mac_model mac_data_table[]=
274{
275 /*
276 * We'll pretend to be a Macintosh II, that's pretty safe.
277 */
278
279 {
280 .ident = MAC_MODEL_II,
281 .name = "Unknown",
282 .adb_type = MAC_ADB_II,
283 .via_type = MAC_VIA_II,
284 .scsi_type = MAC_SCSI_OLD,
285 .scc_type = MAC_SCC_II,
286 .nubus_type = MAC_NUBUS
287 },
288
289 /*
290 * Original MacII hardware
291 *
292 */
293
294 {
295 .ident = MAC_MODEL_II,
296 .name = "II",
297 .adb_type = MAC_ADB_II,
298 .via_type = MAC_VIA_II,
299 .scsi_type = MAC_SCSI_OLD,
300 .scc_type = MAC_SCC_II,
301 .nubus_type = MAC_NUBUS
302 }, {
303 .ident = MAC_MODEL_IIX,
304 .name = "IIx",
305 .adb_type = MAC_ADB_II,
306 .via_type = MAC_VIA_II,
307 .scsi_type = MAC_SCSI_OLD,
308 .scc_type = MAC_SCC_II,
309 .nubus_type = MAC_NUBUS
310 }, {
311 .ident = MAC_MODEL_IICX,
312 .name = "IIcx",
313 .adb_type = MAC_ADB_II,
314 .via_type = MAC_VIA_II,
315 .scsi_type = MAC_SCSI_OLD,
316 .scc_type = MAC_SCC_II,
317 .nubus_type = MAC_NUBUS
318 }, {
319 .ident = MAC_MODEL_SE30,
320 .name = "SE/30",
321 .adb_type = MAC_ADB_II,
322 .via_type = MAC_VIA_II,
323 .scsi_type = MAC_SCSI_OLD,
324 .scc_type = MAC_SCC_II,
325 .nubus_type = MAC_NUBUS
326 },
327
328 /*
329 * Weirdified MacII hardware - all subtley different. Gee thanks
330 * Apple. All these boxes seem to have VIA2 in a different place to
331 * the MacII (+1A000 rather than +4000)
332 * CSA: see http://developer.apple.com/technotes/hw/hw_09.html
333 */
334
335 {
336 .ident = MAC_MODEL_IICI,
337 .name = "IIci",
338 .adb_type = MAC_ADB_II,
339 .via_type = MAC_VIA_IIci,
340 .scsi_type = MAC_SCSI_OLD,
341 .scc_type = MAC_SCC_II,
342 .nubus_type = MAC_NUBUS
343 }, {
344 .ident = MAC_MODEL_IIFX,
345 .name = "IIfx",
346 .adb_type = MAC_ADB_IOP,
347 .via_type = MAC_VIA_IIci,
348 .scsi_type = MAC_SCSI_OLD,
349 .scc_type = MAC_SCC_IOP,
350 .nubus_type = MAC_NUBUS
351 }, {
352 .ident = MAC_MODEL_IISI,
353 .name = "IIsi",
354 .adb_type = MAC_ADB_IISI,
355 .via_type = MAC_VIA_IIci,
356 .scsi_type = MAC_SCSI_OLD,
357 .scc_type = MAC_SCC_II,
358 .nubus_type = MAC_NUBUS
359 }, {
360 .ident = MAC_MODEL_IIVI,
361 .name = "IIvi",
362 .adb_type = MAC_ADB_IISI,
363 .via_type = MAC_VIA_IIci,
364 .scsi_type = MAC_SCSI_OLD,
365 .scc_type = MAC_SCC_II,
366 .nubus_type = MAC_NUBUS
367 }, {
368 .ident = MAC_MODEL_IIVX,
369 .name = "IIvx",
370 .adb_type = MAC_ADB_IISI,
371 .via_type = MAC_VIA_IIci,
372 .scsi_type = MAC_SCSI_OLD,
373 .scc_type = MAC_SCC_II,
374 .nubus_type = MAC_NUBUS
375 },
376
377 /*
378 * Classic models (guessing: similar to SE/30 ?? Nope, similar to LC ...)
379 */
380
381 {
382 .ident = MAC_MODEL_CLII,
383 .name = "Classic II",
384 .adb_type = MAC_ADB_IISI,
385 .via_type = MAC_VIA_IIci,
386 .scsi_type = MAC_SCSI_OLD,
387 .scc_type = MAC_SCC_II,
388 .nubus_type = MAC_NUBUS
389 }, {
390 .ident = MAC_MODEL_CCL,
391 .name = "Color Classic",
392 .adb_type = MAC_ADB_CUDA,
393 .via_type = MAC_VIA_IIci,
394 .scsi_type = MAC_SCSI_OLD,
395 .scc_type = MAC_SCC_II,
396 .nubus_type = MAC_NUBUS},
397
398 /*
399 * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi
400 */
401
402 {
403 .ident = MAC_MODEL_LC,
404 .name = "LC",
405 .adb_type = MAC_ADB_IISI,
406 .via_type = MAC_VIA_IIci,
407 .scsi_type = MAC_SCSI_OLD,
408 .scc_type = MAC_SCC_II,
409 .nubus_type = MAC_NUBUS
410 }, {
411 .ident = MAC_MODEL_LCII,
412 .name = "LC II",
413 .adb_type = MAC_ADB_IISI,
414 .via_type = MAC_VIA_IIci,
415 .scsi_type = MAC_SCSI_OLD,
416 .scc_type = MAC_SCC_II,
417 .nubus_type = MAC_NUBUS
418 }, {
419 .ident = MAC_MODEL_LCIII,
420 .name = "LC III",
421 .adb_type = MAC_ADB_IISI,
422 .via_type = MAC_VIA_IIci,
423 .scsi_type = MAC_SCSI_OLD,
424 .scc_type = MAC_SCC_II,
425 .nubus_type = MAC_NUBUS
426 },
427
428 /*
429 * Quadra. Video is at 0xF9000000, via is like a MacII. We label it differently
430 * as some of the stuff connected to VIA2 seems different. Better SCSI chip and
431 * onboard ethernet using a NatSemi SONIC except the 660AV and 840AV which use an
432 * AMD 79C940 (MACE).
433 * The 700, 900 and 950 have some I/O chips in the wrong place to
434 * confuse us. The 840AV has a SCSI location of its own (same as
435 * the 660AV).
436 */
437
438 {
439 .ident = MAC_MODEL_Q605,
440 .name = "Quadra 605",
441 .adb_type = MAC_ADB_CUDA,
442 .via_type = MAC_VIA_QUADRA,
443 .scsi_type = MAC_SCSI_QUADRA,
444 .scc_type = MAC_SCC_QUADRA,
445 .nubus_type = MAC_NUBUS
446 }, {
447 .ident = MAC_MODEL_Q605_ACC,
448 .name = "Quadra 605",
449 .adb_type = MAC_ADB_CUDA,
450 .via_type = MAC_VIA_QUADRA,
451 .scsi_type = MAC_SCSI_QUADRA,
452 .scc_type = MAC_SCC_QUADRA,
453 .nubus_type = MAC_NUBUS
454 }, {
455 .ident = MAC_MODEL_Q610,
456 .name = "Quadra 610",
457 .adb_type = MAC_ADB_II,
458 .via_type = MAC_VIA_QUADRA,
459 .scsi_type = MAC_SCSI_QUADRA,
460 .scc_type = MAC_SCC_QUADRA,
461 .ether_type = MAC_ETHER_SONIC,
462 .nubus_type = MAC_NUBUS
463 }, {
464 .ident = MAC_MODEL_Q630,
465 .name = "Quadra 630",
466 .adb_type = MAC_ADB_CUDA,
467 .via_type = MAC_VIA_QUADRA,
468 .scsi_type = MAC_SCSI_QUADRA,
469 .ide_type = MAC_IDE_QUADRA,
470 .scc_type = MAC_SCC_QUADRA,
471 .ether_type = MAC_ETHER_SONIC,
472 .nubus_type = MAC_NUBUS
473 }, {
474 .ident = MAC_MODEL_Q650,
475 .name = "Quadra 650",
476 .adb_type = MAC_ADB_II,
477 .via_type = MAC_VIA_QUADRA,
478 .scsi_type = MAC_SCSI_QUADRA,
479 .scc_type = MAC_SCC_QUADRA,
480 .ether_type = MAC_ETHER_SONIC,
481 .nubus_type = MAC_NUBUS
482 },
483 /* The Q700 does have a NS Sonic */
484 {
485 .ident = MAC_MODEL_Q700,
486 .name = "Quadra 700",
487 .adb_type = MAC_ADB_II,
488 .via_type = MAC_VIA_QUADRA,
489 .scsi_type = MAC_SCSI_QUADRA2,
490 .scc_type = MAC_SCC_QUADRA,
491 .ether_type = MAC_ETHER_SONIC,
492 .nubus_type = MAC_NUBUS
493 }, {
494 .ident = MAC_MODEL_Q800,
495 .name = "Quadra 800",
496 .adb_type = MAC_ADB_II,
497 .via_type = MAC_VIA_QUADRA,
498 .scsi_type = MAC_SCSI_QUADRA,
499 .scc_type = MAC_SCC_QUADRA,
500 .ether_type = MAC_ETHER_SONIC,
501 .nubus_type = MAC_NUBUS
502 }, {
503 .ident = MAC_MODEL_Q840,
504 .name = "Quadra 840AV",
505 .adb_type = MAC_ADB_CUDA,
506 .via_type = MAC_VIA_QUADRA,
507 .scsi_type = MAC_SCSI_QUADRA3,
508 .scc_type = MAC_SCC_PSC,
509 .ether_type = MAC_ETHER_MACE,
510 .nubus_type = MAC_NUBUS
511 }, {
512 .ident = MAC_MODEL_Q900,
513 .name = "Quadra 900",
514 .adb_type = MAC_ADB_IOP,
515 .via_type = MAC_VIA_QUADRA,
516 .scsi_type = MAC_SCSI_QUADRA2,
517 .scc_type = MAC_SCC_IOP,
518 .ether_type = MAC_ETHER_SONIC,
519 .nubus_type = MAC_NUBUS
520 }, {
521 .ident = MAC_MODEL_Q950,
522 .name = "Quadra 950",
523 .adb_type = MAC_ADB_IOP,
524 .via_type = MAC_VIA_QUADRA,
525 .scsi_type = MAC_SCSI_QUADRA2,
526 .scc_type = MAC_SCC_IOP,
527 .ether_type = MAC_ETHER_SONIC,
528 .nubus_type = MAC_NUBUS
529 },
530
531 /*
532 * Performa - more LC type machines
533 */
534
535 {
536 .ident = MAC_MODEL_P460,
537 .name = "Performa 460",
538 .adb_type = MAC_ADB_IISI,
539 .via_type = MAC_VIA_IIci,
540 .scsi_type = MAC_SCSI_OLD,
541 .scc_type = MAC_SCC_II,
542 .nubus_type = MAC_NUBUS
543 }, {
544 .ident = MAC_MODEL_P475,
545 .name = "Performa 475",
546 .adb_type = MAC_ADB_CUDA,
547 .via_type = MAC_VIA_QUADRA,
548 .scsi_type = MAC_SCSI_QUADRA,
549 .scc_type = MAC_SCC_II,
550 .nubus_type = MAC_NUBUS
551 }, {
552 .ident = MAC_MODEL_P475F,
553 .name = "Performa 475",
554 .adb_type = MAC_ADB_CUDA,
555 .via_type = MAC_VIA_QUADRA,
556 .scsi_type = MAC_SCSI_QUADRA,
557 .scc_type = MAC_SCC_II,
558 .nubus_type = MAC_NUBUS
559 }, {
560 .ident = MAC_MODEL_P520,
561 .name = "Performa 520",
562 .adb_type = MAC_ADB_CUDA,
563 .via_type = MAC_VIA_IIci,
564 .scsi_type = MAC_SCSI_OLD,
565 .scc_type = MAC_SCC_II,
566 .nubus_type = MAC_NUBUS
567 }, {
568 .ident = MAC_MODEL_P550,
569 .name = "Performa 550",
570 .adb_type = MAC_ADB_CUDA,
571 .via_type = MAC_VIA_IIci,
572 .scsi_type = MAC_SCSI_OLD,
573 .scc_type = MAC_SCC_II,
574 .nubus_type = MAC_NUBUS
575 },
576 /* These have the comm slot, and therefore the possibility of SONIC ethernet */
577 {
578 .ident = MAC_MODEL_P575,
579 .name = "Performa 575",
580 .adb_type = MAC_ADB_CUDA,
581 .via_type = MAC_VIA_QUADRA,
582 .scsi_type = MAC_SCSI_QUADRA,
583 .scc_type = MAC_SCC_II,
584 .ether_type = MAC_ETHER_SONIC,
585 .nubus_type = MAC_NUBUS
586 }, {
587 .ident = MAC_MODEL_P588,
588 .name = "Performa 588",
589 .adb_type = MAC_ADB_CUDA,
590 .via_type = MAC_VIA_QUADRA,
591 .scsi_type = MAC_SCSI_QUADRA,
592 .ide_type = MAC_IDE_QUADRA,
593 .scc_type = MAC_SCC_II,
594 .ether_type = MAC_ETHER_SONIC,
595 .nubus_type = MAC_NUBUS
596 }, {
597 .ident = MAC_MODEL_TV,
598 .name = "TV",
599 .adb_type = MAC_ADB_CUDA,
600 .via_type = MAC_VIA_QUADRA,
601 .scsi_type = MAC_SCSI_OLD,
602 .scc_type = MAC_SCC_II,
603 .nubus_type = MAC_NUBUS
604 }, {
605 .ident = MAC_MODEL_P600,
606 .name = "Performa 600",
607 .adb_type = MAC_ADB_IISI,
608 .via_type = MAC_VIA_IIci,
609 .scsi_type = MAC_SCSI_OLD,
610 .scc_type = MAC_SCC_II,
611 .nubus_type = MAC_NUBUS
612 },
613
614 /*
615 * Centris - just guessing again; maybe like Quadra
616 */
617
618 /* The C610 may or may not have SONIC. We probe to make sure */
619 {
620 .ident = MAC_MODEL_C610,
621 .name = "Centris 610",
622 .adb_type = MAC_ADB_II,
623 .via_type = MAC_VIA_QUADRA,
624 .scsi_type = MAC_SCSI_QUADRA,
625 .scc_type = MAC_SCC_QUADRA,
626 .ether_type = MAC_ETHER_SONIC,
627 .nubus_type = MAC_NUBUS
628 }, {
629 .ident = MAC_MODEL_C650,
630 .name = "Centris 650",
631 .adb_type = MAC_ADB_II,
632 .via_type = MAC_VIA_QUADRA,
633 .scsi_type = MAC_SCSI_QUADRA,
634 .scc_type = MAC_SCC_QUADRA,
635 .ether_type = MAC_ETHER_SONIC,
636 .nubus_type = MAC_NUBUS
637 }, {
638 .ident = MAC_MODEL_C660,
639 .name = "Centris 660AV",
640 .adb_type = MAC_ADB_CUDA,
641 .via_type = MAC_VIA_QUADRA,
642 .scsi_type = MAC_SCSI_QUADRA3,
643 .scc_type = MAC_SCC_PSC,
644 .ether_type = MAC_ETHER_MACE,
645 .nubus_type = MAC_NUBUS
646 },
647
648 /*
649 * The PowerBooks all the same "Combo" custom IC for SCSI and SCC
650 * and a PMU (in two variations?) for ADB. Most of them use the
651 * Quadra-style VIAs. A few models also have IDE from hell.
652 */
653
654 {
655 .ident = MAC_MODEL_PB140,
656 .name = "PowerBook 140",
657 .adb_type = MAC_ADB_PB1,
658 .via_type = MAC_VIA_QUADRA,
659 .scsi_type = MAC_SCSI_OLD,
660 .scc_type = MAC_SCC_QUADRA,
661 .nubus_type = MAC_NUBUS
662 }, {
663 .ident = MAC_MODEL_PB145,
664 .name = "PowerBook 145",
665 .adb_type = MAC_ADB_PB1,
666 .via_type = MAC_VIA_QUADRA,
667 .scsi_type = MAC_SCSI_OLD,
668 .scc_type = MAC_SCC_QUADRA,
669 .nubus_type = MAC_NUBUS
670 }, {
671 .ident = MAC_MODEL_PB150,
672 .name = "PowerBook 150",
673 .adb_type = MAC_ADB_PB1,
674 .via_type = MAC_VIA_IIci,
675 .scsi_type = MAC_SCSI_OLD,
676 .ide_type = MAC_IDE_PB,
677 .scc_type = MAC_SCC_QUADRA,
678 .nubus_type = MAC_NUBUS
679 }, {
680 .ident = MAC_MODEL_PB160,
681 .name = "PowerBook 160",
682 .adb_type = MAC_ADB_PB1,
683 .via_type = MAC_VIA_QUADRA,
684 .scsi_type = MAC_SCSI_OLD,
685 .scc_type = MAC_SCC_QUADRA,
686 .nubus_type = MAC_NUBUS
687 }, {
688 .ident = MAC_MODEL_PB165,
689 .name = "PowerBook 165",
690 .adb_type = MAC_ADB_PB1,
691 .via_type = MAC_VIA_QUADRA,
692 .scsi_type = MAC_SCSI_OLD,
693 .scc_type = MAC_SCC_QUADRA,
694 .nubus_type = MAC_NUBUS
695 }, {
696 .ident = MAC_MODEL_PB165C,
697 .name = "PowerBook 165c",
698 .adb_type = MAC_ADB_PB1,
699 .via_type = MAC_VIA_QUADRA,
700 .scsi_type = MAC_SCSI_OLD,
701 .scc_type = MAC_SCC_QUADRA,
702 .nubus_type = MAC_NUBUS
703 }, {
704 .ident = MAC_MODEL_PB170,
705 .name = "PowerBook 170",
706 .adb_type = MAC_ADB_PB1,
707 .via_type = MAC_VIA_QUADRA,
708 .scsi_type = MAC_SCSI_OLD,
709 .scc_type = MAC_SCC_QUADRA,
710 .nubus_type = MAC_NUBUS
711 }, {
712 .ident = MAC_MODEL_PB180,
713 .name = "PowerBook 180",
714 .adb_type = MAC_ADB_PB1,
715 .via_type = MAC_VIA_QUADRA,
716 .scsi_type = MAC_SCSI_OLD,
717 .scc_type = MAC_SCC_QUADRA,
718 .nubus_type = MAC_NUBUS
719 }, {
720 .ident = MAC_MODEL_PB180C,
721 .name = "PowerBook 180c",
722 .adb_type = MAC_ADB_PB1,
723 .via_type = MAC_VIA_QUADRA,
724 .scsi_type = MAC_SCSI_OLD,
725 .scc_type = MAC_SCC_QUADRA,
726 .nubus_type = MAC_NUBUS
727 }, {
728 .ident = MAC_MODEL_PB190,
729 .name = "PowerBook 190",
730 .adb_type = MAC_ADB_PB2,
731 .via_type = MAC_VIA_QUADRA,
732 .scsi_type = MAC_SCSI_OLD,
733 .ide_type = MAC_IDE_BABOON,
734 .scc_type = MAC_SCC_QUADRA,
735 .nubus_type = MAC_NUBUS
736 }, {
737 .ident = MAC_MODEL_PB520,
738 .name = "PowerBook 520",
739 .adb_type = MAC_ADB_PB2,
740 .via_type = MAC_VIA_QUADRA,
741 .scsi_type = MAC_SCSI_OLD,
742 .scc_type = MAC_SCC_QUADRA,
743 .ether_type = MAC_ETHER_SONIC,
744 .nubus_type = MAC_NUBUS
745 },
746
747 /*
748 * PowerBook Duos are pretty much like normal PowerBooks
749 * All of these probably have onboard SONIC in the Dock which
750 * means we'll have to probe for it eventually.
751 *
752 * Are these reallly MAC_VIA_IIci? The developer notes for the
753 * Duos show pretty much the same custom parts as in most of
754 * the other PowerBooks which would imply MAC_VIA_QUADRA.
755 */
756
757 {
758 .ident = MAC_MODEL_PB210,
759 .name = "PowerBook Duo 210",
760 .adb_type = MAC_ADB_PB2,
761 .via_type = MAC_VIA_IIci,
762 .scsi_type = MAC_SCSI_OLD,
763 .scc_type = MAC_SCC_QUADRA,
764 .nubus_type = MAC_NUBUS
765 }, {
766 .ident = MAC_MODEL_PB230,
767 .name = "PowerBook Duo 230",
768 .adb_type = MAC_ADB_PB2,
769 .via_type = MAC_VIA_IIci,
770 .scsi_type = MAC_SCSI_OLD,
771 .scc_type = MAC_SCC_QUADRA,
772 .nubus_type = MAC_NUBUS
773 }, {
774 .ident = MAC_MODEL_PB250,
775 .name = "PowerBook Duo 250",
776 .adb_type = MAC_ADB_PB2,
777 .via_type = MAC_VIA_IIci,
778 .scsi_type = MAC_SCSI_OLD,
779 .scc_type = MAC_SCC_QUADRA,
780 .nubus_type = MAC_NUBUS
781 }, {
782 .ident = MAC_MODEL_PB270C,
783 .name = "PowerBook Duo 270c",
784 .adb_type = MAC_ADB_PB2,
785 .via_type = MAC_VIA_IIci,
786 .scsi_type = MAC_SCSI_OLD,
787 .scc_type = MAC_SCC_QUADRA,
788 .nubus_type = MAC_NUBUS
789 }, {
790 .ident = MAC_MODEL_PB280,
791 .name = "PowerBook Duo 280",
792 .adb_type = MAC_ADB_PB2,
793 .via_type = MAC_VIA_IIci,
794 .scsi_type = MAC_SCSI_OLD,
795 .scc_type = MAC_SCC_QUADRA,
796 .nubus_type = MAC_NUBUS
797 }, {
798 .ident = MAC_MODEL_PB280C,
799 .name = "PowerBook Duo 280c",
800 .adb_type = MAC_ADB_PB2,
801 .via_type = MAC_VIA_IIci,
802 .scsi_type = MAC_SCSI_OLD,
803 .scc_type = MAC_SCC_QUADRA,
804 .nubus_type = MAC_NUBUS
805 },
806
807 /*
808 * Other stuff ??
809 */
810 {
811 .ident = -1
812 }
813};
814
815void mac_identify(void)
816{
817 struct mac_model *m;
818
819 /* Penguin data useful? */
820 int model = mac_bi_data.id;
821 if (!model) {
822 /* no bootinfo model id -> NetBSD booter was used! */
823 /* XXX FIXME: breaks for model > 31 */
824 model=(mac_bi_data.cpuid>>2)&63;
825 printk (KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
826 }
827
828 macintosh_config = mac_data_table;
829 for (m = macintosh_config ; m->ident != -1 ; m++) {
830 if (m->ident == model) {
831 macintosh_config = m;
832 break;
833 }
834 }
835
836 /* We need to pre-init the IOPs, if any. Otherwise */
837 /* the serial console won't work if the user had */
838 /* the serial ports set to "Faster" mode in MacOS. */
839
840 iop_preinit();
841 mac_debug_init();
842
843 printk (KERN_INFO "Detected Macintosh model: %d \n", model);
844
845 /*
846 * Report booter data:
847 */
848 printk (KERN_DEBUG " Penguin bootinfo data:\n");
849 printk (KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
850 mac_bi_data.videoaddr, mac_bi_data.videorow,
851 mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF,
852 mac_bi_data.dimensions >> 16);
853 printk (KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
854 mac_bi_data.videological, mac_orig_videoaddr,
855 mac_bi_data.sccbase);
856 printk (KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
857 mac_bi_data.boottime, mac_bi_data.gmtbias);
858 printk (KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
859 mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
860#if 0
861 printk ("Ramdisk: addr 0x%lx size 0x%lx\n",
862 m68k_ramdisk.addr, m68k_ramdisk.size);
863#endif
864
865 /*
866 * TODO: set the various fields in macintosh_config->hw_present here!
867 */
868 switch (macintosh_config->scsi_type) {
869 case MAC_SCSI_OLD:
870 MACHW_SET(MAC_SCSI_80);
871 break;
872 case MAC_SCSI_QUADRA:
873 case MAC_SCSI_QUADRA2:
874 case MAC_SCSI_QUADRA3:
875 MACHW_SET(MAC_SCSI_96);
876 if ((macintosh_config->ident == MAC_MODEL_Q900) ||
877 (macintosh_config->ident == MAC_MODEL_Q950))
878 MACHW_SET(MAC_SCSI_96_2);
879 break;
880 default:
881 printk(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n");
882 MACHW_SET(MAC_SCSI_80);
883 break;
884
885 }
886 iop_init();
887 via_init();
888 oss_init();
889 psc_init();
890 baboon_init();
891}
892
893void mac_report_hardware(void)
894{
895 printk(KERN_INFO "Apple Macintosh %s\n", macintosh_config->name);
896}
897
898static void mac_get_model(char *str)
899{
900 strcpy(str,"Macintosh ");
901 strcat(str, macintosh_config->name);
902}
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
new file mode 100644
index 000000000000..cc62ed61cda2
--- /dev/null
+++ b/arch/m68k/mac/debug.c
@@ -0,0 +1,398 @@
1/*
2 * linux/arch/m68k/mac/debug.c
3 *
4 * Shamelessly stolen (SCC code and general framework) from:
5 *
6 * linux/arch/m68k/atari/debug.c
7 *
8 * Atari debugging and serial console stuff
9 *
10 * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file COPYING in the main directory of this archive
14 * for more details.
15 */
16
17#include <linux/config.h>
18#include <linux/types.h>
19#include <linux/sched.h>
20#include <linux/tty.h>
21#include <linux/console.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24
25#define BOOTINFO_COMPAT_1_0
26#include <asm/setup.h>
27#include <asm/bootinfo.h>
28#include <asm/machw.h>
29#include <asm/macints.h>
30
31extern char m68k_debug_device[];
32
33extern struct compat_bootinfo compat_boot_info;
34
35extern unsigned long mac_videobase;
36extern unsigned long mac_videodepth;
37extern unsigned long mac_rowbytes;
38
39extern void mac_serial_print(const char *);
40
41#define DEBUG_HEADS
42#undef DEBUG_SCREEN
43#define DEBUG_SERIAL
44
45/*
46 * These two auxiliary debug functions should go away ASAP. Only usage:
47 * before the console output is up (after head.S come some other crucial
48 * setup routines :-) it permits writing 'data' to the screen as bit patterns
49 * (good luck reading those). Helped to figure that the bootinfo contained
50 * garbage data on the amount and size of memory chunks ...
51 *
52 * The 'pos' argument now simply means 'linefeed after print' ...
53 */
54
55#ifdef DEBUG_SCREEN
56static int peng=0, line=0;
57#endif
58
59void mac_debugging_short(int pos, short num)
60{
61#ifdef DEBUG_SCREEN
62 unsigned char *pengoffset;
63 unsigned char *pptr;
64 int i;
65#endif
66
67#ifdef DEBUG_SERIAL
68 printk("debug: %d !\n", num);
69#endif
70
71#ifdef DEBUG_SCREEN
72 if (!MACH_IS_MAC) {
73 /* printk("debug: %d !\n", num); */
74 return;
75 }
76
77 /* calculate current offset */
78 pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
79 +80*peng;
80
81 pptr=pengoffset;
82
83 for(i=0;i<8*sizeof(short);i++) /* # of bits */
84 {
85 /* value mask for bit i, reverse order */
86 *pptr++ = (num & ( 1 << (8*sizeof(short)-i-1) ) ? 0xFF : 0x00);
87 }
88
89 peng++;
90
91 if (pos) {
92 line++;
93 peng = 0;
94 }
95#endif
96}
97
98void mac_debugging_long(int pos, long addr)
99{
100#ifdef DEBUG_SCREEN
101 unsigned char *pengoffset;
102 unsigned char *pptr;
103 int i;
104#endif
105
106#ifdef DEBUG_SERIAL
107 printk("debug: #%ld !\n", addr);
108#endif
109
110#ifdef DEBUG_SCREEN
111 if (!MACH_IS_MAC) {
112 /* printk("debug: #%ld !\n", addr); */
113 return;
114 }
115
116 pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
117 +80*peng;
118
119 pptr=pengoffset;
120
121 for(i=0;i<8*sizeof(long);i++) /* # of bits */
122 {
123 *pptr++ = (addr & ( 1 << (8*sizeof(long)-i-1) ) ? 0xFF : 0x00);
124 }
125
126 peng++;
127
128 if (pos) {
129 line++;
130 peng = 0;
131 }
132#endif
133}
134
135#ifdef DEBUG_SERIAL
136/*
137 * TODO: serial debug code
138 */
139
140struct mac_SCC
141 {
142 u_char cha_b_ctrl;
143 u_char char_dummy1;
144 u_char cha_a_ctrl;
145 u_char char_dummy2;
146 u_char cha_b_data;
147 u_char char_dummy3;
148 u_char cha_a_data;
149 };
150
151# define scc (*((volatile struct mac_SCC*)mac_bi_data.sccbase))
152
153/* Flag that serial port is already initialized and used */
154int mac_SCC_init_done;
155/* Can be set somewhere, if a SCC master reset has already be done and should
156 * not be repeated; used by kgdb */
157int mac_SCC_reset_done;
158
159static int scc_port = -1;
160
161static struct console mac_console_driver = {
162 .name = "debug",
163 .flags = CON_PRINTBUFFER,
164 .index = -1,
165};
166
167/*
168 * Crude hack to get console output to the screen before the framebuffer
169 * is initialized (happens a lot later in 2.1!).
170 * We just use the console routines declared in head.S, this will interfere
171 * with regular framebuffer console output and should be used exclusively
172 * to debug kernel problems manifesting before framebuffer init (aka WSOD)
173 *
174 * To keep this hack from interfering with the regular console driver, either
175 * deregister this driver before/on framebuffer console init, or silence this
176 * function after the fbcon driver is running (will lose console messages!?).
177 * To debug real early bugs, need to write a 'mac_register_console_hack()'
178 * that is called from start_kernel() before setup_arch() and just registers
179 * this driver if Mac.
180 */
181
182void mac_debug_console_write (struct console *co, const char *str,
183 unsigned int count)
184{
185 mac_serial_print(str);
186}
187
188
189
190/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
191
192#define uSEC 1
193
194static inline void mac_sccb_out (char c)
195{
196 int i;
197 do {
198 for( i = uSEC; i > 0; --i )
199 barrier();
200 } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
201 for( i = uSEC; i > 0; --i )
202 barrier();
203 scc.cha_b_data = c;
204}
205
206static inline void mac_scca_out (char c)
207{
208 int i;
209 do {
210 for( i = uSEC; i > 0; --i )
211 barrier();
212 } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
213 for( i = uSEC; i > 0; --i )
214 barrier();
215 scc.cha_a_data = c;
216}
217
218void mac_sccb_console_write (struct console *co, const char *str,
219 unsigned int count)
220{
221 while (count--) {
222 if (*str == '\n')
223 mac_sccb_out( '\r' );
224 mac_sccb_out( *str++ );
225 }
226}
227
228void mac_scca_console_write (struct console *co, const char *str,
229 unsigned int count)
230{
231 while (count--) {
232 if (*str == '\n')
233 mac_scca_out( '\r' );
234 mac_scca_out( *str++ );
235 }
236}
237
238
239/* The following two functions do a quick'n'dirty initialization of the MFP or
240 * SCC serial ports. They're used by the debugging interface, kgdb, and the
241 * serial console code. */
242#define SCCB_WRITE(reg,val) \
243 do { \
244 int i; \
245 scc.cha_b_ctrl = (reg); \
246 for( i = uSEC; i > 0; --i ) \
247 barrier(); \
248 scc.cha_b_ctrl = (val); \
249 for( i = uSEC; i > 0; --i ) \
250 barrier(); \
251 } while(0)
252
253#define SCCA_WRITE(reg,val) \
254 do { \
255 int i; \
256 scc.cha_a_ctrl = (reg); \
257 for( i = uSEC; i > 0; --i ) \
258 barrier(); \
259 scc.cha_a_ctrl = (val); \
260 for( i = uSEC; i > 0; --i ) \
261 barrier(); \
262 } while(0)
263
264/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
265 * delay of ~ 60us. */
266/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
267#define LONG_DELAY() \
268 do { \
269 int i; \
270 for( i = 60*uSEC; i > 0; --i ) \
271 barrier(); \
272 } while(0)
273
274#ifndef CONFIG_SERIAL_CONSOLE
275static void __init mac_init_scc_port( int cflag, int port )
276#else
277void mac_init_scc_port( int cflag, int port )
278#endif
279{
280 extern int mac_SCC_reset_done;
281
282 /*
283 * baud rates: 1200, 1800, 2400, 4800, 9600, 19.2k, 38.4k, 57.6k, 115.2k
284 */
285
286 static int clksrc_table[9] =
287 /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
288 { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
289 static int clkmode_table[9] =
290 /* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
291 { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
292 static int div_table[9] =
293 /* reg12 (BRG low) */
294 { 94, 62, 46, 22, 10, 4, 1, 0, 0 };
295
296 int baud = cflag & CBAUD;
297 int clksrc, clkmode, div, reg3, reg5;
298
299 if (cflag & CBAUDEX)
300 baud += B38400;
301 if (baud < B1200 || baud > B38400+2)
302 baud = B9600; /* use default 9600bps for non-implemented rates */
303 baud -= B1200; /* tables starts at 1200bps */
304
305 clksrc = clksrc_table[baud];
306 clkmode = clkmode_table[baud];
307 div = div_table[baud];
308
309 reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
310 reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
311
312 if (port == 1) {
313 (void)scc.cha_b_ctrl; /* reset reg pointer */
314 SCCB_WRITE( 9, 0xc0 ); /* reset */
315 LONG_DELAY(); /* extra delay after WR9 access */
316 SCCB_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
317 0x04 /* 1 stopbit */ |
318 clkmode );
319 SCCB_WRITE( 3, reg3 );
320 SCCB_WRITE( 5, reg5 );
321 SCCB_WRITE( 9, 0 ); /* no interrupts */
322 LONG_DELAY(); /* extra delay after WR9 access */
323 SCCB_WRITE( 10, 0 ); /* NRZ mode */
324 SCCB_WRITE( 11, clksrc ); /* main clock source */
325 SCCB_WRITE( 12, div ); /* BRG value */
326 SCCB_WRITE( 13, 0 ); /* BRG high byte */
327 SCCB_WRITE( 14, 1 );
328 SCCB_WRITE( 3, reg3 | 1 );
329 SCCB_WRITE( 5, reg5 | 8 );
330 } else if (port == 0) {
331 (void)scc.cha_a_ctrl; /* reset reg pointer */
332 SCCA_WRITE( 9, 0xc0 ); /* reset */
333 LONG_DELAY(); /* extra delay after WR9 access */
334 SCCA_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
335 0x04 /* 1 stopbit */ |
336 clkmode );
337 SCCA_WRITE( 3, reg3 );
338 SCCA_WRITE( 5, reg5 );
339 SCCA_WRITE( 9, 0 ); /* no interrupts */
340 LONG_DELAY(); /* extra delay after WR9 access */
341 SCCA_WRITE( 10, 0 ); /* NRZ mode */
342 SCCA_WRITE( 11, clksrc ); /* main clock source */
343 SCCA_WRITE( 12, div ); /* BRG value */
344 SCCA_WRITE( 13, 0 ); /* BRG high byte */
345 SCCA_WRITE( 14, 1 );
346 SCCA_WRITE( 3, reg3 | 1 );
347 SCCA_WRITE( 5, reg5 | 8 );
348 }
349
350 mac_SCC_reset_done = 1;
351 mac_SCC_init_done = 1;
352}
353#endif /* DEBUG_SERIAL */
354
355void mac_init_scca_port( int cflag )
356{
357 mac_init_scc_port(cflag, 0);
358}
359
360void mac_init_sccb_port( int cflag )
361{
362 mac_init_scc_port(cflag, 1);
363}
364
365void __init mac_debug_init(void)
366{
367#ifdef DEBUG_SERIAL
368 if ( !strcmp( m68k_debug_device, "ser" )
369 || !strcmp( m68k_debug_device, "ser1" )) {
370 /* Mac modem port */
371 mac_init_scc_port( B9600|CS8, 0 );
372 mac_console_driver.write = mac_scca_console_write;
373 scc_port = 0;
374 }
375 else if (!strcmp( m68k_debug_device, "ser2" )) {
376 /* Mac printer port */
377 mac_init_scc_port( B9600|CS8, 1 );
378 mac_console_driver.write = mac_sccb_console_write;
379 scc_port = 1;
380 }
381#endif
382#ifdef DEBUG_HEADS
383 if ( !strcmp( m68k_debug_device, "scn" )
384 || !strcmp( m68k_debug_device, "con" )) {
385 /* display, using head.S console routines */
386 mac_console_driver.write = mac_debug_console_write;
387 }
388#endif
389 if (mac_console_driver.write)
390 register_console(&mac_console_driver);
391}
392
393/*
394 * Local variables:
395 * c-indent-level: 4
396 * tab-width: 8
397 * End:
398 */
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
new file mode 100644
index 000000000000..d889ba80ccdc
--- /dev/null
+++ b/arch/m68k/mac/iop.c
@@ -0,0 +1,714 @@
1/*
2 * I/O Processor (IOP) management
3 * Written and (C) 1999 by Joshua M. Thompson (funaho@jurai.org)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice and this list of conditions.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice and this list of conditions in the documentation and/or other
12 * materials provided with the distribution.
13 */
14
15/*
16 * The IOP chips are used in the IIfx and some Quadras (900, 950) to manage
17 * serial and ADB. They are actually a 6502 processor and some glue logic.
18 *
19 * 990429 (jmt) - Initial implementation, just enough to knock the SCC IOP
20 * into compatible mode so nobody has to fiddle with the
21 * Serial Switch control panel anymore.
22 * 990603 (jmt) - Added code to grab the correct ISM IOP interrupt for OSS
23 * and non-OSS machines (at least I hope it's correct on a
24 * non-OSS machine -- someone with a Q900 or Q950 needs to
25 * check this.)
26 * 990605 (jmt) - Rearranged things a bit wrt IOP detection; iop_present is
27 * gone, IOP base addresses are now in an array and the
28 * globally-visible functions take an IOP number instead of an
29 * an actual base address.
30 * 990610 (jmt) - Finished the message passing framework and it seems to work.
31 * Sending _definitely_ works; my adb-bus.c mods can send
32 * messages and receive the MSG_COMPLETED status back from the
33 * IOP. The trick now is figuring out the message formats.
34 * 990611 (jmt) - More cleanups. Fixed problem where unclaimed messages on a
35 * receive channel were never properly acknowledged. Bracketed
36 * the remaining debug printk's with #ifdef's and disabled
37 * debugging. I can now type on the console.
38 * 990612 (jmt) - Copyright notice added. Reworked the way replies are handled.
39 * It turns out that replies are placed back in the send buffer
40 * for that channel; messages on the receive channels are always
41 * unsolicited messages from the IOP (and our replies to them
42 * should go back in the receive channel.) Also added tracking
43 * of device names to the listener functions ala the interrupt
44 * handlers.
45 * 990729 (jmt) - Added passing of pt_regs structure to IOP handlers. This is
46 * used by the new unified ADB driver.
47 *
48 * TODO:
49 *
50 * o Something should be periodically checking iop_alive() to make sure the
51 * IOP hasn't died.
52 * o Some of the IOP manager routines need better error checking and
53 * return codes. Nothing major, just prettying up.
54 */
55
56/*
57 * -----------------------
58 * IOP Message Passing 101
59 * -----------------------
60 *
61 * The host talks to the IOPs using a rather simple message-passing scheme via
62 * a shared memory area in the IOP RAM. Each IOP has seven "channels"; each
63 * channel is conneced to a specific software driver on the IOP. For example
64 * on the SCC IOP there is one channel for each serial port. Each channel has
65 * an incoming and and outgoing message queue with a depth of one.
66 *
67 * A message is 32 bytes plus a state byte for the channel (MSG_IDLE, MSG_NEW,
68 * MSG_RCVD, MSG_COMPLETE). To send a message you copy the message into the
69 * buffer, set the state to MSG_NEW and signal the IOP by setting the IRQ flag
70 * in the IOP control to 1. The IOP will move the state to MSG_RCVD when it
71 * receives the message and then to MSG_COMPLETE when the message processing
72 * has completed. It is the host's responsibility at that point to read the
73 * reply back out of the send channel buffer and reset the channel state back
74 * to MSG_IDLE.
75 *
76 * To receive message from the IOP the same procedure is used except the roles
77 * are reversed. That is, the IOP puts message in the channel with a state of
78 * MSG_NEW, and the host receives the message and move its state to MSG_RCVD
79 * and then to MSG_COMPLETE when processing is completed and the reply (if any)
80 * has been placed back in the receive channel. The IOP will then reset the
81 * channel state to MSG_IDLE.
82 *
83 * Two sets of host interrupts are provided, INT0 and INT1. Both appear on one
84 * interrupt level; they are distinguished by a pair of bits in the IOP status
85 * register. The IOP will raise INT0 when one or more messages in the send
86 * channels have gone to the MSG_COMPLETE state and it will raise INT1 when one
87 * or more messages on the receive channels have gone to the MSG_NEW state.
88 *
89 * Since each channel handles only one message we have to implement a small
90 * interrupt-driven queue on our end. Messages to be sent are placed on the
91 * queue for sending and contain a pointer to an optional callback function.
92 * The handler for a message is called when the message state goes to
93 * MSG_COMPLETE.
94 *
95 * For receiving message we maintain a list of handler functions to call when
96 * a message is received on that IOP/channel combination. The handlers are
97 * called much like an interrupt handler and are passed a copy of the message
98 * from the IOP. The message state will be in MSG_RCVD while the handler runs;
99 * it is the handler's responsibility to call iop_complete_message() when
100 * finished; this function moves the message state to MSG_COMPLETE and signals
101 * the IOP. This two-step process is provided to allow the handler to defer
102 * message processing to a bottom-half handler if the processing will take
103 * a signifigant amount of time (handlers are called at interrupt time so they
104 * should execute quickly.)
105 */
106
107#include <linux/config.h>
108#include <linux/types.h>
109#include <linux/kernel.h>
110#include <linux/mm.h>
111#include <linux/delay.h>
112#include <linux/init.h>
113#include <linux/proc_fs.h>
114#include <linux/interrupt.h>
115
116#include <asm/bootinfo.h>
117#include <asm/macintosh.h>
118#include <asm/macints.h>
119#include <asm/mac_iop.h>
120#include <asm/mac_oss.h>
121
122/*#define DEBUG_IOP*/
123
124/* Set to nonezero if the IOPs are present. Set by iop_init() */
125
126int iop_scc_present,iop_ism_present;
127
128#ifdef CONFIG_PROC_FS
129static int iop_get_proc_info(char *, char **, off_t, int);
130#endif /* CONFIG_PROC_FS */
131
132/* structure for tracking channel listeners */
133
134struct listener {
135 const char *devname;
136 void (*handler)(struct iop_msg *, struct pt_regs *);
137};
138
139/*
140 * IOP structures for the two IOPs
141 *
142 * The SCC IOP controls both serial ports (A and B) as its two functions.
143 * The ISM IOP controls the SWIM (floppy drive) and ADB.
144 */
145
146static volatile struct mac_iop *iop_base[NUM_IOPS];
147
148/*
149 * IOP message queues
150 */
151
152static struct iop_msg iop_msg_pool[NUM_IOP_MSGS];
153static struct iop_msg *iop_send_queue[NUM_IOPS][NUM_IOP_CHAN];
154static struct listener iop_listeners[NUM_IOPS][NUM_IOP_CHAN];
155
156irqreturn_t iop_ism_irq(int, void *, struct pt_regs *);
157
158extern void oss_irq_enable(int);
159
160/*
161 * Private access functions
162 */
163
164static __inline__ void iop_loadaddr(volatile struct mac_iop *iop, __u16 addr)
165{
166 iop->ram_addr_lo = addr;
167 iop->ram_addr_hi = addr >> 8;
168}
169
170static __inline__ __u8 iop_readb(volatile struct mac_iop *iop, __u16 addr)
171{
172 iop->ram_addr_lo = addr;
173 iop->ram_addr_hi = addr >> 8;
174 return iop->ram_data;
175}
176
177static __inline__ void iop_writeb(volatile struct mac_iop *iop, __u16 addr, __u8 data)
178{
179 iop->ram_addr_lo = addr;
180 iop->ram_addr_hi = addr >> 8;
181 iop->ram_data = data;
182}
183
184static __inline__ void iop_stop(volatile struct mac_iop *iop)
185{
186 iop->status_ctrl &= ~IOP_RUN;
187}
188
189static __inline__ void iop_start(volatile struct mac_iop *iop)
190{
191 iop->status_ctrl = IOP_RUN | IOP_AUTOINC;
192}
193
194static __inline__ void iop_bypass(volatile struct mac_iop *iop)
195{
196 iop->status_ctrl |= IOP_BYPASS;
197}
198
199static __inline__ void iop_interrupt(volatile struct mac_iop *iop)
200{
201 iop->status_ctrl |= IOP_IRQ;
202}
203
204static int iop_alive(volatile struct mac_iop *iop)
205{
206 int retval;
207
208 retval = (iop_readb(iop, IOP_ADDR_ALIVE) == 0xFF);
209 iop_writeb(iop, IOP_ADDR_ALIVE, 0);
210 return retval;
211}
212
213static struct iop_msg *iop_alloc_msg(void)
214{
215 int i;
216 unsigned long flags;
217
218 local_irq_save(flags);
219
220 for (i = 0 ; i < NUM_IOP_MSGS ; i++) {
221 if (iop_msg_pool[i].status == IOP_MSGSTATUS_UNUSED) {
222 iop_msg_pool[i].status = IOP_MSGSTATUS_WAITING;
223 local_irq_restore(flags);
224 return &iop_msg_pool[i];
225 }
226 }
227
228 local_irq_restore(flags);
229 return NULL;
230}
231
232static void iop_free_msg(struct iop_msg *msg)
233{
234 msg->status = IOP_MSGSTATUS_UNUSED;
235}
236
237/*
238 * This is called by the startup code before anything else. Its purpose
239 * is to find and initialize the IOPs early in the boot sequence, so that
240 * the serial IOP can be placed into bypass mode _before_ we try to
241 * initialize the serial console.
242 */
243
244void __init iop_preinit(void)
245{
246 if (macintosh_config->scc_type == MAC_SCC_IOP) {
247 if (macintosh_config->ident == MAC_MODEL_IIFX) {
248 iop_base[IOP_NUM_SCC] = (struct mac_iop *) SCC_IOP_BASE_IIFX;
249 } else {
250 iop_base[IOP_NUM_SCC] = (struct mac_iop *) SCC_IOP_BASE_QUADRA;
251 }
252 iop_base[IOP_NUM_SCC]->status_ctrl = 0x87;
253 iop_scc_present = 1;
254 } else {
255 iop_base[IOP_NUM_SCC] = NULL;
256 iop_scc_present = 0;
257 }
258 if (macintosh_config->adb_type == MAC_ADB_IOP) {
259 if (macintosh_config->ident == MAC_MODEL_IIFX) {
260 iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_IIFX;
261 } else {
262 iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_QUADRA;
263 }
264 iop_base[IOP_NUM_ISM]->status_ctrl = 0;
265 iop_ism_present = 1;
266 } else {
267 iop_base[IOP_NUM_ISM] = NULL;
268 iop_ism_present = 0;
269 }
270}
271
272/*
273 * Initialize the IOPs, if present.
274 */
275
276void __init iop_init(void)
277{
278 int i;
279
280 if (iop_scc_present) {
281 printk("IOP: detected SCC IOP at %p\n", iop_base[IOP_NUM_SCC]);
282 }
283 if (iop_ism_present) {
284 printk("IOP: detected ISM IOP at %p\n", iop_base[IOP_NUM_ISM]);
285 iop_start(iop_base[IOP_NUM_ISM]);
286 iop_alive(iop_base[IOP_NUM_ISM]); /* clears the alive flag */
287 }
288
289 /* Make the whole pool available and empty the queues */
290
291 for (i = 0 ; i < NUM_IOP_MSGS ; i++) {
292 iop_msg_pool[i].status = IOP_MSGSTATUS_UNUSED;
293 }
294
295 for (i = 0 ; i < NUM_IOP_CHAN ; i++) {
296 iop_send_queue[IOP_NUM_SCC][i] = 0;
297 iop_send_queue[IOP_NUM_ISM][i] = 0;
298 iop_listeners[IOP_NUM_SCC][i].devname = NULL;
299 iop_listeners[IOP_NUM_SCC][i].handler = NULL;
300 iop_listeners[IOP_NUM_ISM][i].devname = NULL;
301 iop_listeners[IOP_NUM_ISM][i].handler = NULL;
302 }
303
304#if 0 /* Crashing in 2.4 now, not yet sure why. --jmt */
305#ifdef CONFIG_PROC_FS
306 create_proc_info_entry("mac_iop", 0, &proc_root, iop_get_proc_info);
307#endif
308#endif
309}
310
311/*
312 * Register the interrupt handler for the IOPs.
313 * TODO: might be wrong for non-OSS machines. Anyone?
314 */
315
316void __init iop_register_interrupts(void)
317{
318 if (iop_ism_present) {
319 if (oss_present) {
320 cpu_request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
321 IRQ_FLG_LOCK, "ISM IOP",
322 (void *) IOP_NUM_ISM);
323 oss_irq_enable(IRQ_MAC_ADB);
324 } else {
325 request_irq(IRQ_VIA2_0, iop_ism_irq,
326 IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
327 (void *) IOP_NUM_ISM);
328 }
329 if (!iop_alive(iop_base[IOP_NUM_ISM])) {
330 printk("IOP: oh my god, they killed the ISM IOP!\n");
331 } else {
332 printk("IOP: the ISM IOP seems to be alive.\n");
333 }
334 }
335}
336
337/*
338 * Register or unregister a listener for a specific IOP and channel
339 *
340 * If the handler pointer is NULL the current listener (if any) is
341 * unregistered. Otherwise the new listener is registered provided
342 * there is no existing listener registered.
343 */
344
345int iop_listen(uint iop_num, uint chan,
346 void (*handler)(struct iop_msg *, struct pt_regs *),
347 const char *devname)
348{
349 if ((iop_num >= NUM_IOPS) || !iop_base[iop_num]) return -EINVAL;
350 if (chan >= NUM_IOP_CHAN) return -EINVAL;
351 if (iop_listeners[iop_num][chan].handler && handler) return -EINVAL;
352 iop_listeners[iop_num][chan].devname = devname;
353 iop_listeners[iop_num][chan].handler = handler;
354 return 0;
355}
356
357/*
358 * Complete reception of a message, which just means copying the reply
359 * into the buffer, setting the channel state to MSG_COMPLETE and
360 * notifying the IOP.
361 */
362
363void iop_complete_message(struct iop_msg *msg)
364{
365 int iop_num = msg->iop_num;
366 int chan = msg->channel;
367 int i,offset;
368
369#ifdef DEBUG_IOP
370 printk("iop_complete(%p): iop %d chan %d\n", msg, msg->iop_num, msg->channel);
371#endif
372
373 offset = IOP_ADDR_RECV_MSG + (msg->channel * IOP_MSG_LEN);
374
375 for (i = 0 ; i < IOP_MSG_LEN ; i++, offset++) {
376 iop_writeb(iop_base[iop_num], offset, msg->reply[i]);
377 }
378
379 iop_writeb(iop_base[iop_num],
380 IOP_ADDR_RECV_STATE + chan, IOP_MSG_COMPLETE);
381 iop_interrupt(iop_base[msg->iop_num]);
382
383 iop_free_msg(msg);
384}
385
386/*
387 * Actually put a message into a send channel buffer
388 */
389
390static void iop_do_send(struct iop_msg *msg)
391{
392 volatile struct mac_iop *iop = iop_base[msg->iop_num];
393 int i,offset;
394
395 offset = IOP_ADDR_SEND_MSG + (msg->channel * IOP_MSG_LEN);
396
397 for (i = 0 ; i < IOP_MSG_LEN ; i++, offset++) {
398 iop_writeb(iop, offset, msg->message[i]);
399 }
400
401 iop_writeb(iop, IOP_ADDR_SEND_STATE + msg->channel, IOP_MSG_NEW);
402
403 iop_interrupt(iop);
404}
405
406/*
407 * Handle sending a message on a channel that
408 * has gone into the IOP_MSG_COMPLETE state.
409 */
410
411static void iop_handle_send(uint iop_num, uint chan, struct pt_regs *regs)
412{
413 volatile struct mac_iop *iop = iop_base[iop_num];
414 struct iop_msg *msg,*msg2;
415 int i,offset;
416
417#ifdef DEBUG_IOP
418 printk("iop_handle_send: iop %d channel %d\n", iop_num, chan);
419#endif
420
421 iop_writeb(iop, IOP_ADDR_SEND_STATE + chan, IOP_MSG_IDLE);
422
423 if (!(msg = iop_send_queue[iop_num][chan])) return;
424
425 msg->status = IOP_MSGSTATUS_COMPLETE;
426 offset = IOP_ADDR_SEND_MSG + (chan * IOP_MSG_LEN);
427 for (i = 0 ; i < IOP_MSG_LEN ; i++, offset++) {
428 msg->reply[i] = iop_readb(iop, offset);
429 }
430 if (msg->handler) (*msg->handler)(msg, regs);
431 msg2 = msg;
432 msg = msg->next;
433 iop_free_msg(msg2);
434
435 iop_send_queue[iop_num][chan] = msg;
436 if (msg) iop_do_send(msg);
437}
438
439/*
440 * Handle reception of a message on a channel that has
441 * gone into the IOP_MSG_NEW state.
442 */
443
444static void iop_handle_recv(uint iop_num, uint chan, struct pt_regs *regs)
445{
446 volatile struct mac_iop *iop = iop_base[iop_num];
447 int i,offset;
448 struct iop_msg *msg;
449
450#ifdef DEBUG_IOP
451 printk("iop_handle_recv: iop %d channel %d\n", iop_num, chan);
452#endif
453
454 msg = iop_alloc_msg();
455 msg->iop_num = iop_num;
456 msg->channel = chan;
457 msg->status = IOP_MSGSTATUS_UNSOL;
458 msg->handler = iop_listeners[iop_num][chan].handler;
459
460 offset = IOP_ADDR_RECV_MSG + (chan * IOP_MSG_LEN);
461
462 for (i = 0 ; i < IOP_MSG_LEN ; i++, offset++) {
463 msg->message[i] = iop_readb(iop, offset);
464 }
465
466 iop_writeb(iop, IOP_ADDR_RECV_STATE + chan, IOP_MSG_RCVD);
467
468 /* If there is a listener, call it now. Otherwise complete */
469 /* the message ourselves to avoid possible stalls. */
470
471 if (msg->handler) {
472 (*msg->handler)(msg, regs);
473 } else {
474#ifdef DEBUG_IOP
475 printk("iop_handle_recv: unclaimed message on iop %d channel %d\n", iop_num, chan);
476 printk("iop_handle_recv:");
477 for (i = 0 ; i < IOP_MSG_LEN ; i++) {
478 printk(" %02X", (uint) msg->message[i]);
479 }
480 printk("\n");
481#endif
482 iop_complete_message(msg);
483 }
484}
485
486/*
487 * Send a message
488 *
489 * The message is placed at the end of the send queue. Afterwards if the
490 * channel is idle we force an immediate send of the next message in the
491 * queue.
492 */
493
494int iop_send_message(uint iop_num, uint chan, void *privdata,
495 uint msg_len, __u8 *msg_data,
496 void (*handler)(struct iop_msg *, struct pt_regs *))
497{
498 struct iop_msg *msg, *q;
499
500 if ((iop_num >= NUM_IOPS) || !iop_base[iop_num]) return -EINVAL;
501 if (chan >= NUM_IOP_CHAN) return -EINVAL;
502 if (msg_len > IOP_MSG_LEN) return -EINVAL;
503
504 msg = iop_alloc_msg();
505 if (!msg) return -ENOMEM;
506
507 msg->next = NULL;
508 msg->status = IOP_MSGSTATUS_WAITING;
509 msg->iop_num = iop_num;
510 msg->channel = chan;
511 msg->caller_priv = privdata;
512 memcpy(msg->message, msg_data, msg_len);
513 msg->handler = handler;
514
515 if (!(q = iop_send_queue[iop_num][chan])) {
516 iop_send_queue[iop_num][chan] = msg;
517 } else {
518 while (q->next) q = q->next;
519 q->next = msg;
520 }
521
522 if (iop_readb(iop_base[iop_num],
523 IOP_ADDR_SEND_STATE + chan) == IOP_MSG_IDLE) {
524 iop_do_send(msg);
525 }
526
527 return 0;
528}
529
530/*
531 * Upload code to the shared RAM of an IOP.
532 */
533
534void iop_upload_code(uint iop_num, __u8 *code_start,
535 uint code_len, __u16 shared_ram_start)
536{
537 if ((iop_num >= NUM_IOPS) || !iop_base[iop_num]) return;
538
539 iop_loadaddr(iop_base[iop_num], shared_ram_start);
540
541 while (code_len--) {
542 iop_base[iop_num]->ram_data = *code_start++;
543 }
544}
545
546/*
547 * Download code from the shared RAM of an IOP.
548 */
549
550void iop_download_code(uint iop_num, __u8 *code_start,
551 uint code_len, __u16 shared_ram_start)
552{
553 if ((iop_num >= NUM_IOPS) || !iop_base[iop_num]) return;
554
555 iop_loadaddr(iop_base[iop_num], shared_ram_start);
556
557 while (code_len--) {
558 *code_start++ = iop_base[iop_num]->ram_data;
559 }
560}
561
562/*
563 * Compare the code in the shared RAM of an IOP with a copy in system memory
564 * and return 0 on match or the first nonmatching system memory address on
565 * failure.
566 */
567
568__u8 *iop_compare_code(uint iop_num, __u8 *code_start,
569 uint code_len, __u16 shared_ram_start)
570{
571 if ((iop_num >= NUM_IOPS) || !iop_base[iop_num]) return code_start;
572
573 iop_loadaddr(iop_base[iop_num], shared_ram_start);
574
575 while (code_len--) {
576 if (*code_start != iop_base[iop_num]->ram_data) {
577 return code_start;
578 }
579 code_start++;
580 }
581 return (__u8 *) 0;
582}
583
584/*
585 * Handle an ISM IOP interrupt
586 */
587
588irqreturn_t iop_ism_irq(int irq, void *dev_id, struct pt_regs *regs)
589{
590 uint iop_num = (uint) dev_id;
591 volatile struct mac_iop *iop = iop_base[iop_num];
592 int i,state;
593
594#ifdef DEBUG_IOP
595 printk("iop_ism_irq: status = %02X\n", (uint) iop->status_ctrl);
596#endif
597
598 /* INT0 indicates a state change on an outgoing message channel */
599
600 if (iop->status_ctrl & IOP_INT0) {
601 iop->status_ctrl = IOP_INT0 | IOP_RUN | IOP_AUTOINC;
602#ifdef DEBUG_IOP
603 printk("iop_ism_irq: new status = %02X, send states",
604 (uint) iop->status_ctrl);
605#endif
606 for (i = 0 ; i < NUM_IOP_CHAN ; i++) {
607 state = iop_readb(iop, IOP_ADDR_SEND_STATE + i);
608#ifdef DEBUG_IOP
609 printk(" %02X", state);
610#endif
611 if (state == IOP_MSG_COMPLETE) {
612 iop_handle_send(iop_num, i, regs);
613 }
614 }
615#ifdef DEBUG_IOP
616 printk("\n");
617#endif
618 }
619
620 if (iop->status_ctrl & IOP_INT1) { /* INT1 for incoming msgs */
621 iop->status_ctrl = IOP_INT1 | IOP_RUN | IOP_AUTOINC;
622#ifdef DEBUG_IOP
623 printk("iop_ism_irq: new status = %02X, recv states",
624 (uint) iop->status_ctrl);
625#endif
626 for (i = 0 ; i < NUM_IOP_CHAN ; i++) {
627 state = iop_readb(iop, IOP_ADDR_RECV_STATE + i);
628#ifdef DEBUG_IOP
629 printk(" %02X", state);
630#endif
631 if (state == IOP_MSG_NEW) {
632 iop_handle_recv(iop_num, i, regs);
633 }
634 }
635#ifdef DEBUG_IOP
636 printk("\n");
637#endif
638 }
639 return IRQ_HANDLED;
640}
641
642#ifdef CONFIG_PROC_FS
643
644char *iop_chan_state(int state)
645{
646 switch(state) {
647 case IOP_MSG_IDLE : return "idle ";
648 case IOP_MSG_NEW : return "new ";
649 case IOP_MSG_RCVD : return "received ";
650 case IOP_MSG_COMPLETE : return "completed ";
651 default : return "unknown ";
652 }
653}
654
655int iop_dump_one_iop(char *buf, int iop_num, char *iop_name)
656{
657 int i,len = 0;
658 volatile struct mac_iop *iop = iop_base[iop_num];
659
660 len += sprintf(buf+len, "%s IOP channel states:\n\n", iop_name);
661 len += sprintf(buf+len, "## send_state recv_state device\n");
662 len += sprintf(buf+len, "------------------------------------------------\n");
663 for (i = 0 ; i < NUM_IOP_CHAN ; i++) {
664 len += sprintf(buf+len, "%2d %10s %10s %s\n", i,
665 iop_chan_state(iop_readb(iop, IOP_ADDR_SEND_STATE+i)),
666 iop_chan_state(iop_readb(iop, IOP_ADDR_RECV_STATE+i)),
667 iop_listeners[iop_num][i].handler?
668 iop_listeners[iop_num][i].devname : "");
669
670 }
671 len += sprintf(buf+len, "\n");
672 return len;
673}
674
675static int iop_get_proc_info(char *buf, char **start, off_t pos, int count)
676{
677 int len, cnt;
678
679 cnt = 0;
680 len = sprintf(buf, "IOPs detected:\n\n");
681
682 if (iop_scc_present) {
683 len += sprintf(buf+len, "SCC IOP (%p): status %02X\n",
684 iop_base[IOP_NUM_SCC],
685 (uint) iop_base[IOP_NUM_SCC]->status_ctrl);
686 }
687 if (iop_ism_present) {
688 len += sprintf(buf+len, "ISM IOP (%p): status %02X\n\n",
689 iop_base[IOP_NUM_ISM],
690 (uint) iop_base[IOP_NUM_ISM]->status_ctrl);
691 }
692
693 if (iop_scc_present) {
694 len += iop_dump_one_iop(buf+len, IOP_NUM_SCC, "SCC");
695
696 }
697
698 if (iop_ism_present) {
699 len += iop_dump_one_iop(buf+len, IOP_NUM_ISM, "ISM");
700
701 }
702
703 if (len >= pos) {
704 if (!*start) {
705 *start = buf + pos;
706 cnt = len - pos;
707 } else {
708 cnt += len;
709 }
710 }
711 return (count > cnt) ? cnt : count;
712}
713
714#endif /* CONFIG_PROC_FS */
diff --git a/arch/m68k/mac/mac_ksyms.c b/arch/m68k/mac/mac_ksyms.c
new file mode 100644
index 000000000000..6e37ceb0f3b5
--- /dev/null
+++ b/arch/m68k/mac/mac_ksyms.c
@@ -0,0 +1,8 @@
1#include <linux/module.h>
2#include <asm/ptrace.h>
3#include <asm/traps.h>
4
5/* Says whether we're using A/UX interrupts or not */
6extern int via_alt_mapping;
7
8EXPORT_SYMBOL(via_alt_mapping);
diff --git a/arch/m68k/mac/mac_penguin.S b/arch/m68k/mac/mac_penguin.S
new file mode 100644
index 000000000000..b3ce30b6071d
--- /dev/null
+++ b/arch/m68k/mac/mac_penguin.S
@@ -0,0 +1,75 @@
1.byte \
20x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
30x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
40x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
50x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
60x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
70x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
80x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
90x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
100x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
110x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
120x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
130x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0x0F,0xFF,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
140x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
150x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
160x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xF0,0xFF,0xFF,0x0F,0xF0,0xF0,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
170x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0x00,0xFF,0xFF,0x0F,0xFF,0x00,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
180x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xF0,0x0F,0xFF,0x0F,0xFF,0xF0,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
190x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x0F,0xFF,0x00,0x0F,0x0F,0xFF,0xF0,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
200x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x0F,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
210x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
220x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
230x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
240x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0xF0,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
250x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x0F,0xF0,0x00,0x00,0xFF,0xF0,0x0F,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
260x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x0F,0xF0,0xFF,0xFF,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
270x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xF0,0x00,0x0F,0xFF,0xF0,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
280x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x0F,0xFF,0x00,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
290x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
300x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x0F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
310x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
320x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
330x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,\
340x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,\
350x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,\
360x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,\
370x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,\
380x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x0F,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,\
390x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,\
400x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,\
410x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,\
420x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,\
430x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,\
440x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,\
450x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,\
460x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
470x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
480x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
490x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
500x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
510x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
520x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
530x00,0x00,0x00,0x00,0x0F,0xF0,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
540x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,\
550x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,\
560x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,\
570x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0xF0,0x00,0x00,\
580x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0xF0,0x00,0x00,\
590x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,\
600x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,\
610x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,\
620x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,\
630x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,\
640x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,\
650x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
660x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
670x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0xF0,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,\
680x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0xFF,0xF0,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,\
690xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,\
700x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,\
710x0F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,\
720x00,0x00,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00,\
730x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x00,0x00,\
740x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x00,0x0F,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,\
750x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00
diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c
new file mode 100644
index 000000000000..44c5cd2ad6a8
--- /dev/null
+++ b/arch/m68k/mac/macboing.c
@@ -0,0 +1,309 @@
1/*
2 * Mac bong noise generator. Note - we ought to put a boingy noise
3 * here 8)
4 *
5 * ----------------------------------------------------------------------
6 * 16.11.98:
7 * rewrote some functions, added support for Enhanced ASC (Quadras)
8 * after the NetBSD asc.c console bell patch by Colin Wood/Frederick Bruck
9 * Juergen Mellinger (juergen.mellinger@t-online.de)
10 */
11
12#include <linux/sched.h>
13#include <linux/timer.h>
14
15#include <asm/macintosh.h>
16#include <asm/mac_asc.h>
17
18static int mac_asc_inited;
19/*
20 * dumb triangular wave table
21 */
22static __u8 mac_asc_wave_tab[ 0x800 ];
23
24/*
25 * Alan's original sine table; needs interpolating to 0x800
26 * (hint: interpolate or hardwire [0 -> Pi/2[, it's symmetric)
27 */
28static const signed char sine_data[] = {
29 0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
30 0, -39, -75, -103, -121, -127, -121, -103, -75, -39
31};
32
33/*
34 * where the ASC hides ...
35 */
36static volatile __u8* mac_asc_regs = ( void* )0x50F14000;
37
38/*
39 * sample rate; is this a good default value?
40 */
41static unsigned long mac_asc_samplespersec = 11050;
42static int mac_bell_duration;
43static unsigned long mac_bell_phase; /* 0..2*Pi -> 0..0x800 (wavetable size) */
44static unsigned long mac_bell_phasepersample;
45
46/*
47 * some function protos
48 */
49static void mac_init_asc( void );
50static void mac_nosound( unsigned long );
51static void mac_quadra_start_bell( unsigned int, unsigned int, unsigned int );
52static void mac_quadra_ring_bell( unsigned long );
53static void mac_av_start_bell( unsigned int, unsigned int, unsigned int );
54static void ( *mac_special_bell )( unsigned int, unsigned int, unsigned int );
55
56/*
57 * our timer to start/continue/stop the bell
58 */
59static struct timer_list mac_sound_timer =
60 TIMER_INITIALIZER(mac_nosound, 0, 0);
61
62/*
63 * Sort of initialize the sound chip (called from mac_mksound on the first
64 * beep).
65 */
66static void mac_init_asc( void )
67{
68 int i;
69
70 /*
71 * do some machine specific initialization
72 * BTW:
73 * the NetBSD Quadra patch identifies the Enhanced Apple Sound Chip via
74 * mac_asc_regs[ 0x800 ] & 0xF0 != 0
75 * this makes no sense here, because we have to set the default sample
76 * rate anyway if we want correct frequencies
77 */
78 switch ( macintosh_config->ident )
79 {
80 case MAC_MODEL_IIFX:
81 /*
82 * The IIfx is always special ...
83 */
84 mac_asc_regs = ( void* )0x50010000;
85 break;
86 /*
87 * not sure about how correct this list is
88 * machines with the EASC enhanced apple sound chip
89 */
90 case MAC_MODEL_Q630:
91 case MAC_MODEL_P475:
92 mac_special_bell = mac_quadra_start_bell;
93 mac_asc_samplespersec = 22150;
94 break;
95 case MAC_MODEL_C660:
96 case MAC_MODEL_Q840:
97 /*
98 * The Quadra 660AV and 840AV use the "Singer" custom ASIC for sound I/O.
99 * It appears to be similar to the "AWACS" custom ASIC in the Power Mac
100 * [678]100. Because Singer and AWACS may have a similar hardware
101 * interface, this would imply that the code in drivers/sound/dmasound.c
102 * for AWACS could be used as a basis for Singer support. All we have to
103 * do is figure out how to do DMA on the 660AV/840AV through the PSC and
104 * figure out where the Singer hardware sits in memory. (I'd look in the
105 * vicinity of the AWACS location in a Power Mac [678]100 first, or the
106 * current location of the Apple Sound Chip--ASC--in other Macs.) The
107 * Power Mac [678]100 info can be found in MkLinux Mach kernel sources.
108 *
109 * Quoted from Apple's Tech Info Library, article number 16405:
110 * "Among desktop Macintosh computers, only the 660AV, 840AV, and Power
111 * Macintosh models have 16-bit audio input and output capability
112 * because of the AT&T DSP3210 hardware circuitry and the 16-bit Singer
113 * codec circuitry in the AVs. The Audio Waveform Amplifier and
114 * Converter (AWAC) chip in the Power Macintosh performs the same
115 * 16-bit I/O functionality. The PowerBook 500 series computers
116 * support 16-bit stereo output, but only mono input."
117 *
118 * http://til.info.apple.com/techinfo.nsf/artnum/n16405
119 *
120 * --David Kilzer
121 */
122 mac_special_bell = mac_av_start_bell;
123 break;
124 case MAC_MODEL_Q650:
125 case MAC_MODEL_Q700:
126 case MAC_MODEL_Q800:
127 case MAC_MODEL_Q900:
128 case MAC_MODEL_Q950:
129 /*
130 * Currently not implemented!
131 */
132 mac_special_bell = NULL;
133 break;
134 default:
135 /*
136 * Every switch needs a default
137 */
138 mac_special_bell = NULL;
139 break;
140 }
141
142 /*
143 * init the wave table with a simple triangular wave
144 * A sine wave would sure be nicer here ...
145 */
146 for ( i = 0; i < 0x400; i++ )
147 {
148 mac_asc_wave_tab[ i ] = i / 4;
149 mac_asc_wave_tab[ i + 0x400 ] = 0xFF - i / 4;
150 }
151 mac_asc_inited = 1;
152}
153
154/*
155 * Called to make noise; current single entry to the boing driver.
156 * Does the job for simple ASC, calls other routines else.
157 * XXX Fixme:
158 * Should be split into asc_mksound, easc_mksound, av_mksound and
159 * function pointer set in mac_init_asc which would be called at
160 * init time.
161 * _This_ is rather ugly ...
162 */
163void mac_mksound( unsigned int freq, unsigned int length )
164{
165 __u32 cfreq = ( freq << 5 ) / 468;
166 __u32 flags;
167 int i;
168
169 if ( mac_special_bell == NULL )
170 {
171 /* Do nothing */
172 return;
173 }
174
175 if ( !mac_asc_inited )
176 mac_init_asc();
177
178 if ( mac_special_bell )
179 {
180 mac_special_bell( freq, length, 128 );
181 return;
182 }
183
184 if ( freq < 20 || freq > 20000 || length == 0 )
185 {
186 mac_nosound( 0 );
187 return;
188 }
189
190 local_irq_save(flags);
191
192 del_timer( &mac_sound_timer );
193
194 for ( i = 0; i < 0x800; i++ )
195 mac_asc_regs[ i ] = 0;
196 for ( i = 0; i < 0x800; i++ )
197 mac_asc_regs[ i ] = mac_asc_wave_tab[ i ];
198
199 for ( i = 0; i < 8; i++ )
200 *( __u32* )( ( __u32 )mac_asc_regs + ASC_CONTROL + 0x814 + 8 * i ) = cfreq;
201
202 mac_asc_regs[ 0x807 ] = 0;
203 mac_asc_regs[ ASC_VOLUME ] = 128;
204 mac_asc_regs[ 0x805 ] = 0;
205 mac_asc_regs[ 0x80F ] = 0;
206 mac_asc_regs[ ASC_MODE ] = ASC_MODE_SAMPLE;
207 mac_asc_regs[ ASC_ENABLE ] = ASC_ENABLE_SAMPLE;
208
209 mac_sound_timer.expires = jiffies + length;
210 add_timer( &mac_sound_timer );
211
212 local_irq_restore(flags);
213}
214
215/*
216 * regular ASC: stop whining ..
217 */
218static void mac_nosound( unsigned long ignored )
219{
220 mac_asc_regs[ ASC_ENABLE ] = 0;
221}
222
223/*
224 * EASC entry; init EASC, don't load wavetable, schedule 'start whining'.
225 */
226static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsigned int volume )
227{
228 __u32 flags;
229
230 /* if the bell is already ringing, ring longer */
231 if ( mac_bell_duration > 0 )
232 {
233 mac_bell_duration += length;
234 return;
235 }
236
237 mac_bell_duration = length;
238 mac_bell_phase = 0;
239 mac_bell_phasepersample = ( freq * sizeof( mac_asc_wave_tab ) ) / mac_asc_samplespersec;
240 /* this is reasonably big for small frequencies */
241
242 local_irq_save(flags);
243
244 /* set the volume */
245 mac_asc_regs[ 0x806 ] = volume;
246
247 /* set up the ASC registers */
248 if ( mac_asc_regs[ 0x801 ] != 1 )
249 {
250 /* select mono mode */
251 mac_asc_regs[ 0x807 ] = 0;
252 /* select sampled sound mode */
253 mac_asc_regs[ 0x802 ] = 0;
254 /* ??? */
255 mac_asc_regs[ 0x801 ] = 1;
256 mac_asc_regs[ 0x803 ] |= 0x80;
257 mac_asc_regs[ 0x803 ] &= 0x7F;
258 }
259
260 mac_sound_timer.function = mac_quadra_ring_bell;
261 mac_sound_timer.expires = jiffies + 1;
262 add_timer( &mac_sound_timer );
263
264 local_irq_restore(flags);
265}
266
267/*
268 * EASC 'start/continue whining'; I'm not sure why the above function didn't
269 * already load the wave table, or at least call this one...
270 * This piece keeps reloading the wave table until done.
271 */
272static void mac_quadra_ring_bell( unsigned long ignored )
273{
274 int i, count = mac_asc_samplespersec / HZ;
275 __u32 flags;
276
277 /*
278 * we neither want a sound buffer overflow nor underflow, so we need to match
279 * the number of samples per timer interrupt as exactly as possible.
280 * using the asc interrupt will give better results in the future
281 * ...and the possibility to use a real sample (a boingy noise, maybe...)
282 */
283
284 local_irq_save(flags);
285
286 del_timer( &mac_sound_timer );
287
288 if ( mac_bell_duration-- > 0 )
289 {
290 for ( i = 0; i < count; i++ )
291 {
292 mac_bell_phase += mac_bell_phasepersample;
293 mac_asc_regs[ 0 ] = mac_asc_wave_tab[ mac_bell_phase & ( sizeof( mac_asc_wave_tab ) - 1 ) ];
294 }
295 mac_sound_timer.expires = jiffies + 1;
296 add_timer( &mac_sound_timer );
297 }
298 else
299 mac_asc_regs[ 0x801 ] = 0;
300
301 local_irq_restore(flags);
302}
303
304/*
305 * AV code - please fill in.
306 */
307static void mac_av_start_bell( unsigned int freq, unsigned int length, unsigned int volume )
308{
309}
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
new file mode 100644
index 000000000000..1809601ad903
--- /dev/null
+++ b/arch/m68k/mac/macints.c
@@ -0,0 +1,760 @@
1/*
2 * Macintosh interrupts
3 *
4 * General design:
5 * In contrary to the Amiga and Atari platforms, the Mac hardware seems to
6 * exclusively use the autovector interrupts (the 'generic level0-level7'
7 * interrupts with exception vectors 0x19-0x1f). The following interrupt levels
8 * are used:
9 * 1 - VIA1
10 * - slot 0: one second interrupt (CA2)
11 * - slot 1: VBlank (CA1)
12 * - slot 2: ADB data ready (SR full)
13 * - slot 3: ADB data (CB2)
14 * - slot 4: ADB clock (CB1)
15 * - slot 5: timer 2
16 * - slot 6: timer 1
17 * - slot 7: status of IRQ; signals 'any enabled int.'
18 *
19 * 2 - VIA2 or RBV
20 * - slot 0: SCSI DRQ (CA2)
21 * - slot 1: NUBUS IRQ (CA1) need to read port A to find which
22 * - slot 2: /EXP IRQ (only on IIci)
23 * - slot 3: SCSI IRQ (CB2)
24 * - slot 4: ASC IRQ (CB1)
25 * - slot 5: timer 2 (not on IIci)
26 * - slot 6: timer 1 (not on IIci)
27 * - slot 7: status of IRQ; signals 'any enabled int.'
28 *
29 * 2 - OSS (IIfx only?)
30 * - slot 0: SCSI interrupt
31 * - slot 1: Sound interrupt
32 *
33 * Levels 3-6 vary by machine type. For VIA or RBV Macintoshes:
34 *
35 * 3 - unused (?)
36 *
37 * 4 - SCC (slot number determined by reading RR3 on the SSC itself)
38 * - slot 1: SCC channel A
39 * - slot 2: SCC channel B
40 *
41 * 5 - unused (?)
42 * [serial errors or special conditions seem to raise level 6
43 * interrupts on some models (LC4xx?)]
44 *
45 * 6 - off switch (?)
46 *
47 * For OSS Macintoshes (IIfx only at this point):
48 *
49 * 3 - Nubus interrupt
50 * - slot 0: Slot $9
51 * - slot 1: Slot $A
52 * - slot 2: Slot $B
53 * - slot 3: Slot $C
54 * - slot 4: Slot $D
55 * - slot 5: Slot $E
56 *
57 * 4 - SCC IOP
58 * - slot 1: SCC channel A
59 * - slot 2: SCC channel B
60 *
61 * 5 - ISM IOP (ADB?)
62 *
63 * 6 - unused
64 *
65 * For PSC Macintoshes (660AV, 840AV):
66 *
67 * 3 - PSC level 3
68 * - slot 0: MACE
69 *
70 * 4 - PSC level 4
71 * - slot 1: SCC channel A interrupt
72 * - slot 2: SCC channel B interrupt
73 * - slot 3: MACE DMA
74 *
75 * 5 - PSC level 5
76 *
77 * 6 - PSC level 6
78 *
79 * Finally we have good 'ole level 7, the non-maskable interrupt:
80 *
81 * 7 - NMI (programmer's switch on the back of some Macs)
82 * Also RAM parity error on models which support it (IIc, IIfx?)
83 *
84 * The current interrupt logic looks something like this:
85 *
86 * - We install dispatchers for the autovector interrupts (1-7). These
87 * dispatchers are responsible for querying the hardware (the
88 * VIA/RBV/OSS/PSC chips) to determine the actual interrupt source. Using
89 * this information a machspec interrupt number is generated by placing the
90 * index of the interrupt hardware into the low three bits and the original
91 * autovector interrupt number in the upper 5 bits. The handlers for the
92 * resulting machspec interrupt are then called.
93 *
94 * - Nubus is a special case because its interrupts are hidden behind two
95 * layers of hardware. Nubus interrupts come in as index 1 on VIA #2,
96 * which translates to IRQ number 17. In this spot we install _another_
97 * dispatcher. This dispatcher finds the interrupting slot number (9-F) and
98 * then forms a new machspec interrupt number as above with the slot number
99 * minus 9 in the low three bits and the pseudo-level 7 in the upper five
100 * bits. The handlers for this new machspec interrupt number are then
101 * called. This puts Nubus interrupts into the range 56-62.
102 *
103 * - The Baboon interrupts (used on some PowerBooks) are an even more special
104 * case. They're hidden behind the Nubus slot $C interrupt thus adding a
105 * third layer of indirection. Why oh why did the Apple engineers do that?
106 *
107 * - We support "fast" and "slow" handlers, just like the Amiga port. The
108 * fast handlers are called first and with all interrupts disabled. They
109 * are expected to execute quickly (hence the name). The slow handlers are
110 * called last with interrupts enabled and the interrupt level restored.
111 * They must therefore be reentrant.
112 *
113 * TODO:
114 *
115 */
116
117#include <linux/types.h>
118#include <linux/kernel.h>
119#include <linux/sched.h>
120#include <linux/kernel_stat.h>
121#include <linux/interrupt.h> /* for intr_count */
122#include <linux/delay.h>
123#include <linux/seq_file.h>
124
125#include <asm/system.h>
126#include <asm/irq.h>
127#include <asm/traps.h>
128#include <asm/bootinfo.h>
129#include <asm/machw.h>
130#include <asm/macintosh.h>
131#include <asm/mac_via.h>
132#include <asm/mac_psc.h>
133#include <asm/hwtest.h>
134#include <asm/errno.h>
135#include <asm/macints.h>
136
137#define DEBUG_SPURIOUS
138#define SHUTUP_SONIC
139
140/*
141 * The mac_irq_list array is an array of linked lists of irq_node_t nodes.
142 * Each node contains one handler to be called whenever the interrupt
143 * occurs, with fast handlers listed before slow handlers.
144 */
145
146irq_node_t *mac_irq_list[NUM_MAC_SOURCES];
147
148/* SCC interrupt mask */
149
150static int scc_mask;
151
152/*
153 * VIA/RBV hooks
154 */
155
156extern void via_init(void);
157extern void via_register_interrupts(void);
158extern void via_irq_enable(int);
159extern void via_irq_disable(int);
160extern void via_irq_clear(int);
161extern int via_irq_pending(int);
162
163/*
164 * OSS hooks
165 */
166
167extern int oss_present;
168
169extern void oss_init(void);
170extern void oss_register_interrupts(void);
171extern void oss_irq_enable(int);
172extern void oss_irq_disable(int);
173extern void oss_irq_clear(int);
174extern int oss_irq_pending(int);
175
176/*
177 * PSC hooks
178 */
179
180extern int psc_present;
181
182extern void psc_init(void);
183extern void psc_register_interrupts(void);
184extern void psc_irq_enable(int);
185extern void psc_irq_disable(int);
186extern void psc_irq_clear(int);
187extern int psc_irq_pending(int);
188
189/*
190 * IOP hooks
191 */
192
193extern void iop_register_interrupts(void);
194
195/*
196 * Baboon hooks
197 */
198
199extern int baboon_present;
200
201extern void baboon_init(void);
202extern void baboon_register_interrupts(void);
203extern void baboon_irq_enable(int);
204extern void baboon_irq_disable(int);
205extern void baboon_irq_clear(int);
206extern int baboon_irq_pending(int);
207
208/*
209 * SCC interrupt routines
210 */
211
212static void scc_irq_enable(int);
213static void scc_irq_disable(int);
214
215/*
216 * console_loglevel determines NMI handler function
217 */
218
219extern irqreturn_t mac_bang(int, void *, struct pt_regs *);
220irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *);
221irqreturn_t mac_debug_handler(int, void *, struct pt_regs *);
222
223/* #define DEBUG_MACINTS */
224
225void mac_init_IRQ(void)
226{
227 int i;
228
229#ifdef DEBUG_MACINTS
230 printk("mac_init_IRQ(): Setting things up...\n");
231#endif
232 /* Initialize the IRQ handler lists. Initially each list is empty, */
233
234 for (i = 0; i < NUM_MAC_SOURCES; i++) {
235 mac_irq_list[i] = NULL;
236 }
237
238 scc_mask = 0;
239
240 /* Make sure the SONIC interrupt is cleared or things get ugly */
241#ifdef SHUTUP_SONIC
242 printk("Killing onboard sonic... ");
243 /* This address should hopefully be mapped already */
244 if (hwreg_present((void*)(0x50f0a000))) {
245 *(long *)(0x50f0a014) = 0x7fffL;
246 *(long *)(0x50f0a010) = 0L;
247 }
248 printk("Done.\n");
249#endif /* SHUTUP_SONIC */
250
251 /*
252 * Now register the handlers for the master IRQ handlers
253 * at levels 1-7. Most of the work is done elsewhere.
254 */
255
256 if (oss_present) {
257 oss_register_interrupts();
258 } else {
259 via_register_interrupts();
260 }
261 if (psc_present) psc_register_interrupts();
262 if (baboon_present) baboon_register_interrupts();
263 iop_register_interrupts();
264 cpu_request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI",
265 mac_nmi_handler);
266#ifdef DEBUG_MACINTS
267 printk("mac_init_IRQ(): Done!\n");
268#endif
269}
270
271/*
272 * Routines to work with irq_node_t's on linked lists lifted from
273 * the Amiga code written by Roman Zippel.
274 */
275
276static inline void mac_insert_irq(irq_node_t **list, irq_node_t *node)
277{
278 unsigned long flags;
279 irq_node_t *cur;
280
281 if (!node->dev_id)
282 printk("%s: Warning: dev_id of %s is zero\n",
283 __FUNCTION__, node->devname);
284
285 local_irq_save(flags);
286
287 cur = *list;
288
289 if (node->flags & IRQ_FLG_FAST) {
290 node->flags &= ~IRQ_FLG_SLOW;
291 while (cur && cur->flags & IRQ_FLG_FAST) {
292 list = &cur->next;
293 cur = cur->next;
294 }
295 } else if (node->flags & IRQ_FLG_SLOW) {
296 while (cur) {
297 list = &cur->next;
298 cur = cur->next;
299 }
300 } else {
301 while (cur && !(cur->flags & IRQ_FLG_SLOW)) {
302 list = &cur->next;
303 cur = cur->next;
304 }
305 }
306
307 node->next = cur;
308 *list = node;
309
310 local_irq_restore(flags);
311}
312
313static inline void mac_delete_irq(irq_node_t **list, void *dev_id)
314{
315 unsigned long flags;
316 irq_node_t *node;
317
318 local_irq_save(flags);
319
320 for (node = *list; node; list = &node->next, node = *list) {
321 if (node->dev_id == dev_id) {
322 *list = node->next;
323 /* Mark it as free. */
324 node->handler = NULL;
325 local_irq_restore(flags);
326 return;
327 }
328 }
329 local_irq_restore(flags);
330 printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
331}
332
333/*
334 * Call all the handlers for a given interrupt. Fast handlers are called
335 * first followed by slow handlers.
336 *
337 * This code taken from the original Amiga code written by Roman Zippel.
338 */
339
340void mac_do_irq_list(int irq, struct pt_regs *fp)
341{
342 irq_node_t *node, *slow_nodes;
343 unsigned long flags;
344
345 kstat_cpu(0).irqs[irq]++;
346
347#ifdef DEBUG_SPURIOUS
348 if (!mac_irq_list[irq] && (console_loglevel > 7)) {
349 printk("mac_do_irq_list: spurious interrupt %d!\n", irq);
350 return;
351 }
352#endif
353
354 /* serve first fast and normal handlers */
355 for (node = mac_irq_list[irq];
356 node && (!(node->flags & IRQ_FLG_SLOW));
357 node = node->next)
358 node->handler(irq, node->dev_id, fp);
359 if (!node) return;
360 local_save_flags(flags);
361 local_irq_restore((flags & ~0x0700) | (fp->sr & 0x0700));
362 /* if slow handlers exists, serve them now */
363 slow_nodes = node;
364 for (; node; node = node->next) {
365 node->handler(irq, node->dev_id, fp);
366 }
367}
368
369/*
370 * mac_enable_irq - enable an interrupt source
371 * mac_disable_irq - disable an interrupt source
372 * mac_clear_irq - clears a pending interrupt
373 * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending)
374 *
375 * These routines are just dispatchers to the VIA/OSS/PSC routines.
376 */
377
378void mac_enable_irq (unsigned int irq)
379{
380 int irq_src = IRQ_SRC(irq);
381
382 switch(irq_src) {
383 case 1: via_irq_enable(irq);
384 break;
385 case 2:
386 case 7: if (oss_present) {
387 oss_irq_enable(irq);
388 } else {
389 via_irq_enable(irq);
390 }
391 break;
392 case 3:
393 case 4:
394 case 5:
395 case 6: if (psc_present) {
396 psc_irq_enable(irq);
397 } else if (oss_present) {
398 oss_irq_enable(irq);
399 } else if (irq_src == 4) {
400 scc_irq_enable(irq);
401 }
402 break;
403 case 8: if (baboon_present) {
404 baboon_irq_enable(irq);
405 }
406 break;
407 }
408}
409
410void mac_disable_irq (unsigned int irq)
411{
412 int irq_src = IRQ_SRC(irq);
413
414 switch(irq_src) {
415 case 1: via_irq_disable(irq);
416 break;
417 case 2:
418 case 7: if (oss_present) {
419 oss_irq_disable(irq);
420 } else {
421 via_irq_disable(irq);
422 }
423 break;
424 case 3:
425 case 4:
426 case 5:
427 case 6: if (psc_present) {
428 psc_irq_disable(irq);
429 } else if (oss_present) {
430 oss_irq_disable(irq);
431 } else if (irq_src == 4) {
432 scc_irq_disable(irq);
433 }
434 break;
435 case 8: if (baboon_present) {
436 baboon_irq_disable(irq);
437 }
438 break;
439 }
440}
441
442void mac_clear_irq( unsigned int irq )
443{
444 switch(IRQ_SRC(irq)) {
445 case 1: via_irq_clear(irq);
446 break;
447 case 2:
448 case 7: if (oss_present) {
449 oss_irq_clear(irq);
450 } else {
451 via_irq_clear(irq);
452 }
453 break;
454 case 3:
455 case 4:
456 case 5:
457 case 6: if (psc_present) {
458 psc_irq_clear(irq);
459 } else if (oss_present) {
460 oss_irq_clear(irq);
461 }
462 break;
463 case 8: if (baboon_present) {
464 baboon_irq_clear(irq);
465 }
466 break;
467 }
468}
469
470int mac_irq_pending( unsigned int irq )
471{
472 switch(IRQ_SRC(irq)) {
473 case 1: return via_irq_pending(irq);
474 case 2:
475 case 7: if (oss_present) {
476 return oss_irq_pending(irq);
477 } else {
478 return via_irq_pending(irq);
479 }
480 case 3:
481 case 4:
482 case 5:
483 case 6: if (psc_present) {
484 return psc_irq_pending(irq);
485 } else if (oss_present) {
486 return oss_irq_pending(irq);
487 }
488 }
489 return 0;
490}
491
492/*
493 * Add an interrupt service routine to an interrupt source.
494 * Returns 0 on success.
495 *
496 * FIXME: You can register interrupts on nonexistent source (ie PSC4 on a
497 * non-PSC machine). We should return -EINVAL in those cases.
498 */
499
500int mac_request_irq(unsigned int irq,
501 irqreturn_t (*handler)(int, void *, struct pt_regs *),
502 unsigned long flags, const char *devname, void *dev_id)
503{
504 irq_node_t *node;
505
506#ifdef DEBUG_MACINTS
507 printk ("%s: irq %d requested for %s\n", __FUNCTION__, irq, devname);
508#endif
509
510 if (irq < VIA1_SOURCE_BASE) {
511 return cpu_request_irq(irq, handler, flags, devname, dev_id);
512 }
513
514 if (irq >= NUM_MAC_SOURCES) {
515 printk ("%s: unknown irq %d requested by %s\n",
516 __FUNCTION__, irq, devname);
517 }
518
519 /* Get a node and stick it onto the right list */
520
521 if (!(node = new_irq_node())) return -ENOMEM;
522
523 node->handler = handler;
524 node->flags = flags;
525 node->dev_id = dev_id;
526 node->devname = devname;
527 node->next = NULL;
528 mac_insert_irq(&mac_irq_list[irq], node);
529
530 /* Now enable the IRQ source */
531
532 mac_enable_irq(irq);
533
534 return 0;
535}
536
537/*
538 * Removes an interrupt service routine from an interrupt source.
539 */
540
541void mac_free_irq(unsigned int irq, void *dev_id)
542{
543#ifdef DEBUG_MACINTS
544 printk ("%s: irq %d freed by %p\n", __FUNCTION__, irq, dev_id);
545#endif
546
547 if (irq < VIA1_SOURCE_BASE) {
548 cpu_free_irq(irq, dev_id);
549 return;
550 }
551
552 if (irq >= NUM_MAC_SOURCES) {
553 printk ("%s: unknown irq %d freed\n",
554 __FUNCTION__, irq);
555 return;
556 }
557
558 mac_delete_irq(&mac_irq_list[irq], dev_id);
559
560 /* If the list for this interrupt is */
561 /* empty then disable the source. */
562
563 if (!mac_irq_list[irq]) {
564 mac_disable_irq(irq);
565 }
566}
567
568/*
569 * Generate a pretty listing for /proc/interrupts
570 *
571 * By the time we're called the autovector interrupt list has already been
572 * generated, so we just need to do the machspec interrupts.
573 *
574 * 990506 (jmt) - rewritten to handle chained machspec interrupt handlers.
575 * Also removed display of num_spurious it is already
576 * displayed for us as autovector irq 0.
577 */
578
579int show_mac_interrupts(struct seq_file *p, void *v)
580{
581 int i;
582 irq_node_t *node;
583 char *base;
584
585 /* Don't do Nubus interrupts in this loop; we do them separately */
586 /* below so that we can print slot numbers instead of IRQ numbers */
587
588 for (i = VIA1_SOURCE_BASE ; i < NUM_MAC_SOURCES ; ++i) {
589
590 /* Nonexistant interrupt or nothing registered; skip it. */
591
592 if ((node = mac_irq_list[i]) == NULL) continue;
593 if (node->flags & IRQ_FLG_STD) continue;
594
595 base = "";
596 switch(IRQ_SRC(i)) {
597 case 1: base = "via1";
598 break;
599 case 2: if (oss_present) {
600 base = "oss";
601 } else {
602 base = "via2";
603 }
604 break;
605 case 3:
606 case 4:
607 case 5:
608 case 6: if (psc_present) {
609 base = "psc";
610 } else if (oss_present) {
611 base = "oss";
612 } else {
613 if (IRQ_SRC(i) == 4) base = "scc";
614 }
615 break;
616 case 7: base = "nbus";
617 break;
618 case 8: base = "bbn";
619 break;
620 }
621 seq_printf(p, "%4s %2d: %10u ", base, i, kstat_cpu(0).irqs[i]);
622
623 do {
624 if (node->flags & IRQ_FLG_FAST) {
625 seq_puts(p, "F ");
626 } else if (node->flags & IRQ_FLG_SLOW) {
627 seq_puts(p, "S ");
628 } else {
629 seq_puts(p, " ");
630 }
631 seq_printf(p, "%s\n", node->devname);
632 if ((node = node->next)) {
633 seq_puts(p, " ");
634 }
635 } while(node);
636
637 }
638 return 0;
639}
640
641void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
642{
643#ifdef DEBUG_SPURIOUS
644 printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
645#endif
646}
647
648static int num_debug[8];
649
650irqreturn_t mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
651{
652 if (num_debug[irq] < 10) {
653 printk("DEBUG: Unexpected IRQ %d\n", irq);
654 num_debug[irq]++;
655 }
656 return IRQ_HANDLED;
657}
658
659static int in_nmi;
660static volatile int nmi_hold;
661
662irqreturn_t mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
663{
664 int i;
665 /*
666 * generate debug output on NMI switch if 'debug' kernel option given
667 * (only works with Penguin!)
668 */
669
670 in_nmi++;
671 for (i=0; i<100; i++)
672 udelay(1000);
673
674 if (in_nmi == 1) {
675 nmi_hold = 1;
676 printk("... pausing, press NMI to resume ...");
677 } else {
678 printk(" ok!\n");
679 nmi_hold = 0;
680 }
681
682 barrier();
683
684 while (nmi_hold == 1)
685 udelay(1000);
686
687 if ( console_loglevel >= 8 ) {
688#if 0
689 show_state();
690 printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp);
691 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
692 fp->d0, fp->d1, fp->d2, fp->d3);
693 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
694 fp->d4, fp->d5, fp->a0, fp->a1);
695
696 if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
697 printk("Corrupted stack page\n");
698 printk("Process %s (pid: %d, stackpage=%08lx)\n",
699 current->comm, current->pid, current->kernel_stack_page);
700 if (intr_count == 1)
701 dump_stack((struct frame *)fp);
702#else
703 /* printk("NMI "); */
704#endif
705 }
706 in_nmi--;
707 return IRQ_HANDLED;
708}
709
710/*
711 * Simple routines for masking and unmasking
712 * SCC interrupts in cases where this can't be
713 * done in hardware (only the PSC can do that.)
714 */
715
716static void scc_irq_enable(int irq) {
717 int irq_idx = IRQ_IDX(irq);
718
719 scc_mask |= (1 << irq_idx);
720}
721
722static void scc_irq_disable(int irq) {
723 int irq_idx = IRQ_IDX(irq);
724
725 scc_mask &= ~(1 << irq_idx);
726}
727
728/*
729 * SCC master interrupt handler. We have to do a bit of magic here
730 * to figure out what channel gave us the interrupt; putting this
731 * here is cleaner than hacking it into drivers/char/macserial.c.
732 */
733
734void mac_scc_dispatch(int irq, void *dev_id, struct pt_regs *regs)
735{
736 volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2;
737 unsigned char reg;
738 unsigned long flags;
739
740 /* Read RR3 from the chip. Always do this on channel A */
741 /* This must be an atomic operation so disable irqs. */
742
743 local_irq_save(flags);
744 *scc = 3;
745 reg = *scc;
746 local_irq_restore(flags);
747
748 /* Now dispatch. Bits 0-2 are for channel B and */
749 /* bits 3-5 are for channel A. We can safely */
750 /* ignore the remaining bits here. */
751 /* */
752 /* Note that we're ignoring scc_mask for now. */
753 /* If we actually mask the ints then we tend to */
754 /* get hammered by very persistent SCC irqs, */
755 /* and since they're autovector interrupts they */
756 /* pretty much kill the system. */
757
758 if (reg & 0x38) mac_do_irq_list(IRQ_SCCA, regs);
759 if (reg & 0x07) mac_do_irq_list(IRQ_SCCB, regs);
760}
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
new file mode 100644
index 000000000000..5b80d7cd954a
--- /dev/null
+++ b/arch/m68k/mac/misc.c
@@ -0,0 +1,651 @@
1/*
2 * Miscellaneous Mac68K-specific stuff
3 */
4
5#include <linux/config.h>
6#include <linux/types.h>
7#include <linux/errno.h>
8#include <linux/miscdevice.h>
9#include <linux/kernel.h>
10#include <linux/delay.h>
11#include <linux/sched.h>
12#include <linux/slab.h>
13#include <linux/time.h>
14#include <linux/rtc.h>
15#include <linux/mm.h>
16
17#include <linux/adb.h>
18#include <linux/cuda.h>
19#include <linux/pmu.h>
20
21#include <asm/uaccess.h>
22#include <asm/io.h>
23#include <asm/rtc.h>
24#include <asm/system.h>
25#include <asm/segment.h>
26#include <asm/setup.h>
27#include <asm/macintosh.h>
28#include <asm/mac_via.h>
29#include <asm/mac_oss.h>
30
31#define BOOTINFO_COMPAT_1_0
32#include <asm/bootinfo.h>
33#include <asm/machdep.h>
34
35/* Offset between Unix time (1970-based) and Mac time (1904-based) */
36
37#define RTC_OFFSET 2082844800
38
39extern struct mac_booter_data mac_bi_data;
40static void (*rom_reset)(void);
41
42#ifdef CONFIG_ADB
43/*
44 * Return the current time as the number of seconds since January 1, 1904.
45 */
46
47static long adb_read_time(void)
48{
49 volatile struct adb_request req;
50 long time;
51
52 adb_request((struct adb_request *) &req, NULL,
53 ADBREQ_RAW|ADBREQ_SYNC,
54 2, CUDA_PACKET, CUDA_GET_TIME);
55
56 time = (req.reply[3] << 24) | (req.reply[4] << 16)
57 | (req.reply[5] << 8) | req.reply[6];
58 return time - RTC_OFFSET;
59}
60
61/*
62 * Set the current system time
63 */
64
65static void adb_write_time(long data)
66{
67 volatile struct adb_request req;
68
69 data += RTC_OFFSET;
70
71 adb_request((struct adb_request *) &req, NULL,
72 ADBREQ_RAW|ADBREQ_SYNC,
73 6, CUDA_PACKET, CUDA_SET_TIME,
74 (data >> 24) & 0xFF, (data >> 16) & 0xFF,
75 (data >> 8) & 0xFF, data & 0xFF);
76}
77
78/*
79 * Get a byte from the NVRAM
80 */
81
82static __u8 adb_read_pram(int offset)
83{
84 volatile struct adb_request req;
85
86 adb_request((struct adb_request *) &req, NULL,
87 ADBREQ_RAW|ADBREQ_SYNC,
88 4, CUDA_PACKET, CUDA_GET_PRAM,
89 (offset >> 8) & 0xFF, offset & 0xFF);
90 return req.reply[3];
91}
92
93/*
94 * Write a byte to the NVRAM
95 */
96
97static void adb_write_pram(int offset, __u8 data)
98{
99 volatile struct adb_request req;
100
101 adb_request((struct adb_request *) &req, NULL,
102 ADBREQ_RAW|ADBREQ_SYNC,
103 5, CUDA_PACKET, CUDA_SET_PRAM,
104 (offset >> 8) & 0xFF, offset & 0xFF,
105 data);
106}
107#endif /* CONFIG_ADB */
108
109/*
110 * VIA PRAM/RTC access routines
111 *
112 * Must be called with interrupts disabled and
113 * the RTC should be enabled.
114 */
115
116static __u8 via_pram_readbyte(void)
117{
118 int i,reg;
119 __u8 data;
120
121 reg = via1[vBufB] & ~VIA1B_vRTCClk;
122
123 /* Set the RTC data line to be an input. */
124
125 via1[vDirB] &= ~VIA1B_vRTCData;
126
127 /* The bits of the byte come out in MSB order */
128
129 data = 0;
130 for (i = 0 ; i < 8 ; i++) {
131 via1[vBufB] = reg;
132 via1[vBufB] = reg | VIA1B_vRTCClk;
133 data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData);
134 }
135
136 /* Return RTC data line to output state */
137
138 via1[vDirB] |= VIA1B_vRTCData;
139
140 return data;
141}
142
143static void via_pram_writebyte(__u8 data)
144{
145 int i,reg,bit;
146
147 reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
148
149 /* The bits of the byte go in in MSB order */
150
151 for (i = 0 ; i < 8 ; i++) {
152 bit = data & 0x80? 1 : 0;
153 data <<= 1;
154 via1[vBufB] = reg | bit;
155 via1[vBufB] = reg | bit | VIA1B_vRTCClk;
156 }
157}
158
159/*
160 * Execute a VIA PRAM/RTC command. For read commands
161 * data should point to a one-byte buffer for the
162 * resulting data. For write commands it should point
163 * to the data byte to for the command.
164 *
165 * This function disables all interrupts while running.
166 */
167
168static void via_pram_command(int command, __u8 *data)
169{
170 unsigned long flags;
171 int is_read;
172
173 local_irq_save(flags);
174
175 /* Enable the RTC and make sure the strobe line is high */
176
177 via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
178
179 if (command & 0xFF00) { /* extended (two-byte) command */
180 via_pram_writebyte((command & 0xFF00) >> 8);
181 via_pram_writebyte(command & 0xFF);
182 is_read = command & 0x8000;
183 } else { /* one-byte command */
184 via_pram_writebyte(command);
185 is_read = command & 0x80;
186 }
187 if (is_read) {
188 *data = via_pram_readbyte();
189 } else {
190 via_pram_writebyte(*data);
191 }
192
193 /* All done, disable the RTC */
194
195 via1[vBufB] |= VIA1B_vRTCEnb;
196
197 local_irq_restore(flags);
198}
199
200static __u8 via_read_pram(int offset)
201{
202 return 0;
203}
204
205static void via_write_pram(int offset, __u8 data)
206{
207}
208
209/*
210 * Return the current time in seconds since January 1, 1904.
211 *
212 * This only works on machines with the VIA-based PRAM/RTC, which
213 * is basically any machine with Mac II-style ADB.
214 */
215
216static long via_read_time(void)
217{
218 union {
219 __u8 cdata[4];
220 long idata;
221 } result, last_result;
222 int ct;
223
224 /*
225 * The NetBSD guys say to loop until you get the same reading
226 * twice in a row.
227 */
228
229 ct = 0;
230 do {
231 if (++ct > 10) {
232 printk("via_read_time: couldn't get valid time, "
233 "last read = 0x%08lx and 0x%08lx\n",
234 last_result.idata, result.idata);
235 break;
236 }
237
238 last_result.idata = result.idata;
239 result.idata = 0;
240
241 via_pram_command(0x81, &result.cdata[3]);
242 via_pram_command(0x85, &result.cdata[2]);
243 via_pram_command(0x89, &result.cdata[1]);
244 via_pram_command(0x8D, &result.cdata[0]);
245 } while (result.idata != last_result.idata);
246
247 return result.idata - RTC_OFFSET;
248}
249
250/*
251 * Set the current time to a number of seconds since January 1, 1904.
252 *
253 * This only works on machines with the VIA-based PRAM/RTC, which
254 * is basically any machine with Mac II-style ADB.
255 */
256
257static void via_write_time(long time)
258{
259 union {
260 __u8 cdata[4];
261 long idata;
262 } data;
263 __u8 temp;
264
265 /* Clear the write protect bit */
266
267 temp = 0x55;
268 via_pram_command(0x35, &temp);
269
270 data.idata = time + RTC_OFFSET;
271 via_pram_command(0x01, &data.cdata[3]);
272 via_pram_command(0x05, &data.cdata[2]);
273 via_pram_command(0x09, &data.cdata[1]);
274 via_pram_command(0x0D, &data.cdata[0]);
275
276 /* Set the write protect bit */
277
278 temp = 0xD5;
279 via_pram_command(0x35, &temp);
280}
281
282static void via_shutdown(void)
283{
284 if (rbv_present) {
285 via2[rBufB] &= ~0x04;
286 } else {
287 /* Direction of vDirB is output */
288 via2[vDirB] |= 0x04;
289 /* Send a value of 0 on that line */
290 via2[vBufB] &= ~0x04;
291 mdelay(1000);
292 }
293}
294
295/*
296 * FIXME: not sure how this is supposed to work exactly...
297 */
298
299static void oss_shutdown(void)
300{
301 oss->rom_ctrl = OSS_POWEROFF;
302}
303
304#ifdef CONFIG_ADB_CUDA
305
306static void cuda_restart(void)
307{
308 adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
309 2, CUDA_PACKET, CUDA_RESET_SYSTEM);
310}
311
312static void cuda_shutdown(void)
313{
314 adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
315 2, CUDA_PACKET, CUDA_POWERDOWN);
316}
317
318#endif /* CONFIG_ADB_CUDA */
319
320#ifdef CONFIG_ADB_PMU
321
322void pmu_restart(void)
323{
324 adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
325 3, PMU_PACKET, PMU_SET_INTR_MASK,
326 PMU_INT_ADB|PMU_INT_TICK);
327
328 adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
329 2, PMU_PACKET, PMU_RESET);
330}
331
332void pmu_shutdown(void)
333{
334 adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
335 3, PMU_PACKET, PMU_SET_INTR_MASK,
336 PMU_INT_ADB|PMU_INT_TICK);
337
338 adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
339 6, PMU_PACKET, PMU_SHUTDOWN,
340 'M', 'A', 'T', 'T');
341}
342
343#endif /* CONFIG_ADB_PMU */
344
345/*
346 *-------------------------------------------------------------------
347 * Below this point are the generic routines; they'll dispatch to the
348 * correct routine for the hardware on which we're running.
349 *-------------------------------------------------------------------
350 */
351
352void mac_pram_read(int offset, __u8 *buffer, int len)
353{
354 __u8 (*func)(int) = NULL;
355 int i;
356
357 if (macintosh_config->adb_type == MAC_ADB_IISI ||
358 macintosh_config->adb_type == MAC_ADB_PB1 ||
359 macintosh_config->adb_type == MAC_ADB_PB2 ||
360 macintosh_config->adb_type == MAC_ADB_CUDA) {
361#ifdef CONFIG_ADB
362 func = adb_read_pram;
363#else
364 return;
365#endif
366 } else {
367 func = via_read_pram;
368 }
369 for (i = 0 ; i < len ; i++) {
370 buffer[i] = (*func)(offset++);
371 }
372}
373
374void mac_pram_write(int offset, __u8 *buffer, int len)
375{
376 void (*func)(int, __u8) = NULL;
377 int i;
378
379 if (macintosh_config->adb_type == MAC_ADB_IISI ||
380 macintosh_config->adb_type == MAC_ADB_PB1 ||
381 macintosh_config->adb_type == MAC_ADB_PB2 ||
382 macintosh_config->adb_type == MAC_ADB_CUDA) {
383#ifdef CONFIG_ADB
384 func = adb_write_pram;
385#else
386 return;
387#endif
388 } else {
389 func = via_write_pram;
390 }
391 for (i = 0 ; i < len ; i++) {
392 (*func)(offset++, buffer[i]);
393 }
394}
395
396void mac_poweroff(void)
397{
398 /*
399 * MAC_ADB_IISI may need to be moved up here if it doesn't actually
400 * work using the ADB packet method. --David Kilzer
401 */
402
403 if (oss_present) {
404 oss_shutdown();
405 } else if (macintosh_config->adb_type == MAC_ADB_II) {
406 via_shutdown();
407#ifdef CONFIG_ADB_CUDA
408 } else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
409 cuda_shutdown();
410#endif
411#ifdef CONFIG_ADB_PMU
412 } else if (macintosh_config->adb_type == MAC_ADB_PB1
413 || macintosh_config->adb_type == MAC_ADB_PB2) {
414 pmu_shutdown();
415#endif
416 }
417 local_irq_enable();
418 printk("It is now safe to turn off your Macintosh.\n");
419 while(1);
420}
421
422void mac_reset(void)
423{
424 if (macintosh_config->adb_type == MAC_ADB_II) {
425 unsigned long flags;
426
427 /* need ROMBASE in booter */
428 /* indeed, plus need to MAP THE ROM !! */
429
430 if (mac_bi_data.rombase == 0)
431 mac_bi_data.rombase = 0x40800000;
432
433 /* works on some */
434 rom_reset = (void *) (mac_bi_data.rombase + 0xa);
435
436 if (macintosh_config->ident == MAC_MODEL_SE30) {
437 /*
438 * MSch: Machines known to crash on ROM reset ...
439 */
440 } else {
441 local_irq_save(flags);
442
443 rom_reset();
444
445 local_irq_restore(flags);
446 }
447#ifdef CONFIG_ADB_CUDA
448 } else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
449 cuda_restart();
450#endif
451#ifdef CONFIG_ADB_PMU
452 } else if (macintosh_config->adb_type == MAC_ADB_PB1
453 || macintosh_config->adb_type == MAC_ADB_PB2) {
454 pmu_restart();
455#endif
456 } else if (CPU_IS_030) {
457
458 /* 030-specific reset routine. The idea is general, but the
459 * specific registers to reset are '030-specific. Until I
460 * have a non-030 machine, I can't test anything else.
461 * -- C. Scott Ananian <cananian@alumni.princeton.edu>
462 */
463
464 unsigned long rombase = 0x40000000;
465
466 /* make a 1-to-1 mapping, using the transparent tran. reg. */
467 unsigned long virt = (unsigned long) mac_reset;
468 unsigned long phys = virt_to_phys(mac_reset);
469 unsigned long offset = phys-virt;
470 local_irq_disable(); /* lets not screw this up, ok? */
471 __asm__ __volatile__(".chip 68030\n\t"
472 "pmove %0,%/tt0\n\t"
473 ".chip 68k"
474 : : "m" ((phys&0xFF000000)|0x8777));
475 /* Now jump to physical address so we can disable MMU */
476 __asm__ __volatile__(
477 ".chip 68030\n\t"
478 "lea %/pc@(1f),%/a0\n\t"
479 "addl %0,%/a0\n\t"/* fixup target address and stack ptr */
480 "addl %0,%/sp\n\t"
481 "pflusha\n\t"
482 "jmp %/a0@\n\t" /* jump into physical memory */
483 "0:.long 0\n\t" /* a constant zero. */
484 /* OK. Now reset everything and jump to reset vector. */
485 "1:\n\t"
486 "lea %/pc@(0b),%/a0\n\t"
487 "pmove %/a0@, %/tc\n\t" /* disable mmu */
488 "pmove %/a0@, %/tt0\n\t" /* disable tt0 */
489 "pmove %/a0@, %/tt1\n\t" /* disable tt1 */
490 "movel #0, %/a0\n\t"
491 "movec %/a0, %/vbr\n\t" /* clear vector base register */
492 "movec %/a0, %/cacr\n\t" /* disable caches */
493 "movel #0x0808,%/a0\n\t"
494 "movec %/a0, %/cacr\n\t" /* flush i&d caches */
495 "movew #0x2700,%/sr\n\t" /* set up status register */
496 "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
497 "movec %/a0, %/isp\n\t"
498 "movel %1@(0x4),%/a0\n\t" /* load reset vector */
499 "reset\n\t" /* reset external devices */
500 "jmp %/a0@\n\t" /* jump to the reset vector */
501 ".chip 68k"
502 : : "r" (offset), "a" (rombase) : "a0");
503 }
504
505 /* should never get here */
506 local_irq_enable();
507 printk ("Restart failed. Please restart manually.\n");
508 while(1);
509}
510
511/*
512 * This function translates seconds since 1970 into a proper date.
513 *
514 * Algorithm cribbed from glibc2.1, __offtime().
515 */
516#define SECS_PER_MINUTE (60)
517#define SECS_PER_HOUR (SECS_PER_MINUTE * 60)
518#define SECS_PER_DAY (SECS_PER_HOUR * 24)
519
520static void unmktime(unsigned long time, long offset,
521 int *yearp, int *monp, int *dayp,
522 int *hourp, int *minp, int *secp)
523{
524 /* How many days come before each month (0-12). */
525 static const unsigned short int __mon_yday[2][13] =
526 {
527 /* Normal years. */
528 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
529 /* Leap years. */
530 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
531 };
532 long int days, rem, y, wday, yday;
533 const unsigned short int *ip;
534
535 days = time / SECS_PER_DAY;
536 rem = time % SECS_PER_DAY;
537 rem += offset;
538 while (rem < 0) {
539 rem += SECS_PER_DAY;
540 --days;
541 }
542 while (rem >= SECS_PER_DAY) {
543 rem -= SECS_PER_DAY;
544 ++days;
545 }
546 *hourp = rem / SECS_PER_HOUR;
547 rem %= SECS_PER_HOUR;
548 *minp = rem / SECS_PER_MINUTE;
549 *secp = rem % SECS_PER_MINUTE;
550 /* January 1, 1970 was a Thursday. */
551 wday = (4 + days) % 7; /* Day in the week. Not currently used */
552 if (wday < 0) wday += 7;
553 y = 1970;
554
555#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
556#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
557#define __isleap(year) \
558 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
559
560 while (days < 0 || days >= (__isleap (y) ? 366 : 365))
561 {
562 /* Guess a corrected year, assuming 365 days per year. */
563 long int yg = y + days / 365 - (days % 365 < 0);
564
565 /* Adjust DAYS and Y to match the guessed year. */
566 days -= ((yg - y) * 365
567 + LEAPS_THRU_END_OF (yg - 1)
568 - LEAPS_THRU_END_OF (y - 1));
569 y = yg;
570 }
571 *yearp = y - 1900;
572 yday = days; /* day in the year. Not currently used. */
573 ip = __mon_yday[__isleap(y)];
574 for (y = 11; days < (long int) ip[y]; --y)
575 continue;
576 days -= ip[y];
577 *monp = y;
578 *dayp = days + 1; /* day in the month */
579 return;
580}
581
582/*
583 * Read/write the hardware clock.
584 */
585
586int mac_hwclk(int op, struct rtc_time *t)
587{
588 unsigned long now;
589
590 if (!op) { /* read */
591 if (macintosh_config->adb_type == MAC_ADB_II) {
592 now = via_read_time();
593 } else
594#ifdef CONFIG_ADB
595 if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
596 (macintosh_config->adb_type == MAC_ADB_PB1) ||
597 (macintosh_config->adb_type == MAC_ADB_PB2) ||
598 (macintosh_config->adb_type == MAC_ADB_CUDA)) {
599 now = adb_read_time();
600 } else
601#endif
602 if (macintosh_config->adb_type == MAC_ADB_IOP) {
603 now = via_read_time();
604 } else {
605 now = 0;
606 }
607
608 t->tm_wday = 0;
609 unmktime(now, 0,
610 &t->tm_year, &t->tm_mon, &t->tm_mday,
611 &t->tm_hour, &t->tm_min, &t->tm_sec);
612 printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n",
613 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
614 } else { /* write */
615 printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n",
616 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
617
618#if 0 /* it trashes my rtc */
619 now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
620 t->tm_hour, t->tm_min, t->tm_sec);
621
622 if (macintosh_config->adb_type == MAC_ADB_II) {
623 via_write_time(now);
624 } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
625 (macintosh_config->adb_type == MAC_ADB_PB1) ||
626 (macintosh_config->adb_type == MAC_ADB_PB2) ||
627 (macintosh_config->adb_type == MAC_ADB_CUDA)) {
628 adb_write_time(now);
629 } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
630 via_write_time(now);
631 }
632#endif
633 }
634 return 0;
635}
636
637/*
638 * Set minutes/seconds in the hardware clock
639 */
640
641int mac_set_clock_mmss (unsigned long nowtime)
642{
643 struct rtc_time now;
644
645 mac_hwclk(0, &now);
646 now.tm_sec = nowtime % 60;
647 now.tm_min = (nowtime / 60) % 60;
648 mac_hwclk(1, &now);
649
650 return 0;
651}
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
new file mode 100644
index 000000000000..333547692724
--- /dev/null
+++ b/arch/m68k/mac/oss.c
@@ -0,0 +1,301 @@
1/*
2 * OSS handling
3 * Written by Joshua M. Thompson (funaho@jurai.org)
4 *
5 *
6 * This chip is used in the IIfx in place of VIA #2. It acts like a fancy
7 * VIA chip with prorammable interrupt levels.
8 *
9 * 990502 (jmt) - Major rewrite for new interrupt architecture as well as some
10 * recent insights into OSS operational details.
11 * 990610 (jmt) - Now taking fulll advantage of the OSS. Interrupts are mapped
12 * to mostly match the A/UX interrupt scheme supported on the
13 * VIA side. Also added support for enabling the ISM irq again
14 * since we now have a functional IOP manager.
15 */
16
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/mm.h>
20#include <linux/delay.h>
21#include <linux/init.h>
22
23#include <asm/bootinfo.h>
24#include <asm/machw.h>
25#include <asm/macintosh.h>
26#include <asm/macints.h>
27#include <asm/mac_via.h>
28#include <asm/mac_oss.h>
29
30int oss_present;
31volatile struct mac_oss *oss;
32
33irqreturn_t oss_irq(int, void *, struct pt_regs *);
34irqreturn_t oss_nubus_irq(int, void *, struct pt_regs *);
35
36extern irqreturn_t via1_irq(int, void *, struct pt_regs *);
37extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *);
38
39/*
40 * Initialize the OSS
41 *
42 * The OSS "detection" code is actually in via_init() which is always called
43 * before us. Thus we can count on oss_present being valid on entry.
44 */
45
46void __init oss_init(void)
47{
48 int i;
49
50 if (!oss_present) return;
51
52 oss = (struct mac_oss *) OSS_BASE;
53
54 /* Disable all interrupts. Unlike a VIA it looks like we */
55 /* do this by setting the source's interrupt level to zero. */
56
57 for (i = 0; i <= OSS_NUM_SOURCES; i++) {
58 oss->irq_level[i] = OSS_IRQLEV_DISABLED;
59 }
60 /* If we disable VIA1 here, we never really handle it... */
61 oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1;
62}
63
64/*
65 * Register the OSS and NuBus interrupt dispatchers.
66 */
67
68void __init oss_register_interrupts(void)
69{
70 cpu_request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
71 "scsi", (void *) oss);
72 cpu_request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
73 "scc", mac_scc_dispatch);
74 cpu_request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
75 "nubus", (void *) oss);
76 cpu_request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
77 "sound", (void *) oss);
78 cpu_request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
79 "via1", (void *) via1);
80}
81
82/*
83 * Initialize OSS for Nubus access
84 */
85
86void __init oss_nubus_init(void)
87{
88}
89
90/*
91 * Handle miscellaneous OSS interrupts. Right now that's just sound
92 * and SCSI; everything else is routed to its own autovector IRQ.
93 */
94
95irqreturn_t oss_irq(int irq, void *dev_id, struct pt_regs *regs)
96{
97 int events;
98
99 events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
100 if (!events)
101 return IRQ_NONE;
102
103#ifdef DEBUG_IRQS
104 if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
105 printk("oss_irq: irq %d events = 0x%04X\n", irq,
106 (int) oss->irq_pending);
107 }
108#endif
109 /* FIXME: how do you clear a pending IRQ? */
110
111 if (events & OSS_IP_SOUND) {
112 /* FIXME: call sound handler */
113 oss->irq_pending &= ~OSS_IP_SOUND;
114 } else if (events & OSS_IP_SCSI) {
115 oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
116 mac_do_irq_list(IRQ_MAC_SCSI, regs);
117 oss->irq_pending &= ~OSS_IP_SCSI;
118 oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
119 } else {
120 /* FIXME: error check here? */
121 }
122 return IRQ_HANDLED;
123}
124
125/*
126 * Nubus IRQ handler, OSS style
127 *
128 * Unlike the VIA/RBV this is on its own autovector interrupt level.
129 */
130
131irqreturn_t oss_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
132{
133 int events, irq_bit, i;
134
135 events = oss->irq_pending & OSS_IP_NUBUS;
136 if (!events)
137 return IRQ_NONE;
138
139#ifdef DEBUG_NUBUS_INT
140 if (console_loglevel > 7) {
141 printk("oss_nubus_irq: events = 0x%04X\n", events);
142 }
143#endif
144 /* There are only six slots on the OSS, not seven */
145
146 for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
147 if (events & irq_bit) {
148 oss->irq_level[i] = OSS_IRQLEV_DISABLED;
149 mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs);
150 oss->irq_pending &= ~irq_bit;
151 oss->irq_level[i] = OSS_IRQLEV_NUBUS;
152 }
153 }
154 return IRQ_HANDLED;
155}
156
157/*
158 * Enable an OSS interrupt
159 *
160 * It looks messy but it's rather straightforward. The switch() statement
161 * just maps the machspec interrupt numbers to the right OSS interrupt
162 * source (if the OSS handles that interrupt) and then sets the interrupt
163 * level for that source to nonzero, thus enabling the interrupt.
164 */
165
166void oss_irq_enable(int irq) {
167#ifdef DEBUG_IRQUSE
168 printk("oss_irq_enable(%d)\n", irq);
169#endif
170 switch(irq) {
171 case IRQ_SCC:
172 case IRQ_SCCA:
173 case IRQ_SCCB:
174 oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_IOPSCC;
175 break;
176 case IRQ_MAC_ADB:
177 oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_IOPISM;
178 break;
179 case IRQ_MAC_SCSI:
180 oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
181 break;
182 case IRQ_NUBUS_9:
183 case IRQ_NUBUS_A:
184 case IRQ_NUBUS_B:
185 case IRQ_NUBUS_C:
186 case IRQ_NUBUS_D:
187 case IRQ_NUBUS_E:
188 irq -= NUBUS_SOURCE_BASE;
189 oss->irq_level[irq] = OSS_IRQLEV_NUBUS;
190 break;
191#ifdef DEBUG_IRQUSE
192 default:
193 printk("%s unknown irq %d\n",__FUNCTION__, irq);
194 break;
195#endif
196 }
197}
198
199/*
200 * Disable an OSS interrupt
201 *
202 * Same as above except we set the source's interrupt level to zero,
203 * to disable the interrupt.
204 */
205
206void oss_irq_disable(int irq) {
207#ifdef DEBUG_IRQUSE
208 printk("oss_irq_disable(%d)\n", irq);
209#endif
210 switch(irq) {
211 case IRQ_SCC:
212 case IRQ_SCCA:
213 case IRQ_SCCB:
214 oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_DISABLED;
215 break;
216 case IRQ_MAC_ADB:
217 oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_DISABLED;
218 break;
219 case IRQ_MAC_SCSI:
220 oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
221 break;
222 case IRQ_NUBUS_9:
223 case IRQ_NUBUS_A:
224 case IRQ_NUBUS_B:
225 case IRQ_NUBUS_C:
226 case IRQ_NUBUS_D:
227 case IRQ_NUBUS_E:
228 irq -= NUBUS_SOURCE_BASE;
229 oss->irq_level[irq] = OSS_IRQLEV_DISABLED;
230 break;
231#ifdef DEBUG_IRQUSE
232 default:
233 printk("%s unknown irq %d\n", __FUNCTION__, irq);
234 break;
235#endif
236 }
237}
238
239/*
240 * Clear an OSS interrupt
241 *
242 * Not sure if this works or not but it's the only method I could
243 * think of based on the contents of the mac_oss structure.
244 */
245
246void oss_irq_clear(int irq) {
247 /* FIXME: how to do this on OSS? */
248 switch(irq) {
249 case IRQ_SCC:
250 case IRQ_SCCA:
251 case IRQ_SCCB:
252 oss->irq_pending &= ~OSS_IP_IOPSCC;
253 break;
254 case IRQ_MAC_ADB:
255 oss->irq_pending &= ~OSS_IP_IOPISM;
256 break;
257 case IRQ_MAC_SCSI:
258 oss->irq_pending &= ~OSS_IP_SCSI;
259 break;
260 case IRQ_NUBUS_9:
261 case IRQ_NUBUS_A:
262 case IRQ_NUBUS_B:
263 case IRQ_NUBUS_C:
264 case IRQ_NUBUS_D:
265 case IRQ_NUBUS_E:
266 irq -= NUBUS_SOURCE_BASE;
267 oss->irq_pending &= ~(1 << irq);
268 break;
269 }
270}
271
272/*
273 * Check to see if a specific OSS interrupt is pending
274 */
275
276int oss_irq_pending(int irq)
277{
278 switch(irq) {
279 case IRQ_SCC:
280 case IRQ_SCCA:
281 case IRQ_SCCB:
282 return oss->irq_pending & OSS_IP_IOPSCC;
283 break;
284 case IRQ_MAC_ADB:
285 return oss->irq_pending & OSS_IP_IOPISM;
286 break;
287 case IRQ_MAC_SCSI:
288 return oss->irq_pending & OSS_IP_SCSI;
289 break;
290 case IRQ_NUBUS_9:
291 case IRQ_NUBUS_A:
292 case IRQ_NUBUS_B:
293 case IRQ_NUBUS_C:
294 case IRQ_NUBUS_D:
295 case IRQ_NUBUS_E:
296 irq -= NUBUS_SOURCE_BASE;
297 return oss->irq_pending & (1 << irq);
298 break;
299 }
300 return 0;
301}
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
new file mode 100644
index 000000000000..e72384e43a1e
--- /dev/null
+++ b/arch/m68k/mac/psc.c
@@ -0,0 +1,197 @@
1/*
2 * Apple Peripheral System Controller (PSC)
3 *
4 * The PSC is used on the AV Macs to control IO functions not handled
5 * by the VIAs (Ethernet, DSP, SCC).
6 *
7 * TO DO:
8 *
9 * Try to figure out what's going on in pIFR5 and pIFR6. There seem to be
10 * persisant interrupt conditions in those registers and I have no idea what
11 * they are. Granted it doesn't affect since we're not enabling any interrupts
12 * on those levels at the moment, but it would be nice to know. I have a feeling
13 * they aren't actually interrupt lines but data lines (to the DSP?)
14 */
15
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/mm.h>
19#include <linux/delay.h>
20#include <linux/init.h>
21
22#include <asm/traps.h>
23#include <asm/bootinfo.h>
24#include <asm/macintosh.h>
25#include <asm/macints.h>
26#include <asm/mac_psc.h>
27
28#define DEBUG_PSC
29
30int psc_present;
31volatile __u8 *psc;
32
33irqreturn_t psc_irq(int, void *, struct pt_regs *);
34
35/*
36 * Debugging dump, used in various places to see what's going on.
37 */
38
39void psc_debug_dump(void)
40{
41 int i;
42
43 if (!psc_present) return;
44 for (i = 0x30 ; i < 0x70 ; i += 0x10) {
45 printk("PSC #%d: IFR = 0x%02X IER = 0x%02X\n",
46 i >> 4,
47 (int) psc_read_byte(pIFRbase + i),
48 (int) psc_read_byte(pIERbase + i));
49 }
50}
51
52/*
53 * Try to kill all DMA channels on the PSC. Not sure how this his
54 * supposed to work; this is code lifted from macmace.c and then
55 * expanded to cover what I think are the other 7 channels.
56 */
57
58void psc_dma_die_die_die(void)
59{
60 int i;
61
62 printk("Killing all PSC DMA channels...");
63 for (i = 0 ; i < 9 ; i++) {
64 psc_write_word(PSC_CTL_BASE + (i << 4), 0x8800);
65 psc_write_word(PSC_CTL_BASE + (i << 4), 0x1000);
66 psc_write_word(PSC_CMD_BASE + (i << 5), 0x1100);
67 psc_write_word(PSC_CMD_BASE + (i << 5) + 0x10, 0x1100);
68 }
69 printk("done!\n");
70}
71
72/*
73 * Initialize the PSC. For now this just involves shutting down all
74 * interrupt sources using the IERs.
75 */
76
77void __init psc_init(void)
78{
79 int i;
80
81 if (macintosh_config->ident != MAC_MODEL_C660
82 && macintosh_config->ident != MAC_MODEL_Q840)
83 {
84 psc = NULL;
85 psc_present = 0;
86 return;
87 }
88
89 /*
90 * The PSC is always at the same spot, but using psc
91 * keeps things consisant with the psc_xxxx functions.
92 */
93
94 psc = (void *) PSC_BASE;
95 psc_present = 1;
96
97 printk("PSC detected at %p\n", psc);
98
99 psc_dma_die_die_die();
100
101#ifdef DEBUG_PSC
102 psc_debug_dump();
103#endif
104 /*
105 * Mask and clear all possible interrupts
106 */
107
108 for (i = 0x30 ; i < 0x70 ; i += 0x10) {
109 psc_write_byte(pIERbase + i, 0x0F);
110 psc_write_byte(pIFRbase + i, 0x0F);
111 }
112}
113
114/*
115 * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
116 */
117
118void __init psc_register_interrupts(void)
119{
120 cpu_request_irq(3, psc_irq, IRQ_FLG_LOCK, "psc3", (void *) 0x30);
121 cpu_request_irq(4, psc_irq, IRQ_FLG_LOCK, "psc4", (void *) 0x40);
122 cpu_request_irq(5, psc_irq, IRQ_FLG_LOCK, "psc5", (void *) 0x50);
123 cpu_request_irq(6, psc_irq, IRQ_FLG_LOCK, "psc6", (void *) 0x60);
124}
125
126/*
127 * PSC interrupt handler. It's a lot like the VIA interrupt handler.
128 */
129
130irqreturn_t psc_irq(int irq, void *dev_id, struct pt_regs *regs)
131{
132 int pIFR = pIFRbase + ((int) dev_id);
133 int pIER = pIERbase + ((int) dev_id);
134 int base_irq;
135 int irq_bit,i;
136 unsigned char events;
137
138 base_irq = irq << 3;
139
140#ifdef DEBUG_IRQS
141 printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
142 irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
143#endif
144
145 events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
146 if (!events)
147 return IRQ_NONE;
148
149 for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
150 if (events & irq_bit) {
151 psc_write_byte(pIER, irq_bit);
152 mac_do_irq_list(base_irq + i, regs);
153 psc_write_byte(pIFR, irq_bit);
154 psc_write_byte(pIER, irq_bit | 0x80);
155 }
156 }
157 return IRQ_HANDLED;
158}
159
160void psc_irq_enable(int irq) {
161 int irq_src = IRQ_SRC(irq);
162 int irq_idx = IRQ_IDX(irq);
163 int pIER = pIERbase + (irq_src << 4);
164
165#ifdef DEBUG_IRQUSE
166 printk("psc_irq_enable(%d)\n", irq);
167#endif
168 psc_write_byte(pIER, (1 << irq_idx) | 0x80);
169}
170
171void psc_irq_disable(int irq) {
172 int irq_src = IRQ_SRC(irq);
173 int irq_idx = IRQ_IDX(irq);
174 int pIER = pIERbase + (irq_src << 4);
175
176#ifdef DEBUG_IRQUSE
177 printk("psc_irq_disable(%d)\n", irq);
178#endif
179 psc_write_byte(pIER, 1 << irq_idx);
180}
181
182void psc_irq_clear(int irq) {
183 int irq_src = IRQ_SRC(irq);
184 int irq_idx = IRQ_IDX(irq);
185 int pIFR = pIERbase + (irq_src << 4);
186
187 psc_write_byte(pIFR, 1 << irq_idx);
188}
189
190int psc_irq_pending(int irq)
191{
192 int irq_src = IRQ_SRC(irq);
193 int irq_idx = IRQ_IDX(irq);
194 int pIFR = pIERbase + (irq_src << 4);
195
196 return psc_read_byte(pIFR) & (1 << irq_idx);
197}
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
new file mode 100644
index 000000000000..cd528bf7b43f
--- /dev/null
+++ b/arch/m68k/mac/via.c
@@ -0,0 +1,619 @@
1/*
2 * 6522 Versatile Interface Adapter (VIA)
3 *
4 * There are two of these on the Mac II. Some IRQ's are vectored
5 * via them as are assorted bits and bobs - eg RTC, ADB.
6 *
7 * CSA: Motorola seems to have removed documentation on the 6522 from
8 * their web site; try
9 * http://nerini.drf.com/vectrex/other/text/chips/6522/
10 * http://www.zymurgy.net/classic/vic20/vicdet1.htm
11 * and
12 * http://193.23.168.87/mikro_laborversuche/via_iobaustein/via6522_1.html
13 * for info. A full-text web search on 6522 AND VIA will probably also
14 * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999
15 *
16 * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b
17 * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org)
18 *
19 */
20
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/mm.h>
24#include <linux/delay.h>
25#include <linux/init.h>
26#include <linux/ide.h>
27
28#include <asm/traps.h>
29#include <asm/bootinfo.h>
30#include <asm/macintosh.h>
31#include <asm/macints.h>
32#include <asm/machw.h>
33#include <asm/mac_via.h>
34#include <asm/mac_psc.h>
35
36volatile __u8 *via1, *via2;
37#if 0
38/* See note in mac_via.h about how this is possibly not useful */
39volatile long *via_memory_bogon=(long *)&via_memory_bogon;
40#endif
41int rbv_present,via_alt_mapping;
42__u8 rbv_clear;
43
44/*
45 * Globals for accessing the VIA chip registers without having to
46 * check if we're hitting a real VIA or an RBV. Normally you could
47 * just hit the combined register (ie, vIER|rIER) but that seems to
48 * break on AV Macs...probably because they actually decode more than
49 * eight address bits. Why can't Apple engineers at least be
50 * _consistently_ lazy? - 1999-05-21 (jmt)
51 */
52
53static int gIER,gIFR,gBufA,gBufB;
54
55/*
56 * Timer defs.
57 */
58
59#define TICK_SIZE 10000
60#define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */
61#define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF)
62#define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8)
63
64static int nubus_active;
65
66void via_debug_dump(void);
67irqreturn_t via1_irq(int, void *, struct pt_regs *);
68irqreturn_t via2_irq(int, void *, struct pt_regs *);
69irqreturn_t via_nubus_irq(int, void *, struct pt_regs *);
70void via_irq_enable(int irq);
71void via_irq_disable(int irq);
72void via_irq_clear(int irq);
73
74extern irqreturn_t mac_bang(int, void *, struct pt_regs *);
75extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *);
76extern int oss_present;
77
78/*
79 * Initialize the VIAs
80 *
81 * First we figure out where they actually _are_ as well as what type of
82 * VIA we have for VIA2 (it could be a real VIA or an RBV or even an OSS.)
83 * Then we pretty much clear them out and disable all IRQ sources.
84 *
85 * Note: the OSS is actually "detected" here and not in oss_init(). It just
86 * seems more logical to do it here since via_init() needs to know
87 * these things anyways.
88 */
89
90void __init via_init(void)
91{
92 switch(macintosh_config->via_type) {
93
94 /* IIci, IIsi, IIvx, IIvi (P6xx), LC series */
95
96 case MAC_VIA_IIci:
97 via1 = (void *) VIA1_BASE;
98 if (macintosh_config->ident == MAC_MODEL_IIFX) {
99 via2 = NULL;
100 rbv_present = 0;
101 oss_present = 1;
102 } else {
103 via2 = (void *) RBV_BASE;
104 rbv_present = 1;
105 oss_present = 0;
106 }
107 if (macintosh_config->ident == MAC_MODEL_LCIII) {
108 rbv_clear = 0x00;
109 } else {
110 /* on most RBVs (& unlike the VIAs), you */
111 /* need to set bit 7 when you write to IFR */
112 /* in order for your clear to occur. */
113 rbv_clear = 0x80;
114 }
115 gIER = rIER;
116 gIFR = rIFR;
117 gBufA = rSIFR;
118 gBufB = rBufB;
119 break;
120
121 /* Quadra and early MacIIs agree on the VIA locations */
122
123 case MAC_VIA_QUADRA:
124 case MAC_VIA_II:
125 via1 = (void *) VIA1_BASE;
126 via2 = (void *) VIA2_BASE;
127 rbv_present = 0;
128 oss_present = 0;
129 rbv_clear = 0x00;
130 gIER = vIER;
131 gIFR = vIFR;
132 gBufA = vBufA;
133 gBufB = vBufB;
134 break;
135 default:
136 panic("UNKNOWN VIA TYPE");
137 }
138
139 printk(KERN_INFO "VIA1 at %p is a 6522 or clone\n", via1);
140
141 printk(KERN_INFO "VIA2 at %p is ", via2);
142 if (rbv_present) {
143 printk(KERN_INFO "an RBV\n");
144 } else if (oss_present) {
145 printk(KERN_INFO "an OSS\n");
146 } else {
147 printk(KERN_INFO "a 6522 or clone\n");
148 }
149
150#ifdef DEBUG_VIA
151 via_debug_dump();
152#endif
153
154 /*
155 * Shut down all IRQ sources, reset the timers, and
156 * kill the timer latch on VIA1.
157 */
158
159 via1[vIER] = 0x7F;
160 via1[vIFR] = 0x7F;
161 via1[vT1LL] = 0;
162 via1[vT1LH] = 0;
163 via1[vT1CL] = 0;
164 via1[vT1CH] = 0;
165 via1[vT2CL] = 0;
166 via1[vT2CH] = 0;
167 via1[vACR] &= 0x3F;
168
169 /*
170 * SE/30: disable video IRQ
171 * XXX: testing for SE/30 VBL
172 */
173
174 if (macintosh_config->ident == MAC_MODEL_SE30) {
175 via1[vDirB] |= 0x40;
176 via1[vBufB] |= 0x40;
177 }
178
179 /*
180 * Set the RTC bits to a known state: all lines to outputs and
181 * RTC disabled (yes that's 0 to enable and 1 to disable).
182 */
183
184 via1[vDirB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk | VIA1B_vRTCData);
185 via1[vBufB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk);
186
187 /* Everything below this point is VIA2/RBV only... */
188
189 if (oss_present) return;
190
191#if 1
192 /* Some machines support an alternate IRQ mapping that spreads */
193 /* Ethernet and Sound out to their own autolevel IRQs and moves */
194 /* VIA1 to level 6. A/UX uses this mapping and we do too. Note */
195 /* that the IIfx emulates this alternate mapping using the OSS. */
196
197 switch(macintosh_config->ident) {
198 case MAC_MODEL_C610:
199 case MAC_MODEL_Q610:
200 case MAC_MODEL_C650:
201 case MAC_MODEL_Q650:
202 case MAC_MODEL_Q700:
203 case MAC_MODEL_Q800:
204 case MAC_MODEL_Q900:
205 case MAC_MODEL_Q950:
206 via_alt_mapping = 1;
207 via1[vDirB] |= 0x40;
208 via1[vBufB] &= ~0x40;
209 break;
210 default:
211 via_alt_mapping = 0;
212 break;
213 }
214#else
215 /* The alernate IRQ mapping seems to just not work. Anyone with a */
216 /* supported machine is welcome to take a stab at fixing it. It */
217 /* _should_ work on the following Quadras: 610,650,700,800,900,950 */
218 /* - 1999-06-12 (jmt) */
219
220 via_alt_mapping = 0;
221#endif
222
223 /*
224 * Now initialize VIA2. For RBV we just kill all interrupts;
225 * for a regular VIA we also reset the timers and stuff.
226 */
227
228 via2[gIER] = 0x7F;
229 via2[gIFR] = 0x7F | rbv_clear;
230 if (!rbv_present) {
231 via2[vT1LL] = 0;
232 via2[vT1LH] = 0;
233 via2[vT1CL] = 0;
234 via2[vT1CH] = 0;
235 via2[vT2CL] = 0;
236 via2[vT2CH] = 0;
237 via2[vACR] &= 0x3F;
238 }
239}
240
241/*
242 * Start the 100 Hz clock
243 */
244
245void __init via_init_clock(irqreturn_t (*func)(int, void *, struct pt_regs *))
246{
247 via1[vACR] |= 0x40;
248 via1[vT1LL] = MAC_CLOCK_LOW;
249 via1[vT1LH] = MAC_CLOCK_HIGH;
250 via1[vT1CL] = MAC_CLOCK_LOW;
251 via1[vT1CH] = MAC_CLOCK_HIGH;
252
253 request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
254}
255
256/*
257 * Register the interrupt dispatchers for VIA or RBV machines only.
258 */
259
260void __init via_register_interrupts(void)
261{
262 if (via_alt_mapping) {
263 cpu_request_irq(IRQ_AUTO_1, via1_irq,
264 IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
265 (void *) via1);
266 cpu_request_irq(IRQ_AUTO_6, via1_irq,
267 IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
268 (void *) via1);
269 } else {
270 cpu_request_irq(IRQ_AUTO_1, via1_irq,
271 IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
272 (void *) via1);
273#if 0 /* interferes with serial on some machines */
274 if (!psc_present) {
275 cpu_request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
276 "Off Switch", mac_bang);
277 }
278#endif
279 }
280 cpu_request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
281 "via2", (void *) via2);
282 if (!psc_present) {
283 cpu_request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
284 "scc", mac_scc_dispatch);
285 }
286 request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
287 "nubus", (void *) via2);
288}
289
290/*
291 * Debugging dump, used in various places to see what's going on.
292 */
293
294void via_debug_dump(void)
295{
296 printk(KERN_DEBUG "VIA1: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
297 (uint) via1[vDirA], (uint) via1[vDirB], (uint) via1[vACR]);
298 printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n",
299 (uint) via1[vPCR], (uint) via1[vIFR], (uint) via1[vIER]);
300 if (oss_present) {
301 printk(KERN_DEBUG "VIA2: <OSS>\n");
302 } else if (rbv_present) {
303 printk(KERN_DEBUG "VIA2: IFR = 0x%02X IER = 0x%02X\n",
304 (uint) via2[rIFR], (uint) via2[rIER]);
305 printk(KERN_DEBUG " SIFR = 0x%02X SIER = 0x%02X\n",
306 (uint) via2[rSIFR], (uint) via2[rSIER]);
307 } else {
308 printk(KERN_DEBUG "VIA2: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
309 (uint) via2[vDirA], (uint) via2[vDirB],
310 (uint) via2[vACR]);
311 printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n",
312 (uint) via2[vPCR],
313 (uint) via2[vIFR], (uint) via2[vIER]);
314 }
315}
316
317/*
318 * This is always executed with interrupts disabled.
319 *
320 * TBI: get time offset between scheduling timer ticks
321 */
322
323unsigned long mac_gettimeoffset (void)
324{
325 unsigned long ticks, offset = 0;
326
327 /* read VIA1 timer 2 current value */
328 ticks = via1[vT1CL] | (via1[vT1CH] << 8);
329 /* The probability of underflow is less than 2% */
330 if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
331 /* Check for pending timer interrupt in VIA1 IFR */
332 if (via1[vIFR] & 0x40) offset = TICK_SIZE;
333
334 ticks = MAC_CLOCK_TICK - ticks;
335 ticks = ticks * 10000L / MAC_CLOCK_TICK;
336
337 return ticks + offset;
338}
339
340/*
341 * Flush the L2 cache on Macs that have it by flipping
342 * the system into 24-bit mode for an instant.
343 */
344
345void via_flush_cache(void)
346{
347 via2[gBufB] &= ~VIA2B_vMode32;
348 via2[gBufB] |= VIA2B_vMode32;
349}
350
351/*
352 * Return the status of the L2 cache on a IIci
353 */
354
355int via_get_cache_disable(void)
356{
357 /* Safeguard against being called accidentally */
358 if (!via2) {
359 printk(KERN_ERR "via_get_cache_disable called on a non-VIA machine!\n");
360 return 1;
361 }
362
363 return (int) via2[gBufB] & VIA2B_vCDis;
364}
365
366/*
367 * Initialize VIA2 for Nubus access
368 */
369
370void __init via_nubus_init(void)
371{
372 /* don't set nubus_active = 0 here, it kills the Baboon */
373 /* interrupt that we've already registered. */
374
375 /* unlock nubus transactions */
376
377 if (!rbv_present) {
378 /* set the line to be an output on non-RBV machines */
379 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
380 (macintosh_config->adb_type != MAC_ADB_PB2)) {
381 via2[vDirB] |= 0x02;
382 }
383 }
384
385 /* this seems to be an ADB bit on PMU machines */
386 /* according to MkLinux. -- jmt */
387
388 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
389 (macintosh_config->adb_type != MAC_ADB_PB2)) {
390 via2[gBufB] |= 0x02;
391 }
392
393 /* disable nubus slot interrupts. */
394 if (rbv_present) {
395 via2[rSIER] = 0x7F;
396 via2[rSIER] = nubus_active | 0x80;
397 } else {
398 /* These are ADB bits on PMU */
399 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
400 (macintosh_config->adb_type != MAC_ADB_PB2)) {
401 switch(macintosh_config->ident)
402 {
403 case MAC_MODEL_II:
404 case MAC_MODEL_IIX:
405 case MAC_MODEL_IICX:
406 case MAC_MODEL_SE30:
407 via2[vBufA] |= 0x3F;
408 via2[vDirA] = ~nubus_active | 0xc0;
409 break;
410 default:
411 via2[vBufA] = 0xFF;
412 via2[vDirA] = ~nubus_active;
413 }
414 }
415 }
416}
417
418/*
419 * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's
420 * via6522.c :-), disable/pending masks added.
421 *
422 * The new interrupt architecture in macints.c takes care of a lot of the
423 * gruntwork for us, including tallying the interrupts and calling the
424 * handlers on the linked list. All we need to do here is basically generate
425 * the machspec interrupt number after clearing the interrupt.
426 */
427
428irqreturn_t via1_irq(int irq, void *dev_id, struct pt_regs *regs)
429{
430 int irq_bit, i;
431 unsigned char events, mask;
432
433 mask = via1[vIER] & 0x7F;
434 if (!(events = via1[vIFR] & mask))
435 return IRQ_NONE;
436
437 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
438 if (events & irq_bit) {
439 via1[vIER] = irq_bit;
440 mac_do_irq_list(VIA1_SOURCE_BASE + i, regs);
441 via1[vIFR] = irq_bit;
442 via1[vIER] = irq_bit | 0x80;
443 }
444
445#if 0 /* freakin' pmu is doing weird stuff */
446 if (!oss_present) {
447 /* This (still) seems to be necessary to get IDE
448 working. However, if you enable VBL interrupts,
449 you're screwed... */
450 /* FIXME: should we check the SLOTIRQ bit before
451 pulling this stunt? */
452 /* No, it won't be set. that's why we're doing this. */
453 via_irq_disable(IRQ_MAC_NUBUS);
454 via_irq_clear(IRQ_MAC_NUBUS);
455 mac_do_irq_list(IRQ_MAC_NUBUS, regs);
456 via_irq_enable(IRQ_MAC_NUBUS);
457 }
458#endif
459 return IRQ_HANDLED;
460}
461
462irqreturn_t via2_irq(int irq, void *dev_id, struct pt_regs *regs)
463{
464 int irq_bit, i;
465 unsigned char events, mask;
466
467 mask = via2[gIER] & 0x7F;
468 if (!(events = via2[gIFR] & mask))
469 return IRQ_NONE;
470
471 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
472 if (events & irq_bit) {
473 via2[gIER] = irq_bit;
474 mac_do_irq_list(VIA2_SOURCE_BASE + i, regs);
475 via2[gIFR] = irq_bit | rbv_clear;
476 via2[gIER] = irq_bit | 0x80;
477 }
478 return IRQ_HANDLED;
479}
480
481/*
482 * Dispatch Nubus interrupts. We are called as a secondary dispatch by the
483 * VIA2 dispatcher as a fast interrupt handler.
484 */
485
486irqreturn_t via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
487{
488 int irq_bit, i;
489 unsigned char events;
490
491 if (!(events = ~via2[gBufA] & nubus_active))
492 return IRQ_NONE;
493
494 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
495 if (events & irq_bit) {
496 via_irq_disable(NUBUS_SOURCE_BASE + i);
497 mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs);
498 via_irq_enable(NUBUS_SOURCE_BASE + i);
499 }
500 }
501 return IRQ_HANDLED;
502}
503
504void via_irq_enable(int irq) {
505 int irq_src = IRQ_SRC(irq);
506 int irq_idx = IRQ_IDX(irq);
507 int irq_bit = 1 << irq_idx;
508
509#ifdef DEBUG_IRQUSE
510 printk(KERN_DEBUG "via_irq_enable(%d)\n", irq);
511#endif
512
513 if (irq_src == 1) {
514 via1[vIER] = irq_bit | 0x80;
515 } else if (irq_src == 2) {
516 /*
517 * Set vPCR for SCSI interrupts (but not on RBV)
518 */
519 if ((irq_idx == 0) && !rbv_present) {
520 if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
521 /* CB2 (IRQ) indep. input, positive edge */
522 /* CA2 (DRQ) indep. input, positive edge */
523 via2[vPCR] = 0x66;
524 } else {
525 /* CB2 (IRQ) indep. input, negative edge */
526 /* CA2 (DRQ) indep. input, negative edge */
527 via2[vPCR] = 0x22;
528 }
529 }
530 via2[gIER] = irq_bit | 0x80;
531 } else if (irq_src == 7) {
532 if (rbv_present) {
533 /* enable the slot interrupt. SIER works like IER. */
534 via2[rSIER] = IER_SET_BIT(irq_idx);
535 } else {
536 /* Make sure the bit is an input, to enable the irq */
537 /* But not on PowerBooks, that's ADB... */
538 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
539 (macintosh_config->adb_type != MAC_ADB_PB2)) {
540 switch(macintosh_config->ident)
541 {
542 case MAC_MODEL_II:
543 case MAC_MODEL_IIX:
544 case MAC_MODEL_IICX:
545 case MAC_MODEL_SE30:
546 via2[vDirA] &= (~irq_bit | 0xc0);
547 break;
548 default:
549 via2[vDirA] &= ~irq_bit;
550 }
551 }
552 }
553 nubus_active |= irq_bit;
554 }
555}
556
557void via_irq_disable(int irq) {
558 int irq_src = IRQ_SRC(irq);
559 int irq_idx = IRQ_IDX(irq);
560 int irq_bit = 1 << irq_idx;
561
562#ifdef DEBUG_IRQUSE
563 printk(KERN_DEBUG "via_irq_disable(%d)\n", irq);
564#endif
565
566 if (irq_src == 1) {
567 via1[vIER] = irq_bit;
568 } else if (irq_src == 2) {
569 via2[gIER] = irq_bit;
570 } else if (irq_src == 7) {
571 if (rbv_present) {
572 /* disable the slot interrupt. SIER works like IER. */
573 via2[rSIER] = IER_CLR_BIT(irq_idx);
574 } else {
575 /* disable the nubus irq by changing dir to output */
576 /* except on PMU */
577 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
578 (macintosh_config->adb_type != MAC_ADB_PB2)) {
579 via2[vDirA] |= irq_bit;
580 }
581 }
582 nubus_active &= ~irq_bit;
583 }
584}
585
586void via_irq_clear(int irq) {
587 int irq_src = IRQ_SRC(irq);
588 int irq_idx = IRQ_IDX(irq);
589 int irq_bit = 1 << irq_idx;
590
591 if (irq_src == 1) {
592 via1[vIFR] = irq_bit;
593 } else if (irq_src == 2) {
594 via2[gIFR] = irq_bit | rbv_clear;
595 } else if (irq_src == 7) {
596 /* FIXME: hmm.. */
597 }
598}
599
600/*
601 * Returns nonzero if an interrupt is pending on the given
602 * VIA/IRQ combination.
603 */
604
605int via_irq_pending(int irq)
606{
607 int irq_src = IRQ_SRC(irq);
608 int irq_idx = IRQ_IDX(irq);
609 int irq_bit = 1 << irq_idx;
610
611 if (irq_src == 1) {
612 return via1[vIFR] & irq_bit;
613 } else if (irq_src == 2) {
614 return via2[gIFR] & irq_bit;
615 } else if (irq_src == 7) {
616 return ~via2[gBufA] & irq_bit;
617 }
618 return 0;
619}
diff --git a/arch/m68k/math-emu/Makefile b/arch/m68k/math-emu/Makefile
new file mode 100644
index 000000000000..539940401814
--- /dev/null
+++ b/arch/m68k/math-emu/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile for the linux kernel.
3#
4
5EXTRA_AFLAGS := -traditional
6
7#EXTRA_AFLAGS += -DFPU_EMU_DEBUG
8#EXTRA_CFLAGS += -DFPU_EMU_DEBUG
9
10obj-y := fp_entry.o fp_scan.o fp_util.o fp_move.o fp_movem.o \
11 fp_cond.o fp_arith.o fp_log.o fp_trig.o
diff --git a/arch/m68k/math-emu/fp_arith.c b/arch/m68k/math-emu/fp_arith.c
new file mode 100644
index 000000000000..08f286db3c5a
--- /dev/null
+++ b/arch/m68k/math-emu/fp_arith.c
@@ -0,0 +1,701 @@
1/*
2
3 fp_arith.c: floating-point math routines for the Linux-m68k
4 floating point emulator.
5
6 Copyright (c) 1998-1999 David Huggins-Daines.
7
8 Somewhat based on the AlphaLinux floating point emulator, by David
9 Mosberger-Tang.
10
11 You may copy, modify, and redistribute this file under the terms of
12 the GNU General Public License, version 2, or any later version, at
13 your convenience.
14 */
15
16#include "fp_emu.h"
17#include "multi_arith.h"
18#include "fp_arith.h"
19
20const struct fp_ext fp_QNaN =
21{
22 .exp = 0x7fff,
23 .mant = { .m64 = ~0 }
24};
25
26const struct fp_ext fp_Inf =
27{
28 .exp = 0x7fff,
29};
30
31/* let's start with the easy ones */
32
33struct fp_ext *
34fp_fabs(struct fp_ext *dest, struct fp_ext *src)
35{
36 dprint(PINSTR, "fabs\n");
37
38 fp_monadic_check(dest, src);
39
40 dest->sign = 0;
41
42 return dest;
43}
44
45struct fp_ext *
46fp_fneg(struct fp_ext *dest, struct fp_ext *src)
47{
48 dprint(PINSTR, "fneg\n");
49
50 fp_monadic_check(dest, src);
51
52 dest->sign = !dest->sign;
53
54 return dest;
55}
56
57/* Now, the slightly harder ones */
58
59/* fp_fadd: Implements the kernel of the FADD, FSADD, FDADD, FSUB,
60 FDSUB, and FCMP instructions. */
61
62struct fp_ext *
63fp_fadd(struct fp_ext *dest, struct fp_ext *src)
64{
65 int diff;
66
67 dprint(PINSTR, "fadd\n");
68
69 fp_dyadic_check(dest, src);
70
71 if (IS_INF(dest)) {
72 /* infinity - infinity == NaN */
73 if (IS_INF(src) && (src->sign != dest->sign))
74 fp_set_nan(dest);
75 return dest;
76 }
77 if (IS_INF(src)) {
78 fp_copy_ext(dest, src);
79 return dest;
80 }
81
82 if (IS_ZERO(dest)) {
83 if (IS_ZERO(src)) {
84 if (src->sign != dest->sign) {
85 if (FPDATA->rnd == FPCR_ROUND_RM)
86 dest->sign = 1;
87 else
88 dest->sign = 0;
89 }
90 } else
91 fp_copy_ext(dest, src);
92 return dest;
93 }
94
95 dest->lowmant = src->lowmant = 0;
96
97 if ((diff = dest->exp - src->exp) > 0)
98 fp_denormalize(src, diff);
99 else if ((diff = -diff) > 0)
100 fp_denormalize(dest, diff);
101
102 if (dest->sign == src->sign) {
103 if (fp_addmant(dest, src))
104 if (!fp_addcarry(dest))
105 return dest;
106 } else {
107 if (dest->mant.m64 < src->mant.m64) {
108 fp_submant(dest, src, dest);
109 dest->sign = !dest->sign;
110 } else
111 fp_submant(dest, dest, src);
112 }
113
114 return dest;
115}
116
117/* fp_fsub: Implements the kernel of the FSUB, FSSUB, and FDSUB
118 instructions.
119
120 Remember that the arguments are in assembler-syntax order! */
121
122struct fp_ext *
123fp_fsub(struct fp_ext *dest, struct fp_ext *src)
124{
125 dprint(PINSTR, "fsub ");
126
127 src->sign = !src->sign;
128 return fp_fadd(dest, src);
129}
130
131
132struct fp_ext *
133fp_fcmp(struct fp_ext *dest, struct fp_ext *src)
134{
135 dprint(PINSTR, "fcmp ");
136
137 FPDATA->temp[1] = *dest;
138 src->sign = !src->sign;
139 return fp_fadd(&FPDATA->temp[1], src);
140}
141
142struct fp_ext *
143fp_ftst(struct fp_ext *dest, struct fp_ext *src)
144{
145 dprint(PINSTR, "ftst\n");
146
147 (void)dest;
148
149 return src;
150}
151
152struct fp_ext *
153fp_fmul(struct fp_ext *dest, struct fp_ext *src)
154{
155 union fp_mant128 temp;
156 int exp;
157
158 dprint(PINSTR, "fmul\n");
159
160 fp_dyadic_check(dest, src);
161
162 /* calculate the correct sign now, as it's necessary for infinities */
163 dest->sign = src->sign ^ dest->sign;
164
165 /* Handle infinities */
166 if (IS_INF(dest)) {
167 if (IS_ZERO(src))
168 fp_set_nan(dest);
169 return dest;
170 }
171 if (IS_INF(src)) {
172 if (IS_ZERO(dest))
173 fp_set_nan(dest);
174 else
175 fp_copy_ext(dest, src);
176 return dest;
177 }
178
179 /* Of course, as we all know, zero * anything = zero. You may
180 not have known that it might be a positive or negative
181 zero... */
182 if (IS_ZERO(dest) || IS_ZERO(src)) {
183 dest->exp = 0;
184 dest->mant.m64 = 0;
185 dest->lowmant = 0;
186
187 return dest;
188 }
189
190 exp = dest->exp + src->exp - 0x3ffe;
191
192 /* shift up the mantissa for denormalized numbers,
193 so that the highest bit is set, this makes the
194 shift of the result below easier */
195 if ((long)dest->mant.m32[0] >= 0)
196 exp -= fp_overnormalize(dest);
197 if ((long)src->mant.m32[0] >= 0)
198 exp -= fp_overnormalize(src);
199
200 /* now, do a 64-bit multiply with expansion */
201 fp_multiplymant(&temp, dest, src);
202
203 /* normalize it back to 64 bits and stuff it back into the
204 destination struct */
205 if ((long)temp.m32[0] > 0) {
206 exp--;
207 fp_putmant128(dest, &temp, 1);
208 } else
209 fp_putmant128(dest, &temp, 0);
210
211 if (exp >= 0x7fff) {
212 fp_set_ovrflw(dest);
213 return dest;
214 }
215 dest->exp = exp;
216 if (exp < 0) {
217 fp_set_sr(FPSR_EXC_UNFL);
218 fp_denormalize(dest, -exp);
219 }
220
221 return dest;
222}
223
224/* fp_fdiv: Implements the "kernel" of the FDIV, FSDIV, FDDIV and
225 FSGLDIV instructions.
226
227 Note that the order of the operands is counter-intuitive: instead
228 of src / dest, the result is actually dest / src. */
229
230struct fp_ext *
231fp_fdiv(struct fp_ext *dest, struct fp_ext *src)
232{
233 union fp_mant128 temp;
234 int exp;
235
236 dprint(PINSTR, "fdiv\n");
237
238 fp_dyadic_check(dest, src);
239
240 /* calculate the correct sign now, as it's necessary for infinities */
241 dest->sign = src->sign ^ dest->sign;
242
243 /* Handle infinities */
244 if (IS_INF(dest)) {
245 /* infinity / infinity = NaN (quiet, as always) */
246 if (IS_INF(src))
247 fp_set_nan(dest);
248 /* infinity / anything else = infinity (with approprate sign) */
249 return dest;
250 }
251 if (IS_INF(src)) {
252 /* anything / infinity = zero (with appropriate sign) */
253 dest->exp = 0;
254 dest->mant.m64 = 0;
255 dest->lowmant = 0;
256
257 return dest;
258 }
259
260 /* zeroes */
261 if (IS_ZERO(dest)) {
262 /* zero / zero = NaN */
263 if (IS_ZERO(src))
264 fp_set_nan(dest);
265 /* zero / anything else = zero */
266 return dest;
267 }
268 if (IS_ZERO(src)) {
269 /* anything / zero = infinity (with appropriate sign) */
270 fp_set_sr(FPSR_EXC_DZ);
271 dest->exp = 0x7fff;
272 dest->mant.m64 = 0;
273
274 return dest;
275 }
276
277 exp = dest->exp - src->exp + 0x3fff;
278
279 /* shift up the mantissa for denormalized numbers,
280 so that the highest bit is set, this makes lots
281 of things below easier */
282 if ((long)dest->mant.m32[0] >= 0)
283 exp -= fp_overnormalize(dest);
284 if ((long)src->mant.m32[0] >= 0)
285 exp -= fp_overnormalize(src);
286
287 /* now, do the 64-bit divide */
288 fp_dividemant(&temp, dest, src);
289
290 /* normalize it back to 64 bits and stuff it back into the
291 destination struct */
292 if (!temp.m32[0]) {
293 exp--;
294 fp_putmant128(dest, &temp, 32);
295 } else
296 fp_putmant128(dest, &temp, 31);
297
298 if (exp >= 0x7fff) {
299 fp_set_ovrflw(dest);
300 return dest;
301 }
302 dest->exp = exp;
303 if (exp < 0) {
304 fp_set_sr(FPSR_EXC_UNFL);
305 fp_denormalize(dest, -exp);
306 }
307
308 return dest;
309}
310
311struct fp_ext *
312fp_fsglmul(struct fp_ext *dest, struct fp_ext *src)
313{
314 int exp;
315
316 dprint(PINSTR, "fsglmul\n");
317
318 fp_dyadic_check(dest, src);
319
320 /* calculate the correct sign now, as it's necessary for infinities */
321 dest->sign = src->sign ^ dest->sign;
322
323 /* Handle infinities */
324 if (IS_INF(dest)) {
325 if (IS_ZERO(src))
326 fp_set_nan(dest);
327 return dest;
328 }
329 if (IS_INF(src)) {
330 if (IS_ZERO(dest))
331 fp_set_nan(dest);
332 else
333 fp_copy_ext(dest, src);
334 return dest;
335 }
336
337 /* Of course, as we all know, zero * anything = zero. You may
338 not have known that it might be a positive or negative
339 zero... */
340 if (IS_ZERO(dest) || IS_ZERO(src)) {
341 dest->exp = 0;
342 dest->mant.m64 = 0;
343 dest->lowmant = 0;
344
345 return dest;
346 }
347
348 exp = dest->exp + src->exp - 0x3ffe;
349
350 /* do a 32-bit multiply */
351 fp_mul64(dest->mant.m32[0], dest->mant.m32[1],
352 dest->mant.m32[0] & 0xffffff00,
353 src->mant.m32[0] & 0xffffff00);
354
355 if (exp >= 0x7fff) {
356 fp_set_ovrflw(dest);
357 return dest;
358 }
359 dest->exp = exp;
360 if (exp < 0) {
361 fp_set_sr(FPSR_EXC_UNFL);
362 fp_denormalize(dest, -exp);
363 }
364
365 return dest;
366}
367
368struct fp_ext *
369fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src)
370{
371 int exp;
372 unsigned long quot, rem;
373
374 dprint(PINSTR, "fsgldiv\n");
375
376 fp_dyadic_check(dest, src);
377
378 /* calculate the correct sign now, as it's necessary for infinities */
379 dest->sign = src->sign ^ dest->sign;
380
381 /* Handle infinities */
382 if (IS_INF(dest)) {
383 /* infinity / infinity = NaN (quiet, as always) */
384 if (IS_INF(src))
385 fp_set_nan(dest);
386 /* infinity / anything else = infinity (with approprate sign) */
387 return dest;
388 }
389 if (IS_INF(src)) {
390 /* anything / infinity = zero (with appropriate sign) */
391 dest->exp = 0;
392 dest->mant.m64 = 0;
393 dest->lowmant = 0;
394
395 return dest;
396 }
397
398 /* zeroes */
399 if (IS_ZERO(dest)) {
400 /* zero / zero = NaN */
401 if (IS_ZERO(src))
402 fp_set_nan(dest);
403 /* zero / anything else = zero */
404 return dest;
405 }
406 if (IS_ZERO(src)) {
407 /* anything / zero = infinity (with appropriate sign) */
408 fp_set_sr(FPSR_EXC_DZ);
409 dest->exp = 0x7fff;
410 dest->mant.m64 = 0;
411
412 return dest;
413 }
414
415 exp = dest->exp - src->exp + 0x3fff;
416
417 dest->mant.m32[0] &= 0xffffff00;
418 src->mant.m32[0] &= 0xffffff00;
419
420 /* do the 32-bit divide */
421 if (dest->mant.m32[0] >= src->mant.m32[0]) {
422 fp_sub64(dest->mant, src->mant);
423 fp_div64(quot, rem, dest->mant.m32[0], 0, src->mant.m32[0]);
424 dest->mant.m32[0] = 0x80000000 | (quot >> 1);
425 dest->mant.m32[1] = (quot & 1) | rem; /* only for rounding */
426 } else {
427 fp_div64(quot, rem, dest->mant.m32[0], 0, src->mant.m32[0]);
428 dest->mant.m32[0] = quot;
429 dest->mant.m32[1] = rem; /* only for rounding */
430 exp--;
431 }
432
433 if (exp >= 0x7fff) {
434 fp_set_ovrflw(dest);
435 return dest;
436 }
437 dest->exp = exp;
438 if (exp < 0) {
439 fp_set_sr(FPSR_EXC_UNFL);
440 fp_denormalize(dest, -exp);
441 }
442
443 return dest;
444}
445
446/* fp_roundint: Internal rounding function for use by several of these
447 emulated instructions.
448
449 This one rounds off the fractional part using the rounding mode
450 specified. */
451
452static void fp_roundint(struct fp_ext *dest, int mode)
453{
454 union fp_mant64 oldmant;
455 unsigned long mask;
456
457 if (!fp_normalize_ext(dest))
458 return;
459
460 /* infinities and zeroes */
461 if (IS_INF(dest) || IS_ZERO(dest))
462 return;
463
464 /* first truncate the lower bits */
465 oldmant = dest->mant;
466 switch (dest->exp) {
467 case 0 ... 0x3ffe:
468 dest->mant.m64 = 0;
469 break;
470 case 0x3fff ... 0x401e:
471 dest->mant.m32[0] &= 0xffffffffU << (0x401e - dest->exp);
472 dest->mant.m32[1] = 0;
473 if (oldmant.m64 == dest->mant.m64)
474 return;
475 break;
476 case 0x401f ... 0x403e:
477 dest->mant.m32[1] &= 0xffffffffU << (0x403e - dest->exp);
478 if (oldmant.m32[1] == dest->mant.m32[1])
479 return;
480 break;
481 default:
482 return;
483 }
484 fp_set_sr(FPSR_EXC_INEX2);
485
486 /* We might want to normalize upwards here... however, since
487 we know that this is only called on the output of fp_fdiv,
488 or with the input to fp_fint or fp_fintrz, and the inputs
489 to all these functions are either normal or denormalized
490 (no subnormals allowed!), there's really no need.
491
492 In the case of fp_fdiv, observe that 0x80000000 / 0xffff =
493 0xffff8000, and the same holds for 128-bit / 64-bit. (i.e. the
494 smallest possible normal dividend and the largest possible normal
495 divisor will still produce a normal quotient, therefore, (normal
496 << 64) / normal is normal in all cases) */
497
498 switch (mode) {
499 case FPCR_ROUND_RN:
500 switch (dest->exp) {
501 case 0 ... 0x3ffd:
502 return;
503 case 0x3ffe:
504 /* As noted above, the input is always normal, so the
505 guard bit (bit 63) is always set. therefore, the
506 only case in which we will NOT round to 1.0 is when
507 the input is exactly 0.5. */
508 if (oldmant.m64 == (1ULL << 63))
509 return;
510 break;
511 case 0x3fff ... 0x401d:
512 mask = 1 << (0x401d - dest->exp);
513 if (!(oldmant.m32[0] & mask))
514 return;
515 if (oldmant.m32[0] & (mask << 1))
516 break;
517 if (!(oldmant.m32[0] << (dest->exp - 0x3ffd)) &&
518 !oldmant.m32[1])
519 return;
520 break;
521 case 0x401e:
522 if (!(oldmant.m32[1] >= 0))
523 return;
524 if (oldmant.m32[0] & 1)
525 break;
526 if (!(oldmant.m32[1] << 1))
527 return;
528 break;
529 case 0x401f ... 0x403d:
530 mask = 1 << (0x403d - dest->exp);
531 if (!(oldmant.m32[1] & mask))
532 return;
533 if (oldmant.m32[1] & (mask << 1))
534 break;
535 if (!(oldmant.m32[1] << (dest->exp - 0x401d)))
536 return;
537 break;
538 default:
539 return;
540 }
541 break;
542 case FPCR_ROUND_RZ:
543 return;
544 default:
545 if (dest->sign ^ (mode - FPCR_ROUND_RM))
546 break;
547 return;
548 }
549
550 switch (dest->exp) {
551 case 0 ... 0x3ffe:
552 dest->exp = 0x3fff;
553 dest->mant.m64 = 1ULL << 63;
554 break;
555 case 0x3fff ... 0x401e:
556 mask = 1 << (0x401e - dest->exp);
557 if (dest->mant.m32[0] += mask)
558 break;
559 dest->mant.m32[0] = 0x80000000;
560 dest->exp++;
561 break;
562 case 0x401f ... 0x403e:
563 mask = 1 << (0x403e - dest->exp);
564 if (dest->mant.m32[1] += mask)
565 break;
566 if (dest->mant.m32[0] += 1)
567 break;
568 dest->mant.m32[0] = 0x80000000;
569 dest->exp++;
570 break;
571 }
572}
573
574/* modrem_kernel: Implementation of the FREM and FMOD instructions
575 (which are exactly the same, except for the rounding used on the
576 intermediate value) */
577
578static struct fp_ext *
579modrem_kernel(struct fp_ext *dest, struct fp_ext *src, int mode)
580{
581 struct fp_ext tmp;
582
583 fp_dyadic_check(dest, src);
584
585 /* Infinities and zeros */
586 if (IS_INF(dest) || IS_ZERO(src)) {
587 fp_set_nan(dest);
588 return dest;
589 }
590 if (IS_ZERO(dest) || IS_INF(src))
591 return dest;
592
593 /* FIXME: there is almost certainly a smarter way to do this */
594 fp_copy_ext(&tmp, dest);
595 fp_fdiv(&tmp, src); /* NOTE: src might be modified */
596 fp_roundint(&tmp, mode);
597 fp_fmul(&tmp, src);
598 fp_fsub(dest, &tmp);
599
600 /* set the quotient byte */
601 fp_set_quotient((dest->mant.m64 & 0x7f) | (dest->sign << 7));
602 return dest;
603}
604
605/* fp_fmod: Implements the kernel of the FMOD instruction.
606
607 Again, the argument order is backwards. The result, as defined in
608 the Motorola manuals, is:
609
610 fmod(src,dest) = (dest - (src * floor(dest / src))) */
611
612struct fp_ext *
613fp_fmod(struct fp_ext *dest, struct fp_ext *src)
614{
615 dprint(PINSTR, "fmod\n");
616 return modrem_kernel(dest, src, FPCR_ROUND_RZ);
617}
618
619/* fp_frem: Implements the kernel of the FREM instruction.
620
621 frem(src,dest) = (dest - (src * round(dest / src)))
622 */
623
624struct fp_ext *
625fp_frem(struct fp_ext *dest, struct fp_ext *src)
626{
627 dprint(PINSTR, "frem\n");
628 return modrem_kernel(dest, src, FPCR_ROUND_RN);
629}
630
631struct fp_ext *
632fp_fint(struct fp_ext *dest, struct fp_ext *src)
633{
634 dprint(PINSTR, "fint\n");
635
636 fp_copy_ext(dest, src);
637
638 fp_roundint(dest, FPDATA->rnd);
639
640 return dest;
641}
642
643struct fp_ext *
644fp_fintrz(struct fp_ext *dest, struct fp_ext *src)
645{
646 dprint(PINSTR, "fintrz\n");
647
648 fp_copy_ext(dest, src);
649
650 fp_roundint(dest, FPCR_ROUND_RZ);
651
652 return dest;
653}
654
655struct fp_ext *
656fp_fscale(struct fp_ext *dest, struct fp_ext *src)
657{
658 int scale, oldround;
659
660 dprint(PINSTR, "fscale\n");
661
662 fp_dyadic_check(dest, src);
663
664 /* Infinities */
665 if (IS_INF(src)) {
666 fp_set_nan(dest);
667 return dest;
668 }
669 if (IS_INF(dest))
670 return dest;
671
672 /* zeroes */
673 if (IS_ZERO(src) || IS_ZERO(dest))
674 return dest;
675
676 /* Source exponent out of range */
677 if (src->exp >= 0x400c) {
678 fp_set_ovrflw(dest);
679 return dest;
680 }
681
682 /* src must be rounded with round to zero. */
683 oldround = FPDATA->rnd;
684 FPDATA->rnd = FPCR_ROUND_RZ;
685 scale = fp_conv_ext2long(src);
686 FPDATA->rnd = oldround;
687
688 /* new exponent */
689 scale += dest->exp;
690
691 if (scale >= 0x7fff) {
692 fp_set_ovrflw(dest);
693 } else if (scale <= 0) {
694 fp_set_sr(FPSR_EXC_UNFL);
695 fp_denormalize(dest, -scale);
696 } else
697 dest->exp = scale;
698
699 return dest;
700}
701
diff --git a/arch/m68k/math-emu/fp_arith.h b/arch/m68k/math-emu/fp_arith.h
new file mode 100644
index 000000000000..2cc3f846c393
--- /dev/null
+++ b/arch/m68k/math-emu/fp_arith.h
@@ -0,0 +1,52 @@
1/*
2
3 fp_arith.h: floating-point math routines for the Linux-m68k
4 floating point emulator.
5
6 Copyright (c) 1998 David Huggins-Daines.
7
8 Somewhat based on the AlphaLinux floating point emulator, by David
9 Mosberger-Tang.
10
11 You may copy, modify, and redistribute this file under the terms of
12 the GNU General Public License, version 2, or any later version, at
13 your convenience.
14
15 */
16
17#ifndef FP_ARITH_H
18#define FP_ARITH_H
19
20/* easy ones */
21struct fp_ext *
22fp_fabs(struct fp_ext *dest, struct fp_ext *src);
23struct fp_ext *
24fp_fneg(struct fp_ext *dest, struct fp_ext *src);
25
26/* straightforward arithmetic */
27struct fp_ext *
28fp_fadd(struct fp_ext *dest, struct fp_ext *src);
29struct fp_ext *
30fp_fsub(struct fp_ext *dest, struct fp_ext *src);
31struct fp_ext *
32fp_fcmp(struct fp_ext *dest, struct fp_ext *src);
33struct fp_ext *
34fp_ftst(struct fp_ext *dest, struct fp_ext *src);
35struct fp_ext *
36fp_fmul(struct fp_ext *dest, struct fp_ext *src);
37struct fp_ext *
38fp_fdiv(struct fp_ext *dest, struct fp_ext *src);
39
40/* ones that do rounding and integer conversions */
41struct fp_ext *
42fp_fmod(struct fp_ext *dest, struct fp_ext *src);
43struct fp_ext *
44fp_frem(struct fp_ext *dest, struct fp_ext *src);
45struct fp_ext *
46fp_fint(struct fp_ext *dest, struct fp_ext *src);
47struct fp_ext *
48fp_fintrz(struct fp_ext *dest, struct fp_ext *src);
49struct fp_ext *
50fp_fscale(struct fp_ext *dest, struct fp_ext *src);
51
52#endif /* FP_ARITH__H */
diff --git a/arch/m68k/math-emu/fp_cond.S b/arch/m68k/math-emu/fp_cond.S
new file mode 100644
index 000000000000..ddae8b1b8b83
--- /dev/null
+++ b/arch/m68k/math-emu/fp_cond.S
@@ -0,0 +1,334 @@
1/*
2 * fp_cond.S
3 *
4 * Copyright Roman Zippel, 1997. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, and the entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions. (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "fp_emu.h"
39#include "fp_decode.h"
40
41 .globl fp_fscc, fp_fbccw, fp_fbccl
42
43#ifdef FPU_EMU_DEBUG
44fp_fnop:
45 printf PDECODE,"fnop\n"
46 jra fp_end
47#else
48#define fp_fnop fp_end
49#endif
50
51fp_fbccw:
52 tst.w %d2
53 jeq fp_fnop
54 printf PDECODE,"fbccw "
55 fp_get_pc %a0
56 lea (-2,%a0,%d2.w),%a0
57 jra 1f
58
59fp_fbccl:
60 printf PDECODE,"fbccl "
61 fp_get_pc %a0
62 move.l %d2,%d0
63 swap %d0
64 fp_get_instr_word %d0,fp_err_ua1
65 lea (-2,%a0,%d0.l),%a0
661: printf PDECODE,"%x",1,%a0
67 move.l %d2,%d0
68 swap %d0
69 jsr fp_compute_cond
70 tst.l %d0
71 jeq 1f
72 fp_put_pc %a0,1
731: printf PDECODE,"\n"
74 jra fp_end
75
76fp_fdbcc:
77 printf PDECODE,"fdbcc "
78 fp_get_pc %a1 | calculate new pc
79 fp_get_instr_word %d0,fp_err_ua1
80 add.w %d0,%a1
81 fp_decode_addr_reg
82 printf PDECODE,"d%d,%x\n",2,%d0,%a1
83 swap %d1 | test condition in %d1
84 tst.w %d1
85 jne 2f
86 move.l %d0,%d1
87 jsr fp_get_data_reg
88 subq.w #1,%d0
89 jcs 1f
90 fp_put_pc %a1,1
911: jsr fp_put_data_reg
922: jra fp_end
93
94| set flags for decode macros for fs<cc>
95do_fscc=1
96do_no_pc_mode=1
97
98fp_fscc:
99 printf PDECODE,"fscc "
100 move.l %d2,%d0
101 jsr fp_compute_cond
102 move.w %d0,%d1
103 swap %d1
104
105 | decode addressing mode
106 fp_decode_addr_mode
107
108 .long fp_data, fp_fdbcc
109 .long fp_indirect, fp_postinc
110 .long fp_predecr, fp_disp16
111 .long fp_extmode0, fp_extmode1
112
113 | addressing mode: data register direct
114fp_data:
115 fp_mode_data_direct
116 move.w %d0,%d1 | save register nr
117 jsr fp_get_data_reg
118 swap %d1
119 move.b %d1,%d0
120 swap %d1
121 jsr fp_put_data_reg
122 printf PDECODE,"\n"
123 jra fp_end
124
125fp_indirect:
126 fp_mode_addr_indirect
127 jra fp_do_scc
128
129fp_postinc:
130 fp_mode_addr_indirect_postinc
131 jra fp_do_scc
132
133fp_predecr:
134 fp_mode_addr_indirect_predec
135 jra fp_do_scc
136
137fp_disp16:
138 fp_mode_addr_indirect_disp16
139 jra fp_do_scc
140
141fp_extmode0:
142 fp_mode_addr_indirect_extmode0
143 jra fp_do_scc
144
145fp_extmode1:
146 bfextu %d2{#13,#3},%d0
147 jmp ([0f:w,%pc,%d0*4])
148
149 .align 4
1500:
151 .long fp_absolute_short, fp_absolute_long
152 .long fp_ill, fp_ill | NOTE: jump here to ftrap.x
153 .long fp_ill, fp_ill
154 .long fp_ill, fp_ill
155
156fp_absolute_short:
157 fp_mode_abs_short
158 jra fp_do_scc
159
160fp_absolute_long:
161 fp_mode_abs_long
162| jra fp_do_scc
163
164fp_do_scc:
165 swap %d1
166 putuser.b %d1,(%a0),fp_err_ua1,%a0
167 printf PDECODE,"\n"
168 jra fp_end
169
170
171#define tst_NAN btst #24,%d1
172#define tst_Z btst #26,%d1
173#define tst_N btst #27,%d1
174
175fp_compute_cond:
176 move.l (FPD_FPSR,FPDATA),%d1
177 btst #4,%d0
178 jeq 1f
179 tst_NAN
180 jeq 1f
181 bset #15,%d1
182 bset #7,%d1
183 move.l %d1,(FPD_FPSR,FPDATA)
1841: and.w #0xf,%d0
185 jmp ([0f:w,%pc,%d0.w*4])
186
187 .align 4
1880:
189 .long fp_f , fp_eq , fp_ogt, fp_oge
190 .long fp_olt, fp_ole, fp_ogl, fp_or
191 .long fp_un , fp_ueq, fp_ugt, fp_uge
192 .long fp_ult, fp_ule, fp_ne , fp_t
193
194fp_f:
195 moveq #0,%d0
196 rts
197
198fp_eq:
199 moveq #0,%d0
200 tst_Z
201 jeq 1f
202 moveq #-1,%d0
2031: rts
204
205fp_ogt:
206 moveq #0,%d0
207 tst_NAN
208 jne 1f
209 tst_Z
210 jne 1f
211 tst_N
212 jne 1f
213 moveq #-1,%d0
2141: rts
215
216fp_oge:
217 moveq #-1,%d0
218 tst_Z
219 jne 2f
220 tst_NAN
221 jne 1f
222 tst_N
223 jeq 2f
2241: moveq #0,%d0
2252: rts
226
227fp_olt:
228 moveq #0,%d0
229 tst_NAN
230 jne 1f
231 tst_Z
232 jne 1f
233 tst_N
234 jeq 1f
235 moveq #-1,%d0
2361: rts
237
238fp_ole:
239 moveq #-1,%d0
240 tst_Z
241 jne 2f
242 tst_NAN
243 jne 1f
244 tst_N
245 jne 2f
2461: moveq #0,%d0
2472: rts
248
249fp_ogl:
250 moveq #0,%d0
251 tst_NAN
252 jne 1f
253 tst_Z
254 jne 1f
255 moveq #-1,%d0
2561: rts
257
258fp_or:
259 moveq #0,%d0
260 tst_NAN
261 jne 1f
262 moveq #-1,%d0
2631: rts
264
265fp_un:
266 moveq #0,%d0
267 tst_NAN
268 jeq 1f
269 moveq #-1,%d0
270 rts
271
272fp_ueq:
273 moveq #-1,%d0
274 tst_NAN
275 jne 1f
276 tst_Z
277 jne 1f
278 moveq #0,%d0
2791: rts
280
281fp_ugt:
282 moveq #-1,%d0
283 tst_NAN
284 jne 2f
285 tst_N
286 jne 1f
287 tst_Z
288 jeq 2f
2891: moveq #0,%d0
2902: rts
291
292fp_uge:
293 moveq #-1,%d0
294 tst_NAN
295 jne 1f
296 tst_Z
297 jne 1f
298 tst_N
299 jeq 1f
300 moveq #0,%d0
3011: rts
302
303fp_ult:
304 moveq #-1,%d0
305 tst_NAN
306 jne 2f
307 tst_Z
308 jne 1f
309 tst_N
310 jne 2f
3111: moveq #0,%d0
3122: rts
313
314fp_ule:
315 moveq #-1,%d0
316 tst_NAN
317 jne 1f
318 tst_Z
319 jne 1f
320 tst_N
321 jne 1f
322 moveq #0,%d0
3231: rts
324
325fp_ne:
326 moveq #0,%d0
327 tst_Z
328 jne 1f
329 moveq #-1,%d0
3301: rts
331
332fp_t:
333 moveq #-1,%d0
334 rts
diff --git a/arch/m68k/math-emu/fp_decode.h b/arch/m68k/math-emu/fp_decode.h
new file mode 100644
index 000000000000..759679d9ab96
--- /dev/null
+++ b/arch/m68k/math-emu/fp_decode.h
@@ -0,0 +1,417 @@
1/*
2 * fp_decode.h
3 *
4 * Copyright Roman Zippel, 1997. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, and the entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions. (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef _FP_DECODE_H
39#define _FP_DECODE_H
40
41/* These macros do the dirty work of the instr decoding, several variables
42 * can be defined in the source file to modify the work of these macros,
43 * currently the following variables are used:
44 * ...
45 * The register usage:
46 * d0 - will contain source operand for data direct mode,
47 * otherwise scratch register
48 * d1 - upper 16bit are reserved for caller
49 * lower 16bit may contain further arguments,
50 * is destroyed during decoding
51 * d2 - contains first two instruction words,
52 * first word will be used for extension word
53 * a0 - will point to source/dest operand for any indirect mode
54 * otherwise scratch register
55 * a1 - scratch register
56 * a2 - base addr to the task structure
57 *
58 * the current implementation doesn't check for every disallowed
59 * addressing mode (e.g. pc relative modes as destination), as long
60 * as it only means a new addressing mode, which should not appear
61 * in a program and that doesn't crash the emulation, I think it's
62 * not a problem to allow these modes.
63 */
64
65do_fmovem=0
66do_fmovem_cr=0
67do_no_pc_mode=0
68do_fscc=0
69
70| first decoding of the instr type
71| this separates the conditional instr
72.macro fp_decode_cond_instr_type
73 bfextu %d2{#8,#2},%d0
74 jmp ([0f:w,%pc,%d0*4])
75
76 .align 4
770:
78| .long "f<op>","fscc/fdbcc"
79| .long "fbccw","fbccl"
80.endm
81
82| second decoding of the instr type
83| this separates most move instr
84.macro fp_decode_move_instr_type
85 bfextu %d2{#16,#3},%d0
86 jmp ([0f:w,%pc,%d0*4])
87
88 .align 4
890:
90| .long "f<op> fpx,fpx","invalid instr"
91| .long "f<op> <ea>,fpx","fmove fpx,<ea>"
92| .long "fmovem <ea>,fpcr","fmovem <ea>,fpx"
93| .long "fmovem fpcr,<ea>","fmovem fpx,<ea>"
94.endm
95
96| extract the source specifier, specifies
97| either source fp register or data format
98.macro fp_decode_sourcespec
99 bfextu %d2{#19,#3},%d0
100.endm
101
102| decode destination format for fmove reg,ea
103.macro fp_decode_dest_format
104 bfextu %d2{#19,#3},%d0
105.endm
106
107| decode source register for fmove reg,ea
108.macro fp_decode_src_reg
109 bfextu %d2{#22,#3},%d0
110.endm
111
112| extract the addressing mode
113| it depends on the instr which of the modes is valid
114.macro fp_decode_addr_mode
115 bfextu %d2{#10,#3},%d0
116 jmp ([0f:w,%pc,%d0*4])
117
118 .align 4
1190:
120| .long "data register direct","addr register direct"
121| .long "addr register indirect"
122| .long "addr register indirect postincrement"
123| .long "addr register indirect predecrement"
124| .long "addr register + index16"
125| .long "extension mode1","extension mode2"
126.endm
127
128| extract the register for the addressing mode
129.macro fp_decode_addr_reg
130 bfextu %d2{#13,#3},%d0
131.endm
132
133| decode the 8bit diplacement from the brief extension word
134.macro fp_decode_disp8
135 move.b %d2,%d0
136 ext.w %d0
137.endm
138
139| decode the index of the brief/full extension word
140.macro fp_decode_index
141 bfextu %d2{#17,#3},%d0 | get the register nr
142 btst #15,%d2 | test for data/addr register
143 jne 1\@f
144 printf PDECODE,"d%d",1,%d0
145 jsr fp_get_data_reg
146 jra 2\@f
1471\@: printf PDECODE,"a%d",1,%d0
148 jsr fp_get_addr_reg
149 move.l %a0,%d0
1502\@:
151debug lea "'l'.w,%a0"
152 btst #11,%d2 | 16/32 bit size?
153 jne 3\@f
154debug lea "'w'.w,%a0"
155 ext.l %d0
1563\@: printf PDECODE,":%c",1,%a0
157 move.w %d2,%d1 | scale factor
158 rol.w #7,%d1
159 and.w #3,%d1
160debug move.l "%d1,-(%sp)"
161debug ext.l "%d1"
162 printf PDECODE,":%d",1,%d1
163debug move.l "(%sp)+,%d1"
164 lsl.l %d1,%d0
165.endm
166
167| decode the base displacement size
168.macro fp_decode_basedisp
169 bfextu %d2{#26,#2},%d0
170 jmp ([0f:w,%pc,%d0*4])
171
172 .align 4
1730:
174| .long "reserved","null displacement"
175| .long "word displacement","long displacement"
176.endm
177
178.macro fp_decode_outerdisp
179 bfextu %d2{#30,#2},%d0
180 jmp ([0f:w,%pc,%d0*4])
181
182 .align 4
1830:
184| .long "no memory indirect action/reserved","null outer displacement"
185| .long "word outer displacement","long outer displacement"
186.endm
187
188| get the extension word and test for brief or full extension type
189.macro fp_get_test_extword label
190 fp_get_instr_word %d2,fp_err_ua1
191 btst #8,%d2
192 jne \label
193.endm
194
195
196| test if %pc is the base register for the indirect addr mode
197.macro fp_test_basereg_d16 label
198 btst #20,%d2
199 jeq \label
200.endm
201
202| test if %pc is the base register for one of the extended modes
203.macro fp_test_basereg_ext label
204 btst #19,%d2
205 jeq \label
206.endm
207
208.macro fp_test_suppr_index label
209 btst #6,%d2
210 jne \label
211.endm
212
213
214| addressing mode: data register direct
215.macro fp_mode_data_direct
216 fp_decode_addr_reg
217 printf PDECODE,"d%d",1,%d0
218.endm
219
220| addressing mode: address register indirect
221.macro fp_mode_addr_indirect
222 fp_decode_addr_reg
223 printf PDECODE,"(a%d)",1,%d0
224 jsr fp_get_addr_reg
225.endm
226
227| adjust stack for byte moves from/to stack
228.macro fp_test_sp_byte_move
229 .if !do_fmovem
230 .if do_fscc
231 move.w #6,%d1
232 .endif
233 cmp.w #7,%d0
234 jne 1\@f
235 .if !do_fscc
236 cmp.w #6,%d1
237 jne 1\@f
238 .endif
239 move.w #4,%d1
2401\@:
241 .endif
242.endm
243
244| addressing mode: address register indirect with postincrement
245.macro fp_mode_addr_indirect_postinc
246 fp_decode_addr_reg
247 printf PDECODE,"(a%d)+",1,%d0
248 fp_test_sp_byte_move
249 jsr fp_get_addr_reg
250 move.l %a0,%a1 | save addr
251 .if do_fmovem
252 lea (%a0,%d1.w*4),%a0
253 .if !do_fmovem_cr
254 lea (%a0,%d1.w*8),%a0
255 .endif
256 .else
257 add.w (fp_datasize,%d1.w*2),%a0
258 .endif
259 jsr fp_put_addr_reg
260 move.l %a1,%a0
261.endm
262
263| addressing mode: address register indirect with predecrement
264.macro fp_mode_addr_indirect_predec
265 fp_decode_addr_reg
266 printf PDECODE,"-(a%d)",1,%d0
267 fp_test_sp_byte_move
268 jsr fp_get_addr_reg
269 .if do_fmovem
270 .if !do_fmovem_cr
271 lea (-12,%a0),%a1 | setup to addr of 1st reg to move
272 neg.w %d1
273 lea (%a0,%d1.w*4),%a0
274 add.w %d1,%d1
275 lea (%a0,%d1.w*4),%a0
276 jsr fp_put_addr_reg
277 move.l %a1,%a0
278 .else
279 neg.w %d1
280 lea (%a0,%d1.w*4),%a0
281 jsr fp_put_addr_reg
282 .endif
283 .else
284 sub.w (fp_datasize,%d1.w*2),%a0
285 jsr fp_put_addr_reg
286 .endif
287.endm
288
289| addressing mode: address register/programm counter indirect
290| with 16bit displacement
291.macro fp_mode_addr_indirect_disp16
292 .if !do_no_pc_mode
293 fp_test_basereg_d16 1f
294 printf PDECODE,"pc"
295 fp_get_pc %a0
296 jra 2f
297 .endif
2981: fp_decode_addr_reg
299 printf PDECODE,"a%d",1,%d0
300 jsr fp_get_addr_reg
3012: fp_get_instr_word %a1,fp_err_ua1
302 printf PDECODE,"@(%x)",1,%a1
303 add.l %a1,%a0
304.endm
305
306| perform preindex (if I/IS == 0xx and xx != 00)
307.macro fp_do_preindex
308 moveq #3,%d0
309 and.w %d2,%d0
310 jeq 1f
311 btst #2,%d2
312 jne 1f
313 printf PDECODE,")@("
314 getuser.l (%a1),%a1,fp_err_ua1,%a1
315debug jra "2f"
3161: printf PDECODE,","
3172:
318.endm
319
320| perform postindex (if I/IS == 1xx)
321.macro fp_do_postindex
322 btst #2,%d2
323 jeq 1f
324 printf PDECODE,")@("
325 getuser.l (%a1),%a1,fp_err_ua1,%a1
326debug jra "2f"
3271: printf PDECODE,","
3282:
329.endm
330
331| all other indirect addressing modes will finally end up here
332.macro fp_mode_addr_indirect_extmode0
333 .if !do_no_pc_mode
334 fp_test_basereg_ext 1f
335 printf PDECODE,"pc"
336 fp_get_pc %a0
337 jra 2f
338 .endif
3391: fp_decode_addr_reg
340 printf PDECODE,"a%d",1,%d0
341 jsr fp_get_addr_reg
3422: move.l %a0,%a1
343 swap %d2
344 fp_get_test_extword 3f
345 | addressing mode: address register/programm counter indirect
346 | with index and 8bit displacement
347 fp_decode_disp8
348debug ext.l "%d0"
349 printf PDECODE,"@(%x,",1,%d0
350 add.w %d0,%a1
351 fp_decode_index
352 add.l %d0,%a1
353 printf PDECODE,")"
354 jra 9f
3553: | addressing mode: address register/programm counter memory indirect
356 | with base and/or outer displacement
357 btst #7,%d2 | base register suppressed?
358 jeq 1f
359 printf PDECODE,"!"
360 sub.l %a1,%a1
3611: printf PDECODE,"@("
362 fp_decode_basedisp
363
364 .long fp_ill,1f
365 .long 2f,3f
366
367#ifdef FPU_EMU_DEBUG
3681: printf PDECODE,"0" | null base displacement
369 jra 1f
370#endif
3712: fp_get_instr_word %a0,fp_err_ua1 | 16bit base displacement
372 printf PDECODE,"%x:w",1,%a0
373 jra 4f
3743: fp_get_instr_long %a0,fp_err_ua1 | 32bit base displacement
375 printf PDECODE,"%x:l",1,%a0
3764: add.l %a0,%a1
3771:
378 fp_do_postindex
379 fp_test_suppr_index 1f
380 fp_decode_index
381 add.l %d0,%a1
3821: fp_do_preindex
383
384 fp_decode_outerdisp
385
386 .long 5f,1f
387 .long 2f,3f
388
389#ifdef FPU_EMU_DEBUG
3901: printf PDECODE,"0" | null outer displacement
391 jra 1f
392#endif
3932: fp_get_instr_word %a0,fp_err_ua1 | 16bit outer displacement
394 printf PDECODE,"%x:w",1,%a0
395 jra 4f
3963: fp_get_instr_long %a0,fp_err_ua1 | 32bit outer displacement
397 printf PDECODE,"%x:l",1,%a0
3984: add.l %a0,%a1
3991:
4005: printf PDECODE,")"
4019: move.l %a1,%a0
402 swap %d2
403.endm
404
405| get the absolute short address from user space
406.macro fp_mode_abs_short
407 fp_get_instr_word %a0,fp_err_ua1
408 printf PDECODE,"%x.w",1,%a0
409.endm
410
411| get the absolute long address from user space
412.macro fp_mode_abs_long
413 fp_get_instr_long %a0,fp_err_ua1
414 printf PDECODE,"%x.l",1,%a0
415.endm
416
417#endif /* _FP_DECODE_H */
diff --git a/arch/m68k/math-emu/fp_emu.h b/arch/m68k/math-emu/fp_emu.h
new file mode 100644
index 000000000000..1d6edc975d89
--- /dev/null
+++ b/arch/m68k/math-emu/fp_emu.h
@@ -0,0 +1,146 @@
1/*
2 * fp_emu.h
3 *
4 * Copyright Roman Zippel, 1997. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, and the entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions. (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef _FP_EMU_H
39#define _FP_EMU_H
40
41#ifdef __ASSEMBLY__
42#include <asm/offsets.h>
43#endif
44#include <asm/math-emu.h>
45
46#ifndef __ASSEMBLY__
47
48#define IS_INF(a) ((a)->exp == 0x7fff)
49#define IS_ZERO(a) ((a)->mant.m64 == 0)
50
51
52#define fp_set_sr(bit) ({ \
53 FPDATA->fpsr |= 1 << (bit); \
54})
55
56#define fp_set_quotient(quotient) ({ \
57 FPDATA->fpsr &= 0xff00ffff; \
58 FPDATA->fpsr |= ((quotient) & 0xff) << 16; \
59})
60
61/* linkage for several useful functions */
62
63/* Normalize the extended struct, return 0 for a NaN */
64#define fp_normalize_ext(fpreg) ({ \
65 register struct fp_ext *reg asm ("a0") = fpreg; \
66 register int res asm ("d0"); \
67 \
68 asm volatile ("jsr fp_conv_ext2ext" \
69 : "=d" (res) : "a" (reg) \
70 : "a1", "d1", "d2", "memory"); \
71 res; \
72})
73
74#define fp_copy_ext(dest, src) ({ \
75 *dest = *src; \
76})
77
78#define fp_monadic_check(dest, src) ({ \
79 fp_copy_ext(dest, src); \
80 if (!fp_normalize_ext(dest)) \
81 return dest; \
82})
83
84#define fp_dyadic_check(dest, src) ({ \
85 if (!fp_normalize_ext(dest)) \
86 return dest; \
87 if (!fp_normalize_ext(src)) { \
88 fp_copy_ext(dest, src); \
89 return dest; \
90 } \
91})
92
93extern const struct fp_ext fp_QNaN;
94extern const struct fp_ext fp_Inf;
95
96#define fp_set_nan(dest) ({ \
97 fp_set_sr(FPSR_EXC_OPERR); \
98 *dest = fp_QNaN; \
99})
100
101/* TODO check rounding mode? */
102#define fp_set_ovrflw(dest) ({ \
103 fp_set_sr(FPSR_EXC_OVFL); \
104 dest->exp = 0x7fff; \
105 dest->mant.m64 = 0; \
106})
107
108#define fp_conv_ext2long(src) ({ \
109 register struct fp_ext *__src asm ("a0") = src; \
110 register int __res asm ("d0"); \
111 \
112 asm volatile ("jsr fp_conv_ext2long" \
113 : "=d" (__res) : "a" (__src) \
114 : "a1", "d1", "d2", "memory"); \
115 __res; \
116})
117
118#define fp_conv_long2ext(dest, src) ({ \
119 register struct fp_ext *__dest asm ("a0") = dest; \
120 register int __src asm ("d0") = src; \
121 \
122 asm volatile ("jsr fp_conv_ext2long" \
123 : : "d" (__src), "a" (__dest) \
124 : "a1", "d1", "d2", "memory"); \
125})
126
127#else /* __ASSEMBLY__ */
128
129/*
130 * set, reset or clear a bit in the fp status register
131 */
132.macro fp_set_sr bit
133 bset #(\bit&7),(FPD_FPSR+3-(\bit/8),FPDATA)
134.endm
135
136.macro fp_clr_sr bit
137 bclr #(\bit&7),(FPD_FPSR+3-(\bit/8),FPDATA)
138.endm
139
140.macro fp_tst_sr bit
141 btst #(\bit&7),(FPD_FPSR+3-(\bit/8),FPDATA)
142.endm
143
144#endif /* __ASSEMBLY__ */
145
146#endif /* _FP_EMU_H */
diff --git a/arch/m68k/math-emu/fp_entry.S b/arch/m68k/math-emu/fp_entry.S
new file mode 100644
index 000000000000..5ec2d9101ea3
--- /dev/null
+++ b/arch/m68k/math-emu/fp_entry.S
@@ -0,0 +1,325 @@
1/*
2 * fp_emu.S
3 *
4 * Copyright Roman Zippel, 1997. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, and the entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions. (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <linux/config.h>
39#include <linux/linkage.h>
40#include <asm/entry.h>
41
42#include "fp_emu.h"
43
44 .globl fpu_emu
45 .globl fp_debugprint
46 .globl fp_err_ua1,fp_err_ua2
47
48 .text
49fpu_emu:
50 SAVE_ALL_INT
51 GET_CURRENT(%d0)
52
53#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
54 tst.l m68k_is040or060
55 jeq 1f
56#endif
57#if defined(CPU_M68040_OR_M68060)
58 move.l (FPS_PC2,%sp),(FPS_PC,%sp)
59#endif
601:
61 | emulate the instruction
62 jsr fp_scan
63
64#if defined(CONFIG_M68060)
65#if !defined(CPU_M68060_ONLY)
66 btst #3,m68k_cputype+3
67 jeq 1f
68#endif
69 btst #7,(FPS_SR,%sp)
70 jne fp_sendtrace060
71#endif
721:
73 | emulation successful?
74 tst.l %d0
75 jeq ret_from_exception
76
77 | send some signal to program here
78
79 jra ret_from_exception
80
81 | we jump here after an access error while trying to access
82 | user space, we correct stackpointer and send a SIGSEGV to
83 | the user process
84fp_err_ua2:
85 addq.l #4,%sp
86fp_err_ua1:
87 addq.l #4,%sp
88 move.l %a0,-(%sp)
89 pea SEGV_MAPERR
90 pea SIGSEGV
91 jsr fpemu_signal
92 add.w #12,%sp
93 jra ret_from_exception
94
95#if defined(CONFIG_M68060)
96 | send a trace signal if we are debugged
97 | it does not really belong here, but...
98fp_sendtrace060:
99 move.l (FPS_PC,%sp),-(%sp)
100 pea TRAP_TRACE
101 pea SIGTRAP
102 jsr fpemu_signal
103 add.w #12,%sp
104 jra ret_from_exception
105#endif
106
107 .globl fp_get_data_reg, fp_put_data_reg
108 .globl fp_get_addr_reg, fp_put_addr_reg
109
110 | Entry points to get/put a register. Some of them can be get/put
111 | directly, others are on the stack, as we read/write the stack
112 | directly here, these function may only be called from within
113 | instruction decoding, otherwise the stack pointer is incorrect
114 | and the stack gets corrupted.
115fp_get_data_reg:
116 jmp ([0f:w,%pc,%d0.w*4])
117
118 .align 4
1190:
120 .long fp_get_d0, fp_get_d1
121 .long fp_get_d2, fp_get_d3
122 .long fp_get_d4, fp_get_d5
123 .long fp_get_d6, fp_get_d7
124
125fp_get_d0:
126 move.l (PT_D0+8,%sp),%d0
127 printf PREGISTER,"{d0->%08x}",1,%d0
128 rts
129
130fp_get_d1:
131 move.l (PT_D1+8,%sp),%d0
132 printf PREGISTER,"{d1->%08x}",1,%d0
133 rts
134
135fp_get_d2:
136 move.l (PT_D2+8,%sp),%d0
137 printf PREGISTER,"{d2->%08x}",1,%d0
138 rts
139
140fp_get_d3:
141 move.l %d3,%d0
142 printf PREGISTER,"{d3->%08x}",1,%d0
143 rts
144
145fp_get_d4:
146 move.l %d4,%d0
147 printf PREGISTER,"{d4->%08x}",1,%d0
148 rts
149
150fp_get_d5:
151 move.l %d5,%d0
152 printf PREGISTER,"{d5->%08x}",1,%d0
153 rts
154
155fp_get_d6:
156 move.l %d6,%d0
157 printf PREGISTER,"{d6->%08x}",1,%d0
158 rts
159
160fp_get_d7:
161 move.l %d7,%d0
162 printf PREGISTER,"{d7->%08x}",1,%d0
163 rts
164
165fp_put_data_reg:
166 jmp ([0f:w,%pc,%d1.w*4])
167
168 .align 4
1690:
170 .long fp_put_d0, fp_put_d1
171 .long fp_put_d2, fp_put_d3
172 .long fp_put_d4, fp_put_d5
173 .long fp_put_d6, fp_put_d7
174
175fp_put_d0:
176 printf PREGISTER,"{d0<-%08x}",1,%d0
177 move.l %d0,(PT_D0+8,%sp)
178 rts
179
180fp_put_d1:
181 printf PREGISTER,"{d1<-%08x}",1,%d0
182 move.l %d0,(PT_D1+8,%sp)
183 rts
184
185fp_put_d2:
186 printf PREGISTER,"{d2<-%08x}",1,%d0
187 move.l %d0,(PT_D2+8,%sp)
188 rts
189
190fp_put_d3:
191 printf PREGISTER,"{d3<-%08x}",1,%d0
192| move.l %d0,%d3
193 move.l %d0,(PT_D3+8,%sp)
194 rts
195
196fp_put_d4:
197 printf PREGISTER,"{d4<-%08x}",1,%d0
198| move.l %d0,%d4
199 move.l %d0,(PT_D4+8,%sp)
200 rts
201
202fp_put_d5:
203 printf PREGISTER,"{d5<-%08x}",1,%d0
204| move.l %d0,%d5
205 move.l %d0,(PT_D5+8,%sp)
206 rts
207
208fp_put_d6:
209 printf PREGISTER,"{d6<-%08x}",1,%d0
210 move.l %d0,%d6
211 rts
212
213fp_put_d7:
214 printf PREGISTER,"{d7<-%08x}",1,%d0
215 move.l %d0,%d7
216 rts
217
218fp_get_addr_reg:
219 jmp ([0f:w,%pc,%d0.w*4])
220
221 .align 4
2220:
223 .long fp_get_a0, fp_get_a1
224 .long fp_get_a2, fp_get_a3
225 .long fp_get_a4, fp_get_a5
226 .long fp_get_a6, fp_get_a7
227
228fp_get_a0:
229 move.l (PT_A0+8,%sp),%a0
230 printf PREGISTER,"{a0->%08x}",1,%a0
231 rts
232
233fp_get_a1:
234 move.l (PT_A1+8,%sp),%a0
235 printf PREGISTER,"{a1->%08x}",1,%a0
236 rts
237
238fp_get_a2:
239 move.l (PT_A2+8,%sp),%a0
240 printf PREGISTER,"{a2->%08x}",1,%a0
241 rts
242
243fp_get_a3:
244 move.l %a3,%a0
245 printf PREGISTER,"{a3->%08x}",1,%a0
246 rts
247
248fp_get_a4:
249 move.l %a4,%a0
250 printf PREGISTER,"{a4->%08x}",1,%a0
251 rts
252
253fp_get_a5:
254 move.l %a5,%a0
255 printf PREGISTER,"{a5->%08x}",1,%a0
256 rts
257
258fp_get_a6:
259 move.l %a6,%a0
260 printf PREGISTER,"{a6->%08x}",1,%a0
261 rts
262
263fp_get_a7:
264 move.l %usp,%a0
265 printf PREGISTER,"{a7->%08x}",1,%a0
266 rts
267
268fp_put_addr_reg:
269 jmp ([0f:w,%pc,%d0.w*4])
270
271 .align 4
2720:
273 .long fp_put_a0, fp_put_a1
274 .long fp_put_a2, fp_put_a3
275 .long fp_put_a4, fp_put_a5
276 .long fp_put_a6, fp_put_a7
277
278fp_put_a0:
279 printf PREGISTER,"{a0<-%08x}",1,%a0
280 move.l %a0,(PT_A0+8,%sp)
281 rts
282
283fp_put_a1:
284 printf PREGISTER,"{a1<-%08x}",1,%a0
285 move.l %a0,(PT_A1+8,%sp)
286 rts
287
288fp_put_a2:
289 printf PREGISTER,"{a2<-%08x}",1,%a0
290 move.l %a0,(PT_A2+8,%sp)
291 rts
292
293fp_put_a3:
294 printf PREGISTER,"{a3<-%08x}",1,%a0
295 move.l %a0,%a3
296 rts
297
298fp_put_a4:
299 printf PREGISTER,"{a4<-%08x}",1,%a0
300 move.l %a0,%a4
301 rts
302
303fp_put_a5:
304 printf PREGISTER,"{a5<-%08x}",1,%a0
305 move.l %a0,%a5
306 rts
307
308fp_put_a6:
309 printf PREGISTER,"{a6<-%08x}",1,%a0
310 move.l %a0,%a6
311 rts
312
313fp_put_a7:
314 printf PREGISTER,"{a7<-%08x}",1,%a0
315 move.l %a0,%usp
316 rts
317
318 .data
319 .align 4
320
321fp_debugprint:
322| .long PMDECODE
323 .long PMINSTR+PMDECODE+PMCONV+PMNORM
324| .long PMCONV+PMNORM+PMINSTR
325| .long 0
diff --git a/arch/m68k/math-emu/fp_log.c b/arch/m68k/math-emu/fp_log.c
new file mode 100644
index 000000000000..87b4f0158560
--- /dev/null
+++ b/arch/m68k/math-emu/fp_log.c
@@ -0,0 +1,223 @@
1/*
2
3 fp_trig.c: floating-point math routines for the Linux-m68k
4 floating point emulator.
5
6 Copyright (c) 1998-1999 David Huggins-Daines / Roman Zippel.
7
8 I hereby give permission, free of charge, to copy, modify, and
9 redistribute this software, in source or binary form, provided that
10 the above copyright notice and the following disclaimer are included
11 in all such copies.
12
13 THIS SOFTWARE IS PROVIDED "AS IS", WITH ABSOLUTELY NO WARRANTY, REAL
14 OR IMPLIED.
15
16*/
17
18#include "fp_emu.h"
19
20static const struct fp_ext fp_one =
21{
22 .exp = 0x3fff,
23};
24
25extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src);
26extern struct fp_ext *fp_fdiv(struct fp_ext *dest, const struct fp_ext *src);
27extern struct fp_ext *fp_fmul(struct fp_ext *dest, const struct fp_ext *src);
28
29struct fp_ext *
30fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
31{
32 struct fp_ext tmp, src2;
33 int i, exp;
34
35 dprint(PINSTR, "fsqrt\n");
36
37 fp_monadic_check(dest, src);
38
39 if (IS_ZERO(dest))
40 return dest;
41
42 if (dest->sign) {
43 fp_set_nan(dest);
44 return dest;
45 }
46 if (IS_INF(dest))
47 return dest;
48
49 /*
50 * sqrt(m) * 2^(p) , if e = 2*p
51 * sqrt(m*2^e) =
52 * sqrt(2*m) * 2^(p) , if e = 2*p + 1
53 *
54 * So we use the last bit of the exponent to decide wether to
55 * use the m or 2*m.
56 *
57 * Since only the fractional part of the mantissa is stored and
58 * the integer part is assumed to be one, we place a 1 or 2 into
59 * the fixed point representation.
60 */
61 exp = dest->exp;
62 dest->exp = 0x3FFF;
63 if (!(exp & 1)) /* lowest bit of exponent is set */
64 dest->exp++;
65 fp_copy_ext(&src2, dest);
66
67 /*
68 * The taylor row arround a for sqrt(x) is:
69 * sqrt(x) = sqrt(a) + 1/(2*sqrt(a))*(x-a) + R
70 * With a=1 this gives:
71 * sqrt(x) = 1 + 1/2*(x-1)
72 * = 1/2*(1+x)
73 */
74 fp_fadd(dest, &fp_one);
75 dest->exp--; /* * 1/2 */
76
77 /*
78 * We now apply the newton rule to the function
79 * f(x) := x^2 - r
80 * which has a null point on x = sqrt(r).
81 *
82 * It gives:
83 * x' := x - f(x)/f'(x)
84 * = x - (x^2 -r)/(2*x)
85 * = x - (x - r/x)/2
86 * = (2*x - x + r/x)/2
87 * = (x + r/x)/2
88 */
89 for (i = 0; i < 9; i++) {
90 fp_copy_ext(&tmp, &src2);
91
92 fp_fdiv(&tmp, dest);
93 fp_fadd(dest, &tmp);
94 dest->exp--;
95 }
96
97 dest->exp += (exp - 0x3FFF) / 2;
98
99 return dest;
100}
101
102struct fp_ext *
103fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src)
104{
105 uprint("fetoxm1\n");
106
107 fp_monadic_check(dest, src);
108
109 if (IS_ZERO(dest))
110 return dest;
111
112 return dest;
113}
114
115struct fp_ext *
116fp_fetox(struct fp_ext *dest, struct fp_ext *src)
117{
118 uprint("fetox\n");
119
120 fp_monadic_check(dest, src);
121
122 return dest;
123}
124
125struct fp_ext *
126fp_ftwotox(struct fp_ext *dest, struct fp_ext *src)
127{
128 uprint("ftwotox\n");
129
130 fp_monadic_check(dest, src);
131
132 return dest;
133}
134
135struct fp_ext *
136fp_ftentox(struct fp_ext *dest, struct fp_ext *src)
137{
138 uprint("ftentox\n");
139
140 fp_monadic_check(dest, src);
141
142 return dest;
143}
144
145struct fp_ext *
146fp_flogn(struct fp_ext *dest, struct fp_ext *src)
147{
148 uprint("flogn\n");
149
150 fp_monadic_check(dest, src);
151
152 return dest;
153}
154
155struct fp_ext *
156fp_flognp1(struct fp_ext *dest, struct fp_ext *src)
157{
158 uprint("flognp1\n");
159
160 fp_monadic_check(dest, src);
161
162 return dest;
163}
164
165struct fp_ext *
166fp_flog10(struct fp_ext *dest, struct fp_ext *src)
167{
168 uprint("flog10\n");
169
170 fp_monadic_check(dest, src);
171
172 return dest;
173}
174
175struct fp_ext *
176fp_flog2(struct fp_ext *dest, struct fp_ext *src)
177{
178 uprint("flog2\n");
179
180 fp_monadic_check(dest, src);
181
182 return dest;
183}
184
185struct fp_ext *
186fp_fgetexp(struct fp_ext *dest, struct fp_ext *src)
187{
188 dprint(PINSTR, "fgetexp\n");
189
190 fp_monadic_check(dest, src);
191
192 if (IS_INF(dest)) {
193 fp_set_nan(dest);
194 return dest;
195 }
196 if (IS_ZERO(dest))
197 return dest;
198
199 fp_conv_long2ext(dest, (int)dest->exp - 0x3FFF);
200
201 fp_normalize_ext(dest);
202
203 return dest;
204}
205
206struct fp_ext *
207fp_fgetman(struct fp_ext *dest, struct fp_ext *src)
208{
209 dprint(PINSTR, "fgetman\n");
210
211 fp_monadic_check(dest, src);
212
213 if (IS_ZERO(dest))
214 return dest;
215
216 if (IS_INF(dest))
217 return dest;
218
219 dest->exp = 0x3FFF;
220
221 return dest;
222}
223
diff --git a/arch/m68k/math-emu/fp_move.S b/arch/m68k/math-emu/fp_move.S
new file mode 100644
index 000000000000..71bdf83ba61a
--- /dev/null
+++ b/arch/m68k/math-emu/fp_move.S
@@ -0,0 +1,244 @@
1/*
2 * fp_move.S
3 *
4 * Copyright Roman Zippel, 1997. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, and the entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions. (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "fp_emu.h"
39#include "fp_decode.h"
40
41do_no_pc_mode=1
42
43 .globl fp_fmove_fp2mem
44
45fp_fmove_fp2mem:
46 clr.b (2+FPD_FPSR,FPDATA)
47 fp_decode_dest_format
48 move.w %d0,%d1 | store data size twice in %d1
49 swap %d1 | one can be trashed below
50 move.w %d0,%d1
51#ifdef FPU_EMU_DEBUG
52 lea 0f,%a0
53 clr.l %d0
54 move.b (%a0,%d1.w),%d0
55 printf PDECODE,"fmove.%c ",1,%d0
56 fp_decode_src_reg
57 printf PDECODE,"fp%d,",1,%d0
58
59 .data
600: .byte 'l','s','x','p','w','d','b','p'
61 .previous
62#endif
63
64 | encode addressing mode for dest
65 fp_decode_addr_mode
66
67 .long fp_data, fp_ill
68 .long fp_indirect, fp_postinc
69 .long fp_predecr, fp_disp16
70 .long fp_extmode0, fp_extmode1
71
72 | addressing mode: data register direct
73fp_data:
74 fp_mode_data_direct
75 move.w %d0,%d1
76 fp_decode_src_reg
77 fp_get_fp_reg
78 lea (FPD_TEMPFP1,FPDATA),%a1
79 move.l (%a0)+,(%a1)+
80 move.l (%a0)+,(%a1)+
81 move.l (%a0),(%a1)
82 lea (-8,%a1),%a0
83 swap %d1
84 move.l %d1,%d2
85 printf PDECODE,"\n"
86 jmp ([0f:w,%pc,%d1.w*4])
87
88 .align 4
890:
90 .long fp_data_long, fp_data_single
91 .long fp_ill, fp_ill
92 .long fp_data_word, fp_ill
93 .long fp_data_byte, fp_ill
94
95fp_data_byte:
96 jsr fp_normalize_ext
97 jsr fp_conv_ext2byte
98 move.l %d0,%d1
99 swap %d2
100 move.w %d2,%d0
101 jsr fp_get_data_reg
102 move.b %d1,%d0
103 move.w %d2,%d1
104 jsr fp_put_data_reg
105 jra fp_final
106
107fp_data_word:
108 jsr fp_normalize_ext
109 jsr fp_conv_ext2short
110 move.l %d0,%d1
111 swap %d2
112 move.w %d2,%d0
113 jsr fp_get_data_reg
114 move.w %d1,%d0
115 move.l %d2,%d1
116 jsr fp_put_data_reg
117 jra fp_final
118
119fp_data_long:
120 jsr fp_normalize_ext
121 jsr fp_conv_ext2long
122 swap %d2
123 move.w %d2,%d1
124 jsr fp_put_data_reg
125 jra fp_final
126
127fp_data_single:
128 jsr fp_normalize_ext
129 jsr fp_conv_ext2single
130 swap %d2
131 move.w %d2,%d1
132 jsr fp_put_data_reg
133 jra fp_final
134
135 | addressing mode: address register indirect
136fp_indirect:
137 fp_mode_addr_indirect
138 jra fp_putdest
139
140 | addressing mode: address register indirect with postincrement
141fp_postinc:
142 fp_mode_addr_indirect_postinc
143 jra fp_putdest
144
145 | addressing mode: address register indirect with predecrement
146fp_predecr:
147 fp_mode_addr_indirect_predec
148 jra fp_putdest
149
150 | addressing mode: address register indirect with 16bit displacement
151fp_disp16:
152 fp_mode_addr_indirect_disp16
153 jra fp_putdest
154
155fp_extmode0:
156 fp_mode_addr_indirect_extmode0
157 jra fp_putdest
158
159fp_extmode1:
160 fp_decode_addr_reg
161 jmp ([0f:w,%pc,%d0*4])
162
163 .align 4
1640:
165 .long fp_abs_short, fp_abs_long
166 .long fp_ill, fp_ill
167 .long fp_ill, fp_ill
168 .long fp_ill, fp_ill
169
170fp_abs_short:
171 fp_mode_abs_short
172 jra fp_putdest
173
174fp_abs_long:
175 fp_mode_abs_long
176 jra fp_putdest
177
178fp_putdest:
179 move.l %a0,%a1
180 fp_decode_src_reg
181 move.l %d1,%d2 | save size
182 fp_get_fp_reg
183 printf PDECODE,"\n"
184 addq.l #8,%a0
185 move.l (%a0),-(%sp)
186 move.l -(%a0),-(%sp)
187 move.l -(%a0),-(%sp)
188 move.l %sp,%a0
189 jsr fp_normalize_ext
190
191 swap %d2
192 jmp ([0f:w,%pc,%d2.w*4])
193
194 .align 4
1950:
196 .long fp_format_long, fp_format_single
197 .long fp_format_extended, fp_format_packed
198 .long fp_format_word, fp_format_double
199 .long fp_format_byte, fp_format_packed
200
201fp_format_long:
202 jsr fp_conv_ext2long
203 putuser.l %d0,(%a1),fp_err_ua1,%a1
204 jra fp_finish_move
205
206fp_format_single:
207 jsr fp_conv_ext2single
208 putuser.l %d0,(%a1),fp_err_ua1,%a1
209 jra fp_finish_move
210
211fp_format_extended:
212 move.l (%a0)+,%d0
213 lsl.w #1,%d0
214 lsl.l #7,%d0
215 lsl.l #8,%d0
216 putuser.l %d0,(%a1)+,fp_err_ua1,%a1
217 move.l (%a0)+,%d0
218 putuser.l %d0,(%a1)+,fp_err_ua1,%a1
219 move.l (%a0),%d0
220 putuser.l %d0,(%a1),fp_err_ua1,%a1
221 jra fp_finish_move
222
223fp_format_packed:
224 /* not supported yet */
225 lea (12,%sp),%sp
226 jra fp_ill
227
228fp_format_word:
229 jsr fp_conv_ext2short
230 putuser.w %d0,(%a1),fp_err_ua1,%a1
231 jra fp_finish_move
232
233fp_format_double:
234 jsr fp_conv_ext2double
235 jra fp_finish_move
236
237fp_format_byte:
238 jsr fp_conv_ext2byte
239 putuser.b %d0,(%a1),fp_err_ua1,%a1
240| jra fp_finish_move
241
242fp_finish_move:
243 lea (12,%sp),%sp
244 jra fp_final
diff --git a/arch/m68k/math-emu/fp_movem.S b/arch/m68k/math-emu/fp_movem.S
new file mode 100644
index 000000000000..8354d39e6c47
--- /dev/null
+++ b/arch/m68k/math-emu/fp_movem.S
@@ -0,0 +1,368 @@
1/*
2 * fp_movem.S
3 *
4 * Copyright Roman Zippel, 1997. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, and the entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions. (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "fp_emu.h"
39#include "fp_decode.h"
40
41| set flags for decode macros for fmovem
42do_fmovem=1
43
44 .globl fp_fmovem_fp, fp_fmovem_cr
45
46| %d1 contains the mask and count of the register list
47| for other register usage see fp_decode.h
48
49fp_fmovem_fp:
50 printf PDECODE,"fmovem.x "
51 | get register list and count them
52 btst #11,%d2
53 jne 1f
54 bfextu %d2{#24,#8},%d0 | static register list
55 jra 2f
561: bfextu %d2{#25,#3},%d0 | dynamic register list
57 jsr fp_get_data_reg
582: move.l %d0,%d1
59 swap %d1
60 jra 2f
611: addq.w #1,%d1 | count the # of registers in
622: lsr.b #1,%d0 | register list and keep it in %d1
63 jcs 1b
64 jne 2b
65 printf PDECODE,"#%08x",1,%d1
66#ifdef FPU_EMU_DEBUG
67 btst #12,%d2
68 jne 1f
69 printf PDECODE,"-" | decremental move
70 jra 2f
711: printf PDECODE,"+" | incremental move
722: btst #13,%d2
73 jeq 1f
74 printf PDECODE,"->" | fpu -> cpu
75 jra 2f
761: printf PDECODE,"<-" | fpu <- cpu
772:
78#endif
79
80 | decode address mode
81 fp_decode_addr_mode
82
83 .long fp_ill, fp_ill
84 .long fpr_indirect, fpr_postinc
85 .long fpr_predecr, fpr_disp16
86 .long fpr_extmode0, fpr_extmode1
87
88 | addressing mode: address register indirect
89fpr_indirect:
90 fp_mode_addr_indirect
91 jra fpr_do_movem
92
93 | addressing mode: address register indirect with postincrement
94fpr_postinc:
95 fp_mode_addr_indirect_postinc
96 jra fpr_do_movem
97
98fpr_predecr:
99 fp_mode_addr_indirect_predec
100 jra fpr_do_movem
101
102 | addressing mode: address register/programm counter indirect
103 | with 16bit displacement
104fpr_disp16:
105 fp_mode_addr_indirect_disp16
106 jra fpr_do_movem
107
108fpr_extmode0:
109 fp_mode_addr_indirect_extmode0
110 jra fpr_do_movem
111
112fpr_extmode1:
113 fp_decode_addr_reg
114 jmp ([0f:w,%pc,%d0*4])
115
116 .align 4
1170:
118 .long fpr_absolute_short, fpr_absolute_long
119 .long fpr_disp16, fpr_extmode0
120 .long fp_ill, fp_ill
121 .long fp_ill, fp_ill
122
123fpr_absolute_short:
124 fp_mode_abs_short
125 jra fpr_do_movem
126
127fpr_absolute_long:
128 fp_mode_abs_long
129| jra fpr_do_movem
130
131fpr_do_movem:
132 swap %d1 | get fpu register list
133 lea (FPD_FPREG,FPDATA),%a1
134 moveq #12,%d0
135 btst #12,%d2
136 jne 1f
137 lea (-12,%a1,%d0*8),%a1
138 neg.l %d0
1391: btst #13,%d2
140 jne 4f
141 | move register from memory into fpu
142 jra 3f
1431: printf PMOVEM,"(%p>%p)",2,%a0,%a1
144 getuser.l (%a0)+,%d2,fp_err_ua1,%a0
145 lsr.l #8,%d2
146 lsr.l #7,%d2
147 lsr.w #1,%d2
148 move.l %d2,(%a1)+
149 getuser.l (%a0)+,%d2,fp_err_ua1,%a0
150 move.l %d2,(%a1)+
151 getuser.l (%a0),%d2,fp_err_ua1,%a0
152 move.l %d2,(%a1)
153 subq.l #8,%a0
154 subq.l #8,%a1
155 add.l %d0,%a0
1562: add.l %d0,%a1
1573: lsl.b #1,%d1
158 jcs 1b
159 jne 2b
160 jra 5f
161 | move register from fpu into memory
1621: printf PMOVEM,"(%p>%p)",2,%a1,%a0
163 move.l (%a1)+,%d2
164 lsl.w #1,%d2
165 lsl.l #7,%d2
166 lsl.l #8,%d2
167 putuser.l %d2,(%a0)+,fp_err_ua1,%a0
168 move.l (%a1)+,%d2
169 putuser.l %d2,(%a0)+,fp_err_ua1,%a0
170 move.l (%a1),%d2
171 putuser.l %d2,(%a0),fp_err_ua1,%a0
172 subq.l #8,%a1
173 subq.l #8,%a0
174 add.l %d0,%a0
1752: add.l %d0,%a1
1764: lsl.b #1,%d1
177 jcs 1b
178 jne 2b
1795:
180 printf PDECODE,"\n"
181#if 0
182 lea (FPD_FPREG,FPDATA),%a0
183 printf PMOVEM,"fp:"
184 printx PMOVEM,%a0@(0)
185 printx PMOVEM,%a0@(12)
186 printf PMOVEM,"\n "
187 printx PMOVEM,%a0@(24)
188 printx PMOVEM,%a0@(36)
189 printf PMOVEM,"\n "
190 printx PMOVEM,%a0@(48)
191 printx PMOVEM,%a0@(60)
192 printf PMOVEM,"\n "
193 printx PMOVEM,%a0@(72)
194 printx PMOVEM,%a0@(84)
195 printf PMOVEM,"\n"
196#endif
197 jra fp_end
198
199| set flags for decode macros for fmovem control register
200do_fmovem=1
201do_fmovem_cr=1
202
203fp_fmovem_cr:
204 printf PDECODE,"fmovem.cr "
205 | get register list and count them
206 bfextu %d2{#19,#3},%d0
207 move.l %d0,%d1
208 swap %d1
209 jra 2f
2101: addq.w #1,%d1
2112: lsr.l #1,%d0
212 jcs 1b
213 jne 2b
214 printf PDECODE,"#%08x",1,%d1
215#ifdef FPU_EMU_DEBUG
216 btst #13,%d2
217 jeq 1f
218 printf PDECODE,"->" | fpu -> cpu
219 jra 2f
2201: printf PDECODE,"<-" | fpu <- cpu
2212:
222#endif
223
224 | decode address mode
225 fp_decode_addr_mode
226
227 .long fpc_data, fpc_addr
228 .long fpc_indirect, fpc_postinc
229 .long fpc_predecr, fpc_disp16
230 .long fpc_extmode0, fpc_extmode1
231
232fpc_data:
233 fp_mode_data_direct
234 move.w %d0,%d1
235 bfffo %d2{#19,#3},%d0
236 sub.w #19,%d0
237 lea (FPD_FPCR,FPDATA,%d0.w*4),%a1
238 btst #13,%d2
239 jne 1f
240 move.w %d1,%d0
241 jsr fp_get_data_reg
242 move.l %d0,(%a1)
243 jra fpc_movem_fin
2441: move.l (%a1),%d0
245 jsr fp_put_data_reg
246 jra fpc_movem_fin
247
248fpc_addr:
249 fp_decode_addr_reg
250 printf PDECODE,"a%d",1,%d0
251 btst #13,%d2
252 jne 1f
253 jsr fp_get_addr_reg
254 move.l %a0,(FPD_FPIAR,FPDATA)
255 jra fpc_movem_fin
2561: move.l (FPD_FPIAR,FPDATA),%a0
257 jsr fp_put_addr_reg
258 jra fpc_movem_fin
259
260fpc_indirect:
261 fp_mode_addr_indirect
262 jra fpc_do_movem
263
264fpc_postinc:
265 fp_mode_addr_indirect_postinc
266 jra fpc_do_movem
267
268fpc_predecr:
269 fp_mode_addr_indirect_predec
270 jra fpc_do_movem
271
272fpc_disp16:
273 fp_mode_addr_indirect_disp16
274 jra fpc_do_movem
275
276fpc_extmode0:
277 fp_mode_addr_indirect_extmode0
278 jra fpc_do_movem
279
280fpc_extmode1:
281 fp_decode_addr_reg
282 jmp ([0f:w,%pc,%d0*4])
283
284 .align 4
2850:
286 .long fpc_absolute_short, fpc_absolute_long
287 .long fpc_disp16, fpc_extmode0
288 .long fpc_immediate, fp_ill
289 .long fp_ill, fp_ill
290
291fpc_absolute_short:
292 fp_mode_abs_short
293 jra fpc_do_movem
294
295fpc_absolute_long:
296 fp_mode_abs_long
297 jra fpc_do_movem
298
299fpc_immediate:
300 fp_get_pc %a0
301 lea (%a0,%d1.w*4),%a1
302 fp_put_pc %a1
303 printf PDECODE,"#imm"
304| jra fpc_do_movem
305#if 0
306 swap %d1
307 lsl.l #5,%d1
308 lea (FPD_FPCR,FPDATA),%a0
309 jra 3f
3101: move.l %d0,(%a0)
3112: addq.l #4,%a0
3123: lsl.b #1,%d1
313 jcs 1b
314 jne 2b
315 jra fpc_movem_fin
316#endif
317
318fpc_do_movem:
319 swap %d1 | get fpu register list
320 lsl.l #5,%d1
321 lea (FPD_FPCR,FPDATA),%a1
3221: btst #13,%d2
323 jne 4f
324
325 | move register from memory into fpu
326 jra 3f
3271: printf PMOVEM,"(%p>%p)",2,%a0,%a1
328 getuser.l (%a0)+,%d0,fp_err_ua1,%a0
329 move.l %d0,(%a1)
3302: addq.l #4,%a1
3313: lsl.b #1,%d1
332 jcs 1b
333 jne 2b
334 jra fpc_movem_fin
335
336 | move register from fpu into memory
3371: printf PMOVEM,"(%p>%p)",2,%a1,%a0
338 move.l (%a1),%d0
339 putuser.l %d0,(%a0)+,fp_err_ua1,%a0
3402: addq.l #4,%a1
3414: lsl.b #1,%d1
342 jcs 1b
343 jne 2b
344
345fpc_movem_fin:
346 and.l #0x0000fff0,(FPD_FPCR,FPDATA)
347 and.l #0x0ffffff8,(FPD_FPSR,FPDATA)
348 move.l (FPD_FPCR,FPDATA),%d0
349 lsr.l #4,%d0
350 moveq #3,%d1
351 and.l %d0,%d1
352 move.w %d1,(FPD_RND,FPDATA)
353 lsr.l #2,%d0
354 moveq #3,%d1
355 and.l %d0,%d1
356 move.w %d1,(FPD_PREC,FPDATA)
357 printf PDECODE,"\n"
358#if 0
359 printf PMOVEM,"fpcr : %08x\n",1,FPDATA@(FPD_FPCR)
360 printf PMOVEM,"fpsr : %08x\n",1,FPDATA@(FPD_FPSR)
361 printf PMOVEM,"fpiar: %08x\n",1,FPDATA@(FPD_FPIAR)
362 clr.l %d0
363 move.w (FPD_PREC,FPDATA),%d0
364 printf PMOVEM,"prec : %04x\n",1,%d0
365 move.w (FPD_RND,FPDATA),%d0
366 printf PMOVEM,"rnd : %04x\n",1,%d0
367#endif
368 jra fp_end
diff --git a/arch/m68k/math-emu/fp_scan.S b/arch/m68k/math-emu/fp_scan.S
new file mode 100644
index 000000000000..e4146ed574db
--- /dev/null
+++ b/arch/m68k/math-emu/fp_scan.S
@@ -0,0 +1,478 @@
1/*
2 * fp_scan.S
3 *
4 * Copyright Roman Zippel, 1997. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, and the entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions. (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "fp_emu.h"
39#include "fp_decode.h"
40
41 .globl fp_scan, fp_datasize
42
43 .data
44
45| %d2 - first two instr words
46| %d1 - operand size
47
48/* operand formats are:
49
50 Long = 0, i.e. fmove.l
51 Single, i.e. fmove.s
52 Extended, i.e. fmove.x
53 Packed-BCD, i.e. fmove.p
54 Word, i.e. fmove.w
55 Double, i.e. fmove.d
56*/
57
58 .text
59
60| On entry:
61| FPDATA - base of emulated FPU registers
62
63fp_scan:
64| normal fpu instruction? (this excludes fsave/frestore)
65 fp_get_pc %a0
66 printf PDECODE,"%08x: ",1,%a0
67 getuser.b (%a0),%d0,fp_err_ua1,%a0
68#if 1
69 cmp.b #0xf2,%d0 | cpid = 1
70#else
71 cmp.b #0xfc,%d0 | cpid = 6
72#endif
73 jne fp_nonstd
74| first two instruction words are kept in %d2
75 getuser.l (%a0)+,%d2,fp_err_ua1,%a0
76 fp_put_pc %a0
77fp_decode_cond: | separate conditional instr
78 fp_decode_cond_instr_type
79
80 .long fp_decode_move, fp_fscc
81 .long fp_fbccw, fp_fbccl
82
83fp_decode_move: | separate move instr
84 fp_decode_move_instr_type
85
86 .long fp_fgen_fp, fp_ill
87 .long fp_fgen_ea, fp_fmove_fp2mem
88 .long fp_fmovem_cr, fp_fmovem_cr
89 .long fp_fmovem_fp, fp_fmovem_fp
90
91| now all arithmetic instr and a few move instr are left
92fp_fgen_fp: | source is a fpu register
93 clr.b (FPD_FPSR+2,FPDATA) | clear the exception byte
94 fp_decode_sourcespec
95 printf PDECODE,"f<op>.x fp%d",1,%d0
96 fp_get_fp_reg
97 lea (FPD_TEMPFP1,FPDATA),%a1 | copy src into a temp location
98 move.l (%a0)+,(%a1)+
99 move.l (%a0)+,(%a1)+
100 move.l (%a0),(%a1)
101 lea (-8,%a1),%a0
102 jra fp_getdest
103
104fp_fgen_ea: | source is <ea>
105 clr.b (FPD_FPSR+2,FPDATA) | clear the exception byte
106 | sort out fmovecr, keep data size in %d1
107 fp_decode_sourcespec
108 cmp.w #7,%d0
109 jeq fp_fmovecr
110 move.w %d0,%d1 | store data size twice in %d1
111 swap %d1 | one can be trashed below
112 move.w %d0,%d1
113#ifdef FPU_EMU_DEBUG
114 lea 0f,%a0
115 clr.l %d0
116 move.b (%a0,%d1.w),%d0
117 printf PDECODE,"f<op>.%c ",1,%d0
118
119 .data
1200: .byte 'l','s','x','p','w','d','b',0
121 .previous
122#endif
123
124/*
125 fp_getsource, fp_getdest
126
127 basically, we end up with a pointer to the source operand in
128 %a1, and a pointer to the destination operand in %a0. both
129 are, of course, 96-bit extended floating point numbers.
130*/
131
132fp_getsource:
133 | decode addressing mode for source
134 fp_decode_addr_mode
135
136 .long fp_data, fp_ill
137 .long fp_indirect, fp_postinc
138 .long fp_predecr, fp_disp16
139 .long fp_extmode0, fp_extmode1
140
141 | addressing mode: data register direct
142fp_data:
143 fp_mode_data_direct
144 jsr fp_get_data_reg
145 lea (FPD_TEMPFP1,FPDATA),%a0
146 jmp ([0f:w,%pc,%d1.w*4])
147
148 .align 4
1490:
150 .long fp_data_long, fp_data_single
151 .long fp_ill, fp_ill
152 .long fp_data_word, fp_ill
153 .long fp_data_byte, fp_ill
154
155 | data types that fit in an integer data register
156fp_data_byte:
157 extb.l %d0
158 jra fp_data_long
159
160fp_data_word:
161 ext.l %d0
162
163fp_data_long:
164 jsr fp_conv_long2ext
165 jra fp_getdest
166
167fp_data_single:
168 jsr fp_conv_single2ext
169 jra fp_getdest
170
171 | addressing mode: address register indirect
172fp_indirect:
173 fp_mode_addr_indirect
174 jra fp_fetchsource
175
176 | addressing mode: address register indirect with postincrement
177fp_postinc:
178 fp_mode_addr_indirect_postinc
179 jra fp_fetchsource
180
181 | addressing mode: address register indirect with predecrement
182fp_predecr:
183 fp_mode_addr_indirect_predec
184 jra fp_fetchsource
185
186 | addressing mode: address register/programm counter indirect
187 | with 16bit displacement
188fp_disp16:
189 fp_mode_addr_indirect_disp16
190 jra fp_fetchsource
191
192 | all other indirect addressing modes will finally end up here
193fp_extmode0:
194 fp_mode_addr_indirect_extmode0
195 jra fp_fetchsource
196
197| all pc relative addressing modes and immediate/absolute modes end up here
198| the first ones are sent to fp_extmode0 or fp_disp16
199| and only the latter are handled here
200fp_extmode1:
201 fp_decode_addr_reg
202 jmp ([0f:w,%pc,%d0*4])
203
204 .align 4
2050:
206 .long fp_abs_short, fp_abs_long
207 .long fp_disp16, fp_extmode0
208 .long fp_immediate, fp_ill
209 .long fp_ill, fp_ill
210
211 | addressing mode: absolute short
212fp_abs_short:
213 fp_mode_abs_short
214 jra fp_fetchsource
215
216 | addressing mode: absolute long
217fp_abs_long:
218 fp_mode_abs_long
219 jra fp_fetchsource
220
221 | addressing mode: immediate data
222fp_immediate:
223 printf PDECODE,"#"
224 fp_get_pc %a0
225 move.w (fp_datasize,%d1.w*2),%d0
226 addq.w #1,%d0
227 and.w #-2,%d0
228#ifdef FPU_EMU_DEBUG
229 movem.l %d0/%d1,-(%sp)
230 movel %a0,%a1
231 clr.l %d1
232 jra 2f
2331: getuser.b (%a1)+,%d1,fp_err_ua1,%a1
234 printf PDECODE,"%02x",1,%d1
2352: dbra %d0,1b
236 movem.l (%sp)+,%d0/%d1
237#endif
238 lea (%a0,%d0.w),%a1
239 fp_put_pc %a1
240| jra fp_fetchsource
241
242fp_fetchsource:
243 move.l %a0,%a1
244 swap %d1
245 lea (FPD_TEMPFP1,FPDATA),%a0
246 jmp ([0f:w,%pc,%d1.w*4])
247
248 .align 4
2490: .long fp_long, fp_single
250 .long fp_ext, fp_pack
251 .long fp_word, fp_double
252 .long fp_byte, fp_ill
253
254fp_long:
255 getuser.l (%a1),%d0,fp_err_ua1,%a1
256 jsr fp_conv_long2ext
257 jra fp_getdest
258
259fp_single:
260 getuser.l (%a1),%d0,fp_err_ua1,%a1
261 jsr fp_conv_single2ext
262 jra fp_getdest
263
264fp_ext:
265 getuser.l (%a1)+,%d0,fp_err_ua1,%a1
266 lsr.l #8,%d0
267 lsr.l #7,%d0
268 lsr.w #1,%d0
269 move.l %d0,(%a0)+
270 getuser.l (%a1)+,%d0,fp_err_ua1,%a1
271 move.l %d0,(%a0)+
272 getuser.l (%a1),%d0,fp_err_ua1,%a1
273 move.l %d0,(%a0)
274 subq.l #8,%a0
275 jra fp_getdest
276
277fp_pack:
278 /* not supported yet */
279 jra fp_ill
280
281fp_word:
282 getuser.w (%a1),%d0,fp_err_ua1,%a1
283 ext.l %d0
284 jsr fp_conv_long2ext
285 jra fp_getdest
286
287fp_double:
288 jsr fp_conv_double2ext
289 jra fp_getdest
290
291fp_byte:
292 getuser.b (%a1),%d0,fp_err_ua1,%a1
293 extb.l %d0
294 jsr fp_conv_long2ext
295| jra fp_getdest
296
297fp_getdest:
298 move.l %a0,%a1
299 bfextu %d2{#22,#3},%d0
300 printf PDECODE,",fp%d\n",1,%d0
301 fp_get_fp_reg
302 movem.l %a0/%a1,-(%sp)
303 pea fp_finalrounding
304 bfextu %d2{#25,#7},%d0
305 jmp ([0f:w,%pc,%d0*4])
306
307 .align 4
3080:
309 .long fp_fmove_mem2fp, fp_fint, fp_fsinh, fp_fintrz
310 .long fp_fsqrt, fp_ill, fp_flognp1, fp_ill
311 .long fp_fetoxm1, fp_ftanh, fp_fatan, fp_ill
312 .long fp_fasin, fp_fatanh, fp_fsin, fp_ftan
313 .long fp_fetox, fp_ftwotox, fp_ftentox, fp_ill
314 .long fp_flogn, fp_flog10, fp_flog2, fp_ill
315 .long fp_fabs, fp_fcosh, fp_fneg, fp_ill
316 .long fp_facos, fp_fcos, fp_fgetexp, fp_fgetman
317 .long fp_fdiv, fp_fmod, fp_fadd, fp_fmul
318 .long fpa_fsgldiv, fp_frem, fp_fscale, fpa_fsglmul
319 .long fp_fsub, fp_ill, fp_ill, fp_ill
320 .long fp_ill, fp_ill, fp_ill, fp_ill
321 .long fp_fsincos0, fp_fsincos1, fp_fsincos2, fp_fsincos3
322 .long fp_fsincos4, fp_fsincos5, fp_fsincos6, fp_fsincos7
323 .long fp_fcmp, fp_ill, fp_ftst, fp_ill
324 .long fp_ill, fp_ill, fp_ill, fp_ill
325 .long fp_fsmove, fp_fssqrt, fp_ill, fp_ill
326 .long fp_fdmove, fp_fdsqrt, fp_ill, fp_ill
327 .long fp_ill, fp_ill, fp_ill, fp_ill
328 .long fp_ill, fp_ill, fp_ill, fp_ill
329 .long fp_ill, fp_ill, fp_ill, fp_ill
330 .long fp_ill, fp_ill, fp_ill, fp_ill
331 .long fp_fsabs, fp_ill, fp_fsneg, fp_ill
332 .long fp_fdabs, fp_ill, fp_fdneg, fp_ill
333 .long fp_fsdiv, fp_ill, fp_fsadd, fp_fsmul
334 .long fp_fddiv, fp_ill, fp_fdadd, fp_fdmul
335 .long fp_fssub, fp_ill, fp_ill, fp_ill
336 .long fp_fdsub, fp_ill, fp_ill, fp_ill
337 .long fp_ill, fp_ill, fp_ill, fp_ill
338 .long fp_ill, fp_ill, fp_ill, fp_ill
339 .long fp_ill, fp_ill, fp_ill, fp_ill
340 .long fp_ill, fp_ill, fp_ill, fp_ill
341
342 | Instructions follow
343
344 | Move an (emulated) ROM constant
345fp_fmovecr:
346 bfextu %d2{#27,#5},%d0
347 printf PINSTR,"fp_fmovecr #%d",1,%d0
348 move.l %d0,%d1
349 add.l %d0,%d0
350 add.l %d1,%d0
351 lea (fp_constants,%d0*4),%a0
352 move.l #0x801cc0ff,%d0
353 addq.l #1,%d1
354 lsl.l %d1,%d0
355 jcc 1f
356 fp_set_sr FPSR_EXC_INEX2 | INEX2 exception
3571: moveq #-128,%d0 | continue with fmove
358 and.l %d0,%d2
359 jra fp_getdest
360
361 .data
362 .align 4
363fp_constants:
364 .long 0x00004000,0xc90fdaa2,0x2168c235 | pi
365 .extend 0,0,0,0,0,0,0,0,0,0
366 .long 0x00003ffd,0x9a209a84,0xfbcff798 | log10(2)
367 .long 0x00004000,0xadf85458,0xa2bb4a9a | e
368 .long 0x00003fff,0xb8aa3b29,0x5c17f0bc | log2(e)
369 .long 0x00003ffd,0xde5bd8a9,0x37287195 | log10(e)
370 .long 0x00000000,0x00000000,0x00000000 | 0.0
371 .long 0x00003ffe,0xb17217f7,0xd1cf79ac | 1n(2)
372 .long 0x00004000,0x935d8ddd,0xaaa8ac17 | 1n(10)
373 | read this as "1.0 * 2^0" - note the high bit in the mantissa
374 .long 0x00003fff,0x80000000,0x00000000 | 10^0
375 .long 0x00004002,0xa0000000,0x00000000 | 10^1
376 .long 0x00004005,0xc8000000,0x00000000 | 10^2
377 .long 0x0000400c,0x9c400000,0x00000000 | 10^4
378 .long 0x00004019,0xbebc2000,0x00000000 | 10^8
379 .long 0x00004034,0x8e1bc9bf,0x04000000 | 10^16
380 .long 0x00004069,0x9dc5ada8,0x2b70b59e | 10^32
381 .long 0x000040d3,0xc2781f49,0xffcfa6d5 | 10^64
382 .long 0x000041a8,0x93ba47c9,0x80e98ce0 | 10^128
383 .long 0x00004351,0xaa7eebfb,0x9df9de8e | 10^256
384 .long 0x000046a3,0xe319a0ae,0xa60e91c7 | 10^512
385 .long 0x00004d48,0xc9767586,0x81750c17 | 10^1024
386 .long 0x00005a92,0x9e8b3b5d,0xc53d5de5 | 10^2048
387 .long 0x00007525,0xc4605202,0x8a20979b | 10^4096
388 .previous
389
390fp_fmove_mem2fp:
391 printf PINSTR,"fmove %p,%p\n",2,%a0,%a1
392 move.l (%a1)+,(%a0)+
393 move.l (%a1)+,(%a0)+
394 move.l (%a1),(%a0)
395 subq.l #8,%a0
396 rts
397
398fpa_fsglmul:
399 move.l #fp_finalrounding_single_fast,(%sp)
400 jra fp_fsglmul
401
402fpa_fsgldiv:
403 move.l #fp_finalrounding_single_fast,(%sp)
404 jra fp_fsgldiv
405
406.macro fp_dosingleprec instr
407 printf PINSTR,"single "
408 move.l #fp_finalrounding_single,(%sp)
409 jra \instr
410.endm
411
412.macro fp_dodoubleprec instr
413 printf PINSTR,"double "
414 move.l #fp_finalrounding_double,(%sp)
415 jra \instr
416.endm
417
418fp_fsmove:
419 fp_dosingleprec fp_fmove_mem2fp
420
421fp_fssqrt:
422 fp_dosingleprec fp_fsqrt
423
424fp_fdmove:
425 fp_dodoubleprec fp_fmove_mem2fp
426
427fp_fdsqrt:
428 fp_dodoubleprec fp_fsqrt
429
430fp_fsabs:
431 fp_dosingleprec fp_fabs
432
433fp_fsneg:
434 fp_dosingleprec fp_fneg
435
436fp_fdabs:
437 fp_dodoubleprec fp_fabs
438
439fp_fdneg:
440 fp_dodoubleprec fp_fneg
441
442fp_fsdiv:
443 fp_dosingleprec fp_fdiv
444
445fp_fsadd:
446 fp_dosingleprec fp_fadd
447
448fp_fsmul:
449 fp_dosingleprec fp_fmul
450
451fp_fddiv:
452 fp_dodoubleprec fp_fdiv
453
454fp_fdadd:
455 fp_dodoubleprec fp_fadd
456
457fp_fdmul:
458 fp_dodoubleprec fp_fmul
459
460fp_fssub:
461 fp_dosingleprec fp_fsub
462
463fp_fdsub:
464 fp_dodoubleprec fp_fsub
465
466fp_nonstd:
467 fp_get_pc %a0
468 getuser.l (%a0),%d0,fp_err_ua1,%a0
469 printf ,"nonstd ((%08x)=%08x)\n",2,%a0,%d0
470 moveq #-1,%d0
471 rts
472
473 .data
474 .align 4
475
476 | data sizes corresponding to the operand formats
477fp_datasize:
478 .word 4, 4, 12, 12, 2, 8, 1, 0
diff --git a/arch/m68k/math-emu/fp_trig.c b/arch/m68k/math-emu/fp_trig.c
new file mode 100644
index 000000000000..6361d0784df2
--- /dev/null
+++ b/arch/m68k/math-emu/fp_trig.c
@@ -0,0 +1,183 @@
1/*
2
3 fp_trig.c: floating-point math routines for the Linux-m68k
4 floating point emulator.
5
6 Copyright (c) 1998-1999 David Huggins-Daines / Roman Zippel.
7
8 I hereby give permission, free of charge, to copy, modify, and
9 redistribute this software, in source or binary form, provided that
10 the above copyright notice and the following disclaimer are included
11 in all such copies.
12
13 THIS SOFTWARE IS PROVIDED "AS IS", WITH ABSOLUTELY NO WARRANTY, REAL
14 OR IMPLIED.
15
16*/
17
18#include "fp_emu.h"
19#include "fp_trig.h"
20
21struct fp_ext *
22fp_fsin(struct fp_ext *dest, struct fp_ext *src)
23{
24 uprint("fsin\n");
25
26 fp_monadic_check(dest, src);
27
28 return dest;
29}
30
31struct fp_ext *
32fp_fcos(struct fp_ext *dest, struct fp_ext *src)
33{
34 uprint("fcos\n");
35
36 fp_monadic_check(dest, src);
37
38 return dest;
39}
40
41struct fp_ext *
42fp_ftan(struct fp_ext *dest, struct fp_ext *src)
43{
44 uprint("ftan\n");
45
46 fp_monadic_check(dest, src);
47
48 return dest;
49}
50
51struct fp_ext *
52fp_fasin(struct fp_ext *dest, struct fp_ext *src)
53{
54 uprint("fasin\n");
55
56 fp_monadic_check(dest, src);
57
58 return dest;
59}
60
61struct fp_ext *
62fp_facos(struct fp_ext *dest, struct fp_ext *src)
63{
64 uprint("facos\n");
65
66 fp_monadic_check(dest, src);
67
68 return dest;
69}
70
71struct fp_ext *
72fp_fatan(struct fp_ext *dest, struct fp_ext *src)
73{
74 uprint("fatan\n");
75
76 fp_monadic_check(dest, src);
77
78 return dest;
79}
80
81struct fp_ext *
82fp_fsinh(struct fp_ext *dest, struct fp_ext *src)
83{
84 uprint("fsinh\n");
85
86 fp_monadic_check(dest, src);
87
88 return dest;
89}
90
91struct fp_ext *
92fp_fcosh(struct fp_ext *dest, struct fp_ext *src)
93{
94 uprint("fcosh\n");
95
96 fp_monadic_check(dest, src);
97
98 return dest;
99}
100
101struct fp_ext *
102fp_ftanh(struct fp_ext *dest, struct fp_ext *src)
103{
104 uprint("ftanh\n");
105
106 fp_monadic_check(dest, src);
107
108 return dest;
109}
110
111struct fp_ext *
112fp_fatanh(struct fp_ext *dest, struct fp_ext *src)
113{
114 uprint("fatanh\n");
115
116 fp_monadic_check(dest, src);
117
118 return dest;
119}
120
121struct fp_ext *
122fp_fsincos0(struct fp_ext *dest, struct fp_ext *src)
123{
124 uprint("fsincos0\n");
125
126 return dest;
127}
128
129struct fp_ext *
130fp_fsincos1(struct fp_ext *dest, struct fp_ext *src)
131{
132 uprint("fsincos1\n");
133
134 return dest;
135}
136
137struct fp_ext *
138fp_fsincos2(struct fp_ext *dest, struct fp_ext *src)
139{
140 uprint("fsincos2\n");
141
142 return dest;
143}
144
145struct fp_ext *
146fp_fsincos3(struct fp_ext *dest, struct fp_ext *src)
147{
148 uprint("fsincos3\n");
149
150 return dest;
151}
152
153struct fp_ext *
154fp_fsincos4(struct fp_ext *dest, struct fp_ext *src)
155{
156 uprint("fsincos4\n");
157
158 return dest;
159}
160
161struct fp_ext *
162fp_fsincos5(struct fp_ext *dest, struct fp_ext *src)
163{
164 uprint("fsincos5\n");
165
166 return dest;
167}
168
169struct fp_ext *
170fp_fsincos6(struct fp_ext *dest, struct fp_ext *src)
171{
172 uprint("fsincos6\n");
173
174 return dest;
175}
176
177struct fp_ext *
178fp_fsincos7(struct fp_ext *dest, struct fp_ext *src)
179{
180 uprint("fsincos7\n");
181
182 return dest;
183}
diff --git a/arch/m68k/math-emu/fp_trig.h b/arch/m68k/math-emu/fp_trig.h
new file mode 100644
index 000000000000..af8b247e9c98
--- /dev/null
+++ b/arch/m68k/math-emu/fp_trig.h
@@ -0,0 +1,32 @@
1/*
2
3 fp_trig.h: floating-point math routines for the Linux-m68k
4 floating point emulator.
5
6 Copyright (c) 1998 David Huggins-Daines.
7
8 I hereby give permission, free of charge, to copy, modify, and
9 redistribute this software, in source or binary form, provided that
10 the above copyright notice and the following disclaimer are included
11 in all such copies.
12
13 THIS SOFTWARE IS PROVIDED "AS IS", WITH ABSOLUTELY NO WARRANTY, REAL
14 OR IMPLIED.
15
16*/
17
18#ifndef FP_TRIG_H
19#define FP_TRIG_H
20
21#include "fp_emu.h"
22
23/* floating point trigonometric instructions:
24
25 the arguments to these are in the "internal" extended format, that
26 is, an "exploded" version of the 96-bit extended fp format used by
27 the 68881.
28
29 they return a status code, which should end up in %d0, if all goes
30 well. */
31
32#endif /* FP_TRIG__H */
diff --git a/arch/m68k/math-emu/fp_util.S b/arch/m68k/math-emu/fp_util.S
new file mode 100644
index 000000000000..a9f7f0129067
--- /dev/null
+++ b/arch/m68k/math-emu/fp_util.S
@@ -0,0 +1,1455 @@
1/*
2 * fp_util.S
3 *
4 * Copyright Roman Zippel, 1997. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, and the entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions. (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <linux/config.h>
39#include "fp_emu.h"
40
41/*
42 * Here are lots of conversion and normalization functions mainly
43 * used by fp_scan.S
44 * Note that these functions are optimized for "normal" numbers,
45 * these are handled first and exit as fast as possible, this is
46 * especially important for fp_normalize_ext/fp_conv_ext2ext, as
47 * it's called very often.
48 * The register usage is optimized for fp_scan.S and which register
49 * is currently at that time unused, be careful if you want change
50 * something here. %d0 and %d1 is always usable, sometimes %d2 (or
51 * only the lower half) most function have to return the %a0
52 * unmodified, so that the caller can immediately reuse it.
53 */
54
55 .globl fp_ill, fp_end
56
57 | exits from fp_scan:
58 | illegal instruction
59fp_ill:
60 printf ,"fp_illegal\n"
61 rts
62 | completed instruction
63fp_end:
64 tst.l (TASK_MM-8,%a2)
65 jmi 1f
66 tst.l (TASK_MM-4,%a2)
67 jmi 1f
68 tst.l (TASK_MM,%a2)
69 jpl 2f
701: printf ,"oops:%p,%p,%p\n",3,%a2@(TASK_MM-8),%a2@(TASK_MM-4),%a2@(TASK_MM)
712: clr.l %d0
72 rts
73
74 .globl fp_conv_long2ext, fp_conv_single2ext
75 .globl fp_conv_double2ext, fp_conv_ext2ext
76 .globl fp_normalize_ext, fp_normalize_double
77 .globl fp_normalize_single, fp_normalize_single_fast
78 .globl fp_conv_ext2double, fp_conv_ext2single
79 .globl fp_conv_ext2long, fp_conv_ext2short
80 .globl fp_conv_ext2byte
81 .globl fp_finalrounding_single, fp_finalrounding_single_fast
82 .globl fp_finalrounding_double
83 .globl fp_finalrounding, fp_finaltest, fp_final
84
85/*
86 * First several conversion functions from a source operand
87 * into the extended format. Note, that only fp_conv_ext2ext
88 * normalizes the number and is always called after the other
89 * conversion functions, which only move the information into
90 * fp_ext structure.
91 */
92
93 | fp_conv_long2ext:
94 |
95 | args: %d0 = source (32-bit long)
96 | %a0 = destination (ptr to struct fp_ext)
97
98fp_conv_long2ext:
99 printf PCONV,"l2e: %p -> %p(",2,%d0,%a0
100 clr.l %d1 | sign defaults to zero
101 tst.l %d0
102 jeq fp_l2e_zero | is source zero?
103 jpl 1f | positive?
104 moveq #1,%d1
105 neg.l %d0
1061: swap %d1
107 move.w #0x3fff+31,%d1
108 move.l %d1,(%a0)+ | set sign / exp
109 move.l %d0,(%a0)+ | set mantissa
110 clr.l (%a0)
111 subq.l #8,%a0 | restore %a0
112 printx PCONV,%a0@
113 printf PCONV,")\n"
114 rts
115 | source is zero
116fp_l2e_zero:
117 clr.l (%a0)+
118 clr.l (%a0)+
119 clr.l (%a0)
120 subq.l #8,%a0
121 printx PCONV,%a0@
122 printf PCONV,")\n"
123 rts
124
125 | fp_conv_single2ext
126 | args: %d0 = source (single-precision fp value)
127 | %a0 = dest (struct fp_ext *)
128
129fp_conv_single2ext:
130 printf PCONV,"s2e: %p -> %p(",2,%d0,%a0
131 move.l %d0,%d1
132 lsl.l #8,%d0 | shift mantissa
133 lsr.l #8,%d1 | exponent / sign
134 lsr.l #7,%d1
135 lsr.w #8,%d1
136 jeq fp_s2e_small | zero / denormal?
137 cmp.w #0xff,%d1 | NaN / Inf?
138 jeq fp_s2e_large
139 bset #31,%d0 | set explizit bit
140 add.w #0x3fff-0x7f,%d1 | re-bias the exponent.
1419: move.l %d1,(%a0)+ | fp_ext.sign, fp_ext.exp
142 move.l %d0,(%a0)+ | high lword of fp_ext.mant
143 clr.l (%a0) | low lword = 0
144 subq.l #8,%a0
145 printx PCONV,%a0@
146 printf PCONV,")\n"
147 rts
148 | zeros and denormalized
149fp_s2e_small:
150 | exponent is zero, so explizit bit is already zero too
151 tst.l %d0
152 jeq 9b
153 move.w #0x4000-0x7f,%d1
154 jra 9b
155 | infinities and NAN
156fp_s2e_large:
157 bclr #31,%d0 | clear explizit bit
158 move.w #0x7fff,%d1
159 jra 9b
160
161fp_conv_double2ext:
162#ifdef FPU_EMU_DEBUG
163 getuser.l %a1@(0),%d0,fp_err_ua2,%a1
164 getuser.l %a1@(4),%d1,fp_err_ua2,%a1
165 printf PCONV,"d2e: %p%p -> %p(",3,%d0,%d1,%a0
166#endif
167 getuser.l (%a1)+,%d0,fp_err_ua2,%a1
168 move.l %d0,%d1
169 lsl.l #8,%d0 | shift high mantissa
170 lsl.l #3,%d0
171 lsr.l #8,%d1 | exponent / sign
172 lsr.l #7,%d1
173 lsr.w #5,%d1
174 jeq fp_d2e_small | zero / denormal?
175 cmp.w #0x7ff,%d1 | NaN / Inf?
176 jeq fp_d2e_large
177 bset #31,%d0 | set explizit bit
178 add.w #0x3fff-0x3ff,%d1 | re-bias the exponent.
1799: move.l %d1,(%a0)+ | fp_ext.sign, fp_ext.exp
180 move.l %d0,(%a0)+
181 getuser.l (%a1)+,%d0,fp_err_ua2,%a1
182 move.l %d0,%d1
183 lsl.l #8,%d0
184 lsl.l #3,%d0
185 move.l %d0,(%a0)
186 moveq #21,%d0
187 lsr.l %d0,%d1
188 or.l %d1,-(%a0)
189 subq.l #4,%a0
190 printx PCONV,%a0@
191 printf PCONV,")\n"
192 rts
193 | zeros and denormalized
194fp_d2e_small:
195 | exponent is zero, so explizit bit is already zero too
196 tst.l %d0
197 jeq 9b
198 move.w #0x4000-0x3ff,%d1
199 jra 9b
200 | infinities and NAN
201fp_d2e_large:
202 bclr #31,%d0 | clear explizit bit
203 move.w #0x7fff,%d1
204 jra 9b
205
206 | fp_conv_ext2ext:
207 | originally used to get longdouble from userspace, now it's
208 | called before arithmetic operations to make sure the number
209 | is normalized [maybe rename it?].
210 | args: %a0 = dest (struct fp_ext *)
211 | returns 0 in %d0 for a NaN, otherwise 1
212
213fp_conv_ext2ext:
214 printf PCONV,"e2e: %p(",1,%a0
215 printx PCONV,%a0@
216 printf PCONV,"), "
217 move.l (%a0)+,%d0
218 cmp.w #0x7fff,%d0 | Inf / NaN?
219 jeq fp_e2e_large
220 move.l (%a0),%d0
221 jpl fp_e2e_small | zero / denorm?
222 | The high bit is set, so normalization is irrelevant.
223fp_e2e_checkround:
224 subq.l #4,%a0
225#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
226 move.b (%a0),%d0
227 jne fp_e2e_round
228#endif
229 printf PCONV,"%p(",1,%a0
230 printx PCONV,%a0@
231 printf PCONV,")\n"
232 moveq #1,%d0
233 rts
234#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
235fp_e2e_round:
236 fp_set_sr FPSR_EXC_INEX2
237 clr.b (%a0)
238 move.w (FPD_RND,FPDATA),%d2
239 jne fp_e2e_roundother | %d2 == 0, round to nearest
240 tst.b %d0 | test guard bit
241 jpl 9f | zero is closer
242 btst #0,(11,%a0) | test lsb bit
243 jne fp_e2e_doroundup | round to infinity
244 lsl.b #1,%d0 | check low bits
245 jeq 9f | round to zero
246fp_e2e_doroundup:
247 addq.l #1,(8,%a0)
248 jcc 9f
249 addq.l #1,(4,%a0)
250 jcc 9f
251 move.w #0x8000,(4,%a0)
252 addq.w #1,(2,%a0)
2539: printf PNORM,"%p(",1,%a0
254 printx PNORM,%a0@
255 printf PNORM,")\n"
256 rts
257fp_e2e_roundother:
258 subq.w #2,%d2
259 jcs 9b | %d2 < 2, round to zero
260 jhi 1f | %d2 > 2, round to +infinity
261 tst.b (1,%a0) | to -inf
262 jne fp_e2e_doroundup | negative, round to infinity
263 jra 9b | positive, round to zero
2641: tst.b (1,%a0) | to +inf
265 jeq fp_e2e_doroundup | positive, round to infinity
266 jra 9b | negative, round to zero
267#endif
268 | zeros and subnormals:
269 | try to normalize these anyway.
270fp_e2e_small:
271 jne fp_e2e_small1 | high lword zero?
272 move.l (4,%a0),%d0
273 jne fp_e2e_small2
274#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
275 clr.l %d0
276 move.b (-4,%a0),%d0
277 jne fp_e2e_small3
278#endif
279 | Genuine zero.
280 clr.w -(%a0)
281 subq.l #2,%a0
282 printf PNORM,"%p(",1,%a0
283 printx PNORM,%a0@
284 printf PNORM,")\n"
285 moveq #1,%d0
286 rts
287 | definitely subnormal, need to shift all 64 bits
288fp_e2e_small1:
289 bfffo %d0{#0,#32},%d1
290 move.w -(%a0),%d2
291 sub.w %d1,%d2
292 jcc 1f
293 | Pathologically small, denormalize.
294 add.w %d2,%d1
295 clr.w %d2
2961: move.w %d2,(%a0)+
297 move.w %d1,%d2
298 jeq fp_e2e_checkround
299 | fancy 64-bit double-shift begins here
300 lsl.l %d2,%d0
301 move.l %d0,(%a0)+
302 move.l (%a0),%d0
303 move.l %d0,%d1
304 lsl.l %d2,%d0
305 move.l %d0,(%a0)
306 neg.w %d2
307 and.w #0x1f,%d2
308 lsr.l %d2,%d1
309 or.l %d1,-(%a0)
310#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
311fp_e2e_extra1:
312 clr.l %d0
313 move.b (-4,%a0),%d0
314 neg.w %d2
315 add.w #24,%d2
316 jcc 1f
317 clr.b (-4,%a0)
318 lsl.l %d2,%d0
319 or.l %d0,(4,%a0)
320 jra fp_e2e_checkround
3211: addq.w #8,%d2
322 lsl.l %d2,%d0
323 move.b %d0,(-4,%a0)
324 lsr.l #8,%d0
325 or.l %d0,(4,%a0)
326#endif
327 jra fp_e2e_checkround
328 | pathologically small subnormal
329fp_e2e_small2:
330 bfffo %d0{#0,#32},%d1
331 add.w #32,%d1
332 move.w -(%a0),%d2
333 sub.w %d1,%d2
334 jcc 1f
335 | Beyond pathologically small, denormalize.
336 add.w %d2,%d1
337 clr.w %d2
3381: move.w %d2,(%a0)+
339 ext.l %d1
340 jeq fp_e2e_checkround
341 clr.l (4,%a0)
342 sub.w #32,%d2
343 jcs 1f
344 lsl.l %d1,%d0 | lower lword needs only to be shifted
345 move.l %d0,(%a0) | into the higher lword
346#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
347 clr.l %d0
348 move.b (-4,%a0),%d0
349 clr.b (-4,%a0)
350 neg.w %d1
351 add.w #32,%d1
352 bfins %d0,(%a0){%d1,#8}
353#endif
354 jra fp_e2e_checkround
3551: neg.w %d1 | lower lword is splitted between
356 bfins %d0,(%a0){%d1,#32} | higher and lower lword
357#ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
358 jra fp_e2e_checkround
359#else
360 move.w %d1,%d2
361 jra fp_e2e_extra1
362 | These are extremely small numbers, that will mostly end up as zero
363 | anyway, so this is only important for correct rounding.
364fp_e2e_small3:
365 bfffo %d0{#24,#8},%d1
366 add.w #40,%d1
367 move.w -(%a0),%d2
368 sub.w %d1,%d2
369 jcc 1f
370 | Pathologically small, denormalize.
371 add.w %d2,%d1
372 clr.w %d2
3731: move.w %d2,(%a0)+
374 ext.l %d1
375 jeq fp_e2e_checkround
376 cmp.w #8,%d1
377 jcs 2f
3781: clr.b (-4,%a0)
379 sub.w #64,%d1
380 jcs 1f
381 add.w #24,%d1
382 lsl.l %d1,%d0
383 move.l %d0,(%a0)
384 jra fp_e2e_checkround
3851: neg.w %d1
386 bfins %d0,(%a0){%d1,#8}
387 jra fp_e2e_checkround
3882: lsl.l %d1,%d0
389 move.b %d0,(-4,%a0)
390 lsr.l #8,%d0
391 move.b %d0,(7,%a0)
392 jra fp_e2e_checkround
393#endif
3941: move.l %d0,%d1 | lower lword is splitted between
395 lsl.l %d2,%d0 | higher and lower lword
396 move.l %d0,(%a0)
397 move.l %d1,%d0
398 neg.w %d2
399 add.w #32,%d2
400 lsr.l %d2,%d0
401 move.l %d0,-(%a0)
402 jra fp_e2e_checkround
403 | Infinities and NaNs
404fp_e2e_large:
405 move.l (%a0)+,%d0
406 jne 3f
4071: tst.l (%a0)
408 jne 4f
409 moveq #1,%d0
4102: subq.l #8,%a0
411 printf PCONV,"%p(",1,%a0
412 printx PCONV,%a0@
413 printf PCONV,")\n"
414 rts
415 | we have maybe a NaN, shift off the highest bit
4163: lsl.l #1,%d0
417 jeq 1b
418 | we have a NaN, clear the return value
4194: clrl %d0
420 jra 2b
421
422
423/*
424 * Normalization functions. Call these on the output of general
425 * FP operators, and before any conversion into the destination
426 * formats. fp_normalize_ext has always to be called first, the
427 * following conversion functions expect an already normalized
428 * number.
429 */
430
431 | fp_normalize_ext:
432 | normalize an extended in extended (unpacked) format, basically
433 | it does the same as fp_conv_ext2ext, additionally it also does
434 | the necessary postprocessing checks.
435 | args: %a0 (struct fp_ext *)
436 | NOTE: it does _not_ modify %a0/%a1 and the upper word of %d2
437
438fp_normalize_ext:
439 printf PNORM,"ne: %p(",1,%a0
440 printx PNORM,%a0@
441 printf PNORM,"), "
442 move.l (%a0)+,%d0
443 cmp.w #0x7fff,%d0 | Inf / NaN?
444 jeq fp_ne_large
445 move.l (%a0),%d0
446 jpl fp_ne_small | zero / denorm?
447 | The high bit is set, so normalization is irrelevant.
448fp_ne_checkround:
449 subq.l #4,%a0
450#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
451 move.b (%a0),%d0
452 jne fp_ne_round
453#endif
454 printf PNORM,"%p(",1,%a0
455 printx PNORM,%a0@
456 printf PNORM,")\n"
457 rts
458#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
459fp_ne_round:
460 fp_set_sr FPSR_EXC_INEX2
461 clr.b (%a0)
462 move.w (FPD_RND,FPDATA),%d2
463 jne fp_ne_roundother | %d2 == 0, round to nearest
464 tst.b %d0 | test guard bit
465 jpl 9f | zero is closer
466 btst #0,(11,%a0) | test lsb bit
467 jne fp_ne_doroundup | round to infinity
468 lsl.b #1,%d0 | check low bits
469 jeq 9f | round to zero
470fp_ne_doroundup:
471 addq.l #1,(8,%a0)
472 jcc 9f
473 addq.l #1,(4,%a0)
474 jcc 9f
475 addq.w #1,(2,%a0)
476 move.w #0x8000,(4,%a0)
4779: printf PNORM,"%p(",1,%a0
478 printx PNORM,%a0@
479 printf PNORM,")\n"
480 rts
481fp_ne_roundother:
482 subq.w #2,%d2
483 jcs 9b | %d2 < 2, round to zero
484 jhi 1f | %d2 > 2, round to +infinity
485 tst.b (1,%a0) | to -inf
486 jne fp_ne_doroundup | negative, round to infinity
487 jra 9b | positive, round to zero
4881: tst.b (1,%a0) | to +inf
489 jeq fp_ne_doroundup | positive, round to infinity
490 jra 9b | negative, round to zero
491#endif
492 | Zeros and subnormal numbers
493 | These are probably merely subnormal, rather than "denormalized"
494 | numbers, so we will try to make them normal again.
495fp_ne_small:
496 jne fp_ne_small1 | high lword zero?
497 move.l (4,%a0),%d0
498 jne fp_ne_small2
499#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
500 clr.l %d0
501 move.b (-4,%a0),%d0
502 jne fp_ne_small3
503#endif
504 | Genuine zero.
505 clr.w -(%a0)
506 subq.l #2,%a0
507 printf PNORM,"%p(",1,%a0
508 printx PNORM,%a0@
509 printf PNORM,")\n"
510 rts
511 | Subnormal.
512fp_ne_small1:
513 bfffo %d0{#0,#32},%d1
514 move.w -(%a0),%d2
515 sub.w %d1,%d2
516 jcc 1f
517 | Pathologically small, denormalize.
518 add.w %d2,%d1
519 clr.w %d2
520 fp_set_sr FPSR_EXC_UNFL
5211: move.w %d2,(%a0)+
522 move.w %d1,%d2
523 jeq fp_ne_checkround
524 | This is exactly the same 64-bit double shift as seen above.
525 lsl.l %d2,%d0
526 move.l %d0,(%a0)+
527 move.l (%a0),%d0
528 move.l %d0,%d1
529 lsl.l %d2,%d0
530 move.l %d0,(%a0)
531 neg.w %d2
532 and.w #0x1f,%d2
533 lsr.l %d2,%d1
534 or.l %d1,-(%a0)
535#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
536fp_ne_extra1:
537 clr.l %d0
538 move.b (-4,%a0),%d0
539 neg.w %d2
540 add.w #24,%d2
541 jcc 1f
542 clr.b (-4,%a0)
543 lsl.l %d2,%d0
544 or.l %d0,(4,%a0)
545 jra fp_ne_checkround
5461: addq.w #8,%d2
547 lsl.l %d2,%d0
548 move.b %d0,(-4,%a0)
549 lsr.l #8,%d0
550 or.l %d0,(4,%a0)
551#endif
552 jra fp_ne_checkround
553 | May or may not be subnormal, if so, only 32 bits to shift.
554fp_ne_small2:
555 bfffo %d0{#0,#32},%d1
556 add.w #32,%d1
557 move.w -(%a0),%d2
558 sub.w %d1,%d2
559 jcc 1f
560 | Beyond pathologically small, denormalize.
561 add.w %d2,%d1
562 clr.w %d2
563 fp_set_sr FPSR_EXC_UNFL
5641: move.w %d2,(%a0)+
565 ext.l %d1
566 jeq fp_ne_checkround
567 clr.l (4,%a0)
568 sub.w #32,%d1
569 jcs 1f
570 lsl.l %d1,%d0 | lower lword needs only to be shifted
571 move.l %d0,(%a0) | into the higher lword
572#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
573 clr.l %d0
574 move.b (-4,%a0),%d0
575 clr.b (-4,%a0)
576 neg.w %d1
577 add.w #32,%d1
578 bfins %d0,(%a0){%d1,#8}
579#endif
580 jra fp_ne_checkround
5811: neg.w %d1 | lower lword is splitted between
582 bfins %d0,(%a0){%d1,#32} | higher and lower lword
583#ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
584 jra fp_ne_checkround
585#else
586 move.w %d1,%d2
587 jra fp_ne_extra1
588 | These are extremely small numbers, that will mostly end up as zero
589 | anyway, so this is only important for correct rounding.
590fp_ne_small3:
591 bfffo %d0{#24,#8},%d1
592 add.w #40,%d1
593 move.w -(%a0),%d2
594 sub.w %d1,%d2
595 jcc 1f
596 | Pathologically small, denormalize.
597 add.w %d2,%d1
598 clr.w %d2
5991: move.w %d2,(%a0)+
600 ext.l %d1
601 jeq fp_ne_checkround
602 cmp.w #8,%d1
603 jcs 2f
6041: clr.b (-4,%a0)
605 sub.w #64,%d1
606 jcs 1f
607 add.w #24,%d1
608 lsl.l %d1,%d0
609 move.l %d0,(%a0)
610 jra fp_ne_checkround
6111: neg.w %d1
612 bfins %d0,(%a0){%d1,#8}
613 jra fp_ne_checkround
6142: lsl.l %d1,%d0
615 move.b %d0,(-4,%a0)
616 lsr.l #8,%d0
617 move.b %d0,(7,%a0)
618 jra fp_ne_checkround
619#endif
620 | Infinities and NaNs, again, same as above.
621fp_ne_large:
622 move.l (%a0)+,%d0
623 jne 3f
6241: tst.l (%a0)
625 jne 4f
6262: subq.l #8,%a0
627 printf PNORM,"%p(",1,%a0
628 printx PNORM,%a0@
629 printf PNORM,")\n"
630 rts
631 | we have maybe a NaN, shift off the highest bit
6323: move.l %d0,%d1
633 lsl.l #1,%d1
634 jne 4f
635 clr.l (-4,%a0)
636 jra 1b
637 | we have a NaN, test if it is signaling
6384: bset #30,%d0
639 jne 2b
640 fp_set_sr FPSR_EXC_SNAN
641 move.l %d0,(-4,%a0)
642 jra 2b
643
644 | these next two do rounding as per the IEEE standard.
645 | values for the rounding modes appear to be:
646 | 0: Round to nearest
647 | 1: Round to zero
648 | 2: Round to -Infinity
649 | 3: Round to +Infinity
650 | both functions expect that fp_normalize was already
651 | called (and extended argument is already normalized
652 | as far as possible), these are used if there is different
653 | rounding precision is selected and before converting
654 | into single/double
655
656 | fp_normalize_double:
657 | normalize an extended with double (52-bit) precision
658 | args: %a0 (struct fp_ext *)
659
660fp_normalize_double:
661 printf PNORM,"nd: %p(",1,%a0
662 printx PNORM,%a0@
663 printf PNORM,"), "
664 move.l (%a0)+,%d2
665 tst.w %d2
666 jeq fp_nd_zero | zero / denormalized
667 cmp.w #0x7fff,%d2
668 jeq fp_nd_huge | NaN / infinitive.
669 sub.w #0x4000-0x3ff,%d2 | will the exponent fit?
670 jcs fp_nd_small | too small.
671 cmp.w #0x7fe,%d2
672 jcc fp_nd_large | too big.
673 addq.l #4,%a0
674 move.l (%a0),%d0 | low lword of mantissa
675 | now, round off the low 11 bits.
676fp_nd_round:
677 moveq #21,%d1
678 lsl.l %d1,%d0 | keep 11 low bits.
679 jne fp_nd_checkround | Are they non-zero?
680 | nothing to do here
6819: subq.l #8,%a0
682 printf PNORM,"%p(",1,%a0
683 printx PNORM,%a0@
684 printf PNORM,")\n"
685 rts
686 | Be careful with the X bit! It contains the lsb
687 | from the shift above, it is needed for round to nearest.
688fp_nd_checkround:
689 fp_set_sr FPSR_EXC_INEX2 | INEX2 bit
690 and.w #0xf800,(2,%a0) | clear bits 0-10
691 move.w (FPD_RND,FPDATA),%d2 | rounding mode
692 jne 2f | %d2 == 0, round to nearest
693 tst.l %d0 | test guard bit
694 jpl 9b | zero is closer
695 | here we test the X bit by adding it to %d2
696 clr.w %d2 | first set z bit, addx only clears it
697 addx.w %d2,%d2 | test lsb bit
698 | IEEE754-specified "round to even" behaviour. If the guard
699 | bit is set, then the number is odd, so rounding works like
700 | in grade-school arithmetic (i.e. 1.5 rounds to 2.0)
701 | Otherwise, an equal distance rounds towards zero, so as not
702 | to produce an odd number. This is strange, but it is what
703 | the standard says.
704 jne fp_nd_doroundup | round to infinity
705 lsl.l #1,%d0 | check low bits
706 jeq 9b | round to zero
707fp_nd_doroundup:
708 | round (the mantissa, that is) towards infinity
709 add.l #0x800,(%a0)
710 jcc 9b | no overflow, good.
711 addq.l #1,-(%a0) | extend to high lword
712 jcc 1f | no overflow, good.
713 | Yow! we have managed to overflow the mantissa. Since this
714 | only happens when %d1 was 0xfffff800, it is now zero, so
715 | reset the high bit, and increment the exponent.
716 move.w #0x8000,(%a0)
717 addq.w #1,-(%a0)
718 cmp.w #0x43ff,(%a0)+ | exponent now overflown?
719 jeq fp_nd_large | yes, so make it infinity.
7201: subq.l #4,%a0
721 printf PNORM,"%p(",1,%a0
722 printx PNORM,%a0@
723 printf PNORM,")\n"
724 rts
7252: subq.w #2,%d2
726 jcs 9b | %d2 < 2, round to zero
727 jhi 3f | %d2 > 2, round to +infinity
728 | Round to +Inf or -Inf. High word of %d2 contains the
729 | sign of the number, by the way.
730 swap %d2 | to -inf
731 tst.b %d2
732 jne fp_nd_doroundup | negative, round to infinity
733 jra 9b | positive, round to zero
7343: swap %d2 | to +inf
735 tst.b %d2
736 jeq fp_nd_doroundup | positive, round to infinity
737 jra 9b | negative, round to zero
738 | Exponent underflow. Try to make a denormal, and set it to
739 | the smallest possible fraction if this fails.
740fp_nd_small:
741 fp_set_sr FPSR_EXC_UNFL | set UNFL bit
742 move.w #0x3c01,(-2,%a0) | 2**-1022
743 neg.w %d2 | degree of underflow
744 cmp.w #32,%d2 | single or double shift?
745 jcc 1f
746 | Again, another 64-bit double shift.
747 move.l (%a0),%d0
748 move.l %d0,%d1
749 lsr.l %d2,%d0
750 move.l %d0,(%a0)+
751 move.l (%a0),%d0
752 lsr.l %d2,%d0
753 neg.w %d2
754 add.w #32,%d2
755 lsl.l %d2,%d1
756 or.l %d1,%d0
757 move.l (%a0),%d1
758 move.l %d0,(%a0)
759 | Check to see if we shifted off any significant bits
760 lsl.l %d2,%d1
761 jeq fp_nd_round | Nope, round.
762 bset #0,%d0 | Yes, so set the "sticky bit".
763 jra fp_nd_round | Now, round.
764 | Another 64-bit single shift and store
7651: sub.w #32,%d2
766 cmp.w #32,%d2 | Do we really need to shift?
767 jcc 2f | No, the number is too small.
768 move.l (%a0),%d0
769 clr.l (%a0)+
770 move.l %d0,%d1
771 lsr.l %d2,%d0
772 neg.w %d2
773 add.w #32,%d2
774 | Again, check to see if we shifted off any significant bits.
775 tst.l (%a0)
776 jeq 1f
777 bset #0,%d0 | Sticky bit.
7781: move.l %d0,(%a0)
779 lsl.l %d2,%d1
780 jeq fp_nd_round
781 bset #0,%d0
782 jra fp_nd_round
783 | Sorry, the number is just too small.
7842: clr.l (%a0)+
785 clr.l (%a0)
786 moveq #1,%d0 | Smallest possible fraction,
787 jra fp_nd_round | round as desired.
788 | zero and denormalized
789fp_nd_zero:
790 tst.l (%a0)+
791 jne 1f
792 tst.l (%a0)
793 jne 1f
794 subq.l #8,%a0
795 printf PNORM,"%p(",1,%a0
796 printx PNORM,%a0@
797 printf PNORM,")\n"
798 rts | zero. nothing to do.
799 | These are not merely subnormal numbers, but true denormals,
800 | i.e. pathologically small (exponent is 2**-16383) numbers.
801 | It is clearly impossible for even a normal extended number
802 | with that exponent to fit into double precision, so just
803 | write these ones off as "too darn small".
8041: fp_set_sr FPSR_EXC_UNFL | Set UNFL bit
805 clr.l (%a0)
806 clr.l -(%a0)
807 move.w #0x3c01,-(%a0) | i.e. 2**-1022
808 addq.l #6,%a0
809 moveq #1,%d0
810 jra fp_nd_round | round.
811 | Exponent overflow. Just call it infinity.
812fp_nd_large:
813 move.w #0x7ff,%d0
814 and.w (6,%a0),%d0
815 jeq 1f
816 fp_set_sr FPSR_EXC_INEX2
8171: fp_set_sr FPSR_EXC_OVFL
818 move.w (FPD_RND,FPDATA),%d2
819 jne 3f | %d2 = 0 round to nearest
8201: move.w #0x7fff,(-2,%a0)
821 clr.l (%a0)+
822 clr.l (%a0)
8232: subq.l #8,%a0
824 printf PNORM,"%p(",1,%a0
825 printx PNORM,%a0@
826 printf PNORM,")\n"
827 rts
8283: subq.w #2,%d2
829 jcs 5f | %d2 < 2, round to zero
830 jhi 4f | %d2 > 2, round to +infinity
831 tst.b (-3,%a0) | to -inf
832 jne 1b
833 jra 5f
8344: tst.b (-3,%a0) | to +inf
835 jeq 1b
8365: move.w #0x43fe,(-2,%a0)
837 moveq #-1,%d0
838 move.l %d0,(%a0)+
839 move.w #0xf800,%d0
840 move.l %d0,(%a0)
841 jra 2b
842 | Infinities or NaNs
843fp_nd_huge:
844 subq.l #4,%a0
845 printf PNORM,"%p(",1,%a0
846 printx PNORM,%a0@
847 printf PNORM,")\n"
848 rts
849
850 | fp_normalize_single:
851 | normalize an extended with single (23-bit) precision
852 | args: %a0 (struct fp_ext *)
853
854fp_normalize_single:
855 printf PNORM,"ns: %p(",1,%a0
856 printx PNORM,%a0@
857 printf PNORM,") "
858 addq.l #2,%a0
859 move.w (%a0)+,%d2
860 jeq fp_ns_zero | zero / denormalized
861 cmp.w #0x7fff,%d2
862 jeq fp_ns_huge | NaN / infinitive.
863 sub.w #0x4000-0x7f,%d2 | will the exponent fit?
864 jcs fp_ns_small | too small.
865 cmp.w #0xfe,%d2
866 jcc fp_ns_large | too big.
867 move.l (%a0)+,%d0 | get high lword of mantissa
868fp_ns_round:
869 tst.l (%a0) | check the low lword
870 jeq 1f
871 | Set a sticky bit if it is non-zero. This should only
872 | affect the rounding in what would otherwise be equal-
873 | distance situations, which is what we want it to do.
874 bset #0,%d0
8751: clr.l (%a0) | zap it from memory.
876 | now, round off the low 8 bits of the hi lword.
877 tst.b %d0 | 8 low bits.
878 jne fp_ns_checkround | Are they non-zero?
879 | nothing to do here
880 subq.l #8,%a0
881 printf PNORM,"%p(",1,%a0
882 printx PNORM,%a0@
883 printf PNORM,")\n"
884 rts
885fp_ns_checkround:
886 fp_set_sr FPSR_EXC_INEX2 | INEX2 bit
887 clr.b -(%a0) | clear low byte of high lword
888 subq.l #3,%a0
889 move.w (FPD_RND,FPDATA),%d2 | rounding mode
890 jne 2f | %d2 == 0, round to nearest
891 tst.b %d0 | test guard bit
892 jpl 9f | zero is closer
893 btst #8,%d0 | test lsb bit
894 | round to even behaviour, see above.
895 jne fp_ns_doroundup | round to infinity
896 lsl.b #1,%d0 | check low bits
897 jeq 9f | round to zero
898fp_ns_doroundup:
899 | round (the mantissa, that is) towards infinity
900 add.l #0x100,(%a0)
901 jcc 9f | no overflow, good.
902 | Overflow. This means that the %d1 was 0xffffff00, so it
903 | is now zero. We will set the mantissa to reflect this, and
904 | increment the exponent (checking for overflow there too)
905 move.w #0x8000,(%a0)
906 addq.w #1,-(%a0)
907 cmp.w #0x407f,(%a0)+ | exponent now overflown?
908 jeq fp_ns_large | yes, so make it infinity.
9099: subq.l #4,%a0
910 printf PNORM,"%p(",1,%a0
911 printx PNORM,%a0@
912 printf PNORM,")\n"
913 rts
914 | check nondefault rounding modes
9152: subq.w #2,%d2
916 jcs 9b | %d2 < 2, round to zero
917 jhi 3f | %d2 > 2, round to +infinity
918 tst.b (-3,%a0) | to -inf
919 jne fp_ns_doroundup | negative, round to infinity
920 jra 9b | positive, round to zero
9213: tst.b (-3,%a0) | to +inf
922 jeq fp_ns_doroundup | positive, round to infinity
923 jra 9b | negative, round to zero
924 | Exponent underflow. Try to make a denormal, and set it to
925 | the smallest possible fraction if this fails.
926fp_ns_small:
927 fp_set_sr FPSR_EXC_UNFL | set UNFL bit
928 move.w #0x3f81,(-2,%a0) | 2**-126
929 neg.w %d2 | degree of underflow
930 cmp.w #32,%d2 | single or double shift?
931 jcc 2f
932 | a 32-bit shift.
933 move.l (%a0),%d0
934 move.l %d0,%d1
935 lsr.l %d2,%d0
936 move.l %d0,(%a0)+
937 | Check to see if we shifted off any significant bits.
938 neg.w %d2
939 add.w #32,%d2
940 lsl.l %d2,%d1
941 jeq 1f
942 bset #0,%d0 | Sticky bit.
943 | Check the lower lword
9441: tst.l (%a0)
945 jeq fp_ns_round
946 clr (%a0)
947 bset #0,%d0 | Sticky bit.
948 jra fp_ns_round
949 | Sorry, the number is just too small.
9502: clr.l (%a0)+
951 clr.l (%a0)
952 moveq #1,%d0 | Smallest possible fraction,
953 jra fp_ns_round | round as desired.
954 | Exponent overflow. Just call it infinity.
955fp_ns_large:
956 tst.b (3,%a0)
957 jeq 1f
958 fp_set_sr FPSR_EXC_INEX2
9591: fp_set_sr FPSR_EXC_OVFL
960 move.w (FPD_RND,FPDATA),%d2
961 jne 3f | %d2 = 0 round to nearest
9621: move.w #0x7fff,(-2,%a0)
963 clr.l (%a0)+
964 clr.l (%a0)
9652: subq.l #8,%a0
966 printf PNORM,"%p(",1,%a0
967 printx PNORM,%a0@
968 printf PNORM,")\n"
969 rts
9703: subq.w #2,%d2
971 jcs 5f | %d2 < 2, round to zero
972 jhi 4f | %d2 > 2, round to +infinity
973 tst.b (-3,%a0) | to -inf
974 jne 1b
975 jra 5f
9764: tst.b (-3,%a0) | to +inf
977 jeq 1b
9785: move.w #0x407e,(-2,%a0)
979 move.l #0xffffff00,(%a0)+
980 clr.l (%a0)
981 jra 2b
982 | zero and denormalized
983fp_ns_zero:
984 tst.l (%a0)+
985 jne 1f
986 tst.l (%a0)
987 jne 1f
988 subq.l #8,%a0
989 printf PNORM,"%p(",1,%a0
990 printx PNORM,%a0@
991 printf PNORM,")\n"
992 rts | zero. nothing to do.
993 | These are not merely subnormal numbers, but true denormals,
994 | i.e. pathologically small (exponent is 2**-16383) numbers.
995 | It is clearly impossible for even a normal extended number
996 | with that exponent to fit into single precision, so just
997 | write these ones off as "too darn small".
9981: fp_set_sr FPSR_EXC_UNFL | Set UNFL bit
999 clr.l (%a0)
1000 clr.l -(%a0)
1001 move.w #0x3f81,-(%a0) | i.e. 2**-126
1002 addq.l #6,%a0
1003 moveq #1,%d0
1004 jra fp_ns_round | round.
1005 | Infinities or NaNs
1006fp_ns_huge:
1007 subq.l #4,%a0
1008 printf PNORM,"%p(",1,%a0
1009 printx PNORM,%a0@
1010 printf PNORM,")\n"
1011 rts
1012
1013 | fp_normalize_single_fast:
1014 | normalize an extended with single (23-bit) precision
1015 | this is only used by fsgldiv/fsgdlmul, where the
1016 | operand is not completly normalized.
1017 | args: %a0 (struct fp_ext *)
1018
1019fp_normalize_single_fast:
1020 printf PNORM,"nsf: %p(",1,%a0
1021 printx PNORM,%a0@
1022 printf PNORM,") "
1023 addq.l #2,%a0
1024 move.w (%a0)+,%d2
1025 cmp.w #0x7fff,%d2
1026 jeq fp_nsf_huge | NaN / infinitive.
1027 move.l (%a0)+,%d0 | get high lword of mantissa
1028fp_nsf_round:
1029 tst.l (%a0) | check the low lword
1030 jeq 1f
1031 | Set a sticky bit if it is non-zero. This should only
1032 | affect the rounding in what would otherwise be equal-
1033 | distance situations, which is what we want it to do.
1034 bset #0,%d0
10351: clr.l (%a0) | zap it from memory.
1036 | now, round off the low 8 bits of the hi lword.
1037 tst.b %d0 | 8 low bits.
1038 jne fp_nsf_checkround | Are they non-zero?
1039 | nothing to do here
1040 subq.l #8,%a0
1041 printf PNORM,"%p(",1,%a0
1042 printx PNORM,%a0@
1043 printf PNORM,")\n"
1044 rts
1045fp_nsf_checkround:
1046 fp_set_sr FPSR_EXC_INEX2 | INEX2 bit
1047 clr.b -(%a0) | clear low byte of high lword
1048 subq.l #3,%a0
1049 move.w (FPD_RND,FPDATA),%d2 | rounding mode
1050 jne 2f | %d2 == 0, round to nearest
1051 tst.b %d0 | test guard bit
1052 jpl 9f | zero is closer
1053 btst #8,%d0 | test lsb bit
1054 | round to even behaviour, see above.
1055 jne fp_nsf_doroundup | round to infinity
1056 lsl.b #1,%d0 | check low bits
1057 jeq 9f | round to zero
1058fp_nsf_doroundup:
1059 | round (the mantissa, that is) towards infinity
1060 add.l #0x100,(%a0)
1061 jcc 9f | no overflow, good.
1062 | Overflow. This means that the %d1 was 0xffffff00, so it
1063 | is now zero. We will set the mantissa to reflect this, and
1064 | increment the exponent (checking for overflow there too)
1065 move.w #0x8000,(%a0)
1066 addq.w #1,-(%a0)
1067 cmp.w #0x407f,(%a0)+ | exponent now overflown?
1068 jeq fp_nsf_large | yes, so make it infinity.
10699: subq.l #4,%a0
1070 printf PNORM,"%p(",1,%a0
1071 printx PNORM,%a0@
1072 printf PNORM,")\n"
1073 rts
1074 | check nondefault rounding modes
10752: subq.w #2,%d2
1076 jcs 9b | %d2 < 2, round to zero
1077 jhi 3f | %d2 > 2, round to +infinity
1078 tst.b (-3,%a0) | to -inf
1079 jne fp_nsf_doroundup | negative, round to infinity
1080 jra 9b | positive, round to zero
10813: tst.b (-3,%a0) | to +inf
1082 jeq fp_nsf_doroundup | positive, round to infinity
1083 jra 9b | negative, round to zero
1084 | Exponent overflow. Just call it infinity.
1085fp_nsf_large:
1086 tst.b (3,%a0)
1087 jeq 1f
1088 fp_set_sr FPSR_EXC_INEX2
10891: fp_set_sr FPSR_EXC_OVFL
1090 move.w (FPD_RND,FPDATA),%d2
1091 jne 3f | %d2 = 0 round to nearest
10921: move.w #0x7fff,(-2,%a0)
1093 clr.l (%a0)+
1094 clr.l (%a0)
10952: subq.l #8,%a0
1096 printf PNORM,"%p(",1,%a0
1097 printx PNORM,%a0@
1098 printf PNORM,")\n"
1099 rts
11003: subq.w #2,%d2
1101 jcs 5f | %d2 < 2, round to zero
1102 jhi 4f | %d2 > 2, round to +infinity
1103 tst.b (-3,%a0) | to -inf
1104 jne 1b
1105 jra 5f
11064: tst.b (-3,%a0) | to +inf
1107 jeq 1b
11085: move.w #0x407e,(-2,%a0)
1109 move.l #0xffffff00,(%a0)+
1110 clr.l (%a0)
1111 jra 2b
1112 | Infinities or NaNs
1113fp_nsf_huge:
1114 subq.l #4,%a0
1115 printf PNORM,"%p(",1,%a0
1116 printx PNORM,%a0@
1117 printf PNORM,")\n"
1118 rts
1119
1120 | conv_ext2int (macro):
1121 | Generates a subroutine that converts an extended value to an
1122 | integer of a given size, again, with the appropriate type of
1123 | rounding.
1124
1125 | Macro arguments:
1126 | s: size, as given in an assembly instruction.
1127 | b: number of bits in that size.
1128
1129 | Subroutine arguments:
1130 | %a0: source (struct fp_ext *)
1131
1132 | Returns the integer in %d0 (like it should)
1133
1134.macro conv_ext2int s,b
1135 .set inf,(1<<(\b-1))-1 | i.e. MAXINT
1136 printf PCONV,"e2i%d: %p(",2,#\b,%a0
1137 printx PCONV,%a0@
1138 printf PCONV,") "
1139 addq.l #2,%a0
1140 move.w (%a0)+,%d2 | exponent
1141 jeq fp_e2i_zero\b | zero / denorm (== 0, here)
1142 cmp.w #0x7fff,%d2
1143 jeq fp_e2i_huge\b | Inf / NaN
1144 sub.w #0x3ffe,%d2
1145 jcs fp_e2i_small\b
1146 cmp.w #\b,%d2
1147 jhi fp_e2i_large\b
1148 move.l (%a0),%d0
1149 move.l %d0,%d1
1150 lsl.l %d2,%d1
1151 jne fp_e2i_round\b
1152 tst.l (4,%a0)
1153 jne fp_e2i_round\b
1154 neg.w %d2
1155 add.w #32,%d2
1156 lsr.l %d2,%d0
11579: tst.w (-4,%a0)
1158 jne 1f
1159 tst.\s %d0
1160 jmi fp_e2i_large\b
1161 printf PCONV,"-> %p\n",1,%d0
1162 rts
11631: neg.\s %d0
1164 jeq 1f
1165 jpl fp_e2i_large\b
11661: printf PCONV,"-> %p\n",1,%d0
1167 rts
1168fp_e2i_round\b:
1169 fp_set_sr FPSR_EXC_INEX2 | INEX2 bit
1170 neg.w %d2
1171 add.w #32,%d2
1172 .if \b>16
1173 jeq 5f
1174 .endif
1175 lsr.l %d2,%d0
1176 move.w (FPD_RND,FPDATA),%d2 | rounding mode
1177 jne 2f | %d2 == 0, round to nearest
1178 tst.l %d1 | test guard bit
1179 jpl 9b | zero is closer
1180 btst %d2,%d0 | test lsb bit (%d2 still 0)
1181 jne fp_e2i_doroundup\b
1182 lsl.l #1,%d1 | check low bits
1183 jne fp_e2i_doroundup\b
1184 tst.l (4,%a0)
1185 jeq 9b
1186fp_e2i_doroundup\b:
1187 addq.l #1,%d0
1188 jra 9b
1189 | check nondefault rounding modes
11902: subq.w #2,%d2
1191 jcs 9b | %d2 < 2, round to zero
1192 jhi 3f | %d2 > 2, round to +infinity
1193 tst.w (-4,%a0) | to -inf
1194 jne fp_e2i_doroundup\b | negative, round to infinity
1195 jra 9b | positive, round to zero
11963: tst.w (-4,%a0) | to +inf
1197 jeq fp_e2i_doroundup\b | positive, round to infinity
1198 jra 9b | negative, round to zero
1199 | we are only want -2**127 get correctly rounded here,
1200 | since the guard bit is in the lower lword.
1201 | everything else ends up anyway as overflow.
1202 .if \b>16
12035: move.w (FPD_RND,FPDATA),%d2 | rounding mode
1204 jne 2b | %d2 == 0, round to nearest
1205 move.l (4,%a0),%d1 | test guard bit
1206 jpl 9b | zero is closer
1207 lsl.l #1,%d1 | check low bits
1208 jne fp_e2i_doroundup\b
1209 jra 9b
1210 .endif
1211fp_e2i_zero\b:
1212 clr.l %d0
1213 tst.l (%a0)+
1214 jne 1f
1215 tst.l (%a0)
1216 jeq 3f
12171: subq.l #4,%a0
1218 fp_clr_sr FPSR_EXC_UNFL | fp_normalize_ext has set this bit
1219fp_e2i_small\b:
1220 fp_set_sr FPSR_EXC_INEX2
1221 clr.l %d0
1222 move.w (FPD_RND,FPDATA),%d2 | rounding mode
1223 subq.w #2,%d2
1224 jcs 3f | %d2 < 2, round to nearest/zero
1225 jhi 2f | %d2 > 2, round to +infinity
1226 tst.w (-4,%a0) | to -inf
1227 jeq 3f
1228 subq.\s #1,%d0
1229 jra 3f
12302: tst.w (-4,%a0) | to +inf
1231 jne 3f
1232 addq.\s #1,%d0
12333: printf PCONV,"-> %p\n",1,%d0
1234 rts
1235fp_e2i_large\b:
1236 fp_set_sr FPSR_EXC_OPERR
1237 move.\s #inf,%d0
1238 tst.w (-4,%a0)
1239 jeq 1f
1240 addq.\s #1,%d0
12411: printf PCONV,"-> %p\n",1,%d0
1242 rts
1243fp_e2i_huge\b:
1244 move.\s (%a0),%d0
1245 tst.l (%a0)
1246 jne 1f
1247 tst.l (%a0)
1248 jeq fp_e2i_large\b
1249 | fp_normalize_ext has set this bit already
1250 | and made the number nonsignaling
12511: fp_tst_sr FPSR_EXC_SNAN
1252 jne 1f
1253 fp_set_sr FPSR_EXC_OPERR
12541: printf PCONV,"-> %p\n",1,%d0
1255 rts
1256.endm
1257
1258fp_conv_ext2long:
1259 conv_ext2int l,32
1260
1261fp_conv_ext2short:
1262 conv_ext2int w,16
1263
1264fp_conv_ext2byte:
1265 conv_ext2int b,8
1266
1267fp_conv_ext2double:
1268 jsr fp_normalize_double
1269 printf PCONV,"e2d: %p(",1,%a0
1270 printx PCONV,%a0@
1271 printf PCONV,"), "
1272 move.l (%a0)+,%d2
1273 cmp.w #0x7fff,%d2
1274 jne 1f
1275 move.w #0x7ff,%d2
1276 move.l (%a0)+,%d0
1277 jra 2f
12781: sub.w #0x3fff-0x3ff,%d2
1279 move.l (%a0)+,%d0
1280 jmi 2f
1281 clr.w %d2
12822: lsl.w #5,%d2
1283 lsl.l #7,%d2
1284 lsl.l #8,%d2
1285 move.l %d0,%d1
1286 lsl.l #1,%d0
1287 lsr.l #4,%d0
1288 lsr.l #8,%d0
1289 or.l %d2,%d0
1290 putuser.l %d0,(%a1)+,fp_err_ua2,%a1
1291 moveq #21,%d0
1292 lsl.l %d0,%d1
1293 move.l (%a0),%d0
1294 lsr.l #4,%d0
1295 lsr.l #7,%d0
1296 or.l %d1,%d0
1297 putuser.l %d0,(%a1),fp_err_ua2,%a1
1298#ifdef FPU_EMU_DEBUG
1299 getuser.l %a1@(-4),%d0,fp_err_ua2,%a1
1300 getuser.l %a1@(0),%d1,fp_err_ua2,%a1
1301 printf PCONV,"%p(%08x%08x)\n",3,%a1,%d0,%d1
1302#endif
1303 rts
1304
1305fp_conv_ext2single:
1306 jsr fp_normalize_single
1307 printf PCONV,"e2s: %p(",1,%a0
1308 printx PCONV,%a0@
1309 printf PCONV,"), "
1310 move.l (%a0)+,%d1
1311 cmp.w #0x7fff,%d1
1312 jne 1f
1313 move.w #0xff,%d1
1314 move.l (%a0)+,%d0
1315 jra 2f
13161: sub.w #0x3fff-0x7f,%d1
1317 move.l (%a0)+,%d0
1318 jmi 2f
1319 clr.w %d1
13202: lsl.w #8,%d1
1321 lsl.l #7,%d1
1322 lsl.l #8,%d1
1323 bclr #31,%d0
1324 lsr.l #8,%d0
1325 or.l %d1,%d0
1326 printf PCONV,"%08x\n",1,%d0
1327 rts
1328
1329 | special return addresses for instr that
1330 | encode the rounding precision in the opcode
1331 | (e.g. fsmove,fdmove)
1332
1333fp_finalrounding_single:
1334 addq.l #8,%sp
1335 jsr fp_normalize_ext
1336 jsr fp_normalize_single
1337 jra fp_finaltest
1338
1339fp_finalrounding_single_fast:
1340 addq.l #8,%sp
1341 jsr fp_normalize_ext
1342 jsr fp_normalize_single_fast
1343 jra fp_finaltest
1344
1345fp_finalrounding_double:
1346 addq.l #8,%sp
1347 jsr fp_normalize_ext
1348 jsr fp_normalize_double
1349 jra fp_finaltest
1350
1351 | fp_finaltest:
1352 | set the emulated status register based on the outcome of an
1353 | emulated instruction.
1354
1355fp_finalrounding:
1356 addq.l #8,%sp
1357| printf ,"f: %p\n",1,%a0
1358 jsr fp_normalize_ext
1359 move.w (FPD_PREC,FPDATA),%d0
1360 subq.w #1,%d0
1361 jcs fp_finaltest
1362 jne 1f
1363 jsr fp_normalize_single
1364 jra 2f
13651: jsr fp_normalize_double
13662:| printf ,"f: %p\n",1,%a0
1367fp_finaltest:
1368 | First, we do some of the obvious tests for the exception
1369 | status byte and condition code bytes of fp_sr here, so that
1370 | they do not have to be handled individually by every
1371 | emulated instruction.
1372 clr.l %d0
1373 addq.l #1,%a0
1374 tst.b (%a0)+ | sign
1375 jeq 1f
1376 bset #FPSR_CC_NEG-24,%d0 | N bit
13771: cmp.w #0x7fff,(%a0)+ | exponent
1378 jeq 2f
1379 | test for zero
1380 moveq #FPSR_CC_Z-24,%d1
1381 tst.l (%a0)+
1382 jne 9f
1383 tst.l (%a0)
1384 jne 9f
1385 jra 8f
1386 | infinitiv and NAN
13872: moveq #FPSR_CC_NAN-24,%d1
1388 move.l (%a0)+,%d2
1389 lsl.l #1,%d2 | ignore high bit
1390 jne 8f
1391 tst.l (%a0)
1392 jne 8f
1393 moveq #FPSR_CC_INF-24,%d1
13948: bset %d1,%d0
13959: move.b %d0,(FPD_FPSR+0,FPDATA) | set condition test result
1396 | move instructions enter here
1397 | Here, we test things in the exception status byte, and set
1398 | other things in the accrued exception byte accordingly.
1399 | Emulated instructions can set various things in the former,
1400 | as defined in fp_emu.h.
1401fp_final:
1402 move.l (FPD_FPSR,FPDATA),%d0
1403#if 0
1404 btst #FPSR_EXC_SNAN,%d0 | EXC_SNAN
1405 jne 1f
1406 btst #FPSR_EXC_OPERR,%d0 | EXC_OPERR
1407 jeq 2f
14081: bset #FPSR_AEXC_IOP,%d0 | set IOP bit
14092: btst #FPSR_EXC_OVFL,%d0 | EXC_OVFL
1410 jeq 1f
1411 bset #FPSR_AEXC_OVFL,%d0 | set OVFL bit
14121: btst #FPSR_EXC_UNFL,%d0 | EXC_UNFL
1413 jeq 1f
1414 btst #FPSR_EXC_INEX2,%d0 | EXC_INEX2
1415 jeq 1f
1416 bset #FPSR_AEXC_UNFL,%d0 | set UNFL bit
14171: btst #FPSR_EXC_DZ,%d0 | EXC_INEX1
1418 jeq 1f
1419 bset #FPSR_AEXC_DZ,%d0 | set DZ bit
14201: btst #FPSR_EXC_OVFL,%d0 | EXC_OVFL
1421 jne 1f
1422 btst #FPSR_EXC_INEX2,%d0 | EXC_INEX2
1423 jne 1f
1424 btst #FPSR_EXC_INEX1,%d0 | EXC_INEX1
1425 jeq 2f
14261: bset #FPSR_AEXC_INEX,%d0 | set INEX bit
14272: move.l %d0,(FPD_FPSR,FPDATA)
1428#else
1429 | same as above, greatly optimized, but untested (yet)
1430 move.l %d0,%d2
1431 lsr.l #5,%d0
1432 move.l %d0,%d1
1433 lsr.l #4,%d1
1434 or.l %d0,%d1
1435 and.b #0x08,%d1
1436 move.l %d2,%d0
1437 lsr.l #6,%d0
1438 or.l %d1,%d0
1439 move.l %d2,%d1
1440 lsr.l #4,%d1
1441 or.b #0xdf,%d1
1442 and.b %d1,%d0
1443 move.l %d2,%d1
1444 lsr.l #7,%d1
1445 and.b #0x80,%d1
1446 or.b %d1,%d0
1447 and.b #0xf8,%d0
1448 or.b %d0,%d2
1449 move.l %d2,(FPD_FPSR,FPDATA)
1450#endif
1451 move.b (FPD_FPSR+2,FPDATA),%d0
1452 and.b (FPD_FPCR+2,FPDATA),%d0
1453 jeq 1f
1454 printf ,"send signal!!!\n"
14551: jra fp_end
diff --git a/arch/m68k/math-emu/multi_arith.h b/arch/m68k/math-emu/multi_arith.h
new file mode 100644
index 000000000000..02251e5afd89
--- /dev/null
+++ b/arch/m68k/math-emu/multi_arith.h
@@ -0,0 +1,819 @@
1/* multi_arith.h: multi-precision integer arithmetic functions, needed
2 to do extended-precision floating point.
3
4 (c) 1998 David Huggins-Daines.
5
6 Somewhat based on arch/alpha/math-emu/ieee-math.c, which is (c)
7 David Mosberger-Tang.
8
9 You may copy, modify, and redistribute this file under the terms of
10 the GNU General Public License, version 2, or any later version, at
11 your convenience. */
12
13/* Note:
14
15 These are not general multi-precision math routines. Rather, they
16 implement the subset of integer arithmetic that we need in order to
17 multiply, divide, and normalize 128-bit unsigned mantissae. */
18
19#ifndef MULTI_ARITH_H
20#define MULTI_ARITH_H
21
22#if 0 /* old code... */
23
24/* Unsigned only, because we don't need signs to multiply and divide. */
25typedef unsigned int int128[4];
26
27/* Word order */
28enum {
29 MSW128,
30 NMSW128,
31 NLSW128,
32 LSW128
33};
34
35/* big-endian */
36#define LO_WORD(ll) (((unsigned int *) &ll)[1])
37#define HI_WORD(ll) (((unsigned int *) &ll)[0])
38
39/* Convenience functions to stuff various integer values into int128s */
40
41static inline void zero128(int128 a)
42{
43 a[LSW128] = a[NLSW128] = a[NMSW128] = a[MSW128] = 0;
44}
45
46/* Human-readable word order in the arguments */
47static inline void set128(unsigned int i3, unsigned int i2, unsigned int i1,
48 unsigned int i0, int128 a)
49{
50 a[LSW128] = i0;
51 a[NLSW128] = i1;
52 a[NMSW128] = i2;
53 a[MSW128] = i3;
54}
55
56/* Convenience functions (for testing as well) */
57static inline void int64_to_128(unsigned long long src, int128 dest)
58{
59 dest[LSW128] = (unsigned int) src;
60 dest[NLSW128] = src >> 32;
61 dest[NMSW128] = dest[MSW128] = 0;
62}
63
64static inline void int128_to_64(const int128 src, unsigned long long *dest)
65{
66 *dest = src[LSW128] | (long long) src[NLSW128] << 32;
67}
68
69static inline void put_i128(const int128 a)
70{
71 printk("%08x %08x %08x %08x\n", a[MSW128], a[NMSW128],
72 a[NLSW128], a[LSW128]);
73}
74
75/* Internal shifters:
76
77 Note that these are only good for 0 < count < 32.
78 */
79
80static inline void _lsl128(unsigned int count, int128 a)
81{
82 a[MSW128] = (a[MSW128] << count) | (a[NMSW128] >> (32 - count));
83 a[NMSW128] = (a[NMSW128] << count) | (a[NLSW128] >> (32 - count));
84 a[NLSW128] = (a[NLSW128] << count) | (a[LSW128] >> (32 - count));
85 a[LSW128] <<= count;
86}
87
88static inline void _lsr128(unsigned int count, int128 a)
89{
90 a[LSW128] = (a[LSW128] >> count) | (a[NLSW128] << (32 - count));
91 a[NLSW128] = (a[NLSW128] >> count) | (a[NMSW128] << (32 - count));
92 a[NMSW128] = (a[NMSW128] >> count) | (a[MSW128] << (32 - count));
93 a[MSW128] >>= count;
94}
95
96/* Should be faster, one would hope */
97
98static inline void lslone128(int128 a)
99{
100 asm volatile ("lsl.l #1,%0\n"
101 "roxl.l #1,%1\n"
102 "roxl.l #1,%2\n"
103 "roxl.l #1,%3\n"
104 :
105 "=d" (a[LSW128]),
106 "=d"(a[NLSW128]),
107 "=d"(a[NMSW128]),
108 "=d"(a[MSW128])
109 :
110 "0"(a[LSW128]),
111 "1"(a[NLSW128]),
112 "2"(a[NMSW128]),
113 "3"(a[MSW128]));
114}
115
116static inline void lsrone128(int128 a)
117{
118 asm volatile ("lsr.l #1,%0\n"
119 "roxr.l #1,%1\n"
120 "roxr.l #1,%2\n"
121 "roxr.l #1,%3\n"
122 :
123 "=d" (a[MSW128]),
124 "=d"(a[NMSW128]),
125 "=d"(a[NLSW128]),
126 "=d"(a[LSW128])
127 :
128 "0"(a[MSW128]),
129 "1"(a[NMSW128]),
130 "2"(a[NLSW128]),
131 "3"(a[LSW128]));
132}
133
134/* Generalized 128-bit shifters:
135
136 These bit-shift to a multiple of 32, then move whole longwords. */
137
138static inline void lsl128(unsigned int count, int128 a)
139{
140 int wordcount, i;
141
142 if (count % 32)
143 _lsl128(count % 32, a);
144
145 if (0 == (wordcount = count / 32))
146 return;
147
148 /* argh, gak, endian-sensitive */
149 for (i = 0; i < 4 - wordcount; i++) {
150 a[i] = a[i + wordcount];
151 }
152 for (i = 3; i >= 4 - wordcount; --i) {
153 a[i] = 0;
154 }
155}
156
157static inline void lsr128(unsigned int count, int128 a)
158{
159 int wordcount, i;
160
161 if (count % 32)
162 _lsr128(count % 32, a);
163
164 if (0 == (wordcount = count / 32))
165 return;
166
167 for (i = 3; i >= wordcount; --i) {
168 a[i] = a[i - wordcount];
169 }
170 for (i = 0; i < wordcount; i++) {
171 a[i] = 0;
172 }
173}
174
175static inline int orl128(int a, int128 b)
176{
177 b[LSW128] |= a;
178}
179
180static inline int btsthi128(const int128 a)
181{
182 return a[MSW128] & 0x80000000;
183}
184
185/* test bits (numbered from 0 = LSB) up to and including "top" */
186static inline int bftestlo128(int top, const int128 a)
187{
188 int r = 0;
189
190 if (top > 31)
191 r |= a[LSW128];
192 if (top > 63)
193 r |= a[NLSW128];
194 if (top > 95)
195 r |= a[NMSW128];
196
197 r |= a[3 - (top / 32)] & ((1 << (top % 32 + 1)) - 1);
198
199 return (r != 0);
200}
201
202/* Aargh. We need these because GCC is broken */
203/* FIXME: do them in assembly, for goodness' sake! */
204static inline void mask64(int pos, unsigned long long *mask)
205{
206 *mask = 0;
207
208 if (pos < 32) {
209 LO_WORD(*mask) = (1 << pos) - 1;
210 return;
211 }
212 LO_WORD(*mask) = -1;
213 HI_WORD(*mask) = (1 << (pos - 32)) - 1;
214}
215
216static inline void bset64(int pos, unsigned long long *dest)
217{
218 /* This conditional will be optimized away. Thanks, GCC! */
219 if (pos < 32)
220 asm volatile ("bset %1,%0":"=m"
221 (LO_WORD(*dest)):"id"(pos));
222 else
223 asm volatile ("bset %1,%0":"=m"
224 (HI_WORD(*dest)):"id"(pos - 32));
225}
226
227static inline int btst64(int pos, unsigned long long dest)
228{
229 if (pos < 32)
230 return (0 != (LO_WORD(dest) & (1 << pos)));
231 else
232 return (0 != (HI_WORD(dest) & (1 << (pos - 32))));
233}
234
235static inline void lsl64(int count, unsigned long long *dest)
236{
237 if (count < 32) {
238 HI_WORD(*dest) = (HI_WORD(*dest) << count)
239 | (LO_WORD(*dest) >> count);
240 LO_WORD(*dest) <<= count;
241 return;
242 }
243 count -= 32;
244 HI_WORD(*dest) = LO_WORD(*dest) << count;
245 LO_WORD(*dest) = 0;
246}
247
248static inline void lsr64(int count, unsigned long long *dest)
249{
250 if (count < 32) {
251 LO_WORD(*dest) = (LO_WORD(*dest) >> count)
252 | (HI_WORD(*dest) << (32 - count));
253 HI_WORD(*dest) >>= count;
254 return;
255 }
256 count -= 32;
257 LO_WORD(*dest) = HI_WORD(*dest) >> count;
258 HI_WORD(*dest) = 0;
259}
260#endif
261
262static inline void fp_denormalize(struct fp_ext *reg, unsigned int cnt)
263{
264 reg->exp += cnt;
265
266 switch (cnt) {
267 case 0 ... 8:
268 reg->lowmant = reg->mant.m32[1] << (8 - cnt);
269 reg->mant.m32[1] = (reg->mant.m32[1] >> cnt) |
270 (reg->mant.m32[0] << (32 - cnt));
271 reg->mant.m32[0] = reg->mant.m32[0] >> cnt;
272 break;
273 case 9 ... 32:
274 reg->lowmant = reg->mant.m32[1] >> (cnt - 8);
275 if (reg->mant.m32[1] << (40 - cnt))
276 reg->lowmant |= 1;
277 reg->mant.m32[1] = (reg->mant.m32[1] >> cnt) |
278 (reg->mant.m32[0] << (32 - cnt));
279 reg->mant.m32[0] = reg->mant.m32[0] >> cnt;
280 break;
281 case 33 ... 39:
282 asm volatile ("bfextu %1{%2,#8},%0" : "=d" (reg->lowmant)
283 : "m" (reg->mant.m32[0]), "d" (64 - cnt));
284 if (reg->mant.m32[1] << (40 - cnt))
285 reg->lowmant |= 1;
286 reg->mant.m32[1] = reg->mant.m32[0] >> (cnt - 32);
287 reg->mant.m32[0] = 0;
288 break;
289 case 40 ... 71:
290 reg->lowmant = reg->mant.m32[0] >> (cnt - 40);
291 if ((reg->mant.m32[0] << (72 - cnt)) || reg->mant.m32[1])
292 reg->lowmant |= 1;
293 reg->mant.m32[1] = reg->mant.m32[0] >> (cnt - 32);
294 reg->mant.m32[0] = 0;
295 break;
296 default:
297 reg->lowmant = reg->mant.m32[0] || reg->mant.m32[1];
298 reg->mant.m32[0] = 0;
299 reg->mant.m32[1] = 0;
300 break;
301 }
302}
303
304static inline int fp_overnormalize(struct fp_ext *reg)
305{
306 int shift;
307
308 if (reg->mant.m32[0]) {
309 asm ("bfffo %1{#0,#32},%0" : "=d" (shift) : "dm" (reg->mant.m32[0]));
310 reg->mant.m32[0] = (reg->mant.m32[0] << shift) | (reg->mant.m32[1] >> (32 - shift));
311 reg->mant.m32[1] = (reg->mant.m32[1] << shift);
312 } else {
313 asm ("bfffo %1{#0,#32},%0" : "=d" (shift) : "dm" (reg->mant.m32[1]));
314 reg->mant.m32[0] = (reg->mant.m32[1] << shift);
315 reg->mant.m32[1] = 0;
316 shift += 32;
317 }
318
319 return shift;
320}
321
322static inline int fp_addmant(struct fp_ext *dest, struct fp_ext *src)
323{
324 int carry;
325
326 /* we assume here, gcc only insert move and a clr instr */
327 asm volatile ("add.b %1,%0" : "=d,g" (dest->lowmant)
328 : "g,d" (src->lowmant), "0,0" (dest->lowmant));
329 asm volatile ("addx.l %1,%0" : "=d" (dest->mant.m32[1])
330 : "d" (src->mant.m32[1]), "0" (dest->mant.m32[1]));
331 asm volatile ("addx.l %1,%0" : "=d" (dest->mant.m32[0])
332 : "d" (src->mant.m32[0]), "0" (dest->mant.m32[0]));
333 asm volatile ("addx.l %0,%0" : "=d" (carry) : "0" (0));
334
335 return carry;
336}
337
338static inline int fp_addcarry(struct fp_ext *reg)
339{
340 if (++reg->exp == 0x7fff) {
341 if (reg->mant.m64)
342 fp_set_sr(FPSR_EXC_INEX2);
343 reg->mant.m64 = 0;
344 fp_set_sr(FPSR_EXC_OVFL);
345 return 0;
346 }
347 reg->lowmant = (reg->mant.m32[1] << 7) | (reg->lowmant ? 1 : 0);
348 reg->mant.m32[1] = (reg->mant.m32[1] >> 1) |
349 (reg->mant.m32[0] << 31);
350 reg->mant.m32[0] = (reg->mant.m32[0] >> 1) | 0x80000000;
351
352 return 1;
353}
354
355static inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1,
356 struct fp_ext *src2)
357{
358 /* we assume here, gcc only insert move and a clr instr */
359 asm volatile ("sub.b %1,%0" : "=d,g" (dest->lowmant)
360 : "g,d" (src2->lowmant), "0,0" (src1->lowmant));
361 asm volatile ("subx.l %1,%0" : "=d" (dest->mant.m32[1])
362 : "d" (src2->mant.m32[1]), "0" (src1->mant.m32[1]));
363 asm volatile ("subx.l %1,%0" : "=d" (dest->mant.m32[0])
364 : "d" (src2->mant.m32[0]), "0" (src1->mant.m32[0]));
365}
366
367#define fp_mul64(desth, destl, src1, src2) ({ \
368 asm ("mulu.l %2,%1:%0" : "=d" (destl), "=d" (desth) \
369 : "g" (src1), "0" (src2)); \
370})
371#define fp_div64(quot, rem, srch, srcl, div) \
372 asm ("divu.l %2,%1:%0" : "=d" (quot), "=d" (rem) \
373 : "dm" (div), "1" (srch), "0" (srcl))
374#define fp_add64(dest1, dest2, src1, src2) ({ \
375 asm ("add.l %1,%0" : "=d,dm" (dest2) \
376 : "dm,d" (src2), "0,0" (dest2)); \
377 asm ("addx.l %1,%0" : "=d" (dest1) \
378 : "d" (src1), "0" (dest1)); \
379})
380#define fp_addx96(dest, src) ({ \
381 /* we assume here, gcc only insert move and a clr instr */ \
382 asm volatile ("add.l %1,%0" : "=d,g" (dest->m32[2]) \
383 : "g,d" (temp.m32[1]), "0,0" (dest->m32[2])); \
384 asm volatile ("addx.l %1,%0" : "=d" (dest->m32[1]) \
385 : "d" (temp.m32[0]), "0" (dest->m32[1])); \
386 asm volatile ("addx.l %1,%0" : "=d" (dest->m32[0]) \
387 : "d" (0), "0" (dest->m32[0])); \
388})
389#define fp_sub64(dest, src) ({ \
390 asm ("sub.l %1,%0" : "=d,dm" (dest.m32[1]) \
391 : "dm,d" (src.m32[1]), "0,0" (dest.m32[1])); \
392 asm ("subx.l %1,%0" : "=d" (dest.m32[0]) \
393 : "d" (src.m32[0]), "0" (dest.m32[0])); \
394})
395#define fp_sub96c(dest, srch, srcm, srcl) ({ \
396 char carry; \
397 asm ("sub.l %1,%0" : "=d,dm" (dest.m32[2]) \
398 : "dm,d" (srcl), "0,0" (dest.m32[2])); \
399 asm ("subx.l %1,%0" : "=d" (dest.m32[1]) \
400 : "d" (srcm), "0" (dest.m32[1])); \
401 asm ("subx.l %2,%1; scs %0" : "=d" (carry), "=d" (dest.m32[0]) \
402 : "d" (srch), "1" (dest.m32[0])); \
403 carry; \
404})
405
406static inline void fp_multiplymant(union fp_mant128 *dest, struct fp_ext *src1,
407 struct fp_ext *src2)
408{
409 union fp_mant64 temp;
410
411 fp_mul64(dest->m32[0], dest->m32[1], src1->mant.m32[0], src2->mant.m32[0]);
412 fp_mul64(dest->m32[2], dest->m32[3], src1->mant.m32[1], src2->mant.m32[1]);
413
414 fp_mul64(temp.m32[0], temp.m32[1], src1->mant.m32[0], src2->mant.m32[1]);
415 fp_addx96(dest, temp);
416
417 fp_mul64(temp.m32[0], temp.m32[1], src1->mant.m32[1], src2->mant.m32[0]);
418 fp_addx96(dest, temp);
419}
420
421static inline void fp_dividemant(union fp_mant128 *dest, struct fp_ext *src,
422 struct fp_ext *div)
423{
424 union fp_mant128 tmp;
425 union fp_mant64 tmp64;
426 unsigned long *mantp = dest->m32;
427 unsigned long fix, rem, first, dummy;
428 int i;
429
430 /* the algorithm below requires dest to be smaller than div,
431 but both have the high bit set */
432 if (src->mant.m64 >= div->mant.m64) {
433 fp_sub64(src->mant, div->mant);
434 *mantp = 1;
435 } else
436 *mantp = 0;
437 mantp++;
438
439 /* basic idea behind this algorithm: we can't divide two 64bit numbers
440 (AB/CD) directly, but we can calculate AB/C0, but this means this
441 quotient is off by C0/CD, so we have to multiply the first result
442 to fix the result, after that we have nearly the correct result
443 and only a few corrections are needed. */
444
445 /* C0/CD can be precalculated, but it's an 64bit division again, but
446 we can make it a bit easier, by dividing first through C so we get
447 10/1D and now only a single shift and the value fits into 32bit. */
448 fix = 0x80000000;
449 dummy = div->mant.m32[1] / div->mant.m32[0] + 1;
450 dummy = (dummy >> 1) | fix;
451 fp_div64(fix, dummy, fix, 0, dummy);
452 fix--;
453
454 for (i = 0; i < 3; i++, mantp++) {
455 if (src->mant.m32[0] == div->mant.m32[0]) {
456 fp_div64(first, rem, 0, src->mant.m32[1], div->mant.m32[0]);
457
458 fp_mul64(*mantp, dummy, first, fix);
459 *mantp += fix;
460 } else {
461 fp_div64(first, rem, src->mant.m32[0], src->mant.m32[1], div->mant.m32[0]);
462
463 fp_mul64(*mantp, dummy, first, fix);
464 }
465
466 fp_mul64(tmp.m32[0], tmp.m32[1], div->mant.m32[0], first - *mantp);
467 fp_add64(tmp.m32[0], tmp.m32[1], 0, rem);
468 tmp.m32[2] = 0;
469
470 fp_mul64(tmp64.m32[0], tmp64.m32[1], *mantp, div->mant.m32[1]);
471 fp_sub96c(tmp, 0, tmp64.m32[0], tmp64.m32[1]);
472
473 src->mant.m32[0] = tmp.m32[1];
474 src->mant.m32[1] = tmp.m32[2];
475
476 while (!fp_sub96c(tmp, 0, div->mant.m32[0], div->mant.m32[1])) {
477 src->mant.m32[0] = tmp.m32[1];
478 src->mant.m32[1] = tmp.m32[2];
479 *mantp += 1;
480 }
481 }
482}
483
484#if 0
485static inline unsigned int fp_fls128(union fp_mant128 *src)
486{
487 unsigned long data;
488 unsigned int res, off;
489
490 if ((data = src->m32[0]))
491 off = 0;
492 else if ((data = src->m32[1]))
493 off = 32;
494 else if ((data = src->m32[2]))
495 off = 64;
496 else if ((data = src->m32[3]))
497 off = 96;
498 else
499 return 128;
500
501 asm ("bfffo %1{#0,#32},%0" : "=d" (res) : "dm" (data));
502 return res + off;
503}
504
505static inline void fp_shiftmant128(union fp_mant128 *src, int shift)
506{
507 unsigned long sticky;
508
509 switch (shift) {
510 case 0:
511 return;
512 case 1:
513 asm volatile ("lsl.l #1,%0"
514 : "=d" (src->m32[3]) : "0" (src->m32[3]));
515 asm volatile ("roxl.l #1,%0"
516 : "=d" (src->m32[2]) : "0" (src->m32[2]));
517 asm volatile ("roxl.l #1,%0"
518 : "=d" (src->m32[1]) : "0" (src->m32[1]));
519 asm volatile ("roxl.l #1,%0"
520 : "=d" (src->m32[0]) : "0" (src->m32[0]));
521 return;
522 case 2 ... 31:
523 src->m32[0] = (src->m32[0] << shift) | (src->m32[1] >> (32 - shift));
524 src->m32[1] = (src->m32[1] << shift) | (src->m32[2] >> (32 - shift));
525 src->m32[2] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
526 src->m32[3] = (src->m32[3] << shift);
527 return;
528 case 32 ... 63:
529 shift -= 32;
530 src->m32[0] = (src->m32[1] << shift) | (src->m32[2] >> (32 - shift));
531 src->m32[1] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
532 src->m32[2] = (src->m32[3] << shift);
533 src->m32[3] = 0;
534 return;
535 case 64 ... 95:
536 shift -= 64;
537 src->m32[0] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
538 src->m32[1] = (src->m32[3] << shift);
539 src->m32[2] = src->m32[3] = 0;
540 return;
541 case 96 ... 127:
542 shift -= 96;
543 src->m32[0] = (src->m32[3] << shift);
544 src->m32[1] = src->m32[2] = src->m32[3] = 0;
545 return;
546 case -31 ... -1:
547 shift = -shift;
548 sticky = 0;
549 if (src->m32[3] << (32 - shift))
550 sticky = 1;
551 src->m32[3] = (src->m32[3] >> shift) | (src->m32[2] << (32 - shift)) | sticky;
552 src->m32[2] = (src->m32[2] >> shift) | (src->m32[1] << (32 - shift));
553 src->m32[1] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift));
554 src->m32[0] = (src->m32[0] >> shift);
555 return;
556 case -63 ... -32:
557 shift = -shift - 32;
558 sticky = 0;
559 if ((src->m32[2] << (32 - shift)) || src->m32[3])
560 sticky = 1;
561 src->m32[3] = (src->m32[2] >> shift) | (src->m32[1] << (32 - shift)) | sticky;
562 src->m32[2] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift));
563 src->m32[1] = (src->m32[0] >> shift);
564 src->m32[0] = 0;
565 return;
566 case -95 ... -64:
567 shift = -shift - 64;
568 sticky = 0;
569 if ((src->m32[1] << (32 - shift)) || src->m32[2] || src->m32[3])
570 sticky = 1;
571 src->m32[3] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift)) | sticky;
572 src->m32[2] = (src->m32[0] >> shift);
573 src->m32[1] = src->m32[0] = 0;
574 return;
575 case -127 ... -96:
576 shift = -shift - 96;
577 sticky = 0;
578 if ((src->m32[0] << (32 - shift)) || src->m32[1] || src->m32[2] || src->m32[3])
579 sticky = 1;
580 src->m32[3] = (src->m32[0] >> shift) | sticky;
581 src->m32[2] = src->m32[1] = src->m32[0] = 0;
582 return;
583 }
584
585 if (shift < 0 && (src->m32[0] || src->m32[1] || src->m32[2] || src->m32[3]))
586 src->m32[3] = 1;
587 else
588 src->m32[3] = 0;
589 src->m32[2] = 0;
590 src->m32[1] = 0;
591 src->m32[0] = 0;
592}
593#endif
594
595static inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src,
596 int shift)
597{
598 unsigned long tmp;
599
600 switch (shift) {
601 case 0:
602 dest->mant.m64 = src->m64[0];
603 dest->lowmant = src->m32[2] >> 24;
604 if (src->m32[3] || (src->m32[2] << 8))
605 dest->lowmant |= 1;
606 break;
607 case 1:
608 asm volatile ("lsl.l #1,%0"
609 : "=d" (tmp) : "0" (src->m32[2]));
610 asm volatile ("roxl.l #1,%0"
611 : "=d" (dest->mant.m32[1]) : "0" (src->m32[1]));
612 asm volatile ("roxl.l #1,%0"
613 : "=d" (dest->mant.m32[0]) : "0" (src->m32[0]));
614 dest->lowmant = tmp >> 24;
615 if (src->m32[3] || (tmp << 8))
616 dest->lowmant |= 1;
617 break;
618 case 31:
619 asm volatile ("lsr.l #1,%1; roxr.l #1,%0"
620 : "=d" (dest->mant.m32[0])
621 : "d" (src->m32[0]), "0" (src->m32[1]));
622 asm volatile ("roxr.l #1,%0"
623 : "=d" (dest->mant.m32[1]) : "0" (src->m32[2]));
624 asm volatile ("roxr.l #1,%0"
625 : "=d" (tmp) : "0" (src->m32[3]));
626 dest->lowmant = tmp >> 24;
627 if (src->m32[3] << 7)
628 dest->lowmant |= 1;
629 break;
630 case 32:
631 dest->mant.m32[0] = src->m32[1];
632 dest->mant.m32[1] = src->m32[2];
633 dest->lowmant = src->m32[3] >> 24;
634 if (src->m32[3] << 8)
635 dest->lowmant |= 1;
636 break;
637 }
638}
639
640#if 0 /* old code... */
641static inline int fls(unsigned int a)
642{
643 int r;
644
645 asm volatile ("bfffo %1{#0,#32},%0"
646 : "=d" (r) : "md" (a));
647 return r;
648}
649
650/* fls = "find last set" (cf. ffs(3)) */
651static inline int fls128(const int128 a)
652{
653 if (a[MSW128])
654 return fls(a[MSW128]);
655 if (a[NMSW128])
656 return fls(a[NMSW128]) + 32;
657 /* XXX: it probably never gets beyond this point in actual
658 use, but that's indicative of a more general problem in the
659 algorithm (i.e. as per the actual 68881 implementation, we
660 really only need at most 67 bits of precision [plus
661 overflow]) so I'm not going to fix it. */
662 if (a[NLSW128])
663 return fls(a[NLSW128]) + 64;
664 if (a[LSW128])
665 return fls(a[LSW128]) + 96;
666 else
667 return -1;
668}
669
670static inline int zerop128(const int128 a)
671{
672 return !(a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]);
673}
674
675static inline int nonzerop128(const int128 a)
676{
677 return (a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]);
678}
679
680/* Addition and subtraction */
681/* Do these in "pure" assembly, because "extended" asm is unmanageable
682 here */
683static inline void add128(const int128 a, int128 b)
684{
685 /* rotating carry flags */
686 unsigned int carry[2];
687
688 carry[0] = a[LSW128] > (0xffffffff - b[LSW128]);
689 b[LSW128] += a[LSW128];
690
691 carry[1] = a[NLSW128] > (0xffffffff - b[NLSW128] - carry[0]);
692 b[NLSW128] = a[NLSW128] + b[NLSW128] + carry[0];
693
694 carry[0] = a[NMSW128] > (0xffffffff - b[NMSW128] - carry[1]);
695 b[NMSW128] = a[NMSW128] + b[NMSW128] + carry[1];
696
697 b[MSW128] = a[MSW128] + b[MSW128] + carry[0];
698}
699
700/* Note: assembler semantics: "b -= a" */
701static inline void sub128(const int128 a, int128 b)
702{
703 /* rotating borrow flags */
704 unsigned int borrow[2];
705
706 borrow[0] = b[LSW128] < a[LSW128];
707 b[LSW128] -= a[LSW128];
708
709 borrow[1] = b[NLSW128] < a[NLSW128] + borrow[0];
710 b[NLSW128] = b[NLSW128] - a[NLSW128] - borrow[0];
711
712 borrow[0] = b[NMSW128] < a[NMSW128] + borrow[1];
713 b[NMSW128] = b[NMSW128] - a[NMSW128] - borrow[1];
714
715 b[MSW128] = b[MSW128] - a[MSW128] - borrow[0];
716}
717
718/* Poor man's 64-bit expanding multiply */
719static inline void mul64(unsigned long long a, unsigned long long b, int128 c)
720{
721 unsigned long long acc;
722 int128 acc128;
723
724 zero128(acc128);
725 zero128(c);
726
727 /* first the low words */
728 if (LO_WORD(a) && LO_WORD(b)) {
729 acc = (long long) LO_WORD(a) * LO_WORD(b);
730 c[NLSW128] = HI_WORD(acc);
731 c[LSW128] = LO_WORD(acc);
732 }
733 /* Next the high words */
734 if (HI_WORD(a) && HI_WORD(b)) {
735 acc = (long long) HI_WORD(a) * HI_WORD(b);
736 c[MSW128] = HI_WORD(acc);
737 c[NMSW128] = LO_WORD(acc);
738 }
739 /* The middle words */
740 if (LO_WORD(a) && HI_WORD(b)) {
741 acc = (long long) LO_WORD(a) * HI_WORD(b);
742 acc128[NMSW128] = HI_WORD(acc);
743 acc128[NLSW128] = LO_WORD(acc);
744 add128(acc128, c);
745 }
746 /* The first and last words */
747 if (HI_WORD(a) && LO_WORD(b)) {
748 acc = (long long) HI_WORD(a) * LO_WORD(b);
749 acc128[NMSW128] = HI_WORD(acc);
750 acc128[NLSW128] = LO_WORD(acc);
751 add128(acc128, c);
752 }
753}
754
755/* Note: unsigned */
756static inline int cmp128(int128 a, int128 b)
757{
758 if (a[MSW128] < b[MSW128])
759 return -1;
760 if (a[MSW128] > b[MSW128])
761 return 1;
762 if (a[NMSW128] < b[NMSW128])
763 return -1;
764 if (a[NMSW128] > b[NMSW128])
765 return 1;
766 if (a[NLSW128] < b[NLSW128])
767 return -1;
768 if (a[NLSW128] > b[NLSW128])
769 return 1;
770
771 return (signed) a[LSW128] - b[LSW128];
772}
773
774inline void div128(int128 a, int128 b, int128 c)
775{
776 int128 mask;
777
778 /* Algorithm:
779
780 Shift the divisor until it's at least as big as the
781 dividend, keeping track of the position to which we've
782 shifted it, i.e. the power of 2 which we've multiplied it
783 by.
784
785 Then, for this power of 2 (the mask), and every one smaller
786 than it, subtract the mask from the dividend and add it to
787 the quotient until the dividend is smaller than the raised
788 divisor. At this point, divide the dividend and the mask
789 by 2 (i.e. shift one place to the right). Lather, rinse,
790 and repeat, until there are no more powers of 2 left. */
791
792 /* FIXME: needless to say, there's room for improvement here too. */
793
794 /* Shift up */
795 /* XXX: since it just has to be "at least as big", we can
796 probably eliminate this horribly wasteful loop. I will
797 have to prove this first, though */
798 set128(0, 0, 0, 1, mask);
799 while (cmp128(b, a) < 0 && !btsthi128(b)) {
800 lslone128(b);
801 lslone128(mask);
802 }
803
804 /* Shift down */
805 zero128(c);
806 do {
807 if (cmp128(a, b) >= 0) {
808 sub128(b, a);
809 add128(mask, c);
810 }
811 lsrone128(mask);
812 lsrone128(b);
813 } while (nonzerop128(mask));
814
815 /* The remainder is in a... */
816}
817#endif
818
819#endif /* MULTI_ARITH_H */
diff --git a/arch/m68k/mm/Makefile b/arch/m68k/mm/Makefile
new file mode 100644
index 000000000000..90f1c735c110
--- /dev/null
+++ b/arch/m68k/mm/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the linux m68k-specific parts of the memory manager.
3#
4
5obj-y := init.o fault.o hwtest.o
6
7obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
8obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
new file mode 100644
index 000000000000..ac48b6d2aff6
--- /dev/null
+++ b/arch/m68k/mm/fault.c
@@ -0,0 +1,219 @@
1/*
2 * linux/arch/m68k/mm/fault.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 */
6
7#include <linux/mman.h>
8#include <linux/mm.h>
9#include <linux/kernel.h>
10#include <linux/ptrace.h>
11#include <linux/interrupt.h>
12#include <linux/module.h>
13
14#include <asm/setup.h>
15#include <asm/traps.h>
16#include <asm/system.h>
17#include <asm/uaccess.h>
18#include <asm/pgalloc.h>
19
20extern void die_if_kernel(char *, struct pt_regs *, long);
21extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
22
23int send_fault_sig(struct pt_regs *regs)
24{
25 siginfo_t siginfo = { 0, 0, 0, };
26
27 siginfo.si_signo = current->thread.signo;
28 siginfo.si_code = current->thread.code;
29 siginfo.si_addr = (void *)current->thread.faddr;
30#ifdef DEBUG
31 printk("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, siginfo.si_signo, siginfo.si_code);
32#endif
33
34 if (user_mode(regs)) {
35 force_sig_info(siginfo.si_signo,
36 &siginfo, current);
37 } else {
38 const struct exception_table_entry *fixup;
39
40 /* Are we prepared to handle this kernel fault? */
41 if ((fixup = search_exception_tables(regs->pc))) {
42 struct pt_regs *tregs;
43 /* Create a new four word stack frame, discarding the old
44 one. */
45 regs->stkadj = frame_extra_sizes[regs->format];
46 tregs = (struct pt_regs *)((ulong)regs + regs->stkadj);
47 tregs->vector = regs->vector;
48 tregs->format = 0;
49 tregs->pc = fixup->fixup;
50 tregs->sr = regs->sr;
51 return -1;
52 }
53
54 //if (siginfo.si_signo == SIGBUS)
55 // force_sig_info(siginfo.si_signo,
56 // &siginfo, current);
57
58 /*
59 * Oops. The kernel tried to access some bad page. We'll have to
60 * terminate things with extreme prejudice.
61 */
62 if ((unsigned long)siginfo.si_addr < PAGE_SIZE)
63 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
64 else
65 printk(KERN_ALERT "Unable to handle kernel access");
66 printk(" at virtual address %p\n", siginfo.si_addr);
67 die_if_kernel("Oops", regs, 0 /*error_code*/);
68 do_exit(SIGKILL);
69 }
70
71 return 1;
72}
73
74/*
75 * This routine handles page faults. It determines the problem, and
76 * then passes it off to one of the appropriate routines.
77 *
78 * error_code:
79 * bit 0 == 0 means no page found, 1 means protection fault
80 * bit 1 == 0 means read, 1 means write
81 *
82 * If this routine detects a bad access, it returns 1, otherwise it
83 * returns 0.
84 */
85int do_page_fault(struct pt_regs *regs, unsigned long address,
86 unsigned long error_code)
87{
88 struct mm_struct *mm = current->mm;
89 struct vm_area_struct * vma;
90 int write, fault;
91
92#ifdef DEBUG
93 printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
94 regs->sr, regs->pc, address, error_code,
95 current->mm->pgd);
96#endif
97
98 /*
99 * If we're in an interrupt or have no user
100 * context, we must not take the fault..
101 */
102 if (in_interrupt() || !mm)
103 goto no_context;
104
105 down_read(&mm->mmap_sem);
106
107 vma = find_vma(mm, address);
108 if (!vma)
109 goto map_err;
110 if (vma->vm_flags & VM_IO)
111 goto acc_err;
112 if (vma->vm_start <= address)
113 goto good_area;
114 if (!(vma->vm_flags & VM_GROWSDOWN))
115 goto map_err;
116 if (user_mode(regs)) {
117 /* Accessing the stack below usp is always a bug. The
118 "+ 256" is there due to some instructions doing
119 pre-decrement on the stack and that doesn't show up
120 until later. */
121 if (address + 256 < rdusp())
122 goto map_err;
123 }
124 if (expand_stack(vma, address))
125 goto map_err;
126
127/*
128 * Ok, we have a good vm_area for this memory access, so
129 * we can handle it..
130 */
131good_area:
132#ifdef DEBUG
133 printk("do_page_fault: good_area\n");
134#endif
135 write = 0;
136 switch (error_code & 3) {
137 default: /* 3: write, present */
138 /* fall through */
139 case 2: /* write, not present */
140 if (!(vma->vm_flags & VM_WRITE))
141 goto acc_err;
142 write++;
143 break;
144 case 1: /* read, present */
145 goto acc_err;
146 case 0: /* read, not present */
147 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
148 goto acc_err;
149 }
150
151 /*
152 * If for any reason at all we couldn't handle the fault,
153 * make sure we exit gracefully rather than endlessly redo
154 * the fault.
155 */
156
157 survive:
158 fault = handle_mm_fault(mm, vma, address, write);
159#ifdef DEBUG
160 printk("handle_mm_fault returns %d\n",fault);
161#endif
162 switch (fault) {
163 case 1:
164 current->min_flt++;
165 break;
166 case 2:
167 current->maj_flt++;
168 break;
169 case 0:
170 goto bus_err;
171 default:
172 goto out_of_memory;
173 }
174
175 up_read(&mm->mmap_sem);
176 return 0;
177
178/*
179 * We ran out of memory, or some other thing happened to us that made
180 * us unable to handle the page fault gracefully.
181 */
182out_of_memory:
183 up_read(&mm->mmap_sem);
184 if (current->pid == 1) {
185 yield();
186 down_read(&mm->mmap_sem);
187 goto survive;
188 }
189
190 printk("VM: killing process %s\n", current->comm);
191 if (user_mode(regs))
192 do_exit(SIGKILL);
193
194no_context:
195 current->thread.signo = SIGBUS;
196 current->thread.faddr = address;
197 return send_fault_sig(regs);
198
199bus_err:
200 current->thread.signo = SIGBUS;
201 current->thread.code = BUS_ADRERR;
202 current->thread.faddr = address;
203 goto send_sig;
204
205map_err:
206 current->thread.signo = SIGSEGV;
207 current->thread.code = SEGV_MAPERR;
208 current->thread.faddr = address;
209 goto send_sig;
210
211acc_err:
212 current->thread.signo = SIGSEGV;
213 current->thread.code = SEGV_ACCERR;
214 current->thread.faddr = address;
215
216send_sig:
217 up_read(&mm->mmap_sem);
218 return send_fault_sig(regs);
219}
diff --git a/arch/m68k/mm/hwtest.c b/arch/m68k/mm/hwtest.c
new file mode 100644
index 000000000000..2c7dde3c6430
--- /dev/null
+++ b/arch/m68k/mm/hwtest.c
@@ -0,0 +1,85 @@
1/* Tests for presence or absence of hardware registers.
2 * This code was originally in atari/config.c, but I noticed
3 * that it was also in drivers/nubus/nubus.c and I wanted to
4 * use it in hp300/config.c, so it seemed sensible to pull it
5 * out into its own file.
6 *
7 * The test is for use when trying to read a hardware register
8 * that isn't present would cause a bus error. We set up a
9 * temporary handler so that this doesn't kill the kernel.
10 *
11 * There is a test-by-reading and a test-by-writing; I present
12 * them here complete with the comments from the original atari
13 * config.c...
14 * -- PMM <pmaydell@chiark.greenend.org.uk>, 05/1998
15 */
16
17/* This function tests for the presence of an address, specially a
18 * hardware register address. It is called very early in the kernel
19 * initialization process, when the VBR register isn't set up yet. On
20 * an Atari, it still points to address 0, which is unmapped. So a bus
21 * error would cause another bus error while fetching the exception
22 * vector, and the CPU would do nothing at all. So we needed to set up
23 * a temporary VBR and a vector table for the duration of the test.
24 */
25
26#include <linux/module.h>
27
28int hwreg_present( volatile void *regp )
29{
30 int ret = 0;
31 long save_sp, save_vbr;
32 long tmp_vectors[3];
33
34 __asm__ __volatile__
35 ( "movec %/vbr,%2\n\t"
36 "movel #Lberr1,%4@(8)\n\t"
37 "movec %4,%/vbr\n\t"
38 "movel %/sp,%1\n\t"
39 "moveq #0,%0\n\t"
40 "tstb %3@\n\t"
41 "nop\n\t"
42 "moveq #1,%0\n"
43 "Lberr1:\n\t"
44 "movel %1,%/sp\n\t"
45 "movec %2,%/vbr"
46 : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
47 : "a" (regp), "a" (tmp_vectors)
48 );
49
50 return( ret );
51}
52EXPORT_SYMBOL(hwreg_present);
53
54/* Basically the same, but writes a value into a word register, protected
55 * by a bus error handler. Returns 1 if successful, 0 otherwise.
56 */
57
58int hwreg_write( volatile void *regp, unsigned short val )
59{
60 int ret;
61 long save_sp, save_vbr;
62 long tmp_vectors[3];
63
64 __asm__ __volatile__
65 ( "movec %/vbr,%2\n\t"
66 "movel #Lberr2,%4@(8)\n\t"
67 "movec %4,%/vbr\n\t"
68 "movel %/sp,%1\n\t"
69 "moveq #0,%0\n\t"
70 "movew %5,%3@\n\t"
71 "nop \n\t" /* If this nop isn't present, 'ret' may already be
72 * loaded with 1 at the time the bus error
73 * happens! */
74 "moveq #1,%0\n"
75 "Lberr2:\n\t"
76 "movel %1,%/sp\n\t"
77 "movec %2,%/vbr"
78 : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
79 : "a" (regp), "a" (tmp_vectors), "g" (val)
80 );
81
82 return( ret );
83}
84EXPORT_SYMBOL(hwreg_write);
85
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
new file mode 100644
index 000000000000..c45beb955943
--- /dev/null
+++ b/arch/m68k/mm/init.c
@@ -0,0 +1,147 @@
1/*
2 * linux/arch/m68k/mm/init.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 *
6 * Contains common initialization routines, specific init code moved
7 * to motorola.c and sun3mmu.c
8 */
9
10#include <linux/config.h>
11#include <linux/signal.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/swap.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/types.h>
18#include <linux/init.h>
19#include <linux/bootmem.h>
20
21#include <asm/setup.h>
22#include <asm/uaccess.h>
23#include <asm/page.h>
24#include <asm/pgalloc.h>
25#include <asm/system.h>
26#include <asm/machdep.h>
27#include <asm/io.h>
28#ifdef CONFIG_ATARI
29#include <asm/atari_stram.h>
30#endif
31#include <asm/tlb.h>
32
33DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
34
35/*
36 * ZERO_PAGE is a special page that is used for zero-initialized
37 * data and COW.
38 */
39
40void *empty_zero_page;
41
42void show_mem(void)
43{
44 unsigned long i;
45 int free = 0, total = 0, reserved = 0, shared = 0;
46 int cached = 0;
47
48 printk("\nMem-info:\n");
49 show_free_areas();
50 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
51 i = max_mapnr;
52 while (i-- > 0) {
53 total++;
54 if (PageReserved(mem_map+i))
55 reserved++;
56 else if (PageSwapCache(mem_map+i))
57 cached++;
58 else if (!page_count(mem_map+i))
59 free++;
60 else
61 shared += page_count(mem_map+i) - 1;
62 }
63 printk("%d pages of RAM\n",total);
64 printk("%d free pages\n",free);
65 printk("%d reserved pages\n",reserved);
66 printk("%d pages shared\n",shared);
67 printk("%d pages swap cached\n",cached);
68}
69
70extern void init_pointer_table(unsigned long ptable);
71
72/* References to section boundaries */
73
74extern char _text, _etext, _edata, __bss_start, _end;
75extern char __init_begin, __init_end;
76
77extern pmd_t *zero_pgtable;
78
79void __init mem_init(void)
80{
81 int codepages = 0;
82 int datapages = 0;
83 int initpages = 0;
84 unsigned long tmp;
85#ifndef CONFIG_SUN3
86 int i;
87#endif
88
89 max_mapnr = num_physpages = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT);
90
91#ifdef CONFIG_ATARI
92 if (MACH_IS_ATARI)
93 atari_stram_mem_init_hook();
94#endif
95
96 /* this will put all memory onto the freelists */
97 totalram_pages = free_all_bootmem();
98
99 for (tmp = PAGE_OFFSET ; tmp < (unsigned long)high_memory; tmp += PAGE_SIZE) {
100 if (PageReserved(virt_to_page(tmp))) {
101 if (tmp >= (unsigned long)&_text
102 && tmp < (unsigned long)&_etext)
103 codepages++;
104 else if (tmp >= (unsigned long) &__init_begin
105 && tmp < (unsigned long) &__init_end)
106 initpages++;
107 else
108 datapages++;
109 continue;
110 }
111 }
112
113#ifndef CONFIG_SUN3
114 /* insert pointer tables allocated so far into the tablelist */
115 init_pointer_table((unsigned long)kernel_pg_dir);
116 for (i = 0; i < PTRS_PER_PGD; i++) {
117 if (pgd_present(kernel_pg_dir[i]))
118 init_pointer_table(__pgd_page(kernel_pg_dir[i]));
119 }
120
121 /* insert also pointer table that we used to unmap the zero page */
122 if (zero_pgtable)
123 init_pointer_table((unsigned long)zero_pgtable);
124#endif
125
126 printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
127 (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
128 max_mapnr << (PAGE_SHIFT-10),
129 codepages << (PAGE_SHIFT-10),
130 datapages << (PAGE_SHIFT-10),
131 initpages << (PAGE_SHIFT-10));
132}
133
134#ifdef CONFIG_BLK_DEV_INITRD
135void free_initrd_mem(unsigned long start, unsigned long end)
136{
137 int pages = 0;
138 for (; start < end; start += PAGE_SIZE) {
139 ClearPageReserved(virt_to_page(start));
140 set_page_count(virt_to_page(start), 1);
141 free_page(start);
142 totalram_pages++;
143 pages++;
144 }
145 printk ("Freeing initrd memory: %dk freed\n", pages);
146}
147#endif
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
new file mode 100644
index 000000000000..5dcb3fa35ea9
--- /dev/null
+++ b/arch/m68k/mm/kmap.c
@@ -0,0 +1,361 @@
1/*
2 * linux/arch/m68k/mm/kmap.c
3 *
4 * Copyright (C) 1997 Roman Hodek
5 *
6 * 10/01/99 cleaned up the code and changing to the same interface
7 * used by other architectures /Roman Zippel
8 */
9
10#include <linux/config.h>
11#include <linux/mm.h>
12#include <linux/kernel.h>
13#include <linux/string.h>
14#include <linux/types.h>
15#include <linux/slab.h>
16#include <linux/vmalloc.h>
17
18#include <asm/setup.h>
19#include <asm/segment.h>
20#include <asm/page.h>
21#include <asm/pgalloc.h>
22#include <asm/io.h>
23#include <asm/system.h>
24
25#undef DEBUG
26
27#define PTRTREESIZE (256*1024)
28
29/*
30 * For 040/060 we can use the virtual memory area like other architectures,
31 * but for 020/030 we want to use early termination page descriptor and we
32 * can't mix this with normal page descriptors, so we have to copy that code
33 * (mm/vmalloc.c) and return appriorate aligned addresses.
34 */
35
36#ifdef CPU_M68040_OR_M68060_ONLY
37
38#define IO_SIZE PAGE_SIZE
39
40static inline struct vm_struct *get_io_area(unsigned long size)
41{
42 return get_vm_area(size, VM_IOREMAP);
43}
44
45
46static inline void free_io_area(void *addr)
47{
48 vfree((void *)(PAGE_MASK & (unsigned long)addr));
49}
50
51#else
52
53#define IO_SIZE (256*1024)
54
55static struct vm_struct *iolist;
56
57static struct vm_struct *get_io_area(unsigned long size)
58{
59 unsigned long addr;
60 struct vm_struct **p, *tmp, *area;
61
62 area = (struct vm_struct *)kmalloc(sizeof(*area), GFP_KERNEL);
63 if (!area)
64 return NULL;
65 addr = KMAP_START;
66 for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
67 if (size + addr < (unsigned long)tmp->addr)
68 break;
69 if (addr > KMAP_END-size)
70 return NULL;
71 addr = tmp->size + (unsigned long)tmp->addr;
72 }
73 area->addr = (void *)addr;
74 area->size = size + IO_SIZE;
75 area->next = *p;
76 *p = area;
77 return area;
78}
79
80static inline void free_io_area(void *addr)
81{
82 struct vm_struct **p, *tmp;
83
84 if (!addr)
85 return;
86 addr = (void *)((unsigned long)addr & -IO_SIZE);
87 for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
88 if (tmp->addr == addr) {
89 *p = tmp->next;
90 __iounmap(tmp->addr, tmp->size);
91 kfree(tmp);
92 return;
93 }
94 }
95}
96
97#endif
98
99/*
100 * Map some physical address range into the kernel address space. The
101 * code is copied and adapted from map_chunk().
102 */
103/* Rewritten by Andreas Schwab to remove all races. */
104
105void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
106{
107 struct vm_struct *area;
108 unsigned long virtaddr, retaddr;
109 long offset;
110 pgd_t *pgd_dir;
111 pmd_t *pmd_dir;
112 pte_t *pte_dir;
113
114 /*
115 * Don't allow mappings that wrap..
116 */
117 if (!size || size > physaddr + size)
118 return NULL;
119
120#ifdef CONFIG_AMIGA
121 if (MACH_IS_AMIGA) {
122 if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
123 && (cacheflag == IOMAP_NOCACHE_SER))
124 return (void *)physaddr;
125 }
126#endif
127
128#ifdef DEBUG
129 printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
130#endif
131 /*
132 * Mappings have to be aligned
133 */
134 offset = physaddr & (IO_SIZE - 1);
135 physaddr &= -IO_SIZE;
136 size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
137
138 /*
139 * Ok, go for it..
140 */
141 area = get_io_area(size);
142 if (!area)
143 return NULL;
144
145 virtaddr = (unsigned long)area->addr;
146 retaddr = virtaddr + offset;
147#ifdef DEBUG
148 printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
149#endif
150
151 /*
152 * add cache and table flags to physical address
153 */
154 if (CPU_IS_040_OR_060) {
155 physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
156 _PAGE_ACCESSED | _PAGE_DIRTY);
157 switch (cacheflag) {
158 case IOMAP_FULL_CACHING:
159 physaddr |= _PAGE_CACHE040;
160 break;
161 case IOMAP_NOCACHE_SER:
162 default:
163 physaddr |= _PAGE_NOCACHE_S;
164 break;
165 case IOMAP_NOCACHE_NONSER:
166 physaddr |= _PAGE_NOCACHE;
167 break;
168 case IOMAP_WRITETHROUGH:
169 physaddr |= _PAGE_CACHE040W;
170 break;
171 }
172 } else {
173 physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
174 switch (cacheflag) {
175 case IOMAP_NOCACHE_SER:
176 case IOMAP_NOCACHE_NONSER:
177 default:
178 physaddr |= _PAGE_NOCACHE030;
179 break;
180 case IOMAP_FULL_CACHING:
181 case IOMAP_WRITETHROUGH:
182 break;
183 }
184 }
185
186 while ((long)size > 0) {
187#ifdef DEBUG
188 if (!(virtaddr & (PTRTREESIZE-1)))
189 printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
190#endif
191 pgd_dir = pgd_offset_k(virtaddr);
192 pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
193 if (!pmd_dir) {
194 printk("ioremap: no mem for pmd_dir\n");
195 return NULL;
196 }
197
198 if (CPU_IS_020_OR_030) {
199 pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
200 physaddr += PTRTREESIZE;
201 virtaddr += PTRTREESIZE;
202 size -= PTRTREESIZE;
203 } else {
204 pte_dir = pte_alloc_kernel(&init_mm, pmd_dir, virtaddr);
205 if (!pte_dir) {
206 printk("ioremap: no mem for pte_dir\n");
207 return NULL;
208 }
209
210 pte_val(*pte_dir) = physaddr;
211 virtaddr += PAGE_SIZE;
212 physaddr += PAGE_SIZE;
213 size -= PAGE_SIZE;
214 }
215 }
216#ifdef DEBUG
217 printk("\n");
218#endif
219 flush_tlb_all();
220
221 return (void *)retaddr;
222}
223
224/*
225 * Unmap a ioremap()ed region again
226 */
227void iounmap(void *addr)
228{
229#ifdef CONFIG_AMIGA
230 if ((!MACH_IS_AMIGA) ||
231 (((unsigned long)addr < 0x40000000) ||
232 ((unsigned long)addr > 0x60000000)))
233 free_io_area(addr);
234#else
235 free_io_area(addr);
236#endif
237}
238
239/*
240 * __iounmap unmaps nearly everything, so be careful
241 * it doesn't free currently pointer/page tables anymore but it
242 * wans't used anyway and might be added later.
243 */
244void __iounmap(void *addr, unsigned long size)
245{
246 unsigned long virtaddr = (unsigned long)addr;
247 pgd_t *pgd_dir;
248 pmd_t *pmd_dir;
249 pte_t *pte_dir;
250
251 while ((long)size > 0) {
252 pgd_dir = pgd_offset_k(virtaddr);
253 if (pgd_bad(*pgd_dir)) {
254 printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
255 pgd_clear(pgd_dir);
256 return;
257 }
258 pmd_dir = pmd_offset(pgd_dir, virtaddr);
259
260 if (CPU_IS_020_OR_030) {
261 int pmd_off = (virtaddr/PTRTREESIZE) & 15;
262
263 if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
264 pmd_dir->pmd[pmd_off] = 0;
265 virtaddr += PTRTREESIZE;
266 size -= PTRTREESIZE;
267 continue;
268 }
269 }
270
271 if (pmd_bad(*pmd_dir)) {
272 printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
273 pmd_clear(pmd_dir);
274 return;
275 }
276 pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
277
278 pte_val(*pte_dir) = 0;
279 virtaddr += PAGE_SIZE;
280 size -= PAGE_SIZE;
281 }
282
283 flush_tlb_all();
284}
285
286/*
287 * Set new cache mode for some kernel address space.
288 * The caller must push data for that range itself, if such data may already
289 * be in the cache.
290 */
291void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
292{
293 unsigned long virtaddr = (unsigned long)addr;
294 pgd_t *pgd_dir;
295 pmd_t *pmd_dir;
296 pte_t *pte_dir;
297
298 if (CPU_IS_040_OR_060) {
299 switch (cmode) {
300 case IOMAP_FULL_CACHING:
301 cmode = _PAGE_CACHE040;
302 break;
303 case IOMAP_NOCACHE_SER:
304 default:
305 cmode = _PAGE_NOCACHE_S;
306 break;
307 case IOMAP_NOCACHE_NONSER:
308 cmode = _PAGE_NOCACHE;
309 break;
310 case IOMAP_WRITETHROUGH:
311 cmode = _PAGE_CACHE040W;
312 break;
313 }
314 } else {
315 switch (cmode) {
316 case IOMAP_NOCACHE_SER:
317 case IOMAP_NOCACHE_NONSER:
318 default:
319 cmode = _PAGE_NOCACHE030;
320 break;
321 case IOMAP_FULL_CACHING:
322 case IOMAP_WRITETHROUGH:
323 cmode = 0;
324 }
325 }
326
327 while ((long)size > 0) {
328 pgd_dir = pgd_offset_k(virtaddr);
329 if (pgd_bad(*pgd_dir)) {
330 printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
331 pgd_clear(pgd_dir);
332 return;
333 }
334 pmd_dir = pmd_offset(pgd_dir, virtaddr);
335
336 if (CPU_IS_020_OR_030) {
337 int pmd_off = (virtaddr/PTRTREESIZE) & 15;
338
339 if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
340 pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
341 _CACHEMASK040) | cmode;
342 virtaddr += PTRTREESIZE;
343 size -= PTRTREESIZE;
344 continue;
345 }
346 }
347
348 if (pmd_bad(*pmd_dir)) {
349 printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
350 pmd_clear(pmd_dir);
351 return;
352 }
353 pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
354
355 pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
356 virtaddr += PAGE_SIZE;
357 size -= PAGE_SIZE;
358 }
359
360 flush_tlb_all();
361}
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
new file mode 100644
index 000000000000..1453a6013721
--- /dev/null
+++ b/arch/m68k/mm/memory.c
@@ -0,0 +1,471 @@
1/*
2 * linux/arch/m68k/mm/memory.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 */
6
7#include <linux/config.h>
8#include <linux/mm.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/types.h>
12#include <linux/slab.h>
13#include <linux/init.h>
14#include <linux/pagemap.h>
15
16#include <asm/setup.h>
17#include <asm/segment.h>
18#include <asm/page.h>
19#include <asm/pgalloc.h>
20#include <asm/system.h>
21#include <asm/traps.h>
22#include <asm/machdep.h>
23
24
25/* ++andreas: {get,free}_pointer_table rewritten to use unused fields from
26 struct page instead of separately kmalloced struct. Stolen from
27 arch/sparc/mm/srmmu.c ... */
28
29typedef struct list_head ptable_desc;
30static LIST_HEAD(ptable_list);
31
32#define PD_PTABLE(page) ((ptable_desc *)&(virt_to_page(page)->lru))
33#define PD_PAGE(ptable) (list_entry(ptable, struct page, lru))
34#define PD_MARKBITS(dp) (*(unsigned char *)&PD_PAGE(dp)->index)
35
36#define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t))
37
38void __init init_pointer_table(unsigned long ptable)
39{
40 ptable_desc *dp;
41 unsigned long page = ptable & PAGE_MASK;
42 unsigned char mask = 1 << ((ptable - page)/PTABLE_SIZE);
43
44 dp = PD_PTABLE(page);
45 if (!(PD_MARKBITS(dp) & mask)) {
46 PD_MARKBITS(dp) = 0xff;
47 list_add(dp, &ptable_list);
48 }
49
50 PD_MARKBITS(dp) &= ~mask;
51#ifdef DEBUG
52 printk("init_pointer_table: %lx, %x\n", ptable, PD_MARKBITS(dp));
53#endif
54
55 /* unreserve the page so it's possible to free that page */
56 PD_PAGE(dp)->flags &= ~(1 << PG_reserved);
57 set_page_count(PD_PAGE(dp), 1);
58
59 return;
60}
61
62pmd_t *get_pointer_table (void)
63{
64 ptable_desc *dp = ptable_list.next;
65 unsigned char mask = PD_MARKBITS (dp);
66 unsigned char tmp;
67 unsigned int off;
68
69 /*
70 * For a pointer table for a user process address space, a
71 * table is taken from a page allocated for the purpose. Each
72 * page can hold 8 pointer tables. The page is remapped in
73 * virtual address space to be noncacheable.
74 */
75 if (mask == 0) {
76 void *page;
77 ptable_desc *new;
78
79 if (!(page = (void *)get_zeroed_page(GFP_KERNEL)))
80 return NULL;
81
82 flush_tlb_kernel_page(page);
83 nocache_page(page);
84
85 new = PD_PTABLE(page);
86 PD_MARKBITS(new) = 0xfe;
87 list_add_tail(new, dp);
88
89 return (pmd_t *)page;
90 }
91
92 for (tmp = 1, off = 0; (mask & tmp) == 0; tmp <<= 1, off += PTABLE_SIZE)
93 ;
94 PD_MARKBITS(dp) = mask & ~tmp;
95 if (!PD_MARKBITS(dp)) {
96 /* move to end of list */
97 list_del(dp);
98 list_add_tail(dp, &ptable_list);
99 }
100 return (pmd_t *) (page_address(PD_PAGE(dp)) + off);
101}
102
103int free_pointer_table (pmd_t *ptable)
104{
105 ptable_desc *dp;
106 unsigned long page = (unsigned long)ptable & PAGE_MASK;
107 unsigned char mask = 1 << (((unsigned long)ptable - page)/PTABLE_SIZE);
108
109 dp = PD_PTABLE(page);
110 if (PD_MARKBITS (dp) & mask)
111 panic ("table already free!");
112
113 PD_MARKBITS (dp) |= mask;
114
115 if (PD_MARKBITS(dp) == 0xff) {
116 /* all tables in page are free, free page */
117 list_del(dp);
118 cache_page((void *)page);
119 free_page (page);
120 return 1;
121 } else if (ptable_list.next != dp) {
122 /*
123 * move this descriptor to the front of the list, since
124 * it has one or more free tables.
125 */
126 list_del(dp);
127 list_add(dp, &ptable_list);
128 }
129 return 0;
130}
131
132#ifdef DEBUG_INVALID_PTOV
133int mm_inv_cnt = 5;
134#endif
135
136#ifndef CONFIG_SINGLE_MEMORY_CHUNK
137/*
138 * The following two routines map from a physical address to a kernel
139 * virtual address and vice versa.
140 */
141unsigned long mm_vtop(unsigned long vaddr)
142{
143 int i=0;
144 unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET;
145
146 do {
147 if (voff < m68k_memory[i].size) {
148#ifdef DEBUGPV
149 printk ("VTOP(%p)=%lx\n", vaddr,
150 m68k_memory[i].addr + voff);
151#endif
152 return m68k_memory[i].addr + voff;
153 }
154 voff -= m68k_memory[i].size;
155 } while (++i < m68k_num_memory);
156
157 /* As a special case allow `__pa(high_memory)'. */
158 if (voff == 0)
159 return m68k_memory[i-1].addr + m68k_memory[i-1].size;
160
161 return -1;
162}
163#endif
164
165#ifndef CONFIG_SINGLE_MEMORY_CHUNK
166unsigned long mm_ptov (unsigned long paddr)
167{
168 int i = 0;
169 unsigned long poff, voff = PAGE_OFFSET;
170
171 do {
172 poff = paddr - m68k_memory[i].addr;
173 if (poff < m68k_memory[i].size) {
174#ifdef DEBUGPV
175 printk ("PTOV(%lx)=%lx\n", paddr, poff + voff);
176#endif
177 return poff + voff;
178 }
179 voff += m68k_memory[i].size;
180 } while (++i < m68k_num_memory);
181
182#ifdef DEBUG_INVALID_PTOV
183 if (mm_inv_cnt > 0) {
184 mm_inv_cnt--;
185 printk("Invalid use of phys_to_virt(0x%lx) at 0x%p!\n",
186 paddr, __builtin_return_address(0));
187 }
188#endif
189 return -1;
190}
191#endif
192
193/* invalidate page in both caches */
194static inline void clear040(unsigned long paddr)
195{
196 asm volatile (
197 "nop\n\t"
198 ".chip 68040\n\t"
199 "cinvp %%bc,(%0)\n\t"
200 ".chip 68k"
201 : : "a" (paddr));
202}
203
204/* invalidate page in i-cache */
205static inline void cleari040(unsigned long paddr)
206{
207 asm volatile (
208 "nop\n\t"
209 ".chip 68040\n\t"
210 "cinvp %%ic,(%0)\n\t"
211 ".chip 68k"
212 : : "a" (paddr));
213}
214
215/* push page in both caches */
216/* RZ: cpush %bc DOES invalidate %ic, regardless of DPI */
217static inline void push040(unsigned long paddr)
218{
219 asm volatile (
220 "nop\n\t"
221 ".chip 68040\n\t"
222 "cpushp %%bc,(%0)\n\t"
223 ".chip 68k"
224 : : "a" (paddr));
225}
226
227/* push and invalidate page in both caches, must disable ints
228 * to avoid invalidating valid data */
229static inline void pushcl040(unsigned long paddr)
230{
231 unsigned long flags;
232
233 local_irq_save(flags);
234 push040(paddr);
235 if (CPU_IS_060)
236 clear040(paddr);
237 local_irq_restore(flags);
238}
239
240/*
241 * 040: Hit every page containing an address in the range paddr..paddr+len-1.
242 * (Low order bits of the ea of a CINVP/CPUSHP are "don't care"s).
243 * Hit every page until there is a page or less to go. Hit the next page,
244 * and the one after that if the range hits it.
245 */
246/* ++roman: A little bit more care is required here: The CINVP instruction
247 * invalidates cache entries WITHOUT WRITING DIRTY DATA BACK! So the beginning
248 * and the end of the region must be treated differently if they are not
249 * exactly at the beginning or end of a page boundary. Else, maybe too much
250 * data becomes invalidated and thus lost forever. CPUSHP does what we need:
251 * it invalidates the page after pushing dirty data to memory. (Thanks to Jes
252 * for discovering the problem!)
253 */
254/* ... but on the '060, CPUSH doesn't invalidate (for us, since we have set
255 * the DPI bit in the CACR; would it cause problems with temporarily changing
256 * this?). So we have to push first and then additionally to invalidate.
257 */
258
259
260/*
261 * cache_clear() semantics: Clear any cache entries for the area in question,
262 * without writing back dirty entries first. This is useful if the data will
263 * be overwritten anyway, e.g. by DMA to memory. The range is defined by a
264 * _physical_ address.
265 */
266
267void cache_clear (unsigned long paddr, int len)
268{
269 if (CPU_IS_040_OR_060) {
270 int tmp;
271
272 /*
273 * We need special treatment for the first page, in case it
274 * is not page-aligned. Page align the addresses to work
275 * around bug I17 in the 68060.
276 */
277 if ((tmp = -paddr & (PAGE_SIZE - 1))) {
278 pushcl040(paddr & PAGE_MASK);
279 if ((len -= tmp) <= 0)
280 return;
281 paddr += tmp;
282 }
283 tmp = PAGE_SIZE;
284 paddr &= PAGE_MASK;
285 while ((len -= tmp) >= 0) {
286 clear040(paddr);
287 paddr += tmp;
288 }
289 if ((len += tmp))
290 /* a page boundary gets crossed at the end */
291 pushcl040(paddr);
292 }
293 else /* 68030 or 68020 */
294 asm volatile ("movec %/cacr,%/d0\n\t"
295 "oriw %0,%/d0\n\t"
296 "movec %/d0,%/cacr"
297 : : "i" (FLUSH_I_AND_D)
298 : "d0");
299#ifdef CONFIG_M68K_L2_CACHE
300 if(mach_l2_flush)
301 mach_l2_flush(0);
302#endif
303}
304
305
306/*
307 * cache_push() semantics: Write back any dirty cache data in the given area,
308 * and invalidate the range in the instruction cache. It needs not (but may)
309 * invalidate those entries also in the data cache. The range is defined by a
310 * _physical_ address.
311 */
312
313void cache_push (unsigned long paddr, int len)
314{
315 if (CPU_IS_040_OR_060) {
316 int tmp = PAGE_SIZE;
317
318 /*
319 * on 68040 or 68060, push cache lines for pages in the range;
320 * on the '040 this also invalidates the pushed lines, but not on
321 * the '060!
322 */
323 len += paddr & (PAGE_SIZE - 1);
324
325 /*
326 * Work around bug I17 in the 68060 affecting some instruction
327 * lines not being invalidated properly.
328 */
329 paddr &= PAGE_MASK;
330
331 do {
332 push040(paddr);
333 paddr += tmp;
334 } while ((len -= tmp) > 0);
335 }
336 /*
337 * 68030/68020 have no writeback cache. On the other hand,
338 * cache_push is actually a superset of cache_clear (the lines
339 * get written back and invalidated), so we should make sure
340 * to perform the corresponding actions. After all, this is getting
341 * called in places where we've just loaded code, or whatever, so
342 * flushing the icache is appropriate; flushing the dcache shouldn't
343 * be required.
344 */
345 else /* 68030 or 68020 */
346 asm volatile ("movec %/cacr,%/d0\n\t"
347 "oriw %0,%/d0\n\t"
348 "movec %/d0,%/cacr"
349 : : "i" (FLUSH_I)
350 : "d0");
351#ifdef CONFIG_M68K_L2_CACHE
352 if(mach_l2_flush)
353 mach_l2_flush(1);
354#endif
355}
356
357static unsigned long virt_to_phys_slow(unsigned long vaddr)
358{
359 if (CPU_IS_060) {
360 mm_segment_t fs = get_fs();
361 unsigned long paddr;
362
363 set_fs(get_ds());
364
365 /* The PLPAR instruction causes an access error if the translation
366 * is not possible. To catch this we use the same exception mechanism
367 * as for user space accesses in <asm/uaccess.h>. */
368 asm volatile (".chip 68060\n"
369 "1: plpar (%0)\n"
370 ".chip 68k\n"
371 "2:\n"
372 ".section .fixup,\"ax\"\n"
373 " .even\n"
374 "3: sub.l %0,%0\n"
375 " jra 2b\n"
376 ".previous\n"
377 ".section __ex_table,\"a\"\n"
378 " .align 4\n"
379 " .long 1b,3b\n"
380 ".previous"
381 : "=a" (paddr)
382 : "0" (vaddr));
383 set_fs(fs);
384 return paddr;
385 } else if (CPU_IS_040) {
386 mm_segment_t fs = get_fs();
387 unsigned long mmusr;
388
389 set_fs(get_ds());
390
391 asm volatile (".chip 68040\n\t"
392 "ptestr (%1)\n\t"
393 "movec %%mmusr, %0\n\t"
394 ".chip 68k"
395 : "=r" (mmusr)
396 : "a" (vaddr));
397 set_fs(fs);
398
399 if (mmusr & MMU_R_040)
400 return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK);
401 } else {
402 unsigned short mmusr;
403 unsigned long *descaddr;
404
405 asm volatile ("ptestr #5,%2@,#7,%0\n\t"
406 "pmove %%psr,%1@"
407 : "=a&" (descaddr)
408 : "a" (&mmusr), "a" (vaddr));
409 if (mmusr & (MMU_I|MMU_B|MMU_L))
410 return 0;
411 descaddr = phys_to_virt((unsigned long)descaddr);
412 switch (mmusr & MMU_NUM) {
413 case 1:
414 return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff);
415 case 2:
416 return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff);
417 case 3:
418 return (*descaddr & PAGE_MASK) | (vaddr & ~PAGE_MASK);
419 }
420 }
421 return 0;
422}
423
424/* Push n pages at kernel virtual address and clear the icache */
425/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
426void flush_icache_range(unsigned long address, unsigned long endaddr)
427{
428 if (CPU_IS_040_OR_060) {
429 address &= PAGE_MASK;
430
431 if (address >= PAGE_OFFSET && address < (unsigned long)high_memory) {
432 do {
433 asm volatile ("nop\n\t"
434 ".chip 68040\n\t"
435 "cpushp %%bc,(%0)\n\t"
436 ".chip 68k"
437 : : "a" (virt_to_phys((void *)address)));
438 address += PAGE_SIZE;
439 } while (address < endaddr);
440 } else {
441 do {
442 asm volatile ("nop\n\t"
443 ".chip 68040\n\t"
444 "cpushp %%bc,(%0)\n\t"
445 ".chip 68k"
446 : : "a" (virt_to_phys_slow(address)));
447 address += PAGE_SIZE;
448 } while (address < endaddr);
449 }
450 } else {
451 unsigned long tmp;
452 asm volatile ("movec %%cacr,%0\n\t"
453 "orw %1,%0\n\t"
454 "movec %0,%%cacr"
455 : "=&d" (tmp)
456 : "di" (FLUSH_I));
457 }
458}
459
460
461#ifndef CONFIG_SINGLE_MEMORY_CHUNK
462int mm_end_of_chunk (unsigned long addr, int len)
463{
464 int i;
465
466 for (i = 0; i < m68k_num_memory; i++)
467 if (m68k_memory[i].addr + m68k_memory[i].size == addr + len)
468 return 1;
469 return 0;
470}
471#endif
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
new file mode 100644
index 000000000000..d855fec26317
--- /dev/null
+++ b/arch/m68k/mm/motorola.c
@@ -0,0 +1,285 @@
1/*
2 * linux/arch/m68k/motorola.c
3 *
4 * Routines specific to the Motorola MMU, originally from:
5 * linux/arch/m68k/init.c
6 * which are Copyright (C) 1995 Hamish Macdonald
7 *
8 * Moved 8/20/1999 Sam Creasey
9 */
10
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/signal.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/swap.h>
17#include <linux/kernel.h>
18#include <linux/string.h>
19#include <linux/types.h>
20#include <linux/init.h>
21#include <linux/bootmem.h>
22
23#include <asm/setup.h>
24#include <asm/uaccess.h>
25#include <asm/page.h>
26#include <asm/pgalloc.h>
27#include <asm/system.h>
28#include <asm/machdep.h>
29#include <asm/io.h>
30#include <asm/dma.h>
31#ifdef CONFIG_ATARI
32#include <asm/atari_stram.h>
33#endif
34
35#undef DEBUG
36
37#ifndef mm_cachebits
38/*
39 * Bits to add to page descriptors for "normal" caching mode.
40 * For 68020/030 this is 0.
41 * For 68040, this is _PAGE_CACHE040 (cachable, copyback)
42 */
43unsigned long mm_cachebits;
44EXPORT_SYMBOL(mm_cachebits);
45#endif
46
47static pte_t * __init kernel_page_table(void)
48{
49 pte_t *ptablep;
50
51 ptablep = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
52
53 clear_page(ptablep);
54 __flush_page_to_ram(ptablep);
55 flush_tlb_kernel_page(ptablep);
56 nocache_page(ptablep);
57
58 return ptablep;
59}
60
61static pmd_t *last_pgtable __initdata = NULL;
62pmd_t *zero_pgtable __initdata = NULL;
63
64static pmd_t * __init kernel_ptr_table(void)
65{
66 if (!last_pgtable) {
67 unsigned long pmd, last;
68 int i;
69
70 /* Find the last ptr table that was used in head.S and
71 * reuse the remaining space in that page for further
72 * ptr tables.
73 */
74 last = (unsigned long)kernel_pg_dir;
75 for (i = 0; i < PTRS_PER_PGD; i++) {
76 if (!pgd_present(kernel_pg_dir[i]))
77 continue;
78 pmd = __pgd_page(kernel_pg_dir[i]);
79 if (pmd > last)
80 last = pmd;
81 }
82
83 last_pgtable = (pmd_t *)last;
84#ifdef DEBUG
85 printk("kernel_ptr_init: %p\n", last_pgtable);
86#endif
87 }
88
89 last_pgtable += PTRS_PER_PMD;
90 if (((unsigned long)last_pgtable & ~PAGE_MASK) == 0) {
91 last_pgtable = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
92
93 clear_page(last_pgtable);
94 __flush_page_to_ram(last_pgtable);
95 flush_tlb_kernel_page(last_pgtable);
96 nocache_page(last_pgtable);
97 }
98
99 return last_pgtable;
100}
101
102static unsigned long __init
103map_chunk (unsigned long addr, long size)
104{
105#define PTRTREESIZE (256*1024)
106#define ROOTTREESIZE (32*1024*1024)
107 static unsigned long virtaddr = PAGE_OFFSET;
108 unsigned long physaddr;
109 pgd_t *pgd_dir;
110 pmd_t *pmd_dir;
111 pte_t *pte_dir;
112
113 physaddr = (addr | m68k_supervisor_cachemode |
114 _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
115 if (CPU_IS_040_OR_060)
116 physaddr |= _PAGE_GLOBAL040;
117
118 while (size > 0) {
119#ifdef DEBUG
120 if (!(virtaddr & (PTRTREESIZE-1)))
121 printk ("\npa=%#lx va=%#lx ", physaddr & PAGE_MASK,
122 virtaddr);
123#endif
124 pgd_dir = pgd_offset_k(virtaddr);
125 if (virtaddr && CPU_IS_020_OR_030) {
126 if (!(virtaddr & (ROOTTREESIZE-1)) &&
127 size >= ROOTTREESIZE) {
128#ifdef DEBUG
129 printk ("[very early term]");
130#endif
131 pgd_val(*pgd_dir) = physaddr;
132 size -= ROOTTREESIZE;
133 virtaddr += ROOTTREESIZE;
134 physaddr += ROOTTREESIZE;
135 continue;
136 }
137 }
138 if (!pgd_present(*pgd_dir)) {
139 pmd_dir = kernel_ptr_table();
140#ifdef DEBUG
141 printk ("[new pointer %p]", pmd_dir);
142#endif
143 pgd_set(pgd_dir, pmd_dir);
144 } else
145 pmd_dir = pmd_offset(pgd_dir, virtaddr);
146
147 if (CPU_IS_020_OR_030) {
148 if (virtaddr) {
149#ifdef DEBUG
150 printk ("[early term]");
151#endif
152 pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
153 physaddr += PTRTREESIZE;
154 } else {
155 int i;
156#ifdef DEBUG
157 printk ("[zero map]");
158#endif
159 zero_pgtable = kernel_ptr_table();
160 pte_dir = (pte_t *)zero_pgtable;
161 pmd_dir->pmd[0] = virt_to_phys(pte_dir) |
162 _PAGE_TABLE | _PAGE_ACCESSED;
163 pte_val(*pte_dir++) = 0;
164 physaddr += PAGE_SIZE;
165 for (i = 1; i < 64; physaddr += PAGE_SIZE, i++)
166 pte_val(*pte_dir++) = physaddr;
167 }
168 size -= PTRTREESIZE;
169 virtaddr += PTRTREESIZE;
170 } else {
171 if (!pmd_present(*pmd_dir)) {
172#ifdef DEBUG
173 printk ("[new table]");
174#endif
175 pte_dir = kernel_page_table();
176 pmd_set(pmd_dir, pte_dir);
177 }
178 pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
179
180 if (virtaddr) {
181 if (!pte_present(*pte_dir))
182 pte_val(*pte_dir) = physaddr;
183 } else
184 pte_val(*pte_dir) = 0;
185 size -= PAGE_SIZE;
186 virtaddr += PAGE_SIZE;
187 physaddr += PAGE_SIZE;
188 }
189
190 }
191#ifdef DEBUG
192 printk("\n");
193#endif
194
195 return virtaddr;
196}
197
198/*
199 * paging_init() continues the virtual memory environment setup which
200 * was begun by the code in arch/head.S.
201 */
202void __init paging_init(void)
203{
204 int chunk;
205 unsigned long mem_avail = 0;
206 unsigned long zones_size[3] = { 0, };
207
208#ifdef DEBUG
209 {
210 extern unsigned long availmem;
211 printk ("start of paging_init (%p, %lx, %lx, %lx)\n",
212 kernel_pg_dir, availmem, start_mem, end_mem);
213 }
214#endif
215
216 /* Fix the cache mode in the page descriptors for the 680[46]0. */
217 if (CPU_IS_040_OR_060) {
218 int i;
219#ifndef mm_cachebits
220 mm_cachebits = _PAGE_CACHE040;
221#endif
222 for (i = 0; i < 16; i++)
223 pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
224 }
225
226 /*
227 * Map the physical memory available into the kernel virtual
228 * address space. It may allocate some memory for page
229 * tables and thus modify availmem.
230 */
231
232 for (chunk = 0; chunk < m68k_num_memory; chunk++) {
233 mem_avail = map_chunk (m68k_memory[chunk].addr,
234 m68k_memory[chunk].size);
235
236 }
237
238 flush_tlb_all();
239#ifdef DEBUG
240 printk ("memory available is %ldKB\n", mem_avail >> 10);
241 printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
242 start_mem, end_mem);
243#endif
244
245 /*
246 * initialize the bad page table and bad page to point
247 * to a couple of allocated pages
248 */
249 empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
250 memset(empty_zero_page, 0, PAGE_SIZE);
251
252 /*
253 * Set up SFC/DFC registers
254 */
255 set_fs(KERNEL_DS);
256
257#ifdef DEBUG
258 printk ("before free_area_init\n");
259#endif
260 zones_size[0] = (mach_max_dma_address < (unsigned long)high_memory ?
261 (mach_max_dma_address+1) : (unsigned long)high_memory);
262 zones_size[1] = (unsigned long)high_memory - zones_size[0];
263
264 zones_size[0] = (zones_size[0] - PAGE_OFFSET) >> PAGE_SHIFT;
265 zones_size[1] >>= PAGE_SHIFT;
266
267 free_area_init(zones_size);
268}
269
270extern char __init_begin, __init_end;
271
272void free_initmem(void)
273{
274 unsigned long addr;
275
276 addr = (unsigned long)&__init_begin;
277 for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
278 virt_to_page(addr)->flags &= ~(1 << PG_reserved);
279 set_page_count(virt_to_page(addr), 1);
280 free_page(addr);
281 totalram_pages++;
282 }
283}
284
285
diff --git a/arch/m68k/mm/sun3kmap.c b/arch/m68k/mm/sun3kmap.c
new file mode 100644
index 000000000000..7f0d86f3fe73
--- /dev/null
+++ b/arch/m68k/mm/sun3kmap.c
@@ -0,0 +1,156 @@
1/*
2 * linux/arch/m68k/mm/sun3kmap.c
3 *
4 * Copyright (C) 2002 Sam Creasey <sammy@sammy.net>
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/types.h>
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <linux/vmalloc.h>
15
16#include <asm/page.h>
17#include <asm/pgtable.h>
18#include <asm/io.h>
19#include <asm/sun3mmu.h>
20
21#undef SUN3_KMAP_DEBUG
22
23#ifdef SUN3_KMAP_DEBUG
24extern void print_pte_vaddr(unsigned long vaddr);
25#endif
26
27extern void mmu_emu_map_pmeg (int context, int vaddr);
28
29static inline void do_page_mapin(unsigned long phys, unsigned long virt,
30 unsigned long type)
31{
32 unsigned long pte;
33 pte_t ptep;
34
35 ptep = pfn_pte(phys >> PAGE_SHIFT, PAGE_KERNEL);
36 pte = pte_val(ptep);
37 pte |= type;
38
39 sun3_put_pte(virt, pte);
40
41#ifdef SUN3_KMAP_DEBUG
42 print_pte_vaddr(virt);
43#endif
44
45}
46
47static inline void do_pmeg_mapin(unsigned long phys, unsigned long virt,
48 unsigned long type, int pages)
49{
50
51 if(sun3_get_segmap(virt & ~SUN3_PMEG_MASK) == SUN3_INVALID_PMEG)
52 mmu_emu_map_pmeg(sun3_get_context(), virt);
53
54 while(pages) {
55 do_page_mapin(phys, virt, type);
56 phys += PAGE_SIZE;
57 virt += PAGE_SIZE;
58 pages--;
59 }
60}
61
62void *sun3_ioremap(unsigned long phys, unsigned long size,
63 unsigned long type)
64{
65 struct vm_struct *area;
66 unsigned long offset, virt, ret;
67 int pages;
68
69 if(!size)
70 return NULL;
71
72 /* page align */
73 offset = phys & (PAGE_SIZE-1);
74 phys &= ~(PAGE_SIZE-1);
75
76 size += offset;
77 size = PAGE_ALIGN(size);
78 if((area = get_vm_area(size, VM_IOREMAP)) == NULL)
79 return NULL;
80
81#ifdef SUN3_KMAP_DEBUG
82 printk("ioremap: got virt %p size %lx(%lx)\n",
83 area->addr, size, area->size);
84#endif
85
86 pages = size / PAGE_SIZE;
87 virt = (unsigned long)area->addr;
88 ret = virt + offset;
89
90 while(pages) {
91 int seg_pages;
92
93 seg_pages = (SUN3_PMEG_SIZE - (virt & SUN3_PMEG_MASK)) / PAGE_SIZE;
94 if(seg_pages > pages)
95 seg_pages = pages;
96
97 do_pmeg_mapin(phys, virt, type, seg_pages);
98
99 pages -= seg_pages;
100 phys += seg_pages * PAGE_SIZE;
101 virt += seg_pages * PAGE_SIZE;
102 }
103
104 return (void *)ret;
105
106}
107
108
109void *__ioremap(unsigned long phys, unsigned long size, int cache)
110{
111
112 return sun3_ioremap(phys, size, SUN3_PAGE_TYPE_IO);
113
114}
115
116void iounmap(void *addr)
117{
118 vfree((void *)(PAGE_MASK & (unsigned long)addr));
119}
120
121/* sun3_map_test(addr, val) -- Reads a byte from addr, storing to val,
122 * trapping the potential read fault. Returns 0 if the access faulted,
123 * 1 on success.
124 *
125 * This function is primarily used to check addresses on the VME bus.
126 *
127 * Mucking with the page fault handler seems a little hackish to me, but
128 * SunOS, NetBSD, and Mach all implemented this check in such a manner,
129 * so I figure we're allowed.
130 */
131int sun3_map_test(unsigned long addr, char *val)
132{
133 int ret = 0;
134
135 __asm__ __volatile__
136 (".globl _sun3_map_test_start\n"
137 "_sun3_map_test_start:\n"
138 "1: moveb (%2), (%0)\n"
139 " moveq #1, %1\n"
140 "2:\n"
141 ".section .fixup,\"ax\"\n"
142 ".even\n"
143 "3: moveq #0, %1\n"
144 " jmp 2b\n"
145 ".previous\n"
146 ".section __ex_table,\"a\"\n"
147 ".align 4\n"
148 ".long 1b,3b\n"
149 ".previous\n"
150 ".globl _sun3_map_test_end\n"
151 "_sun3_map_test_end:\n"
152 : "=a"(val), "=r"(ret)
153 : "a"(addr));
154
155 return ret;
156}
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
new file mode 100644
index 000000000000..a47be196a47c
--- /dev/null
+++ b/arch/m68k/mm/sun3mmu.c
@@ -0,0 +1,102 @@
1/*
2 * linux/arch/m68k/mm/sun3mmu.c
3 *
4 * Implementations of mm routines specific to the sun3 MMU.
5 *
6 * Moved here 8/20/1999 Sam Creasey
7 *
8 */
9
10#include <linux/signal.h>
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/swap.h>
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/types.h>
17#include <linux/init.h>
18#include <linux/bootmem.h>
19
20#include <asm/setup.h>
21#include <asm/uaccess.h>
22#include <asm/page.h>
23#include <asm/pgtable.h>
24#include <asm/system.h>
25#include <asm/machdep.h>
26#include <asm/io.h>
27
28extern void mmu_emu_init (unsigned long bootmem_end);
29
30const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
31
32extern unsigned long num_pages;
33
34void free_initmem(void)
35{
36}
37
38/* For the sun3 we try to follow the i386 paging_init() more closely */
39/* start_mem and end_mem have PAGE_OFFSET added already */
40/* now sets up tables using sun3 PTEs rather than i386 as before. --m */
41void __init paging_init(void)
42{
43 pgd_t * pg_dir;
44 pte_t * pg_table;
45 int i;
46 unsigned long address;
47 unsigned long next_pgtable;
48 unsigned long bootmem_end;
49 unsigned long zones_size[3] = {0, 0, 0};
50 unsigned long size;
51
52
53#ifdef TEST_VERIFY_AREA
54 wp_works_ok = 0;
55#endif
56 empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
57 memset(empty_zero_page, 0, PAGE_SIZE);
58
59 address = PAGE_OFFSET;
60 pg_dir = swapper_pg_dir;
61 memset (swapper_pg_dir, 0, sizeof (swapper_pg_dir));
62 memset (kernel_pg_dir, 0, sizeof (kernel_pg_dir));
63
64 size = num_pages * sizeof(pte_t);
65 size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
66
67 next_pgtable = (unsigned long)alloc_bootmem_pages(size);
68 bootmem_end = (next_pgtable + size + PAGE_SIZE) & PAGE_MASK;
69
70 /* Map whole memory from PAGE_OFFSET (0x0E000000) */
71 pg_dir += PAGE_OFFSET >> PGDIR_SHIFT;
72
73 while (address < (unsigned long)high_memory) {
74 pg_table = (pte_t *) __pa (next_pgtable);
75 next_pgtable += PTRS_PER_PTE * sizeof (pte_t);
76 pgd_val(*pg_dir) = (unsigned long) pg_table;
77 pg_dir++;
78
79 /* now change pg_table to kernel virtual addresses */
80 pg_table = (pte_t *) __va ((unsigned long) pg_table);
81 for (i=0; i<PTRS_PER_PTE; ++i, ++pg_table) {
82 pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT);
83 if (address >= (unsigned long)high_memory)
84 pte_val (pte) = 0;
85 set_pte (pg_table, pte);
86 address += PAGE_SIZE;
87 }
88 }
89
90 mmu_emu_init(bootmem_end);
91
92 current->mm = NULL;
93
94 /* memory sizing is a hack stolen from motorola.c.. hope it works for us */
95 zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
96 zones_size[1] = 0;
97
98 free_area_init(zones_size);
99
100}
101
102
diff --git a/arch/m68k/mvme147/147ints.c b/arch/m68k/mvme147/147ints.c
new file mode 100644
index 000000000000..69a744ee35a3
--- /dev/null
+++ b/arch/m68k/mvme147/147ints.c
@@ -0,0 +1,145 @@
1/*
2 * arch/m68k/mvme147/147ints.c
3 *
4 * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk]
5 *
6 * based on amiints.c -- Amiga Linux interrupt handling code
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file README.legal in the main directory of this archive
10 * for more details.
11 *
12 */
13
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/seq_file.h>
18
19#include <asm/ptrace.h>
20#include <asm/system.h>
21#include <asm/irq.h>
22#include <asm/traps.h>
23
24static irqreturn_t mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp);
25
26/*
27 * This should ideally be 4 elements only, for speed.
28 */
29
30static struct {
31 irqreturn_t (*handler)(int, void *, struct pt_regs *);
32 unsigned long flags;
33 void *dev_id;
34 const char *devname;
35 unsigned count;
36} irq_tab[256];
37
38/*
39 * void mvme147_init_IRQ (void)
40 *
41 * Parameters: None
42 *
43 * Returns: Nothing
44 *
45 * This function is called during kernel startup to initialize
46 * the mvme147 IRQ handling routines.
47 */
48
49void mvme147_init_IRQ (void)
50{
51 int i;
52
53 for (i = 0; i < 256; i++) {
54 irq_tab[i].handler = mvme147_defhand;
55 irq_tab[i].flags = IRQ_FLG_STD;
56 irq_tab[i].dev_id = NULL;
57 irq_tab[i].devname = NULL;
58 irq_tab[i].count = 0;
59 }
60}
61
62int mvme147_request_irq(unsigned int irq,
63 irqreturn_t (*handler)(int, void *, struct pt_regs *),
64 unsigned long flags, const char *devname, void *dev_id)
65{
66 if (irq > 255) {
67 printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
68 return -ENXIO;
69 }
70 if (!(irq_tab[irq].flags & IRQ_FLG_STD)) {
71 if (irq_tab[irq].flags & IRQ_FLG_LOCK) {
72 printk("%s: IRQ %d from %s is not replaceable\n",
73 __FUNCTION__, irq, irq_tab[irq].devname);
74 return -EBUSY;
75 }
76 if (flags & IRQ_FLG_REPLACE) {
77 printk("%s: %s can't replace IRQ %d from %s\n",
78 __FUNCTION__, devname, irq, irq_tab[irq].devname);
79 return -EBUSY;
80 }
81 }
82 irq_tab[irq].handler = handler;
83 irq_tab[irq].flags = flags;
84 irq_tab[irq].dev_id = dev_id;
85 irq_tab[irq].devname = devname;
86 return 0;
87}
88
89void mvme147_free_irq(unsigned int irq, void *dev_id)
90{
91 if (irq > 255) {
92 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
93 return;
94 }
95 if (irq_tab[irq].dev_id != dev_id)
96 printk("%s: Removing probably wrong IRQ %d from %s\n",
97 __FUNCTION__, irq, irq_tab[irq].devname);
98
99 irq_tab[irq].handler = mvme147_defhand;
100 irq_tab[irq].flags = IRQ_FLG_STD;
101 irq_tab[irq].dev_id = NULL;
102 irq_tab[irq].devname = NULL;
103}
104
105irqreturn_t mvme147_process_int (unsigned long vec, struct pt_regs *fp)
106{
107 if (vec > 255) {
108 printk ("mvme147_process_int: Illegal vector %ld\n", vec);
109 return IRQ_NONE;
110 } else {
111 irq_tab[vec].count++;
112 irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
113 return IRQ_HANDLED;
114 }
115}
116
117int show_mvme147_interrupts (struct seq_file *p, void *v)
118{
119 int i;
120
121 for (i = 0; i < 256; i++) {
122 if (irq_tab[i].count)
123 seq_printf(p, "Vec 0x%02x: %8d %s\n",
124 i, irq_tab[i].count,
125 irq_tab[i].devname ? irq_tab[i].devname : "free");
126 }
127 return 0;
128}
129
130
131static irqreturn_t mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp)
132{
133 printk ("Unknown interrupt 0x%02x\n", irq);
134 return IRQ_NONE;
135}
136
137void mvme147_enable_irq (unsigned int irq)
138{
139}
140
141
142void mvme147_disable_irq (unsigned int irq)
143{
144}
145
diff --git a/arch/m68k/mvme147/Makefile b/arch/m68k/mvme147/Makefile
new file mode 100644
index 000000000000..f0153ed3efa5
--- /dev/null
+++ b/arch/m68k/mvme147/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/mvme147 source directory
3#
4
5obj-y := config.o 147ints.o
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
new file mode 100644
index 000000000000..0fcf9720c2fe
--- /dev/null
+++ b/arch/m68k/mvme147/config.c
@@ -0,0 +1,229 @@
1/*
2 * arch/m68k/mvme147/config.c
3 *
4 * Copyright (C) 1996 Dave Frascone [chaos@mindspring.com]
5 * Cloned from Richard Hirst [richard@sleepie.demon.co.uk]
6 *
7 * Based on:
8 *
9 * Copyright (C) 1993 Hamish Macdonald
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file README.legal in the main directory of this archive
13 * for more details.
14 */
15
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/mm.h>
19#include <linux/tty.h>
20#include <linux/console.h>
21#include <linux/linkage.h>
22#include <linux/init.h>
23#include <linux/major.h>
24#include <linux/genhd.h>
25#include <linux/rtc.h>
26#include <linux/interrupt.h>
27
28#include <asm/bootinfo.h>
29#include <asm/system.h>
30#include <asm/pgtable.h>
31#include <asm/setup.h>
32#include <asm/irq.h>
33#include <asm/traps.h>
34#include <asm/rtc.h>
35#include <asm/machdep.h>
36#include <asm/mvme147hw.h>
37
38
39extern irqreturn_t mvme147_process_int (int level, struct pt_regs *regs);
40extern void mvme147_init_IRQ (void);
41extern void mvme147_free_irq (unsigned int, void *);
42extern int show_mvme147_interrupts (struct seq_file *, void *);
43extern void mvme147_enable_irq (unsigned int);
44extern void mvme147_disable_irq (unsigned int);
45static void mvme147_get_model(char *model);
46static int mvme147_get_hardware_list(char *buffer);
47extern int mvme147_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
48extern void mvme147_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
49extern unsigned long mvme147_gettimeoffset (void);
50extern int mvme147_hwclk (int, struct rtc_time *);
51extern int mvme147_set_clock_mmss (unsigned long);
52extern void mvme147_reset (void);
53extern void mvme147_waitbut(void);
54
55
56static int bcd2int (unsigned char b);
57
58/* Save tick handler routine pointer, will point to do_timer() in
59 * kernel/sched.c, called via mvme147_process_int() */
60
61irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
62
63
64int mvme147_parse_bootinfo(const struct bi_record *bi)
65{
66 if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO)
67 return 0;
68 else
69 return 1;
70}
71
72void mvme147_reset(void)
73{
74 printk ("\r\n\nCalled mvme147_reset\r\n");
75 m147_pcc->watchdog = 0x0a; /* Clear timer */
76 m147_pcc->watchdog = 0xa5; /* Enable watchdog - 100ms to reset */
77 while (1)
78 ;
79}
80
81static void mvme147_get_model(char *model)
82{
83 sprintf(model, "Motorola MVME147");
84}
85
86
87static int mvme147_get_hardware_list(char *buffer)
88{
89 *buffer = '\0';
90
91 return 0;
92}
93
94
95void __init config_mvme147(void)
96{
97 mach_max_dma_address = 0x01000000;
98 mach_sched_init = mvme147_sched_init;
99 mach_init_IRQ = mvme147_init_IRQ;
100 mach_gettimeoffset = mvme147_gettimeoffset;
101 mach_hwclk = mvme147_hwclk;
102 mach_set_clock_mmss = mvme147_set_clock_mmss;
103 mach_reset = mvme147_reset;
104 mach_free_irq = mvme147_free_irq;
105 mach_process_int = mvme147_process_int;
106 mach_get_irq_list = show_mvme147_interrupts;
107 mach_request_irq = mvme147_request_irq;
108 enable_irq = mvme147_enable_irq;
109 disable_irq = mvme147_disable_irq;
110 mach_get_model = mvme147_get_model;
111 mach_get_hardware_list = mvme147_get_hardware_list;
112
113 /* Board type is only set by newer versions of vmelilo/tftplilo */
114 if (!vme_brdtype)
115 vme_brdtype = VME_TYPE_MVME147;
116}
117
118
119/* Using pcc tick timer 1 */
120
121static irqreturn_t mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp)
122{
123 m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
124 m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
125 return tick_handler(irq, dev_id, fp);
126}
127
128
129void mvme147_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
130{
131 tick_handler = timer_routine;
132 request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
133 IRQ_FLG_REPLACE, "timer 1", NULL);
134
135 /* Init the clock with a value */
136 /* our clock goes off every 6.25us */
137 m147_pcc->t1_preload = PCC_TIMER_PRELOAD;
138 m147_pcc->t1_cntrl = 0x0; /* clear timer */
139 m147_pcc->t1_cntrl = 0x3; /* start timer */
140 m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; /* clear pending ints */
141 m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
142}
143
144/* This is always executed with interrupts disabled. */
145/* XXX There are race hazards in this code XXX */
146unsigned long mvme147_gettimeoffset (void)
147{
148 volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
149 unsigned short n;
150
151 n = *cp;
152 while (n != *cp)
153 n = *cp;
154
155 n -= PCC_TIMER_PRELOAD;
156 return (unsigned long)n * 25 / 4;
157}
158
159static int bcd2int (unsigned char b)
160{
161 return ((b>>4)*10 + (b&15));
162}
163
164int mvme147_hwclk(int op, struct rtc_time *t)
165{
166#warning check me!
167 if (!op) {
168 m147_rtc->ctrl = RTC_READ;
169 t->tm_year = bcd2int (m147_rtc->bcd_year);
170 t->tm_mon = bcd2int (m147_rtc->bcd_mth);
171 t->tm_mday = bcd2int (m147_rtc->bcd_dom);
172 t->tm_hour = bcd2int (m147_rtc->bcd_hr);
173 t->tm_min = bcd2int (m147_rtc->bcd_min);
174 t->tm_sec = bcd2int (m147_rtc->bcd_sec);
175 m147_rtc->ctrl = 0;
176 }
177 return 0;
178}
179
180int mvme147_set_clock_mmss (unsigned long nowtime)
181{
182 return 0;
183}
184
185/*------------------- Serial console stuff ------------------------*/
186
187static void scc_delay (void)
188{
189 int n;
190 volatile int trash;
191
192 for (n = 0; n < 20; n++)
193 trash = n;
194}
195
196static void scc_write (char ch)
197{
198 volatile char *p = (volatile char *)M147_SCC_A_ADDR;
199
200 do {
201 scc_delay();
202 }
203 while (!(*p & 4));
204 scc_delay();
205 *p = 8;
206 scc_delay();
207 *p = ch;
208}
209
210
211void m147_scc_write (struct console *co, const char *str, unsigned count)
212{
213 unsigned long flags;
214
215 local_irq_save(flags);
216
217 while (count--)
218 {
219 if (*str == '\n')
220 scc_write ('\r');
221 scc_write (*str++);
222 }
223 local_irq_restore(flags);
224}
225
226void mvme147_init_console_port (struct console *co, int cflag)
227{
228 co->write = m147_scc_write;
229}
diff --git a/arch/m68k/mvme16x/16xints.c b/arch/m68k/mvme16x/16xints.c
new file mode 100644
index 000000000000..793ef735b59c
--- /dev/null
+++ b/arch/m68k/mvme16x/16xints.c
@@ -0,0 +1,149 @@
1/*
2 * arch/m68k/mvme16x/16xints.c
3 *
4 * Copyright (C) 1995 Richard Hirst [richard@sleepie.demon.co.uk]
5 *
6 * based on amiints.c -- Amiga Linux interrupt handling code
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file README.legal in the main directory of this archive
10 * for more details.
11 *
12 */
13
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/seq_file.h>
18
19#include <asm/system.h>
20#include <asm/ptrace.h>
21#include <asm/irq.h>
22
23static irqreturn_t mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp);
24
25/*
26 * This should ideally be 4 elements only, for speed.
27 */
28
29static struct {
30 irqreturn_t (*handler)(int, void *, struct pt_regs *);
31 unsigned long flags;
32 void *dev_id;
33 const char *devname;
34 unsigned count;
35} irq_tab[192];
36
37/*
38 * void mvme16x_init_IRQ (void)
39 *
40 * Parameters: None
41 *
42 * Returns: Nothing
43 *
44 * This function is called during kernel startup to initialize
45 * the mvme16x IRQ handling routines. Should probably ensure
46 * that the base vectors for the VMEChip2 and PCCChip2 are valid.
47 */
48
49void mvme16x_init_IRQ (void)
50{
51 int i;
52
53 for (i = 0; i < 192; i++) {
54 irq_tab[i].handler = mvme16x_defhand;
55 irq_tab[i].flags = IRQ_FLG_STD;
56 irq_tab[i].dev_id = NULL;
57 irq_tab[i].devname = NULL;
58 irq_tab[i].count = 0;
59 }
60}
61
62int mvme16x_request_irq(unsigned int irq,
63 irqreturn_t (*handler)(int, void *, struct pt_regs *),
64 unsigned long flags, const char *devname, void *dev_id)
65{
66 if (irq < 64 || irq > 255) {
67 printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
68 return -ENXIO;
69 }
70
71 if (!(irq_tab[irq-64].flags & IRQ_FLG_STD)) {
72 if (irq_tab[irq-64].flags & IRQ_FLG_LOCK) {
73 printk("%s: IRQ %d from %s is not replaceable\n",
74 __FUNCTION__, irq, irq_tab[irq-64].devname);
75 return -EBUSY;
76 }
77 if (flags & IRQ_FLG_REPLACE) {
78 printk("%s: %s can't replace IRQ %d from %s\n",
79 __FUNCTION__, devname, irq, irq_tab[irq-64].devname);
80 return -EBUSY;
81 }
82 }
83 irq_tab[irq-64].handler = handler;
84 irq_tab[irq-64].flags = flags;
85 irq_tab[irq-64].dev_id = dev_id;
86 irq_tab[irq-64].devname = devname;
87 return 0;
88}
89
90void mvme16x_free_irq(unsigned int irq, void *dev_id)
91{
92 if (irq < 64 || irq > 255) {
93 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
94 return;
95 }
96
97 if (irq_tab[irq-64].dev_id != dev_id)
98 printk("%s: Removing probably wrong IRQ %d from %s\n",
99 __FUNCTION__, irq, irq_tab[irq-64].devname);
100
101 irq_tab[irq-64].handler = mvme16x_defhand;
102 irq_tab[irq-64].flags = IRQ_FLG_STD;
103 irq_tab[irq-64].dev_id = NULL;
104 irq_tab[irq-64].devname = NULL;
105}
106
107irqreturn_t mvme16x_process_int (unsigned long vec, struct pt_regs *fp)
108{
109 if (vec < 64 || vec > 255) {
110 printk ("mvme16x_process_int: Illegal vector %ld", vec);
111 return IRQ_NONE;
112 } else {
113 irq_tab[vec-64].count++;
114 irq_tab[vec-64].handler(vec, irq_tab[vec-64].dev_id, fp);
115 return IRQ_HANDLED;
116 }
117}
118
119int show_mvme16x_interrupts (struct seq_file *p, void *v)
120{
121 int i;
122
123 for (i = 0; i < 192; i++) {
124 if (irq_tab[i].count)
125 seq_printf(p, "Vec 0x%02x: %8d %s\n",
126 i+64, irq_tab[i].count,
127 irq_tab[i].devname ? irq_tab[i].devname : "free");
128 }
129 return 0;
130}
131
132
133static irqreturn_t mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp)
134{
135 printk ("Unknown interrupt 0x%02x\n", irq);
136 return IRQ_NONE;
137}
138
139
140void mvme16x_enable_irq (unsigned int irq)
141{
142}
143
144
145void mvme16x_disable_irq (unsigned int irq)
146{
147}
148
149
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
new file mode 100644
index 000000000000..5129f56b64a3
--- /dev/null
+++ b/arch/m68k/mvme16x/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/mvme16x source directory
3#
4
5obj-y := config.o 16xints.o rtc.o mvme16x_ksyms.o
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
new file mode 100644
index 000000000000..26ce81c1337d
--- /dev/null
+++ b/arch/m68k/mvme16x/config.c
@@ -0,0 +1,286 @@
1/*
2 * arch/m68k/mvme16x/config.c
3 *
4 * Copyright (C) 1995 Richard Hirst [richard@sleepie.demon.co.uk]
5 *
6 * Based on:
7 *
8 * linux/amiga/config.c
9 *
10 * Copyright (C) 1993 Hamish Macdonald
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file README.legal in the main directory of this archive
14 * for more details.
15 */
16
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/mm.h>
20#include <linux/tty.h>
21#include <linux/console.h>
22#include <linux/linkage.h>
23#include <linux/init.h>
24#include <linux/major.h>
25#include <linux/genhd.h>
26#include <linux/rtc.h>
27#include <linux/interrupt.h>
28
29#include <asm/bootinfo.h>
30#include <asm/system.h>
31#include <asm/pgtable.h>
32#include <asm/setup.h>
33#include <asm/irq.h>
34#include <asm/traps.h>
35#include <asm/rtc.h>
36#include <asm/machdep.h>
37#include <asm/mvme16xhw.h>
38
39extern t_bdid mvme_bdid;
40
41static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
42
43extern irqreturn_t mvme16x_process_int (int level, struct pt_regs *regs);
44extern void mvme16x_init_IRQ (void);
45extern void mvme16x_free_irq (unsigned int, void *);
46extern int show_mvme16x_interrupts (struct seq_file *, void *);
47extern void mvme16x_enable_irq (unsigned int);
48extern void mvme16x_disable_irq (unsigned int);
49static void mvme16x_get_model(char *model);
50static int mvme16x_get_hardware_list(char *buffer);
51extern int mvme16x_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
52extern void mvme16x_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
53extern unsigned long mvme16x_gettimeoffset (void);
54extern int mvme16x_hwclk (int, struct rtc_time *);
55extern int mvme16x_set_clock_mmss (unsigned long);
56extern void mvme16x_reset (void);
57extern void mvme16x_waitbut(void);
58
59int bcd2int (unsigned char b);
60
61/* Save tick handler routine pointer, will point to do_timer() in
62 * kernel/sched.c, called via mvme16x_process_int() */
63
64static irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
65
66
67unsigned short mvme16x_config;
68
69
70int mvme16x_parse_bootinfo(const struct bi_record *bi)
71{
72 if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO)
73 return 0;
74 else
75 return 1;
76}
77
78void mvme16x_reset(void)
79{
80 printk ("\r\n\nCalled mvme16x_reset\r\n"
81 "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r");
82 /* The string of returns is to delay the reset until the whole
83 * message is output. Assert reset bit in GCSR */
84 *(volatile char *)0xfff40107 = 0x80;
85}
86
87static void mvme16x_get_model(char *model)
88{
89 p_bdid p = &mvme_bdid;
90 char suf[4];
91
92 suf[1] = p->brdsuffix[0];
93 suf[2] = p->brdsuffix[1];
94 suf[3] = '\0';
95 suf[0] = suf[1] ? '-' : '\0';
96
97 sprintf(model, "Motorola MVME%x%s", p->brdno, suf);
98}
99
100
101static int mvme16x_get_hardware_list(char *buffer)
102{
103 p_bdid p = &mvme_bdid;
104 int len = 0;
105
106 if (p->brdno == 0x0162 || p->brdno == 0x0172)
107 {
108 unsigned char rev = *(unsigned char *)MVME162_VERSION_REG;
109
110 len += sprintf (buffer+len, "VMEchip2 %spresent\n",
111 rev & MVME16x_CONFIG_NO_VMECHIP2 ? "NOT " : "");
112 len += sprintf (buffer+len, "SCSI interface %spresent\n",
113 rev & MVME16x_CONFIG_NO_SCSICHIP ? "NOT " : "");
114 len += sprintf (buffer+len, "Ethernet i/f %spresent\n",
115 rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : "");
116 }
117 else
118 *buffer = '\0';
119
120 return (len);
121}
122
123
124#define pcc2chip ((volatile u_char *)0xfff42000)
125#define PccSCCMICR 0x1d
126#define PccSCCTICR 0x1e
127#define PccSCCRICR 0x1f
128
129void __init config_mvme16x(void)
130{
131 p_bdid p = &mvme_bdid;
132 char id[40];
133
134 mach_max_dma_address = 0xffffffff;
135 mach_sched_init = mvme16x_sched_init;
136 mach_init_IRQ = mvme16x_init_IRQ;
137 mach_gettimeoffset = mvme16x_gettimeoffset;
138 mach_hwclk = mvme16x_hwclk;
139 mach_set_clock_mmss = mvme16x_set_clock_mmss;
140 mach_reset = mvme16x_reset;
141 mach_free_irq = mvme16x_free_irq;
142 mach_process_int = mvme16x_process_int;
143 mach_get_irq_list = show_mvme16x_interrupts;
144 mach_request_irq = mvme16x_request_irq;
145 enable_irq = mvme16x_enable_irq;
146 disable_irq = mvme16x_disable_irq;
147 mach_get_model = mvme16x_get_model;
148 mach_get_hardware_list = mvme16x_get_hardware_list;
149
150 /* Report board revision */
151
152 if (strncmp("BDID", p->bdid, 4))
153 {
154 printk ("\n\nBug call .BRD_ID returned garbage - giving up\n\n");
155 while (1)
156 ;
157 }
158 /* Board type is only set by newer versions of vmelilo/tftplilo */
159 if (vme_brdtype == 0)
160 vme_brdtype = p->brdno;
161
162 mvme16x_get_model(id);
163 printk ("\nBRD_ID: %s BUG %x.%x %02x/%02x/%02x\n", id, p->rev>>4,
164 p->rev&0xf, p->yr, p->mth, p->day);
165 if (p->brdno == 0x0162 || p->brdno == 0x172)
166 {
167 unsigned char rev = *(unsigned char *)MVME162_VERSION_REG;
168
169 mvme16x_config = rev | MVME16x_CONFIG_GOT_SCCA;
170
171 printk ("MVME%x Hardware status:\n", p->brdno);
172 printk (" CPU Type 68%s040\n",
173 rev & MVME16x_CONFIG_GOT_FPU ? "" : "LC");
174 printk (" CPU clock %dMHz\n",
175 rev & MVME16x_CONFIG_SPEED_32 ? 32 : 25);
176 printk (" VMEchip2 %spresent\n",
177 rev & MVME16x_CONFIG_NO_VMECHIP2 ? "NOT " : "");
178 printk (" SCSI interface %spresent\n",
179 rev & MVME16x_CONFIG_NO_SCSICHIP ? "NOT " : "");
180 printk (" Ethernet interface %spresent\n",
181 rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : "");
182 }
183 else
184 {
185 mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401;
186
187 /* Dont allow any interrupts from the CD2401 until the interrupt */
188 /* handlers are installed */
189
190 pcc2chip[PccSCCMICR] = 0x10;
191 pcc2chip[PccSCCTICR] = 0x10;
192 pcc2chip[PccSCCRICR] = 0x10;
193 }
194}
195
196static irqreturn_t mvme16x_abort_int (int irq, void *dev_id, struct pt_regs *fp)
197{
198 p_bdid p = &mvme_bdid;
199 unsigned long *new = (unsigned long *)vectors;
200 unsigned long *old = (unsigned long *)0xffe00000;
201 volatile unsigned char uc, *ucp;
202
203 if (p->brdno == 0x0162 || p->brdno == 0x172)
204 {
205 ucp = (volatile unsigned char *)0xfff42043;
206 uc = *ucp | 8;
207 *ucp = uc;
208 }
209 else
210 {
211 *(volatile unsigned long *)0xfff40074 = 0x40000000;
212 }
213 *(new+4) = *(old+4); /* Illegal instruction */
214 *(new+9) = *(old+9); /* Trace */
215 *(new+47) = *(old+47); /* Trap #15 */
216
217 if (p->brdno == 0x0162 || p->brdno == 0x172)
218 *(new+0x5e) = *(old+0x5e); /* ABORT switch */
219 else
220 *(new+0x6e) = *(old+0x6e); /* ABORT switch */
221 return IRQ_HANDLED;
222}
223
224static irqreturn_t mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp)
225{
226 *(volatile unsigned char *)0xfff4201b |= 8;
227 return tick_handler(irq, dev_id, fp);
228}
229
230void mvme16x_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
231{
232 p_bdid p = &mvme_bdid;
233 int irq;
234
235 tick_handler = timer_routine;
236 /* Using PCCchip2 or MC2 chip tick timer 1 */
237 *(volatile unsigned long *)0xfff42008 = 0;
238 *(volatile unsigned long *)0xfff42004 = 10000; /* 10ms */
239 *(volatile unsigned char *)0xfff42017 |= 3;
240 *(volatile unsigned char *)0xfff4201b = 0x16;
241 if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0,
242 "timer", mvme16x_timer_int))
243 panic ("Couldn't register timer int");
244
245 if (p->brdno == 0x0162 || p->brdno == 0x172)
246 irq = MVME162_IRQ_ABORT;
247 else
248 irq = MVME167_IRQ_ABORT;
249 if (request_irq(irq, mvme16x_abort_int, 0,
250 "abort", mvme16x_abort_int))
251 panic ("Couldn't register abort int");
252}
253
254
255/* This is always executed with interrupts disabled. */
256unsigned long mvme16x_gettimeoffset (void)
257{
258 return (*(volatile unsigned long *)0xfff42008);
259}
260
261int bcd2int (unsigned char b)
262{
263 return ((b>>4)*10 + (b&15));
264}
265
266int mvme16x_hwclk(int op, struct rtc_time *t)
267{
268#warning check me!
269 if (!op) {
270 rtc->ctrl = RTC_READ;
271 t->tm_year = bcd2int (rtc->bcd_year);
272 t->tm_mon = bcd2int (rtc->bcd_mth);
273 t->tm_mday = bcd2int (rtc->bcd_dom);
274 t->tm_hour = bcd2int (rtc->bcd_hr);
275 t->tm_min = bcd2int (rtc->bcd_min);
276 t->tm_sec = bcd2int (rtc->bcd_sec);
277 rtc->ctrl = 0;
278 }
279 return 0;
280}
281
282int mvme16x_set_clock_mmss (unsigned long nowtime)
283{
284 return 0;
285}
286
diff --git a/arch/m68k/mvme16x/mvme16x_ksyms.c b/arch/m68k/mvme16x/mvme16x_ksyms.c
new file mode 100644
index 000000000000..4a8a3634bb47
--- /dev/null
+++ b/arch/m68k/mvme16x/mvme16x_ksyms.c
@@ -0,0 +1,6 @@
1#include <linux/module.h>
2#include <linux/types.h>
3#include <asm/ptrace.h>
4#include <asm/mvme16xhw.h>
5
6EXPORT_SYMBOL(mvme16x_config);
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
new file mode 100644
index 000000000000..8a2425069088
--- /dev/null
+++ b/arch/m68k/mvme16x/rtc.c
@@ -0,0 +1,172 @@
1/*
2 * Real Time Clock interface for Linux on the MVME16x
3 *
4 * Based on the PC driver by Paul Gortmaker.
5 */
6
7#define RTC_VERSION "1.00"
8
9#include <linux/types.h>
10#include <linux/errno.h>
11#include <linux/miscdevice.h>
12#include <linux/slab.h>
13#include <linux/ioport.h>
14#include <linux/fcntl.h>
15#include <linux/init.h>
16#include <linux/poll.h>
17#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
18#include <linux/smp_lock.h>
19#include <asm/mvme16xhw.h>
20
21#include <asm/io.h>
22#include <asm/uaccess.h>
23#include <asm/system.h>
24#include <asm/setup.h>
25
26/*
27 * We sponge a minor off of the misc major. No need slurping
28 * up another valuable major dev number for this. If you add
29 * an ioctl, make sure you don't conflict with SPARC's RTC
30 * ioctls.
31 */
32
33#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
34#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
35
36static const unsigned char days_in_mo[] =
37{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
38
39static atomic_t rtc_ready = ATOMIC_INIT(1);
40
41static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
42 unsigned long arg)
43{
44 volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE;
45 unsigned long flags;
46 struct rtc_time wtime;
47
48 switch (cmd) {
49 case RTC_RD_TIME: /* Read the time/date from RTC */
50 {
51 local_irq_save(flags);
52 /* Ensure clock and real-time-mode-register are accessible */
53 rtc->ctrl = RTC_READ;
54 memset(&wtime, 0, sizeof(struct rtc_time));
55 wtime.tm_sec = BCD2BIN(rtc->bcd_sec);
56 wtime.tm_min = BCD2BIN(rtc->bcd_min);
57 wtime.tm_hour = BCD2BIN(rtc->bcd_hr);
58 wtime.tm_mday = BCD2BIN(rtc->bcd_dom);
59 wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1;
60 wtime.tm_year = BCD2BIN(rtc->bcd_year);
61 if (wtime.tm_year < 70)
62 wtime.tm_year += 100;
63 wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
64 rtc->ctrl = 0;
65 local_irq_restore(flags);
66 return copy_to_user((void *)arg, &wtime, sizeof wtime) ?
67 -EFAULT : 0;
68 }
69 case RTC_SET_TIME: /* Set the RTC */
70 {
71 struct rtc_time rtc_tm;
72 unsigned char mon, day, hrs, min, sec, leap_yr;
73 unsigned int yrs;
74
75 if (!capable(CAP_SYS_ADMIN))
76 return -EACCES;
77
78 if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
79 sizeof(struct rtc_time)))
80 return -EFAULT;
81
82 yrs = rtc_tm.tm_year;
83 if (yrs < 1900)
84 yrs += 1900;
85 mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
86 day = rtc_tm.tm_mday;
87 hrs = rtc_tm.tm_hour;
88 min = rtc_tm.tm_min;
89 sec = rtc_tm.tm_sec;
90
91 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
92
93 if ((mon > 12) || (day == 0))
94 return -EINVAL;
95
96 if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
97 return -EINVAL;
98
99 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
100 return -EINVAL;
101
102 if (yrs >= 2070)
103 return -EINVAL;
104
105 local_irq_save(flags);
106 rtc->ctrl = RTC_WRITE;
107
108 rtc->bcd_sec = BIN2BCD(sec);
109 rtc->bcd_min = BIN2BCD(min);
110 rtc->bcd_hr = BIN2BCD(hrs);
111 rtc->bcd_dom = BIN2BCD(day);
112 rtc->bcd_mth = BIN2BCD(mon);
113 rtc->bcd_year = BIN2BCD(yrs%100);
114
115 rtc->ctrl = 0;
116 local_irq_restore(flags);
117 return 0;
118 }
119 default:
120 return -EINVAL;
121 }
122}
123
124/*
125 * We enforce only one user at a time here with the open/close.
126 * Also clear the previous interrupt data on an open, and clean
127 * up things on a close.
128 */
129
130static int rtc_open(struct inode *inode, struct file *file)
131{
132 if( !atomic_dec_and_test(&rtc_ready) )
133 {
134 atomic_inc( &rtc_ready );
135 return -EBUSY;
136 }
137
138 return 0;
139}
140
141static int rtc_release(struct inode *inode, struct file *file)
142{
143 atomic_inc( &rtc_ready );
144 return 0;
145}
146
147/*
148 * The various file operations we support.
149 */
150
151static struct file_operations rtc_fops = {
152 .ioctl = rtc_ioctl,
153 .open = rtc_open,
154 .release = rtc_release,
155};
156
157static struct miscdevice rtc_dev=
158{
159 .minor = RTC_MINOR,
160 .name = "rtc",
161 .fops = &rtc_fops
162};
163
164int __init rtc_MK48T08_init(void)
165{
166 if (!MACH_IS_MVME16x)
167 return -ENODEV;
168
169 printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION);
170 return misc_register(&rtc_dev);
171}
172
diff --git a/arch/m68k/q40/Makefile b/arch/m68k/q40/Makefile
new file mode 100644
index 000000000000..27eb42796afa
--- /dev/null
+++ b/arch/m68k/q40/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/q40 source directory
3#
4
5obj-y := config.o q40ints.o
diff --git a/arch/m68k/q40/README b/arch/m68k/q40/README
new file mode 100644
index 000000000000..6bdbf4879570
--- /dev/null
+++ b/arch/m68k/q40/README
@@ -0,0 +1,138 @@
1Linux for the Q40
2=================
3
4You may try http://www.geocities.com/SiliconValley/Bay/2602/ for
5some up to date information. Booter and other tools will be also
6available from this place or ftp.uni-erlangen.de/linux/680x0/q40/
7and mirrors.
8
9Hints to documentation usually refer to the linux source tree in
10/usr/src/linux/Documentation unless URL given.
11
12It seems IRQ unmasking can't be safely done on a Q40. IRQ probing
13is not implemented - do not try it! (See below)
14
15For a list of kernel command-line options read the documentation for the
16particular device drivers.
17
18The floppy imposes a very high interrupt load on the CPU, approx 30K/s.
19When something blocks interrupts (HD) it will lose some of them, so far
20this is not known to have caused any data loss. On highly loaded systems
21it can make the floppy very slow or practically stop. Other Q40 OS' simply
22poll the floppy for this reason - something that can't be done in Linux.
23Only possible cure is getting a 82072 controller with fifo instead of
24the 8272A.
25
26drivers used by the Q40, apart from the very obvious (console etc.):
27 drivers/char/q40_keyb.c # use PC keymaps for national keyboards
28 serial.c # normal PC driver - any speed
29 lp.c # printer driver
30 genrtc.c # RTC
31 char/joystick/* # most of this should work, not
32 # in default config.in
33 block/q40ide.c # startup for ide
34 ide* # see Documentation/ide.txt
35 floppy.c # normal PC driver, DMA emu in asm/floppy.h
36 # and arch/m68k/kernel/entry.S
37 # see drivers/block/README.fd
38 net/ne.c
39 video/q40fb.c
40 parport/*
41 sound/dmasound_core.c
42 dmasound_q40.c
43
44Various other PC drivers can be enabled simply by adding them to
45arch/m68k/config.in, especially 8 bit devices should be without any
46problems. For cards using 16bit io/mem more care is required, like
47checking byte order issues, hacking memcpy_*_io etc.
48
49
50Debugging
51=========
52
53Upon startup the kernel will usually output "ABCQGHIJ" into the SRAM,
54preceded by the booter signature. This is a trace just in case something
55went wrong during earliest setup stages of head.S.
56**Changed** to preserve SRAM contents by default, this is only done when
57requested - SRAM must start with '%LX$' signature to do this. '-d' option
58to 'lxx' loader enables this.
59
60SRAM can also be used as additional console device, use debug=mem.
61This will save kernel startup msgs into SRAM, the screen will display
62only the penguin - and shell prompt if it gets that far..
63Unfortunately only 2000 bytes are available.
64
65Serial console works and can also be used for debugging, see loader_txt
66
67Most problems seem to be caused by fawlty or badly configured io-cards or
68hard drives anyway.
69Make sure to configure the parallel port as SPP and remove IRQ/DMA jumpers
70for first testing. The Q40 does not support DMA and may have trouble with
71parallel ports version of interrupts.
72
73
74Q40 Hardware Description
75========================
76
77This is just an overview, see asm-m68k/* for details ask if you have any
78questions.
79
80The Q40 consists of a 68040@40 MHz, 1MB video RAM, up to 32MB RAM, AT-style
81keyboard interface, 1 Programmable LED, 2x8bit DACs and up to 1MB ROM, 1MB
82shadow ROM.
83The Q60 has any of 68060 or 68LC060 and up to 128 MB RAM.
84
85Most interfacing like floppy, IDE, serial and parallel ports is done via ISA
86slots. The ISA io and mem range is mapped (sparse&byteswapped!) into separate
87regions of the memory.
88The main interrupt register IIRQ_REG will indicate whether an IRQ was internal
89or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs.
90
91The Q40 custom chip is programmable to provide 2 periodic timers:
92 - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!!
93 - 10 or 20 KHz - level 4, used for dma-sound
94
95Linux uses the 200 Hz interrupt for timer and beep by default.
96
97
98Interrupts
99==========
100
101q40 master chip handles only a subset of level triggered interrupts.
102
103Linux has some requirements wrt interrupt architecture, these are
104to my knowledge:
105 (a) interrupt handler must not be reentered even when sti() is called
106 from within handler
107 (b) working enable/disable_irq
108
109Luckily these requirements are only important for drivers shared
110with other architectures - ide,serial,parallel, ethernet.
111q40ints.c now contains a trivial hack for (a), (b) is more difficult
112because only irq's 4-15 can be disabled - and only all of them at once.
113Thus disable_irq() can effectively block the machine if the driver goes
114asleep.
115One thing to keep in mind when hacking around the interrupt code is
116that there is no way to find out which IRQ caused a request, [EI]IRQ_REG
117displays current state of the various IRQ lines.
118
119Keyboard
120========
121
122q40 receives AT make/break codes from the keyboard, these are translated to
123the PC scancodes x86 Linux uses. So by theory every national keyboard should
124work just by loading the appropriate x86 keytable - see any national-HOWTO.
125
126Unfortunately the AT->PC translation isn't quite trivial and even worse, my
127documentation of it is absolutely minimal - thus some exotic keys may not
128behave exactly as expected.
129
130There is still hope that it can be fixed completely though. If you encounter
131problems, email me ideally this:
132 - exact keypress/release sequence
133 - 'showkey -s' run on q40, non-X session
134 - 'showkey -s' run on a PC, non-X session
135 - AT codes as displayed by the q40 debugging ROM
136btw if the showkey output from PC and Q40 doesn't differ then you have some
137classic configuration problem - don't send me anything in this case
138
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
new file mode 100644
index 000000000000..02b626bae4ae
--- /dev/null
+++ b/arch/m68k/q40/config.c
@@ -0,0 +1,365 @@
1/*
2 * arch/m68k/q40/config.c
3 *
4 * Copyright (C) 1999 Richard Zidlicky
5 *
6 * originally based on:
7 *
8 * linux/bvme/config.c
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file README.legal in the main directory of this archive
12 * for more details.
13 */
14
15#include <linux/config.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/mm.h>
19#include <linux/tty.h>
20#include <linux/console.h>
21#include <linux/linkage.h>
22#include <linux/init.h>
23#include <linux/major.h>
24#include <linux/serial_reg.h>
25#include <linux/rtc.h>
26#include <linux/vt_kern.h>
27
28#include <asm/io.h>
29#include <asm/rtc.h>
30#include <asm/bootinfo.h>
31#include <asm/system.h>
32#include <asm/pgtable.h>
33#include <asm/setup.h>
34#include <asm/irq.h>
35#include <asm/traps.h>
36#include <asm/machdep.h>
37#include <asm/q40_master.h>
38
39extern void floppy_setup(char *str, int *ints);
40
41extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
42extern irqreturn_t (*q40_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
43extern void q40_init_IRQ (void);
44extern void q40_free_irq (unsigned int, void *);
45extern int show_q40_interrupts (struct seq_file *, void *);
46extern void q40_enable_irq (unsigned int);
47extern void q40_disable_irq (unsigned int);
48static void q40_get_model(char *model);
49static int q40_get_hardware_list(char *buffer);
50extern int q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
51extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
52
53extern unsigned long q40_gettimeoffset (void);
54extern int q40_hwclk (int, struct rtc_time *);
55extern unsigned int q40_get_ss (void);
56extern int q40_set_clock_mmss (unsigned long);
57static int q40_get_rtc_pll(struct rtc_pll_info *pll);
58static int q40_set_rtc_pll(struct rtc_pll_info *pll);
59extern void q40_reset (void);
60void q40_halt(void);
61extern void q40_waitbut(void);
62void q40_set_vectors (void);
63
64extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ );
65
66extern char m68k_debug_device[];
67static void q40_mem_console_write(struct console *co, const char *b,
68 unsigned int count);
69
70extern int ql_ticks;
71
72static struct console q40_console_driver = {
73 .name = "debug",
74 .flags = CON_PRINTBUFFER,
75 .index = -1,
76};
77
78
79/* early debugging function:*/
80extern char *q40_mem_cptr; /*=(char *)0xff020000;*/
81static int _cpleft;
82
83static void q40_mem_console_write(struct console *co, const char *s,
84 unsigned int count)
85{
86 char *p=(char *)s;
87
88 if (count<_cpleft)
89 while (count-- >0){
90 *q40_mem_cptr=*p++;
91 q40_mem_cptr+=4;
92 _cpleft--;
93 }
94}
95#if 0
96void printq40(char *str)
97{
98 int l=strlen(str);
99 char *p=q40_mem_cptr;
100
101 while (l-- >0 && _cpleft-- >0)
102 {
103 *p=*str++;
104 p+=4;
105 }
106 q40_mem_cptr=p;
107}
108#endif
109
110static int halted=0;
111
112#ifdef CONFIG_HEARTBEAT
113static void q40_heartbeat(int on)
114{
115 if (halted) return;
116
117 if (on)
118 Q40_LED_ON();
119 else
120 Q40_LED_OFF();
121}
122#endif
123
124void q40_reset(void)
125{
126 halted=1;
127 printk ("\n\n*******************************************\n"
128 "Called q40_reset : press the RESET button!! \n"
129 "*******************************************\n");
130 Q40_LED_ON();
131 while(1) ;
132}
133void q40_halt(void)
134{
135 halted=1;
136 printk ("\n\n*******************\n"
137 " Called q40_halt\n"
138 "*******************\n");
139 Q40_LED_ON();
140 while(1) ;
141}
142
143static void q40_get_model(char *model)
144{
145 sprintf(model, "Q40");
146}
147
148/* No hardware options on Q40? */
149
150static int q40_get_hardware_list(char *buffer)
151{
152 *buffer = '\0';
153 return 0;
154}
155
156static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0};
157void q40_disable_irqs(void)
158{
159 unsigned i,j;
160
161 j=0;
162 while((i=serports[j++])) outb(0,i+UART_IER);
163 master_outb(0,EXT_ENABLE_REG);
164 master_outb(0,KEY_IRQ_ENABLE_REG);
165}
166
167void __init config_q40(void)
168{
169 mach_sched_init = q40_sched_init;
170
171 mach_init_IRQ = q40_init_IRQ;
172 mach_gettimeoffset = q40_gettimeoffset;
173 mach_hwclk = q40_hwclk;
174 mach_get_ss = q40_get_ss;
175 mach_get_rtc_pll = q40_get_rtc_pll;
176 mach_set_rtc_pll = q40_set_rtc_pll;
177 mach_set_clock_mmss = q40_set_clock_mmss;
178
179 mach_reset = q40_reset;
180 mach_free_irq = q40_free_irq;
181 mach_process_int = q40_process_int;
182 mach_get_irq_list = show_q40_interrupts;
183 mach_request_irq = q40_request_irq;
184 enable_irq = q40_enable_irq;
185 disable_irq = q40_disable_irq;
186 mach_default_handler = &q40_default_handler;
187 mach_get_model = q40_get_model;
188 mach_get_hardware_list = q40_get_hardware_list;
189
190#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
191 mach_beep = q40_mksound;
192#endif
193#ifdef CONFIG_HEARTBEAT
194 mach_heartbeat = q40_heartbeat;
195#endif
196 mach_halt = q40_halt;
197#ifdef CONFIG_DUMMY_CONSOLE
198 conswitchp = &dummy_con;
199#endif
200
201 /* disable a few things that SMSQ might have left enabled */
202 q40_disable_irqs();
203
204 /* no DMA at all, but ide-scsi requires it.. make sure
205 * all physical RAM fits into the boundary - otherwise
206 * allocator may play costly and useless tricks */
207 mach_max_dma_address = 1024*1024*1024;
208
209 /* useful for early debugging stages - writes kernel messages into SRAM */
210 if (!strncmp( m68k_debug_device,"mem",3 ))
211 {
212 /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
213 _cpleft=2000-((long)q40_mem_cptr-0xff020000)/4;
214 q40_console_driver.write = q40_mem_console_write;
215 register_console(&q40_console_driver);
216 }
217}
218
219
220int q40_parse_bootinfo(const struct bi_record *rec)
221{
222 return 1;
223}
224
225
226static inline unsigned char bcd2bin (unsigned char b)
227{
228 return ((b>>4)*10 + (b&15));
229}
230
231static inline unsigned char bin2bcd (unsigned char b)
232{
233 return (((b/10)*16) + (b%10));
234}
235
236
237unsigned long q40_gettimeoffset (void)
238{
239 return 5000*(ql_ticks!=0);
240}
241
242
243/*
244 * Looks like op is non-zero for setting the clock, and zero for
245 * reading the clock.
246 *
247 * struct hwclk_time {
248 * unsigned sec; 0..59
249 * unsigned min; 0..59
250 * unsigned hour; 0..23
251 * unsigned day; 1..31
252 * unsigned mon; 0..11
253 * unsigned year; 00...
254 * int wday; 0..6, 0 is Sunday, -1 means unknown/don't set
255 * };
256 */
257
258int q40_hwclk(int op, struct rtc_time *t)
259{
260 if (op)
261 { /* Write.... */
262 Q40_RTC_CTRL |= Q40_RTC_WRITE;
263
264 Q40_RTC_SECS = bin2bcd(t->tm_sec);
265 Q40_RTC_MINS = bin2bcd(t->tm_min);
266 Q40_RTC_HOUR = bin2bcd(t->tm_hour);
267 Q40_RTC_DATE = bin2bcd(t->tm_mday);
268 Q40_RTC_MNTH = bin2bcd(t->tm_mon + 1);
269 Q40_RTC_YEAR = bin2bcd(t->tm_year%100);
270 if (t->tm_wday >= 0)
271 Q40_RTC_DOW = bin2bcd(t->tm_wday+1);
272
273 Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
274 }
275 else
276 { /* Read.... */
277 Q40_RTC_CTRL |= Q40_RTC_READ;
278
279 t->tm_year = bcd2bin (Q40_RTC_YEAR);
280 t->tm_mon = bcd2bin (Q40_RTC_MNTH)-1;
281 t->tm_mday = bcd2bin (Q40_RTC_DATE);
282 t->tm_hour = bcd2bin (Q40_RTC_HOUR);
283 t->tm_min = bcd2bin (Q40_RTC_MINS);
284 t->tm_sec = bcd2bin (Q40_RTC_SECS);
285
286 Q40_RTC_CTRL &= ~(Q40_RTC_READ);
287
288 if (t->tm_year < 70)
289 t->tm_year += 100;
290 t->tm_wday = bcd2bin(Q40_RTC_DOW)-1;
291
292 }
293
294 return 0;
295}
296
297unsigned int q40_get_ss(void)
298{
299 return bcd2bin(Q40_RTC_SECS);
300}
301
302/*
303 * Set the minutes and seconds from seconds value 'nowtime'. Fail if
304 * clock is out by > 30 minutes. Logic lifted from atari code.
305 */
306
307int q40_set_clock_mmss (unsigned long nowtime)
308{
309 int retval = 0;
310 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
311
312 int rtc_minutes;
313
314
315 rtc_minutes = bcd2bin (Q40_RTC_MINS);
316
317 if ((rtc_minutes < real_minutes
318 ? real_minutes - rtc_minutes
319 : rtc_minutes - real_minutes) < 30)
320 {
321 Q40_RTC_CTRL |= Q40_RTC_WRITE;
322 Q40_RTC_MINS = bin2bcd(real_minutes);
323 Q40_RTC_SECS = bin2bcd(real_seconds);
324 Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
325 }
326 else
327 retval = -1;
328
329
330 return retval;
331}
332
333
334/* get and set PLL calibration of RTC clock */
335#define Q40_RTC_PLL_MASK ((1<<5)-1)
336#define Q40_RTC_PLL_SIGN (1<<5)
337
338static int q40_get_rtc_pll(struct rtc_pll_info *pll)
339{
340 int tmp=Q40_RTC_CTRL;
341 pll->pll_value = tmp & Q40_RTC_PLL_MASK;
342 if (tmp & Q40_RTC_PLL_SIGN)
343 pll->pll_value = -pll->pll_value;
344 pll->pll_max=31;
345 pll->pll_min=-31;
346 pll->pll_posmult=512;
347 pll->pll_negmult=256;
348 pll->pll_clock=125829120;
349 return 0;
350}
351
352static int q40_set_rtc_pll(struct rtc_pll_info *pll)
353{
354 if (!pll->pll_ctrl){
355 /* the docs are a bit unclear so I am doublesetting */
356 /* RTC_WRITE here ... */
357 int tmp = (pll->pll_value & 31) | (pll->pll_value<0 ? 32 : 0) |
358 Q40_RTC_WRITE;
359 Q40_RTC_CTRL |= Q40_RTC_WRITE;
360 Q40_RTC_CTRL = tmp;
361 Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
362 return 0;
363 } else
364 return -EINVAL;
365}
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
new file mode 100644
index 000000000000..f8ecc2664fe6
--- /dev/null
+++ b/arch/m68k/q40/q40ints.c
@@ -0,0 +1,476 @@
1/*
2 * arch/m68k/q40/q40ints.c
3 *
4 * Copyright (C) 1999,2001 Richard Zidlicky
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 *
10 * .. used to be loosely based on bvme6000ints.c
11 *
12 */
13
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/string.h>
18#include <linux/sched.h>
19#include <linux/seq_file.h>
20#include <linux/interrupt.h>
21#include <linux/hardirq.h>
22
23#include <asm/rtc.h>
24#include <asm/ptrace.h>
25#include <asm/system.h>
26#include <asm/irq.h>
27#include <asm/traps.h>
28
29#include <asm/q40_master.h>
30#include <asm/q40ints.h>
31
32/*
33 * Q40 IRQs are defined as follows:
34 * 3,4,5,6,7,10,11,14,15 : ISA dev IRQs
35 * 16-31: reserved
36 * 32 : keyboard int
37 * 33 : frame int (50/200 Hz periodic timer)
38 * 34 : sample int (10/20 KHz periodic timer)
39 *
40*/
41
42extern int ints_inited;
43
44
45irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp);
46
47
48static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
49static irqreturn_t default_handler(int lev, void *dev_id, struct pt_regs *regs);
50
51
52#define DEVNAME_SIZE 24
53
54static struct q40_irq_node {
55 irqreturn_t (*handler)(int, void *, struct pt_regs *);
56 unsigned long flags;
57 void *dev_id;
58 /* struct q40_irq_node *next;*/
59 char devname[DEVNAME_SIZE];
60 unsigned count;
61 unsigned short state;
62} irq_tab[Q40_IRQ_MAX+1];
63
64short unsigned q40_ablecount[Q40_IRQ_MAX+1];
65
66/*
67 * void q40_init_IRQ (void)
68 *
69 * Parameters: None
70 *
71 * Returns: Nothing
72 *
73 * This function is called during kernel startup to initialize
74 * the q40 IRQ handling routines.
75 */
76
77static int disabled=0;
78
79void q40_init_IRQ (void)
80{
81 int i;
82
83 disabled=0;
84 for (i = 0; i <= Q40_IRQ_MAX; i++) {
85 irq_tab[i].handler = q40_defhand;
86 irq_tab[i].flags = 0;
87 irq_tab[i].dev_id = NULL;
88 /* irq_tab[i].next = NULL;*/
89 irq_tab[i].devname[0] = 0;
90 irq_tab[i].count = 0;
91 irq_tab[i].state =0;
92 q40_ablecount[i]=0; /* all enabled */
93 }
94
95 /* setup handler for ISA ints */
96 cpu_request_irq(IRQ2, q40_irq2_handler, 0, "q40 ISA and master chip",
97 NULL);
98
99 /* now enable some ints.. */
100 master_outb(1,EXT_ENABLE_REG); /* ISA IRQ 5-15 */
101
102 /* make sure keyboard IRQ is disabled */
103 master_outb(0,KEY_IRQ_ENABLE_REG);
104}
105
106int q40_request_irq(unsigned int irq,
107 irqreturn_t (*handler)(int, void *, struct pt_regs *),
108 unsigned long flags, const char *devname, void *dev_id)
109{
110 /*printk("q40_request_irq %d, %s\n",irq,devname);*/
111
112 if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
113 printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
114 return -ENXIO;
115 }
116
117 /* test for ISA ints not implemented by HW */
118 switch (irq)
119 {
120 case 1: case 2: case 8: case 9:
121 case 12: case 13:
122 printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
123 return -ENXIO;
124 case 11:
125 printk("warning IRQ 10 and 11 not distinguishable\n");
126 irq=10;
127 default:
128 ;
129 }
130
131 if (irq<Q40_IRQ_SAMPLE)
132 {
133 if (irq_tab[irq].dev_id != NULL)
134 {
135 printk("%s: IRQ %d from %s is not replaceable\n",
136 __FUNCTION__, irq, irq_tab[irq].devname);
137 return -EBUSY;
138 }
139 /*printk("IRQ %d set to handler %p\n",irq,handler);*/
140 if (dev_id==NULL)
141 {
142 printk("WARNING: dev_id == NULL in request_irq\n");
143 dev_id=(void*)1;
144 }
145 irq_tab[irq].handler = handler;
146 irq_tab[irq].flags = flags;
147 irq_tab[irq].dev_id = dev_id;
148 strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname));
149 irq_tab[irq].state = 0;
150 return 0;
151 }
152 else {
153 /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/
154 cpu_request_irq(4, handler, flags, devname, dev_id);
155 cpu_request_irq(6, handler, flags, devname, dev_id);
156 return 0;
157 }
158}
159
160void q40_free_irq(unsigned int irq, void *dev_id)
161{
162 if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
163 printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id);
164 return;
165 }
166
167 /* test for ISA ints not implemented by HW */
168 switch (irq)
169 {
170 case 1: case 2: case 8: case 9:
171 case 12: case 13:
172 printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id);
173 return;
174 case 11: irq=10;
175 default:
176 ;
177 }
178
179 if (irq<Q40_IRQ_SAMPLE)
180 {
181 if (irq_tab[irq].dev_id != dev_id)
182 printk("%s: Removing probably wrong IRQ %d from %s\n",
183 __FUNCTION__, irq, irq_tab[irq].devname);
184
185 irq_tab[irq].handler = q40_defhand;
186 irq_tab[irq].flags = 0;
187 irq_tab[irq].dev_id = NULL;
188 /* irq_tab[irq].devname = NULL; */
189 /* do not reset state !! */
190 }
191 else
192 { /* == Q40_IRQ_SAMPLE */
193 cpu_free_irq(4, dev_id);
194 cpu_free_irq(6, dev_id);
195 }
196}
197
198
199irqreturn_t q40_process_int (int level, struct pt_regs *fp)
200{
201 printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n",
202 level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2);
203 printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG));
204 return IRQ_HANDLED;
205}
206
207/*
208 * this stuff doesn't really belong here..
209*/
210
211int ql_ticks; /* 200Hz ticks since last jiffie */
212static int sound_ticks;
213
214#define SVOL 45
215
216void q40_mksound(unsigned int hz, unsigned int ticks)
217{
218 /* for now ignore hz, except that hz==0 switches off sound */
219 /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
220 if (hz==0)
221 {
222 if (sound_ticks)
223 sound_ticks=1;
224
225 *DAC_LEFT=128;
226 *DAC_RIGHT=128;
227
228 return;
229 }
230 /* sound itself is done in q40_timer_int */
231 if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
232 sound_ticks=ticks<<1;
233}
234
235static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *);
236
237static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs)
238{
239 ql_ticks = ql_ticks ? 0 : 1;
240 if (sound_ticks)
241 {
242 unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
243 sound_ticks--;
244 *DAC_LEFT=sval;
245 *DAC_RIGHT=sval;
246 }
247
248 if (!ql_ticks)
249 q40_timer_routine(irq, dev, regs);
250 return IRQ_HANDLED;
251}
252
253void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
254{
255 int timer_irq;
256
257 q40_timer_routine = timer_routine;
258 timer_irq=Q40_IRQ_FRAME;
259
260 if (request_irq(timer_irq, q40_timer_int, 0,
261 "timer", q40_timer_int))
262 panic ("Couldn't register timer int");
263
264 master_outb(-1,FRAME_CLEAR_REG);
265 master_outb( 1,FRAME_RATE_REG);
266}
267
268
269/*
270 * tables to translate bits into IRQ numbers
271 * it is a good idea to order the entries by priority
272 *
273*/
274
275struct IRQ_TABLE{ unsigned mask; int irq ;};
276#if 0
277static struct IRQ_TABLE iirqs[]={
278 {Q40_IRQ_FRAME_MASK,Q40_IRQ_FRAME},
279 {Q40_IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
280 {0,0}};
281#endif
282static struct IRQ_TABLE eirqs[] = {
283 { .mask = Q40_IRQ3_MASK, .irq = 3 }, /* ser 1 */
284 { .mask = Q40_IRQ4_MASK, .irq = 4 }, /* ser 2 */
285 { .mask = Q40_IRQ14_MASK, .irq = 14 }, /* IDE 1 */
286 { .mask = Q40_IRQ15_MASK, .irq = 15 }, /* IDE 2 */
287 { .mask = Q40_IRQ6_MASK, .irq = 6 }, /* floppy, handled elsewhere */
288 { .mask = Q40_IRQ7_MASK, .irq = 7 }, /* par */
289 { .mask = Q40_IRQ5_MASK, .irq = 5 },
290 { .mask = Q40_IRQ10_MASK, .irq = 10 },
291 {0,0}
292};
293
294/* complain only this many times about spurious ints : */
295static int ccleirq=60; /* ISA dev IRQ's*/
296/*static int cclirq=60;*/ /* internal */
297
298/* FIXME: add shared ints,mask,unmask,probing.... */
299
300#define IRQ_INPROGRESS 1
301/*static unsigned short saved_mask;*/
302//static int do_tint=0;
303
304#define DEBUG_Q40INT
305/*#define IP_USE_DISABLE *//* would be nice, but crashes ???? */
306
307static int mext_disabled=0; /* ext irq disabled by master chip? */
308static int aliased_irq=0; /* how many times inside handler ?*/
309
310
311/* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */
312irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
313{
314 unsigned mir, mer;
315 int irq,i;
316
317//repeat:
318 mir=master_inb(IIRQ_REG);
319 if (mir&Q40_IRQ_FRAME_MASK) {
320 irq_tab[Q40_IRQ_FRAME].count++;
321 irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);
322 master_outb(-1,FRAME_CLEAR_REG);
323 }
324 if ((mir&Q40_IRQ_SER_MASK) || (mir&Q40_IRQ_EXT_MASK)) {
325 mer=master_inb(EIRQ_REG);
326 for (i=0; eirqs[i].mask; i++) {
327 if (mer&(eirqs[i].mask)) {
328 irq=eirqs[i].irq;
329/*
330 * There is a little mess wrt which IRQ really caused this irq request. The
331 * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they
332 * are read - which is long after the request came in. In theory IRQs should
333 * not just go away but they occassionally do
334 */
335 if (irq>4 && irq<=15 && mext_disabled) {
336 /*aliased_irq++;*/
337 goto iirq;
338 }
339 if (irq_tab[irq].handler == q40_defhand ) {
340 printk("handler for IRQ %d not defined\n",irq);
341 continue; /* ignore uninited INTs :-( */
342 }
343 if ( irq_tab[irq].state & IRQ_INPROGRESS ) {
344 /* some handlers do local_irq_enable() for irq latency reasons, */
345 /* however reentering an active irq handler is not permitted */
346#ifdef IP_USE_DISABLE
347 /* in theory this is the better way to do it because it still */
348 /* lets through eg the serial irqs, unfortunately it crashes */
349 disable_irq(irq);
350 disabled=1;
351#else
352 /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */
353 fp->sr = (((fp->sr) & (~0x700))+0x200);
354 disabled=1;
355#endif
356 goto iirq;
357 }
358 irq_tab[irq].count++;
359 irq_tab[irq].state |= IRQ_INPROGRESS;
360 irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
361 irq_tab[irq].state &= ~IRQ_INPROGRESS;
362
363 /* naively enable everything, if that fails than */
364 /* this function will be reentered immediately thus */
365 /* getting another chance to disable the IRQ */
366
367 if ( disabled ) {
368#ifdef IP_USE_DISABLE
369 if (irq>4){
370 disabled=0;
371 enable_irq(irq);}
372#else
373 disabled=0;
374 /*printk("reenabling irq %d\n",irq); */
375#endif
376 }
377// used to do 'goto repeat;' here, this delayed bh processing too long
378 return IRQ_HANDLED;
379 }
380 }
381 if (mer && ccleirq>0 && !aliased_irq)
382 printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
383 }
384 iirq:
385 mir=master_inb(IIRQ_REG);
386 /* should test whether keyboard irq is really enabled, doing it in defhand */
387 if (mir&Q40_IRQ_KEYB_MASK) {
388 irq_tab[Q40_IRQ_KEYBOARD].count++;
389 irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
390 }
391 return IRQ_HANDLED;
392}
393
394int show_q40_interrupts (struct seq_file *p, void *v)
395{
396 int i;
397
398 for (i = 0; i <= Q40_IRQ_MAX; i++) {
399 if (irq_tab[i].count)
400 seq_printf(p, "%sIRQ %02d: %8d %s%s\n",
401 (i<=15) ? "ISA-" : " " ,
402 i, irq_tab[i].count,
403 irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
404 irq_tab[i].handler == q40_defhand ?
405 " (now unassigned)" : "");
406 }
407 return 0;
408}
409
410
411static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
412{
413 if (irq!=Q40_IRQ_KEYBOARD)
414 printk ("Unknown q40 interrupt %d\n", irq);
415 else master_outb(-1,KEYBOARD_UNLOCK_REG);
416 return IRQ_NONE;
417}
418static irqreturn_t default_handler(int lev, void *dev_id, struct pt_regs *regs)
419{
420 printk ("Uninitialised interrupt level %d\n", lev);
421 return IRQ_NONE;
422}
423
424irqreturn_t (*q40_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
425 [0] = default_handler,
426 [1] = default_handler,
427 [2] = default_handler,
428 [3] = default_handler,
429 [4] = default_handler,
430 [5] = default_handler,
431 [6] = default_handler,
432 [7] = default_handler
433};
434
435
436void q40_enable_irq (unsigned int irq)
437{
438 if ( irq>=5 && irq<=15 )
439 {
440 mext_disabled--;
441 if (mext_disabled>0)
442 printk("q40_enable_irq : nested disable/enable\n");
443 if (mext_disabled==0)
444 master_outb(1,EXT_ENABLE_REG);
445 }
446}
447
448
449void q40_disable_irq (unsigned int irq)
450{
451 /* disable ISA iqs : only do something if the driver has been
452 * verified to be Q40 "compatible" - right now IDE, NE2K
453 * Any driver should not attempt to sleep across disable_irq !!
454 */
455
456 if ( irq>=5 && irq<=15 ) {
457 master_outb(0,EXT_ENABLE_REG);
458 mext_disabled++;
459 if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled);
460 }
461}
462
463unsigned long q40_probe_irq_on (void)
464{
465 printk("irq probing not working - reconfigure the driver to avoid this\n");
466 return -1;
467}
468int q40_probe_irq_off (unsigned long irqs)
469{
470 return -1;
471}
472/*
473 * Local variables:
474 * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040 -c -o q40ints.o q40ints.c"
475 * End:
476 */
diff --git a/arch/m68k/sun3/Makefile b/arch/m68k/sun3/Makefile
new file mode 100644
index 000000000000..4d4f0695d985
--- /dev/null
+++ b/arch/m68k/sun3/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for Linux arch/m68k/sun3 source directory
3#
4
5obj-y := sun3_ksyms.o sun3ints.o sun3dvma.o sbus.o idprom.o
6
7obj-$(CONFIG_SUN3) += config.o mmu_emu.o leds.o dvma.o intersil.o
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
new file mode 100644
index 000000000000..77d05bcc3221
--- /dev/null
+++ b/arch/m68k/sun3/config.c
@@ -0,0 +1,188 @@
1/*
2 * linux/arch/m68k/sun3/config.c
3 *
4 * Copyright (C) 1996,1997 Pekka Pietik{inen
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/config.h>
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/mm.h>
15#include <linux/tty.h>
16#include <linux/console.h>
17#include <linux/init.h>
18#include <linux/bootmem.h>
19
20#include <asm/oplib.h>
21#include <asm/setup.h>
22#include <asm/contregs.h>
23#include <asm/movs.h>
24#include <asm/pgtable.h>
25#include <asm/sun3-head.h>
26#include <asm/sun3mmu.h>
27#include <asm/rtc.h>
28#include <asm/machdep.h>
29#include <asm/intersil.h>
30#include <asm/irq.h>
31#include <asm/segment.h>
32#include <asm/sun3ints.h>
33
34extern char _text, _end;
35
36char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
37
38extern unsigned long sun3_gettimeoffset(void);
39extern int show_sun3_interrupts (struct seq_file *, void *);
40extern void sun3_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
41extern void sun3_get_model (char* model);
42extern void idprom_init (void);
43extern int sun3_hwclk(int set, struct rtc_time *t);
44
45volatile char* clock_va;
46extern volatile unsigned char* sun3_intreg;
47extern unsigned long availmem;
48unsigned long num_pages;
49
50static int sun3_get_hardware_list(char *buffer)
51{
52
53 int len = 0;
54
55 len += sprintf(buffer + len, "PROM Revision:\t%s\n",
56 romvec->pv_monid);
57
58 return len;
59
60}
61
62void __init sun3_init(void)
63{
64 unsigned char enable_register;
65 int i;
66
67 m68k_machtype= MACH_SUN3;
68 m68k_cputype = CPU_68020;
69 m68k_fputype = FPU_68881; /* mc68881 actually */
70 m68k_mmutype = MMU_SUN3;
71 clock_va = (char *) 0xfe06000; /* dark */
72 sun3_intreg = (unsigned char *) 0xfe0a000; /* magic */
73 sun3_disable_interrupts();
74
75 prom_init((void *)LINUX_OPPROM_BEGVM);
76
77 GET_CONTROL_BYTE(AC_SENABLE,enable_register);
78 enable_register |= 0x50; /* Enable FPU */
79 SET_CONTROL_BYTE(AC_SENABLE,enable_register);
80 GET_CONTROL_BYTE(AC_SENABLE,enable_register);
81
82 /* This code looks suspicious, because it doesn't subtract
83 memory belonging to the kernel from the available space */
84
85
86 memset(sun3_reserved_pmeg, 0, sizeof(sun3_reserved_pmeg));
87
88 /* Reserve important PMEGS */
89 /* FIXME: These should be probed instead of hardcoded */
90
91 for (i=0; i<8; i++) /* Kernel PMEGs */
92 sun3_reserved_pmeg[i] = 1;
93
94 sun3_reserved_pmeg[247] = 1; /* ROM mapping */
95 sun3_reserved_pmeg[248] = 1; /* AMD Ethernet */
96 sun3_reserved_pmeg[251] = 1; /* VB area */
97 sun3_reserved_pmeg[254] = 1; /* main I/O */
98
99 sun3_reserved_pmeg[249] = 1;
100 sun3_reserved_pmeg[252] = 1;
101 sun3_reserved_pmeg[253] = 1;
102 set_fs(KERNEL_DS);
103}
104
105/* Without this, Bad Things happen when something calls arch_reset. */
106static void sun3_reboot (void)
107{
108 prom_reboot ("vmlinux");
109}
110
111static void sun3_halt (void)
112{
113 prom_halt ();
114}
115
116/* sun3 bootmem allocation */
117
118void __init sun3_bootmem_alloc(unsigned long memory_start, unsigned long memory_end)
119{
120 unsigned long start_page;
121
122 /* align start/end to page boundaries */
123 memory_start = ((memory_start + (PAGE_SIZE-1)) & PAGE_MASK);
124 memory_end = memory_end & PAGE_MASK;
125
126 start_page = __pa(memory_start) >> PAGE_SHIFT;
127 num_pages = __pa(memory_end) >> PAGE_SHIFT;
128
129 high_memory = (void *)memory_end;
130 availmem = memory_start;
131
132 availmem += init_bootmem_node(NODE_DATA(0), start_page, 0, num_pages);
133 availmem = (availmem + (PAGE_SIZE-1)) & PAGE_MASK;
134
135 free_bootmem(__pa(availmem), memory_end - (availmem));
136}
137
138
139void __init config_sun3(void)
140{
141 unsigned long memory_start, memory_end;
142
143 printk("ARCH: SUN3\n");
144 idprom_init();
145
146 /* Subtract kernel memory from available memory */
147
148 mach_sched_init = sun3_sched_init;
149 mach_init_IRQ = sun3_init_IRQ;
150 mach_default_handler = &sun3_default_handler;
151 mach_request_irq = sun3_request_irq;
152 mach_free_irq = sun3_free_irq;
153 enable_irq = sun3_enable_irq;
154 disable_irq = sun3_disable_irq;
155 mach_process_int = sun3_process_int;
156 mach_get_irq_list = show_sun3_interrupts;
157 mach_reset = sun3_reboot;
158 mach_gettimeoffset = sun3_gettimeoffset;
159 mach_get_model = sun3_get_model;
160 mach_hwclk = sun3_hwclk;
161 mach_halt = sun3_halt;
162 mach_get_hardware_list = sun3_get_hardware_list;
163#if defined(CONFIG_DUMMY_CONSOLE)
164 conswitchp = &dummy_con;
165#endif
166
167 memory_start = ((((int)&_end) + 0x2000) & ~0x1fff);
168// PROM seems to want the last couple of physical pages. --m
169 memory_end = *(romvec->pv_sun3mem) + PAGE_OFFSET - 2*PAGE_SIZE;
170
171 m68k_num_memory=1;
172 m68k_memory[0].size=*(romvec->pv_sun3mem);
173
174 sun3_bootmem_alloc(memory_start, memory_end);
175}
176
177void __init sun3_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
178{
179 sun3_disable_interrupts();
180 intersil_clock->cmd_reg=(INTERSIL_RUN|INTERSIL_INT_DISABLE|INTERSIL_24H_MODE);
181 intersil_clock->int_reg=INTERSIL_HZ_100_MASK;
182 intersil_clear();
183 sun3_enable_irq(5);
184 intersil_clock->cmd_reg=(INTERSIL_RUN|INTERSIL_INT_ENABLE|INTERSIL_24H_MODE);
185 sun3_enable_interrupts();
186 intersil_clear();
187}
188
diff --git a/arch/m68k/sun3/dvma.c b/arch/m68k/sun3/dvma.c
new file mode 100644
index 000000000000..d2b3093f2405
--- /dev/null
+++ b/arch/m68k/sun3/dvma.c
@@ -0,0 +1,71 @@
1/*
2 * linux/arch/m68k/sun3/dvma.c
3 *
4 * Written by Sam Creasey
5 *
6 * Sun3 IOMMU routines used for dvma accesses.
7 *
8 */
9
10#include <linux/kernel.h>
11#include <linux/mm.h>
12#include <linux/bootmem.h>
13#include <linux/list.h>
14#include <asm/page.h>
15#include <asm/pgtable.h>
16#include <asm/sun3mmu.h>
17#include <asm/dvma.h>
18
19
20static unsigned long ptelist[120];
21
22inline unsigned long dvma_page(unsigned long kaddr, unsigned long vaddr)
23{
24 unsigned long pte;
25 unsigned long j;
26 pte_t ptep;
27
28 j = *(volatile unsigned long *)kaddr;
29 *(volatile unsigned long *)kaddr = j;
30
31 ptep = pfn_pte(virt_to_pfn(kaddr), PAGE_KERNEL);
32 pte = pte_val(ptep);
33// printk("dvma_remap: addr %lx -> %lx pte %08lx len %x\n",
34// kaddr, vaddr, pte, len);
35 if(ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] != pte) {
36 sun3_put_pte(vaddr, pte);
37 ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] = pte;
38 }
39
40 return (vaddr + (kaddr & ~PAGE_MASK));
41
42}
43
44int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
45 int len)
46{
47
48 unsigned long end;
49 unsigned long vaddr;
50
51 vaddr = dvma_btov(baddr);
52
53 end = vaddr + len;
54
55 while(vaddr < end) {
56 dvma_page(kaddr, vaddr);
57 kaddr += PAGE_SIZE;
58 vaddr += PAGE_SIZE;
59 }
60
61 return 0;
62
63}
64
65void sun3_dvma_init(void)
66{
67
68 memset(ptelist, 0, sizeof(ptelist));
69
70
71}
diff --git a/arch/m68k/sun3/idprom.c b/arch/m68k/sun3/idprom.c
new file mode 100644
index 000000000000..02c1fee6fe74
--- /dev/null
+++ b/arch/m68k/sun3/idprom.c
@@ -0,0 +1,129 @@
1/* $Id: idprom.c,v 1.22 1996/11/13 05:09:25 davem Exp $
2 * idprom.c: Routines to load the idprom into kernel addresses and
3 * interpret the data contained within.
4 *
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 * Sun3/3x models added by David Monro (davidm@psrg.cs.usyd.edu.au)
7 */
8
9#include <linux/kernel.h>
10#include <linux/types.h>
11#include <linux/init.h>
12#include <linux/string.h>
13
14#include <asm/oplib.h>
15#include <asm/idprom.h>
16#include <asm/machines.h> /* Fun with Sun released architectures. */
17
18struct idprom *idprom;
19static struct idprom idprom_buffer;
20
21/* Here is the master table of Sun machines which use some implementation
22 * of the Sparc CPU and have a meaningful IDPROM machtype value that we
23 * know about. See asm-sparc/machines.h for empirical constants.
24 */
25struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = {
26/* First, Sun3's */
27 { .name = "Sun 3/160 Series", .id_machtype = (SM_SUN3 | SM_3_160) },
28 { .name = "Sun 3/50", .id_machtype = (SM_SUN3 | SM_3_50) },
29 { .name = "Sun 3/260 Series", .id_machtype = (SM_SUN3 | SM_3_260) },
30 { .name = "Sun 3/110 Series", .id_machtype = (SM_SUN3 | SM_3_110) },
31 { .name = "Sun 3/60", .id_machtype = (SM_SUN3 | SM_3_60) },
32 { .name = "Sun 3/E", .id_machtype = (SM_SUN3 | SM_3_E) },
33/* Now, Sun3x's */
34 { .name = "Sun 3/460 Series", .id_machtype = (SM_SUN3X | SM_3_460) },
35 { .name = "Sun 3/80", .id_machtype = (SM_SUN3X | SM_3_80) },
36/* Then, Sun4's */
37// { .name = "Sun 4/100 Series", .id_machtype = (SM_SUN4 | SM_4_110) },
38// { .name = "Sun 4/200 Series", .id_machtype = (SM_SUN4 | SM_4_260) },
39// { .name = "Sun 4/300 Series", .id_machtype = (SM_SUN4 | SM_4_330) },
40// { .name = "Sun 4/400 Series", .id_machtype = (SM_SUN4 | SM_4_470) },
41/* And now, Sun4c's */
42// { .name = "Sun4c SparcStation 1", .id_machtype = (SM_SUN4C | SM_4C_SS1) },
43// { .name = "Sun4c SparcStation IPC", .id_machtype = (SM_SUN4C | SM_4C_IPC) },
44// { .name = "Sun4c SparcStation 1+", .id_machtype = (SM_SUN4C | SM_4C_SS1PLUS) },
45// { .name = "Sun4c SparcStation SLC", .id_machtype = (SM_SUN4C | SM_4C_SLC) },
46// { .name = "Sun4c SparcStation 2", .id_machtype = (SM_SUN4C | SM_4C_SS2) },
47// { .name = "Sun4c SparcStation ELC", .id_machtype = (SM_SUN4C | SM_4C_ELC) },
48// { .name = "Sun4c SparcStation IPX", .id_machtype = (SM_SUN4C | SM_4C_IPX) },
49/* Finally, early Sun4m's */
50// { .name = "Sun4m SparcSystem600", .id_machtype = (SM_SUN4M | SM_4M_SS60) },
51// { .name = "Sun4m SparcStation10/20", .id_machtype = (SM_SUN4M | SM_4M_SS50) },
52// { .name = "Sun4m SparcStation5", .id_machtype = (SM_SUN4M | SM_4M_SS40) },
53/* One entry for the OBP arch's which are sun4d, sun4e, and newer sun4m's */
54// { .name = "Sun4M OBP based system", .id_machtype = (SM_SUN4M_OBP | 0x0) }
55};
56
57static void __init display_system_type(unsigned char machtype)
58{
59 register int i;
60
61 for (i = 0; i < NUM_SUN_MACHINES; i++) {
62 if(Sun_Machines[i].id_machtype == machtype) {
63 if (machtype != (SM_SUN4M_OBP | 0x00))
64 printk("TYPE: %s\n", Sun_Machines[i].name);
65 else {
66#if 0
67 prom_getproperty(prom_root_node, "banner-name",
68 sysname, sizeof(sysname));
69 printk("TYPE: %s\n", sysname);
70#endif
71 }
72 return;
73 }
74 }
75
76 prom_printf("IDPROM: Bogus id_machtype value, 0x%x\n", machtype);
77 prom_halt();
78}
79
80void sun3_get_model(unsigned char* model)
81{
82 register int i;
83
84 for (i = 0; i < NUM_SUN_MACHINES; i++) {
85 if(Sun_Machines[i].id_machtype == idprom->id_machtype) {
86 strcpy(model, Sun_Machines[i].name);
87 return;
88 }
89 }
90}
91
92
93
94/* Calculate the IDPROM checksum (xor of the data bytes). */
95static unsigned char __init calc_idprom_cksum(struct idprom *idprom)
96{
97 unsigned char cksum, i, *ptr = (unsigned char *)idprom;
98
99 for (i = cksum = 0; i <= 0x0E; i++)
100 cksum ^= *ptr++;
101
102 return cksum;
103}
104
105/* Create a local IDPROM copy, verify integrity, and display information. */
106void __init idprom_init(void)
107{
108 prom_get_idprom((char *) &idprom_buffer, sizeof(idprom_buffer));
109
110 idprom = &idprom_buffer;
111
112 if (idprom->id_format != 0x01) {
113 prom_printf("IDPROM: Unknown format type!\n");
114 prom_halt();
115 }
116
117 if (idprom->id_cksum != calc_idprom_cksum(idprom)) {
118 prom_printf("IDPROM: Checksum failure (nvram=%x, calc=%x)!\n",
119 idprom->id_cksum, calc_idprom_cksum(idprom));
120 prom_halt();
121 }
122
123 display_system_type(idprom->id_machtype);
124
125 printk("Ethernet address: %x:%x:%x:%x:%x:%x\n",
126 idprom->id_ethaddr[0], idprom->id_ethaddr[1],
127 idprom->id_ethaddr[2], idprom->id_ethaddr[3],
128 idprom->id_ethaddr[4], idprom->id_ethaddr[5]);
129}
diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
new file mode 100644
index 000000000000..db359d7402a6
--- /dev/null
+++ b/arch/m68k/sun3/intersil.c
@@ -0,0 +1,76 @@
1/*
2 * arch/m68k/sun3/intersil.c
3 *
4 * basic routines for accessing the intersil clock within the sun3 machines
5 *
6 * started 11/12/1999 Sam Creasey
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/rtc.h>
15
16#include <asm/errno.h>
17#include <asm/system.h>
18#include <asm/semaphore.h>
19#include <asm/rtc.h>
20#include <asm/intersil.h>
21
22
23/* bits to set for start/run of the intersil */
24#define STOP_VAL (INTERSIL_STOP | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE)
25#define START_VAL (INTERSIL_RUN | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE)
26
27/* does this need to be implemented? */
28unsigned long sun3_gettimeoffset(void)
29{
30 return 1;
31}
32
33
34/* get/set hwclock */
35
36int sun3_hwclk(int set, struct rtc_time *t)
37{
38 volatile struct intersil_dt *todintersil;
39 unsigned long flags;
40
41 todintersil = (struct intersil_dt *) &intersil_clock->counter;
42
43 local_irq_save(flags);
44
45 intersil_clock->cmd_reg = STOP_VAL;
46
47 /* set or read the clock */
48 if(set) {
49 todintersil->csec = 0;
50 todintersil->hour = t->tm_hour;
51 todintersil->minute = t->tm_min;
52 todintersil->second = t->tm_sec;
53 todintersil->month = t->tm_mon;
54 todintersil->day = t->tm_mday;
55 todintersil->year = t->tm_year - 68;
56 todintersil->weekday = t->tm_wday;
57 } else {
58 /* read clock */
59 t->tm_sec = todintersil->csec;
60 t->tm_hour = todintersil->hour;
61 t->tm_min = todintersil->minute;
62 t->tm_sec = todintersil->second;
63 t->tm_mon = todintersil->month;
64 t->tm_mday = todintersil->day;
65 t->tm_year = todintersil->year + 68;
66 t->tm_wday = todintersil->weekday;
67 }
68
69 intersil_clock->cmd_reg = START_VAL;
70
71 local_irq_restore(flags);
72
73 return 0;
74
75}
76
diff --git a/arch/m68k/sun3/leds.c b/arch/m68k/sun3/leds.c
new file mode 100644
index 000000000000..a3e948463982
--- /dev/null
+++ b/arch/m68k/sun3/leds.c
@@ -0,0 +1,13 @@
1#include <asm/contregs.h>
2#include <asm/sun3mmu.h>
3#include <asm/io.h>
4
5void sun3_leds(unsigned char byte)
6{
7 unsigned char dfc;
8
9 GET_DFC(dfc);
10 SET_DFC(FC_CONTROL);
11 SET_CONTROL_BYTE(AC_LEDS,byte);
12 SET_DFC(dfc);
13}
diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c
new file mode 100644
index 000000000000..7a0e3a220687
--- /dev/null
+++ b/arch/m68k/sun3/mmu_emu.c
@@ -0,0 +1,427 @@
1/*
2** Tablewalk MMU emulator
3**
4** by Toshiyasu Morita
5**
6** Started 1/16/98 @ 2:22 am
7*/
8
9#include <linux/mman.h>
10#include <linux/mm.h>
11#include <linux/kernel.h>
12#include <linux/ptrace.h>
13#include <linux/delay.h>
14#include <linux/bootmem.h>
15#include <linux/bitops.h>
16#include <linux/module.h>
17
18#include <asm/setup.h>
19#include <asm/traps.h>
20#include <asm/system.h>
21#include <asm/uaccess.h>
22#include <asm/page.h>
23#include <asm/pgtable.h>
24#include <asm/sun3mmu.h>
25#include <asm/segment.h>
26#include <asm/oplib.h>
27#include <asm/mmu_context.h>
28#include <asm/dvma.h>
29
30extern void prom_reboot (char *) __attribute__ ((__noreturn__));
31
32#undef DEBUG_MMU_EMU
33#define DEBUG_PROM_MAPS
34
35/*
36** Defines
37*/
38
39#define CONTEXTS_NUM 8
40#define SEGMAPS_PER_CONTEXT_NUM 2048
41#define PAGES_PER_SEGMENT 16
42#define PMEGS_NUM 256
43#define PMEG_MASK 0xFF
44
45/*
46** Globals
47*/
48
49unsigned long vmalloc_end;
50EXPORT_SYMBOL(vmalloc_end);
51
52unsigned long pmeg_vaddr[PMEGS_NUM];
53unsigned char pmeg_alloc[PMEGS_NUM];
54unsigned char pmeg_ctx[PMEGS_NUM];
55
56/* pointers to the mm structs for each task in each
57 context. 0xffffffff is a marker for kernel context */
58struct mm_struct *ctx_alloc[CONTEXTS_NUM] = {
59 [0] = (struct mm_struct *)0xffffffff
60};
61
62/* has this context been mmdrop'd? */
63static unsigned char ctx_avail = CONTEXTS_NUM-1;
64
65/* array of pages to be marked off for the rom when we do mem_init later */
66/* 256 pages lets the rom take up to 2mb of physical ram.. I really
67 hope it never wants mote than that. */
68unsigned long rom_pages[256];
69
70/* Print a PTE value in symbolic form. For debugging. */
71void print_pte (pte_t pte)
72{
73#if 0
74 /* Verbose version. */
75 unsigned long val = pte_val (pte);
76 printk (" pte=%lx [addr=%lx",
77 val, (val & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT);
78 if (val & SUN3_PAGE_VALID) printk (" valid");
79 if (val & SUN3_PAGE_WRITEABLE) printk (" write");
80 if (val & SUN3_PAGE_SYSTEM) printk (" sys");
81 if (val & SUN3_PAGE_NOCACHE) printk (" nocache");
82 if (val & SUN3_PAGE_ACCESSED) printk (" accessed");
83 if (val & SUN3_PAGE_MODIFIED) printk (" modified");
84 switch (val & SUN3_PAGE_TYPE_MASK) {
85 case SUN3_PAGE_TYPE_MEMORY: printk (" memory"); break;
86 case SUN3_PAGE_TYPE_IO: printk (" io"); break;
87 case SUN3_PAGE_TYPE_VME16: printk (" vme16"); break;
88 case SUN3_PAGE_TYPE_VME32: printk (" vme32"); break;
89 }
90 printk ("]\n");
91#else
92 /* Terse version. More likely to fit on a line. */
93 unsigned long val = pte_val (pte);
94 char flags[7], *type;
95
96 flags[0] = (val & SUN3_PAGE_VALID) ? 'v' : '-';
97 flags[1] = (val & SUN3_PAGE_WRITEABLE) ? 'w' : '-';
98 flags[2] = (val & SUN3_PAGE_SYSTEM) ? 's' : '-';
99 flags[3] = (val & SUN3_PAGE_NOCACHE) ? 'x' : '-';
100 flags[4] = (val & SUN3_PAGE_ACCESSED) ? 'a' : '-';
101 flags[5] = (val & SUN3_PAGE_MODIFIED) ? 'm' : '-';
102 flags[6] = '\0';
103
104 switch (val & SUN3_PAGE_TYPE_MASK) {
105 case SUN3_PAGE_TYPE_MEMORY: type = "memory"; break;
106 case SUN3_PAGE_TYPE_IO: type = "io" ; break;
107 case SUN3_PAGE_TYPE_VME16: type = "vme16" ; break;
108 case SUN3_PAGE_TYPE_VME32: type = "vme32" ; break;
109 default: type = "unknown?"; break;
110 }
111
112 printk (" pte=%08lx [%07lx %s %s]\n",
113 val, (val & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT, flags, type);
114#endif
115}
116
117/* Print the PTE value for a given virtual address. For debugging. */
118void print_pte_vaddr (unsigned long vaddr)
119{
120 printk (" vaddr=%lx [%02lx]", vaddr, sun3_get_segmap (vaddr));
121 print_pte (__pte (sun3_get_pte (vaddr)));
122}
123
124/*
125 * Initialise the MMU emulator.
126 */
127void mmu_emu_init(unsigned long bootmem_end)
128{
129 unsigned long seg, num;
130 int i,j;
131
132 memset(rom_pages, 0, sizeof(rom_pages));
133 memset(pmeg_vaddr, 0, sizeof(pmeg_vaddr));
134 memset(pmeg_alloc, 0, sizeof(pmeg_alloc));
135 memset(pmeg_ctx, 0, sizeof(pmeg_ctx));
136
137 /* pmeg align the end of bootmem, adding another pmeg,
138 * later bootmem allocations will likely need it */
139 bootmem_end = (bootmem_end + (2 * SUN3_PMEG_SIZE)) & ~SUN3_PMEG_MASK;
140
141 /* mark all of the pmegs used thus far as reserved */
142 for (i=0; i < __pa(bootmem_end) / SUN3_PMEG_SIZE ; ++i)
143 pmeg_alloc[i] = 2;
144
145
146 /* I'm thinking that most of the top pmeg's are going to be
147 used for something, and we probably shouldn't risk it */
148 for(num = 0xf0; num <= 0xff; num++)
149 pmeg_alloc[num] = 2;
150
151 /* liberate all existing mappings in the rest of kernel space */
152 for(seg = bootmem_end; seg < 0x0f800000; seg += SUN3_PMEG_SIZE) {
153 i = sun3_get_segmap(seg);
154
155 if(!pmeg_alloc[i]) {
156#ifdef DEBUG_MMU_EMU
157 printk("freed: ");
158 print_pte_vaddr (seg);
159#endif
160 sun3_put_segmap(seg, SUN3_INVALID_PMEG);
161 }
162 }
163
164 j = 0;
165 for (num=0, seg=0x0F800000; seg<0x10000000; seg+=16*PAGE_SIZE) {
166 if (sun3_get_segmap (seg) != SUN3_INVALID_PMEG) {
167#ifdef DEBUG_PROM_MAPS
168 for(i = 0; i < 16; i++) {
169 printk ("mapped:");
170 print_pte_vaddr (seg + (i*PAGE_SIZE));
171 break;
172 }
173#endif
174 // the lowest mapping here is the end of our
175 // vmalloc region
176 if(!vmalloc_end)
177 vmalloc_end = seg;
178
179 // mark the segmap alloc'd, and reserve any
180 // of the first 0xbff pages the hardware is
181 // already using... does any sun3 support > 24mb?
182 pmeg_alloc[sun3_get_segmap(seg)] = 2;
183 }
184 }
185
186 dvma_init();
187
188
189 /* blank everything below the kernel, and we've got the base
190 mapping to start all the contexts off with... */
191 for(seg = 0; seg < PAGE_OFFSET; seg += SUN3_PMEG_SIZE)
192 sun3_put_segmap(seg, SUN3_INVALID_PMEG);
193
194 set_fs(MAKE_MM_SEG(3));
195 for(seg = 0; seg < 0x10000000; seg += SUN3_PMEG_SIZE) {
196 i = sun3_get_segmap(seg);
197 for(j = 1; j < CONTEXTS_NUM; j++)
198 (*(romvec->pv_setctxt))(j, (void *)seg, i);
199 }
200 set_fs(KERNEL_DS);
201
202}
203
204/* erase the mappings for a dead context. Uses the pg_dir for hints
205 as the pmeg tables proved somewhat unreliable, and unmapping all of
206 TASK_SIZE was much slower and no more stable. */
207/* todo: find a better way to keep track of the pmegs used by a
208 context for when they're cleared */
209void clear_context(unsigned long context)
210{
211 unsigned char oldctx;
212 unsigned long i;
213
214 if(context) {
215 if(!ctx_alloc[context])
216 panic("clear_context: context not allocated\n");
217
218 ctx_alloc[context]->context = SUN3_INVALID_CONTEXT;
219 ctx_alloc[context] = (struct mm_struct *)0;
220 ctx_avail++;
221 }
222
223 oldctx = sun3_get_context();
224
225 sun3_put_context(context);
226
227 for(i = 0; i < SUN3_INVALID_PMEG; i++) {
228 if((pmeg_ctx[i] == context) && (pmeg_alloc[i] == 1)) {
229 sun3_put_segmap(pmeg_vaddr[i], SUN3_INVALID_PMEG);
230 pmeg_ctx[i] = 0;
231 pmeg_alloc[i] = 0;
232 pmeg_vaddr[i] = 0;
233 }
234 }
235
236 sun3_put_context(oldctx);
237}
238
239/* gets an empty context. if full, kills the next context listed to
240 die first */
241/* This context invalidation scheme is, well, totally arbitrary, I'm
242 sure it could be much more intellegent... but it gets the job done
243 for now without much overhead in making it's decision. */
244/* todo: come up with optimized scheme for flushing contexts */
245unsigned long get_free_context(struct mm_struct *mm)
246{
247 unsigned long new = 1;
248 static unsigned char next_to_die = 1;
249
250 if(!ctx_avail) {
251 /* kill someone to get our context */
252 new = next_to_die;
253 clear_context(new);
254 next_to_die = (next_to_die + 1) & 0x7;
255 if(!next_to_die)
256 next_to_die++;
257 } else {
258 while(new < CONTEXTS_NUM) {
259 if(ctx_alloc[new])
260 new++;
261 else
262 break;
263 }
264 // check to make sure one was really free...
265 if(new == CONTEXTS_NUM)
266 panic("get_free_context: failed to find free context");
267 }
268
269 ctx_alloc[new] = mm;
270 ctx_avail--;
271
272 return new;
273}
274
275/*
276 * Dynamically select a `spare' PMEG and use it to map virtual `vaddr' in
277 * `context'. Maintain internal PMEG management structures. This doesn't
278 * actually map the physical address, but does clear the old mappings.
279 */
280//todo: better allocation scheme? but is extra complexity worthwhile?
281//todo: only clear old entries if necessary? how to tell?
282
283inline void mmu_emu_map_pmeg (int context, int vaddr)
284{
285 static unsigned char curr_pmeg = 128;
286 int i;
287
288 /* Round address to PMEG boundary. */
289 vaddr &= ~SUN3_PMEG_MASK;
290
291 /* Find a spare one. */
292 while (pmeg_alloc[curr_pmeg] == 2)
293 ++curr_pmeg;
294
295
296#ifdef DEBUG_MMU_EMU
297printk("mmu_emu_map_pmeg: pmeg %x to context %d vaddr %x\n",
298 curr_pmeg, context, vaddr);
299#endif
300
301 /* Invalidate old mapping for the pmeg, if any */
302 if (pmeg_alloc[curr_pmeg] == 1) {
303 sun3_put_context(pmeg_ctx[curr_pmeg]);
304 sun3_put_segmap (pmeg_vaddr[curr_pmeg], SUN3_INVALID_PMEG);
305 sun3_put_context(context);
306 }
307
308 /* Update PMEG management structures. */
309 // don't take pmeg's away from the kernel...
310 if(vaddr >= PAGE_OFFSET) {
311 /* map kernel pmegs into all contexts */
312 unsigned char i;
313
314 for(i = 0; i < CONTEXTS_NUM; i++) {
315 sun3_put_context(i);
316 sun3_put_segmap (vaddr, curr_pmeg);
317 }
318 sun3_put_context(context);
319 pmeg_alloc[curr_pmeg] = 2;
320 pmeg_ctx[curr_pmeg] = 0;
321
322 }
323 else {
324 pmeg_alloc[curr_pmeg] = 1;
325 pmeg_ctx[curr_pmeg] = context;
326 sun3_put_segmap (vaddr, curr_pmeg);
327
328 }
329 pmeg_vaddr[curr_pmeg] = vaddr;
330
331 /* Set hardware mapping and clear the old PTE entries. */
332 for (i=0; i<SUN3_PMEG_SIZE; i+=SUN3_PTE_SIZE)
333 sun3_put_pte (vaddr + i, SUN3_PAGE_SYSTEM);
334
335 /* Consider a different one next time. */
336 ++curr_pmeg;
337}
338
339/*
340 * Handle a pagefault at virtual address `vaddr'; check if there should be a
341 * page there (specifically, whether the software pagetables indicate that
342 * there is). This is necessary due to the limited size of the second-level
343 * Sun3 hardware pagetables (256 groups of 16 pages). If there should be a
344 * mapping present, we select a `spare' PMEG and use it to create a mapping.
345 * `read_flag' is nonzero for a read fault; zero for a write. Returns nonzero
346 * if we successfully handled the fault.
347 */
348//todo: should we bump minor pagefault counter? if so, here or in caller?
349//todo: possibly inline this into bus_error030 in <asm/buserror.h> ?
350
351// kernel_fault is set when a kernel page couldn't be demand mapped,
352// and forces another try using the kernel page table. basically a
353// hack so that vmalloc would work correctly.
354
355int mmu_emu_handle_fault (unsigned long vaddr, int read_flag, int kernel_fault)
356{
357 unsigned long segment, offset;
358 unsigned char context;
359 pte_t *pte;
360 pgd_t * crp;
361
362 if(current->mm == NULL) {
363 crp = swapper_pg_dir;
364 context = 0;
365 } else {
366 context = current->mm->context;
367 if(kernel_fault)
368 crp = swapper_pg_dir;
369 else
370 crp = current->mm->pgd;
371 }
372
373#ifdef DEBUG_MMU_EMU
374 printk ("mmu_emu_handle_fault: vaddr=%lx type=%s crp=%p\n",
375 vaddr, read_flag ? "read" : "write", crp);
376#endif
377
378 segment = (vaddr >> SUN3_PMEG_SIZE_BITS) & 0x7FF;
379 offset = (vaddr >> SUN3_PTE_SIZE_BITS) & 0xF;
380
381#ifdef DEBUG_MMU_EMU
382 printk ("mmu_emu_handle_fault: segment=%lx offset=%lx\n", segment, offset);
383#endif
384
385 pte = (pte_t *) pgd_val (*(crp + segment));
386
387//todo: next line should check for valid pmd properly.
388 if (!pte) {
389// printk ("mmu_emu_handle_fault: invalid pmd\n");
390 return 0;
391 }
392
393 pte = (pte_t *) __va ((unsigned long)(pte + offset));
394
395 /* Make sure this is a valid page */
396 if (!(pte_val (*pte) & SUN3_PAGE_VALID))
397 return 0;
398
399 /* Make sure there's a pmeg allocated for the page */
400 if (sun3_get_segmap (vaddr&~SUN3_PMEG_MASK) == SUN3_INVALID_PMEG)
401 mmu_emu_map_pmeg (context, vaddr);
402
403 /* Write the pte value to hardware MMU */
404 sun3_put_pte (vaddr&PAGE_MASK, pte_val (*pte));
405
406 /* Update software copy of the pte value */
407// I'm not sure this is necessary. If this is required, we ought to simply
408// copy this out when we reuse the PMEG or at some other convenient time.
409// Doing it here is fairly meaningless, anyway, as we only know about the
410// first access to a given page. --m
411 if (!read_flag) {
412 if (pte_val (*pte) & SUN3_PAGE_WRITEABLE)
413 pte_val (*pte) |= (SUN3_PAGE_ACCESSED
414 | SUN3_PAGE_MODIFIED);
415 else
416 return 0; /* Write-protect error. */
417 } else
418 pte_val (*pte) |= SUN3_PAGE_ACCESSED;
419
420#ifdef DEBUG_MMU_EMU
421 printk ("seg:%d crp:%p ->", get_fs().seg, crp);
422 print_pte_vaddr (vaddr);
423 printk ("\n");
424#endif
425
426 return 1;
427}
diff --git a/arch/m68k/sun3/prom/Makefile b/arch/m68k/sun3/prom/Makefile
new file mode 100644
index 000000000000..6e48ae2a7175
--- /dev/null
+++ b/arch/m68k/sun3/prom/Makefile
@@ -0,0 +1,7 @@
1# $Id: Makefile,v 1.5 1995/11/25 00:59:48 davem Exp $
2# Makefile for the Sun Boot PROM interface library under
3# Linux.
4#
5
6obj-y := init.o console.o printf.o misc.o
7#bootstr.o init.o misc.o segment.o console.o printf.o
diff --git a/arch/m68k/sun3/prom/console.c b/arch/m68k/sun3/prom/console.c
new file mode 100644
index 000000000000..52c1427863de
--- /dev/null
+++ b/arch/m68k/sun3/prom/console.c
@@ -0,0 +1,174 @@
1/* $Id: console.c,v 1.10 1996/12/18 06:46:54 tridge Exp $
2 * console.c: Routines that deal with sending and receiving IO
3 * to/from the current console device using the PROM.
4 *
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <asm/openprom.h>
12#include <asm/oplib.h>
13#include <asm/system.h>
14#include <linux/string.h>
15
16/* Non blocking get character from console input device, returns -1
17 * if no input was taken. This can be used for polling.
18 */
19int
20prom_nbgetchar(void)
21{
22 int i = -1;
23 unsigned long flags;
24
25 local_irq_save(flags);
26 i = (*(romvec->pv_nbgetchar))();
27 local_irq_restore(flags);
28 return i; /* Ugh, we could spin forever on unsupported proms ;( */
29}
30
31/* Non blocking put character to console device, returns -1 if
32 * unsuccessful.
33 */
34int
35prom_nbputchar(char c)
36{
37 unsigned long flags;
38 int i = -1;
39
40 local_irq_save(flags);
41 i = (*(romvec->pv_nbputchar))(c);
42 local_irq_restore(flags);
43 return i; /* Ugh, we could spin forever on unsupported proms ;( */
44}
45
46/* Blocking version of get character routine above. */
47char
48prom_getchar(void)
49{
50 int character;
51 while((character = prom_nbgetchar()) == -1) ;
52 return (char) character;
53}
54
55/* Blocking version of put character routine above. */
56void
57prom_putchar(char c)
58{
59 while(prom_nbputchar(c) == -1) ;
60 return;
61}
62
63/* Query for input device type */
64#if 0
65enum prom_input_device
66prom_query_input_device()
67{
68 unsigned long flags;
69 int st_p;
70 char propb[64];
71 char *p;
72
73 switch(prom_vers) {
74 case PROM_V0:
75 case PROM_V2:
76 default:
77 switch(*romvec->pv_stdin) {
78 case PROMDEV_KBD: return PROMDEV_IKBD;
79 case PROMDEV_TTYA: return PROMDEV_ITTYA;
80 case PROMDEV_TTYB: return PROMDEV_ITTYB;
81 default:
82 return PROMDEV_I_UNK;
83 };
84 case PROM_V3:
85 case PROM_P1275:
86 local_irq_save(flags);
87 st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
88 __asm__ __volatile__("ld [%0], %%g6\n\t" : :
89 "r" (&current_set[smp_processor_id()]) :
90 "memory");
91 local_irq_restore(flags);
92 if(prom_node_has_property(st_p, "keyboard"))
93 return PROMDEV_IKBD;
94 prom_getproperty(st_p, "device_type", propb, sizeof(propb));
95 if(strncmp(propb, "serial", sizeof("serial")))
96 return PROMDEV_I_UNK;
97 prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
98 p = propb;
99 while(*p) p++; p -= 2;
100 if(p[0] == ':') {
101 if(p[1] == 'a')
102 return PROMDEV_ITTYA;
103 else if(p[1] == 'b')
104 return PROMDEV_ITTYB;
105 }
106 return PROMDEV_I_UNK;
107 case PROM_AP1000:
108 return PROMDEV_I_UNK;
109 };
110}
111#endif
112
113/* Query for output device type */
114
115#if 0
116enum prom_output_device
117prom_query_output_device()
118{
119 unsigned long flags;
120 int st_p;
121 char propb[64];
122 char *p;
123 int propl;
124
125 switch(prom_vers) {
126 case PROM_V0:
127 switch(*romvec->pv_stdin) {
128 case PROMDEV_SCREEN: return PROMDEV_OSCREEN;
129 case PROMDEV_TTYA: return PROMDEV_OTTYA;
130 case PROMDEV_TTYB: return PROMDEV_OTTYB;
131 };
132 break;
133 case PROM_V2:
134 case PROM_V3:
135 case PROM_P1275:
136 local_irq_save(flags);
137 st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
138 __asm__ __volatile__("ld [%0], %%g6\n\t" : :
139 "r" (&current_set[smp_processor_id()]) :
140 "memory");
141 local_irq_restore(flags);
142 propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
143 if (propl >= 0 && propl == sizeof("display") &&
144 strncmp("display", propb, sizeof("display")) == 0)
145 {
146 return PROMDEV_OSCREEN;
147 }
148 if(prom_vers == PROM_V3) {
149 if(strncmp("serial", propb, sizeof("serial")))
150 return PROMDEV_O_UNK;
151 prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb));
152 p = propb;
153 while(*p) p++; p -= 2;
154 if(p[0]==':') {
155 if(p[1] == 'a')
156 return PROMDEV_OTTYA;
157 else if(p[1] == 'b')
158 return PROMDEV_OTTYB;
159 }
160 return PROMDEV_O_UNK;
161 } else {
162 /* This works on SS-2 (an early OpenFirmware) still. */
163 switch(*romvec->pv_stdin) {
164 case PROMDEV_TTYA: return PROMDEV_OTTYA;
165 case PROMDEV_TTYB: return PROMDEV_OTTYB;
166 };
167 }
168 break;
169 case PROM_AP1000:
170 return PROMDEV_I_UNK;
171 };
172 return PROMDEV_O_UNK;
173}
174#endif
diff --git a/arch/m68k/sun3/prom/init.c b/arch/m68k/sun3/prom/init.c
new file mode 100644
index 000000000000..2e6ae56aec12
--- /dev/null
+++ b/arch/m68k/sun3/prom/init.c
@@ -0,0 +1,89 @@
1/* $Id: init.c,v 1.9 1996/12/18 06:46:55 tridge Exp $
2 * init.c: Initialize internal variables used by the PROM
3 * library functions.
4 *
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#include <linux/config.h>
9#include <linux/kernel.h>
10#include <linux/init.h>
11
12#include <asm/openprom.h>
13#include <asm/oplib.h>
14
15struct linux_romvec *romvec;
16enum prom_major_version prom_vers;
17unsigned int prom_rev, prom_prev;
18
19/* The root node of the prom device tree. */
20int prom_root_node;
21
22/* Pointer to the device tree operations structure. */
23struct linux_nodeops *prom_nodeops;
24
25/* You must call prom_init() before you attempt to use any of the
26 * routines in the prom library. It returns 0 on success, 1 on
27 * failure. It gets passed the pointer to the PROM vector.
28 */
29
30extern void prom_meminit(void);
31extern void prom_ranges_init(void);
32
33void __init prom_init(struct linux_romvec *rp)
34{
35#ifdef CONFIG_AP1000
36 extern struct linux_romvec *ap_prom_init(void);
37 rp = ap_prom_init();
38#endif
39
40 romvec = rp;
41#ifndef CONFIG_SUN3
42 switch(romvec->pv_romvers) {
43 case 0:
44 prom_vers = PROM_V0;
45 break;
46 case 2:
47 prom_vers = PROM_V2;
48 break;
49 case 3:
50 prom_vers = PROM_V3;
51 break;
52 case 4:
53 prom_vers = PROM_P1275;
54 prom_printf("PROMLIB: Sun IEEE Prom not supported yet\n");
55 prom_halt();
56 break;
57 case 42: /* why not :-) */
58 prom_vers = PROM_AP1000;
59 break;
60
61 default:
62 prom_printf("PROMLIB: Bad PROM version %d\n",
63 romvec->pv_romvers);
64 prom_halt();
65 break;
66 };
67
68 prom_rev = romvec->pv_plugin_revision;
69 prom_prev = romvec->pv_printrev;
70 prom_nodeops = romvec->pv_nodeops;
71
72 prom_root_node = prom_getsibling(0);
73 if((prom_root_node == 0) || (prom_root_node == -1))
74 prom_halt();
75
76 if((((unsigned long) prom_nodeops) == 0) ||
77 (((unsigned long) prom_nodeops) == -1))
78 prom_halt();
79
80 prom_meminit();
81
82 prom_ranges_init();
83#endif
84// printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n",
85// romvec->pv_romvers, prom_rev);
86
87 /* Initialization successful. */
88 return;
89}
diff --git a/arch/m68k/sun3/prom/misc.c b/arch/m68k/sun3/prom/misc.c
new file mode 100644
index 000000000000..b88716f2c68c
--- /dev/null
+++ b/arch/m68k/sun3/prom/misc.c
@@ -0,0 +1,94 @@
1/* $Id: misc.c,v 1.15 1997/05/14 20:45:00 davem Exp $
2 * misc.c: Miscellaneous prom functions that don't belong
3 * anywhere else.
4 *
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <asm/sun3-head.h>
12#include <asm/idprom.h>
13#include <asm/openprom.h>
14#include <asm/oplib.h>
15#include <asm/movs.h>
16
17/* Reset and reboot the machine with the command 'bcommand'. */
18void
19prom_reboot(char *bcommand)
20{
21 unsigned long flags;
22 local_irq_save(flags);
23 (*(romvec->pv_reboot))(bcommand);
24 local_irq_restore(flags);
25}
26
27/* Drop into the prom, with the chance to continue with the 'go'
28 * prom command.
29 */
30void
31prom_cmdline(void)
32{
33}
34
35/* Drop into the prom, but completely terminate the program.
36 * No chance of continuing.
37 */
38void
39prom_halt(void)
40{
41 unsigned long flags;
42again:
43 local_irq_save(flags);
44 (*(romvec->pv_halt))();
45 local_irq_restore(flags);
46 goto again; /* PROM is out to get me -DaveM */
47}
48
49typedef void (*sfunc_t)(void);
50
51/* Get the idprom and stuff it into buffer 'idbuf'. Returns the
52 * format type. 'num_bytes' is the number of bytes that your idbuf
53 * has space for. Returns 0xff on error.
54 */
55unsigned char
56prom_get_idprom(char *idbuf, int num_bytes)
57{
58 int i, oldsfc;
59 GET_SFC(oldsfc);
60 SET_SFC(FC_CONTROL);
61 for(i=0;i<num_bytes; i++)
62 {
63 /* There is a problem with the GET_CONTROL_BYTE
64 macro; defining the extra variable
65 gets around it.
66 */
67 int c;
68 GET_CONTROL_BYTE(SUN3_IDPROM_BASE + i, c);
69 idbuf[i] = c;
70 }
71 SET_SFC(oldsfc);
72 return idbuf[0];
73}
74
75/* Get the major prom version number. */
76int
77prom_version(void)
78{
79 return romvec->pv_romvers;
80}
81
82/* Get the prom plugin-revision. */
83int
84prom_getrev(void)
85{
86 return prom_rev;
87}
88
89/* Get the prom firmware print revision. */
90int
91prom_getprev(void)
92{
93 return prom_prev;
94}
diff --git a/arch/m68k/sun3/prom/printf.c b/arch/m68k/sun3/prom/printf.c
new file mode 100644
index 000000000000..e6ee1006344e
--- /dev/null
+++ b/arch/m68k/sun3/prom/printf.c
@@ -0,0 +1,61 @@
1/* $Id: printf.c,v 1.5 1996/04/04 16:31:07 tridge Exp $
2 * printf.c: Internal prom library printf facility.
3 *
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 */
6
7/* This routine is internal to the prom library, no one else should know
8 * about or use it! It's simple and smelly anyway....
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13
14#include <asm/openprom.h>
15#include <asm/oplib.h>
16
17#ifdef CONFIG_KGDB
18extern int kgdb_initialized;
19#endif
20
21static char ppbuf[1024];
22
23void
24prom_printf(char *fmt, ...)
25{
26 va_list args;
27 char ch, *bptr;
28 int i;
29
30 va_start(args, fmt);
31
32#ifdef CONFIG_KGDB
33 ppbuf[0] = 'O';
34 i = vsprintf(ppbuf + 1, fmt, args) + 1;
35#else
36 i = vsprintf(ppbuf, fmt, args);
37#endif
38
39 bptr = ppbuf;
40
41#ifdef CONFIG_AP1000
42 ap_write(1,bptr,strlen(bptr));
43#else
44
45#ifdef CONFIG_KGDB
46 if (kgdb_initialized) {
47 printk("kgdb_initialized = %d\n", kgdb_initialized);
48 putpacket(bptr, 1);
49 } else
50#else
51 while((ch = *(bptr++)) != 0) {
52 if(ch == '\n')
53 prom_putchar('\r');
54
55 prom_putchar(ch);
56 }
57#endif
58#endif
59 va_end(args);
60 return;
61}
diff --git a/arch/m68k/sun3/sbus.c b/arch/m68k/sun3/sbus.c
new file mode 100644
index 000000000000..babdbfa3cda7
--- /dev/null
+++ b/arch/m68k/sun3/sbus.c
@@ -0,0 +1,27 @@
1/*
2 * SBus helper functions
3 *
4 * Sun3 don't have a sbus, but many of the used devices are also
5 * used on Sparc machines with sbus. To avoid having a lot of
6 * duplicate code, we provide necessary glue stuff to make using
7 * of the sbus driver code possible.
8 *
9 * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
10 */
11
12#include <linux/types.h>
13#include <linux/compiler.h>
14#include <linux/init.h>
15
16int __init sbus_init(void)
17{
18 return 0;
19}
20
21void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
22 u32 bus_type, int rdonly)
23{
24 return (void *)address;
25}
26
27subsys_initcall(sbus_init);
diff --git a/arch/m68k/sun3/sun3_ksyms.c b/arch/m68k/sun3/sun3_ksyms.c
new file mode 100644
index 000000000000..43e5a9af8abd
--- /dev/null
+++ b/arch/m68k/sun3/sun3_ksyms.c
@@ -0,0 +1,13 @@
1#include <linux/module.h>
2#include <linux/types.h>
3#include <asm/dvma.h>
4#include <asm/idprom.h>
5
6/*
7 * Add things here when you find the need for it.
8 */
9EXPORT_SYMBOL(dvma_map_align);
10EXPORT_SYMBOL(dvma_unmap);
11EXPORT_SYMBOL(dvma_malloc_align);
12EXPORT_SYMBOL(dvma_free);
13EXPORT_SYMBOL(idprom);
diff --git a/arch/m68k/sun3/sun3dvma.c b/arch/m68k/sun3/sun3dvma.c
new file mode 100644
index 000000000000..f04a1d25f1a2
--- /dev/null
+++ b/arch/m68k/sun3/sun3dvma.c
@@ -0,0 +1,379 @@
1/*
2 * linux/arch/m68k/mm/sun3dvma.c
3 *
4 * Copyright (C) 2000 Sam Creasey
5 *
6 * Contains common routines for sun3/sun3x DVMA management.
7 */
8
9#include <linux/config.h>
10#include <linux/kernel.h>
11#include <linux/mm.h>
12#include <linux/list.h>
13
14#include <asm/page.h>
15#include <asm/pgtable.h>
16#include <asm/dvma.h>
17
18#undef DVMA_DEBUG
19
20#ifdef CONFIG_SUN3X
21extern void dvma_unmap_iommu(unsigned long baddr, int len);
22#else
23static inline void dvma_unmap_iommu(unsigned long a, int b)
24{
25}
26#endif
27
28#ifdef CONFIG_SUN3
29extern void sun3_dvma_init(void);
30#endif
31
32unsigned long iommu_use[IOMMU_TOTAL_ENTRIES];
33
34#define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT)
35
36#define dvma_entry_use(baddr) (iommu_use[dvma_index(baddr)])
37
38struct hole {
39 unsigned long start;
40 unsigned long end;
41 unsigned long size;
42 struct list_head list;
43};
44
45static struct list_head hole_list;
46static struct list_head hole_cache;
47static struct hole initholes[64];
48
49#ifdef DVMA_DEBUG
50
51static unsigned long dvma_allocs;
52static unsigned long dvma_frees;
53static unsigned long long dvma_alloc_bytes;
54static unsigned long long dvma_free_bytes;
55
56static void print_use(void)
57{
58
59 int i;
60 int j = 0;
61
62 printk("dvma entry usage:\n");
63
64 for(i = 0; i < IOMMU_TOTAL_ENTRIES; i++) {
65 if(!iommu_use[i])
66 continue;
67
68 j++;
69
70 printk("dvma entry: %08lx len %08lx\n",
71 ( i << DVMA_PAGE_SHIFT) + DVMA_START,
72 iommu_use[i]);
73 }
74
75 printk("%d entries in use total\n", j);
76
77 printk("allocation/free calls: %lu/%lu\n", dvma_allocs, dvma_frees);
78 printk("allocation/free bytes: %Lx/%Lx\n", dvma_alloc_bytes,
79 dvma_free_bytes);
80}
81
82static void print_holes(struct list_head *holes)
83{
84
85 struct list_head *cur;
86 struct hole *hole;
87
88 printk("listing dvma holes\n");
89 list_for_each(cur, holes) {
90 hole = list_entry(cur, struct hole, list);
91
92 if((hole->start == 0) && (hole->end == 0) && (hole->size == 0))
93 continue;
94
95 printk("hole: start %08lx end %08lx size %08lx\n", hole->start, hole->end, hole->size);
96 }
97
98 printk("end of hole listing...\n");
99
100}
101#endif /* DVMA_DEBUG */
102
103static inline int refill(void)
104{
105
106 struct hole *hole;
107 struct hole *prev = NULL;
108 struct list_head *cur;
109 int ret = 0;
110
111 list_for_each(cur, &hole_list) {
112 hole = list_entry(cur, struct hole, list);
113
114 if(!prev) {
115 prev = hole;
116 continue;
117 }
118
119 if(hole->end == prev->start) {
120 hole->size += prev->size;
121 hole->end = prev->end;
122 list_del(&(prev->list));
123 list_add(&(prev->list), &hole_cache);
124 ret++;
125 }
126
127 }
128
129 return ret;
130}
131
132static inline struct hole *rmcache(void)
133{
134 struct hole *ret;
135
136 if(list_empty(&hole_cache)) {
137 if(!refill()) {
138 printk("out of dvma hole cache!\n");
139 BUG();
140 }
141 }
142
143 ret = list_entry(hole_cache.next, struct hole, list);
144 list_del(&(ret->list));
145
146 return ret;
147
148}
149
150static inline unsigned long get_baddr(int len, unsigned long align)
151{
152
153 struct list_head *cur;
154 struct hole *hole;
155
156 if(list_empty(&hole_list)) {
157#ifdef DVMA_DEBUG
158 printk("out of dvma holes! (printing hole cache)\n");
159 print_holes(&hole_cache);
160 print_use();
161#endif
162 BUG();
163 }
164
165 list_for_each(cur, &hole_list) {
166 unsigned long newlen;
167
168 hole = list_entry(cur, struct hole, list);
169
170 if(align > DVMA_PAGE_SIZE)
171 newlen = len + ((hole->end - len) & (align-1));
172 else
173 newlen = len;
174
175 if(hole->size > newlen) {
176 hole->end -= newlen;
177 hole->size -= newlen;
178 dvma_entry_use(hole->end) = newlen;
179#ifdef DVMA_DEBUG
180 dvma_allocs++;
181 dvma_alloc_bytes += newlen;
182#endif
183 return hole->end;
184 } else if(hole->size == newlen) {
185 list_del(&(hole->list));
186 list_add(&(hole->list), &hole_cache);
187 dvma_entry_use(hole->start) = newlen;
188#ifdef DVMA_DEBUG
189 dvma_allocs++;
190 dvma_alloc_bytes += newlen;
191#endif
192 return hole->start;
193 }
194
195 }
196
197 printk("unable to find dvma hole!\n");
198 BUG();
199 return 0;
200}
201
202static inline int free_baddr(unsigned long baddr)
203{
204
205 unsigned long len;
206 struct hole *hole;
207 struct list_head *cur;
208 unsigned long orig_baddr;
209
210 orig_baddr = baddr;
211 len = dvma_entry_use(baddr);
212 dvma_entry_use(baddr) = 0;
213 baddr &= DVMA_PAGE_MASK;
214 dvma_unmap_iommu(baddr, len);
215
216#ifdef DVMA_DEBUG
217 dvma_frees++;
218 dvma_free_bytes += len;
219#endif
220
221 list_for_each(cur, &hole_list) {
222 hole = list_entry(cur, struct hole, list);
223
224 if(hole->end == baddr) {
225 hole->end += len;
226 hole->size += len;
227 return 0;
228 } else if(hole->start == (baddr + len)) {
229 hole->start = baddr;
230 hole->size += len;
231 return 0;
232 }
233
234 }
235
236 hole = rmcache();
237
238 hole->start = baddr;
239 hole->end = baddr + len;
240 hole->size = len;
241
242// list_add_tail(&(hole->list), cur);
243 list_add(&(hole->list), cur);
244
245 return 0;
246
247}
248
249void dvma_init(void)
250{
251
252 struct hole *hole;
253 int i;
254
255 INIT_LIST_HEAD(&hole_list);
256 INIT_LIST_HEAD(&hole_cache);
257
258 /* prepare the hole cache */
259 for(i = 0; i < 64; i++)
260 list_add(&(initholes[i].list), &hole_cache);
261
262 hole = rmcache();
263 hole->start = DVMA_START;
264 hole->end = DVMA_END;
265 hole->size = DVMA_SIZE;
266
267 list_add(&(hole->list), &hole_list);
268
269 memset(iommu_use, 0, sizeof(iommu_use));
270
271 dvma_unmap_iommu(DVMA_START, DVMA_SIZE);
272
273#ifdef CONFIG_SUN3
274 sun3_dvma_init();
275#endif
276
277}
278
279inline unsigned long dvma_map_align(unsigned long kaddr, int len, int align)
280{
281
282 unsigned long baddr;
283 unsigned long off;
284
285 if(!len)
286 len = 0x800;
287
288 if(!kaddr || !len) {
289// printk("error: kaddr %lx len %x\n", kaddr, len);
290// *(int *)4 = 0;
291 return 0;
292 }
293
294#ifdef DEBUG
295 printk("dvma_map request %08lx bytes from %08lx\n",
296 len, kaddr);
297#endif
298 off = kaddr & ~DVMA_PAGE_MASK;
299 kaddr &= PAGE_MASK;
300 len += off;
301 len = ((len + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK);
302
303 if(align == 0)
304 align = DVMA_PAGE_SIZE;
305 else
306 align = ((align + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK);
307
308 baddr = get_baddr(len, align);
309// printk("using baddr %lx\n", baddr);
310
311 if(!dvma_map_iommu(kaddr, baddr, len))
312 return (baddr + off);
313
314 printk("dvma_map failed kaddr %lx baddr %lx len %x\n", kaddr, baddr, len);
315 BUG();
316 return 0;
317}
318
319void dvma_unmap(void *baddr)
320{
321 unsigned long addr;
322
323 addr = (unsigned long)baddr;
324 /* check if this is a vme mapping */
325 if(!(addr & 0x00f00000))
326 addr |= 0xf00000;
327
328 free_baddr(addr);
329
330 return;
331
332}
333
334
335void *dvma_malloc_align(unsigned long len, unsigned long align)
336{
337 unsigned long kaddr;
338 unsigned long baddr;
339 unsigned long vaddr;
340
341 if(!len)
342 return NULL;
343
344#ifdef DEBUG
345 printk("dvma_malloc request %lx bytes\n", len);
346#endif
347 len = ((len + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK);
348
349 if((kaddr = __get_free_pages(GFP_ATOMIC, get_order(len))) == 0)
350 return NULL;
351
352 if((baddr = (unsigned long)dvma_map_align(kaddr, len, align)) == 0) {
353 free_pages(kaddr, get_order(len));
354 return NULL;
355 }
356
357 vaddr = dvma_btov(baddr);
358
359 if(dvma_map_cpu(kaddr, vaddr, len) < 0) {
360 dvma_unmap((void *)baddr);
361 free_pages(kaddr, get_order(len));
362 return NULL;
363 }
364
365#ifdef DEBUG
366 printk("mapped %08lx bytes %08lx kern -> %08lx bus\n",
367 len, kaddr, baddr);
368#endif
369
370 return (void *)vaddr;
371
372}
373
374void dvma_free(void *vaddr)
375{
376
377 return;
378
379}
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
new file mode 100644
index 000000000000..e62a033cd493
--- /dev/null
+++ b/arch/m68k/sun3/sun3ints.c
@@ -0,0 +1,265 @@
1 /*
2 * linux/arch/m68k/sun3/sun3ints.c -- Sun-3(x) Linux interrupt handling code
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive
6 * for more details.
7 */
8
9#include <linux/config.h>
10#include <linux/types.h>
11#include <linux/kernel.h>
12#include <linux/sched.h>
13#include <linux/kernel_stat.h>
14#include <linux/interrupt.h>
15#include <asm/segment.h>
16#include <asm/intersil.h>
17#include <asm/oplib.h>
18#include <asm/sun3ints.h>
19#include <linux/seq_file.h>
20
21extern void sun3_leds (unsigned char);
22static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp);
23
24void sun3_disable_interrupts(void)
25{
26 sun3_disable_irq(0);
27}
28
29void sun3_enable_interrupts(void)
30{
31 sun3_enable_irq(0);
32}
33
34int led_pattern[8] = {
35 ~(0x80), ~(0x01),
36 ~(0x40), ~(0x02),
37 ~(0x20), ~(0x04),
38 ~(0x10), ~(0x08)
39};
40
41volatile unsigned char* sun3_intreg;
42
43void sun3_insert_irq(irq_node_t **list, irq_node_t *node)
44{
45}
46
47void sun3_delete_irq(irq_node_t **list, void *dev_id)
48{
49}
50
51void sun3_enable_irq(unsigned int irq)
52{
53 *sun3_intreg |= (1<<irq);
54}
55
56void sun3_disable_irq(unsigned int irq)
57{
58 *sun3_intreg &= ~(1<<irq);
59}
60
61inline void sun3_do_irq(int irq, struct pt_regs *fp)
62{
63 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
64 *sun3_intreg &= ~(1<<irq);
65 *sun3_intreg |= (1<<irq);
66}
67
68static irqreturn_t sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
69{
70 sun3_do_irq(irq,fp);
71 if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 2000))
72 sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%16000)
73 /2000]);
74 return IRQ_HANDLED;
75}
76
77static irqreturn_t sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
78{
79 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
80#ifdef CONFIG_SUN3
81 intersil_clear();
82#endif
83 *sun3_intreg &= ~(1<<irq);
84 *sun3_intreg |= (1<<irq);
85#ifdef CONFIG_SUN3
86 intersil_clear();
87#endif
88 do_timer(fp);
89#ifndef CONFIG_SMP
90 update_process_times(user_mode(fp));
91#endif
92 if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 20))
93 sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%160)
94 /20]);
95 return IRQ_HANDLED;
96}
97
98/* handle requested ints, excepting 5 and 7, which always do the same
99 thing */
100irqreturn_t (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
101 [0] = sun3_inthandle,
102 [1] = sun3_inthandle,
103 [2] = sun3_inthandle,
104 [3] = sun3_inthandle,
105 [4] = sun3_inthandle,
106 [5] = sun3_int5,
107 [6] = sun3_inthandle,
108 [7] = sun3_int7
109};
110
111static const char *dev_names[SYS_IRQS] = {
112 [5] = "timer",
113 [7] = "int7 handler"
114};
115static void *dev_ids[SYS_IRQS];
116static irqreturn_t (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
117 [5] = sun3_int5,
118 [7] = sun3_int7
119};
120static irqreturn_t (*sun3_vechandler[SUN3_INT_VECS])(int, void *, struct pt_regs *);
121static void *vec_ids[SUN3_INT_VECS];
122static const char *vec_names[SUN3_INT_VECS];
123static int vec_ints[SUN3_INT_VECS];
124
125
126int show_sun3_interrupts(struct seq_file *p, void *v)
127{
128 int i;
129
130 for(i = 0; i < (SUN3_INT_VECS-1); i++) {
131 if(sun3_vechandler[i] != NULL) {
132 seq_printf(p, "vec %3d: %10u %s\n", i+64,
133 vec_ints[i],
134 (vec_names[i]) ? vec_names[i] :
135 "sun3_vechandler");
136 }
137 }
138
139 return 0;
140}
141
142static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
143{
144 if(sun3_inthandler[irq] == NULL)
145 panic ("bad interrupt %d received (id %p)\n",irq, dev_id);
146
147 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
148 *sun3_intreg &= ~(1<<irq);
149
150 sun3_inthandler[irq](irq, dev_ids[irq], fp);
151 return IRQ_HANDLED;
152}
153
154static irqreturn_t sun3_vec255(int irq, void *dev_id, struct pt_regs *fp)
155{
156// intersil_clear();
157 return IRQ_HANDLED;
158}
159
160void sun3_init_IRQ(void)
161{
162 int i;
163
164 *sun3_intreg = 1;
165
166 for(i = 0; i < SYS_IRQS; i++)
167 {
168 if(dev_names[i])
169 cpu_request_irq(i, sun3_default_handler[i], 0,
170 dev_names[i], NULL);
171 }
172
173 for(i = 0; i < 192; i++)
174 sun3_vechandler[i] = NULL;
175
176 sun3_vechandler[191] = sun3_vec255;
177}
178
179int sun3_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
180 unsigned long flags, const char *devname, void *dev_id)
181{
182
183 if(irq < SYS_IRQS) {
184 if(sun3_inthandler[irq] != NULL) {
185 printk("sun3_request_irq: request for irq %d -- already taken!\n", irq);
186 return 1;
187 }
188
189 sun3_inthandler[irq] = handler;
190 dev_ids[irq] = dev_id;
191 dev_names[irq] = devname;
192
193 /* setting devname would be nice */
194 cpu_request_irq(irq, sun3_default_handler[irq], 0, devname,
195 NULL);
196
197 return 0;
198 } else {
199 if((irq >= 64) && (irq <= 255)) {
200 int vec;
201
202 vec = irq - 64;
203 if(sun3_vechandler[vec] != NULL) {
204 printk("sun3_request_irq: request for vec %d -- already taken!\n", irq);
205 return 1;
206 }
207
208 sun3_vechandler[vec] = handler;
209 vec_ids[vec] = dev_id;
210 vec_names[vec] = devname;
211 vec_ints[vec] = 0;
212
213 return 0;
214 }
215 }
216
217 printk("sun3_request_irq: invalid irq %d\n", irq);
218 return 1;
219
220}
221
222void sun3_free_irq(unsigned int irq, void *dev_id)
223{
224
225 if(irq < SYS_IRQS) {
226 if(sun3_inthandler[irq] == NULL)
227 panic("sun3_free_int: attempt to free unused irq %d\n", irq);
228 if(dev_ids[irq] != dev_id)
229 panic("sun3_free_int: incorrect dev_id for irq %d\n", irq);
230
231 sun3_inthandler[irq] = NULL;
232 return;
233 } else if((irq >= 64) && (irq <= 255)) {
234 int vec;
235
236 vec = irq - 64;
237 if(sun3_vechandler[vec] == NULL)
238 panic("sun3_free_int: attempt to free unused vector %d\n", irq);
239 if(vec_ids[irq] != dev_id)
240 panic("sun3_free_int: incorrect dev_id for vec %d\n", irq);
241
242 sun3_vechandler[vec] = NULL;
243 return;
244 } else {
245 panic("sun3_free_irq: invalid irq %d\n", irq);
246 }
247}
248
249irqreturn_t sun3_process_int(int irq, struct pt_regs *regs)
250{
251
252 if((irq >= 64) && (irq <= 255)) {
253 int vec;
254
255 vec = irq - 64;
256 if(sun3_vechandler[vec] == NULL)
257 panic ("bad interrupt vector %d received\n",irq);
258
259 vec_ints[vec]++;
260 return sun3_vechandler[vec](irq, vec_ids[vec], regs);
261 } else {
262 panic("sun3_process_int: unable to handle interrupt vector %d\n",
263 irq);
264 }
265}
diff --git a/arch/m68k/sun3x/Makefile b/arch/m68k/sun3x/Makefile
new file mode 100644
index 000000000000..be5776d9a01e
--- /dev/null
+++ b/arch/m68k/sun3x/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/sun3x source directory
3#
4
5obj-y := config.o time.o dvma.o prom.o
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
new file mode 100644
index 000000000000..0ef547f5494d
--- /dev/null
+++ b/arch/m68k/sun3x/config.c
@@ -0,0 +1,99 @@
1/*
2 * Setup kernel for a Sun3x machine
3 *
4 * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
5 *
6 * based on code from Oliver Jowett <oliver@jowett.manawatu.gen.nz>
7 */
8
9#include <linux/config.h>
10#include <linux/types.h>
11#include <linux/mm.h>
12#include <linux/console.h>
13#include <linux/init.h>
14
15#include <asm/system.h>
16#include <asm/machdep.h>
17#include <asm/irq.h>
18#include <asm/sun3xprom.h>
19#include <asm/sun3ints.h>
20#include <asm/setup.h>
21#include <asm/oplib.h>
22
23#include "time.h"
24
25volatile char *clock_va;
26extern volatile unsigned char *sun3_intreg;
27
28extern void sun3_get_model(char *model);
29
30void sun3_leds(unsigned int i)
31{
32
33}
34
35static int sun3x_get_hardware_list(char *buffer)
36{
37
38 int len = 0;
39
40 len += sprintf(buffer + len, "PROM Revision:\t%s\n",
41 romvec->pv_monid);
42
43 return len;
44
45}
46
47/*
48 * Setup the sun3x configuration info
49 */
50void __init config_sun3x(void)
51{
52
53 sun3x_prom_init();
54
55 mach_get_irq_list = show_sun3_interrupts;
56 mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
57
58 mach_default_handler = &sun3_default_handler;
59 mach_sched_init = sun3x_sched_init;
60 mach_init_IRQ = sun3_init_IRQ;
61 enable_irq = sun3_enable_irq;
62 disable_irq = sun3_disable_irq;
63 mach_request_irq = sun3_request_irq;
64 mach_free_irq = sun3_free_irq;
65 mach_process_int = sun3_process_int;
66
67 mach_gettimeoffset = sun3x_gettimeoffset;
68 mach_reset = sun3x_reboot;
69
70 mach_hwclk = sun3x_hwclk;
71 mach_get_model = sun3_get_model;
72 mach_get_hardware_list = sun3x_get_hardware_list;
73
74#ifdef CONFIG_DUMMY_CONSOLE
75 conswitchp = &dummy_con;
76#endif
77
78 sun3_intreg = (unsigned char *)SUN3X_INTREG;
79
80 /* only the serial console is known to work anyway... */
81#if 0
82 switch (*(unsigned char *)SUN3X_EEPROM_CONS) {
83 case 0x10:
84 serial_console = 1;
85 conswitchp = NULL;
86 break;
87 case 0x11:
88 serial_console = 2;
89 conswitchp = NULL;
90 break;
91 default:
92 serial_console = 0;
93 conswitchp = &dummy_con;
94 break;
95 }
96#endif
97
98}
99
diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c
new file mode 100644
index 000000000000..32e55adfeb8e
--- /dev/null
+++ b/arch/m68k/sun3x/dvma.c
@@ -0,0 +1,208 @@
1/*
2 * Virtual DMA allocation
3 *
4 * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
5 *
6 * 11/26/2000 -- disabled the existing code because it didn't work for
7 * me in 2.4. Replaced with a significantly more primitive version
8 * similar to the sun3 code. the old functionality was probably more
9 * desirable, but.... -- Sam Creasey (sammy@oh.verio.com)
10 *
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/bitops.h>
16#include <linux/mm.h>
17#include <linux/bootmem.h>
18#include <linux/slab.h>
19#include <linux/vmalloc.h>
20
21#include <asm/sun3x.h>
22#include <asm/dvma.h>
23#include <asm/io.h>
24#include <asm/page.h>
25#include <asm/pgtable.h>
26#include <asm/pgalloc.h>
27
28/* IOMMU support */
29
30#define IOMMU_ADDR_MASK 0x03ffe000
31#define IOMMU_CACHE_INHIBIT 0x00000040
32#define IOMMU_FULL_BLOCK 0x00000020
33#define IOMMU_MODIFIED 0x00000010
34#define IOMMU_USED 0x00000008
35#define IOMMU_WRITE_PROTECT 0x00000004
36#define IOMMU_DT_MASK 0x00000003
37#define IOMMU_DT_INVALID 0x00000000
38#define IOMMU_DT_VALID 0x00000001
39#define IOMMU_DT_BAD 0x00000002
40
41
42static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;
43
44
45#define dvma_entry_paddr(index) (iommu_pte[index] & IOMMU_ADDR_MASK)
46#define dvma_entry_vaddr(index,paddr) ((index << DVMA_PAGE_SHIFT) | \
47 (paddr & (DVMA_PAGE_SIZE-1)))
48#if 0
49#define dvma_entry_set(index,addr) (iommu_pte[index] = \
50 (addr & IOMMU_ADDR_MASK) | \
51 IOMMU_DT_VALID | IOMMU_CACHE_INHIBIT)
52#else
53#define dvma_entry_set(index,addr) (iommu_pte[index] = \
54 (addr & IOMMU_ADDR_MASK) | \
55 IOMMU_DT_VALID)
56#endif
57#define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID)
58#define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \
59 ((addr & 0x03c00000) >> \
60 (DVMA_PAGE_SHIFT+4)))
61
62#undef DEBUG
63
64#ifdef DEBUG
65/* code to print out a dvma mapping for debugging purposes */
66void dvma_print (unsigned long dvma_addr)
67{
68
69 unsigned long index;
70
71 index = dvma_addr >> DVMA_PAGE_SHIFT;
72
73 printk("idx %lx dvma_addr %08lx paddr %08lx\n", index, dvma_addr,
74 dvma_entry_paddr(index));
75
76
77}
78#endif
79
80
81/* create a virtual mapping for a page assigned within the IOMMU
82 so that the cpu can reach it easily */
83inline int dvma_map_cpu(unsigned long kaddr,
84 unsigned long vaddr, int len)
85{
86 pgd_t *pgd;
87 unsigned long end;
88 int ret = 0;
89
90 kaddr &= PAGE_MASK;
91 vaddr &= PAGE_MASK;
92
93 end = PAGE_ALIGN(vaddr + len);
94
95#ifdef DEBUG
96 printk("dvma: mapping kern %08lx to virt %08lx\n",
97 kaddr, vaddr);
98#endif
99 pgd = pgd_offset_k(vaddr);
100
101 do {
102 pmd_t *pmd;
103 unsigned long end2;
104
105 if((pmd = pmd_alloc(&init_mm, pgd, vaddr)) == NULL) {
106 ret = -ENOMEM;
107 goto out;
108 }
109
110 if((end & PGDIR_MASK) > (vaddr & PGDIR_MASK))
111 end2 = (vaddr + (PGDIR_SIZE-1)) & PGDIR_MASK;
112 else
113 end2 = end;
114
115 do {
116 pte_t *pte;
117 unsigned long end3;
118
119 if((pte = pte_alloc_kernel(&init_mm, pmd, vaddr)) == NULL) {
120 ret = -ENOMEM;
121 goto out;
122 }
123
124 if((end2 & PMD_MASK) > (vaddr & PMD_MASK))
125 end3 = (vaddr + (PMD_SIZE-1)) & PMD_MASK;
126 else
127 end3 = end2;
128
129 do {
130#ifdef DEBUG
131 printk("mapping %08lx phys to %08lx\n",
132 __pa(kaddr), vaddr);
133#endif
134 set_pte(pte, pfn_pte(virt_to_pfn(kaddr),
135 PAGE_KERNEL));
136 pte++;
137 kaddr += PAGE_SIZE;
138 vaddr += PAGE_SIZE;
139 } while(vaddr < end3);
140
141 } while(vaddr < end2);
142
143 } while(vaddr < end);
144
145 flush_tlb_all();
146
147 out:
148 return ret;
149}
150
151
152inline int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
153 int len)
154{
155 unsigned long end, index;
156
157 index = baddr >> DVMA_PAGE_SHIFT;
158 end = ((baddr+len) >> DVMA_PAGE_SHIFT);
159
160 if(len & ~DVMA_PAGE_MASK)
161 end++;
162
163 for(; index < end ; index++) {
164// if(dvma_entry_use(index))
165// BUG();
166// printk("mapping pa %lx to ba %lx\n", __pa(kaddr), index << DVMA_PAGE_SHIFT);
167
168 dvma_entry_set(index, __pa(kaddr));
169
170 iommu_pte[index] |= IOMMU_FULL_BLOCK;
171// dvma_entry_inc(index);
172
173 kaddr += DVMA_PAGE_SIZE;
174 }
175
176#ifdef DEBUG
177 for(index = (baddr >> DVMA_PAGE_SHIFT); index < end; index++)
178 dvma_print(index << DVMA_PAGE_SHIFT);
179#endif
180 return 0;
181
182}
183
184void dvma_unmap_iommu(unsigned long baddr, int len)
185{
186
187 int index, end;
188
189
190 index = baddr >> DVMA_PAGE_SHIFT;
191 end = (DVMA_PAGE_ALIGN(baddr+len) >> DVMA_PAGE_SHIFT);
192
193 for(; index < end ; index++) {
194#ifdef DEBUG
195 printk("freeing bus mapping %08x\n", index << DVMA_PAGE_SHIFT);
196#endif
197#if 0
198 if(!dvma_entry_use(index))
199 printk("dvma_unmap freeing unused entry %04x\n",
200 index);
201 else
202 dvma_entry_dec(index);
203#endif
204 dvma_entry_clr(index);
205 }
206
207}
208
diff --git a/arch/m68k/sun3x/prom.c b/arch/m68k/sun3x/prom.c
new file mode 100644
index 000000000000..574cf06df9e4
--- /dev/null
+++ b/arch/m68k/sun3x/prom.c
@@ -0,0 +1,166 @@
1/* Prom access routines for the sun3x */
2
3#include <linux/types.h>
4#include <linux/kernel.h>
5#include <linux/tty.h>
6#include <linux/console.h>
7#include <linux/init.h>
8#include <linux/mm.h>
9#include <linux/string.h>
10
11#include <asm/page.h>
12#include <asm/pgtable.h>
13#include <asm/bootinfo.h>
14#include <asm/setup.h>
15#include <asm/traps.h>
16#include <asm/sun3xprom.h>
17#include <asm/idprom.h>
18#include <asm/segment.h>
19#include <asm/sun3ints.h>
20#include <asm/openprom.h>
21#include <asm/machines.h>
22
23void (*sun3x_putchar)(int);
24int (*sun3x_getchar)(void);
25int (*sun3x_mayget)(void);
26int (*sun3x_mayput)(int);
27void (*sun3x_prom_reboot)(void);
28e_vector sun3x_prom_abort;
29struct linux_romvec *romvec;
30
31/* prom vector table */
32e_vector *sun3x_prom_vbr;
33
34/* Handle returning to the prom */
35void sun3x_halt(void)
36{
37 unsigned long flags;
38
39 /* Disable interrupts while we mess with things */
40 local_irq_save(flags);
41
42 /* Restore prom vbr */
43 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
44
45 /* Restore prom NMI clock */
46// sun3x_disable_intreg(5);
47 sun3_enable_irq(7);
48
49 /* Let 'er rip */
50 __asm__ volatile ("trap #14" : : );
51
52 /* Restore everything */
53 sun3_disable_irq(7);
54 sun3_enable_irq(5);
55
56 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
57 local_irq_restore(flags);
58}
59
60void sun3x_reboot(void)
61{
62 /* This never returns, don't bother saving things */
63 local_irq_disable();
64
65 /* Restore prom vbr */
66 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
67
68 /* Restore prom NMI clock */
69 sun3_disable_irq(5);
70 sun3_enable_irq(7);
71
72 /* Let 'er rip */
73 (*romvec->pv_reboot)("vmlinux");
74}
75
76extern char m68k_debug_device[];
77
78static void sun3x_prom_write(struct console *co, const char *s,
79 unsigned int count)
80{
81 while (count--) {
82 if (*s == '\n')
83 sun3x_putchar('\r');
84 sun3x_putchar(*s++);
85 }
86}
87
88/* debug console - write-only */
89
90static struct console sun3x_debug = {
91 .name = "debug",
92 .write = sun3x_prom_write,
93 .flags = CON_PRINTBUFFER,
94 .index = -1,
95};
96
97void sun3x_prom_init(void)
98{
99 /* Read the vector table */
100
101 sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
102 sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
103 sun3x_mayget = *(int (**)(void)) (SUN3X_P_MAYGET);
104 sun3x_mayput = *(int (**)(int)) (SUN3X_P_MAYPUT);
105 sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
106 sun3x_prom_abort = *(e_vector *) (SUN3X_P_ABORT);
107 romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
108
109 idprom_init();
110
111 if(!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
112 printk("Warning: machine reports strange type %02x\n",
113 idprom->id_machtype);
114 printk("Pretending it's a 3/80, but very afraid...\n");
115 idprom->id_machtype = SM_SUN3X | SM_3_80;
116 }
117
118 /* point trap #14 at abort.
119 * XXX this is futile since we restore the vbr first - oops
120 */
121 vectors[VEC_TRAP14] = sun3x_prom_abort;
122
123 /* If debug=prom was specified, start the debug console */
124
125 if (!strcmp(m68k_debug_device, "prom"))
126 register_console(&sun3x_debug);
127
128
129}
130
131/* some prom functions to export */
132int prom_getintdefault(int node, char *property, int deflt)
133{
134 return deflt;
135}
136
137int prom_getbool (int node, char *prop)
138{
139 return 1;
140}
141
142void prom_printf(char *fmt, ...)
143{
144
145}
146
147void prom_halt (void)
148{
149 sun3x_halt();
150}
151
152/* Get the idprom and stuff it into buffer 'idbuf'. Returns the
153 * format type. 'num_bytes' is the number of bytes that your idbuf
154 * has space for. Returns 0xff on error.
155 */
156unsigned char
157prom_get_idprom(char *idbuf, int num_bytes)
158{
159 int i;
160
161 /* make a copy of the idprom structure */
162 for(i = 0; i < num_bytes; i++)
163 idbuf[i] = ((char *)SUN3X_IDPROM)[i];
164
165 return idbuf[0];
166}
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
new file mode 100644
index 000000000000..6f4204fbecd7
--- /dev/null
+++ b/arch/m68k/sun3x/time.c
@@ -0,0 +1,103 @@
1/*
2 * linux/arch/m68k/sun3x/time.c
3 *
4 * Sun3x-specific time handling
5 */
6
7#include <linux/types.h>
8#include <linux/kd.h>
9#include <linux/init.h>
10#include <linux/sched.h>
11#include <linux/kernel_stat.h>
12#include <linux/interrupt.h>
13#include <linux/rtc.h>
14#include <linux/bcd.h>
15
16#include <asm/irq.h>
17#include <asm/io.h>
18#include <asm/system.h>
19#include <asm/traps.h>
20#include <asm/sun3x.h>
21#include <asm/sun3ints.h>
22#include <asm/rtc.h>
23
24#include "time.h"
25
26#define M_CONTROL 0xf8
27#define M_SEC 0xf9
28#define M_MIN 0xfa
29#define M_HOUR 0xfb
30#define M_DAY 0xfc
31#define M_DATE 0xfd
32#define M_MONTH 0xfe
33#define M_YEAR 0xff
34
35#define C_WRITE 0x80
36#define C_READ 0x40
37#define C_SIGN 0x20
38#define C_CALIB 0x1f
39
40int sun3x_hwclk(int set, struct rtc_time *t)
41{
42 volatile struct mostek_dt *h =
43 (struct mostek_dt *)(SUN3X_EEPROM+M_CONTROL);
44 unsigned long flags;
45
46 local_irq_save(flags);
47
48 if(set) {
49 h->csr |= C_WRITE;
50 h->sec = BIN2BCD(t->tm_sec);
51 h->min = BIN2BCD(t->tm_min);
52 h->hour = BIN2BCD(t->tm_hour);
53 h->wday = BIN2BCD(t->tm_wday);
54 h->mday = BIN2BCD(t->tm_mday);
55 h->month = BIN2BCD(t->tm_mon);
56 h->year = BIN2BCD(t->tm_year);
57 h->csr &= ~C_WRITE;
58 } else {
59 h->csr |= C_READ;
60 t->tm_sec = BCD2BIN(h->sec);
61 t->tm_min = BCD2BIN(h->min);
62 t->tm_hour = BCD2BIN(h->hour);
63 t->tm_wday = BCD2BIN(h->wday);
64 t->tm_mday = BCD2BIN(h->mday);
65 t->tm_mon = BCD2BIN(h->month);
66 t->tm_year = BCD2BIN(h->year);
67 h->csr &= ~C_READ;
68 }
69
70 local_irq_restore(flags);
71
72 return 0;
73}
74/* Not much we can do here */
75unsigned long sun3x_gettimeoffset (void)
76{
77 return 0L;
78}
79
80#if 0
81static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs)
82{
83 void (*vector)(int, void *, struct pt_regs *) = dev_id;
84
85 /* Clear the pending interrupt - pulse the enable line low */
86 disable_irq(5);
87 enable_irq(5);
88
89 vector(irq, NULL, regs);
90}
91#endif
92
93void __init sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
94{
95
96 sun3_disable_interrupts();
97
98
99 /* Pulse enable low to get the clock started */
100 sun3_disable_irq(5);
101 sun3_enable_irq(5);
102 sun3_enable_interrupts();
103}
diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h
new file mode 100644
index 000000000000..e7e43b4ec4a1
--- /dev/null
+++ b/arch/m68k/sun3x/time.h
@@ -0,0 +1,19 @@
1#ifndef SUN3X_TIME_H
2#define SUN3X_TIME_H
3
4extern int sun3x_hwclk(int set, struct rtc_time *t);
5unsigned long sun3x_gettimeoffset (void);
6void sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *));
7
8struct mostek_dt {
9 volatile unsigned char csr;
10 volatile unsigned char sec;
11 volatile unsigned char min;
12 volatile unsigned char hour;
13 volatile unsigned char wday;
14 volatile unsigned char mday;
15 volatile unsigned char month;
16 volatile unsigned char year;
17};
18
19#endif
diff --git a/arch/m68k/tools/amiga/Makefile b/arch/m68k/tools/amiga/Makefile
new file mode 100644
index 000000000000..113436136089
--- /dev/null
+++ b/arch/m68k/tools/amiga/Makefile
@@ -0,0 +1,11 @@
1
2CC = m68k-cbm-amigados-gcc
3CFLAGS = -Wall -O2
4
5
6All: dmesg
7
8
9dmesg: dmesg.c
10 $(CC) $(CFLAGS) -o dmesg dmesg.c -noixemul
11
diff --git a/arch/m68k/tools/amiga/dmesg.c b/arch/m68k/tools/amiga/dmesg.c
new file mode 100644
index 000000000000..e892748e7386
--- /dev/null
+++ b/arch/m68k/tools/amiga/dmesg.c
@@ -0,0 +1,69 @@
1/*
2 * linux/arch/m68k/tools/amiga/dmesg.c -- Retrieve the kernel messages stored
3 * in Chip RAM with the kernel command
4 * line option `debug=mem'.
5 *
6 * © Copyright 1996 by Geert Uytterhoeven <geert@linux-m68k.org>
7 *
8 *
9 * Usage:
10 *
11 * dmesg
12 * dmesg <CHIPMEM_END>
13 *
14 *
15 * This file is subject to the terms and conditions of the GNU General Public
16 * License. See the file COPYING in the main directory of the Linux
17 * distribution for more details.
18 */
19
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24
25
26#define CHIPMEM_START 0x00000000
27#define CHIPMEM_END 0x00200000 /* overridden by argv[1] */
28
29#define SAVEKMSG_MAGIC1 0x53415645 /* 'SAVE' */
30#define SAVEKMSG_MAGIC2 0x4B4D5347 /* 'KMSG' */
31
32struct savekmsg {
33 u_long magic1; /* SAVEKMSG_MAGIC1 */
34 u_long magic2; /* SAVEKMSG_MAGIC2 */
35 u_long magicptr; /* address of magic1 */
36 u_long size;
37 char data[0];
38};
39
40
41int main(int argc, char *argv[])
42{
43 u_long start = CHIPMEM_START, end = CHIPMEM_END, p;
44 int found = 0;
45 struct savekmsg *m = NULL;
46
47 if (argc >= 2)
48 end = strtoul(argv[1], NULL, 0);
49 printf("Searching for SAVEKMSG magic...\n");
50 for (p = start; p <= end-sizeof(struct savekmsg); p += 4) {
51 m = (struct savekmsg *)p;
52 if ((m->magic1 == SAVEKMSG_MAGIC1) && (m->magic2 == SAVEKMSG_MAGIC2) &&
53 (m->magicptr == p)) {
54 found = 1;
55 break;
56 }
57 }
58 if (!found)
59 printf("Not found\n");
60 else {
61 printf("Found %ld bytes at 0x%08lx\n", m->size, (u_long)&m->data);
62 puts(">>>>>>>>>>>>>>>>>>>>");
63 fflush(stdout);
64 write(1, &m->data, m->size);
65 fflush(stdout);
66 puts("<<<<<<<<<<<<<<<<<<<<");
67 }
68 return(0);
69}