/* * arch/s390/kernel/s390fpu.c * * S390 version * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) * * s390fpu.h functions for saving & restoring the fpu state. * * I couldn't inline these as linux/sched.h included half the world * & was required to at the task structure. * & the functions were too complex to make macros from. * ( & as usual I didn't feel like debugging inline code ). */ #include #include int save_fp_regs1(s390_fp_regs *fpregs) { int has_ieee=MACHINE_HAS_IEEE; /* I don't think we can use STE here as this would load fp registers 0 & 2 into memory locations 0 & 1 etc. */ asm volatile ("STD 0,8(%0)\n\t" "STD 2,24(%0)\n\t" "STD 4,40(%0)\n\t" "STD 6,56(%0)" : : "a" (fpregs) : "memory" ); if(has_ieee) { asm volatile ("STFPC 0(%0)\n\t" "STD 1,16(%0)\n\t" "STD 3,32(%0)\n\t" "STD 5,48(%0)\n\t" "STD 7,64(%0)\n\t" "STD 8,72(%0)\n\t" "STD 9,80(%0)\n\t" "STD 10,88(%0)\n\t" "STD 11,96(%0)\n\t" "STD 12,104(%0)\n\t" "STD 13,112(%0)\n\t" "STD 14,120(%0)\n\t" "STD 15,128(%0)\n\t" : : "a" (fpregs) : "memory" ); } return(has_ieee); } void save_fp_regs(s390_fp_regs *fpregs) { #if CONFIG_IEEEFPU_EMULATION s390_fp_regs *currentfprs; #endif #if CONFIG_IEEEFPU_EMULATION if(!save_fp_regs1(fpregs)) { currentfprs=¤t->thread.fp_regs; fpregs->fpc=currentfprs->fpc; fpregs->fprs[1].d=currentfprs->fprs[1].d; fpregs->fprs[3].d=currentfprs->fprs[3].d; fpregs->fprs[5].d=currentfprs->fprs[5].d; fpregs->fprs[7].d=currentfprs->fprs[7].d; memcpy(&fpregs->fprs[8].d,¤tfprs->fprs[8].d,sizeof(freg_t)*8); } #else save_fp_regs1(fpregs); #endif } int restore_fp_regs1(s390_fp_regs *fpregs) { int has_ieee=MACHINE_HAS_IEEE; asm volatile ("LD 0,8(%0)\n\t" "LD 2,24(%0)\n\t" "LD 4,40(%0)\n\t" "LD 6,56(%0)" : : "a" (fpregs) : "memory" ); if(has_ieee) { asm volatile ("LFPC 0(%0)\n\t" "LD 1,16(%0)\n\t" "LD 3,32(%0)\n\t" "LD 5,48(%0)\n\t" "LD 7,64(%0)\n\t" "LD 8,72(%0)\n\t" "LD 9,80(%0)\n\t" "LD 10,88(%0)\n\t" "LD 11,96(%0)\n\t" "LD 12,104(%0)\n\t" "LD 13,112(%0)\n\t" "LD 14,120(%0)\n\t" "LD 15,128(%0)\n\t" : : "a" (fpregs) : "memory" ); } return(has_ieee); } void restore_fp_regs(s390_fp_regs *fpregs) { #if CONFIG_IEEEFPU_EMULATION s390_fp_regs *currentfprs; #endif #if CONFIG_IEEEFPU_EMULATION if(!restore_fp_regs1(fpregs)) { currentfprs=¤t->thread.fp_regs; currentfprs->fpc=fpregs->fpc; currentfprs->fprs[1].d=fpregs->fprs[1].d; currentfprs->fprs[3].d=fpregs->fprs[3].d; currentfprs->fprs[5].d=fpregs->fprs[5].d; currentfprs->fprs[7].d=fpregs->fprs[7].d; memcpy(¤tfprs->fprs[8].d,&fpregs->fprs[8].d,sizeof(freg_t)*8); } #else restore_fp_regs1(fpregs); #endif }