1/* 2 * arch/s390/kernel/s390fpu.c 3 * 4 * S390 version 5 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 7 * 8 * s390fpu.h functions for saving & restoring the fpu state. 9 * 10 * I couldn't inline these as linux/sched.h included half the world 11 * & was required to at the task structure. 12 * & the functions were too complex to make macros from. 13 * ( & as usual I didn't feel like debugging inline code ). 14 */ 15 16#include <linux/config.h> 17#include <linux/sched.h> 18 19int save_fp_regs1(s390_fp_regs *fpregs) 20{ 21 int has_ieee=MACHINE_HAS_IEEE; 22/* 23 I don't think we can use STE here as this would load 24 fp registers 0 & 2 into memory locations 0 & 1 etc. 25 */ 26 asm volatile ("STD 0,8(%0)\n\t" 27 "STD 2,24(%0)\n\t" 28 "STD 4,40(%0)\n\t" 29 "STD 6,56(%0)" 30 : 31 : "a" (fpregs) 32 : "memory" 33 ); 34 if(has_ieee) 35 { 36 asm volatile ("STFPC 0(%0)\n\t" 37 "STD 1,16(%0)\n\t" 38 "STD 3,32(%0)\n\t" 39 "STD 5,48(%0)\n\t" 40 "STD 7,64(%0)\n\t" 41 "STD 8,72(%0)\n\t" 42 "STD 9,80(%0)\n\t" 43 "STD 10,88(%0)\n\t" 44 "STD 11,96(%0)\n\t" 45 "STD 12,104(%0)\n\t" 46 "STD 13,112(%0)\n\t" 47 "STD 14,120(%0)\n\t" 48 "STD 15,128(%0)\n\t" 49 : 50 : "a" (fpregs) 51 : "memory" 52 ); 53 } 54 return(has_ieee); 55} 56 57 58void save_fp_regs(s390_fp_regs *fpregs) 59{ 60#if CONFIG_MATHEMU 61 s390_fp_regs *currentfprs; 62 63 if(!save_fp_regs1(fpregs)) 64 { 65 currentfprs=¤t->thread.fp_regs; 66 fpregs->fpc=currentfprs->fpc; 67 fpregs->fprs[1].d=currentfprs->fprs[1].d; 68 fpregs->fprs[3].d=currentfprs->fprs[3].d; 69 fpregs->fprs[5].d=currentfprs->fprs[5].d; 70 fpregs->fprs[7].d=currentfprs->fprs[7].d; 71 memcpy(&fpregs->fprs[8].d,¤tfprs->fprs[8].d,sizeof(freg_t)*8); 72 } 73#else 74 save_fp_regs1(fpregs); 75#endif 76} 77 78 79int restore_fp_regs1(s390_fp_regs *fpregs) 80{ 81 int has_ieee=MACHINE_HAS_IEEE; 82 83 /* If we don't mask with the FPC_VALID_MASK here 84 * we've got a very quick shutdown -h now command 85 * via a kernel specification exception. 86 */ 87 fpregs->fpc&=FPC_VALID_MASK; 88 asm volatile ("LD 0,8(%0)\n\t" 89 "LD 2,24(%0)\n\t" 90 "LD 4,40(%0)\n\t" 91 "LD 6,56(%0)" 92 : 93 : "a" (fpregs) 94 : "memory" 95 ); 96 if(has_ieee) 97 { 98 asm volatile ("LFPC 0(%0)\n\t" 99 "LD 1,16(%0)\n\t" 100 "LD 3,32(%0)\n\t" 101 "LD 5,48(%0)\n\t" 102 "LD 7,64(%0)\n\t" 103 "LD 8,72(%0)\n\t" 104 "LD 9,80(%0)\n\t" 105 "LD 10,88(%0)\n\t" 106 "LD 11,96(%0)\n\t" 107 "LD 12,104(%0)\n\t" 108 "LD 13,112(%0)\n\t" 109 "LD 14,120(%0)\n\t" 110 "LD 15,128(%0)\n\t" 111 : 112 : "a" (fpregs) 113 : "memory" 114 ); 115 } 116 return(has_ieee); 117} 118 119void restore_fp_regs(s390_fp_regs *fpregs) 120{ 121#if CONFIG_MATHEMU 122 s390_fp_regs *currentfprs; 123 124 if(!restore_fp_regs1(fpregs)) 125 { 126 currentfprs=¤t->thread.fp_regs; 127 currentfprs->fpc=fpregs->fpc; 128 currentfprs->fprs[1].d=fpregs->fprs[1].d; 129 currentfprs->fprs[3].d=fpregs->fprs[3].d; 130 currentfprs->fprs[5].d=fpregs->fprs[5].d; 131 currentfprs->fprs[7].d=fpregs->fprs[7].d; 132 memcpy(¤tfprs->fprs[8].d,&fpregs->fprs[8].d,sizeof(freg_t)*8); 133 } 134#else 135 restore_fp_regs1(fpregs); 136#endif 137} 138 139