]>
Commit | Line | Data |
---|---|---|
bf90e1ea VG |
1 | /* |
2 | * fpu.c - save/restore of Floating Point Unit Registers on task switch | |
3 | * | |
4 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | */ | |
10 | ||
11 | #include <linux/sched.h> | |
12 | #include <asm/switch_to.h> | |
13 | ||
14 | /* | |
15 | * To save/restore FPU regs, simplest scheme would use LR/SR insns. | |
16 | * However since SR serializes the pipeline, an alternate "hack" can be used | |
17 | * which uses the FPU Exchange insn (DEXCL) to r/w FPU regs. | |
18 | * | |
19 | * Store to 64bit dpfp1 reg from a pair of core regs: | |
20 | * dexcl1 0, r1, r0 ; where r1:r0 is the 64 bit val | |
21 | * | |
22 | * Read from dpfp1 into pair of core regs (w/o clobbering dpfp1) | |
23 | * mov_s r3, 0 | |
24 | * daddh11 r1, r3, r3 ; get "hi" into r1 (dpfp1 unchanged) | |
25 | * dexcl1 r0, r1, r3 ; get "low" into r0 (dpfp1 low clobbered) | |
26 | * dexcl1 0, r1, r0 ; restore dpfp1 to orig value | |
27 | * | |
28 | * However we can tweak the read, so that read-out of outgoing task's FPU regs | |
29 | * and write of incoming task's regs happen in one shot. So all the work is | |
30 | * done before context switch | |
31 | */ | |
32 | ||
33 | void fpu_save_restore(struct task_struct *prev, struct task_struct *next) | |
34 | { | |
35 | unsigned int *saveto = &prev->thread.fpu.aux_dpfp[0].l; | |
36 | unsigned int *readfrom = &next->thread.fpu.aux_dpfp[0].l; | |
37 | ||
38 | const unsigned int zero = 0; | |
39 | ||
40 | __asm__ __volatile__( | |
41 | "daddh11 %0, %2, %2\n" | |
42 | "dexcl1 %1, %3, %4\n" | |
43 | : "=&r" (*(saveto + 1)), /* early clobber must here */ | |
44 | "=&r" (*(saveto)) | |
45 | : "r" (zero), "r" (*(readfrom + 1)), "r" (*(readfrom)) | |
46 | ); | |
47 | ||
48 | __asm__ __volatile__( | |
49 | "daddh22 %0, %2, %2\n" | |
50 | "dexcl2 %1, %3, %4\n" | |
51 | : "=&r"(*(saveto + 3)), /* early clobber must here */ | |
52 | "=&r"(*(saveto + 2)) | |
53 | : "r" (zero), "r" (*(readfrom + 3)), "r" (*(readfrom + 2)) | |
54 | ); | |
55 | } |