static inline int rt_restore_fpu_state()

in kernel/signal.c [331:424]


static inline int rt_restore_fpu_state(struct ucontext __user *uc)
{
	unsigned char fpstate[FPCONTEXT_SIZE];
	int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0);
	fpregset_t fpregs;
	int err = 1;

	if (FPU_IS_EMU) {
		/* restore fpu control register */
		if (__copy_from_user(current->thread.fpcntl,
				uc->uc_mcontext.fpregs.f_fpcntl, 12))
			goto out;
		/* restore all other fpu register */
		if (__copy_from_user(current->thread.fp,
				uc->uc_mcontext.fpregs.f_fpregs, 96))
			goto out;
		return 0;
	}

	if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
		goto out;
	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
		if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
			context_size = fpstate[1];
		/* Verify the frame format.  */
		if (!(CPU_IS_060 || CPU_IS_COLDFIRE) &&
		     (fpstate[0] != fpu_version))
			goto out;
		if (CPU_IS_020_OR_030) {
			if (m68k_fputype & FPU_68881 &&
			    !(context_size == 0x18 || context_size == 0xb4))
				goto out;
			if (m68k_fputype & FPU_68882 &&
			    !(context_size == 0x38 || context_size == 0xd4))
				goto out;
		} else if (CPU_IS_040) {
			if (!(context_size == 0x00 ||
			      context_size == 0x28 ||
			      context_size == 0x60))
				goto out;
		} else if (CPU_IS_060) {
			if (!(fpstate[3] == 0x00 ||
			      fpstate[3] == 0x60 ||
			      fpstate[3] == 0xe0))
				goto out;
		} else if (CPU_IS_COLDFIRE) {
			if (!(fpstate[3] == 0x00 ||
			      fpstate[3] == 0x05 ||
			      fpstate[3] == 0xe5))
				goto out;
		} else
			goto out;
		if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
				     sizeof(fpregs)))
			goto out;

		if (CPU_IS_COLDFIRE) {
			__asm__ volatile ("fmovemd %0,%%fp0-%%fp7\n\t"
					  "fmovel %1,%%fpcr\n\t"
					  "fmovel %2,%%fpsr\n\t"
					  "fmovel %3,%%fpiar"
					  : /* no outputs */
					  : "m" (fpregs.f_fpregs[0]),
					    "m" (fpregs.f_fpcntl[0]),
					    "m" (fpregs.f_fpcntl[1]),
					    "m" (fpregs.f_fpcntl[2]));
		} else {
			__asm__ volatile (".chip 68k/68881\n\t"
					  "fmovemx %0,%%fp0-%%fp7\n\t"
					  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
					  ".chip 68k"
					  : /* no outputs */
					  : "m" (*fpregs.f_fpregs),
					    "m" (*fpregs.f_fpcntl));
		}
	}
	if (context_size &&
	    __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
			     context_size))
		goto out;

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

out:
	return err;
}