fpu.h (cceb9bd63373061ad7b75c321808a2fb11c86545) fpu.h (4227a2d4efc9c84f35826dc4d1e6dc183f6c1c05)
1/*
2 * Copyright (C) 2002 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.

--- 22 unchanged lines hidden (view full) ---

31struct sigcontext32;
32
33extern void _init_fpu(void);
34extern void _save_fp(struct task_struct *);
35extern void _restore_fp(struct task_struct *);
36
37/*
38 * This enum specifies a mode in which we want the FPU to operate, for cores
1/*
2 * Copyright (C) 2002 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.

--- 22 unchanged lines hidden (view full) ---

31struct sigcontext32;
32
33extern void _init_fpu(void);
34extern void _save_fp(struct task_struct *);
35extern void _restore_fp(struct task_struct *);
36
37/*
38 * This enum specifies a mode in which we want the FPU to operate, for cores
39 * which implement the Status.FR bit. Note that FPU_32BIT & FPU_64BIT
40 * purposefully have the values 0 & 1 respectively, so that an integer value
41 * of Status.FR can be trivially casted to the corresponding enum fpu_mode.
39 * which implement the Status.FR bit. Note that the bottom bit of the value
40 * purposefully matches the desired value of the Status.FR bit.
42 */
43enum fpu_mode {
44 FPU_32BIT = 0, /* FR = 0 */
41 */
42enum fpu_mode {
43 FPU_32BIT = 0, /* FR = 0 */
45 FPU_64BIT, /* FR = 1 */
44 FPU_64BIT, /* FR = 1, FRE = 0 */
46 FPU_AS_IS,
45 FPU_AS_IS,
46 FPU_HYBRID, /* FR = 1, FRE = 1 */
47
48#define FPU_FR_MASK 0x1
47};
48
49static inline int __enable_fpu(enum fpu_mode mode)
50{
51 int fr;
52
53 switch (mode) {
54 case FPU_AS_IS:
55 /* just enable the FPU in its current mode */
56 set_c0_status(ST0_CU1);
57 enable_fpu_hazard();
58 return 0;
59
49};
50
51static inline int __enable_fpu(enum fpu_mode mode)
52{
53 int fr;
54
55 switch (mode) {
56 case FPU_AS_IS:
57 /* just enable the FPU in its current mode */
58 set_c0_status(ST0_CU1);
59 enable_fpu_hazard();
60 return 0;
61
62 case FPU_HYBRID:
63 if (!cpu_has_fre)
64 return SIGFPE;
65
66 /* set FRE */
67 write_c0_config5(read_c0_config5() | MIPS_CONF5_FRE);
68 goto fr_common;
69
60 case FPU_64BIT:
61#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
62 /* we only have a 32-bit FPU */
63 return SIGFPE;
64#endif
65 /* fall through */
66 case FPU_32BIT:
70 case FPU_64BIT:
71#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
72 /* we only have a 32-bit FPU */
73 return SIGFPE;
74#endif
75 /* fall through */
76 case FPU_32BIT:
77 /* clear FRE */
78 write_c0_config5(read_c0_config5() & ~MIPS_CONF5_FRE);
79fr_common:
67 /* set CU1 & change FR appropriately */
80 /* set CU1 & change FR appropriately */
68 fr = (int)mode;
81 fr = (int)mode & FPU_FR_MASK;
69 change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0));
70 enable_fpu_hazard();
71
72 /* check FR has the desired value */
73 return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE;
74
75 default:
76 BUG();

--- 20 unchanged lines hidden (view full) ---

97 return cpu_has_fpu && __is_fpu_owner();
98}
99
100static inline int __own_fpu(void)
101{
102 enum fpu_mode mode;
103 int ret;
104
82 change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0));
83 enable_fpu_hazard();
84
85 /* check FR has the desired value */
86 return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE;
87
88 default:
89 BUG();

--- 20 unchanged lines hidden (view full) ---

110 return cpu_has_fpu && __is_fpu_owner();
111}
112
113static inline int __own_fpu(void)
114{
115 enum fpu_mode mode;
116 int ret;
117
105 mode = !test_thread_flag(TIF_32BIT_FPREGS);
118 if (test_thread_flag(TIF_HYBRID_FPREGS))
119 mode = FPU_HYBRID;
120 else
121 mode = !test_thread_flag(TIF_32BIT_FPREGS);
122
106 ret = __enable_fpu(mode);
107 if (ret)
108 return ret;
109
110 KSTK_STATUS(current) |= ST0_CU1;
123 ret = __enable_fpu(mode);
124 if (ret)
125 return ret;
126
127 KSTK_STATUS(current) |= ST0_CU1;
111 if (mode == FPU_64BIT)
128 if (mode == FPU_64BIT || mode == FPU_HYBRID)
112 KSTK_STATUS(current) |= ST0_FR;
113 else /* mode == FPU_32BIT */
114 KSTK_STATUS(current) &= ~ST0_FR;
115
116 set_thread_flag(TIF_USEDFPU);
117 return 0;
118}
119

--- 41 unchanged lines hidden (view full) ---

161}
162
163static inline int init_fpu(void)
164{
165 int ret = 0;
166
167 if (cpu_has_fpu) {
168 ret = __own_fpu();
129 KSTK_STATUS(current) |= ST0_FR;
130 else /* mode == FPU_32BIT */
131 KSTK_STATUS(current) &= ~ST0_FR;
132
133 set_thread_flag(TIF_USEDFPU);
134 return 0;
135}
136

--- 41 unchanged lines hidden (view full) ---

178}
179
180static inline int init_fpu(void)
181{
182 int ret = 0;
183
184 if (cpu_has_fpu) {
185 ret = __own_fpu();
169 if (!ret)
186 if (!ret) {
187 unsigned int config5 = read_c0_config5();
188
189 /*
190 * Ensure FRE is clear whilst running _init_fpu, since
191 * single precision FP instructions are used. If FRE
192 * was set then we'll just end up initialising all 32
193 * 64b registers.
194 */
195 write_c0_config5(config5 & ~MIPS_CONF5_FRE);
196 enable_fpu_hazard();
197
170 _init_fpu();
198 _init_fpu();
199
200 /* Restore FRE */
201 write_c0_config5(config5);
202 enable_fpu_hazard();
203 }
171 } else
172 fpu_emulator_init_fpu();
173
174 return ret;
175}
176
177static inline void save_fp(struct task_struct *tsk)
178{

--- 23 unchanged lines hidden ---
204 } else
205 fpu_emulator_init_fpu();
206
207 return ret;
208}
209
210static inline void save_fp(struct task_struct *tsk)
211{

--- 23 unchanged lines hidden ---