source: mainline/kernel/arch/arm32/src/fpu_context.c@ 957ce9a5

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 957ce9a5 was 957ce9a5, checked in by Jan Vesely <jano.vesely@…>, 13 years ago

arm32: Implement and allow lazy FPU context switching.

It's horribly slow and gui fails to draw things properly.

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/*
2 * Copyright (c) 2012 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup arm32
30 * @{
31 */
32/** @file
33 * @brief arm32 FPU context
34 */
35
36#include <fpu_context.h>
37#include <arch.h>
38#include <cpu.h>
39
40#define FPSID_IMPLEMENTER(r) ((r) >> 24)
41#define FPSID_SW_ONLY_FLAG (1 << 23)
42#define FPSID_SUBACHITECTURE(r) (((r) >> 16) & 0x7f)
43#define FPSID_PART_NUMBER(r) (((r) >> 8) & 0xff)
44#define FPSID_VARIANT(r) (((r) >> 4) 0xf)
45#define FPSID_REVISION(r) (((r) >> 0) 0xf)
46enum {
47 FPU_VFPv1 = 0x00,
48 FPU_VFPv2_COMMONv1 = 0x01,
49 FPU_VFPv3_COMMONv2 = 0x02, /* Check MVFR0 and MVFR 1*/
50 FPU_VFPv3_NOTRAP = 0x3, /* Does not support trap */
51 FPU_VFPv3 = 0x4,
52};
53
54static void (*save_context)(fpu_context_t *ctx);
55static void (*restore_context)(fpu_context_t *ctx);
56
57/** Saves 32 single precision fpu registers.
58 * @param ctx FPU context area.
59 * Used by VFPv1
60 */
61static void fpu_context_save_s32(fpu_context_t *ctx)
62{
63 asm volatile (
64 "vmrs r1, fpscr\n"
65 "stm %0, {r1}\n"
66 "vstm %0, {s0-s31}\n"
67 ::"r" (ctx): "r1","memory"
68 );
69}
70
71/** Restores 32 single precision fpu registers.
72 * @param ctx FPU context area.
73 * Used by VFPv1
74 */
75static void fpu_context_restore_s32(fpu_context_t *ctx)
76{
77 asm volatile (
78 "ldm %0, {r1}\n"
79 "vmsr fpscr, r1\n"
80 "vldm %0, {s0-s31}\n"
81 ::"r" (ctx): "r1"
82 );
83}
84
85/** Saves 16 double precision fpu registers.
86 * @param ctx FPU context area.
87 * Used by VFPv2, VFPv3-d16, and VFPv4-d16.
88 */
89static void fpu_context_save_d16(fpu_context_t *ctx)
90{
91 asm volatile (
92 "vmrs r1, fpscr\n"
93 "stm %0, {r1}\n"
94 "vstm %0, {d0-d15}\n"
95 ::"r" (ctx): "r1","memory"
96 );
97}
98
99/** Restores 16 double precision fpu registers.
100 * @param ctx FPU context area.
101 * Used by VFPv2, VFPv3-d16, and VFPv4-d16.
102 */
103static void fpu_context_restore_d16(fpu_context_t *ctx)
104{
105 asm volatile (
106 "ldm %0, {r1}\n"
107 "vmsr fpscr, r1\n"
108 "vldm %0, {d0-d15}\n"
109 ::"r" (ctx): "r1"
110 );
111}
112
113/** Saves 32 double precision fpu registers.
114 * @param ctx FPU context area.
115 * Used by VFPv3-d32, VFPv4-d32, and advanced SIMD.
116 */
117static void fpu_context_save_d32(fpu_context_t *ctx)
118{
119 asm volatile (
120 "vmrs r1, fpscr\n"
121 "stm %0, {r1}\n"
122 "vstm %0, {d0-d15}\n"
123 "vstm %0, {d16-d31}\n"
124 ::"r" (ctx): "r1","memory"
125 );
126}
127
128/** Restores 32 double precision fpu registers.
129 * @param ctx FPU context area.
130 * Used by VFPv3-d32, VFPv4-d32, and advanced SIMD.
131 */
132static void fpu_context_restore_d32(fpu_context_t *ctx)
133{
134 asm volatile (
135 "ldm %0, {r1}\n"
136 "vmsr fpscr, r1\n"
137 "vldm %0, {d0-d15}\n"
138 "vldm %0, {d16-d31}\n"
139 ::"r" (ctx): "r1"
140 );
141}
142
143void fpu_init(void)
144{
145 fpu_enable();
146}
147
148void fpu_setup(void)
149{
150 uint32_t fpsid = 0;
151 asm volatile (
152 "vmrs %0,fpsid\n"
153 :"=r"(fpsid)::
154 );
155 if (fpsid & FPSID_SW_ONLY_FLAG) {
156 printf("No FPU avaiable\n");
157 return;
158 }
159 switch (FPSID_SUBACHITECTURE(fpsid))
160 {
161 case FPU_VFPv1:
162 printf("Detected VFPv1\n");
163 save_context = fpu_context_save_s32;
164 restore_context = fpu_context_restore_s32;
165 break;
166 case FPU_VFPv2_COMMONv1:
167 printf("Detected VFPv2\n");
168 save_context = fpu_context_save_d16;
169 restore_context = fpu_context_restore_d16;
170 break;
171 case FPU_VFPv3_COMMONv2:
172 case FPU_VFPv3_NOTRAP:
173 case FPU_VFPv3: {
174 uint32_t mvfr0 = 0;
175 asm volatile (
176 "vmrs %0,mvfr0\n"
177 :"=r"(mvfr0)::
178 );
179 /* See page B4-1637 */
180 if ((mvfr0 & 0xf) == 0x1) {
181 printf("Detected VFPv3+ with 32 regs\n");
182 save_context = fpu_context_save_d32;
183 restore_context = fpu_context_restore_d32;
184 } else {
185 printf("Detected VFPv3+ with 16 regs\n");
186 save_context = fpu_context_save_d16;
187 restore_context = fpu_context_restore_d16;
188 }
189 break;
190 }
191
192 }
193}
194
195void fpu_enable(void)
196{
197 /* Enable FPU instructions */
198 asm volatile (
199 "ldr r1, =0x40000000\n"
200 "vmsr fpexc, r1\n"
201 ::: "r1"
202 );
203}
204
205void fpu_disable(void)
206{
207 /* Disable FPU instructions */
208 asm volatile (
209 "ldr r1, =0x00000000\n"
210 "vmsr fpexc, r1\n"
211 ::: "r1"
212 );
213}
214
215void fpu_context_save(fpu_context_t *ctx)
216{
217 if (save_context)
218 save_context(ctx);
219}
220
221void fpu_context_restore(fpu_context_t *ctx)
222{
223 if (restore_context)
224 restore_context(ctx);
225}
Note: See TracBrowser for help on using the repository browser.