git: c5d4a124d093 - main - conf: remove powerpcspe
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 09 Jan 2026 20:13:35 UTC
The branch main has been updated by emaste:
URL: https://cgit.FreeBSD.org/src/commit/?id=c5d4a124d093f11784833f25d1332a54465678fb
commit c5d4a124d093f11784833f25d1332a54465678fb
Author: Minsoo Choo <minsoochoo0122@proton.me>
AuthorDate: 2025-12-03 04:06:10 +0000
Commit: Ed Maste <emaste@FreeBSD.org>
CommitDate: 2026-01-09 20:11:22 +0000
conf: remove powerpcspe
Signed-off-by: Minsoo Choo <minsoochoo0122@proton.me>
Reviewed by: emaste
Pull Request: https://github.com/freebsd/freebsd-src/pull/1914
(cherry picked from commit 4a5a1c17ac43356fae053524187bb16f8fc1ac70)
---
sys/conf/files.powerpc | 51 ++--
sys/conf/ldscript.powerpcspe | 143 ---------
sys/conf/options.powerpc | 1 -
sys/powerpc/booke/spe.c | 685 -------------------------------------------
4 files changed, 25 insertions(+), 855 deletions(-)
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 0deada385f31..7989f1c9bea4 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -75,7 +75,7 @@ crypto/openssl/powerpc64/sha512p8-ppc.S optional ossl powerpc64
crypto/openssl/powerpc64/vpaes-ppc.S optional ossl powerpc64
crypto/openssl/powerpc64/x25519-ppc64.S optional ossl powerpc64
-cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs powerpc | dtrace powerpc | zfs powerpcspe | dtrace powerpcspe compile-with "${ZFS_C}"
+cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs powerpc | dtrace powerpc compile-with "${ZFS_C}"
cddl/dev/dtrace/powerpc/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}"
cddl/dev/dtrace/powerpc/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}"
cddl/dev/fbt/powerpc/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}"
@@ -235,25 +235,25 @@ dev/tsec/if_tsec_fdt.c optional tsec
dev/uart/uart_cpu_powerpc.c optional uart
dev/usb/controller/ehci_fsl.c optional ehci mpc85xx
dev/vt/hw/ofwfb/ofwfb.c optional vt aim
-kern/subr_atomic64.c optional powerpc | powerpcspe
+kern/subr_atomic64.c optional powerpc
kern/subr_dummy_vdso_tc.c standard
kern/subr_sfbuf.c standard
-libkern/ashldi3.c optional powerpc | powerpcspe
-libkern/ashrdi3.c optional powerpc | powerpcspe
+libkern/ashldi3.c optional powerpc
+libkern/ashrdi3.c optional powerpc
libkern/bcopy.c standard
-libkern/cmpdi2.c optional powerpc | powerpcspe
-libkern/divdi3.c optional powerpc | powerpcspe
-libkern/lshrdi3.c optional powerpc | powerpcspe
+libkern/cmpdi2.c optional powerpc
+libkern/divdi3.c optional powerpc
+libkern/lshrdi3.c optional powerpc
libkern/memcmp.c standard
libkern/memset.c standard
-libkern/moddi3.c optional powerpc | powerpcspe
-libkern/qdivrem.c optional powerpc | powerpcspe
+libkern/moddi3.c optional powerpc
+libkern/qdivrem.c optional powerpc
libkern/strcmp.c standard
libkern/strlen.c standard
libkern/strncmp.c standard
-libkern/ucmpdi2.c optional powerpc | powerpcspe
-libkern/udivdi3.c optional powerpc | powerpcspe
-libkern/umoddi3.c optional powerpc | powerpcspe
+libkern/ucmpdi2.c optional powerpc
+libkern/udivdi3.c optional powerpc
+libkern/umoddi3.c optional powerpc
powerpc/aim/locore.S optional aim no-obj
powerpc/aim/aim_machdep.c optional aim
powerpc/aim/mmu_oea.c optional aim powerpc
@@ -263,29 +263,28 @@ powerpc/aim/moea64_native.c optional aim
powerpc/aim/mp_cpudep.c optional aim
powerpc/aim/slb.c optional aim powerpc64 | aim powerpc64le
powerpc/amigaone/platform_amigaone.c optional amigaone
-powerpc/amigaone/cpld_a1222.c optional powerpc amigaone | powerpcspe amigaone
-powerpc/amigaone/cpld_x5000.c optional powerpc amigaone | powerpc64 amigaone
+powerpc/amigaone/cpld_a1222.c optional powerpc amigaone
+powerpc/amigaone/cpld_x5000.c optional powerpc amigaone
powerpc/booke/locore.S optional booke no-obj
powerpc/booke/booke_machdep.c optional booke
powerpc/booke/machdep_e500.c optional booke_e500
powerpc/booke/mp_cpudep.c optional booke smp
powerpc/booke/platform_bare.c optional booke
powerpc/booke/pmap.c optional booke
-powerpc/booke/spe.c optional powerpcspe
powerpc/cpufreq/dfs.c optional cpufreq
powerpc/cpufreq/mpc85xx_jog.c optional cpufreq mpc85xx
powerpc/cpufreq/pcr.c optional cpufreq aim
powerpc/cpufreq/pmcr.c optional cpufreq aim powerpc64 | cpufreq aim powerpc64le
powerpc/cpufreq/pmufreq.c optional cpufreq aim pmu
-powerpc/fpu/fpu_add.c optional fpu_emu | powerpcspe
-powerpc/fpu/fpu_compare.c optional fpu_emu | powerpcspe
-powerpc/fpu/fpu_div.c optional fpu_emu | powerpcspe
+powerpc/fpu/fpu_add.c optional fpu_emu
+powerpc/fpu/fpu_compare.c optional fpu_emu
+powerpc/fpu/fpu_div.c optional fpu_emu
powerpc/fpu/fpu_emu.c optional fpu_emu
-powerpc/fpu/fpu_explode.c optional fpu_emu | powerpcspe
-powerpc/fpu/fpu_implode.c optional fpu_emu | powerpcspe
-powerpc/fpu/fpu_mul.c optional fpu_emu | powerpcspe
+powerpc/fpu/fpu_explode.c optional fpu_emu
+powerpc/fpu/fpu_implode.c optional fpu_emu
+powerpc/fpu/fpu_mul.c optional fpu_emu
powerpc/fpu/fpu_sqrt.c optional fpu_emu
-powerpc/fpu/fpu_subr.c optional fpu_emu | powerpcspe
+powerpc/fpu/fpu_subr.c optional fpu_emu
powerpc/mambo/mambocall.S optional mambo
powerpc/mambo/mambo.c optional mambo
powerpc/mambo/mambo_console.c optional mambo
@@ -358,7 +357,7 @@ powerpc/powernv/platform_powernv.c optional powernv
powerpc/powernv/powernv_centaur.c optional powernv
powerpc/powernv/powernv_xscom.c optional powernv
powerpc/powernv/xive.c optional powernv
-powerpc/powerpc/altivec.c optional !powerpcspe
+powerpc/powerpc/altivec.c standard
powerpc/powerpc/autoconf.c standard
powerpc/powerpc/bus_machdep.c standard
powerpc/powerpc/busdma_machdep.c standard
@@ -371,7 +370,7 @@ powerpc/powerpc/db_hwwatch.c optional ddb
powerpc/powerpc/db_interface.c optional ddb
powerpc/powerpc/db_trace.c optional ddb
powerpc/powerpc/dump_machdep.c standard
-powerpc/powerpc/elf32_machdep.c optional powerpc | powerpcspe | compat_freebsd32
+powerpc/powerpc/elf32_machdep.c optional powerpc | compat_freebsd32
powerpc/powerpc/elf64_machdep.c optional powerpc64 | powerpc64le
powerpc/powerpc/exec_machdep.c standard
powerpc/powerpc/fpu.c standard
@@ -393,9 +392,9 @@ powerpc/powerpc/ptrace_machdep.c standard
powerpc/powerpc/sc_machdep.c optional sc
powerpc/powerpc/sdt_machdep.c optional powerpc64 kdtrace_hooks
powerpc/powerpc/setjmp.S standard
-powerpc/powerpc/sigcode32.S optional powerpc | powerpcspe | compat_freebsd32
+powerpc/powerpc/sigcode32.S optional powerpc | compat_freebsd32
powerpc/powerpc/sigcode64.S optional powerpc64 | powerpc64le
-powerpc/powerpc/swtch32.S optional powerpc | powerpcspe
+powerpc/powerpc/swtch32.S optional powerpc
powerpc/powerpc/swtch64.S optional powerpc64 | powerpc64le
powerpc/powerpc/stack_machdep.c optional ddb | stack
powerpc/powerpc/support.S optional powerpc64 | powerpc64le | booke
diff --git a/sys/conf/ldscript.powerpcspe b/sys/conf/ldscript.powerpcspe
deleted file mode 100644
index fa82cbe8330f..000000000000
--- a/sys/conf/ldscript.powerpcspe
+++ /dev/null
@@ -1,143 +0,0 @@
-OUTPUT_FORMAT("elf32-powerpc-freebsd", "elf32-powerpc-freebsd",
- "elf32-powerpc-freebsd")
-OUTPUT_ARCH(powerpc)
-ENTRY(__start)
-SEARCH_DIR(/usr/lib);
-PROVIDE (__stack = 0);
-PHDRS
-{
- kernel PT_LOAD;
- dynamic PT_DYNAMIC;
-}
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
-
- . = kernbase + SIZEOF_HEADERS;
- PROVIDE (begin = . - SIZEOF_HEADERS);
-
- .text :
- {
- *(.glink)
- *(.text)
- *(.stub)
- /* .gnu.warning sections are handled specially by elf32.em. */
- *(.gnu.warning)
- *(.gnu.linkonce.t*)
- } :kernel =0
- _etext = .;
- PROVIDE (etext = .);
-
- .interp : { *(.interp) }
- .hash : { *(.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
- .rela.text :
- { *(.rela.text) *(.rela.gnu.linkonce.t*) }
- .rela.data :
- { *(.rela.data) *(.rela.gnu.linkonce.d*) }
- .rela.rodata :
- { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
- .rela.got : { *(.rela.got) }
- .rela.got1 : { *(.rela.got1) }
- .rela.got2 : { *(.rela.got2) }
- .rela.ctors : { *(.rela.ctors) }
- .rela.dtors : { *(.rela.dtors) }
- .rela.init : { *(.rela.init) }
- .rela.fini : { *(.rela.fini) }
- .rela.bss : { *(.rela.bss) }
- .rela.plt : { *(.rela.plt) }
- .rela.sdata : { *(.rela.sdata) }
- .rela.sbss : { *(.rela.sbss) }
- .rela.sdata2 : { *(.rela.sdata2) }
- .rela.sbss2 : { *(.rela.sbss2) }
-
- .init : { *(.init) } =0
- .fini : { *(.fini) } =0
- .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
- .rodata1 : { *(.rodata1) }
- .note.gnu.build-id : {
- PROVIDE (__build_id_start = .);
- *(.note.gnu.build-id)
- PROVIDE (__build_id_end = .);
- }
- .sdata2 : { *(.sdata2) }
- .sbss2 : { *(.sbss2) }
- /* Adjust the address for the data segment to the next page up. */
- . = ((. + 0x1000) & ~(0x1000 - 1));
- .data :
- {
- *(.data)
- *(.gnu.linkonce.d*)
- CONSTRUCTORS
- }
- .data1 : { *(.data1) }
- .got1 : { *(.got1) }
- . = ALIGN(4096);
- .got : { *(.got) }
- .got.plt : { *(.got.plt) }
- .init_array :
- {
- PROVIDE_HIDDEN (__init_array_start = .);
- KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*)))
- KEEP (*(.init_array))
- PROVIDE_HIDDEN (__init_array_end = .);
- }
- .fini_array :
- {
- PROVIDE_HIDDEN (__fini_array_start = .);
- KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*)))
- KEEP (*(.fini_array))
- PROVIDE_HIDDEN (__fini_array_end = .);
- }
- .dynamic : { *(.dynamic) } :kernel :dynamic
- /* Put .ctors and .dtors next to the .got2 section, so that the pointers
- get relocated with -mrelocatable. Also put in the .fixup pointers.
- The current compiler no longer needs this, but keep it around for 2.7.2 */
- PROVIDE (_GOT2_START_ = .);
- .got2 : { *(.got2) } :kernel
- PROVIDE (__CTOR_LIST__ = .);
- .ctors : { *(.ctors) }
- PROVIDE (__CTOR_END__ = .);
- PROVIDE (__DTOR_LIST__ = .);
- .dtors : { *(.dtors) }
- PROVIDE (__DTOR_END__ = .);
- PROVIDE (_FIXUP_START_ = .);
- .fixup : { *(.fixup) }
- PROVIDE (_FIXUP_END_ = .);
- PROVIDE (_GOT2_END_ = .);
- /* We want the small data sections together, so single-instruction offsets
- can access them all, and initialized data all before uninitialized, so
- we can shorten the on-disk segment size. */
- .sdata : { *(.sdata) }
- _edata = .;
- PROVIDE (edata = .);
- .sbss :
- {
- PROVIDE (__sbss_start = .);
- *(.sbss)
- *(.scommon)
- *(.dynsbss)
- PROVIDE (__sbss_end = .);
- }
- .plt : { *(.plt) }
- .bss :
- {
- PROVIDE (__bss_start = .);
- *(.dynbss)
- *(.bss)
- *(COMMON)
- }
- _end = . ;
- PROVIDE (end = .);
-
- /* Debug */
- INCLUDE debuginfo.ldscript
-
- .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
- /DISCARD/ : { *(.note.GNU-stack) }
-}
-
diff --git a/sys/conf/options.powerpc b/sys/conf/options.powerpc
index a6096d1b32ca..c8ab0e066f49 100644
--- a/sys/conf/options.powerpc
+++ b/sys/conf/options.powerpc
@@ -8,7 +8,6 @@ CELL
POWERPC
POWERPC64
POWERPC64LE
-POWERPCSPE
FPU_EMU
diff --git a/sys/powerpc/booke/spe.c b/sys/powerpc/booke/spe.c
deleted file mode 100644
index e10392508e4e..000000000000
--- a/sys/powerpc/booke/spe.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/*-
- * Copyright (C) 1996 Wolfgang Solfrank.
- * Copyright (C) 1996 TooLs GmbH.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by TooLs GmbH.
- * 4. The name of TooLs GmbH may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $NetBSD: fpu.c,v 1.5 2001/07/22 11:29:46 wiz Exp $
- */
-
-#include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/systm.h>
-#include <sys/limits.h>
-
-#include <machine/altivec.h>
-#include <machine/fpu.h>
-#include <machine/ieeefp.h>
-#include <machine/pcb.h>
-#include <machine/psl.h>
-
-#include <powerpc/fpu/fpu_arith.h>
-#include <powerpc/fpu/fpu_emu.h>
-#include <powerpc/fpu/fpu_extern.h>
-
-void spe_handle_fpdata(struct trapframe *);
-void spe_handle_fpround(struct trapframe *);
-static int spe_emu_instr(uint32_t, struct fpemu *, struct fpn **, uint32_t *);
-
-static void
-save_vec_int(struct thread *td)
-{
- int msr;
- struct pcb *pcb;
-
- pcb = td->td_pcb;
-
- /*
- * Temporarily re-enable the vector unit during the save
- */
- msr = mfmsr();
- mtmsr(msr | PSL_VEC);
-
- /*
- * Save the vector registers and SPEFSCR to the PCB
- */
-#define EVSTDW(n) __asm ("evstdw %1,0(%0)" \
- :: "b"(pcb->pcb_vec.vr[n]), "n"(n));
- EVSTDW(0); EVSTDW(1); EVSTDW(2); EVSTDW(3);
- EVSTDW(4); EVSTDW(5); EVSTDW(6); EVSTDW(7);
- EVSTDW(8); EVSTDW(9); EVSTDW(10); EVSTDW(11);
- EVSTDW(12); EVSTDW(13); EVSTDW(14); EVSTDW(15);
- EVSTDW(16); EVSTDW(17); EVSTDW(18); EVSTDW(19);
- EVSTDW(20); EVSTDW(21); EVSTDW(22); EVSTDW(23);
- EVSTDW(24); EVSTDW(25); EVSTDW(26); EVSTDW(27);
- EVSTDW(28); EVSTDW(29); EVSTDW(30); EVSTDW(31);
-#undef EVSTDW
-
- __asm ( "evxor 0,0,0\n"
- "evmwumiaa 0,0,0\n"
- "evstdd 0,0(%0)" :: "b"(&pcb->pcb_vec.spare[0]));
- pcb->pcb_vec.vscr = mfspr(SPR_SPEFSCR);
-
- /*
- * Disable vector unit again
- */
- isync();
- mtmsr(msr);
-
-}
-
-void
-enable_vec(struct thread *td)
-{
- int msr;
- struct pcb *pcb;
- struct trapframe *tf;
-
- pcb = td->td_pcb;
- tf = trapframe(td);
-
- /*
- * Save the thread's SPE CPU number, and set the CPU's current
- * vector thread
- */
- td->td_pcb->pcb_veccpu = PCPU_GET(cpuid);
- PCPU_SET(vecthread, td);
-
- /*
- * Enable the vector unit for when the thread returns from the
- * exception. If this is the first time the unit has been used by
- * the thread, initialise the vector registers and VSCR to 0, and
- * set the flag to indicate that the vector unit is in use.
- */
- tf->srr1 |= PSL_VEC;
- if (!(pcb->pcb_flags & PCB_VEC)) {
- memset(&pcb->pcb_vec, 0, sizeof pcb->pcb_vec);
- pcb->pcb_flags |= PCB_VEC;
- pcb->pcb_vec.vscr = mfspr(SPR_SPEFSCR);
- }
-
- /*
- * Temporarily enable the vector unit so the registers
- * can be restored.
- */
- msr = mfmsr();
- mtmsr(msr | PSL_VEC);
-
- /* Restore SPEFSCR and ACC. Use %r0 as the scratch for ACC. */
- mtspr(SPR_SPEFSCR, pcb->pcb_vec.vscr);
- __asm __volatile("isync;evldd 0, 0(%0); evmra 0,0\n"
- :: "b"(&pcb->pcb_vec.spare[0]));
-
- /*
- * The lower half of each register will be restored on trap return. Use
- * %r0 as a scratch register, and restore it last.
- */
-#define EVLDW(n) __asm __volatile("evldw 0, 0(%0); evmergehilo "#n",0,"#n \
- :: "b"(&pcb->pcb_vec.vr[n]));
- EVLDW(1); EVLDW(2); EVLDW(3); EVLDW(4);
- EVLDW(5); EVLDW(6); EVLDW(7); EVLDW(8);
- EVLDW(9); EVLDW(10); EVLDW(11); EVLDW(12);
- EVLDW(13); EVLDW(14); EVLDW(15); EVLDW(16);
- EVLDW(17); EVLDW(18); EVLDW(19); EVLDW(20);
- EVLDW(21); EVLDW(22); EVLDW(23); EVLDW(24);
- EVLDW(25); EVLDW(26); EVLDW(27); EVLDW(28);
- EVLDW(29); EVLDW(30); EVLDW(31); EVLDW(0);
-#undef EVLDW
-
- isync();
- mtmsr(msr);
-}
-
-void
-save_vec(struct thread *td)
-{
- struct pcb *pcb;
-
- pcb = td->td_pcb;
-
- save_vec_int(td);
-
- /*
- * Clear the current vec thread and pcb's CPU id
- * XXX should this be left clear to allow lazy save/restore ?
- */
- pcb->pcb_veccpu = INT_MAX;
- PCPU_SET(vecthread, NULL);
-}
-
-/*
- * Save SPE state without dropping ownership. This will only save state if
- * the current vector-thread is `td'. This is used for taking core dumps, so
- * don't leak kernel information; overwrite the low words of each vector with
- * their real value, taken from the thread's trap frame, unconditionally.
- */
-void
-save_vec_nodrop(struct thread *td)
-{
- struct pcb *pcb;
- int i;
-
- if (td == PCPU_GET(vecthread))
- save_vec_int(td);
-
- pcb = td->td_pcb;
-
- for (i = 0; i < 32; i++) {
- pcb->pcb_vec.vr[i][1] =
- td->td_frame ? td->td_frame->fixreg[i] : 0;
- }
-}
-
-#define SPE_INST_MASK 0x31f
-#define EADD 0x200
-#define ESUB 0x201
-#define EABS 0x204
-#define ENABS 0x205
-#define ENEG 0x206
-#define EMUL 0x208
-#define EDIV 0x209
-#define ECMPGT 0x20c
-#define ECMPLT 0x20d
-#define ECMPEQ 0x20e
-#define ECFUI 0x210
-#define ECFSI 0x211
-#define ECTUI 0x214
-#define ECTSI 0x215
-#define ECTUF 0x216
-#define ECTSF 0x217
-#define ECTUIZ 0x218
-#define ECTSIZ 0x21a
-
-#define SPE 0x4
-#define SPFP 0x6
-#define DPFP 0x7
-
-#define SPE_OPC 4
-#define OPC_SHIFT 26
-
-#define EVFSADD 0x280
-#define EVFSSUB 0x281
-#define EVFSABS 0x284
-#define EVFSNABS 0x285
-#define EVFSNEG 0x286
-#define EVFSMUL 0x288
-#define EVFSDIV 0x289
-#define EVFSCMPGT 0x28c
-#define EVFSCMPLT 0x28d
-#define EVFSCMPEQ 0x28e
-#define EVFSCFUI 0x290
-#define EVFSCFSI 0x291
-#define EVFSCTUI 0x294
-#define EVFSCTSI 0x295
-#define EVFSCTUF 0x296
-#define EVFSCTSF 0x297
-#define EVFSCTUIZ 0x298
-#define EVFSCTSIZ 0x29a
-
-#define EFSADD 0x2c0
-#define EFSSUB 0x2c1
-#define EFSABS 0x2c4
-#define EFSNABS 0x2c5
-#define EFSNEG 0x2c6
-#define EFSMUL 0x2c8
-#define EFSDIV 0x2c9
-#define EFSCMPGT 0x2cc
-#define EFSCMPLT 0x2cd
-#define EFSCMPEQ 0x2ce
-#define EFSCFD 0x2cf
-#define EFSCFUI 0x2d0
-#define EFSCFSI 0x2d1
-#define EFSCTUI 0x2d4
-#define EFSCTSI 0x2d5
-#define EFSCTUF 0x2d6
-#define EFSCTSF 0x2d7
-#define EFSCTUIZ 0x2d8
-#define EFSCTSIZ 0x2da
-
-#define EFDADD 0x2e0
-#define EFDSUB 0x2e1
-#define EFDABS 0x2e4
-#define EFDNABS 0x2e5
-#define EFDNEG 0x2e6
-#define EFDMUL 0x2e8
-#define EFDDIV 0x2e9
-#define EFDCMPGT 0x2ec
-#define EFDCMPLT 0x2ed
-#define EFDCMPEQ 0x2ee
-#define EFDCFS 0x2ef
-#define EFDCFUI 0x2f0
-#define EFDCFSI 0x2f1
-#define EFDCTUI 0x2f4
-#define EFDCTSI 0x2f5
-#define EFDCTUF 0x2f6
-#define EFDCTSF 0x2f7
-#define EFDCTUIZ 0x2f8
-#define EFDCTSIZ 0x2fa
-
-enum {
- NONE,
- SINGLE,
- DOUBLE,
- VECTOR,
-};
-
-static uint32_t fpscr_to_spefscr(uint32_t fpscr)
-{
- uint32_t spefscr;
-
- spefscr = 0;
-
- if (fpscr & FPSCR_VX)
- spefscr |= SPEFSCR_FINV;
- if (fpscr & FPSCR_OX)
- spefscr |= SPEFSCR_FOVF;
- if (fpscr & FPSCR_UX)
- spefscr |= SPEFSCR_FUNF;
- if (fpscr & FPSCR_ZX)
- spefscr |= SPEFSCR_FDBZ;
- if (fpscr & FPSCR_XX)
- spefscr |= SPEFSCR_FX;
-
- return (spefscr);
-}
-
-/* Sign is 0 for unsigned, 1 for signed. */
-static int
-spe_to_int(struct fpemu *fpemu, struct fpn *fpn, uint32_t *val, int sign)
-{
- uint32_t res[2];
-
- res[0] = fpu_ftox(fpemu, fpn, res);
- if (res[0] != UINT_MAX && res[0] != 0)
- fpemu->fe_cx |= FPSCR_OX;
- else if (sign == 0 && res[0] != 0)
- fpemu->fe_cx |= FPSCR_UX;
- else
- *val = res[1];
-
- return (0);
-}
-
-/* Masked instruction */
-/*
- * For compare instructions, returns 1 if success, 0 if not. For all others,
- * returns -1, or -2 if no result needs recorded.
- */
-static int
-spe_emu_instr(uint32_t instr, struct fpemu *fpemu,
- struct fpn **result, uint32_t *iresult)
-{
- switch (instr & SPE_INST_MASK) {
- case EABS:
- case ENABS:
- case ENEG:
- /* Taken care of elsewhere. */
- break;
- case ECTUIZ:
- fpemu->fe_cx &= ~FPSCR_RN;
- fpemu->fe_cx |= FP_RZ;
- case ECTUI:
- spe_to_int(fpemu, &fpemu->fe_f2, iresult, 0);
- return (-1);
- case ECTSIZ:
- fpemu->fe_cx &= ~FPSCR_RN;
- fpemu->fe_cx |= FP_RZ;
- case ECTSI:
- spe_to_int(fpemu, &fpemu->fe_f2, iresult, 1);
- return (-1);
- case EADD:
- *result = fpu_add(fpemu);
- break;
- case ESUB:
- *result = fpu_sub(fpemu);
- break;
- case EMUL:
- *result = fpu_mul(fpemu);
- break;
- case EDIV:
- *result = fpu_div(fpemu);
- break;
- case ECMPGT:
- fpu_compare(fpemu, 0);
- if (fpemu->fe_cx & FPSCR_FG)
- return (1);
- return (0);
- case ECMPLT:
- fpu_compare(fpemu, 0);
- if (fpemu->fe_cx & FPSCR_FL)
- return (1);
- return (0);
- case ECMPEQ:
- fpu_compare(fpemu, 0);
- if (fpemu->fe_cx & FPSCR_FE)
- return (1);
- return (0);
- default:
- printf("Unknown instruction %x\n", instr);
- }
-
- return (-1);
-}
-
-static int
-spe_explode(struct fpemu *fe, struct fpn *fp, uint32_t type,
- uint32_t hi, uint32_t lo)
-{
- uint32_t s;
-
- fp->fp_sign = hi >> 31;
- fp->fp_sticky = 0;
- switch (type) {
- case SINGLE:
- s = fpu_stof(fp, hi);
- break;
-
- case DOUBLE:
- s = fpu_dtof(fp, hi, lo);
- break;
- }
-
- if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
- /*
- * Input is a signalling NaN. All operations that return
- * an input NaN operand put it through a ``NaN conversion'',
- * which basically just means ``turn on the quiet bit''.
- * We do this here so that all NaNs internally look quiet
- * (we can tell signalling ones by their class).
- */
- fp->fp_mant[0] |= FP_QUIETBIT;
- fe->fe_cx = FPSCR_VXSNAN; /* assert invalid operand */
- s = FPC_SNAN;
- }
- fp->fp_class = s;
-
- return (0);
-}
-
-/*
- * Save the high word of a 64-bit GPR for manipulation in the exception handler.
- */
-static uint32_t
-spe_save_reg_high(int reg)
-{
- uint32_t vec[2];
-#define EVSTDW(n) case n: __asm __volatile ("evstdw %1,0(%0)" \
- :: "b"(vec), "n"(n) : "memory"); break;
- switch (reg) {
- EVSTDW(0); EVSTDW(1); EVSTDW(2); EVSTDW(3);
- EVSTDW(4); EVSTDW(5); EVSTDW(6); EVSTDW(7);
- EVSTDW(8); EVSTDW(9); EVSTDW(10); EVSTDW(11);
- EVSTDW(12); EVSTDW(13); EVSTDW(14); EVSTDW(15);
- EVSTDW(16); EVSTDW(17); EVSTDW(18); EVSTDW(19);
- EVSTDW(20); EVSTDW(21); EVSTDW(22); EVSTDW(23);
- EVSTDW(24); EVSTDW(25); EVSTDW(26); EVSTDW(27);
- EVSTDW(28); EVSTDW(29); EVSTDW(30); EVSTDW(31);
- }
-#undef EVSTDW
-
- return (vec[0]);
-}
-
-/*
- * Load the given value into the high word of the requested register.
- */
-static void
-spe_load_reg_high(int reg, uint32_t val)
-{
-#define EVLDW(n) case n: __asm __volatile("evmergelo "#n",%0,"#n \
- :: "r"(val)); break;
- switch (reg) {
- EVLDW(1); EVLDW(2); EVLDW(3); EVLDW(4);
- EVLDW(5); EVLDW(6); EVLDW(7); EVLDW(8);
- EVLDW(9); EVLDW(10); EVLDW(11); EVLDW(12);
- EVLDW(13); EVLDW(14); EVLDW(15); EVLDW(16);
- EVLDW(17); EVLDW(18); EVLDW(19); EVLDW(20);
- EVLDW(21); EVLDW(22); EVLDW(23); EVLDW(24);
- EVLDW(25); EVLDW(26); EVLDW(27); EVLDW(28);
- EVLDW(29); EVLDW(30); EVLDW(31); EVLDW(0);
- }
-#undef EVLDW
-
-}
-
-void
-spe_handle_fpdata(struct trapframe *frame)
-{
- struct fpemu fpemu;
- struct fpn *result;
- uint32_t instr, instr_sec_op;
- uint32_t cr_shift, ra, rb, rd, src;
- uint32_t high, low, res, tmp; /* For vector operations. */
- uint32_t spefscr = 0;
- uint32_t ftod_res[2];
- int width; /* Single, Double, Vector, Integer */
- int err;
- uint32_t msr;
-
- err = fueword32((void *)frame->srr0, &instr);
-
- if (err != 0)
- return;
- /* Fault. */;
-
- if ((instr >> OPC_SHIFT) != SPE_OPC)
- return;
-
- msr = mfmsr();
- /*
- * 'cr' field is the upper 3 bits of rd. Magically, since a) rd is 5
- * bits, b) each 'cr' field is 4 bits, and c) Only the 'GT' bit is
- * modified for most compare operations, the full value of rd can be
- * used as a shift value.
- */
- rd = (instr >> 21) & 0x1f;
- ra = (instr >> 16) & 0x1f;
- rb = (instr >> 11) & 0x1f;
- src = (instr >> 5) & 0x7;
- cr_shift = 28 - (rd & 0x1f);
-
- instr_sec_op = (instr & 0x7ff);
-
- memset(&fpemu, 0, sizeof(fpemu));
-
- width = NONE;
- switch (src) {
- case SPE:
- mtmsr(msr | PSL_VEC);
- switch (instr_sec_op) {
- case EVFSABS:
- high = spe_save_reg_high(ra) & ~(1U << 31);
- frame->fixreg[rd] = frame->fixreg[ra] & ~(1U << 31);
- spe_load_reg_high(rd, high);
- break;
- case EVFSNABS:
- high = spe_save_reg_high(ra) | (1U << 31);
- frame->fixreg[rd] = frame->fixreg[ra] | (1U << 31);
- spe_load_reg_high(rd, high);
- break;
- case EVFSNEG:
- high = spe_save_reg_high(ra) ^ (1U << 31);
- frame->fixreg[rd] = frame->fixreg[ra] ^ (1U << 31);
- spe_load_reg_high(rd, high);
- break;
- default:
- /* High word */
- spe_explode(&fpemu, &fpemu.fe_f1, SINGLE,
- spe_save_reg_high(ra), 0);
- spe_explode(&fpemu, &fpemu.fe_f2, SINGLE,
- spe_save_reg_high(rb), 0);
- high = spe_emu_instr(instr_sec_op, &fpemu, &result,
- &tmp);
-
- if (high < 0)
- spe_load_reg_high(rd, tmp);
-
- spefscr = fpscr_to_spefscr(fpemu.fe_cx) << 16;
- /* Clear the fpemu to start over on the lower bits. */
- memset(&fpemu, 0, sizeof(fpemu));
-
- /* Now low word */
- spe_explode(&fpemu, &fpemu.fe_f1, SINGLE,
- frame->fixreg[ra], 0);
- spe_explode(&fpemu, &fpemu.fe_f2, SINGLE,
- frame->fixreg[rb], 0);
- spefscr |= fpscr_to_spefscr(fpemu.fe_cx);
- low = spe_emu_instr(instr_sec_op, &fpemu, &result,
- &frame->fixreg[rd]);
- if (instr_sec_op == EVFSCMPEQ ||
- instr_sec_op == EVFSCMPGT ||
- instr_sec_op == EVFSCMPLT) {
- res = (high << 3) | (low << 2) |
- ((high | low) << 1) | (high & low);
- width = NONE;
- } else
- width = VECTOR;
- break;
- }
- goto end;
-
- case SPFP:
- switch (instr_sec_op) {
- case EFSABS:
- frame->fixreg[rd] = frame->fixreg[ra] & ~(1U << 31);
- break;
- case EFSNABS:
- frame->fixreg[rd] = frame->fixreg[ra] | (1U << 31);
- break;
- case EFSNEG:
- frame->fixreg[rd] = frame->fixreg[ra] ^ (1U << 31);
- break;
- case EFSCFD:
- mtmsr(msr | PSL_VEC);
- spe_explode(&fpemu, &fpemu.fe_f3, DOUBLE,
- spe_save_reg_high(rb), frame->fixreg[rb]);
- result = &fpemu.fe_f3;
- width = SINGLE;
- break;
- default:
- spe_explode(&fpemu, &fpemu.fe_f1, SINGLE,
- frame->fixreg[ra], 0);
- spe_explode(&fpemu, &fpemu.fe_f2, SINGLE,
- frame->fixreg[rb], 0);
- width = SINGLE;
- }
- break;
- case DPFP:
- mtmsr(msr | PSL_VEC);
- switch (instr_sec_op) {
- case EFDABS:
- high = spe_save_reg_high(ra) & ~(1U << 31);
- frame->fixreg[rd] = frame->fixreg[ra];
- spe_load_reg_high(rd, high);
- break;
- case EFDNABS:
- high = spe_save_reg_high(ra) | (1U << 31);
- frame->fixreg[rd] = frame->fixreg[ra];
- spe_load_reg_high(rd, high);
- break;
- case EFDNEG:
- high = spe_save_reg_high(ra) ^ (1U << 31);
- frame->fixreg[rd] = frame->fixreg[ra];
- spe_load_reg_high(rd, high);
- break;
- case EFDCFS:
- spe_explode(&fpemu, &fpemu.fe_f3, SINGLE,
- frame->fixreg[rb], 0);
- result = &fpemu.fe_f3;
- width = DOUBLE;
- break;
- default:
- spe_explode(&fpemu, &fpemu.fe_f1, DOUBLE,
- spe_save_reg_high(ra), frame->fixreg[ra]);
- spe_explode(&fpemu, &fpemu.fe_f2, DOUBLE,
- spe_save_reg_high(rb), frame->fixreg[rb]);
- width = DOUBLE;
- }
- break;
- }
- switch (instr_sec_op) {
- case EFDCFS:
- case EFSCFD:
- /* Already handled. */
- break;
- default:
- res = spe_emu_instr(instr_sec_op, &fpemu, &result,
- &frame->fixreg[rd]);
- if (res != -1)
- res <<= 2;
- break;
- }
-
- switch (instr_sec_op & SPE_INST_MASK) {
- case ECMPEQ:
- case ECMPGT:
- case ECMPLT:
- frame->cr &= ~(0xf << cr_shift);
- frame->cr |= (res << cr_shift);
- break;
- case ECTUI:
- case ECTUIZ:
- case ECTSI:
- case ECTSIZ:
- break;
- default:
- switch (width) {
- case NONE:
- case VECTOR:
- break;
- case SINGLE:
- frame->fixreg[rd] = fpu_ftos(&fpemu, result);
- break;
- case DOUBLE:
- spe_load_reg_high(rd, fpu_ftod(&fpemu, result, ftod_res));
- frame->fixreg[rd] = ftod_res[1];
- break;
- default:
- panic("Unknown storage width %d", width);
- break;
- }
- }
-
-end:
- spefscr |= (mfspr(SPR_SPEFSCR) & ~SPEFSCR_FINVS);
- mtspr(SPR_SPEFSCR, spefscr);
- frame->srr0 += 4;
- mtmsr(msr);
-
- return;
-}
-
-void
-spe_handle_fpround(struct trapframe *frame)
*** 8 LINES SKIPPED ***