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 
save_fp_regs1(s390_fp_regs * fpregs)19 int 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 
save_fp_regs(s390_fp_regs * fpregs)58 void 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=&current->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,&currentfprs->fprs[8].d,sizeof(freg_t)*8);
72 	}
73 #else
74 	save_fp_regs1(fpregs);
75 #endif
76 }
77 
78 
restore_fp_regs1(s390_fp_regs * fpregs)79 int 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 
restore_fp_regs(s390_fp_regs * fpregs)119 void 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=&current->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(&currentfprs->fprs[8].d,&fpregs->fprs[8].d,sizeof(freg_t)*8);
133 	}
134 #else
135 	restore_fp_regs1(fpregs);
136 #endif
137 }
138 
139