Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #ifndef _ASM_MATH_EMU_H |
2 | #define _ASM_MATH_EMU_H | |
3 | ||
4 | #include <asm/setup.h> | |
5 | #include <linux/linkage.h> | |
6 | ||
7 | /* Status Register bits */ | |
8 | ||
9 | /* accrued exception bits */ | |
10 | #define FPSR_AEXC_INEX 3 | |
11 | #define FPSR_AEXC_DZ 4 | |
12 | #define FPSR_AEXC_UNFL 5 | |
13 | #define FPSR_AEXC_OVFL 6 | |
14 | #define FPSR_AEXC_IOP 7 | |
15 | ||
16 | /* exception status bits */ | |
17 | #define FPSR_EXC_INEX1 8 | |
18 | #define FPSR_EXC_INEX2 9 | |
19 | #define FPSR_EXC_DZ 10 | |
20 | #define FPSR_EXC_UNFL 11 | |
21 | #define FPSR_EXC_OVFL 12 | |
22 | #define FPSR_EXC_OPERR 13 | |
23 | #define FPSR_EXC_SNAN 14 | |
24 | #define FPSR_EXC_BSUN 15 | |
25 | ||
26 | /* quotient byte, assumes big-endian, of course */ | |
27 | #define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1)) | |
28 | ||
29 | /* condition code bits */ | |
30 | #define FPSR_CC_NAN 24 | |
31 | #define FPSR_CC_INF 25 | |
32 | #define FPSR_CC_Z 26 | |
33 | #define FPSR_CC_NEG 27 | |
34 | ||
35 | ||
36 | /* Control register bits */ | |
37 | ||
38 | /* rounding mode */ | |
39 | #define FPCR_ROUND_RN 0 /* round to nearest/even */ | |
40 | #define FPCR_ROUND_RZ 1 /* round to zero */ | |
41 | #define FPCR_ROUND_RM 2 /* minus infinity */ | |
42 | #define FPCR_ROUND_RP 3 /* plus infinity */ | |
43 | ||
44 | /* rounding precision */ | |
45 | #define FPCR_PRECISION_X 0 /* long double */ | |
46 | #define FPCR_PRECISION_S 1 /* double */ | |
47 | #define FPCR_PRECISION_D 2 /* float */ | |
48 | ||
49 | ||
50 | /* Flags to select the debugging output */ | |
51 | #define PDECODE 0 | |
52 | #define PEXECUTE 1 | |
53 | #define PCONV 2 | |
54 | #define PNORM 3 | |
55 | #define PREGISTER 4 | |
56 | #define PINSTR 5 | |
57 | #define PUNIMPL 6 | |
58 | #define PMOVEM 7 | |
59 | ||
60 | #define PMDECODE (1<<PDECODE) | |
61 | #define PMEXECUTE (1<<PEXECUTE) | |
62 | #define PMCONV (1<<PCONV) | |
63 | #define PMNORM (1<<PNORM) | |
64 | #define PMREGISTER (1<<PREGISTER) | |
65 | #define PMINSTR (1<<PINSTR) | |
66 | #define PMUNIMPL (1<<PUNIMPL) | |
67 | #define PMMOVEM (1<<PMOVEM) | |
68 | ||
69 | #ifndef __ASSEMBLY__ | |
70 | ||
71 | #include <linux/kernel.h> | |
72 | #include <linux/sched.h> | |
73 | ||
74 | union fp_mant64 { | |
75 | unsigned long long m64; | |
76 | unsigned long m32[2]; | |
77 | }; | |
78 | ||
79 | union fp_mant128 { | |
80 | unsigned long long m64[2]; | |
81 | unsigned long m32[4]; | |
82 | }; | |
83 | ||
84 | /* internal representation of extended fp numbers */ | |
85 | struct fp_ext { | |
86 | unsigned char lowmant; | |
87 | unsigned char sign; | |
88 | unsigned short exp; | |
89 | union fp_mant64 mant; | |
90 | }; | |
91 | ||
92 | /* C representation of FPU registers */ | |
93 | /* NOTE: if you change this, you have to change the assembler offsets | |
94 | below and the size in <asm/fpu.h>, too */ | |
95 | struct fp_data { | |
96 | struct fp_ext fpreg[8]; | |
97 | unsigned int fpcr; | |
98 | unsigned int fpsr; | |
99 | unsigned int fpiar; | |
100 | unsigned short prec; | |
101 | unsigned short rnd; | |
102 | struct fp_ext temp[2]; | |
103 | }; | |
104 | ||
105 | #if FPU_EMU_DEBUG | |
106 | extern unsigned int fp_debugprint; | |
107 | ||
108 | #define dprint(bit, fmt, args...) ({ \ | |
109 | if (fp_debugprint & (1 << (bit))) \ | |
110 | printk(fmt, ## args); \ | |
111 | }) | |
112 | #else | |
113 | #define dprint(bit, fmt, args...) | |
114 | #endif | |
115 | ||
116 | #define uprint(str) ({ \ | |
117 | static int __count = 3; \ | |
118 | \ | |
119 | if (__count > 0) { \ | |
120 | printk("You just hit an unimplemented " \ | |
121 | "fpu instruction (%s)\n", str); \ | |
122 | printk("Please report this to ....\n"); \ | |
123 | __count--; \ | |
124 | } \ | |
125 | }) | |
126 | ||
127 | #define FPDATA ((struct fp_data *)current->thread.fp) | |
128 | ||
129 | #else /* __ASSEMBLY__ */ | |
130 | ||
131 | #define FPDATA %a2 | |
132 | ||
133 | /* offsets from the base register to the floating point data in the task struct */ | |
134 | #define FPD_FPREG (TASK_THREAD+THREAD_FPREG+0) | |
135 | #define FPD_FPCR (TASK_THREAD+THREAD_FPREG+96) | |
136 | #define FPD_FPSR (TASK_THREAD+THREAD_FPREG+100) | |
137 | #define FPD_FPIAR (TASK_THREAD+THREAD_FPREG+104) | |
138 | #define FPD_PREC (TASK_THREAD+THREAD_FPREG+108) | |
139 | #define FPD_RND (TASK_THREAD+THREAD_FPREG+110) | |
140 | #define FPD_TEMPFP1 (TASK_THREAD+THREAD_FPREG+112) | |
141 | #define FPD_TEMPFP2 (TASK_THREAD+THREAD_FPREG+124) | |
142 | #define FPD_SIZEOF (TASK_THREAD+THREAD_FPREG+136) | |
143 | ||
144 | /* offsets on the stack to access saved registers, | |
145 | * these are only used during instruction decoding | |
146 | * where we always know how deep we're on the stack. | |
147 | */ | |
148 | #define FPS_DO (PT_D0) | |
149 | #define FPS_D1 (PT_D1) | |
150 | #define FPS_D2 (PT_D2) | |
151 | #define FPS_A0 (PT_A0) | |
152 | #define FPS_A1 (PT_A1) | |
153 | #define FPS_A2 (PT_A2) | |
154 | #define FPS_SR (PT_SR) | |
155 | #define FPS_PC (PT_PC) | |
156 | #define FPS_EA (PT_PC+6) | |
157 | #define FPS_PC2 (PT_PC+10) | |
158 | ||
159 | .macro fp_get_fp_reg | |
160 | lea (FPD_FPREG,FPDATA,%d0.w*4),%a0 | |
161 | lea (%a0,%d0.w*8),%a0 | |
162 | .endm | |
163 | ||
164 | /* Macros used to get/put the current program counter. | |
165 | * 020/030 use a different stack frame then 040/060, for the | |
166 | * 040/060 the return pc points already to the next location, | |
167 | * so this only needs to be modified for jump instructions. | |
168 | */ | |
169 | .macro fp_get_pc dest | |
170 | move.l (FPS_PC+4,%sp),\dest | |
171 | .endm | |
172 | ||
173 | .macro fp_put_pc src,jump=0 | |
174 | move.l \src,(FPS_PC+4,%sp) | |
175 | .endm | |
176 | ||
177 | .macro fp_get_instr_data f,s,dest,label | |
178 | getuser \f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4) | |
179 | addq.l #\s,%sp@(FPS_PC+4) | |
180 | .endm | |
181 | ||
182 | .macro fp_get_instr_word dest,label,addr | |
183 | fp_get_instr_data w,2,\dest,\label,\addr | |
184 | .endm | |
185 | ||
186 | .macro fp_get_instr_long dest,label,addr | |
187 | fp_get_instr_data l,4,\dest,\label,\addr | |
188 | .endm | |
189 | ||
190 | /* These macros are used to read from/write to user space | |
191 | * on error we jump to the fixup section, load the fault | |
192 | * address into %a0 and jump to the exit. | |
193 | * (derived from <asm/uaccess.h>) | |
194 | */ | |
195 | .macro getuser size,src,dest,label,addr | |
196 | | printf ,"[\size<%08x]",1,\addr | |
197 | .Lu1\@: moves\size \src,\dest | |
198 | ||
199 | .section .fixup,"ax" | |
200 | .even | |
201 | .Lu2\@: move.l \addr,%a0 | |
202 | jra \label | |
203 | .previous | |
204 | ||
205 | .section __ex_table,"a" | |
206 | .align 4 | |
207 | .long .Lu1\@,.Lu2\@ | |
208 | .previous | |
209 | .endm | |
210 | ||
211 | .macro putuser size,src,dest,label,addr | |
212 | | printf ,"[\size>%08x]",1,\addr | |
213 | .Lu1\@: moves\size \src,\dest | |
214 | .Lu2\@: | |
215 | ||
216 | .section .fixup,"ax" | |
217 | .even | |
218 | .Lu3\@: move.l \addr,%a0 | |
219 | jra \label | |
220 | .previous | |
221 | ||
222 | .section __ex_table,"a" | |
223 | .align 4 | |
224 | .long .Lu1\@,.Lu3\@ | |
225 | .long .Lu2\@,.Lu3\@ | |
226 | .previous | |
227 | .endm | |
228 | ||
229 | ||
230 | .macro movestack nr,arg1,arg2,arg3,arg4,arg5 | |
231 | .if \nr | |
232 | movestack (\nr-1),\arg2,\arg3,\arg4,\arg5 | |
233 | move.l \arg1,-(%sp) | |
234 | .endif | |
235 | .endm | |
236 | ||
237 | .macro printf bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5 | |
238 | #ifdef FPU_EMU_DEBUG | |
239 | .data | |
240 | .Lpdata\@: | |
241 | .string "\string" | |
242 | .previous | |
243 | ||
244 | movem.l %d0/%d1/%a0/%a1,-(%sp) | |
245 | .if \bit+1 | |
246 | #if 0 | |
247 | moveq #\bit,%d0 | |
248 | andw #7,%d0 | |
249 | btst %d0,fp_debugprint+((31-\bit)/8) | |
250 | #else | |
251 | btst #\bit,fp_debugprint+((31-\bit)/8) | |
252 | #endif | |
253 | jeq .Lpskip\@ | |
254 | .endif | |
255 | movestack \nr,\arg1,\arg2,\arg3,\arg4,\arg5 | |
256 | pea .Lpdata\@ | |
257 | jsr printk | |
258 | lea ((\nr+1)*4,%sp),%sp | |
259 | .Lpskip\@: | |
260 | movem.l (%sp)+,%d0/%d1/%a0/%a1 | |
261 | #endif | |
262 | .endm | |
263 | ||
264 | .macro printx bit,fp | |
265 | #ifdef FPU_EMU_DEBUG | |
266 | movem.l %d0/%a0,-(%sp) | |
267 | lea \fp,%a0 | |
268 | #if 0 | |
269 | moveq #'+',%d0 | |
270 | tst.w (%a0) | |
271 | jeq .Lx1\@ | |
272 | moveq #'-',%d0 | |
273 | .Lx1\@: printf \bit," %c",1,%d0 | |
274 | move.l (4,%a0),%d0 | |
275 | bclr #31,%d0 | |
276 | jne .Lx2\@ | |
277 | printf \bit,"0." | |
278 | jra .Lx3\@ | |
279 | .Lx2\@: printf \bit,"1." | |
280 | .Lx3\@: printf \bit,"%08x%08x",2,%d0,%a0@(8) | |
281 | move.w (2,%a0),%d0 | |
282 | ext.l %d0 | |
283 | printf \bit,"E%04x",1,%d0 | |
284 | #else | |
285 | printf \bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8) | |
286 | #endif | |
287 | movem.l (%sp)+,%d0/%a0 | |
288 | #endif | |
289 | .endm | |
290 | ||
291 | .macro debug instr,args | |
292 | #ifdef FPU_EMU_DEBUG | |
293 | \instr \args | |
294 | #endif | |
295 | .endm | |
296 | ||
297 | ||
298 | #endif /* __ASSEMBLY__ */ | |
299 | ||
300 | #endif /* _ASM_FRV_MATH_EMU_H */ | |
301 |