This source file includes following definitions.
- nwfpe_notify
- fpe_init
- fpe_exit
- float_raise
1
2
3
4
5
6
7
8
9
10
11
12 #include "fpa11.h"
13
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16
17
18 #include <linux/errno.h>
19 #include <linux/types.h>
20 #include <linux/kernel.h>
21 #include <linux/signal.h>
22 #include <linux/sched/signal.h>
23 #include <linux/init.h>
24
25 #include <asm/thread_notify.h>
26
27 #include "softfloat.h"
28 #include "fpopcode.h"
29 #include "fpmodule.h"
30 #include "fpa11.inl"
31
32
33 #ifdef CONFIG_FPE_NWFPE_XP
34 #define NWFPE_BITS "extended"
35 #else
36 #define NWFPE_BITS "double"
37 #endif
38
39 #ifdef MODULE
40 void fp_send_sig(unsigned long sig, struct task_struct *p, int priv);
41 #else
42 #define fp_send_sig send_sig
43 #define kern_fp_enter fp_enter
44
45 extern char fpe_type[];
46 #endif
47
48 static int nwfpe_notify(struct notifier_block *self, unsigned long cmd, void *v)
49 {
50 struct thread_info *thread = v;
51
52 if (cmd == THREAD_NOTIFY_FLUSH)
53 nwfpe_init_fpa(&thread->fpstate);
54
55 return NOTIFY_DONE;
56 }
57
58 static struct notifier_block nwfpe_notifier_block = {
59 .notifier_call = nwfpe_notify,
60 };
61
62
63 void fp_setup(void);
64
65
66 extern void (*kern_fp_enter)(void);
67
68
69 static void (*orig_fp_enter)(void);
70
71
72 extern void nwfpe_enter(void);
73
74 static int __init fpe_init(void)
75 {
76 if (sizeof(FPA11) > sizeof(union fp_state)) {
77 pr_err("nwfpe: bad structure size\n");
78 return -EINVAL;
79 }
80
81 if (sizeof(FPREG) != 12) {
82 pr_err("nwfpe: bad register size\n");
83 return -EINVAL;
84 }
85 if (fpe_type[0] && strcmp(fpe_type, "nwfpe"))
86 return 0;
87
88
89 pr_info("NetWinder Floating Point Emulator V0.97 ("
90 NWFPE_BITS " precision)\n");
91
92 thread_register_notifier(&nwfpe_notifier_block);
93
94
95 orig_fp_enter = kern_fp_enter;
96 kern_fp_enter = nwfpe_enter;
97
98 return 0;
99 }
100
101 static void __exit fpe_exit(void)
102 {
103 thread_unregister_notifier(&nwfpe_notifier_block);
104
105 kern_fp_enter = orig_fp_enter;
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 #ifdef CONFIG_DEBUG_USER
127
128 static int debug = ~BIT_IXC;
129 #endif
130
131 void float_raise(signed char flags)
132 {
133 register unsigned int fpsr, cumulativeTraps;
134
135 #ifdef CONFIG_DEBUG_USER
136 if (flags & debug)
137 printk(KERN_DEBUG
138 "NWFPE: %s[%d] takes exception %08x at %ps from %08lx\n",
139 current->comm, current->pid, flags,
140 __builtin_return_address(0), GET_USERREG()->ARM_pc);
141 #endif
142
143
144 fpsr = readFPSR();
145 cumulativeTraps = 0;
146
147
148
149 if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC))
150 cumulativeTraps |= BIT_IXC;
151 if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC))
152 cumulativeTraps |= BIT_UFC;
153 if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC))
154 cumulativeTraps |= BIT_OFC;
155 if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC))
156 cumulativeTraps |= BIT_DZC;
157 if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC))
158 cumulativeTraps |= BIT_IOC;
159
160
161 if (cumulativeTraps)
162 writeFPSR(fpsr | cumulativeTraps);
163
164
165 if (fpsr & (flags << 16))
166 fp_send_sig(SIGFPE, current, 1);
167 }
168
169 module_init(fpe_init);
170 module_exit(fpe_exit);
171
172 MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
173 MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)");
174 MODULE_LICENSE("GPL");
175
176 #ifdef CONFIG_DEBUG_USER
177 module_param(debug, int, 0644);
178 #endif