1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __ASM_ALPHA_FPU_H 3 #define __ASM_ALPHA_FPU_H 4 5 #include <asm/special_insns.h> 6 #include <uapi/asm/fpu.h> 7 8 /* The following two functions don't need trapb/excb instructions 9 around the mf_fpcr/mt_fpcr instructions because (a) the kernel 10 never generates arithmetic faults and (b) call_pal instructions 11 are implied trap barriers. */ 12 13 static inline unsigned long 14 rdfpcr(void) 15 { 16 unsigned long tmp, ret; 17 18 preempt_disable(); 19 if (current_thread_info()->status & TS_SAVED_FP) { 20 ret = current_thread_info()->fp[31]; 21 } else { 22 #if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67) 23 __asm__ __volatile__ ( 24 "ftoit $f0,%0\n\t" 25 "mf_fpcr $f0\n\t" 26 "ftoit $f0,%1\n\t" 27 "itoft %0,$f0" 28 : "=r"(tmp), "=r"(ret)); 29 #else 30 __asm__ __volatile__ ( 31 "stt $f0,%0\n\t" 32 "mf_fpcr $f0\n\t" 33 "stt $f0,%1\n\t" 34 "ldt $f0,%0" 35 : "=m"(tmp), "=m"(ret)); 36 #endif 37 } 38 preempt_enable(); 39 40 return ret; 41 } 42 43 static inline void 44 wrfpcr(unsigned long val) 45 { 46 unsigned long tmp; 47 48 preempt_disable(); 49 if (current_thread_info()->status & TS_SAVED_FP) { 50 current_thread_info()->status |= TS_RESTORE_FP; 51 current_thread_info()->fp[31] = val; 52 } else { 53 #if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67) 54 __asm__ __volatile__ ( 55 "ftoit $f0,%0\n\t" 56 "itoft %1,$f0\n\t" 57 "mt_fpcr $f0\n\t" 58 "itoft %0,$f0" 59 : "=&r"(tmp) : "r"(val)); 60 #else 61 __asm__ __volatile__ ( 62 "stt $f0,%0\n\t" 63 "ldt $f0,%1\n\t" 64 "mt_fpcr $f0\n\t" 65 "ldt $f0,%0" 66 : "=m"(tmp) : "m"(val)); 67 #endif 68 } 69 preempt_enable(); 70 } 71 72 static inline unsigned long 73 swcr_update_status(unsigned long swcr, unsigned long fpcr) 74 { 75 /* EV6 implements most of the bits in hardware. Collect 76 the acrued exception bits from the real fpcr. */ 77 if (implver() == IMPLVER_EV6) { 78 swcr &= ~IEEE_STATUS_MASK; 79 swcr |= (fpcr >> 35) & IEEE_STATUS_MASK; 80 } 81 return swcr; 82 } 83 84 extern unsigned long alpha_read_fp_reg (unsigned long reg); 85 extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); 86 extern unsigned long alpha_read_fp_reg_s (unsigned long reg); 87 extern void alpha_write_fp_reg_s (unsigned long reg, unsigned long val); 88 89 #endif /* __ASM_ALPHA_FPU_H */ 90