? compile/DAINTREE4 ? i386/conf/DAINTREE4 Index: conf/options.i386 =================================================================== RCS file: /home/ncvs/src/sys/conf/options.i386,v retrieving revision 1.132.2.6 diff -u -r1.132.2.6 options.i386 --- conf/options.i386 2001/08/10 17:16:35 1.132.2.6 +++ conf/options.i386 2001/08/15 00:50:51 @@ -58,6 +58,7 @@ CYRIX_CACHE_WORKS opt_cpu.h CYRIX_CACHE_REALLY_WORKS opt_cpu.h NO_MEMORY_HOLE opt_cpu.h +CPU_ENABLE_SSE opt_cpu.h # The CPU type affects the endian conversion functions all over the kernel. I386_CPU opt_global.h Index: gnu/i386/fpemul/fpu_system.h =================================================================== RCS file: /home/ncvs/src/sys/gnu/i386/fpemul/fpu_system.h,v retrieving revision 1.7 diff -u -r1.7 fpu_system.h --- gnu/i386/fpemul/fpu_system.h 1999/08/28 00:42:51 1.7 +++ gnu/i386/fpemul/fpu_system.h 2001/08/15 00:50:51 @@ -69,7 +69,7 @@ #include */ -#define I387 (*(union i387_union *)&(((struct pcb *)curproc->p_addr)->pcb_savefpu)) +#define I387 (*(union i387_union *)&(((struct pcb *)curproc->p_addr)->pcb_save.sv_87)) #define FPU_info (I387.soft.frame) #define FPU_CS (*(unsigned short *) &(FPU_info->tf_cs)) Index: i386/conf/LINT =================================================================== RCS file: /home/ncvs/src/sys/i386/conf/Attic/LINT,v retrieving revision 1.749.2.76 diff -u -r1.749.2.76 LINT --- i386/conf/LINT 2001/08/09 01:12:49 1.749.2.76 +++ i386/conf/LINT 2001/08/15 00:50:51 @@ -166,6 +166,8 @@ # reorder). This option should not be used if you use memory mapped # I/O device(s). # +# CPU_ENABLE_SSE enables SSE/MMX2 instructions support. +# # CPU_FASTER_5X86_FPU enables faster FPU exception handler. # # CPU_I486_ON_386 enables CPU cache on i486 based CPU upgrade products @@ -227,6 +229,7 @@ options CPU_BTB_EN options CPU_DIRECT_MAPPED_CACHE options CPU_DISABLE_5X86_LSSER +options CPU_ENABLE_SSE options CPU_FASTER_5X86_FPU options CPU_I486_ON_386 options CPU_IORT Index: i386/i386/exception.s =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/exception.s,v retrieving revision 1.65.2.2 diff -u -r1.65.2.2 exception.s --- i386/i386/exception.s 2000/07/07 00:38:46 1.65.2.2 +++ i386/i386/exception.s 2001/08/15 00:50:51 @@ -200,6 +200,9 @@ IDTVEC(align) TRAP(T_ALIGNFLT) +IDTVEC(xmm) + pushl $0; TRAP(T_XMMFLT) + /* * _alltraps entry point. Interrupts are enabled if this was a trap * gate (TGT), else disabled if this was an interrupt gate (IGT). Index: i386/i386/genassym.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/genassym.c,v retrieving revision 1.86.2.1 diff -u -r1.86.2.1 genassym.c --- i386/i386/genassym.c 2000/05/16 06:58:06 1.86.2.1 +++ i386/i386/genassym.c 2001/08/15 00:50:51 @@ -132,8 +132,9 @@ ASSYM(PCB_SPARE, offsetof(struct pcb, __pcb_spare)); ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); -ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_savefpu)); -ASSYM(PCB_SAVEFPU_SIZE, sizeof(struct save87)); +ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_save)); +ASSYM(PCB_SAVEFPU_SIZE, sizeof(union savefpu)); +ASSYM(PCB_SAVE87_SIZE, sizeof(struct save87)); ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); #ifdef SMP Index: i386/i386/initcpu.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/initcpu.c,v retrieving revision 1.19.2.2 diff -u -r1.19.2.2 initcpu.c --- i386/i386/initcpu.c 2000/10/15 03:09:32 1.19.2.2 +++ i386/i386/initcpu.c 2001/08/15 00:50:51 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -61,8 +62,14 @@ static void init_6x86MX(void); static void init_ppro(void); static void init_mendocino(void); +void enable_sse(void); #endif +int hw_instruction_sse = 0; +SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, + &hw_instruction_sse, 0, + "SIMD/MMX2 instructions available in CPU"); + #ifdef I486_CPU /* * IBM Blue Lightning @@ -501,6 +508,20 @@ #endif /* CPU_PPRO2CELERON */ } +/* + * Initialize CR4 (Control register 4) to enable SSE instructions. + */ +void +enable_sse(void) +{ +#if defined(CPU_ENABLE_SSE) + if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) { + load_cr4(rcr4() | CR4_FXSR | CR4_XMM); + cpu_fxsr = hw_instruction_sse = 1; + } +#endif +} + #endif /* I686_CPU */ void @@ -550,6 +571,9 @@ default: break; } +#ifdef I686_CPU + enable_sse(); +#endif #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE) /* Index: i386/i386/locore.s =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/locore.s,v retrieving revision 1.132.2.4 diff -u -r1.132.2.4 locore.s --- i386/i386/locore.s 2001/06/15 09:38:04 1.132.2.4 +++ i386/i386/locore.s 2001/08/15 00:50:51 @@ -96,12 +96,13 @@ .globl _boothowto,_bootdev .globl _cpu,_cpu_vendor,_cpu_id,_bootinfo - .globl _cpu_high, _cpu_feature + .globl _cpu_high, _cpu_feature, _cpu_fxsr _cpu: .long 0 /* are we 386, 386sx, or 486 */ _cpu_id: .long 0 /* stepping ID */ _cpu_high: .long 0 /* highest arg to CPUID */ _cpu_feature: .long 0 /* features */ +_cpu_fxsr: .long 0 /* use fxsave/fxrstor instruction */ _cpu_vendor: .space 20 /* CPU origin code */ _bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ Index: i386/i386/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v retrieving revision 1.385.2.15 diff -u -r1.385.2.15 machdep.c --- i386/i386/machdep.c 2001/07/30 23:27:59 1.385.2.15 +++ i386/i386/machdep.c 2001/08/15 00:50:51 @@ -126,6 +126,10 @@ extern void initializecpu(void); static void cpu_startup __P((void *)); +#ifdef CPU_ENABLE_SSE +static void set_fpregs_xmm __P((struct save87 *, struct savexmm *)); +static void fill_fpregs_xmm __P((struct savexmm *, struct save87 *)); +#endif /* CPU_ENABLE_SSE */ SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) static MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf"); @@ -1378,7 +1382,7 @@ IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm), IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), - IDTVEC(syscall), IDTVEC(int0x80_syscall); + IDTVEC(xmm), IDTVEC(syscall), IDTVEC(int0x80_syscall); void sdtossd(sd, ssd) @@ -1910,6 +1914,7 @@ setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(18, &IDTVEC(mchk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + setidt(19, &IDTVEC(xmm), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(0x80, &IDTVEC(int0x80_syscall), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); @@ -2104,8 +2109,8 @@ *(int*)((char *)p->p_addr + off) = data; return (0); } - min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu); - if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) { + min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_save); + if (off >= min && off <= min + sizeof(union savefpu) - sizeof(int)) { *(int*)((char *)p->p_addr + off) = data; return (0); } @@ -2173,12 +2178,73 @@ return (0); } +#ifdef CPU_ENABLE_SSE +static void +fill_fpregs_xmm(sv_xmm, sv_87) + struct savexmm *sv_xmm; + struct save87 *sv_87; +{ + register struct env87 *penv_87 = &sv_87->sv_env; + register struct envxmm *penv_xmm = &sv_xmm->sv_env; + int i; + + /* FPU control/status */ + penv_87->en_cw = penv_xmm->en_cw; + penv_87->en_sw = penv_xmm->en_sw; + penv_87->en_tw = penv_xmm->en_tw; + penv_87->en_fip = penv_xmm->en_fip; + penv_87->en_fcs = penv_xmm->en_fcs; + penv_87->en_opcode = penv_xmm->en_opcode; + penv_87->en_foo = penv_xmm->en_foo; + penv_87->en_fos = penv_xmm->en_fos; + + /* FPU registers */ + for (i = 0; i < 8; ++i) + sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc; + + sv_87->sv_ex_sw = sv_xmm->sv_ex_sw; +} + +static void +set_fpregs_xmm(sv_87, sv_xmm) + struct save87 *sv_87; + struct savexmm *sv_xmm; +{ + register struct env87 *penv_87 = &sv_87->sv_env; + register struct envxmm *penv_xmm = &sv_xmm->sv_env; + int i; + + /* FPU control/status */ + penv_xmm->en_cw = penv_87->en_cw; + penv_xmm->en_sw = penv_87->en_sw; + penv_xmm->en_tw = penv_87->en_tw; + penv_xmm->en_fip = penv_87->en_fip; + penv_xmm->en_fcs = penv_87->en_fcs; + penv_xmm->en_opcode = penv_87->en_opcode; + penv_xmm->en_foo = penv_87->en_foo; + penv_xmm->en_fos = penv_87->en_fos; + + /* FPU registers */ + for (i = 0; i < 8; ++i) + sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i]; + + sv_xmm->sv_ex_sw = sv_87->sv_ex_sw; +} +#endif /* CPU_ENABLE_SSE */ + int fill_fpregs(p, fpregs) struct proc *p; struct fpreg *fpregs; { - bcopy(&p->p_addr->u_pcb.pcb_savefpu, fpregs, sizeof *fpregs); +#ifdef CPU_ENABLE_SSE + if (cpu_fxsr) { + fill_fpregs_xmm(&p->p_addr->u_pcb.pcb_save.sv_xmm, + (struct save87 *)fpregs); + return (0); + } +#endif /* CPU_ENABLE_SSE */ + bcopy(&p->p_addr->u_pcb.pcb_save.sv_87, fpregs, sizeof *fpregs); return (0); } @@ -2187,7 +2253,14 @@ struct proc *p; struct fpreg *fpregs; { - bcopy(fpregs, &p->p_addr->u_pcb.pcb_savefpu, sizeof *fpregs); +#ifdef CPU_ENABLE_SSE + if (cpu_fxsr) { + set_fpregs_xmm((struct save87 *)fpregs, + &p->p_addr->u_pcb.pcb_save.sv_xmm); + return (0); + } +#endif /* CPU_ENABLE_SSE */ + bcopy(fpregs, &p->p_addr->u_pcb.pcb_save.sv_87, sizeof *fpregs); return (0); } Index: i386/i386/math_emu.h =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/math_emu.h,v retrieving revision 1.7 diff -u -r1.7 math_emu.h --- i386/i386/math_emu.h 1999/08/28 00:43:47 1.7 +++ i386/i386/math_emu.h 2001/08/15 00:50:51 @@ -69,7 +69,7 @@ int32_t st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ }; -#define I387 (*(struct i387_struct *)&(((struct pcb *)curproc->p_addr)->pcb_savefpu)) +#define I387 (*(struct i387_struct *)&(((struct pcb *)curproc->p_addr)->pcb_save.sv_87)) #define SWD (*(struct swd *) &I387.swd) #define ROUNDING ((I387.cwd >> 10) & 3) #define PRECISION ((I387.cwd >> 8) & 3) Index: i386/i386/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/mp_machdep.c,v retrieving revision 1.115.2.8 diff -u -r1.115.2.8 mp_machdep.c --- i386/i386/mp_machdep.c 2001/06/15 09:38:03 1.115.2.8 +++ i386/i386/mp_machdep.c 2001/08/15 00:50:51 @@ -2263,6 +2263,8 @@ * * XXX: Needs to handshake and wait for completion before proceding. */ +extern void enable_sse(void); + void smp_invltlb(void) { @@ -2417,6 +2419,9 @@ /* set up FPU state on the AP */ npxinit(__INITIAL_NPXCW__); + + /* set up SSE registers */ + enable_sse(); /* A quick check from sanity claus */ apic_id = (apic_id_to_logical[(lapic.id & 0x0f000000) >> 24]); Index: i386/i386/support.s =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/support.s,v retrieving revision 1.67.2.4 diff -u -r1.67.2.4 support.s --- i386/i386/support.s 2001/07/12 02:57:11 1.67.2.4 +++ i386/i386/support.s 2001/08/15 00:50:51 @@ -954,7 +954,7 @@ ENTRY(fastmove) pushl %ebp movl %esp,%ebp - subl $PCB_SAVEFPU_SIZE+3*4,%esp + subl $PCB_SAVE87_SIZE+3*4,%esp movl 8(%ebp),%ecx cmpl $63,%ecx @@ -993,7 +993,7 @@ movl _curpcb,%esi addl $PCB_SAVEFPU,%esi cld - movl $PCB_SAVEFPU_SIZE>>2,%ecx + movl $PCB_SAVE87_SIZE>>2,%ecx rep movsl movl -12(%ebp),%ecx @@ -1070,7 +1070,7 @@ addl $PCB_SAVEFPU,%edi movl %esp,%esi cld - movl $PCB_SAVEFPU_SIZE>>2,%ecx + movl $PCB_SAVE87_SIZE>>2,%ecx rep movsl movl -12(%ebp),%ecx @@ -1109,7 +1109,7 @@ addl $PCB_SAVEFPU,%edi movl %esp,%esi cld - movl $PCB_SAVEFPU_SIZE>>2,%ecx + movl $PCB_SAVE87_SIZE>>2,%ecx rep movsl Index: i386/i386/trap.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/trap.c,v retrieving revision 1.147.2.4 diff -u -r1.147.2.4 trap.c --- i386/i386/trap.c 2001/07/29 22:48:37 1.147.2.4 +++ i386/i386/trap.c 2001/08/15 00:50:51 @@ -433,6 +433,11 @@ ucode = T_FPOPFLT; i = SIGILL; break; + + case T_XMMFLT: /* SIMD floating-point exception */ + ucode = 0; /* XXX */ + i = SIGFPE; + break; } } else { kernel_trap: Index: i386/i386/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/vm_machdep.c,v retrieving revision 1.132.2.3 diff -u -r1.132.2.3 vm_machdep.c --- i386/i386/vm_machdep.c 2001/06/15 09:38:00 1.132.2.3 +++ i386/i386/vm_machdep.c 2001/08/15 00:50:51 @@ -142,7 +142,7 @@ #if NNPX > 0 /* Ensure that p1's pcb is up to date. */ if (npxproc == p1) - npxsave(&p1->p_addr->u_pcb.pcb_savefpu); + npxsave(&p1->p_addr->u_pcb.pcb_save); #endif /* Copy p1's pcb. */ Index: i386/include/asnames.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/Attic/asnames.h,v retrieving revision 1.44.2.1 diff -u -r1.44.2.1 asnames.h --- i386/include/asnames.h 2000/05/16 06:58:10 1.44.2.1 +++ i386/include/asnames.h 2001/08/15 00:50:51 @@ -144,6 +144,7 @@ #define _Xstk Xstk #define _Xsyscall Xsyscall #define _Xtss Xtss +#define _Xxmm Xxmm #define __default_ldt _default_ldt #define __ucodesel _ucodesel #define __udatasel _udatasel @@ -191,6 +192,7 @@ #define _cpu_apic_versions cpu_apic_versions #define _cpu_class cpu_class #define _cpu_feature cpu_feature +#define _cpu_fxsr cpu_fxsr #define _cpu_high cpu_high #define _cpu_id cpu_id #define _cpu_num_to_apic_id cpu_num_to_apic_id Index: i386/include/md_var.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/md_var.h,v retrieving revision 1.35.2.1 diff -u -r1.35.2.1 md_var.h --- i386/include/md_var.h 2001/06/15 09:37:57 1.35.2.1 +++ i386/include/md_var.h 2001/08/15 00:50:51 @@ -47,6 +47,7 @@ extern u_int cpu_feature; extern u_int cpu_high; extern u_int cpu_id; +extern u_int cpu_fxsr; extern char cpu_vendor[]; extern u_int cyrix_did; extern char kstack[]; Index: i386/include/npx.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/npx.h,v retrieving revision 1.18 diff -u -r1.18 npx.h --- i386/include/npx.h 2000/03/10 17:56:33 1.18 +++ i386/include/npx.h 2001/08/15 00:50:51 @@ -87,6 +87,42 @@ u_char sv_pad[64]; /* padding; used by emulators */ }; +struct envxmm { + u_int16_t en_cw; /* control word (16bits) */ + u_int16_t en_sw; /* status word (16bits) */ + u_int16_t en_tw; /* tag word (16bits) */ + u_int16_t en_opcode; /* opcode last executed (11 bits ) */ + u_int32_t en_fip; /* floating point instruction pointer */ + u_int16_t en_fcs; /* floating code segment selector */ + u_int16_t en_pad0; /* padding */ + u_int32_t en_foo; /* floating operand offset */ + u_int16_t en_fos; /* floating operand segment selector */ + u_int16_t en_pad1; /* padding */ + u_int32_t en_mxcsr; /* SSE sontorol/status register */ + u_int32_t en_pad2; /* padding */ +}; + +/* Contents of each SSE extended accumulator */ +struct xmmacc { + u_char xmm_bytes[16]; +}; + +struct savexmm { + struct envxmm sv_env; + struct { + struct fpacc87 fp_acc; + u_char fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[8]; + u_long sv_ex_sw; /* status word for last exception */ + u_char sv_pad[220]; +} __attribute__((aligned(16))); + +union savefpu { + struct save87 sv_87; + struct savexmm sv_xmm; +}; + /* * The hardware default control word for i387's and later coprocessors is * 0x37F, giving: @@ -114,7 +150,7 @@ int npxdna __P((void)); void npxexit __P((struct proc *p)); void npxinit __P((int control)); -void npxsave __P((struct save87 *addr)); +void npxsave __P((union savefpu *addr)); #endif #endif /* !_MACHINE_NPX_H_ */ Index: i386/include/pcb.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/pcb.h,v retrieving revision 1.32 diff -u -r1.32 pcb.h --- i386/include/pcb.h 1999/12/29 04:33:03 1.32 +++ i386/include/pcb.h 2001/08/15 00:50:51 @@ -67,7 +67,7 @@ #else struct pcb_ldt *pcb_ldt_dontuse; #endif - struct save87 pcb_savefpu; /* floating point state for 287/387 */ + union savefpu pcb_save; u_char pcb_flags; #define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */ #define PCB_DBREGS 0x02 /* process using debug registers */ Index: i386/include/specialreg.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/specialreg.h,v retrieving revision 1.19 diff -u -r1.19 specialreg.h --- i386/include/specialreg.h 1999/09/10 15:51:44 1.19 +++ i386/include/specialreg.h 2001/08/15 00:50:51 @@ -93,6 +93,8 @@ #define CPUID_PGE 0x2000 #define CPUID_MCA 0x4000 #define CPUID_CMOV 0x8000 +#define CPUID_FXSR 0x01000000 +#define CPUID_XMM 0x02000000 /* * Model-specific registers for the i386 family Index: i386/include/trap.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/trap.h,v retrieving revision 1.10.2.1 diff -u -r1.10.2.1 trap.h --- i386/include/trap.h 2000/03/20 10:27:52 1.10.2.1 +++ i386/include/trap.h 2001/08/15 00:50:51 @@ -65,7 +65,8 @@ #define T_SEGNPFLT 26 /* segment not present fault */ #define T_STKFLT 27 /* stack fault */ #define T_MCHK 28 /* machine check trap */ -#define T_RESERVED 29 /* reserved (unknown) */ +#define T_XMMFLT 29 /* SIMD floating-point exception */ +#define T_RESERVED 30 /* reserved (unknown) */ /* XXX most of the following codes aren't used, but could be. */ Index: i386/isa/npx.c =================================================================== RCS file: /home/ncvs/src/sys/i386/isa/npx.c,v retrieving revision 1.80 diff -u -r1.80 npx.c --- i386/isa/npx.c 2000/01/29 16:17:36 1.80 +++ i386/isa/npx.c 2001/08/15 00:50:52 @@ -35,6 +35,7 @@ * $FreeBSD: src/sys/i386/isa/npx.c,v 1.80 2000/01/29 16:17:36 peter Exp $ */ +#include "opt_cpu.h" #include "opt_debug_npx.h" #include "opt_math_emulate.h" @@ -96,6 +97,8 @@ #define fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr))) #define fp_divide_by_0() __asm("fldz; fld1; fdiv %st,%st(1); fnop") #define frstor(addr) __asm("frstor %0" : : "m" (*(addr))) +#define fxrstor(addr) __asm("fxrstor %0" : : "m" (*(addr))) +#define fxsave(addr) __asm __volatile("fxsave %0" : "=m" (*(addr))) #define start_emulating() __asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \ : : "n" (CR0_TS) : "ax") #define stop_emulating() __asm("clts") @@ -111,11 +114,23 @@ void fnstsw __P((caddr_t addr)); void fp_divide_by_0 __P((void)); void frstor __P((caddr_t addr)); +void fxsave __P((caddr_t addr)); +void fxrstor __P((caddr_t addr)); void start_emulating __P((void)); void stop_emulating __P((void)); #endif /* __GNUC__ */ +#ifdef CPU_ENABLE_SSE +#define GET_FPU_EXSW_PTR(pcb) \ + (cpu_fxsr ? \ + &(pcb)->pcb_save.sv_xmm.sv_ex_sw : \ + &(pcb)->pcb_save.sv_87.sv_ex_sw) +#else /* CPU_ENABLE_SSE */ +#define GET_FPU_EXSW_PTR(pcb) \ + (&(pcb)->pcb_save.sv_87.sv_ex_sw) +#endif /* CPU_ENABLE_SSE */ + typedef u_char bool_t; static int npx_attach __P((device_t dev)); @@ -123,6 +138,8 @@ static void npx_identify __P((driver_t *driver, device_t parent)); static int npx_probe __P((device_t dev)); static int npx_probe1 __P((device_t dev)); +static void fpusave __P((union savefpu *)); +static void fpurstor __P((union savefpu *)); #ifdef I586_CPU static long timezero __P((const char *funcname, void (*func)(void *buf, size_t len))); @@ -474,7 +491,7 @@ npxinit(control) u_short control; { - struct save87 dummy; + static union savefpu dummy; if (!npx_exists) return; @@ -487,7 +504,7 @@ stop_emulating(); fldcw(&control); if (curpcb != NULL) - fnsave(&curpcb->pcb_savefpu); + fpusave(&curpcb->pcb_save); start_emulating(); } @@ -500,13 +517,13 @@ { if (p == npxproc) - npxsave(&curpcb->pcb_savefpu); + npxsave(&curpcb->pcb_save); #ifdef NPX_DEBUG if (npx_exists) { u_int masked_exceptions; - masked_exceptions = curpcb->pcb_savefpu.sv_env.en_cw - & curpcb->pcb_savefpu.sv_env.en_sw & 0x7f; + masked_exceptions = curpcb->pcb_save.sv_87.sv_env.en_cw + & curpcb->pcb_save.sv_87.sv_env.en_sw & 0x7f; /* * Log exceptions that would have trapped with the old * control word (overflow, divide by 0, and invalid operand). @@ -714,6 +731,7 @@ int code; u_short control; struct intrframe *frame; + u_long *exstat; if (npxproc == NULL || !npx_exists) { printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", @@ -726,8 +744,9 @@ panic("npxintr from non-current process"); } + exstat = GET_FPU_EXSW_PTR(curpcb); outb(0xf0, 0); - fnstsw(&curpcb->pcb_savefpu.sv_ex_sw); + fnstsw(exstat); fnstcw(&control); fnclex(); @@ -753,8 +772,7 @@ * this exception. */ code = - fpetable[(curpcb->pcb_savefpu.sv_ex_sw & ~control & 0x3f) | - (curpcb->pcb_savefpu.sv_ex_sw & 0x40)]; + fpetable[(*exstat & ~control & 0x3f) | (*exstat & 0x40)]; trapsignal(curproc, SIGFPE, code); } else { /* @@ -785,6 +803,8 @@ int npxdna() { + u_long *exstat; + if (!npx_exists) return (0); if (npxproc != NULL) { @@ -797,7 +817,8 @@ * Record new context early in case frstor causes an IRQ13. */ npxproc = curproc; - curpcb->pcb_savefpu.sv_ex_sw = 0; + exstat = GET_FPU_EXSW_PTR(curpcb); + *exstat = 0; /* * The following frstor may cause an IRQ13 when the state being * restored has a pending error. The error will appear to have been @@ -810,7 +831,7 @@ * fnsave are broken, so our treatment breaks fnclex if it is the * first FPU instruction after a context switch. */ - frstor(&curpcb->pcb_savefpu); + fpurstor(&curpcb->pcb_save); return (1); } @@ -825,17 +846,18 @@ */ void npxsave(addr) - struct save87 *addr; + union savefpu *addr; { -#ifdef SMP +#if defined(SMP) || defined(CPU_ENABLE_SSE) stop_emulating(); - fnsave(addr); + fpusave(addr); + /* fnop(); */ start_emulating(); npxproc = NULL; -#else /* SMP */ +#else /* SMP or CPU_ENABLE_SSE */ u_char icu1_mask; u_char icu2_mask; @@ -868,6 +890,28 @@ enable_intr(); /* back to usual state */ #endif /* SMP */ +} + +static void +fpusave(addr) + union savefpu *addr; +{ + + if (!cpu_fxsr) + fnsave(addr); + else + fxsave(addr); +} + +static void +fpurstor(addr) + union savefpu *addr; +{ + + if (!cpu_fxsr) + frstor(addr); + else + fxrstor(addr); } #ifdef I586_CPU