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=¤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
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=¤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