1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
/*
* 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 <linux/config.h>
#include <linux/sched.h>
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
}
|