-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfpu.c
92 lines (81 loc) · 1.11 KB
/
fpu.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "ureg.h"
#include "sysreg.h"
/* libc */
extern ulong getfcr(void);
extern void setfcr(ulong fcr);
extern ulong getfsr(void);
extern void setfsr(ulong fsr);
void
fpuinit(void)
{
fpoff();
}
void
fpon(void)
{
syswr(CPACR_EL1, 3<<20);
}
void
fpoff(void)
{
syswr(CPACR_EL1, 0<<20);
}
void
fpinit(void)
{
fpon();
setfcr(0);
setfsr(0);
}
void
fpclear(void)
{
fpoff();
}
void
fpsave(FPsave *p)
{
p->control = getfcr();
p->status = getfsr();
fpsaveregs(p->regs);
fpoff();
}
void
fprestore(FPsave *p)
{
fpon();
setfcr(p->control);
setfsr(p->status);
fploadregs(p->regs);
}
void
mathtrap(Ureg*)
{
int s;
if((up->fpstate & FPillegal) != 0){
postnote(up, 1, "sys: floating point in note handler", NDebug);
return;
}
switch(up->fpstate){
case FPinit:
s = splhi();
fpinit();
up->fpstate = FPactive;
splx(s);
break;
case FPinactive:
s = splhi();
fprestore(up->fpsave);
up->fpstate = FPactive;
splx(s);
break;
case FPactive:
postnote(up, 1, "sys: floating point error", NDebug);
break;
}
}