Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #ifndef _ASM_M68K_SETUP_H |
2 | #define _ASM_M68K_SETUP_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 | #ifdef FPU_EMU_DEBUG | |
106 | extern unsigned int fp_debugprint; | |
107 | ||
f0b914ae | 108 | #define dprint(bit, fmt, ...) ({ \ |
1da177e4 | 109 | if (fp_debugprint & (1 << (bit))) \ |
f0b914ae | 110 | pr_info(fmt, ##__VA_ARGS__); \ |
1da177e4 LT |
111 | }) |
112 | #else | |
f0b914ae | 113 | #define dprint(bit, fmt, ...) no_printk(fmt, ##__VA_ARGS__) |
1da177e4 LT |
114 | #endif |
115 | ||
116 | #define uprint(str) ({ \ | |
117 | static int __count = 3; \ | |
118 | \ | |
119 | if (__count > 0) { \ | |
f0b914ae | 120 | pr_err("You just hit an unimplemented " \ |
1da177e4 | 121 | "fpu instruction (%s)\n", str); \ |
f0b914ae | 122 | pr_err("Please report this to ....\n"); \ |
1da177e4 LT |
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 | */ | |
f159ee78 HC |
148 | #define FPS_DO (PT_OFF_D0) |
149 | #define FPS_D1 (PT_OFF_D1) | |
150 | #define FPS_D2 (PT_OFF_D2) | |
151 | #define FPS_A0 (PT_OFF_A0) | |
152 | #define FPS_A1 (PT_OFF_A1) | |
153 | #define FPS_A2 (PT_OFF_A2) | |
154 | #define FPS_SR (PT_OFF_SR) | |
155 | #define FPS_PC (PT_OFF_PC) | |
156 | #define FPS_EA (PT_OFF_PC+6) | |
157 | #define FPS_PC2 (PT_OFF_PC+10) | |
1da177e4 LT |
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 | ||
38135614 AV |
229 | /* work around binutils idiocy */ |
230 | old_gas=-1 | |
231 | .irp gas_ident.x .x | |
232 | old_gas=old_gas+1 | |
233 | .endr | |
234 | .if !old_gas | |
235 | .irp m b,w,l | |
236 | .macro getuser.\m src,dest,label,addr | |
237 | getuser .\m,\src,\dest,\label,\addr | |
238 | .endm | |
239 | .macro putuser.\m src,dest,label,addr | |
240 | putuser .\m,\src,\dest,\label,\addr | |
241 | .endm | |
242 | .endr | |
243 | .endif | |
1da177e4 LT |
244 | |
245 | .macro movestack nr,arg1,arg2,arg3,arg4,arg5 | |
246 | .if \nr | |
247 | movestack (\nr-1),\arg2,\arg3,\arg4,\arg5 | |
248 | move.l \arg1,-(%sp) | |
249 | .endif | |
250 | .endm | |
251 | ||
252 | .macro printf bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5 | |
253 | #ifdef FPU_EMU_DEBUG | |
254 | .data | |
255 | .Lpdata\@: | |
256 | .string "\string" | |
257 | .previous | |
258 | ||
259 | movem.l %d0/%d1/%a0/%a1,-(%sp) | |
260 | .if \bit+1 | |
261 | #if 0 | |
262 | moveq #\bit,%d0 | |
263 | andw #7,%d0 | |
264 | btst %d0,fp_debugprint+((31-\bit)/8) | |
265 | #else | |
266 | btst #\bit,fp_debugprint+((31-\bit)/8) | |
267 | #endif | |
268 | jeq .Lpskip\@ | |
269 | .endif | |
270 | movestack \nr,\arg1,\arg2,\arg3,\arg4,\arg5 | |
271 | pea .Lpdata\@ | |
272 | jsr printk | |
273 | lea ((\nr+1)*4,%sp),%sp | |
274 | .Lpskip\@: | |
275 | movem.l (%sp)+,%d0/%d1/%a0/%a1 | |
276 | #endif | |
277 | .endm | |
278 | ||
279 | .macro printx bit,fp | |
280 | #ifdef FPU_EMU_DEBUG | |
281 | movem.l %d0/%a0,-(%sp) | |
282 | lea \fp,%a0 | |
283 | #if 0 | |
284 | moveq #'+',%d0 | |
285 | tst.w (%a0) | |
286 | jeq .Lx1\@ | |
287 | moveq #'-',%d0 | |
288 | .Lx1\@: printf \bit," %c",1,%d0 | |
289 | move.l (4,%a0),%d0 | |
290 | bclr #31,%d0 | |
291 | jne .Lx2\@ | |
292 | printf \bit,"0." | |
293 | jra .Lx3\@ | |
294 | .Lx2\@: printf \bit,"1." | |
295 | .Lx3\@: printf \bit,"%08x%08x",2,%d0,%a0@(8) | |
296 | move.w (2,%a0),%d0 | |
297 | ext.l %d0 | |
298 | printf \bit,"E%04x",1,%d0 | |
299 | #else | |
300 | printf \bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8) | |
301 | #endif | |
302 | movem.l (%sp)+,%d0/%a0 | |
303 | #endif | |
304 | .endm | |
305 | ||
306 | .macro debug instr,args | |
307 | #ifdef FPU_EMU_DEBUG | |
308 | \instr \args | |
309 | #endif | |
310 | .endm | |
311 | ||
312 | ||
313 | #endif /* __ASSEMBLY__ */ | |
314 | ||
315 | #endif /* _ASM_M68K_SETUP_H */ |