static inline int rt_save_fpu_state()

in kernel/signal.c [482:548]


static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
{
	unsigned char fpstate[FPCONTEXT_SIZE];
	int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0);
	int err = 0;

	if (FPU_IS_EMU) {
		/* save fpu control register */
		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
				current->thread.fpcntl, 12);
		/* save all other fpu register */
		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
				current->thread.fp, 96);
		return err;
	}

	if (CPU_IS_COLDFIRE) {
		__asm__ volatile ("fsave %0" : : "m" (*fpstate) : "memory");
	} else {
		__asm__ volatile (".chip 68k/68881\n\t"
				  "fsave %0\n\t"
				  ".chip 68k"
				  : : "m" (*fpstate) : "memory");
	}

	err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
		fpregset_t fpregs;
		if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
			context_size = fpstate[1];
		fpu_version = fpstate[0];
		if (CPU_IS_020_OR_030 && !regs->stkadj &&
		    regs->vector >= (VEC_FPBRUC * 4) &&
		    regs->vector <= (VEC_FPNAN * 4)) {
			/* Clear pending exception in 68882 idle frame */
			if (*(unsigned short *) fpstate == 0x1f38)
				fpstate[0x38] |= 1 << 3;
		}
		if (CPU_IS_COLDFIRE) {
			__asm__ volatile ("fmovemd %%fp0-%%fp7,%0\n\t"
					  "fmovel %%fpcr,%1\n\t"
					  "fmovel %%fpsr,%2\n\t"
					  "fmovel %%fpiar,%3"
					  : "=m" (fpregs.f_fpregs[0]),
					    "=m" (fpregs.f_fpcntl[0]),
					    "=m" (fpregs.f_fpcntl[1]),
					    "=m" (fpregs.f_fpcntl[2])
					  : /* no inputs */
					  : "memory");
		} else {
			__asm__ volatile (".chip 68k/68881\n\t"
					  "fmovemx %%fp0-%%fp7,%0\n\t"
					  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
					  ".chip 68k"
					  : "=m" (*fpregs.f_fpregs),
					    "=m" (*fpregs.f_fpcntl)
					  : /* no inputs */
					  : "memory");
		}
		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
				    sizeof(fpregs));
	}
	if (context_size)
		err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
				    context_size);
	return err;
}