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 13static inline unsigned long 14rdfpcr(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 43static inline void 44wrfpcr(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 72static inline unsigned long 73swcr_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 84extern unsigned long alpha_read_fp_reg (unsigned long reg); 85extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); 86extern unsigned long alpha_read_fp_reg_s (unsigned long reg); 87extern void alpha_write_fp_reg_s (unsigned long reg, unsigned long val); 88 89#endif /* __ASM_ALPHA_FPU_H */ 90