Deleted Added
sdiff udiff text old ( 190426 ) new ( 208833 )
full compact
1/*-
2 * Copyright (c) 1990 William Jolitz.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * 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:

--- 17 unchanged lines hidden (view full) ---

26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * from: @(#)npx.c 7.2 (Berkeley) 5/12/91
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/i386/isa/npx.c 190426 2009-03-25 22:08:30Z jhb $");
35
36#include "opt_cpu.h"
37#include "opt_isa.h"
38#include "opt_npx.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/bus.h>

--- 87 unchanged lines hidden (view full) ---

130void start_emulating(void);
131void stop_emulating(void);
132
133#endif /* __GNUCLIKE_ASM && !lint */
134
135#ifdef CPU_ENABLE_SSE
136#define GET_FPU_CW(thread) \
137 (cpu_fxsr ? \
138 (thread)->td_pcb->pcb_save.sv_xmm.sv_env.en_cw : \
139 (thread)->td_pcb->pcb_save.sv_87.sv_env.en_cw)
140#define GET_FPU_SW(thread) \
141 (cpu_fxsr ? \
142 (thread)->td_pcb->pcb_save.sv_xmm.sv_env.en_sw : \
143 (thread)->td_pcb->pcb_save.sv_87.sv_env.en_sw)
144#define SET_FPU_CW(savefpu, value) do { \
145 if (cpu_fxsr) \
146 (savefpu)->sv_xmm.sv_env.en_cw = (value); \
147 else \
148 (savefpu)->sv_87.sv_env.en_cw = (value); \
149} while (0)
150#else /* CPU_ENABLE_SSE */
151#define GET_FPU_CW(thread) \
152 (thread->td_pcb->pcb_save.sv_87.sv_env.en_cw)
153#define GET_FPU_SW(thread) \
154 (thread->td_pcb->pcb_save.sv_87.sv_env.en_sw)
155#define SET_FPU_CW(savefpu, value) \
156 (savefpu)->sv_87.sv_env.en_cw = (value)
157#endif /* CPU_ENABLE_SSE */
158
159typedef u_char bool_t;
160
161#ifdef CPU_ENABLE_SSE
162static void fpu_clean_state(void);

--- 334 unchanged lines hidden (view full) ---

497void
498npxexit(td)
499 struct thread *td;
500{
501 register_t savecrit;
502
503 savecrit = intr_disable();
504 if (curthread == PCPU_GET(fpcurthread))
505 npxsave(&PCPU_GET(curpcb)->pcb_save);
506 intr_restore(savecrit);
507#ifdef NPX_DEBUG
508 if (npx_exists) {
509 u_int masked_exceptions;
510
511 masked_exceptions = GET_FPU_CW(td) & GET_FPU_SW(td) & 0x7f;
512 /*
513 * Log exceptions that would have trapped with the old

--- 290 unchanged lines hidden (view full) ---

804 * This is the first time this thread has used the FPU or
805 * the PCB doesn't contain a clean FPU state. Explicitly
806 * load an initial state.
807 */
808 fpurstor(&npx_initialstate);
809 if (pcb->pcb_initial_npxcw != __INITIAL_NPXCW__)
810 fldcw(&pcb->pcb_initial_npxcw);
811 pcb->pcb_flags |= PCB_NPXINITDONE;
812 } else {
813 /*
814 * The following fpurstor() may cause an IRQ13 when the
815 * state being restored has a pending error. The error will
816 * appear to have been triggered by the current (npx) user
817 * instruction even when that instruction is a no-wait
818 * instruction that should not trigger an error (e.g.,
819 * fnclex). On at least one 486 system all of the no-wait
820 * instructions are broken the same as frstor, so our
821 * treatment does not amplify the breakage. On at least
822 * one 386/Cyrix 387 system, fnclex works correctly while
823 * frstor and fnsave are broken, so our treatment breaks
824 * fnclex if it is the first FPU instruction after a context
825 * switch.
826 */
827 fpurstor(&pcb->pcb_save);
828 }
829 intr_restore(s);
830
831 return (1);
832}
833
834/*
835 * Wrapper for fnsave instruction, partly to handle hardware bugs. When npx

--- 54 unchanged lines hidden (view full) ---

890 start_emulating();
891}
892
893/*
894 * Get the state of the FPU without dropping ownership (if possible).
895 * It returns the FPU ownership status.
896 */
897int
898npxgetregs(td, addr)
899 struct thread *td;
900 union savefpu *addr;
901{
902 register_t s;
903
904 if (!npx_exists)
905 return (_MC_FPOWNED_NONE);
906
907 if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
908 bcopy(&npx_initialstate, addr, sizeof(npx_initialstate));
909 SET_FPU_CW(addr, td->td_pcb->pcb_initial_npxcw);
910 return (_MC_FPOWNED_NONE);
911 }
912 s = intr_disable();
913 if (td == PCPU_GET(fpcurthread)) {
914 fpusave(addr);
915#ifdef CPU_ENABLE_SSE
916 if (!cpu_fxsr)
917#endif
918 /*
919 * fnsave initializes the FPU and destroys whatever
920 * context it contains. Make sure the FPU owner
921 * starts with a clean state next time.
922 */
923 npxdrop();
924 intr_restore(s);
925 return (_MC_FPOWNED_FPU);
926 } else {
927 intr_restore(s);
928 bcopy(&td->td_pcb->pcb_save, addr, sizeof(*addr));
929 return (_MC_FPOWNED_PCB);
930 }
931}
932
933/*
934 * Set the state of the FPU.
935 */
936void
937npxsetregs(td, addr)
938 struct thread *td;
939 union savefpu *addr;
940{
941 register_t s;
942
943 if (!npx_exists)
944 return;
945
946 s = intr_disable();
947 if (td == PCPU_GET(fpcurthread)) {
948#ifdef CPU_ENABLE_SSE
949 if (!cpu_fxsr)
950#endif
951 fnclex(); /* As in npxdrop(). */
952 fpurstor(addr);
953 intr_restore(s);
954 } else {
955 intr_restore(s);
956 bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr));
957 }
958 curthread->td_pcb->pcb_flags |= PCB_NPXINITDONE;
959}
960
961static void
962fpusave(addr)
963 union savefpu *addr;
964{
965
966#ifdef CPU_ENABLE_SSE
967 if (cpu_fxsr)
968 fxsave(addr);

--- 150 unchanged lines hidden (view full) ---

1119
1120static devclass_t npxisa_devclass;
1121
1122DRIVER_MODULE(npxisa, isa, npxisa_driver, npxisa_devclass, 0, 0);
1123#ifndef PC98
1124DRIVER_MODULE(npxisa, acpi, npxisa_driver, npxisa_devclass, 0, 0);
1125#endif
1126#endif /* DEV_ISA */