fpu.c revision 266004
1/*- 2 * Copyright (C) 1996 Wolfgang Solfrank. 3 * Copyright (C) 1996 TooLs GmbH. 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: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by TooLs GmbH. 17 * 4. The name of TooLs GmbH may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $NetBSD: fpu.c,v 1.5 2001/07/22 11:29:46 wiz Exp $ 32 */ 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/fpu.c 266004 2014-05-14 04:42:38Z ian $"); 36 37#include <sys/param.h> 38#include <sys/proc.h> 39#include <sys/systm.h> 40#include <sys/limits.h> 41 42#include <machine/fpu.h> 43#include <machine/pcb.h> 44#include <machine/psl.h> 45 46void 47enable_fpu(struct thread *td) 48{ 49 int msr; 50 struct pcb *pcb; 51 struct trapframe *tf; 52 53 pcb = td->td_pcb; 54 tf = trapframe(td); 55 56 /* 57 * Save the thread's FPU CPU number, and set the CPU's current 58 * FPU thread 59 */ 60 td->td_pcb->pcb_fpcpu = PCPU_GET(cpuid); 61 PCPU_SET(fputhread, td); 62 63 /* 64 * Enable the FPU for when the thread returns from the exception. 65 * If this is the first time the FPU has been used by the thread, 66 * initialise the FPU registers and FPSCR to 0, and set the flag 67 * to indicate that the FPU is in use. 68 */ 69 pcb->pcb_flags |= PCB_FPU; 70 tf->srr1 |= PSL_FP; 71 if (!(pcb->pcb_flags & PCB_FPREGS)) { 72 memset(&pcb->pcb_fpu, 0, sizeof pcb->pcb_fpu); 73 pcb->pcb_flags |= PCB_FPREGS; 74 } 75 76 /* 77 * Temporarily enable floating-point so the registers 78 * can be restored. 79 */ 80 msr = mfmsr(); 81 mtmsr(msr | PSL_FP); 82 isync(); 83 84 /* 85 * Load the floating point registers and FPSCR from the PCB. 86 * (A value of 0xff for mtfsf specifies that all 8 4-bit fields 87 * of the saved FPSCR are to be loaded from the FPU reg). 88 */ 89 __asm __volatile ("lfd 0,0(%0); mtfsf 0xff,0" 90 :: "b"(&pcb->pcb_fpu.fpscr)); 91 92#define LFP(n) __asm ("lfd " #n ", 0(%0)" \ 93 :: "b"(&pcb->pcb_fpu.fpr[n])); 94 LFP(0); LFP(1); LFP(2); LFP(3); 95 LFP(4); LFP(5); LFP(6); LFP(7); 96 LFP(8); LFP(9); LFP(10); LFP(11); 97 LFP(12); LFP(13); LFP(14); LFP(15); 98 LFP(16); LFP(17); LFP(18); LFP(19); 99 LFP(20); LFP(21); LFP(22); LFP(23); 100 LFP(24); LFP(25); LFP(26); LFP(27); 101 LFP(28); LFP(29); LFP(30); LFP(31); 102#undef LFP 103 104 isync(); 105 mtmsr(msr); 106} 107 108void 109save_fpu(struct thread *td) 110{ 111 int msr; 112 struct pcb *pcb; 113 114 pcb = td->td_pcb; 115 116 /* 117 * Temporarily re-enable floating-point during the save 118 */ 119 msr = mfmsr(); 120 mtmsr(msr | PSL_FP); 121 isync(); 122 123 /* 124 * Save the floating-point registers and FPSCR to the PCB 125 */ 126#define SFP(n) __asm ("stfd " #n ", 0(%0)" \ 127 :: "b"(&pcb->pcb_fpu.fpr[n])); 128 SFP(0); SFP(1); SFP(2); SFP(3); 129 SFP(4); SFP(5); SFP(6); SFP(7); 130 SFP(8); SFP(9); SFP(10); SFP(11); 131 SFP(12); SFP(13); SFP(14); SFP(15); 132 SFP(16); SFP(17); SFP(18); SFP(19); 133 SFP(20); SFP(21); SFP(22); SFP(23); 134 SFP(24); SFP(25); SFP(26); SFP(27); 135 SFP(28); SFP(29); SFP(30); SFP(31); 136#undef SFP 137 __asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); 138 139 /* 140 * Disable floating-point again 141 */ 142 isync(); 143 mtmsr(msr); 144 145 /* 146 * Clear the current fp thread and pcb's CPU id 147 * XXX should this be left clear to allow lazy save/restore ? 148 */ 149 pcb->pcb_fpcpu = INT_MAX; 150 PCPU_SET(fputhread, NULL); 151} 152 153