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