linux/arch/nds32/include/asm/fpu.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/* Copyright (C) 2005-2018 Andes Technology Corporation */
   3
   4#ifndef __ASM_NDS32_FPU_H
   5#define __ASM_NDS32_FPU_H
   6
   7#if IS_ENABLED(CONFIG_FPU)
   8#ifndef __ASSEMBLY__
   9#include <linux/sched/task_stack.h>
  10#include <linux/preempt.h>
  11#include <asm/ptrace.h>
  12
  13extern bool has_fpu;
  14
  15extern void save_fpu(struct task_struct *__tsk);
  16extern void load_fpu(const struct fpu_struct *fpregs);
  17extern bool do_fpu_exception(unsigned int subtype, struct pt_regs *regs);
  18extern int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu);
  19
  20#define test_tsk_fpu(regs)      (regs->fucop_ctl & FUCOP_CTL_mskCP0EN)
  21
  22/*
  23 * Initially load the FPU with signalling NANS.  This bit pattern
  24 * has the property that no matter whether considered as single or as
  25 * double precision, it still represents a signalling NAN.
  26 */
  27
  28#define sNAN64    0xFFFFFFFFFFFFFFFFULL
  29#define sNAN32    0xFFFFFFFFUL
  30
  31#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
  32/*
  33 * Denormalized number is unsupported by nds32 FPU. Hence the operation
  34 * is treated as underflow cases when the final result is a denormalized
  35 * number. To enhance precision, underflow exception trap should be
  36 * enabled by default and kerenl will re-execute it by fpu emulator
  37 * when getting underflow exception.
  38 */
  39#define FPCSR_INIT  (FPCSR_mskUDFE | FPCSR_mskIEXE)
  40#else
  41#define FPCSR_INIT  0x0UL
  42#endif
  43
  44extern const struct fpu_struct init_fpuregs;
  45
  46static inline void disable_ptreg_fpu(struct pt_regs *regs)
  47{
  48        regs->fucop_ctl &= ~FUCOP_CTL_mskCP0EN;
  49}
  50
  51static inline void enable_ptreg_fpu(struct pt_regs *regs)
  52{
  53        regs->fucop_ctl |= FUCOP_CTL_mskCP0EN;
  54}
  55
  56static inline void enable_fpu(void)
  57{
  58        unsigned long fucop_ctl;
  59
  60        fucop_ctl = __nds32__mfsr(NDS32_SR_FUCOP_CTL) | FUCOP_CTL_mskCP0EN;
  61        __nds32__mtsr(fucop_ctl, NDS32_SR_FUCOP_CTL);
  62        __nds32__isb();
  63}
  64
  65static inline void disable_fpu(void)
  66{
  67        unsigned long fucop_ctl;
  68
  69        fucop_ctl = __nds32__mfsr(NDS32_SR_FUCOP_CTL) & ~FUCOP_CTL_mskCP0EN;
  70        __nds32__mtsr(fucop_ctl, NDS32_SR_FUCOP_CTL);
  71        __nds32__isb();
  72}
  73
  74static inline void lose_fpu(void)
  75{
  76        preempt_disable();
  77#if IS_ENABLED(CONFIG_LAZY_FPU)
  78        if (last_task_used_math == current) {
  79                last_task_used_math = NULL;
  80#else
  81        if (test_tsk_fpu(task_pt_regs(current))) {
  82#endif
  83                save_fpu(current);
  84        }
  85        disable_ptreg_fpu(task_pt_regs(current));
  86        preempt_enable();
  87}
  88
  89static inline void own_fpu(void)
  90{
  91        preempt_disable();
  92#if IS_ENABLED(CONFIG_LAZY_FPU)
  93        if (last_task_used_math != current) {
  94                if (last_task_used_math != NULL)
  95                        save_fpu(last_task_used_math);
  96                load_fpu(&current->thread.fpu);
  97                last_task_used_math = current;
  98        }
  99#else
 100        if (!test_tsk_fpu(task_pt_regs(current))) {
 101                load_fpu(&current->thread.fpu);
 102        }
 103#endif
 104        enable_ptreg_fpu(task_pt_regs(current));
 105        preempt_enable();
 106}
 107
 108#if !IS_ENABLED(CONFIG_LAZY_FPU)
 109static inline void unlazy_fpu(struct task_struct *tsk)
 110{
 111        preempt_disable();
 112        if (test_tsk_fpu(task_pt_regs(tsk)))
 113                save_fpu(tsk);
 114        preempt_enable();
 115}
 116#endif /* !CONFIG_LAZY_FPU */
 117static inline void clear_fpu(struct pt_regs *regs)
 118{
 119        preempt_disable();
 120        if (test_tsk_fpu(regs))
 121                disable_ptreg_fpu(regs);
 122        preempt_enable();
 123}
 124#endif /* CONFIG_FPU */
 125#endif /* __ASSEMBLY__ */
 126#endif /* __ASM_NDS32_FPU_H */
 127