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$"); 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 tf->srr1 |= PSL_FP; 70 if (!(pcb->pcb_flags & PCB_FPU)) { 71 memset(&pcb->pcb_fpu, 0, sizeof pcb->pcb_fpu); 72 pcb->pcb_flags |= PCB_FPU; 73 } 74 75 /* 76 * Temporarily enable floating-point so the registers 77 * can be restored. 78 */ 79 msr = mfmsr(); 80 mtmsr(msr | PSL_FP); 81 isync(); 82 83 /* 84 * Load the floating point registers and FPSCR from the PCB. 85 * (A value of 0xff for mtfsf specifies that all 8 4-bit fields 86 * of the saved FPSCR are to be loaded from the FPU reg). 87 */ 88 __asm __volatile ("lfd 0,0(%0); mtfsf 0xff,0" 89 :: "b"(&pcb->pcb_fpu.fpscr)); 90 91#define LFP(n) __asm ("lfd " #n ", 0(%0)" \ 92 :: "b"(&pcb->pcb_fpu.fpr[n])); 93 LFP(0); LFP(1); LFP(2); LFP(3); 94 LFP(4); LFP(5); LFP(6); LFP(7); 95 LFP(8); LFP(9); LFP(10); LFP(11); 96 LFP(12); LFP(13); LFP(14); LFP(15); 97 LFP(16); LFP(17); LFP(18); LFP(19); 98 LFP(20); LFP(21); LFP(22); LFP(23); 99 LFP(24); LFP(25); LFP(26); LFP(27); 100 LFP(28); LFP(29); LFP(30); LFP(31); 101#undef LFP 102 103 isync(); 104 mtmsr(msr); 105} 106 107void 108save_fpu(struct thread *td) 109{ 110 int msr; 111 struct pcb *pcb; 112 113 pcb = td->td_pcb; 114 115 /* 116 * Temporarily re-enable floating-point during the save 117 */ 118 msr = mfmsr(); 119 mtmsr(msr | PSL_FP); 120 isync(); 121 122 /* 123 * Save the floating-point registers and FPSCR to the PCB 124 */ 125#define SFP(n) __asm ("stfd " #n ", 0(%0)" \ 126 :: "b"(&pcb->pcb_fpu.fpr[n])); 127 SFP(0); SFP(1); SFP(2); SFP(3); 128 SFP(4); SFP(5); SFP(6); SFP(7); 129 SFP(8); SFP(9); SFP(10); SFP(11); 130 SFP(12); SFP(13); SFP(14); SFP(15); 131 SFP(16); SFP(17); SFP(18); SFP(19); 132 SFP(20); SFP(21); SFP(22); SFP(23); 133 SFP(24); SFP(25); SFP(26); SFP(27); 134 SFP(28); SFP(29); SFP(30); SFP(31); 135#undef SFP 136 __asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); 137 138 /* 139 * Disable floating-point again 140 */ 141 isync(); 142 mtmsr(msr); 143 144 /* 145 * Clear the current fp thread and pcb's CPU id 146 * XXX should this be left clear to allow lazy save/restore ? 147 */ 148 pcb->pcb_fpcpu = INT_MAX; 149 PCPU_SET(fputhread, NULL); 150} 151 152