source: mainline/kernel/arch/arm32/src/fpu_context.c@ 65871bb

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

arm32: Don't try to initialize FPU without CONFIG_FPU

Print warning if we try to setup FPU on a machine that has none.

  • 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}
146
147void fpu_setup(void)
148{
149 uint32_t fpsid = 0;
150 asm volatile (
151 "vmrs %0,fpsid\n"
152 :"=r"(fpsid)::
153 );
154 if (fpsid & FPSID_SW_ONLY_FLAG) {
155 printf("No FPU avaiable\n");
156 return;
157 }
158 switch (FPSID_SUBACHITECTURE(fpsid))
159 {
160 case FPU_VFPv1:
161 printf("Detected VFPv1\n");
162 save_context = fpu_context_save_s32;
163 restore_context = fpu_context_restore_s32;
164 break;
165 case FPU_VFPv2_COMMONv1:
166 printf("Detected VFPv2\n");
167 save_context = fpu_context_save_d16;
168 restore_context = fpu_context_restore_d16;
169 break;
170 case FPU_VFPv3_COMMONv2:
171 case FPU_VFPv3_NOTRAP:
172 case FPU_VFPv3: {
173 uint32_t mvfr0 = 0;
174 asm volatile (
175 "vmrs %0,mvfr0\n"
176 :"=r"(mvfr0)::
177 );
178 /* See page B4-1637 */
179 if ((mvfr0 & 0xf) == 0x1) {
180 printf("Detected VFPv3+ with 32 regs\n");
181 save_context = fpu_context_save_d32;
182 restore_context = fpu_context_restore_d32;
183 } else {
184 printf("Detected VFPv3+ with 16 regs\n");
185 save_context = fpu_context_save_d16;
186 restore_context = fpu_context_restore_d16;
187 }
188 break;
189 }
190
191 }
192}
193
194void fpu_enable(void)
195{
196 /* Enable FPU instructions */
197 asm volatile (
198 "ldr r1, =0x40000000\n"
199 "vmsr fpexc, r1\n"
200 ::: "r1"
201 );
202}
203
204void fpu_disable(void)
205{
206 /* Disable FPU instructions */
207 asm volatile (
208 "ldr r1, =0x00000000\n"
209 "vmsr fpexc, r1\n"
210 ::: "r1"
211 );
212}
213
214void fpu_context_save(fpu_context_t *ctx)
215{
216 if (save_context)
217 save_context(ctx);
218}
219
220void fpu_context_restore(fpu_context_t *ctx)
221{
222 if (restore_context)
223 restore_context(ctx);
224}
Note: See TracBrowser for help on using the repository browser.