source: mainline/kernel/arch/arm32/src/fpu_context.c@ 8ff9484

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

arm32: Implement all variants of FPU context save/restore.

  • Property mode set to 100644
File size: 5.1 KB
RevLine 
[8ff9484]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 uint32_t fpsid = 0;
146 uint32_t mvfr0 = 0;
147 asm volatile (
148 "vmrs %0,fpsid\n"
149 "vmrs %1,mvfr0\n"
150 :"=r"(fpsid), "=r"(mvfr0)::
151 );
152 //TODO: Identify FPU unit
153 //and set correct functions to save/restore ctx
154 switch (FPSID_SUBACHITECTURE(fpsid))
155 {
156 case FPU_VFPv1:
157 save_context = fpu_context_save_s32;
158 restore_context = fpu_context_restore_s32;
159 break;
160 case FPU_VFPv2_COMMONv1:
161 save_context = fpu_context_save_d16;
162 restore_context = fpu_context_restore_d16;
163 break;
164 case FPU_VFPv3_COMMONv2:
165 case FPU_VFPv3_NOTRAP:
166 case FPU_VFPv3:
167 /* See page B4-1637 */
168 if ((mvfr0 & 0xf) == 0x1) {
169 save_context = fpu_context_save_d32;
170 restore_context = fpu_context_restore_d32;
171 } else {
172 save_context = fpu_context_save_d16;
173 restore_context = fpu_context_restore_d16;
174 }
175 break;
176
177 }
178}
179
180void fpu_enable(void)
181{
182 /* Enable FPU instructions */
183 asm volatile (
184 "ldr r1, =0x40000000\n"
185 "vmsr fpexc, r1\n"
186 ::: "r1"
187 );
188}
189
190void fpu_disable(void)
191{
192 /* Disable FPU instructions */
193 asm volatile (
194 "ldr r1, =0x00000000\n"
195 "vmsr fpexc, r1\n"
196 ::: "r1"
197 );
198}
199
200void fpu_context_save(fpu_context_t *ctx)
201{
202 save_context(ctx);
203}
204
205void fpu_context_restore(fpu_context_t *ctx)
206{
207 restore_context(ctx);
208}
Note: See TracBrowser for help on using the repository browser.