Changeset View
Changeset View
Standalone View
Standalone View
head/sys/powerpc/powerpc/fpu.c
| Show All 39 Lines | |||||
| #include <sys/proc.h> | #include <sys/proc.h> | ||||
| #include <sys/systm.h> | #include <sys/systm.h> | ||||
| #include <sys/limits.h> | #include <sys/limits.h> | ||||
| #include <machine/fpu.h> | #include <machine/fpu.h> | ||||
| #include <machine/pcb.h> | #include <machine/pcb.h> | ||||
| #include <machine/psl.h> | #include <machine/psl.h> | ||||
| static void | |||||
| save_fpu_int(struct thread *td) | |||||
| { | |||||
| int msr; | |||||
| struct pcb *pcb; | |||||
| pcb = td->td_pcb; | |||||
| /* | |||||
| * Temporarily re-enable floating-point during the save | |||||
| */ | |||||
| msr = mfmsr(); | |||||
| if (pcb->pcb_flags & PCB_VSX) | |||||
| mtmsr(msr | PSL_FP | PSL_VSX); | |||||
| else | |||||
| mtmsr(msr | PSL_FP); | |||||
| /* | |||||
| * Save the floating-point registers and FPSCR to the PCB | |||||
| */ | |||||
| if (pcb->pcb_flags & PCB_VSX) { | |||||
| #define SFP(n) __asm ("stxvw4x " #n ", 0,%0" \ | |||||
| :: "b"(&pcb->pcb_fpu.fpr[n])); | |||||
| SFP(0); SFP(1); SFP(2); SFP(3); | |||||
| SFP(4); SFP(5); SFP(6); SFP(7); | |||||
| SFP(8); SFP(9); SFP(10); SFP(11); | |||||
| SFP(12); SFP(13); SFP(14); SFP(15); | |||||
| SFP(16); SFP(17); SFP(18); SFP(19); | |||||
| SFP(20); SFP(21); SFP(22); SFP(23); | |||||
| SFP(24); SFP(25); SFP(26); SFP(27); | |||||
| SFP(28); SFP(29); SFP(30); SFP(31); | |||||
| #undef SFP | |||||
| } else { | |||||
| #define SFP(n) __asm ("stfd " #n ", 0(%0)" \ | |||||
| :: "b"(&pcb->pcb_fpu.fpr[n])); | |||||
| SFP(0); SFP(1); SFP(2); SFP(3); | |||||
| SFP(4); SFP(5); SFP(6); SFP(7); | |||||
| SFP(8); SFP(9); SFP(10); SFP(11); | |||||
| SFP(12); SFP(13); SFP(14); SFP(15); | |||||
| SFP(16); SFP(17); SFP(18); SFP(19); | |||||
| SFP(20); SFP(21); SFP(22); SFP(23); | |||||
| SFP(24); SFP(25); SFP(26); SFP(27); | |||||
| SFP(28); SFP(29); SFP(30); SFP(31); | |||||
| #undef SFP | |||||
| } | |||||
| __asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); | |||||
| /* | |||||
| * Disable floating-point again | |||||
| */ | |||||
| isync(); | |||||
| mtmsr(msr); | |||||
| } | |||||
| void | void | ||||
| enable_fpu(struct thread *td) | enable_fpu(struct thread *td) | ||||
| { | { | ||||
| int msr; | int msr; | ||||
| struct pcb *pcb; | struct pcb *pcb; | ||||
| struct trapframe *tf; | struct trapframe *tf; | ||||
| pcb = td->td_pcb; | pcb = td->td_pcb; | ||||
| ▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | enable_fpu(struct thread *td) | ||||
| isync(); | isync(); | ||||
| mtmsr(msr); | mtmsr(msr); | ||||
| } | } | ||||
| void | void | ||||
| save_fpu(struct thread *td) | save_fpu(struct thread *td) | ||||
| { | { | ||||
| int msr; | |||||
| struct pcb *pcb; | struct pcb *pcb; | ||||
| pcb = td->td_pcb; | pcb = td->td_pcb; | ||||
| /* | save_fpu_int(td); | ||||
| * Temporarily re-enable floating-point during the save | |||||
| */ | |||||
| msr = mfmsr(); | |||||
| if (pcb->pcb_flags & PCB_VSX) | |||||
| mtmsr(msr | PSL_FP | PSL_VSX); | |||||
| else | |||||
| mtmsr(msr | PSL_FP); | |||||
| /* | /* | ||||
| * Save the floating-point registers and FPSCR to the PCB | * Clear the current fp thread and pcb's CPU id | ||||
| * XXX should this be left clear to allow lazy save/restore ? | |||||
| */ | */ | ||||
| if (pcb->pcb_flags & PCB_VSX) { | pcb->pcb_fpcpu = INT_MAX; | ||||
| #define SFP(n) __asm ("stxvw4x " #n ", 0,%0" \ | PCPU_SET(fputhread, NULL); | ||||
| :: "b"(&pcb->pcb_fpu.fpr[n])); | |||||
| SFP(0); SFP(1); SFP(2); SFP(3); | |||||
| SFP(4); SFP(5); SFP(6); SFP(7); | |||||
| SFP(8); SFP(9); SFP(10); SFP(11); | |||||
| SFP(12); SFP(13); SFP(14); SFP(15); | |||||
| SFP(16); SFP(17); SFP(18); SFP(19); | |||||
| SFP(20); SFP(21); SFP(22); SFP(23); | |||||
| SFP(24); SFP(25); SFP(26); SFP(27); | |||||
| SFP(28); SFP(29); SFP(30); SFP(31); | |||||
| #undef SFP | |||||
| } else { | |||||
| #define SFP(n) __asm ("stfd " #n ", 0(%0)" \ | |||||
| :: "b"(&pcb->pcb_fpu.fpr[n])); | |||||
| SFP(0); SFP(1); SFP(2); SFP(3); | |||||
| SFP(4); SFP(5); SFP(6); SFP(7); | |||||
| SFP(8); SFP(9); SFP(10); SFP(11); | |||||
| SFP(12); SFP(13); SFP(14); SFP(15); | |||||
| SFP(16); SFP(17); SFP(18); SFP(19); | |||||
| SFP(20); SFP(21); SFP(22); SFP(23); | |||||
| SFP(24); SFP(25); SFP(26); SFP(27); | |||||
| SFP(28); SFP(29); SFP(30); SFP(31); | |||||
| #undef SFP | |||||
| } | } | ||||
| __asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); | |||||
| /* | /* | ||||
| * Disable floating-point again | * Save fpu state without dropping ownership. This will only save state if | ||||
| * the current fpu thread is `td'. | |||||
| */ | */ | ||||
| isync(); | void | ||||
| mtmsr(msr); | save_fpu_nodrop(struct thread *td) | ||||
| { | |||||
| struct thread *ftd; | |||||
| /* | ftd = PCPU_GET(fputhread); | ||||
| * Clear the current fp thread and pcb's CPU id | if (td != ftd) { | ||||
| * XXX should this be left clear to allow lazy save/restore ? | return; | ||||
| */ | |||||
| pcb->pcb_fpcpu = INT_MAX; | |||||
| PCPU_SET(fputhread, NULL); | |||||
| } | } | ||||
| save_fpu_int(td); | |||||
| } | |||||