0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/cpu.h>
0010 #include <linux/sched.h>
0011 #include <asm/fpu/types.h>
0012 #include <asm/fpu/api.h>
0013
0014 asm(".include \"asm/vx-insn.h\"\n");
0015
0016 void __kernel_fpu_begin(struct kernel_fpu *state, u32 flags)
0017 {
0018
0019
0020
0021
0022 flags &= state->mask;
0023
0024 if (flags & KERNEL_FPC)
0025
0026 asm volatile("stfpc %0" : "=Q" (state->fpc));
0027
0028 if (!MACHINE_HAS_VX) {
0029 if (flags & KERNEL_VXR_V0V7) {
0030
0031 asm volatile("std 0,%0" : "=Q" (state->fprs[0]));
0032 asm volatile("std 1,%0" : "=Q" (state->fprs[1]));
0033 asm volatile("std 2,%0" : "=Q" (state->fprs[2]));
0034 asm volatile("std 3,%0" : "=Q" (state->fprs[3]));
0035 asm volatile("std 4,%0" : "=Q" (state->fprs[4]));
0036 asm volatile("std 5,%0" : "=Q" (state->fprs[5]));
0037 asm volatile("std 6,%0" : "=Q" (state->fprs[6]));
0038 asm volatile("std 7,%0" : "=Q" (state->fprs[7]));
0039 asm volatile("std 8,%0" : "=Q" (state->fprs[8]));
0040 asm volatile("std 9,%0" : "=Q" (state->fprs[9]));
0041 asm volatile("std 10,%0" : "=Q" (state->fprs[10]));
0042 asm volatile("std 11,%0" : "=Q" (state->fprs[11]));
0043 asm volatile("std 12,%0" : "=Q" (state->fprs[12]));
0044 asm volatile("std 13,%0" : "=Q" (state->fprs[13]));
0045 asm volatile("std 14,%0" : "=Q" (state->fprs[14]));
0046 asm volatile("std 15,%0" : "=Q" (state->fprs[15]));
0047 }
0048 return;
0049 }
0050
0051
0052 asm volatile (
0053
0054
0055
0056
0057 " la 1,%[vxrs]\n"
0058 " tmll %[m],30\n"
0059 " jz 7f\n"
0060 " jo 5f\n"
0061
0062
0063
0064
0065 " chi %[m],12\n"
0066 " jne 0f\n"
0067 " VSTM 8,23,128,1\n"
0068 " j 7f\n"
0069
0070 "0: tmll %[m],6\n"
0071 " jz 3f\n"
0072 " jo 2f\n"
0073 " brc 2,1f\n"
0074 " VSTM 0,7,0,1\n"
0075 " j 3f\n"
0076 "1: VSTM 8,15,128,1\n"
0077 " j 3f\n"
0078 "2: VSTM 0,15,0,1\n"
0079
0080 "3: tmll %[m],24\n"
0081 " jz 7f\n"
0082 " jo 6f\n"
0083 " brc 2,4f\n"
0084 " VSTM 16,23,256,1\n"
0085 " j 7f\n"
0086 "4: VSTM 24,31,384,1\n"
0087 " j 7f\n"
0088 "5: VSTM 0,15,0,1\n"
0089 "6: VSTM 16,31,256,1\n"
0090 "7:"
0091 : [vxrs] "=Q" (*(struct vx_array *) &state->vxrs)
0092 : [m] "d" (flags)
0093 : "1", "cc");
0094 }
0095 EXPORT_SYMBOL(__kernel_fpu_begin);
0096
0097 void __kernel_fpu_end(struct kernel_fpu *state, u32 flags)
0098 {
0099
0100
0101
0102
0103
0104 flags &= state->mask;
0105
0106 if (flags & KERNEL_FPC)
0107
0108 asm volatile("lfpc %0" : : "Q" (state->fpc));
0109
0110 if (!MACHINE_HAS_VX) {
0111 if (flags & KERNEL_VXR_V0V7) {
0112
0113 asm volatile("ld 0,%0" : : "Q" (state->fprs[0]));
0114 asm volatile("ld 1,%0" : : "Q" (state->fprs[1]));
0115 asm volatile("ld 2,%0" : : "Q" (state->fprs[2]));
0116 asm volatile("ld 3,%0" : : "Q" (state->fprs[3]));
0117 asm volatile("ld 4,%0" : : "Q" (state->fprs[4]));
0118 asm volatile("ld 5,%0" : : "Q" (state->fprs[5]));
0119 asm volatile("ld 6,%0" : : "Q" (state->fprs[6]));
0120 asm volatile("ld 7,%0" : : "Q" (state->fprs[7]));
0121 asm volatile("ld 8,%0" : : "Q" (state->fprs[8]));
0122 asm volatile("ld 9,%0" : : "Q" (state->fprs[9]));
0123 asm volatile("ld 10,%0" : : "Q" (state->fprs[10]));
0124 asm volatile("ld 11,%0" : : "Q" (state->fprs[11]));
0125 asm volatile("ld 12,%0" : : "Q" (state->fprs[12]));
0126 asm volatile("ld 13,%0" : : "Q" (state->fprs[13]));
0127 asm volatile("ld 14,%0" : : "Q" (state->fprs[14]));
0128 asm volatile("ld 15,%0" : : "Q" (state->fprs[15]));
0129 }
0130 return;
0131 }
0132
0133
0134 asm volatile (
0135
0136
0137
0138
0139 " la 1,%[vxrs]\n"
0140 " tmll %[m],30\n"
0141 " jz 7f\n"
0142 " jo 5f\n"
0143
0144
0145
0146
0147 " chi %[m],12\n"
0148 " jne 0f\n"
0149 " VLM 8,23,128,1\n"
0150 " j 7f\n"
0151
0152 "0: tmll %[m],6\n"
0153 " jz 3f\n"
0154 " jo 2f\n"
0155 " brc 2,1f\n"
0156 " VLM 0,7,0,1\n"
0157 " j 3f\n"
0158 "1: VLM 8,15,128,1\n"
0159 " j 3f\n"
0160 "2: VLM 0,15,0,1\n"
0161
0162 "3: tmll %[m],24\n"
0163 " jz 7f\n"
0164 " jo 6f\n"
0165 " brc 2,4f\n"
0166 " VLM 16,23,256,1\n"
0167 " j 7f\n"
0168 "4: VLM 24,31,384,1\n"
0169 " j 7f\n"
0170 "5: VLM 0,15,0,1\n"
0171 "6: VLM 16,31,256,1\n"
0172 "7:"
0173 : [vxrs] "=Q" (*(struct vx_array *) &state->vxrs)
0174 : [m] "d" (flags)
0175 : "1", "cc");
0176 }
0177 EXPORT_SYMBOL(__kernel_fpu_end);
0178
0179 void __load_fpu_regs(void)
0180 {
0181 struct fpu *state = ¤t->thread.fpu;
0182 unsigned long *regs = current->thread.fpu.regs;
0183
0184 asm volatile("lfpc %0" : : "Q" (state->fpc));
0185 if (likely(MACHINE_HAS_VX)) {
0186 asm volatile("lgr 1,%0\n"
0187 "VLM 0,15,0,1\n"
0188 "VLM 16,31,256,1\n"
0189 :
0190 : "d" (regs)
0191 : "1", "cc", "memory");
0192 } else {
0193 asm volatile("ld 0,%0" : : "Q" (regs[0]));
0194 asm volatile("ld 1,%0" : : "Q" (regs[1]));
0195 asm volatile("ld 2,%0" : : "Q" (regs[2]));
0196 asm volatile("ld 3,%0" : : "Q" (regs[3]));
0197 asm volatile("ld 4,%0" : : "Q" (regs[4]));
0198 asm volatile("ld 5,%0" : : "Q" (regs[5]));
0199 asm volatile("ld 6,%0" : : "Q" (regs[6]));
0200 asm volatile("ld 7,%0" : : "Q" (regs[7]));
0201 asm volatile("ld 8,%0" : : "Q" (regs[8]));
0202 asm volatile("ld 9,%0" : : "Q" (regs[9]));
0203 asm volatile("ld 10,%0" : : "Q" (regs[10]));
0204 asm volatile("ld 11,%0" : : "Q" (regs[11]));
0205 asm volatile("ld 12,%0" : : "Q" (regs[12]));
0206 asm volatile("ld 13,%0" : : "Q" (regs[13]));
0207 asm volatile("ld 14,%0" : : "Q" (regs[14]));
0208 asm volatile("ld 15,%0" : : "Q" (regs[15]));
0209 }
0210 clear_cpu_flag(CIF_FPU);
0211 }
0212 EXPORT_SYMBOL(__load_fpu_regs);
0213
0214 void load_fpu_regs(void)
0215 {
0216 raw_local_irq_disable();
0217 __load_fpu_regs();
0218 raw_local_irq_enable();
0219 }
0220 EXPORT_SYMBOL(load_fpu_regs);
0221
0222 void save_fpu_regs(void)
0223 {
0224 unsigned long flags, *regs;
0225 struct fpu *state;
0226
0227 local_irq_save(flags);
0228
0229 if (test_cpu_flag(CIF_FPU))
0230 goto out;
0231
0232 state = ¤t->thread.fpu;
0233 regs = current->thread.fpu.regs;
0234
0235 asm volatile("stfpc %0" : "=Q" (state->fpc));
0236 if (likely(MACHINE_HAS_VX)) {
0237 asm volatile("lgr 1,%0\n"
0238 "VSTM 0,15,0,1\n"
0239 "VSTM 16,31,256,1\n"
0240 :
0241 : "d" (regs)
0242 : "1", "cc", "memory");
0243 } else {
0244 asm volatile("std 0,%0" : "=Q" (regs[0]));
0245 asm volatile("std 1,%0" : "=Q" (regs[1]));
0246 asm volatile("std 2,%0" : "=Q" (regs[2]));
0247 asm volatile("std 3,%0" : "=Q" (regs[3]));
0248 asm volatile("std 4,%0" : "=Q" (regs[4]));
0249 asm volatile("std 5,%0" : "=Q" (regs[5]));
0250 asm volatile("std 6,%0" : "=Q" (regs[6]));
0251 asm volatile("std 7,%0" : "=Q" (regs[7]));
0252 asm volatile("std 8,%0" : "=Q" (regs[8]));
0253 asm volatile("std 9,%0" : "=Q" (regs[9]));
0254 asm volatile("std 10,%0" : "=Q" (regs[10]));
0255 asm volatile("std 11,%0" : "=Q" (regs[11]));
0256 asm volatile("std 12,%0" : "=Q" (regs[12]));
0257 asm volatile("std 13,%0" : "=Q" (regs[13]));
0258 asm volatile("std 14,%0" : "=Q" (regs[14]));
0259 asm volatile("std 15,%0" : "=Q" (regs[15]));
0260 }
0261 set_cpu_flag(CIF_FPU);
0262 out:
0263 local_irq_restore(flags);
0264 }
0265 EXPORT_SYMBOL(save_fpu_regs);