18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __ASM_ALPHA_FPU_H
38c2ecf20Sopenharmony_ci#define __ASM_ALPHA_FPU_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <asm/special_insns.h>
68c2ecf20Sopenharmony_ci#include <uapi/asm/fpu.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/* The following two functions don't need trapb/excb instructions
98c2ecf20Sopenharmony_ci   around the mf_fpcr/mt_fpcr instructions because (a) the kernel
108c2ecf20Sopenharmony_ci   never generates arithmetic faults and (b) call_pal instructions
118c2ecf20Sopenharmony_ci   are implied trap barriers.  */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic inline unsigned long
148c2ecf20Sopenharmony_cirdfpcr(void)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	unsigned long tmp, ret;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
198c2ecf20Sopenharmony_ci	__asm__ __volatile__ (
208c2ecf20Sopenharmony_ci		"ftoit $f0,%0\n\t"
218c2ecf20Sopenharmony_ci		"mf_fpcr $f0\n\t"
228c2ecf20Sopenharmony_ci		"ftoit $f0,%1\n\t"
238c2ecf20Sopenharmony_ci		"itoft %0,$f0"
248c2ecf20Sopenharmony_ci		: "=r"(tmp), "=r"(ret));
258c2ecf20Sopenharmony_ci#else
268c2ecf20Sopenharmony_ci	__asm__ __volatile__ (
278c2ecf20Sopenharmony_ci		"stt $f0,%0\n\t"
288c2ecf20Sopenharmony_ci		"mf_fpcr $f0\n\t"
298c2ecf20Sopenharmony_ci		"stt $f0,%1\n\t"
308c2ecf20Sopenharmony_ci		"ldt $f0,%0"
318c2ecf20Sopenharmony_ci		: "=m"(tmp), "=m"(ret));
328c2ecf20Sopenharmony_ci#endif
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	return ret;
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic inline void
388c2ecf20Sopenharmony_ciwrfpcr(unsigned long val)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	unsigned long tmp;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
438c2ecf20Sopenharmony_ci	__asm__ __volatile__ (
448c2ecf20Sopenharmony_ci		"ftoit $f0,%0\n\t"
458c2ecf20Sopenharmony_ci		"itoft %1,$f0\n\t"
468c2ecf20Sopenharmony_ci		"mt_fpcr $f0\n\t"
478c2ecf20Sopenharmony_ci		"itoft %0,$f0"
488c2ecf20Sopenharmony_ci		: "=&r"(tmp) : "r"(val));
498c2ecf20Sopenharmony_ci#else
508c2ecf20Sopenharmony_ci	__asm__ __volatile__ (
518c2ecf20Sopenharmony_ci		"stt $f0,%0\n\t"
528c2ecf20Sopenharmony_ci		"ldt $f0,%1\n\t"
538c2ecf20Sopenharmony_ci		"mt_fpcr $f0\n\t"
548c2ecf20Sopenharmony_ci		"ldt $f0,%0"
558c2ecf20Sopenharmony_ci		: "=m"(tmp) : "m"(val));
568c2ecf20Sopenharmony_ci#endif
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic inline unsigned long
608c2ecf20Sopenharmony_ciswcr_update_status(unsigned long swcr, unsigned long fpcr)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	/* EV6 implements most of the bits in hardware.  Collect
638c2ecf20Sopenharmony_ci	   the acrued exception bits from the real fpcr.  */
648c2ecf20Sopenharmony_ci	if (implver() == IMPLVER_EV6) {
658c2ecf20Sopenharmony_ci		swcr &= ~IEEE_STATUS_MASK;
668c2ecf20Sopenharmony_ci		swcr |= (fpcr >> 35) & IEEE_STATUS_MASK;
678c2ecf20Sopenharmony_ci	}
688c2ecf20Sopenharmony_ci	return swcr;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciextern unsigned long alpha_read_fp_reg (unsigned long reg);
728c2ecf20Sopenharmony_ciextern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
738c2ecf20Sopenharmony_ciextern unsigned long alpha_read_fp_reg_s (unsigned long reg);
748c2ecf20Sopenharmony_ciextern void alpha_write_fp_reg_s (unsigned long reg, unsigned long val);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci#endif /* __ASM_ALPHA_FPU_H */
77