diff options
Diffstat (limited to 'arch/mips/math-emu')
47 files changed, 6787 insertions, 0 deletions
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile new file mode 100644 index 000000000000..121a848a3594 --- /dev/null +++ b/arch/mips/math-emu/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # Makefile for the Linux/MIPS kernel FPU emulation. | ||
3 | # | ||
4 | |||
5 | obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ | ||
6 | ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \ | ||
7 | dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \ | ||
8 | dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \ | ||
9 | sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \ | ||
10 | sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ | ||
11 | dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o | ||
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c new file mode 100644 index 000000000000..20a552be02ee --- /dev/null +++ b/arch/mips/math-emu/cp1emu.c | |||
@@ -0,0 +1,1322 @@ | |||
1 | /* | ||
2 | * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator | ||
3 | * | ||
4 | * MIPS floating point support | ||
5 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
6 | * http://www.algor.co.uk | ||
7 | * | ||
8 | * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com | ||
9 | * Copyright (C) 2000 MIPS Technologies, Inc. | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * A complete emulator for MIPS coprocessor 1 instructions. This is | ||
25 | * required for #float(switch) or #float(trap), where it catches all | ||
26 | * COP1 instructions via the "CoProcessor Unusable" exception. | ||
27 | * | ||
28 | * More surprisingly it is also required for #float(ieee), to help out | ||
29 | * the hardware fpu at the boundaries of the IEEE-754 representation | ||
30 | * (denormalised values, infinities, underflow, etc). It is made | ||
31 | * quite nasty because emulation of some non-COP1 instructions is | ||
32 | * required, e.g. in branch delay slots. | ||
33 | * | ||
34 | * Note if you know that you won't have an fpu, then you'll get much | ||
35 | * better performance by compiling with -msoft-float! | ||
36 | */ | ||
37 | #include <linux/sched.h> | ||
38 | |||
39 | #include <asm/inst.h> | ||
40 | #include <asm/bootinfo.h> | ||
41 | #include <asm/cpu.h> | ||
42 | #include <asm/cpu-features.h> | ||
43 | #include <asm/processor.h> | ||
44 | #include <asm/ptrace.h> | ||
45 | #include <asm/signal.h> | ||
46 | #include <asm/mipsregs.h> | ||
47 | #include <asm/fpu_emulator.h> | ||
48 | #include <asm/uaccess.h> | ||
49 | #include <asm/branch.h> | ||
50 | |||
51 | #include "ieee754.h" | ||
52 | #include "dsemul.h" | ||
53 | |||
54 | /* Strap kernel emulator for full MIPS IV emulation */ | ||
55 | |||
56 | #ifdef __mips | ||
57 | #undef __mips | ||
58 | #endif | ||
59 | #define __mips 4 | ||
60 | |||
61 | /* Function which emulates a floating point instruction. */ | ||
62 | |||
63 | static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *, | ||
64 | mips_instruction); | ||
65 | |||
66 | #if __mips >= 4 && __mips != 32 | ||
67 | static int fpux_emu(struct pt_regs *, | ||
68 | struct mips_fpu_soft_struct *, mips_instruction); | ||
69 | #endif | ||
70 | |||
71 | /* Further private data for which no space exists in mips_fpu_soft_struct */ | ||
72 | |||
73 | struct mips_fpu_emulator_private fpuemuprivate; | ||
74 | |||
75 | /* Control registers */ | ||
76 | |||
77 | #define FPCREG_RID 0 /* $0 = revision id */ | ||
78 | #define FPCREG_CSR 31 /* $31 = csr */ | ||
79 | |||
80 | /* Convert Mips rounding mode (0..3) to IEEE library modes. */ | ||
81 | static const unsigned char ieee_rm[4] = { | ||
82 | IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD | ||
83 | }; | ||
84 | |||
85 | #if __mips >= 4 | ||
86 | /* convert condition code register number to csr bit */ | ||
87 | static const unsigned int fpucondbit[8] = { | ||
88 | FPU_CSR_COND0, | ||
89 | FPU_CSR_COND1, | ||
90 | FPU_CSR_COND2, | ||
91 | FPU_CSR_COND3, | ||
92 | FPU_CSR_COND4, | ||
93 | FPU_CSR_COND5, | ||
94 | FPU_CSR_COND6, | ||
95 | FPU_CSR_COND7 | ||
96 | }; | ||
97 | #endif | ||
98 | |||
99 | |||
100 | /* | ||
101 | * Redundant with logic already in kernel/branch.c, | ||
102 | * embedded in compute_return_epc. At some point, | ||
103 | * a single subroutine should be used across both | ||
104 | * modules. | ||
105 | */ | ||
106 | static int isBranchInstr(mips_instruction * i) | ||
107 | { | ||
108 | switch (MIPSInst_OPCODE(*i)) { | ||
109 | case spec_op: | ||
110 | switch (MIPSInst_FUNC(*i)) { | ||
111 | case jalr_op: | ||
112 | case jr_op: | ||
113 | return 1; | ||
114 | } | ||
115 | break; | ||
116 | |||
117 | case bcond_op: | ||
118 | switch (MIPSInst_RT(*i)) { | ||
119 | case bltz_op: | ||
120 | case bgez_op: | ||
121 | case bltzl_op: | ||
122 | case bgezl_op: | ||
123 | case bltzal_op: | ||
124 | case bgezal_op: | ||
125 | case bltzall_op: | ||
126 | case bgezall_op: | ||
127 | return 1; | ||
128 | } | ||
129 | break; | ||
130 | |||
131 | case j_op: | ||
132 | case jal_op: | ||
133 | case jalx_op: | ||
134 | case beq_op: | ||
135 | case bne_op: | ||
136 | case blez_op: | ||
137 | case bgtz_op: | ||
138 | case beql_op: | ||
139 | case bnel_op: | ||
140 | case blezl_op: | ||
141 | case bgtzl_op: | ||
142 | return 1; | ||
143 | |||
144 | case cop0_op: | ||
145 | case cop1_op: | ||
146 | case cop2_op: | ||
147 | case cop1x_op: | ||
148 | if (MIPSInst_RS(*i) == bc_op) | ||
149 | return 1; | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * In the Linux kernel, we support selection of FPR format on the | ||
158 | * basis of the Status.FR bit. This does imply that, if a full 32 | ||
159 | * FPRs are desired, there needs to be a flip-flop that can be written | ||
160 | * to one at that bit position. In any case, O32 MIPS ABI uses | ||
161 | * only the even FPRs (Status.FR = 0). | ||
162 | */ | ||
163 | |||
164 | #define CP0_STATUS_FR_SUPPORT | ||
165 | |||
166 | #ifdef CP0_STATUS_FR_SUPPORT | ||
167 | #define FR_BIT ST0_FR | ||
168 | #else | ||
169 | #define FR_BIT 0 | ||
170 | #endif | ||
171 | |||
172 | #define SIFROMREG(si,x) ((si) = \ | ||
173 | (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ | ||
174 | (int)ctx->fpr[x] : \ | ||
175 | (int)(ctx->fpr[x & ~1] >> 32 )) | ||
176 | #define SITOREG(si,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \ | ||
177 | (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ | ||
178 | ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \ | ||
179 | ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32) | ||
180 | |||
181 | #define DIFROMREG(di,x) ((di) = \ | ||
182 | ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)]) | ||
183 | #define DITOREG(di,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] \ | ||
184 | = (di)) | ||
185 | |||
186 | #define SPFROMREG(sp,x) SIFROMREG((sp).bits,x) | ||
187 | #define SPTOREG(sp,x) SITOREG((sp).bits,x) | ||
188 | #define DPFROMREG(dp,x) DIFROMREG((dp).bits,x) | ||
189 | #define DPTOREG(dp,x) DITOREG((dp).bits,x) | ||
190 | |||
191 | /* | ||
192 | * Emulate the single floating point instruction pointed at by EPC. | ||
193 | * Two instructions if the instruction is in a branch delay slot. | ||
194 | */ | ||
195 | |||
196 | static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx) | ||
197 | { | ||
198 | mips_instruction ir; | ||
199 | vaddr_t emulpc, contpc; | ||
200 | unsigned int cond; | ||
201 | |||
202 | if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) { | ||
203 | fpuemuprivate.stats.errors++; | ||
204 | return SIGBUS; | ||
205 | } | ||
206 | |||
207 | /* XXX NEC Vr54xx bug workaround */ | ||
208 | if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) | ||
209 | xcp->cp0_cause &= ~CAUSEF_BD; | ||
210 | |||
211 | if (xcp->cp0_cause & CAUSEF_BD) { | ||
212 | /* | ||
213 | * The instruction to be emulated is in a branch delay slot | ||
214 | * which means that we have to emulate the branch instruction | ||
215 | * BEFORE we do the cop1 instruction. | ||
216 | * | ||
217 | * This branch could be a COP1 branch, but in that case we | ||
218 | * would have had a trap for that instruction, and would not | ||
219 | * come through this route. | ||
220 | * | ||
221 | * Linux MIPS branch emulator operates on context, updating the | ||
222 | * cp0_epc. | ||
223 | */ | ||
224 | emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */ | ||
225 | |||
226 | if (__compute_return_epc(xcp)) { | ||
227 | #ifdef CP1DBG | ||
228 | printk("failed to emulate branch at %p\n", | ||
229 | REG_TO_VA(xcp->cp0_epc)); | ||
230 | #endif | ||
231 | return SIGILL; | ||
232 | } | ||
233 | if (get_user(ir, (mips_instruction *) emulpc)) { | ||
234 | fpuemuprivate.stats.errors++; | ||
235 | return SIGBUS; | ||
236 | } | ||
237 | /* __compute_return_epc() will have updated cp0_epc */ | ||
238 | contpc = REG_TO_VA xcp->cp0_epc; | ||
239 | /* In order not to confuse ptrace() et al, tweak context */ | ||
240 | xcp->cp0_epc = VA_TO_REG emulpc - 4; | ||
241 | } | ||
242 | else { | ||
243 | emulpc = REG_TO_VA xcp->cp0_epc; | ||
244 | contpc = REG_TO_VA(xcp->cp0_epc + 4); | ||
245 | } | ||
246 | |||
247 | emul: | ||
248 | fpuemuprivate.stats.emulated++; | ||
249 | switch (MIPSInst_OPCODE(ir)) { | ||
250 | #ifndef SINGLE_ONLY_FPU | ||
251 | case ldc1_op:{ | ||
252 | u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + | ||
253 | MIPSInst_SIMM(ir)); | ||
254 | u64 val; | ||
255 | |||
256 | fpuemuprivate.stats.loads++; | ||
257 | if (get_user(val, va)) { | ||
258 | fpuemuprivate.stats.errors++; | ||
259 | return SIGBUS; | ||
260 | } | ||
261 | DITOREG(val, MIPSInst_RT(ir)); | ||
262 | break; | ||
263 | } | ||
264 | |||
265 | case sdc1_op:{ | ||
266 | u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + | ||
267 | MIPSInst_SIMM(ir)); | ||
268 | u64 val; | ||
269 | |||
270 | fpuemuprivate.stats.stores++; | ||
271 | DIFROMREG(val, MIPSInst_RT(ir)); | ||
272 | if (put_user(val, va)) { | ||
273 | fpuemuprivate.stats.errors++; | ||
274 | return SIGBUS; | ||
275 | } | ||
276 | break; | ||
277 | } | ||
278 | #endif | ||
279 | |||
280 | case lwc1_op:{ | ||
281 | u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + | ||
282 | MIPSInst_SIMM(ir)); | ||
283 | u32 val; | ||
284 | |||
285 | fpuemuprivate.stats.loads++; | ||
286 | if (get_user(val, va)) { | ||
287 | fpuemuprivate.stats.errors++; | ||
288 | return SIGBUS; | ||
289 | } | ||
290 | #ifdef SINGLE_ONLY_FPU | ||
291 | if (MIPSInst_RT(ir) & 1) { | ||
292 | /* illegal register in single-float mode */ | ||
293 | return SIGILL; | ||
294 | } | ||
295 | #endif | ||
296 | SITOREG(val, MIPSInst_RT(ir)); | ||
297 | break; | ||
298 | } | ||
299 | |||
300 | case swc1_op:{ | ||
301 | u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + | ||
302 | MIPSInst_SIMM(ir)); | ||
303 | u32 val; | ||
304 | |||
305 | fpuemuprivate.stats.stores++; | ||
306 | #ifdef SINGLE_ONLY_FPU | ||
307 | if (MIPSInst_RT(ir) & 1) { | ||
308 | /* illegal register in single-float mode */ | ||
309 | return SIGILL; | ||
310 | } | ||
311 | #endif | ||
312 | SIFROMREG(val, MIPSInst_RT(ir)); | ||
313 | if (put_user(val, va)) { | ||
314 | fpuemuprivate.stats.errors++; | ||
315 | return SIGBUS; | ||
316 | } | ||
317 | break; | ||
318 | } | ||
319 | |||
320 | case cop1_op: | ||
321 | switch (MIPSInst_RS(ir)) { | ||
322 | |||
323 | #if __mips64 && !defined(SINGLE_ONLY_FPU) | ||
324 | case dmfc_op: | ||
325 | /* copregister fs -> gpr[rt] */ | ||
326 | if (MIPSInst_RT(ir) != 0) { | ||
327 | DIFROMREG(xcp->regs[MIPSInst_RT(ir)], | ||
328 | MIPSInst_RD(ir)); | ||
329 | } | ||
330 | break; | ||
331 | |||
332 | case dmtc_op: | ||
333 | /* copregister fs <- rt */ | ||
334 | DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); | ||
335 | break; | ||
336 | #endif | ||
337 | |||
338 | case mfc_op: | ||
339 | /* copregister rd -> gpr[rt] */ | ||
340 | #ifdef SINGLE_ONLY_FPU | ||
341 | if (MIPSInst_RD(ir) & 1) { | ||
342 | /* illegal register in single-float mode */ | ||
343 | return SIGILL; | ||
344 | } | ||
345 | #endif | ||
346 | if (MIPSInst_RT(ir) != 0) { | ||
347 | SIFROMREG(xcp->regs[MIPSInst_RT(ir)], | ||
348 | MIPSInst_RD(ir)); | ||
349 | } | ||
350 | break; | ||
351 | |||
352 | case mtc_op: | ||
353 | /* copregister rd <- rt */ | ||
354 | #ifdef SINGLE_ONLY_FPU | ||
355 | if (MIPSInst_RD(ir) & 1) { | ||
356 | /* illegal register in single-float mode */ | ||
357 | return SIGILL; | ||
358 | } | ||
359 | #endif | ||
360 | SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); | ||
361 | break; | ||
362 | |||
363 | case cfc_op:{ | ||
364 | /* cop control register rd -> gpr[rt] */ | ||
365 | u32 value; | ||
366 | |||
367 | if (ir == CP1UNDEF) { | ||
368 | return do_dsemulret(xcp); | ||
369 | } | ||
370 | if (MIPSInst_RD(ir) == FPCREG_CSR) { | ||
371 | value = ctx->fcr31; | ||
372 | #ifdef CSRTRACE | ||
373 | printk("%p gpr[%d]<-csr=%08x\n", | ||
374 | REG_TO_VA(xcp->cp0_epc), | ||
375 | MIPSInst_RT(ir), value); | ||
376 | #endif | ||
377 | } | ||
378 | else if (MIPSInst_RD(ir) == FPCREG_RID) | ||
379 | value = 0; | ||
380 | else | ||
381 | value = 0; | ||
382 | if (MIPSInst_RT(ir)) | ||
383 | xcp->regs[MIPSInst_RT(ir)] = value; | ||
384 | break; | ||
385 | } | ||
386 | |||
387 | case ctc_op:{ | ||
388 | /* copregister rd <- rt */ | ||
389 | u32 value; | ||
390 | |||
391 | if (MIPSInst_RT(ir) == 0) | ||
392 | value = 0; | ||
393 | else | ||
394 | value = xcp->regs[MIPSInst_RT(ir)]; | ||
395 | |||
396 | /* we only have one writable control reg | ||
397 | */ | ||
398 | if (MIPSInst_RD(ir) == FPCREG_CSR) { | ||
399 | #ifdef CSRTRACE | ||
400 | printk("%p gpr[%d]->csr=%08x\n", | ||
401 | REG_TO_VA(xcp->cp0_epc), | ||
402 | MIPSInst_RT(ir), value); | ||
403 | #endif | ||
404 | ctx->fcr31 = value; | ||
405 | /* copy new rounding mode and | ||
406 | flush bit to ieee library state! */ | ||
407 | ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0; | ||
408 | ieee754_csr.rm = ieee_rm[value & 0x3]; | ||
409 | } | ||
410 | if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { | ||
411 | return SIGFPE; | ||
412 | } | ||
413 | break; | ||
414 | } | ||
415 | |||
416 | case bc_op:{ | ||
417 | int likely = 0; | ||
418 | |||
419 | if (xcp->cp0_cause & CAUSEF_BD) | ||
420 | return SIGILL; | ||
421 | |||
422 | #if __mips >= 4 | ||
423 | cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2]; | ||
424 | #else | ||
425 | cond = ctx->fcr31 & FPU_CSR_COND; | ||
426 | #endif | ||
427 | switch (MIPSInst_RT(ir) & 3) { | ||
428 | case bcfl_op: | ||
429 | likely = 1; | ||
430 | case bcf_op: | ||
431 | cond = !cond; | ||
432 | break; | ||
433 | case bctl_op: | ||
434 | likely = 1; | ||
435 | case bct_op: | ||
436 | break; | ||
437 | default: | ||
438 | /* thats an illegal instruction */ | ||
439 | return SIGILL; | ||
440 | } | ||
441 | |||
442 | xcp->cp0_cause |= CAUSEF_BD; | ||
443 | if (cond) { | ||
444 | /* branch taken: emulate dslot | ||
445 | * instruction | ||
446 | */ | ||
447 | xcp->cp0_epc += 4; | ||
448 | contpc = REG_TO_VA | ||
449 | (xcp->cp0_epc + | ||
450 | (MIPSInst_SIMM(ir) << 2)); | ||
451 | |||
452 | if (get_user(ir, (mips_instruction *) | ||
453 | REG_TO_VA xcp->cp0_epc)) { | ||
454 | fpuemuprivate.stats.errors++; | ||
455 | return SIGBUS; | ||
456 | } | ||
457 | |||
458 | switch (MIPSInst_OPCODE(ir)) { | ||
459 | case lwc1_op: | ||
460 | case swc1_op: | ||
461 | #if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU) | ||
462 | case ldc1_op: | ||
463 | case sdc1_op: | ||
464 | #endif | ||
465 | case cop1_op: | ||
466 | #if __mips >= 4 && __mips != 32 | ||
467 | case cop1x_op: | ||
468 | #endif | ||
469 | /* its one of ours */ | ||
470 | goto emul; | ||
471 | #if __mips >= 4 | ||
472 | case spec_op: | ||
473 | if (MIPSInst_FUNC(ir) == movc_op) | ||
474 | goto emul; | ||
475 | break; | ||
476 | #endif | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * Single step the non-cp1 | ||
481 | * instruction in the dslot | ||
482 | */ | ||
483 | return mips_dsemul(xcp, ir, VA_TO_REG contpc); | ||
484 | } | ||
485 | else { | ||
486 | /* branch not taken */ | ||
487 | if (likely) { | ||
488 | /* | ||
489 | * branch likely nullifies | ||
490 | * dslot if not taken | ||
491 | */ | ||
492 | xcp->cp0_epc += 4; | ||
493 | contpc += 4; | ||
494 | /* | ||
495 | * else continue & execute | ||
496 | * dslot as normal insn | ||
497 | */ | ||
498 | } | ||
499 | } | ||
500 | break; | ||
501 | } | ||
502 | |||
503 | default: | ||
504 | if (!(MIPSInst_RS(ir) & 0x10)) | ||
505 | return SIGILL; | ||
506 | { | ||
507 | int sig; | ||
508 | |||
509 | /* a real fpu computation instruction */ | ||
510 | if ((sig = fpu_emu(xcp, ctx, ir))) | ||
511 | return sig; | ||
512 | } | ||
513 | } | ||
514 | break; | ||
515 | |||
516 | #if __mips >= 4 && __mips != 32 | ||
517 | case cop1x_op:{ | ||
518 | int sig; | ||
519 | |||
520 | if ((sig = fpux_emu(xcp, ctx, ir))) | ||
521 | return sig; | ||
522 | break; | ||
523 | } | ||
524 | #endif | ||
525 | |||
526 | #if __mips >= 4 | ||
527 | case spec_op: | ||
528 | if (MIPSInst_FUNC(ir) != movc_op) | ||
529 | return SIGILL; | ||
530 | cond = fpucondbit[MIPSInst_RT(ir) >> 2]; | ||
531 | if (((ctx->fcr31 & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0)) | ||
532 | xcp->regs[MIPSInst_RD(ir)] = | ||
533 | xcp->regs[MIPSInst_RS(ir)]; | ||
534 | break; | ||
535 | #endif | ||
536 | |||
537 | default: | ||
538 | return SIGILL; | ||
539 | } | ||
540 | |||
541 | /* we did it !! */ | ||
542 | xcp->cp0_epc = VA_TO_REG(contpc); | ||
543 | xcp->cp0_cause &= ~CAUSEF_BD; | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | /* | ||
548 | * Conversion table from MIPS compare ops 48-63 | ||
549 | * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig); | ||
550 | */ | ||
551 | static const unsigned char cmptab[8] = { | ||
552 | 0, /* cmp_0 (sig) cmp_sf */ | ||
553 | IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ | ||
554 | IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ | ||
555 | IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ | ||
556 | IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ | ||
557 | IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ | ||
558 | IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ | ||
559 | IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ | ||
560 | }; | ||
561 | |||
562 | |||
563 | #if __mips >= 4 && __mips != 32 | ||
564 | |||
565 | /* | ||
566 | * Additional MIPS4 instructions | ||
567 | */ | ||
568 | |||
569 | #define DEF3OP(name, p, f1, f2, f3) \ | ||
570 | static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \ | ||
571 | ieee754##p t) \ | ||
572 | { \ | ||
573 | struct ieee754_csr ieee754_csr_save; \ | ||
574 | s = f1 (s, t); \ | ||
575 | ieee754_csr_save = ieee754_csr; \ | ||
576 | s = f2 (s, r); \ | ||
577 | ieee754_csr_save.cx |= ieee754_csr.cx; \ | ||
578 | ieee754_csr_save.sx |= ieee754_csr.sx; \ | ||
579 | s = f3 (s); \ | ||
580 | ieee754_csr.cx |= ieee754_csr_save.cx; \ | ||
581 | ieee754_csr.sx |= ieee754_csr_save.sx; \ | ||
582 | return s; \ | ||
583 | } | ||
584 | |||
585 | static ieee754dp fpemu_dp_recip(ieee754dp d) | ||
586 | { | ||
587 | return ieee754dp_div(ieee754dp_one(0), d); | ||
588 | } | ||
589 | |||
590 | static ieee754dp fpemu_dp_rsqrt(ieee754dp d) | ||
591 | { | ||
592 | return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d)); | ||
593 | } | ||
594 | |||
595 | static ieee754sp fpemu_sp_recip(ieee754sp s) | ||
596 | { | ||
597 | return ieee754sp_div(ieee754sp_one(0), s); | ||
598 | } | ||
599 | |||
600 | static ieee754sp fpemu_sp_rsqrt(ieee754sp s) | ||
601 | { | ||
602 | return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); | ||
603 | } | ||
604 | |||
605 | DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,); | ||
606 | DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,); | ||
607 | DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg); | ||
608 | DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg); | ||
609 | DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,); | ||
610 | DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,); | ||
611 | DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); | ||
612 | DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); | ||
613 | |||
614 | static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, | ||
615 | mips_instruction ir) | ||
616 | { | ||
617 | unsigned rcsr = 0; /* resulting csr */ | ||
618 | |||
619 | fpuemuprivate.stats.cp1xops++; | ||
620 | |||
621 | switch (MIPSInst_FMA_FFMT(ir)) { | ||
622 | case s_fmt:{ /* 0 */ | ||
623 | |||
624 | ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); | ||
625 | ieee754sp fd, fr, fs, ft; | ||
626 | u32 *va; | ||
627 | u32 val; | ||
628 | |||
629 | switch (MIPSInst_FUNC(ir)) { | ||
630 | case lwxc1_op: | ||
631 | va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + | ||
632 | xcp->regs[MIPSInst_FT(ir)]); | ||
633 | |||
634 | fpuemuprivate.stats.loads++; | ||
635 | if (get_user(val, va)) { | ||
636 | fpuemuprivate.stats.errors++; | ||
637 | return SIGBUS; | ||
638 | } | ||
639 | #ifdef SINGLE_ONLY_FPU | ||
640 | if (MIPSInst_FD(ir) & 1) { | ||
641 | /* illegal register in single-float | ||
642 | * mode | ||
643 | */ | ||
644 | return SIGILL; | ||
645 | } | ||
646 | #endif | ||
647 | SITOREG(val, MIPSInst_FD(ir)); | ||
648 | break; | ||
649 | |||
650 | case swxc1_op: | ||
651 | va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + | ||
652 | xcp->regs[MIPSInst_FT(ir)]); | ||
653 | |||
654 | fpuemuprivate.stats.stores++; | ||
655 | #ifdef SINGLE_ONLY_FPU | ||
656 | if (MIPSInst_FS(ir) & 1) { | ||
657 | /* illegal register in single-float | ||
658 | * mode | ||
659 | */ | ||
660 | return SIGILL; | ||
661 | } | ||
662 | #endif | ||
663 | |||
664 | SIFROMREG(val, MIPSInst_FS(ir)); | ||
665 | if (put_user(val, va)) { | ||
666 | fpuemuprivate.stats.errors++; | ||
667 | return SIGBUS; | ||
668 | } | ||
669 | break; | ||
670 | |||
671 | case madd_s_op: | ||
672 | handler = fpemu_sp_madd; | ||
673 | goto scoptop; | ||
674 | case msub_s_op: | ||
675 | handler = fpemu_sp_msub; | ||
676 | goto scoptop; | ||
677 | case nmadd_s_op: | ||
678 | handler = fpemu_sp_nmadd; | ||
679 | goto scoptop; | ||
680 | case nmsub_s_op: | ||
681 | handler = fpemu_sp_nmsub; | ||
682 | goto scoptop; | ||
683 | |||
684 | scoptop: | ||
685 | SPFROMREG(fr, MIPSInst_FR(ir)); | ||
686 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
687 | SPFROMREG(ft, MIPSInst_FT(ir)); | ||
688 | fd = (*handler) (fr, fs, ft); | ||
689 | SPTOREG(fd, MIPSInst_FD(ir)); | ||
690 | |||
691 | copcsr: | ||
692 | if (ieee754_cxtest(IEEE754_INEXACT)) | ||
693 | rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; | ||
694 | if (ieee754_cxtest(IEEE754_UNDERFLOW)) | ||
695 | rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; | ||
696 | if (ieee754_cxtest(IEEE754_OVERFLOW)) | ||
697 | rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; | ||
698 | if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) | ||
699 | rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; | ||
700 | |||
701 | ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; | ||
702 | if (ieee754_csr.nod) | ||
703 | ctx->fcr31 |= 0x1000000; | ||
704 | if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { | ||
705 | /*printk ("SIGFPE: fpu csr = %08x\n", | ||
706 | ctx->fcr31); */ | ||
707 | return SIGFPE; | ||
708 | } | ||
709 | |||
710 | break; | ||
711 | |||
712 | default: | ||
713 | return SIGILL; | ||
714 | } | ||
715 | break; | ||
716 | } | ||
717 | |||
718 | #ifndef SINGLE_ONLY_FPU | ||
719 | case d_fmt:{ /* 1 */ | ||
720 | ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp); | ||
721 | ieee754dp fd, fr, fs, ft; | ||
722 | u64 *va; | ||
723 | u64 val; | ||
724 | |||
725 | switch (MIPSInst_FUNC(ir)) { | ||
726 | case ldxc1_op: | ||
727 | va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + | ||
728 | xcp->regs[MIPSInst_FT(ir)]); | ||
729 | |||
730 | fpuemuprivate.stats.loads++; | ||
731 | if (get_user(val, va)) { | ||
732 | fpuemuprivate.stats.errors++; | ||
733 | return SIGBUS; | ||
734 | } | ||
735 | DITOREG(val, MIPSInst_FD(ir)); | ||
736 | break; | ||
737 | |||
738 | case sdxc1_op: | ||
739 | va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + | ||
740 | xcp->regs[MIPSInst_FT(ir)]); | ||
741 | |||
742 | fpuemuprivate.stats.stores++; | ||
743 | DIFROMREG(val, MIPSInst_FS(ir)); | ||
744 | if (put_user(val, va)) { | ||
745 | fpuemuprivate.stats.errors++; | ||
746 | return SIGBUS; | ||
747 | } | ||
748 | break; | ||
749 | |||
750 | case madd_d_op: | ||
751 | handler = fpemu_dp_madd; | ||
752 | goto dcoptop; | ||
753 | case msub_d_op: | ||
754 | handler = fpemu_dp_msub; | ||
755 | goto dcoptop; | ||
756 | case nmadd_d_op: | ||
757 | handler = fpemu_dp_nmadd; | ||
758 | goto dcoptop; | ||
759 | case nmsub_d_op: | ||
760 | handler = fpemu_dp_nmsub; | ||
761 | goto dcoptop; | ||
762 | |||
763 | dcoptop: | ||
764 | DPFROMREG(fr, MIPSInst_FR(ir)); | ||
765 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
766 | DPFROMREG(ft, MIPSInst_FT(ir)); | ||
767 | fd = (*handler) (fr, fs, ft); | ||
768 | DPTOREG(fd, MIPSInst_FD(ir)); | ||
769 | goto copcsr; | ||
770 | |||
771 | default: | ||
772 | return SIGILL; | ||
773 | } | ||
774 | break; | ||
775 | } | ||
776 | #endif | ||
777 | |||
778 | case 0x7: /* 7 */ | ||
779 | if (MIPSInst_FUNC(ir) != pfetch_op) { | ||
780 | return SIGILL; | ||
781 | } | ||
782 | /* ignore prefx operation */ | ||
783 | break; | ||
784 | |||
785 | default: | ||
786 | return SIGILL; | ||
787 | } | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | #endif | ||
792 | |||
793 | |||
794 | |||
795 | /* | ||
796 | * Emulate a single COP1 arithmetic instruction. | ||
797 | */ | ||
798 | static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, | ||
799 | mips_instruction ir) | ||
800 | { | ||
801 | int rfmt; /* resulting format */ | ||
802 | unsigned rcsr = 0; /* resulting csr */ | ||
803 | unsigned cond; | ||
804 | union { | ||
805 | ieee754dp d; | ||
806 | ieee754sp s; | ||
807 | int w; | ||
808 | #if __mips64 | ||
809 | s64 l; | ||
810 | #endif | ||
811 | } rv; /* resulting value */ | ||
812 | |||
813 | fpuemuprivate.stats.cp1ops++; | ||
814 | switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { | ||
815 | case s_fmt:{ /* 0 */ | ||
816 | union { | ||
817 | ieee754sp(*b) (ieee754sp, ieee754sp); | ||
818 | ieee754sp(*u) (ieee754sp); | ||
819 | } handler; | ||
820 | |||
821 | switch (MIPSInst_FUNC(ir)) { | ||
822 | /* binary ops */ | ||
823 | case fadd_op: | ||
824 | handler.b = ieee754sp_add; | ||
825 | goto scopbop; | ||
826 | case fsub_op: | ||
827 | handler.b = ieee754sp_sub; | ||
828 | goto scopbop; | ||
829 | case fmul_op: | ||
830 | handler.b = ieee754sp_mul; | ||
831 | goto scopbop; | ||
832 | case fdiv_op: | ||
833 | handler.b = ieee754sp_div; | ||
834 | goto scopbop; | ||
835 | |||
836 | /* unary ops */ | ||
837 | #if __mips >= 2 || __mips64 | ||
838 | case fsqrt_op: | ||
839 | handler.u = ieee754sp_sqrt; | ||
840 | goto scopuop; | ||
841 | #endif | ||
842 | #if __mips >= 4 && __mips != 32 | ||
843 | case frsqrt_op: | ||
844 | handler.u = fpemu_sp_rsqrt; | ||
845 | goto scopuop; | ||
846 | case frecip_op: | ||
847 | handler.u = fpemu_sp_recip; | ||
848 | goto scopuop; | ||
849 | #endif | ||
850 | #if __mips >= 4 | ||
851 | case fmovc_op: | ||
852 | cond = fpucondbit[MIPSInst_FT(ir) >> 2]; | ||
853 | if (((ctx->fcr31 & cond) != 0) != | ||
854 | ((MIPSInst_FT(ir) & 1) != 0)) | ||
855 | return 0; | ||
856 | SPFROMREG(rv.s, MIPSInst_FS(ir)); | ||
857 | break; | ||
858 | case fmovz_op: | ||
859 | if (xcp->regs[MIPSInst_FT(ir)] != 0) | ||
860 | return 0; | ||
861 | SPFROMREG(rv.s, MIPSInst_FS(ir)); | ||
862 | break; | ||
863 | case fmovn_op: | ||
864 | if (xcp->regs[MIPSInst_FT(ir)] == 0) | ||
865 | return 0; | ||
866 | SPFROMREG(rv.s, MIPSInst_FS(ir)); | ||
867 | break; | ||
868 | #endif | ||
869 | case fabs_op: | ||
870 | handler.u = ieee754sp_abs; | ||
871 | goto scopuop; | ||
872 | case fneg_op: | ||
873 | handler.u = ieee754sp_neg; | ||
874 | goto scopuop; | ||
875 | case fmov_op: | ||
876 | /* an easy one */ | ||
877 | SPFROMREG(rv.s, MIPSInst_FS(ir)); | ||
878 | goto copcsr; | ||
879 | |||
880 | /* binary op on handler */ | ||
881 | scopbop: | ||
882 | { | ||
883 | ieee754sp fs, ft; | ||
884 | |||
885 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
886 | SPFROMREG(ft, MIPSInst_FT(ir)); | ||
887 | |||
888 | rv.s = (*handler.b) (fs, ft); | ||
889 | goto copcsr; | ||
890 | } | ||
891 | scopuop: | ||
892 | { | ||
893 | ieee754sp fs; | ||
894 | |||
895 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
896 | rv.s = (*handler.u) (fs); | ||
897 | goto copcsr; | ||
898 | } | ||
899 | copcsr: | ||
900 | if (ieee754_cxtest(IEEE754_INEXACT)) | ||
901 | rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; | ||
902 | if (ieee754_cxtest(IEEE754_UNDERFLOW)) | ||
903 | rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; | ||
904 | if (ieee754_cxtest(IEEE754_OVERFLOW)) | ||
905 | rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; | ||
906 | if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) | ||
907 | rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; | ||
908 | if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) | ||
909 | rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; | ||
910 | break; | ||
911 | |||
912 | /* unary conv ops */ | ||
913 | case fcvts_op: | ||
914 | return SIGILL; /* not defined */ | ||
915 | case fcvtd_op:{ | ||
916 | #ifdef SINGLE_ONLY_FPU | ||
917 | return SIGILL; /* not defined */ | ||
918 | #else | ||
919 | ieee754sp fs; | ||
920 | |||
921 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
922 | rv.d = ieee754dp_fsp(fs); | ||
923 | rfmt = d_fmt; | ||
924 | goto copcsr; | ||
925 | } | ||
926 | #endif | ||
927 | case fcvtw_op:{ | ||
928 | ieee754sp fs; | ||
929 | |||
930 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
931 | rv.w = ieee754sp_tint(fs); | ||
932 | rfmt = w_fmt; | ||
933 | goto copcsr; | ||
934 | } | ||
935 | |||
936 | #if __mips >= 2 || __mips64 | ||
937 | case fround_op: | ||
938 | case ftrunc_op: | ||
939 | case fceil_op: | ||
940 | case ffloor_op:{ | ||
941 | unsigned int oldrm = ieee754_csr.rm; | ||
942 | ieee754sp fs; | ||
943 | |||
944 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
945 | ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; | ||
946 | rv.w = ieee754sp_tint(fs); | ||
947 | ieee754_csr.rm = oldrm; | ||
948 | rfmt = w_fmt; | ||
949 | goto copcsr; | ||
950 | } | ||
951 | #endif /* __mips >= 2 */ | ||
952 | |||
953 | #if __mips64 && !defined(SINGLE_ONLY_FPU) | ||
954 | case fcvtl_op:{ | ||
955 | ieee754sp fs; | ||
956 | |||
957 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
958 | rv.l = ieee754sp_tlong(fs); | ||
959 | rfmt = l_fmt; | ||
960 | goto copcsr; | ||
961 | } | ||
962 | |||
963 | case froundl_op: | ||
964 | case ftruncl_op: | ||
965 | case fceill_op: | ||
966 | case ffloorl_op:{ | ||
967 | unsigned int oldrm = ieee754_csr.rm; | ||
968 | ieee754sp fs; | ||
969 | |||
970 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
971 | ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; | ||
972 | rv.l = ieee754sp_tlong(fs); | ||
973 | ieee754_csr.rm = oldrm; | ||
974 | rfmt = l_fmt; | ||
975 | goto copcsr; | ||
976 | } | ||
977 | #endif /* __mips64 && !fpu(single) */ | ||
978 | |||
979 | default: | ||
980 | if (MIPSInst_FUNC(ir) >= fcmp_op) { | ||
981 | unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; | ||
982 | ieee754sp fs, ft; | ||
983 | |||
984 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
985 | SPFROMREG(ft, MIPSInst_FT(ir)); | ||
986 | rv.w = ieee754sp_cmp(fs, ft, | ||
987 | cmptab[cmpop & 0x7], cmpop & 0x8); | ||
988 | rfmt = -1; | ||
989 | if ((cmpop & 0x8) && ieee754_cxtest | ||
990 | (IEEE754_INVALID_OPERATION)) | ||
991 | rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; | ||
992 | else | ||
993 | goto copcsr; | ||
994 | |||
995 | } | ||
996 | else { | ||
997 | return SIGILL; | ||
998 | } | ||
999 | break; | ||
1000 | } | ||
1001 | break; | ||
1002 | } | ||
1003 | |||
1004 | #ifndef SINGLE_ONLY_FPU | ||
1005 | case d_fmt:{ | ||
1006 | union { | ||
1007 | ieee754dp(*b) (ieee754dp, ieee754dp); | ||
1008 | ieee754dp(*u) (ieee754dp); | ||
1009 | } handler; | ||
1010 | |||
1011 | switch (MIPSInst_FUNC(ir)) { | ||
1012 | /* binary ops */ | ||
1013 | case fadd_op: | ||
1014 | handler.b = ieee754dp_add; | ||
1015 | goto dcopbop; | ||
1016 | case fsub_op: | ||
1017 | handler.b = ieee754dp_sub; | ||
1018 | goto dcopbop; | ||
1019 | case fmul_op: | ||
1020 | handler.b = ieee754dp_mul; | ||
1021 | goto dcopbop; | ||
1022 | case fdiv_op: | ||
1023 | handler.b = ieee754dp_div; | ||
1024 | goto dcopbop; | ||
1025 | |||
1026 | /* unary ops */ | ||
1027 | #if __mips >= 2 || __mips64 | ||
1028 | case fsqrt_op: | ||
1029 | handler.u = ieee754dp_sqrt; | ||
1030 | goto dcopuop; | ||
1031 | #endif | ||
1032 | #if __mips >= 4 && __mips != 32 | ||
1033 | case frsqrt_op: | ||
1034 | handler.u = fpemu_dp_rsqrt; | ||
1035 | goto dcopuop; | ||
1036 | case frecip_op: | ||
1037 | handler.u = fpemu_dp_recip; | ||
1038 | goto dcopuop; | ||
1039 | #endif | ||
1040 | #if __mips >= 4 | ||
1041 | case fmovc_op: | ||
1042 | cond = fpucondbit[MIPSInst_FT(ir) >> 2]; | ||
1043 | if (((ctx->fcr31 & cond) != 0) != | ||
1044 | ((MIPSInst_FT(ir) & 1) != 0)) | ||
1045 | return 0; | ||
1046 | DPFROMREG(rv.d, MIPSInst_FS(ir)); | ||
1047 | break; | ||
1048 | case fmovz_op: | ||
1049 | if (xcp->regs[MIPSInst_FT(ir)] != 0) | ||
1050 | return 0; | ||
1051 | DPFROMREG(rv.d, MIPSInst_FS(ir)); | ||
1052 | break; | ||
1053 | case fmovn_op: | ||
1054 | if (xcp->regs[MIPSInst_FT(ir)] == 0) | ||
1055 | return 0; | ||
1056 | DPFROMREG(rv.d, MIPSInst_FS(ir)); | ||
1057 | break; | ||
1058 | #endif | ||
1059 | case fabs_op: | ||
1060 | handler.u = ieee754dp_abs; | ||
1061 | goto dcopuop; | ||
1062 | |||
1063 | case fneg_op: | ||
1064 | handler.u = ieee754dp_neg; | ||
1065 | goto dcopuop; | ||
1066 | |||
1067 | case fmov_op: | ||
1068 | /* an easy one */ | ||
1069 | DPFROMREG(rv.d, MIPSInst_FS(ir)); | ||
1070 | goto copcsr; | ||
1071 | |||
1072 | /* binary op on handler */ | ||
1073 | dcopbop:{ | ||
1074 | ieee754dp fs, ft; | ||
1075 | |||
1076 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
1077 | DPFROMREG(ft, MIPSInst_FT(ir)); | ||
1078 | |||
1079 | rv.d = (*handler.b) (fs, ft); | ||
1080 | goto copcsr; | ||
1081 | } | ||
1082 | dcopuop:{ | ||
1083 | ieee754dp fs; | ||
1084 | |||
1085 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
1086 | rv.d = (*handler.u) (fs); | ||
1087 | goto copcsr; | ||
1088 | } | ||
1089 | |||
1090 | /* unary conv ops */ | ||
1091 | case fcvts_op:{ | ||
1092 | ieee754dp fs; | ||
1093 | |||
1094 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
1095 | rv.s = ieee754sp_fdp(fs); | ||
1096 | rfmt = s_fmt; | ||
1097 | goto copcsr; | ||
1098 | } | ||
1099 | case fcvtd_op: | ||
1100 | return SIGILL; /* not defined */ | ||
1101 | |||
1102 | case fcvtw_op:{ | ||
1103 | ieee754dp fs; | ||
1104 | |||
1105 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
1106 | rv.w = ieee754dp_tint(fs); /* wrong */ | ||
1107 | rfmt = w_fmt; | ||
1108 | goto copcsr; | ||
1109 | } | ||
1110 | |||
1111 | #if __mips >= 2 || __mips64 | ||
1112 | case fround_op: | ||
1113 | case ftrunc_op: | ||
1114 | case fceil_op: | ||
1115 | case ffloor_op:{ | ||
1116 | unsigned int oldrm = ieee754_csr.rm; | ||
1117 | ieee754dp fs; | ||
1118 | |||
1119 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
1120 | ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; | ||
1121 | rv.w = ieee754dp_tint(fs); | ||
1122 | ieee754_csr.rm = oldrm; | ||
1123 | rfmt = w_fmt; | ||
1124 | goto copcsr; | ||
1125 | } | ||
1126 | #endif | ||
1127 | |||
1128 | #if __mips64 && !defined(SINGLE_ONLY_FPU) | ||
1129 | case fcvtl_op:{ | ||
1130 | ieee754dp fs; | ||
1131 | |||
1132 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
1133 | rv.l = ieee754dp_tlong(fs); | ||
1134 | rfmt = l_fmt; | ||
1135 | goto copcsr; | ||
1136 | } | ||
1137 | |||
1138 | case froundl_op: | ||
1139 | case ftruncl_op: | ||
1140 | case fceill_op: | ||
1141 | case ffloorl_op:{ | ||
1142 | unsigned int oldrm = ieee754_csr.rm; | ||
1143 | ieee754dp fs; | ||
1144 | |||
1145 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
1146 | ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; | ||
1147 | rv.l = ieee754dp_tlong(fs); | ||
1148 | ieee754_csr.rm = oldrm; | ||
1149 | rfmt = l_fmt; | ||
1150 | goto copcsr; | ||
1151 | } | ||
1152 | #endif /* __mips >= 3 && !fpu(single) */ | ||
1153 | |||
1154 | default: | ||
1155 | if (MIPSInst_FUNC(ir) >= fcmp_op) { | ||
1156 | unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; | ||
1157 | ieee754dp fs, ft; | ||
1158 | |||
1159 | DPFROMREG(fs, MIPSInst_FS(ir)); | ||
1160 | DPFROMREG(ft, MIPSInst_FT(ir)); | ||
1161 | rv.w = ieee754dp_cmp(fs, ft, | ||
1162 | cmptab[cmpop & 0x7], cmpop & 0x8); | ||
1163 | rfmt = -1; | ||
1164 | if ((cmpop & 0x8) | ||
1165 | && | ||
1166 | ieee754_cxtest | ||
1167 | (IEEE754_INVALID_OPERATION)) | ||
1168 | rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; | ||
1169 | else | ||
1170 | goto copcsr; | ||
1171 | |||
1172 | } | ||
1173 | else { | ||
1174 | return SIGILL; | ||
1175 | } | ||
1176 | break; | ||
1177 | } | ||
1178 | break; | ||
1179 | } | ||
1180 | #endif /* ifndef SINGLE_ONLY_FPU */ | ||
1181 | |||
1182 | case w_fmt:{ | ||
1183 | ieee754sp fs; | ||
1184 | |||
1185 | switch (MIPSInst_FUNC(ir)) { | ||
1186 | case fcvts_op: | ||
1187 | /* convert word to single precision real */ | ||
1188 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
1189 | rv.s = ieee754sp_fint(fs.bits); | ||
1190 | rfmt = s_fmt; | ||
1191 | goto copcsr; | ||
1192 | #ifndef SINGLE_ONLY_FPU | ||
1193 | case fcvtd_op: | ||
1194 | /* convert word to double precision real */ | ||
1195 | SPFROMREG(fs, MIPSInst_FS(ir)); | ||
1196 | rv.d = ieee754dp_fint(fs.bits); | ||
1197 | rfmt = d_fmt; | ||
1198 | goto copcsr; | ||
1199 | #endif | ||
1200 | default: | ||
1201 | return SIGILL; | ||
1202 | } | ||
1203 | break; | ||
1204 | } | ||
1205 | |||
1206 | #if __mips64 && !defined(SINGLE_ONLY_FPU) | ||
1207 | case l_fmt:{ | ||
1208 | switch (MIPSInst_FUNC(ir)) { | ||
1209 | case fcvts_op: | ||
1210 | /* convert long to single precision real */ | ||
1211 | rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]); | ||
1212 | rfmt = s_fmt; | ||
1213 | goto copcsr; | ||
1214 | case fcvtd_op: | ||
1215 | /* convert long to double precision real */ | ||
1216 | rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]); | ||
1217 | rfmt = d_fmt; | ||
1218 | goto copcsr; | ||
1219 | default: | ||
1220 | return SIGILL; | ||
1221 | } | ||
1222 | break; | ||
1223 | } | ||
1224 | #endif | ||
1225 | |||
1226 | default: | ||
1227 | return SIGILL; | ||
1228 | } | ||
1229 | |||
1230 | /* | ||
1231 | * Update the fpu CSR register for this operation. | ||
1232 | * If an exception is required, generate a tidy SIGFPE exception, | ||
1233 | * without updating the result register. | ||
1234 | * Note: cause exception bits do not accumulate, they are rewritten | ||
1235 | * for each op; only the flag/sticky bits accumulate. | ||
1236 | */ | ||
1237 | ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; | ||
1238 | if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { | ||
1239 | /*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */ | ||
1240 | return SIGFPE; | ||
1241 | } | ||
1242 | |||
1243 | /* | ||
1244 | * Now we can safely write the result back to the register file. | ||
1245 | */ | ||
1246 | switch (rfmt) { | ||
1247 | case -1:{ | ||
1248 | #if __mips >= 4 | ||
1249 | cond = fpucondbit[MIPSInst_FD(ir) >> 2]; | ||
1250 | #else | ||
1251 | cond = FPU_CSR_COND; | ||
1252 | #endif | ||
1253 | if (rv.w) | ||
1254 | ctx->fcr31 |= cond; | ||
1255 | else | ||
1256 | ctx->fcr31 &= ~cond; | ||
1257 | break; | ||
1258 | } | ||
1259 | #ifndef SINGLE_ONLY_FPU | ||
1260 | case d_fmt: | ||
1261 | DPTOREG(rv.d, MIPSInst_FD(ir)); | ||
1262 | break; | ||
1263 | #endif | ||
1264 | case s_fmt: | ||
1265 | SPTOREG(rv.s, MIPSInst_FD(ir)); | ||
1266 | break; | ||
1267 | case w_fmt: | ||
1268 | SITOREG(rv.w, MIPSInst_FD(ir)); | ||
1269 | break; | ||
1270 | #if __mips64 && !defined(SINGLE_ONLY_FPU) | ||
1271 | case l_fmt: | ||
1272 | DITOREG(rv.l, MIPSInst_FD(ir)); | ||
1273 | break; | ||
1274 | #endif | ||
1275 | default: | ||
1276 | return SIGILL; | ||
1277 | } | ||
1278 | |||
1279 | return 0; | ||
1280 | } | ||
1281 | |||
1282 | int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp, | ||
1283 | struct mips_fpu_soft_struct *ctx) | ||
1284 | { | ||
1285 | gpreg_t oldepc, prevepc; | ||
1286 | mips_instruction insn; | ||
1287 | int sig = 0; | ||
1288 | |||
1289 | oldepc = xcp->cp0_epc; | ||
1290 | do { | ||
1291 | prevepc = xcp->cp0_epc; | ||
1292 | |||
1293 | if (get_user(insn, (mips_instruction *) xcp->cp0_epc)) { | ||
1294 | fpuemuprivate.stats.errors++; | ||
1295 | return SIGBUS; | ||
1296 | } | ||
1297 | if (insn == 0) | ||
1298 | xcp->cp0_epc += 4; /* skip nops */ | ||
1299 | else { | ||
1300 | /* Update ieee754_csr. Only relevant if we have a | ||
1301 | h/w FPU */ | ||
1302 | ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0; | ||
1303 | ieee754_csr.rm = ieee_rm[ctx->fcr31 & 0x3]; | ||
1304 | ieee754_csr.cx = (ctx->fcr31 >> 12) & 0x1f; | ||
1305 | sig = cop1Emulate(xcp, ctx); | ||
1306 | } | ||
1307 | |||
1308 | if (cpu_has_fpu) | ||
1309 | break; | ||
1310 | if (sig) | ||
1311 | break; | ||
1312 | |||
1313 | cond_resched(); | ||
1314 | } while (xcp->cp0_epc > prevepc); | ||
1315 | |||
1316 | /* SIGILL indicates a non-fpu instruction */ | ||
1317 | if (sig == SIGILL && xcp->cp0_epc != oldepc) | ||
1318 | /* but if epc has advanced, then ignore it */ | ||
1319 | sig = 0; | ||
1320 | |||
1321 | return sig; | ||
1322 | } | ||
diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c new file mode 100644 index 000000000000..bcf73bb5c33a --- /dev/null +++ b/arch/mips/math-emu/dp_add.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include "ieee754dp.h" | ||
30 | |||
31 | ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y) | ||
32 | { | ||
33 | COMPXDP; | ||
34 | COMPYDP; | ||
35 | |||
36 | EXPLODEXDP; | ||
37 | EXPLODEYDP; | ||
38 | |||
39 | CLEARCX; | ||
40 | |||
41 | FLUSHXDP; | ||
42 | FLUSHYDP; | ||
43 | |||
44 | switch (CLPAIR(xc, yc)) { | ||
45 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): | ||
46 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): | ||
47 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): | ||
48 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): | ||
49 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): | ||
50 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): | ||
51 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): | ||
52 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): | ||
53 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): | ||
54 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): | ||
55 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): | ||
56 | SETCX(IEEE754_INVALID_OPERATION); | ||
57 | return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y); | ||
58 | |||
59 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): | ||
60 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): | ||
61 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): | ||
62 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): | ||
63 | return y; | ||
64 | |||
65 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | ||
66 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): | ||
67 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): | ||
68 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): | ||
69 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): | ||
70 | return x; | ||
71 | |||
72 | |||
73 | /* Infinity handling | ||
74 | */ | ||
75 | |||
76 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | ||
77 | if (xs == ys) | ||
78 | return x; | ||
79 | SETCX(IEEE754_INVALID_OPERATION); | ||
80 | return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y); | ||
81 | |||
82 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | ||
83 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | ||
84 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | ||
85 | return y; | ||
86 | |||
87 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | ||
88 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | ||
89 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | ||
90 | return x; | ||
91 | |||
92 | /* Zero handling | ||
93 | */ | ||
94 | |||
95 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | ||
96 | if (xs == ys) | ||
97 | return x; | ||
98 | else | ||
99 | return ieee754dp_zero(ieee754_csr.rm == | ||
100 | IEEE754_RD); | ||
101 | |||
102 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | ||
103 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | ||
104 | return x; | ||
105 | |||
106 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | ||
107 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | ||
108 | return y; | ||
109 | |||
110 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | ||
111 | DPDNORMX; | ||
112 | |||
113 | /* FALL THROUGH */ | ||
114 | |||
115 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | ||
116 | DPDNORMY; | ||
117 | break; | ||
118 | |||
119 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | ||
120 | DPDNORMX; | ||
121 | break; | ||
122 | |||
123 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | ||
124 | break; | ||
125 | } | ||
126 | assert(xm & DP_HIDDEN_BIT); | ||
127 | assert(ym & DP_HIDDEN_BIT); | ||
128 | |||
129 | /* provide guard,round and stick bit space */ | ||
130 | xm <<= 3; | ||
131 | ym <<= 3; | ||
132 | |||
133 | if (xe > ye) { | ||
134 | /* have to shift y fraction right to align | ||
135 | */ | ||
136 | int s = xe - ye; | ||
137 | ym = XDPSRS(ym, s); | ||
138 | ye += s; | ||
139 | } else if (ye > xe) { | ||
140 | /* have to shift x fraction right to align | ||
141 | */ | ||
142 | int s = ye - xe; | ||
143 | xm = XDPSRS(xm, s); | ||
144 | xe += s; | ||
145 | } | ||
146 | assert(xe == ye); | ||
147 | assert(xe <= DP_EMAX); | ||
148 | |||
149 | if (xs == ys) { | ||
150 | /* generate 28 bit result of adding two 27 bit numbers | ||
151 | * leaving result in xm,xs,xe | ||
152 | */ | ||
153 | xm = xm + ym; | ||
154 | xe = xe; | ||
155 | xs = xs; | ||
156 | |||
157 | if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ | ||
158 | xm = XDPSRS1(xm); | ||
159 | xe++; | ||
160 | } | ||
161 | } else { | ||
162 | if (xm >= ym) { | ||
163 | xm = xm - ym; | ||
164 | xe = xe; | ||
165 | xs = xs; | ||
166 | } else { | ||
167 | xm = ym - xm; | ||
168 | xe = xe; | ||
169 | xs = ys; | ||
170 | } | ||
171 | if (xm == 0) | ||
172 | return ieee754dp_zero(ieee754_csr.rm == | ||
173 | IEEE754_RD); | ||
174 | |||
175 | /* normalize to rounding precision */ | ||
176 | while ((xm >> (DP_MBITS + 3)) == 0) { | ||
177 | xm <<= 1; | ||
178 | xe--; | ||
179 | } | ||
180 | |||
181 | } | ||
182 | DPNORMRET2(xs, xe, xm, "add", x, y); | ||
183 | } | ||
diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c new file mode 100644 index 000000000000..8ab4f320a478 --- /dev/null +++ b/arch/mips/math-emu/dp_cmp.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | COMPYDP; | ||
34 | |||
35 | EXPLODEXDP; | ||
36 | EXPLODEYDP; | ||
37 | FLUSHXDP; | ||
38 | FLUSHYDP; | ||
39 | CLEARCX; /* Even clear inexact flag here */ | ||
40 | |||
41 | if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) { | ||
42 | if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) | ||
43 | SETCX(IEEE754_INVALID_OPERATION); | ||
44 | if (cmp & IEEE754_CUN) | ||
45 | return 1; | ||
46 | if (cmp & (IEEE754_CLT | IEEE754_CGT)) { | ||
47 | if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION)) | ||
48 | return ieee754si_xcpt(0, "fcmpf", x); | ||
49 | } | ||
50 | return 0; | ||
51 | } else { | ||
52 | s64 vx = x.bits; | ||
53 | s64 vy = y.bits; | ||
54 | |||
55 | if (vx < 0) | ||
56 | vx = -vx ^ DP_SIGN_BIT; | ||
57 | if (vy < 0) | ||
58 | vy = -vy ^ DP_SIGN_BIT; | ||
59 | |||
60 | if (vx < vy) | ||
61 | return (cmp & IEEE754_CLT) != 0; | ||
62 | else if (vx == vy) | ||
63 | return (cmp & IEEE754_CEQ) != 0; | ||
64 | else | ||
65 | return (cmp & IEEE754_CGT) != 0; | ||
66 | } | ||
67 | } | ||
diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c new file mode 100644 index 000000000000..6acedce3b32d --- /dev/null +++ b/arch/mips/math-emu/dp_div.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | COMPYDP; | ||
34 | |||
35 | EXPLODEXDP; | ||
36 | EXPLODEYDP; | ||
37 | |||
38 | CLEARCX; | ||
39 | |||
40 | FLUSHXDP; | ||
41 | FLUSHYDP; | ||
42 | |||
43 | switch (CLPAIR(xc, yc)) { | ||
44 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): | ||
45 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): | ||
46 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): | ||
47 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): | ||
48 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): | ||
49 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): | ||
50 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): | ||
51 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): | ||
52 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): | ||
53 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): | ||
54 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y); | ||
57 | |||
58 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): | ||
59 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): | ||
60 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): | ||
61 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): | ||
62 | return y; | ||
63 | |||
64 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | ||
65 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): | ||
66 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): | ||
67 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): | ||
68 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): | ||
69 | return x; | ||
70 | |||
71 | |||
72 | /* Infinity handling | ||
73 | */ | ||
74 | |||
75 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | ||
76 | SETCX(IEEE754_INVALID_OPERATION); | ||
77 | return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); | ||
78 | |||
79 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | ||
80 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | ||
81 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | ||
82 | return ieee754dp_zero(xs ^ ys); | ||
83 | |||
84 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | ||
85 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | ||
86 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | ||
87 | return ieee754dp_inf(xs ^ ys); | ||
88 | |||
89 | /* Zero handling | ||
90 | */ | ||
91 | |||
92 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | ||
93 | SETCX(IEEE754_INVALID_OPERATION); | ||
94 | return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); | ||
95 | |||
96 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | ||
97 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | ||
98 | SETCX(IEEE754_ZERO_DIVIDE); | ||
99 | return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y); | ||
100 | |||
101 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | ||
102 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | ||
103 | return ieee754dp_zero(xs == ys ? 0 : 1); | ||
104 | |||
105 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | ||
106 | DPDNORMX; | ||
107 | |||
108 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | ||
109 | DPDNORMY; | ||
110 | break; | ||
111 | |||
112 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | ||
113 | DPDNORMX; | ||
114 | break; | ||
115 | |||
116 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | ||
117 | break; | ||
118 | } | ||
119 | assert(xm & DP_HIDDEN_BIT); | ||
120 | assert(ym & DP_HIDDEN_BIT); | ||
121 | |||
122 | /* provide rounding space */ | ||
123 | xm <<= 3; | ||
124 | ym <<= 3; | ||
125 | |||
126 | { | ||
127 | /* now the dirty work */ | ||
128 | |||
129 | u64 rm = 0; | ||
130 | int re = xe - ye; | ||
131 | u64 bm; | ||
132 | |||
133 | for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) { | ||
134 | if (xm >= ym) { | ||
135 | xm -= ym; | ||
136 | rm |= bm; | ||
137 | if (xm == 0) | ||
138 | break; | ||
139 | } | ||
140 | xm <<= 1; | ||
141 | } | ||
142 | rm <<= 1; | ||
143 | if (xm) | ||
144 | rm |= 1; /* have remainder, set sticky */ | ||
145 | |||
146 | assert(rm); | ||
147 | |||
148 | /* normalise rm to rounding precision ? | ||
149 | */ | ||
150 | while ((rm >> (DP_MBITS + 3)) == 0) { | ||
151 | rm <<= 1; | ||
152 | re--; | ||
153 | } | ||
154 | |||
155 | DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); | ||
156 | } | ||
157 | } | ||
diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c new file mode 100644 index 000000000000..0065deaee24b --- /dev/null +++ b/arch/mips/math-emu/dp_fint.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | ieee754dp ieee754dp_fint(int x) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | xc = ( 0 ? xc : xc ); | ||
37 | |||
38 | if (x == 0) | ||
39 | return ieee754dp_zero(0); | ||
40 | if (x == 1 || x == -1) | ||
41 | return ieee754dp_one(x < 0); | ||
42 | if (x == 10 || x == -10) | ||
43 | return ieee754dp_ten(x < 0); | ||
44 | |||
45 | xs = (x < 0); | ||
46 | if (xs) { | ||
47 | if (x == (1 << 31)) | ||
48 | xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */ | ||
49 | else | ||
50 | xm = -x; | ||
51 | } else { | ||
52 | xm = x; | ||
53 | } | ||
54 | |||
55 | #if 1 | ||
56 | /* normalize - result can never be inexact or overflow */ | ||
57 | xe = DP_MBITS; | ||
58 | while ((xm >> DP_MBITS) == 0) { | ||
59 | xm <<= 1; | ||
60 | xe--; | ||
61 | } | ||
62 | return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); | ||
63 | #else | ||
64 | /* normalize */ | ||
65 | xe = DP_MBITS + 3; | ||
66 | while ((xm >> (DP_MBITS + 3)) == 0) { | ||
67 | xm <<= 1; | ||
68 | xe--; | ||
69 | } | ||
70 | DPNORMRET1(xs, xe, xm, "fint", x); | ||
71 | #endif | ||
72 | } | ||
73 | |||
74 | ieee754dp ieee754dp_funs(unsigned int u) | ||
75 | { | ||
76 | if ((int) u < 0) | ||
77 | return ieee754dp_add(ieee754dp_1e31(), | ||
78 | ieee754dp_fint(u & ~(1 << 31))); | ||
79 | return ieee754dp_fint(u); | ||
80 | } | ||
diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c new file mode 100644 index 000000000000..cb105b1dd860 --- /dev/null +++ b/arch/mips/math-emu/dp_flong.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | ieee754dp ieee754dp_flong(s64 x) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | xc = ( 0 ? xc : xc ); | ||
37 | |||
38 | if (x == 0) | ||
39 | return ieee754dp_zero(0); | ||
40 | if (x == 1 || x == -1) | ||
41 | return ieee754dp_one(x < 0); | ||
42 | if (x == 10 || x == -10) | ||
43 | return ieee754dp_ten(x < 0); | ||
44 | |||
45 | xs = (x < 0); | ||
46 | if (xs) { | ||
47 | if (x == (1ULL << 63)) | ||
48 | xm = (1ULL << 63); /* max neg can't be safely negated */ | ||
49 | else | ||
50 | xm = -x; | ||
51 | } else { | ||
52 | xm = x; | ||
53 | } | ||
54 | |||
55 | /* normalize */ | ||
56 | xe = DP_MBITS + 3; | ||
57 | if (xm >> (DP_MBITS + 1 + 3)) { | ||
58 | /* shunt out overflow bits */ | ||
59 | while (xm >> (DP_MBITS + 1 + 3)) { | ||
60 | XDPSRSX1(); | ||
61 | } | ||
62 | } else { | ||
63 | /* normalize in grs extended double precision */ | ||
64 | while ((xm >> (DP_MBITS + 3)) == 0) { | ||
65 | xm <<= 1; | ||
66 | xe--; | ||
67 | } | ||
68 | } | ||
69 | DPNORMRET1(xs, xe, xm, "dp_flong", x); | ||
70 | } | ||
71 | |||
72 | ieee754dp ieee754dp_fulong(u64 u) | ||
73 | { | ||
74 | if ((s64) u < 0) | ||
75 | return ieee754dp_add(ieee754dp_1e63(), | ||
76 | ieee754dp_flong(u & ~(1ULL << 63))); | ||
77 | return ieee754dp_flong(u); | ||
78 | } | ||
diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c new file mode 100644 index 000000000000..e650cb10c947 --- /dev/null +++ b/arch/mips/math-emu/dp_frexp.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | /* close to ieeep754dp_logb | ||
31 | */ | ||
32 | ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr) | ||
33 | { | ||
34 | COMPXDP; | ||
35 | CLEARCX; | ||
36 | EXPLODEXDP; | ||
37 | |||
38 | switch (xc) { | ||
39 | case IEEE754_CLASS_SNAN: | ||
40 | case IEEE754_CLASS_QNAN: | ||
41 | case IEEE754_CLASS_INF: | ||
42 | case IEEE754_CLASS_ZERO: | ||
43 | *eptr = 0; | ||
44 | return x; | ||
45 | case IEEE754_CLASS_DNORM: | ||
46 | DPDNORMX; | ||
47 | break; | ||
48 | case IEEE754_CLASS_NORM: | ||
49 | break; | ||
50 | } | ||
51 | *eptr = xe + 1; | ||
52 | return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT); | ||
53 | } | ||
diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c new file mode 100644 index 000000000000..494d19ac7049 --- /dev/null +++ b/arch/mips/math-emu/dp_fsp.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | ieee754dp ieee754dp_fsp(ieee754sp x) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | |||
34 | EXPLODEXSP; | ||
35 | |||
36 | CLEARCX; | ||
37 | |||
38 | FLUSHXSP; | ||
39 | |||
40 | switch (xc) { | ||
41 | case IEEE754_CLASS_SNAN: | ||
42 | SETCX(IEEE754_INVALID_OPERATION); | ||
43 | return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp"); | ||
44 | case IEEE754_CLASS_QNAN: | ||
45 | return ieee754dp_nanxcpt(builddp(xs, | ||
46 | DP_EMAX + 1 + DP_EBIAS, | ||
47 | ((u64) xm | ||
48 | << (DP_MBITS - | ||
49 | SP_MBITS))), "fsp", | ||
50 | x); | ||
51 | case IEEE754_CLASS_INF: | ||
52 | return ieee754dp_inf(xs); | ||
53 | case IEEE754_CLASS_ZERO: | ||
54 | return ieee754dp_zero(xs); | ||
55 | case IEEE754_CLASS_DNORM: | ||
56 | /* normalize */ | ||
57 | while ((xm >> SP_MBITS) == 0) { | ||
58 | xm <<= 1; | ||
59 | xe--; | ||
60 | } | ||
61 | break; | ||
62 | case IEEE754_CLASS_NORM: | ||
63 | break; | ||
64 | } | ||
65 | |||
66 | /* CANT possibly overflow,underflow, or need rounding | ||
67 | */ | ||
68 | |||
69 | /* drop the hidden bit */ | ||
70 | xm &= ~SP_HIDDEN_BIT; | ||
71 | |||
72 | return builddp(xs, xe + DP_EBIAS, | ||
73 | (u64) xm << (DP_MBITS - SP_MBITS)); | ||
74 | } | ||
diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c new file mode 100644 index 000000000000..603388621ca5 --- /dev/null +++ b/arch/mips/math-emu/dp_logb.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | ieee754dp ieee754dp_logb(ieee754dp x) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | EXPLODEXDP; | ||
37 | |||
38 | switch (xc) { | ||
39 | case IEEE754_CLASS_SNAN: | ||
40 | return ieee754dp_nanxcpt(x, "logb", x); | ||
41 | case IEEE754_CLASS_QNAN: | ||
42 | return x; | ||
43 | case IEEE754_CLASS_INF: | ||
44 | return ieee754dp_inf(0); | ||
45 | case IEEE754_CLASS_ZERO: | ||
46 | return ieee754dp_inf(1); | ||
47 | case IEEE754_CLASS_DNORM: | ||
48 | DPDNORMX; | ||
49 | break; | ||
50 | case IEEE754_CLASS_NORM: | ||
51 | break; | ||
52 | } | ||
53 | return ieee754dp_fint(xe); | ||
54 | } | ||
diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c new file mode 100644 index 000000000000..25861a42c36f --- /dev/null +++ b/arch/mips/math-emu/dp_modf.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | /* modf function is always exact for a finite number | ||
31 | */ | ||
32 | ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip) | ||
33 | { | ||
34 | COMPXDP; | ||
35 | |||
36 | CLEARCX; | ||
37 | |||
38 | EXPLODEXDP; | ||
39 | |||
40 | switch (xc) { | ||
41 | case IEEE754_CLASS_SNAN: | ||
42 | case IEEE754_CLASS_QNAN: | ||
43 | case IEEE754_CLASS_INF: | ||
44 | case IEEE754_CLASS_ZERO: | ||
45 | *ip = x; | ||
46 | return x; | ||
47 | case IEEE754_CLASS_DNORM: | ||
48 | /* far to small */ | ||
49 | *ip = ieee754dp_zero(xs); | ||
50 | return x; | ||
51 | case IEEE754_CLASS_NORM: | ||
52 | break; | ||
53 | } | ||
54 | if (xe < 0) { | ||
55 | *ip = ieee754dp_zero(xs); | ||
56 | return x; | ||
57 | } | ||
58 | if (xe >= DP_MBITS) { | ||
59 | *ip = x; | ||
60 | return ieee754dp_zero(xs); | ||
61 | } | ||
62 | /* generate ipart mantissa by clearing bottom bits | ||
63 | */ | ||
64 | *ip = builddp(xs, xe + DP_EBIAS, | ||
65 | ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) & | ||
66 | ~DP_HIDDEN_BIT); | ||
67 | |||
68 | /* generate fpart mantissa by clearing top bits | ||
69 | * and normalizing (must be able to normalize) | ||
70 | */ | ||
71 | xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe)); | ||
72 | if (xm == 0) | ||
73 | return ieee754dp_zero(xs); | ||
74 | |||
75 | while ((xm >> DP_MBITS) == 0) { | ||
76 | xm <<= 1; | ||
77 | xe--; | ||
78 | } | ||
79 | return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); | ||
80 | } | ||
diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c new file mode 100644 index 000000000000..f2373902f524 --- /dev/null +++ b/arch/mips/math-emu/dp_mul.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | COMPYDP; | ||
34 | |||
35 | EXPLODEXDP; | ||
36 | EXPLODEYDP; | ||
37 | |||
38 | CLEARCX; | ||
39 | |||
40 | FLUSHXDP; | ||
41 | FLUSHYDP; | ||
42 | |||
43 | switch (CLPAIR(xc, yc)) { | ||
44 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): | ||
45 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): | ||
46 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): | ||
47 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): | ||
48 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): | ||
49 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): | ||
50 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): | ||
51 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): | ||
52 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): | ||
53 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): | ||
54 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y); | ||
57 | |||
58 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): | ||
59 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): | ||
60 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): | ||
61 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): | ||
62 | return y; | ||
63 | |||
64 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | ||
65 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): | ||
66 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): | ||
67 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): | ||
68 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): | ||
69 | return x; | ||
70 | |||
71 | |||
72 | /* Infinity handling */ | ||
73 | |||
74 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | ||
75 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | ||
76 | SETCX(IEEE754_INVALID_OPERATION); | ||
77 | return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y); | ||
78 | |||
79 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | ||
80 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | ||
81 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | ||
82 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | ||
83 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | ||
84 | return ieee754dp_inf(xs ^ ys); | ||
85 | |||
86 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | ||
87 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | ||
88 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | ||
89 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | ||
90 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | ||
91 | return ieee754dp_zero(xs ^ ys); | ||
92 | |||
93 | |||
94 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | ||
95 | DPDNORMX; | ||
96 | |||
97 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | ||
98 | DPDNORMY; | ||
99 | break; | ||
100 | |||
101 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | ||
102 | DPDNORMX; | ||
103 | break; | ||
104 | |||
105 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | ||
106 | break; | ||
107 | } | ||
108 | /* rm = xm * ym, re = xe+ye basicly */ | ||
109 | assert(xm & DP_HIDDEN_BIT); | ||
110 | assert(ym & DP_HIDDEN_BIT); | ||
111 | { | ||
112 | int re = xe + ye; | ||
113 | int rs = xs ^ ys; | ||
114 | u64 rm; | ||
115 | |||
116 | /* shunt to top of word */ | ||
117 | xm <<= 64 - (DP_MBITS + 1); | ||
118 | ym <<= 64 - (DP_MBITS + 1); | ||
119 | |||
120 | /* multiply 32bits xm,ym to give high 32bits rm with stickness | ||
121 | */ | ||
122 | |||
123 | /* 32 * 32 => 64 */ | ||
124 | #define DPXMULT(x,y) ((u64)(x) * (u64)y) | ||
125 | |||
126 | { | ||
127 | unsigned lxm = xm; | ||
128 | unsigned hxm = xm >> 32; | ||
129 | unsigned lym = ym; | ||
130 | unsigned hym = ym >> 32; | ||
131 | u64 lrm; | ||
132 | u64 hrm; | ||
133 | |||
134 | lrm = DPXMULT(lxm, lym); | ||
135 | hrm = DPXMULT(hxm, hym); | ||
136 | |||
137 | { | ||
138 | u64 t = DPXMULT(lxm, hym); | ||
139 | { | ||
140 | u64 at = | ||
141 | lrm + (t << 32); | ||
142 | hrm += at < lrm; | ||
143 | lrm = at; | ||
144 | } | ||
145 | hrm = hrm + (t >> 32); | ||
146 | } | ||
147 | |||
148 | { | ||
149 | u64 t = DPXMULT(hxm, lym); | ||
150 | { | ||
151 | u64 at = | ||
152 | lrm + (t << 32); | ||
153 | hrm += at < lrm; | ||
154 | lrm = at; | ||
155 | } | ||
156 | hrm = hrm + (t >> 32); | ||
157 | } | ||
158 | rm = hrm | (lrm != 0); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * sticky shift down to normal rounding precision | ||
163 | */ | ||
164 | if ((s64) rm < 0) { | ||
165 | rm = | ||
166 | (rm >> (64 - (DP_MBITS + 1 + 3))) | | ||
167 | ((rm << (DP_MBITS + 1 + 3)) != 0); | ||
168 | re++; | ||
169 | } else { | ||
170 | rm = | ||
171 | (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) | | ||
172 | ((rm << (DP_MBITS + 1 + 3 + 1)) != 0); | ||
173 | } | ||
174 | assert(rm & (DP_HIDDEN_BIT << 3)); | ||
175 | DPNORMRET2(rs, re, rm, "mul", x, y); | ||
176 | } | ||
177 | } | ||
diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c new file mode 100644 index 000000000000..b84e6338330e --- /dev/null +++ b/arch/mips/math-emu/dp_scalb.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | ieee754dp ieee754dp_scalb(ieee754dp x, int n) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | EXPLODEXDP; | ||
37 | |||
38 | switch (xc) { | ||
39 | case IEEE754_CLASS_SNAN: | ||
40 | return ieee754dp_nanxcpt(x, "scalb", x, n); | ||
41 | case IEEE754_CLASS_QNAN: | ||
42 | case IEEE754_CLASS_INF: | ||
43 | case IEEE754_CLASS_ZERO: | ||
44 | return x; | ||
45 | case IEEE754_CLASS_DNORM: | ||
46 | DPDNORMX; | ||
47 | break; | ||
48 | case IEEE754_CLASS_NORM: | ||
49 | break; | ||
50 | } | ||
51 | DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); | ||
52 | } | ||
53 | |||
54 | |||
55 | ieee754dp ieee754dp_ldexp(ieee754dp x, int n) | ||
56 | { | ||
57 | return ieee754dp_scalb(x, n); | ||
58 | } | ||
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c new file mode 100644 index 000000000000..495c1ac94298 --- /dev/null +++ b/arch/mips/math-emu/dp_simple.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | int ieee754dp_finite(ieee754dp x) | ||
31 | { | ||
32 | return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS; | ||
33 | } | ||
34 | |||
35 | ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y) | ||
36 | { | ||
37 | CLEARCX; | ||
38 | DPSIGN(x) = DPSIGN(y); | ||
39 | return x; | ||
40 | } | ||
41 | |||
42 | |||
43 | ieee754dp ieee754dp_neg(ieee754dp x) | ||
44 | { | ||
45 | COMPXDP; | ||
46 | |||
47 | EXPLODEXDP; | ||
48 | CLEARCX; | ||
49 | FLUSHXDP; | ||
50 | |||
51 | if (xc == IEEE754_CLASS_SNAN) { | ||
52 | SETCX(IEEE754_INVALID_OPERATION); | ||
53 | return ieee754dp_nanxcpt(ieee754dp_indef(), "neg"); | ||
54 | } | ||
55 | |||
56 | if (ieee754dp_isnan(x)) /* but not infinity */ | ||
57 | return ieee754dp_nanxcpt(x, "neg", x); | ||
58 | |||
59 | /* quick fix up */ | ||
60 | DPSIGN(x) ^= 1; | ||
61 | return x; | ||
62 | } | ||
63 | |||
64 | |||
65 | ieee754dp ieee754dp_abs(ieee754dp x) | ||
66 | { | ||
67 | COMPXDP; | ||
68 | |||
69 | EXPLODEXDP; | ||
70 | CLEARCX; | ||
71 | FLUSHXDP; | ||
72 | |||
73 | if (xc == IEEE754_CLASS_SNAN) { | ||
74 | SETCX(IEEE754_INVALID_OPERATION); | ||
75 | return ieee754dp_nanxcpt(ieee754dp_indef(), "neg"); | ||
76 | } | ||
77 | |||
78 | if (ieee754dp_isnan(x)) /* but not infinity */ | ||
79 | return ieee754dp_nanxcpt(x, "abs", x); | ||
80 | |||
81 | /* quick fix up */ | ||
82 | DPSIGN(x) = 0; | ||
83 | return x; | ||
84 | } | ||
diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c new file mode 100644 index 000000000000..c35e871ae975 --- /dev/null +++ b/arch/mips/math-emu/dp_sqrt.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision square root | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | static const unsigned table[] = { | ||
31 | 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592, | ||
32 | 29598, 36145, 43202, 50740, 58733, 67158, 75992, | ||
33 | 85215, 83599, 71378, 60428, 50647, 41945, 34246, | ||
34 | 27478, 21581, 16499, 12183, 8588, 5674, 3403, | ||
35 | 1742, 661, 130 | ||
36 | }; | ||
37 | |||
38 | ieee754dp ieee754dp_sqrt(ieee754dp x) | ||
39 | { | ||
40 | struct ieee754_csr oldcsr; | ||
41 | ieee754dp y, z, t; | ||
42 | unsigned scalx, yh; | ||
43 | COMPXDP; | ||
44 | |||
45 | EXPLODEXDP; | ||
46 | CLEARCX; | ||
47 | FLUSHXDP; | ||
48 | |||
49 | /* x == INF or NAN? */ | ||
50 | switch (xc) { | ||
51 | case IEEE754_CLASS_QNAN: | ||
52 | /* sqrt(Nan) = Nan */ | ||
53 | return ieee754dp_nanxcpt(x, "sqrt"); | ||
54 | case IEEE754_CLASS_SNAN: | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); | ||
57 | case IEEE754_CLASS_ZERO: | ||
58 | /* sqrt(0) = 0 */ | ||
59 | return x; | ||
60 | case IEEE754_CLASS_INF: | ||
61 | if (xs) { | ||
62 | /* sqrt(-Inf) = Nan */ | ||
63 | SETCX(IEEE754_INVALID_OPERATION); | ||
64 | return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); | ||
65 | } | ||
66 | /* sqrt(+Inf) = Inf */ | ||
67 | return x; | ||
68 | case IEEE754_CLASS_DNORM: | ||
69 | DPDNORMX; | ||
70 | /* fall through */ | ||
71 | case IEEE754_CLASS_NORM: | ||
72 | if (xs) { | ||
73 | /* sqrt(-x) = Nan */ | ||
74 | SETCX(IEEE754_INVALID_OPERATION); | ||
75 | return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); | ||
76 | } | ||
77 | break; | ||
78 | } | ||
79 | |||
80 | /* save old csr; switch off INX enable & flag; set RN rounding */ | ||
81 | oldcsr = ieee754_csr; | ||
82 | ieee754_csr.mx &= ~IEEE754_INEXACT; | ||
83 | ieee754_csr.sx &= ~IEEE754_INEXACT; | ||
84 | ieee754_csr.rm = IEEE754_RN; | ||
85 | |||
86 | /* adjust exponent to prevent overflow */ | ||
87 | scalx = 0; | ||
88 | if (xe > 512) { /* x > 2**-512? */ | ||
89 | xe -= 512; /* x = x / 2**512 */ | ||
90 | scalx += 256; | ||
91 | } else if (xe < -512) { /* x < 2**-512? */ | ||
92 | xe += 512; /* x = x * 2**512 */ | ||
93 | scalx -= 256; | ||
94 | } | ||
95 | |||
96 | y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); | ||
97 | |||
98 | /* magic initial approximation to almost 8 sig. bits */ | ||
99 | yh = y.bits >> 32; | ||
100 | yh = (yh >> 1) + 0x1ff80000; | ||
101 | yh = yh - table[(yh >> 15) & 31]; | ||
102 | y.bits = ((u64) yh << 32) | (y.bits & 0xffffffff); | ||
103 | |||
104 | /* Heron's rule once with correction to improve to ~18 sig. bits */ | ||
105 | /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */ | ||
106 | t = ieee754dp_div(x, y); | ||
107 | y = ieee754dp_add(y, t); | ||
108 | y.bits -= 0x0010000600000000LL; | ||
109 | y.bits &= 0xffffffff00000000LL; | ||
110 | |||
111 | /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */ | ||
112 | /* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */ | ||
113 | z = t = ieee754dp_mul(y, y); | ||
114 | t.parts.bexp += 0x001; | ||
115 | t = ieee754dp_add(t, z); | ||
116 | z = ieee754dp_mul(ieee754dp_sub(x, z), y); | ||
117 | |||
118 | /* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */ | ||
119 | t = ieee754dp_div(z, ieee754dp_add(t, x)); | ||
120 | t.parts.bexp += 0x001; | ||
121 | y = ieee754dp_add(y, t); | ||
122 | |||
123 | /* twiddle last bit to force y correctly rounded */ | ||
124 | |||
125 | /* set RZ, clear INEX flag */ | ||
126 | ieee754_csr.rm = IEEE754_RZ; | ||
127 | ieee754_csr.sx &= ~IEEE754_INEXACT; | ||
128 | |||
129 | /* t=x/y; ...chopped quotient, possibly inexact */ | ||
130 | t = ieee754dp_div(x, y); | ||
131 | |||
132 | if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) { | ||
133 | |||
134 | if (!(ieee754_csr.sx & IEEE754_INEXACT)) | ||
135 | /* t = t-ulp */ | ||
136 | t.bits -= 1; | ||
137 | |||
138 | /* add inexact to result status */ | ||
139 | oldcsr.cx |= IEEE754_INEXACT; | ||
140 | oldcsr.sx |= IEEE754_INEXACT; | ||
141 | |||
142 | switch (oldcsr.rm) { | ||
143 | case IEEE754_RP: | ||
144 | y.bits += 1; | ||
145 | /* drop through */ | ||
146 | case IEEE754_RN: | ||
147 | t.bits += 1; | ||
148 | break; | ||
149 | } | ||
150 | |||
151 | /* y=y+t; ...chopped sum */ | ||
152 | y = ieee754dp_add(y, t); | ||
153 | |||
154 | /* adjust scalx for correctly rounded sqrt(x) */ | ||
155 | scalx -= 1; | ||
156 | } | ||
157 | |||
158 | /* py[n0]=py[n0]+scalx; ...scale back y */ | ||
159 | y.parts.bexp += scalx; | ||
160 | |||
161 | /* restore rounding mode, possibly set inexact */ | ||
162 | ieee754_csr = oldcsr; | ||
163 | |||
164 | return y; | ||
165 | } | ||
diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c new file mode 100644 index 000000000000..b30c5b1f1a2c --- /dev/null +++ b/arch/mips/math-emu/dp_sub.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | COMPYDP; | ||
34 | |||
35 | EXPLODEXDP; | ||
36 | EXPLODEYDP; | ||
37 | |||
38 | CLEARCX; | ||
39 | |||
40 | FLUSHXDP; | ||
41 | FLUSHYDP; | ||
42 | |||
43 | switch (CLPAIR(xc, yc)) { | ||
44 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): | ||
45 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): | ||
46 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): | ||
47 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): | ||
48 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): | ||
49 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): | ||
50 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): | ||
51 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): | ||
52 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): | ||
53 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): | ||
54 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y); | ||
57 | |||
58 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): | ||
59 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): | ||
60 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): | ||
61 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): | ||
62 | return y; | ||
63 | |||
64 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | ||
65 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): | ||
66 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): | ||
67 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): | ||
68 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): | ||
69 | return x; | ||
70 | |||
71 | |||
72 | /* Infinity handling | ||
73 | */ | ||
74 | |||
75 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | ||
76 | if (xs != ys) | ||
77 | return x; | ||
78 | SETCX(IEEE754_INVALID_OPERATION); | ||
79 | return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y); | ||
80 | |||
81 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | ||
82 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | ||
83 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | ||
84 | return ieee754dp_inf(ys ^ 1); | ||
85 | |||
86 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | ||
87 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | ||
88 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | ||
89 | return x; | ||
90 | |||
91 | /* Zero handling | ||
92 | */ | ||
93 | |||
94 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | ||
95 | if (xs != ys) | ||
96 | return x; | ||
97 | else | ||
98 | return ieee754dp_zero(ieee754_csr.rm == | ||
99 | IEEE754_RD); | ||
100 | |||
101 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | ||
102 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | ||
103 | return x; | ||
104 | |||
105 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | ||
106 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | ||
107 | /* quick fix up */ | ||
108 | DPSIGN(y) ^= 1; | ||
109 | return y; | ||
110 | |||
111 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | ||
112 | DPDNORMX; | ||
113 | /* FAAL THOROUGH */ | ||
114 | |||
115 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | ||
116 | /* normalize ym,ye */ | ||
117 | DPDNORMY; | ||
118 | break; | ||
119 | |||
120 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | ||
121 | /* normalize xm,xe */ | ||
122 | DPDNORMX; | ||
123 | break; | ||
124 | |||
125 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | ||
126 | break; | ||
127 | } | ||
128 | /* flip sign of y and handle as add */ | ||
129 | ys ^= 1; | ||
130 | |||
131 | assert(xm & DP_HIDDEN_BIT); | ||
132 | assert(ym & DP_HIDDEN_BIT); | ||
133 | |||
134 | |||
135 | /* provide guard,round and stick bit dpace */ | ||
136 | xm <<= 3; | ||
137 | ym <<= 3; | ||
138 | |||
139 | if (xe > ye) { | ||
140 | /* have to shift y fraction right to align | ||
141 | */ | ||
142 | int s = xe - ye; | ||
143 | ym = XDPSRS(ym, s); | ||
144 | ye += s; | ||
145 | } else if (ye > xe) { | ||
146 | /* have to shift x fraction right to align | ||
147 | */ | ||
148 | int s = ye - xe; | ||
149 | xm = XDPSRS(xm, s); | ||
150 | xe += s; | ||
151 | } | ||
152 | assert(xe == ye); | ||
153 | assert(xe <= DP_EMAX); | ||
154 | |||
155 | if (xs == ys) { | ||
156 | /* generate 28 bit result of adding two 27 bit numbers | ||
157 | */ | ||
158 | xm = xm + ym; | ||
159 | xe = xe; | ||
160 | xs = xs; | ||
161 | |||
162 | if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ | ||
163 | xm = XDPSRS1(xm); /* shift preserving sticky */ | ||
164 | xe++; | ||
165 | } | ||
166 | } else { | ||
167 | if (xm >= ym) { | ||
168 | xm = xm - ym; | ||
169 | xe = xe; | ||
170 | xs = xs; | ||
171 | } else { | ||
172 | xm = ym - xm; | ||
173 | xe = xe; | ||
174 | xs = ys; | ||
175 | } | ||
176 | if (xm == 0) { | ||
177 | if (ieee754_csr.rm == IEEE754_RD) | ||
178 | return ieee754dp_zero(1); /* round negative inf. => sign = -1 */ | ||
179 | else | ||
180 | return ieee754dp_zero(0); /* other round modes => sign = 1 */ | ||
181 | } | ||
182 | |||
183 | /* normalize to rounding precision | ||
184 | */ | ||
185 | while ((xm >> (DP_MBITS + 3)) == 0) { | ||
186 | xm <<= 1; | ||
187 | xe--; | ||
188 | } | ||
189 | } | ||
190 | DPNORMRET2(xs, xe, xm, "sub", x, y); | ||
191 | } | ||
diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c new file mode 100644 index 000000000000..77b2b7ccf28a --- /dev/null +++ b/arch/mips/math-emu/dp_tint.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include "ieee754dp.h" | ||
30 | |||
31 | int ieee754dp_tint(ieee754dp x) | ||
32 | { | ||
33 | COMPXDP; | ||
34 | |||
35 | CLEARCX; | ||
36 | |||
37 | EXPLODEXDP; | ||
38 | FLUSHXDP; | ||
39 | |||
40 | switch (xc) { | ||
41 | case IEEE754_CLASS_SNAN: | ||
42 | case IEEE754_CLASS_QNAN: | ||
43 | case IEEE754_CLASS_INF: | ||
44 | SETCX(IEEE754_INVALID_OPERATION); | ||
45 | return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); | ||
46 | case IEEE754_CLASS_ZERO: | ||
47 | return 0; | ||
48 | case IEEE754_CLASS_DNORM: | ||
49 | case IEEE754_CLASS_NORM: | ||
50 | break; | ||
51 | } | ||
52 | if (xe > 31) { | ||
53 | /* Set invalid. We will only use overflow for floating | ||
54 | point overflow */ | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); | ||
57 | } | ||
58 | /* oh gawd */ | ||
59 | if (xe > DP_MBITS) { | ||
60 | xm <<= xe - DP_MBITS; | ||
61 | } else if (xe < DP_MBITS) { | ||
62 | u64 residue; | ||
63 | int round; | ||
64 | int sticky; | ||
65 | int odd; | ||
66 | |||
67 | if (xe < -1) { | ||
68 | residue = xm; | ||
69 | round = 0; | ||
70 | sticky = residue != 0; | ||
71 | xm = 0; | ||
72 | } | ||
73 | else { | ||
74 | residue = xm << (64 - DP_MBITS + xe); | ||
75 | round = (residue >> 63) != 0; | ||
76 | sticky = (residue << 1) != 0; | ||
77 | xm >>= DP_MBITS - xe; | ||
78 | } | ||
79 | /* Note: At this point upper 32 bits of xm are guaranteed | ||
80 | to be zero */ | ||
81 | odd = (xm & 0x1) != 0x0; | ||
82 | switch (ieee754_csr.rm) { | ||
83 | case IEEE754_RN: | ||
84 | if (round && (sticky || odd)) | ||
85 | xm++; | ||
86 | break; | ||
87 | case IEEE754_RZ: | ||
88 | break; | ||
89 | case IEEE754_RU: /* toward +Infinity */ | ||
90 | if ((round || sticky) && !xs) | ||
91 | xm++; | ||
92 | break; | ||
93 | case IEEE754_RD: /* toward -Infinity */ | ||
94 | if ((round || sticky) && xs) | ||
95 | xm++; | ||
96 | break; | ||
97 | } | ||
98 | /* look for valid corner case 0x80000000 */ | ||
99 | if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) { | ||
100 | /* This can happen after rounding */ | ||
101 | SETCX(IEEE754_INVALID_OPERATION); | ||
102 | return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); | ||
103 | } | ||
104 | if (round || sticky) | ||
105 | SETCX(IEEE754_INEXACT); | ||
106 | } | ||
107 | if (xs) | ||
108 | return -xm; | ||
109 | else | ||
110 | return xm; | ||
111 | } | ||
112 | |||
113 | |||
114 | unsigned int ieee754dp_tuns(ieee754dp x) | ||
115 | { | ||
116 | ieee754dp hb = ieee754dp_1e31(); | ||
117 | |||
118 | /* what if x < 0 ?? */ | ||
119 | if (ieee754dp_lt(x, hb)) | ||
120 | return (unsigned) ieee754dp_tint(x); | ||
121 | |||
122 | return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) | | ||
123 | ((unsigned) 1 << 31); | ||
124 | } | ||
diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c new file mode 100644 index 000000000000..d71113e07164 --- /dev/null +++ b/arch/mips/math-emu/dp_tlong.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | s64 ieee754dp_tlong(ieee754dp x) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | EXPLODEXDP; | ||
37 | FLUSHXDP; | ||
38 | |||
39 | switch (xc) { | ||
40 | case IEEE754_CLASS_SNAN: | ||
41 | case IEEE754_CLASS_QNAN: | ||
42 | case IEEE754_CLASS_INF: | ||
43 | SETCX(IEEE754_INVALID_OPERATION); | ||
44 | return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); | ||
45 | case IEEE754_CLASS_ZERO: | ||
46 | return 0; | ||
47 | case IEEE754_CLASS_DNORM: | ||
48 | case IEEE754_CLASS_NORM: | ||
49 | break; | ||
50 | } | ||
51 | if (xe >= 63) { | ||
52 | /* look for valid corner case */ | ||
53 | if (xe == 63 && xs && xm == DP_HIDDEN_BIT) | ||
54 | return -0x8000000000000000LL; | ||
55 | /* Set invalid. We will only use overflow for floating | ||
56 | point overflow */ | ||
57 | SETCX(IEEE754_INVALID_OPERATION); | ||
58 | return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); | ||
59 | } | ||
60 | /* oh gawd */ | ||
61 | if (xe > DP_MBITS) { | ||
62 | xm <<= xe - DP_MBITS; | ||
63 | } else if (xe < DP_MBITS) { | ||
64 | u64 residue; | ||
65 | int round; | ||
66 | int sticky; | ||
67 | int odd; | ||
68 | |||
69 | if (xe < -1) { | ||
70 | residue = xm; | ||
71 | round = 0; | ||
72 | sticky = residue != 0; | ||
73 | xm = 0; | ||
74 | } | ||
75 | else { | ||
76 | /* Shifting a u64 64 times does not work, | ||
77 | * so we do it in two steps. Be aware that xe | ||
78 | * may be -1 */ | ||
79 | residue = xm << (xe + 1); | ||
80 | residue <<= 63 - DP_MBITS; | ||
81 | round = (residue >> 63) != 0; | ||
82 | sticky = (residue << 1) != 0; | ||
83 | xm >>= DP_MBITS - xe; | ||
84 | } | ||
85 | odd = (xm & 0x1) != 0x0; | ||
86 | switch (ieee754_csr.rm) { | ||
87 | case IEEE754_RN: | ||
88 | if (round && (sticky || odd)) | ||
89 | xm++; | ||
90 | break; | ||
91 | case IEEE754_RZ: | ||
92 | break; | ||
93 | case IEEE754_RU: /* toward +Infinity */ | ||
94 | if ((round || sticky) && !xs) | ||
95 | xm++; | ||
96 | break; | ||
97 | case IEEE754_RD: /* toward -Infinity */ | ||
98 | if ((round || sticky) && xs) | ||
99 | xm++; | ||
100 | break; | ||
101 | } | ||
102 | if ((xm >> 63) != 0) { | ||
103 | /* This can happen after rounding */ | ||
104 | SETCX(IEEE754_INVALID_OPERATION); | ||
105 | return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); | ||
106 | } | ||
107 | if (round || sticky) | ||
108 | SETCX(IEEE754_INEXACT); | ||
109 | } | ||
110 | if (xs) | ||
111 | return -xm; | ||
112 | else | ||
113 | return xm; | ||
114 | } | ||
115 | |||
116 | |||
117 | u64 ieee754dp_tulong(ieee754dp x) | ||
118 | { | ||
119 | ieee754dp hb = ieee754dp_1e63(); | ||
120 | |||
121 | /* what if x < 0 ?? */ | ||
122 | if (ieee754dp_lt(x, hb)) | ||
123 | return (u64) ieee754dp_tlong(x); | ||
124 | |||
125 | return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) | | ||
126 | (1ULL << 63); | ||
127 | } | ||
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c new file mode 100644 index 000000000000..aa989c2246da --- /dev/null +++ b/arch/mips/math-emu/dsemul.c | |||
@@ -0,0 +1,172 @@ | |||
1 | #include <linux/compiler.h> | ||
2 | #include <linux/mm.h> | ||
3 | #include <linux/signal.h> | ||
4 | #include <linux/smp.h> | ||
5 | #include <linux/smp_lock.h> | ||
6 | |||
7 | #include <asm/asm.h> | ||
8 | #include <asm/bootinfo.h> | ||
9 | #include <asm/byteorder.h> | ||
10 | #include <asm/cpu.h> | ||
11 | #include <asm/inst.h> | ||
12 | #include <asm/processor.h> | ||
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/branch.h> | ||
15 | #include <asm/mipsregs.h> | ||
16 | #include <asm/system.h> | ||
17 | #include <asm/cacheflush.h> | ||
18 | |||
19 | #include <asm/fpu_emulator.h> | ||
20 | |||
21 | #include "ieee754.h" | ||
22 | #include "dsemul.h" | ||
23 | |||
24 | /* Strap kernel emulator for full MIPS IV emulation */ | ||
25 | |||
26 | #ifdef __mips | ||
27 | #undef __mips | ||
28 | #endif | ||
29 | #define __mips 4 | ||
30 | |||
31 | extern struct mips_fpu_emulator_private fpuemuprivate; | ||
32 | |||
33 | |||
34 | /* | ||
35 | * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when | ||
36 | * we have to emulate the instruction in a COP1 branch delay slot. Do | ||
37 | * not change cp0_epc due to the instruction | ||
38 | * | ||
39 | * According to the spec: | ||
40 | * 1) it shouldnt be a branch :-) | ||
41 | * 2) it can be a COP instruction :-( | ||
42 | * 3) if we are tring to run a protected memory space we must take | ||
43 | * special care on memory access instructions :-( | ||
44 | */ | ||
45 | |||
46 | /* | ||
47 | * "Trampoline" return routine to catch exception following | ||
48 | * execution of delay-slot instruction execution. | ||
49 | */ | ||
50 | |||
51 | struct emuframe { | ||
52 | mips_instruction emul; | ||
53 | mips_instruction badinst; | ||
54 | mips_instruction cookie; | ||
55 | gpreg_t epc; | ||
56 | }; | ||
57 | |||
58 | int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc) | ||
59 | { | ||
60 | extern asmlinkage void handle_dsemulret(void); | ||
61 | mips_instruction *dsemul_insns; | ||
62 | struct emuframe *fr; | ||
63 | int err; | ||
64 | |||
65 | if (ir == 0) { /* a nop is easy */ | ||
66 | regs->cp0_epc = cpc; | ||
67 | regs->cp0_cause &= ~CAUSEF_BD; | ||
68 | return 0; | ||
69 | } | ||
70 | #ifdef DSEMUL_TRACE | ||
71 | printk("dsemul %lx %lx\n", regs->cp0_epc, cpc); | ||
72 | |||
73 | #endif | ||
74 | |||
75 | /* | ||
76 | * The strategy is to push the instruction onto the user stack | ||
77 | * and put a trap after it which we can catch and jump to | ||
78 | * the required address any alternative apart from full | ||
79 | * instruction emulation!!. | ||
80 | * | ||
81 | * Algorithmics used a system call instruction, and | ||
82 | * borrowed that vector. MIPS/Linux version is a bit | ||
83 | * more heavyweight in the interests of portability and | ||
84 | * multiprocessor support. For Linux we generate a | ||
85 | * an unaligned access and force an address error exception. | ||
86 | * | ||
87 | * For embedded systems (stand-alone) we prefer to use a | ||
88 | * non-existing CP1 instruction. This prevents us from emulating | ||
89 | * branches, but gives us a cleaner interface to the exception | ||
90 | * handler (single entry point). | ||
91 | */ | ||
92 | |||
93 | /* Ensure that the two instructions are in the same cache line */ | ||
94 | dsemul_insns = (mips_instruction *) REG_TO_VA ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7); | ||
95 | fr = (struct emuframe *) dsemul_insns; | ||
96 | |||
97 | /* Verify that the stack pointer is not competely insane */ | ||
98 | if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe)))) | ||
99 | return SIGBUS; | ||
100 | |||
101 | err = __put_user(ir, &fr->emul); | ||
102 | err |= __put_user((mips_instruction)BADINST, &fr->badinst); | ||
103 | err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie); | ||
104 | err |= __put_user(cpc, &fr->epc); | ||
105 | |||
106 | if (unlikely(err)) { | ||
107 | fpuemuprivate.stats.errors++; | ||
108 | return SIGBUS; | ||
109 | } | ||
110 | |||
111 | regs->cp0_epc = VA_TO_REG & fr->emul; | ||
112 | |||
113 | flush_cache_sigtramp((unsigned long)&fr->badinst); | ||
114 | |||
115 | return SIGILL; /* force out of emulation loop */ | ||
116 | } | ||
117 | |||
118 | int do_dsemulret(struct pt_regs *xcp) | ||
119 | { | ||
120 | struct emuframe *fr; | ||
121 | gpreg_t epc; | ||
122 | u32 insn, cookie; | ||
123 | int err = 0; | ||
124 | |||
125 | fr = (struct emuframe *) (xcp->cp0_epc - sizeof(mips_instruction)); | ||
126 | |||
127 | /* | ||
128 | * If we can't even access the area, something is very wrong, but we'll | ||
129 | * leave that to the default handling | ||
130 | */ | ||
131 | if (!access_ok(VERIFY_READ, fr, sizeof(struct emuframe))) | ||
132 | return 0; | ||
133 | |||
134 | /* | ||
135 | * Do some sanity checking on the stackframe: | ||
136 | * | ||
137 | * - Is the instruction pointed to by the EPC an BADINST? | ||
138 | * - Is the following memory word the BD_COOKIE? | ||
139 | */ | ||
140 | err = __get_user(insn, &fr->badinst); | ||
141 | err |= __get_user(cookie, &fr->cookie); | ||
142 | |||
143 | if (unlikely(err || (insn != BADINST) || (cookie != BD_COOKIE))) { | ||
144 | fpuemuprivate.stats.errors++; | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * At this point, we are satisfied that it's a BD emulation trap. Yes, | ||
150 | * a user might have deliberately put two malformed and useless | ||
151 | * instructions in a row in his program, in which case he's in for a | ||
152 | * nasty surprise - the next instruction will be treated as a | ||
153 | * continuation address! Alas, this seems to be the only way that we | ||
154 | * can handle signals, recursion, and longjmps() in the context of | ||
155 | * emulating the branch delay instruction. | ||
156 | */ | ||
157 | |||
158 | #ifdef DSEMUL_TRACE | ||
159 | printk("dsemulret\n"); | ||
160 | #endif | ||
161 | if (__get_user(epc, &fr->epc)) { /* Saved EPC */ | ||
162 | /* This is not a good situation to be in */ | ||
163 | force_sig(SIGBUS, current); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | /* Set EPC to return to post-branch instruction */ | ||
169 | xcp->cp0_epc = epc; | ||
170 | |||
171 | return 1; | ||
172 | } | ||
diff --git a/arch/mips/math-emu/dsemul.h b/arch/mips/math-emu/dsemul.h new file mode 100644 index 000000000000..dbd85f95268d --- /dev/null +++ b/arch/mips/math-emu/dsemul.h | |||
@@ -0,0 +1,23 @@ | |||
1 | typedef long gpreg_t; | ||
2 | typedef void *vaddr_t; | ||
3 | |||
4 | #define REG_TO_VA (vaddr_t) | ||
5 | #define VA_TO_REG (gpreg_t) | ||
6 | |||
7 | int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc); | ||
8 | int do_dsemulret(struct pt_regs *xcp); | ||
9 | |||
10 | /* Instruction which will always cause an address error */ | ||
11 | #define AdELOAD 0x8c000001 /* lw $0,1($0) */ | ||
12 | /* Instruction which will plainly cause a CP1 exception when FPU is disabled */ | ||
13 | #define CP1UNDEF 0x44400001 /* cfc1 $0,$0 undef */ | ||
14 | |||
15 | /* Instruction inserted following the badinst to further tag the sequence */ | ||
16 | #define BD_COOKIE 0x0000bd36 /* tne $0,$0 with baggage */ | ||
17 | |||
18 | /* Setup which instruction to use for trampoline */ | ||
19 | #ifdef STANDALONE_EMULATOR | ||
20 | #define BADINST CP1UNDEF | ||
21 | #else | ||
22 | #define BADINST AdELOAD | ||
23 | #endif | ||
diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c new file mode 100644 index 000000000000..f0a364adbf34 --- /dev/null +++ b/arch/mips/math-emu/ieee754.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* ieee754 floating point arithmetic | ||
2 | * single and double precision | ||
3 | * | ||
4 | * BUGS | ||
5 | * not much dp done | ||
6 | * doesn't generate IEEE754_INEXACT | ||
7 | * | ||
8 | */ | ||
9 | /* | ||
10 | * MIPS floating point support | ||
11 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
12 | * http://www.algor.co.uk | ||
13 | * | ||
14 | * ######################################################################## | ||
15 | * | ||
16 | * This program is free software; you can distribute it and/or modify it | ||
17 | * under the terms of the GNU General Public License (Version 2) as | ||
18 | * published by the Free Software Foundation. | ||
19 | * | ||
20 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
21 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
22 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
23 | * for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along | ||
26 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
28 | * | ||
29 | * ######################################################################## | ||
30 | */ | ||
31 | |||
32 | |||
33 | #include "ieee754int.h" | ||
34 | |||
35 | #define DP_EBIAS 1023 | ||
36 | #define DP_EMIN (-1022) | ||
37 | #define DP_EMAX 1023 | ||
38 | |||
39 | #define SP_EBIAS 127 | ||
40 | #define SP_EMIN (-126) | ||
41 | #define SP_EMAX 127 | ||
42 | |||
43 | /* indexed by class */ | ||
44 | const char *const ieee754_cname[] = { | ||
45 | "Normal", | ||
46 | "Zero", | ||
47 | "Denormal", | ||
48 | "Infinity", | ||
49 | "QNaN", | ||
50 | "SNaN", | ||
51 | }; | ||
52 | |||
53 | /* the control status register | ||
54 | */ | ||
55 | struct ieee754_csr ieee754_csr; | ||
56 | |||
57 | /* special constants | ||
58 | */ | ||
59 | |||
60 | |||
61 | #if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) | ||
62 | #define SPSTR(s,b,m) {m,b,s} | ||
63 | #define DPSTR(s,b,mh,ml) {ml,mh,b,s} | ||
64 | #endif | ||
65 | |||
66 | #ifdef __MIPSEB__ | ||
67 | #define SPSTR(s,b,m) {s,b,m} | ||
68 | #define DPSTR(s,b,mh,ml) {s,b,mh,ml} | ||
69 | #endif | ||
70 | |||
71 | const struct ieee754dp_konst __ieee754dp_spcvals[] = { | ||
72 | DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */ | ||
73 | DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */ | ||
74 | DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */ | ||
75 | DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */ | ||
76 | DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */ | ||
77 | DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */ | ||
78 | DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */ | ||
79 | DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */ | ||
80 | DPSTR(0,DP_EMAX+1+DP_EBIAS,0x7FFFF,0xFFFFFFFF), /* + indef quiet Nan */ | ||
81 | DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */ | ||
82 | DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */ | ||
83 | DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */ | ||
84 | DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */ | ||
85 | DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */ | ||
86 | DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */ | ||
87 | DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */ | ||
88 | DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */ | ||
89 | }; | ||
90 | |||
91 | const struct ieee754sp_konst __ieee754sp_spcvals[] = { | ||
92 | SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */ | ||
93 | SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */ | ||
94 | SPSTR(0, SP_EBIAS, 0), /* + 1.0 */ | ||
95 | SPSTR(1, SP_EBIAS, 0), /* - 1.0 */ | ||
96 | SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */ | ||
97 | SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */ | ||
98 | SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */ | ||
99 | SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */ | ||
100 | SPSTR(0,SP_EMAX+1+SP_EBIAS,0x3FFFFF), /* + indef quiet Nan */ | ||
101 | SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */ | ||
102 | SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */ | ||
103 | SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */ | ||
104 | SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */ | ||
105 | SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */ | ||
106 | SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */ | ||
107 | SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */ | ||
108 | SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */ | ||
109 | }; | ||
110 | |||
111 | |||
112 | int ieee754si_xcpt(int r, const char *op, ...) | ||
113 | { | ||
114 | struct ieee754xctx ax; | ||
115 | |||
116 | if (!TSTX()) | ||
117 | return r; | ||
118 | ax.op = op; | ||
119 | ax.rt = IEEE754_RT_SI; | ||
120 | ax.rv.si = r; | ||
121 | va_start(ax.ap, op); | ||
122 | ieee754_xcpt(&ax); | ||
123 | return ax.rv.si; | ||
124 | } | ||
125 | |||
126 | s64 ieee754di_xcpt(s64 r, const char *op, ...) | ||
127 | { | ||
128 | struct ieee754xctx ax; | ||
129 | |||
130 | if (!TSTX()) | ||
131 | return r; | ||
132 | ax.op = op; | ||
133 | ax.rt = IEEE754_RT_DI; | ||
134 | ax.rv.di = r; | ||
135 | va_start(ax.ap, op); | ||
136 | ieee754_xcpt(&ax); | ||
137 | return ax.rv.di; | ||
138 | } | ||
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h new file mode 100644 index 000000000000..b8772f46972d --- /dev/null +++ b/arch/mips/math-emu/ieee754.h | |||
@@ -0,0 +1,489 @@ | |||
1 | /* single and double precision fp ops | ||
2 | * missing extended precision. | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | /************************************************************************** | ||
28 | * Nov 7, 2000 | ||
29 | * Modification to allow integration with Linux kernel | ||
30 | * | ||
31 | * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com | ||
32 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | ||
33 | *************************************************************************/ | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | /* Going from Algorithmics to Linux native environment, add this */ | ||
37 | #include <linux/types.h> | ||
38 | |||
39 | /* | ||
40 | * Not very pretty, but the Linux kernel's normal va_list definition | ||
41 | * does not allow it to be used as a structure element, as it is here. | ||
42 | */ | ||
43 | #ifndef _STDARG_H | ||
44 | #include <stdarg.h> | ||
45 | #endif | ||
46 | |||
47 | #else | ||
48 | |||
49 | /* Note that __KERNEL__ is taken to mean Linux kernel */ | ||
50 | |||
51 | #if #system(OpenBSD) | ||
52 | #include <machine/types.h> | ||
53 | #endif | ||
54 | #include <machine/endian.h> | ||
55 | |||
56 | #endif /* __KERNEL__ */ | ||
57 | |||
58 | #if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) | ||
59 | struct ieee754dp_konst { | ||
60 | unsigned mantlo:32; | ||
61 | unsigned manthi:20; | ||
62 | unsigned bexp:11; | ||
63 | unsigned sign:1; | ||
64 | }; | ||
65 | struct ieee754sp_konst { | ||
66 | unsigned mant:23; | ||
67 | unsigned bexp:8; | ||
68 | unsigned sign:1; | ||
69 | }; | ||
70 | |||
71 | typedef union _ieee754dp { | ||
72 | struct ieee754dp_konst oparts; | ||
73 | struct { | ||
74 | u64 mant:52; | ||
75 | unsigned int bexp:11; | ||
76 | unsigned int sign:1; | ||
77 | } parts; | ||
78 | u64 bits; | ||
79 | double d; | ||
80 | } ieee754dp; | ||
81 | |||
82 | typedef union _ieee754sp { | ||
83 | struct ieee754sp_konst parts; | ||
84 | float f; | ||
85 | u32 bits; | ||
86 | } ieee754sp; | ||
87 | #endif | ||
88 | |||
89 | #if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) | ||
90 | struct ieee754dp_konst { | ||
91 | unsigned sign:1; | ||
92 | unsigned bexp:11; | ||
93 | unsigned manthi:20; | ||
94 | unsigned mantlo:32; | ||
95 | }; | ||
96 | typedef union _ieee754dp { | ||
97 | struct ieee754dp_konst oparts; | ||
98 | struct { | ||
99 | unsigned int sign:1; | ||
100 | unsigned int bexp:11; | ||
101 | u64 mant:52; | ||
102 | } parts; | ||
103 | double d; | ||
104 | u64 bits; | ||
105 | } ieee754dp; | ||
106 | |||
107 | struct ieee754sp_konst { | ||
108 | unsigned sign:1; | ||
109 | unsigned bexp:8; | ||
110 | unsigned mant:23; | ||
111 | }; | ||
112 | |||
113 | typedef union _ieee754sp { | ||
114 | struct ieee754sp_konst parts; | ||
115 | float f; | ||
116 | u32 bits; | ||
117 | } ieee754sp; | ||
118 | #endif | ||
119 | |||
120 | /* | ||
121 | * single precision (often aka float) | ||
122 | */ | ||
123 | int ieee754sp_finite(ieee754sp x); | ||
124 | int ieee754sp_class(ieee754sp x); | ||
125 | |||
126 | ieee754sp ieee754sp_abs(ieee754sp x); | ||
127 | ieee754sp ieee754sp_neg(ieee754sp x); | ||
128 | ieee754sp ieee754sp_scalb(ieee754sp x, int); | ||
129 | ieee754sp ieee754sp_logb(ieee754sp x); | ||
130 | |||
131 | /* x with sign of y */ | ||
132 | ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y); | ||
133 | |||
134 | ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y); | ||
135 | ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y); | ||
136 | ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y); | ||
137 | ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y); | ||
138 | |||
139 | ieee754sp ieee754sp_fint(int x); | ||
140 | ieee754sp ieee754sp_funs(unsigned x); | ||
141 | ieee754sp ieee754sp_flong(s64 x); | ||
142 | ieee754sp ieee754sp_fulong(u64 x); | ||
143 | ieee754sp ieee754sp_fdp(ieee754dp x); | ||
144 | |||
145 | int ieee754sp_tint(ieee754sp x); | ||
146 | unsigned int ieee754sp_tuns(ieee754sp x); | ||
147 | s64 ieee754sp_tlong(ieee754sp x); | ||
148 | u64 ieee754sp_tulong(ieee754sp x); | ||
149 | |||
150 | int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig); | ||
151 | /* | ||
152 | * basic sp math | ||
153 | */ | ||
154 | ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip); | ||
155 | ieee754sp ieee754sp_frexp(ieee754sp x, int *exp); | ||
156 | ieee754sp ieee754sp_ldexp(ieee754sp x, int exp); | ||
157 | |||
158 | ieee754sp ieee754sp_ceil(ieee754sp x); | ||
159 | ieee754sp ieee754sp_floor(ieee754sp x); | ||
160 | ieee754sp ieee754sp_trunc(ieee754sp x); | ||
161 | |||
162 | ieee754sp ieee754sp_sqrt(ieee754sp x); | ||
163 | |||
164 | /* | ||
165 | * double precision (often aka double) | ||
166 | */ | ||
167 | int ieee754dp_finite(ieee754dp x); | ||
168 | int ieee754dp_class(ieee754dp x); | ||
169 | |||
170 | /* x with sign of y */ | ||
171 | ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y); | ||
172 | |||
173 | ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y); | ||
174 | ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y); | ||
175 | ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y); | ||
176 | ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y); | ||
177 | |||
178 | ieee754dp ieee754dp_abs(ieee754dp x); | ||
179 | ieee754dp ieee754dp_neg(ieee754dp x); | ||
180 | ieee754dp ieee754dp_scalb(ieee754dp x, int); | ||
181 | |||
182 | /* return exponent as integer in floating point format | ||
183 | */ | ||
184 | ieee754dp ieee754dp_logb(ieee754dp x); | ||
185 | |||
186 | ieee754dp ieee754dp_fint(int x); | ||
187 | ieee754dp ieee754dp_funs(unsigned x); | ||
188 | ieee754dp ieee754dp_flong(s64 x); | ||
189 | ieee754dp ieee754dp_fulong(u64 x); | ||
190 | ieee754dp ieee754dp_fsp(ieee754sp x); | ||
191 | |||
192 | ieee754dp ieee754dp_ceil(ieee754dp x); | ||
193 | ieee754dp ieee754dp_floor(ieee754dp x); | ||
194 | ieee754dp ieee754dp_trunc(ieee754dp x); | ||
195 | |||
196 | int ieee754dp_tint(ieee754dp x); | ||
197 | unsigned int ieee754dp_tuns(ieee754dp x); | ||
198 | s64 ieee754dp_tlong(ieee754dp x); | ||
199 | u64 ieee754dp_tulong(ieee754dp x); | ||
200 | |||
201 | int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig); | ||
202 | /* | ||
203 | * basic sp math | ||
204 | */ | ||
205 | ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip); | ||
206 | ieee754dp ieee754dp_frexp(ieee754dp x, int *exp); | ||
207 | ieee754dp ieee754dp_ldexp(ieee754dp x, int exp); | ||
208 | |||
209 | ieee754dp ieee754dp_ceil(ieee754dp x); | ||
210 | ieee754dp ieee754dp_floor(ieee754dp x); | ||
211 | ieee754dp ieee754dp_trunc(ieee754dp x); | ||
212 | |||
213 | ieee754dp ieee754dp_sqrt(ieee754dp x); | ||
214 | |||
215 | |||
216 | |||
217 | /* 5 types of floating point number | ||
218 | */ | ||
219 | #define IEEE754_CLASS_NORM 0x00 | ||
220 | #define IEEE754_CLASS_ZERO 0x01 | ||
221 | #define IEEE754_CLASS_DNORM 0x02 | ||
222 | #define IEEE754_CLASS_INF 0x03 | ||
223 | #define IEEE754_CLASS_SNAN 0x04 | ||
224 | #define IEEE754_CLASS_QNAN 0x05 | ||
225 | extern const char *const ieee754_cname[]; | ||
226 | |||
227 | /* exception numbers */ | ||
228 | #define IEEE754_INEXACT 0x01 | ||
229 | #define IEEE754_UNDERFLOW 0x02 | ||
230 | #define IEEE754_OVERFLOW 0x04 | ||
231 | #define IEEE754_ZERO_DIVIDE 0x08 | ||
232 | #define IEEE754_INVALID_OPERATION 0x10 | ||
233 | |||
234 | /* cmp operators | ||
235 | */ | ||
236 | #define IEEE754_CLT 0x01 | ||
237 | #define IEEE754_CEQ 0x02 | ||
238 | #define IEEE754_CGT 0x04 | ||
239 | #define IEEE754_CUN 0x08 | ||
240 | |||
241 | /* rounding mode | ||
242 | */ | ||
243 | #define IEEE754_RN 0 /* round to nearest */ | ||
244 | #define IEEE754_RZ 1 /* round toward zero */ | ||
245 | #define IEEE754_RD 2 /* round toward -Infinity */ | ||
246 | #define IEEE754_RU 3 /* round toward +Infinity */ | ||
247 | |||
248 | /* other naming */ | ||
249 | #define IEEE754_RM IEEE754_RD | ||
250 | #define IEEE754_RP IEEE754_RU | ||
251 | |||
252 | /* "normal" comparisons | ||
253 | */ | ||
254 | static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y) | ||
255 | { | ||
256 | return ieee754sp_cmp(x, y, IEEE754_CEQ, 0); | ||
257 | } | ||
258 | |||
259 | static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y) | ||
260 | { | ||
261 | return ieee754sp_cmp(x, y, | ||
262 | IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); | ||
263 | } | ||
264 | |||
265 | static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y) | ||
266 | { | ||
267 | return ieee754sp_cmp(x, y, IEEE754_CLT, 0); | ||
268 | } | ||
269 | |||
270 | static __inline int ieee754sp_le(ieee754sp x, ieee754sp y) | ||
271 | { | ||
272 | return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); | ||
273 | } | ||
274 | |||
275 | static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y) | ||
276 | { | ||
277 | return ieee754sp_cmp(x, y, IEEE754_CGT, 0); | ||
278 | } | ||
279 | |||
280 | |||
281 | static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y) | ||
282 | { | ||
283 | return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); | ||
284 | } | ||
285 | |||
286 | static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y) | ||
287 | { | ||
288 | return ieee754dp_cmp(x, y, IEEE754_CEQ, 0); | ||
289 | } | ||
290 | |||
291 | static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y) | ||
292 | { | ||
293 | return ieee754dp_cmp(x, y, | ||
294 | IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); | ||
295 | } | ||
296 | |||
297 | static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y) | ||
298 | { | ||
299 | return ieee754dp_cmp(x, y, IEEE754_CLT, 0); | ||
300 | } | ||
301 | |||
302 | static __inline int ieee754dp_le(ieee754dp x, ieee754dp y) | ||
303 | { | ||
304 | return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); | ||
305 | } | ||
306 | |||
307 | static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y) | ||
308 | { | ||
309 | return ieee754dp_cmp(x, y, IEEE754_CGT, 0); | ||
310 | } | ||
311 | |||
312 | static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y) | ||
313 | { | ||
314 | return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); | ||
315 | } | ||
316 | |||
317 | |||
318 | /* like strtod | ||
319 | */ | ||
320 | ieee754dp ieee754dp_fstr(const char *s, char **endp); | ||
321 | char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); | ||
322 | |||
323 | |||
324 | /* the control status register | ||
325 | */ | ||
326 | struct ieee754_csr { | ||
327 | unsigned pad:13; | ||
328 | unsigned nod:1; /* set 1 for no denormalised numbers */ | ||
329 | unsigned cx:5; /* exceptions this operation */ | ||
330 | unsigned mx:5; /* exception enable mask */ | ||
331 | unsigned sx:5; /* exceptions total */ | ||
332 | unsigned rm:2; /* current rounding mode */ | ||
333 | }; | ||
334 | extern struct ieee754_csr ieee754_csr; | ||
335 | |||
336 | static __inline unsigned ieee754_getrm(void) | ||
337 | { | ||
338 | return (ieee754_csr.rm); | ||
339 | } | ||
340 | static __inline unsigned ieee754_setrm(unsigned rm) | ||
341 | { | ||
342 | return (ieee754_csr.rm = rm); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * get current exceptions | ||
347 | */ | ||
348 | static __inline unsigned ieee754_getcx(void) | ||
349 | { | ||
350 | return (ieee754_csr.cx); | ||
351 | } | ||
352 | |||
353 | /* test for current exception condition | ||
354 | */ | ||
355 | static __inline int ieee754_cxtest(unsigned n) | ||
356 | { | ||
357 | return (ieee754_csr.cx & n); | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * get sticky exceptions | ||
362 | */ | ||
363 | static __inline unsigned ieee754_getsx(void) | ||
364 | { | ||
365 | return (ieee754_csr.sx); | ||
366 | } | ||
367 | |||
368 | /* clear sticky conditions | ||
369 | */ | ||
370 | static __inline unsigned ieee754_clrsx(void) | ||
371 | { | ||
372 | return (ieee754_csr.sx = 0); | ||
373 | } | ||
374 | |||
375 | /* test for sticky exception condition | ||
376 | */ | ||
377 | static __inline int ieee754_sxtest(unsigned n) | ||
378 | { | ||
379 | return (ieee754_csr.sx & n); | ||
380 | } | ||
381 | |||
382 | /* debugging */ | ||
383 | ieee754sp ieee754sp_dump(char *s, ieee754sp x); | ||
384 | ieee754dp ieee754dp_dump(char *s, ieee754dp x); | ||
385 | |||
386 | #define IEEE754_SPCVAL_PZERO 0 | ||
387 | #define IEEE754_SPCVAL_NZERO 1 | ||
388 | #define IEEE754_SPCVAL_PONE 2 | ||
389 | #define IEEE754_SPCVAL_NONE 3 | ||
390 | #define IEEE754_SPCVAL_PTEN 4 | ||
391 | #define IEEE754_SPCVAL_NTEN 5 | ||
392 | #define IEEE754_SPCVAL_PINFINITY 6 | ||
393 | #define IEEE754_SPCVAL_NINFINITY 7 | ||
394 | #define IEEE754_SPCVAL_INDEF 8 | ||
395 | #define IEEE754_SPCVAL_PMAX 9 /* +max norm */ | ||
396 | #define IEEE754_SPCVAL_NMAX 10 /* -max norm */ | ||
397 | #define IEEE754_SPCVAL_PMIN 11 /* +min norm */ | ||
398 | #define IEEE754_SPCVAL_NMIN 12 /* +min norm */ | ||
399 | #define IEEE754_SPCVAL_PMIND 13 /* +min denorm */ | ||
400 | #define IEEE754_SPCVAL_NMIND 14 /* +min denorm */ | ||
401 | #define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ | ||
402 | #define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ | ||
403 | |||
404 | extern const struct ieee754dp_konst __ieee754dp_spcvals[]; | ||
405 | extern const struct ieee754sp_konst __ieee754sp_spcvals[]; | ||
406 | #define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals) | ||
407 | #define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals) | ||
408 | |||
409 | /* return infinity with given sign | ||
410 | */ | ||
411 | #define ieee754dp_inf(sn) \ | ||
412 | (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)]) | ||
413 | #define ieee754dp_zero(sn) \ | ||
414 | (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) | ||
415 | #define ieee754dp_one(sn) \ | ||
416 | (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) | ||
417 | #define ieee754dp_ten(sn) \ | ||
418 | (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) | ||
419 | #define ieee754dp_indef() \ | ||
420 | (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF]) | ||
421 | #define ieee754dp_max(sn) \ | ||
422 | (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) | ||
423 | #define ieee754dp_min(sn) \ | ||
424 | (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) | ||
425 | #define ieee754dp_mind(sn) \ | ||
426 | (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) | ||
427 | #define ieee754dp_1e31() \ | ||
428 | (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31]) | ||
429 | #define ieee754dp_1e63() \ | ||
430 | (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63]) | ||
431 | |||
432 | #define ieee754sp_inf(sn) \ | ||
433 | (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)]) | ||
434 | #define ieee754sp_zero(sn) \ | ||
435 | (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) | ||
436 | #define ieee754sp_one(sn) \ | ||
437 | (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) | ||
438 | #define ieee754sp_ten(sn) \ | ||
439 | (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) | ||
440 | #define ieee754sp_indef() \ | ||
441 | (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF]) | ||
442 | #define ieee754sp_max(sn) \ | ||
443 | (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) | ||
444 | #define ieee754sp_min(sn) \ | ||
445 | (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) | ||
446 | #define ieee754sp_mind(sn) \ | ||
447 | (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) | ||
448 | #define ieee754sp_1e31() \ | ||
449 | (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31]) | ||
450 | #define ieee754sp_1e63() \ | ||
451 | (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63]) | ||
452 | |||
453 | /* indefinite integer value | ||
454 | */ | ||
455 | #define ieee754si_indef() INT_MAX | ||
456 | #ifdef LONG_LONG_MAX | ||
457 | #define ieee754di_indef() LONG_LONG_MAX | ||
458 | #else | ||
459 | #define ieee754di_indef() ((s64)(~0ULL>>1)) | ||
460 | #endif | ||
461 | |||
462 | /* IEEE exception context, passed to handler */ | ||
463 | struct ieee754xctx { | ||
464 | const char *op; /* operation name */ | ||
465 | int rt; /* result type */ | ||
466 | union { | ||
467 | ieee754sp sp; /* single precision */ | ||
468 | ieee754dp dp; /* double precision */ | ||
469 | #ifdef IEEE854_XP | ||
470 | ieee754xp xp; /* extended precision */ | ||
471 | #endif | ||
472 | int si; /* standard signed integer (32bits) */ | ||
473 | s64 di; /* extended signed integer (64bits) */ | ||
474 | } rv; /* default result format implied by op */ | ||
475 | va_list ap; | ||
476 | }; | ||
477 | |||
478 | /* result types for xctx.rt */ | ||
479 | #define IEEE754_RT_SP 0 | ||
480 | #define IEEE754_RT_DP 1 | ||
481 | #define IEEE754_RT_XP 2 | ||
482 | #define IEEE754_RT_SI 3 | ||
483 | #define IEEE754_RT_DI 4 | ||
484 | |||
485 | extern void ieee754_xcpt(struct ieee754xctx *xcp); | ||
486 | |||
487 | /* compat */ | ||
488 | #define ieee754dp_fix(x) ieee754dp_tint(x) | ||
489 | #define ieee754sp_fix(x) ieee754sp_tint(x) | ||
diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c new file mode 100644 index 000000000000..7e900f30987e --- /dev/null +++ b/arch/mips/math-emu/ieee754d.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * Some debug functions | ||
3 | * | ||
4 | * MIPS floating point support | ||
5 | * | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * This program is free software; you can distribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License (Version 2) as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
16 | * for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
21 | * | ||
22 | * Nov 7, 2000 | ||
23 | * Modified to build and operate in Linux kernel environment. | ||
24 | * | ||
25 | * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com | ||
26 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | ||
27 | */ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include "ieee754.h" | ||
31 | |||
32 | #define DP_EBIAS 1023 | ||
33 | #define DP_EMIN (-1022) | ||
34 | #define DP_EMAX 1023 | ||
35 | #define DP_FBITS 52 | ||
36 | |||
37 | #define SP_EBIAS 127 | ||
38 | #define SP_EMIN (-126) | ||
39 | #define SP_EMAX 127 | ||
40 | #define SP_FBITS 23 | ||
41 | |||
42 | #define DP_MBIT(x) ((u64)1 << (x)) | ||
43 | #define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) | ||
44 | #define DP_SIGN_BIT DP_MBIT(63) | ||
45 | |||
46 | |||
47 | #define SP_MBIT(x) ((u32)1 << (x)) | ||
48 | #define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) | ||
49 | #define SP_SIGN_BIT SP_MBIT(31) | ||
50 | |||
51 | |||
52 | #define SPSIGN(sp) (sp.parts.sign) | ||
53 | #define SPBEXP(sp) (sp.parts.bexp) | ||
54 | #define SPMANT(sp) (sp.parts.mant) | ||
55 | |||
56 | #define DPSIGN(dp) (dp.parts.sign) | ||
57 | #define DPBEXP(dp) (dp.parts.bexp) | ||
58 | #define DPMANT(dp) (dp.parts.mant) | ||
59 | |||
60 | ieee754dp ieee754dp_dump(char *m, ieee754dp x) | ||
61 | { | ||
62 | int i; | ||
63 | |||
64 | printk("%s", m); | ||
65 | printk("<%08x,%08x>\n", (unsigned) (x.bits >> 32), | ||
66 | (unsigned) x.bits); | ||
67 | printk("\t="); | ||
68 | switch (ieee754dp_class(x)) { | ||
69 | case IEEE754_CLASS_QNAN: | ||
70 | case IEEE754_CLASS_SNAN: | ||
71 | printk("Nan %c", DPSIGN(x) ? '-' : '+'); | ||
72 | for (i = DP_FBITS - 1; i >= 0; i--) | ||
73 | printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); | ||
74 | break; | ||
75 | case IEEE754_CLASS_INF: | ||
76 | printk("%cInfinity", DPSIGN(x) ? '-' : '+'); | ||
77 | break; | ||
78 | case IEEE754_CLASS_ZERO: | ||
79 | printk("%cZero", DPSIGN(x) ? '-' : '+'); | ||
80 | break; | ||
81 | case IEEE754_CLASS_DNORM: | ||
82 | printk("%c0.", DPSIGN(x) ? '-' : '+'); | ||
83 | for (i = DP_FBITS - 1; i >= 0; i--) | ||
84 | printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); | ||
85 | printk("e%d", DPBEXP(x) - DP_EBIAS); | ||
86 | break; | ||
87 | case IEEE754_CLASS_NORM: | ||
88 | printk("%c1.", DPSIGN(x) ? '-' : '+'); | ||
89 | for (i = DP_FBITS - 1; i >= 0; i--) | ||
90 | printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); | ||
91 | printk("e%d", DPBEXP(x) - DP_EBIAS); | ||
92 | break; | ||
93 | default: | ||
94 | printk("Illegal/Unknown IEEE754 value class"); | ||
95 | } | ||
96 | printk("\n"); | ||
97 | return x; | ||
98 | } | ||
99 | |||
100 | ieee754sp ieee754sp_dump(char *m, ieee754sp x) | ||
101 | { | ||
102 | int i; | ||
103 | |||
104 | printk("%s=", m); | ||
105 | printk("<%08x>\n", (unsigned) x.bits); | ||
106 | printk("\t="); | ||
107 | switch (ieee754sp_class(x)) { | ||
108 | case IEEE754_CLASS_QNAN: | ||
109 | case IEEE754_CLASS_SNAN: | ||
110 | printk("Nan %c", SPSIGN(x) ? '-' : '+'); | ||
111 | for (i = SP_FBITS - 1; i >= 0; i--) | ||
112 | printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); | ||
113 | break; | ||
114 | case IEEE754_CLASS_INF: | ||
115 | printk("%cInfinity", SPSIGN(x) ? '-' : '+'); | ||
116 | break; | ||
117 | case IEEE754_CLASS_ZERO: | ||
118 | printk("%cZero", SPSIGN(x) ? '-' : '+'); | ||
119 | break; | ||
120 | case IEEE754_CLASS_DNORM: | ||
121 | printk("%c0.", SPSIGN(x) ? '-' : '+'); | ||
122 | for (i = SP_FBITS - 1; i >= 0; i--) | ||
123 | printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); | ||
124 | printk("e%d", SPBEXP(x) - SP_EBIAS); | ||
125 | break; | ||
126 | case IEEE754_CLASS_NORM: | ||
127 | printk("%c1.", SPSIGN(x) ? '-' : '+'); | ||
128 | for (i = SP_FBITS - 1; i >= 0; i--) | ||
129 | printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); | ||
130 | printk("e%d", SPBEXP(x) - SP_EBIAS); | ||
131 | break; | ||
132 | default: | ||
133 | printk("Illegal/Unknown IEEE754 value class"); | ||
134 | } | ||
135 | printk("\n"); | ||
136 | return x; | ||
137 | } | ||
138 | |||
diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c new file mode 100644 index 000000000000..3e214aac4b12 --- /dev/null +++ b/arch/mips/math-emu/ieee754dp.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * double precision: common utilities | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754dp.h" | ||
29 | |||
30 | int ieee754dp_class(ieee754dp x) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | EXPLODEXDP; | ||
34 | return xc; | ||
35 | } | ||
36 | |||
37 | int ieee754dp_isnan(ieee754dp x) | ||
38 | { | ||
39 | return ieee754dp_class(x) >= IEEE754_CLASS_SNAN; | ||
40 | } | ||
41 | |||
42 | int ieee754dp_issnan(ieee754dp x) | ||
43 | { | ||
44 | assert(ieee754dp_isnan(x)); | ||
45 | return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1)); | ||
46 | } | ||
47 | |||
48 | |||
49 | ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) | ||
50 | { | ||
51 | struct ieee754xctx ax; | ||
52 | if (!TSTX()) | ||
53 | return r; | ||
54 | |||
55 | ax.op = op; | ||
56 | ax.rt = IEEE754_RT_DP; | ||
57 | ax.rv.dp = r; | ||
58 | va_start(ax.ap, op); | ||
59 | ieee754_xcpt(&ax); | ||
60 | return ax.rv.dp; | ||
61 | } | ||
62 | |||
63 | ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) | ||
64 | { | ||
65 | struct ieee754xctx ax; | ||
66 | |||
67 | assert(ieee754dp_isnan(r)); | ||
68 | |||
69 | if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */ | ||
70 | return r; | ||
71 | |||
72 | if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { | ||
73 | /* not enabled convert to a quiet NaN */ | ||
74 | DPMANT(r) &= (~DP_MBIT(DP_MBITS-1)); | ||
75 | if (ieee754dp_isnan(r)) | ||
76 | return r; | ||
77 | else | ||
78 | return ieee754dp_indef(); | ||
79 | } | ||
80 | |||
81 | ax.op = op; | ||
82 | ax.rt = 0; | ||
83 | ax.rv.dp = r; | ||
84 | va_start(ax.ap, op); | ||
85 | ieee754_xcpt(&ax); | ||
86 | return ax.rv.dp; | ||
87 | } | ||
88 | |||
89 | ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y) | ||
90 | { | ||
91 | assert(ieee754dp_isnan(x)); | ||
92 | assert(ieee754dp_isnan(y)); | ||
93 | |||
94 | if (DPMANT(x) > DPMANT(y)) | ||
95 | return x; | ||
96 | else | ||
97 | return y; | ||
98 | } | ||
99 | |||
100 | |||
101 | static u64 get_rounding(int sn, u64 xm) | ||
102 | { | ||
103 | /* inexact must round of 3 bits | ||
104 | */ | ||
105 | if (xm & (DP_MBIT(3) - 1)) { | ||
106 | switch (ieee754_csr.rm) { | ||
107 | case IEEE754_RZ: | ||
108 | break; | ||
109 | case IEEE754_RN: | ||
110 | xm += 0x3 + ((xm >> 3) & 1); | ||
111 | /* xm += (xm&0x8)?0x4:0x3 */ | ||
112 | break; | ||
113 | case IEEE754_RU: /* toward +Infinity */ | ||
114 | if (!sn) /* ?? */ | ||
115 | xm += 0x8; | ||
116 | break; | ||
117 | case IEEE754_RD: /* toward -Infinity */ | ||
118 | if (sn) /* ?? */ | ||
119 | xm += 0x8; | ||
120 | break; | ||
121 | } | ||
122 | } | ||
123 | return xm; | ||
124 | } | ||
125 | |||
126 | |||
127 | /* generate a normal/denormal number with over,under handling | ||
128 | * sn is sign | ||
129 | * xe is an unbiased exponent | ||
130 | * xm is 3bit extended precision value. | ||
131 | */ | ||
132 | ieee754dp ieee754dp_format(int sn, int xe, u64 xm) | ||
133 | { | ||
134 | assert(xm); /* we don't gen exact zeros (probably should) */ | ||
135 | |||
136 | assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */ | ||
137 | assert(xm & (DP_HIDDEN_BIT << 3)); | ||
138 | |||
139 | if (xe < DP_EMIN) { | ||
140 | /* strip lower bits */ | ||
141 | int es = DP_EMIN - xe; | ||
142 | |||
143 | if (ieee754_csr.nod) { | ||
144 | SETCX(IEEE754_UNDERFLOW); | ||
145 | SETCX(IEEE754_INEXACT); | ||
146 | |||
147 | switch(ieee754_csr.rm) { | ||
148 | case IEEE754_RN: | ||
149 | return ieee754dp_zero(sn); | ||
150 | case IEEE754_RZ: | ||
151 | return ieee754dp_zero(sn); | ||
152 | case IEEE754_RU: /* toward +Infinity */ | ||
153 | if(sn == 0) | ||
154 | return ieee754dp_min(0); | ||
155 | else | ||
156 | return ieee754dp_zero(1); | ||
157 | case IEEE754_RD: /* toward -Infinity */ | ||
158 | if(sn == 0) | ||
159 | return ieee754dp_zero(0); | ||
160 | else | ||
161 | return ieee754dp_min(1); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | if (xe == DP_EMIN - 1 | ||
166 | && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3)) | ||
167 | { | ||
168 | /* Not tiny after rounding */ | ||
169 | SETCX(IEEE754_INEXACT); | ||
170 | xm = get_rounding(sn, xm); | ||
171 | xm >>= 1; | ||
172 | /* Clear grs bits */ | ||
173 | xm &= ~(DP_MBIT(3) - 1); | ||
174 | xe++; | ||
175 | } | ||
176 | else { | ||
177 | /* sticky right shift es bits | ||
178 | */ | ||
179 | xm = XDPSRS(xm, es); | ||
180 | xe += es; | ||
181 | assert((xm & (DP_HIDDEN_BIT << 3)) == 0); | ||
182 | assert(xe == DP_EMIN); | ||
183 | } | ||
184 | } | ||
185 | if (xm & (DP_MBIT(3) - 1)) { | ||
186 | SETCX(IEEE754_INEXACT); | ||
187 | if ((xm & (DP_HIDDEN_BIT << 3)) == 0) { | ||
188 | SETCX(IEEE754_UNDERFLOW); | ||
189 | } | ||
190 | |||
191 | /* inexact must round of 3 bits | ||
192 | */ | ||
193 | xm = get_rounding(sn, xm); | ||
194 | /* adjust exponent for rounding add overflowing | ||
195 | */ | ||
196 | if (xm >> (DP_MBITS + 3 + 1)) { | ||
197 | /* add causes mantissa overflow */ | ||
198 | xm >>= 1; | ||
199 | xe++; | ||
200 | } | ||
201 | } | ||
202 | /* strip grs bits */ | ||
203 | xm >>= 3; | ||
204 | |||
205 | assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ | ||
206 | assert(xe >= DP_EMIN); | ||
207 | |||
208 | if (xe > DP_EMAX) { | ||
209 | SETCX(IEEE754_OVERFLOW); | ||
210 | SETCX(IEEE754_INEXACT); | ||
211 | /* -O can be table indexed by (rm,sn) */ | ||
212 | switch (ieee754_csr.rm) { | ||
213 | case IEEE754_RN: | ||
214 | return ieee754dp_inf(sn); | ||
215 | case IEEE754_RZ: | ||
216 | return ieee754dp_max(sn); | ||
217 | case IEEE754_RU: /* toward +Infinity */ | ||
218 | if (sn == 0) | ||
219 | return ieee754dp_inf(0); | ||
220 | else | ||
221 | return ieee754dp_max(1); | ||
222 | case IEEE754_RD: /* toward -Infinity */ | ||
223 | if (sn == 0) | ||
224 | return ieee754dp_max(0); | ||
225 | else | ||
226 | return ieee754dp_inf(1); | ||
227 | } | ||
228 | } | ||
229 | /* gen norm/denorm/zero */ | ||
230 | |||
231 | if ((xm & DP_HIDDEN_BIT) == 0) { | ||
232 | /* we underflow (tiny/zero) */ | ||
233 | assert(xe == DP_EMIN); | ||
234 | if (ieee754_csr.mx & IEEE754_UNDERFLOW) | ||
235 | SETCX(IEEE754_UNDERFLOW); | ||
236 | return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm); | ||
237 | } else { | ||
238 | assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ | ||
239 | assert(xm & DP_HIDDEN_BIT); | ||
240 | |||
241 | return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); | ||
242 | } | ||
243 | } | ||
diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h new file mode 100644 index 000000000000..a37370dae232 --- /dev/null +++ b/arch/mips/math-emu/ieee754dp.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * IEEE754 floating point | ||
3 | * double precision internal header file | ||
4 | */ | ||
5 | /* | ||
6 | * MIPS floating point support | ||
7 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
8 | * http://www.algor.co.uk | ||
9 | * | ||
10 | * ######################################################################## | ||
11 | * | ||
12 | * This program is free software; you can distribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License (Version 2) as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
17 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
19 | * for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License along | ||
22 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
23 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
24 | * | ||
25 | * ######################################################################## | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include "ieee754int.h" | ||
30 | |||
31 | #define assert(expr) ((void)0) | ||
32 | |||
33 | /* 3bit extended double precision sticky right shift */ | ||
34 | #define XDPSRS(v,rs) \ | ||
35 | ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) | ||
36 | |||
37 | #define XDPSRSX1() \ | ||
38 | (xe++, (xm = (xm >> 1) | (xm & 1))) | ||
39 | |||
40 | #define XDPSRS1(v) \ | ||
41 | (((v) >> 1) | ((v) & 1)) | ||
42 | |||
43 | /* convert denormal to normalized with extended exponent */ | ||
44 | #define DPDNORMx(m,e) \ | ||
45 | while( (m >> DP_MBITS) == 0) { m <<= 1; e--; } | ||
46 | #define DPDNORMX DPDNORMx(xm,xe) | ||
47 | #define DPDNORMY DPDNORMx(ym,ye) | ||
48 | |||
49 | static __inline ieee754dp builddp(int s, int bx, u64 m) | ||
50 | { | ||
51 | ieee754dp r; | ||
52 | |||
53 | assert((s) == 0 || (s) == 1); | ||
54 | assert((bx) >= DP_EMIN - 1 + DP_EBIAS | ||
55 | && (bx) <= DP_EMAX + 1 + DP_EBIAS); | ||
56 | assert(((m) >> DP_MBITS) == 0); | ||
57 | |||
58 | r.parts.sign = s; | ||
59 | r.parts.bexp = bx; | ||
60 | r.parts.mant = m; | ||
61 | return r; | ||
62 | } | ||
63 | |||
64 | extern int ieee754dp_isnan(ieee754dp); | ||
65 | extern int ieee754dp_issnan(ieee754dp); | ||
66 | extern int ieee754si_xcpt(int, const char *, ...); | ||
67 | extern s64 ieee754di_xcpt(s64, const char *, ...); | ||
68 | extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...); | ||
69 | extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...); | ||
70 | extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp); | ||
71 | extern ieee754dp ieee754dp_format(int, int, u64); | ||
72 | |||
73 | |||
74 | #define DPNORMRET2(s,e,m,name,a0,a1) \ | ||
75 | { \ | ||
76 | ieee754dp V = ieee754dp_format(s,e,m); \ | ||
77 | if(TSTX()) \ | ||
78 | return ieee754dp_xcpt(V,name,a0,a1); \ | ||
79 | else \ | ||
80 | return V; \ | ||
81 | } | ||
82 | |||
83 | #define DPNORMRET1(s,e,m,name,a0) DPNORMRET2(s,e,m,name,a0,a0) | ||
diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h new file mode 100644 index 000000000000..4a5a81d6b893 --- /dev/null +++ b/arch/mips/math-emu/ieee754int.h | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * IEEE754 floating point | ||
3 | * common internal header file | ||
4 | */ | ||
5 | /* | ||
6 | * MIPS floating point support | ||
7 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
8 | * http://www.algor.co.uk | ||
9 | * | ||
10 | * ######################################################################## | ||
11 | * | ||
12 | * This program is free software; you can distribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License (Version 2) as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
17 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
19 | * for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License along | ||
22 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
23 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
24 | * | ||
25 | * ######################################################################## | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include "ieee754.h" | ||
30 | |||
31 | #define DP_EBIAS 1023 | ||
32 | #define DP_EMIN (-1022) | ||
33 | #define DP_EMAX 1023 | ||
34 | #define DP_MBITS 52 | ||
35 | |||
36 | #define SP_EBIAS 127 | ||
37 | #define SP_EMIN (-126) | ||
38 | #define SP_EMAX 127 | ||
39 | #define SP_MBITS 23 | ||
40 | |||
41 | #define DP_MBIT(x) ((u64)1 << (x)) | ||
42 | #define DP_HIDDEN_BIT DP_MBIT(DP_MBITS) | ||
43 | #define DP_SIGN_BIT DP_MBIT(63) | ||
44 | |||
45 | #define SP_MBIT(x) ((u32)1 << (x)) | ||
46 | #define SP_HIDDEN_BIT SP_MBIT(SP_MBITS) | ||
47 | #define SP_SIGN_BIT SP_MBIT(31) | ||
48 | |||
49 | |||
50 | #define SPSIGN(sp) (sp.parts.sign) | ||
51 | #define SPBEXP(sp) (sp.parts.bexp) | ||
52 | #define SPMANT(sp) (sp.parts.mant) | ||
53 | |||
54 | #define DPSIGN(dp) (dp.parts.sign) | ||
55 | #define DPBEXP(dp) (dp.parts.bexp) | ||
56 | #define DPMANT(dp) (dp.parts.mant) | ||
57 | |||
58 | #define CLPAIR(x,y) ((x)*6+(y)) | ||
59 | |||
60 | #define CLEARCX \ | ||
61 | (ieee754_csr.cx = 0) | ||
62 | |||
63 | #define SETCX(x) \ | ||
64 | (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x)) | ||
65 | |||
66 | #define SETANDTESTCX(x) \ | ||
67 | (SETCX(x),ieee754_csr.mx & (x)) | ||
68 | |||
69 | #define TSTX() \ | ||
70 | (ieee754_csr.cx & ieee754_csr.mx) | ||
71 | |||
72 | |||
73 | #define COMPXSP \ | ||
74 | unsigned xm; int xe; int xs; int xc | ||
75 | |||
76 | #define COMPYSP \ | ||
77 | unsigned ym; int ye; int ys; int yc | ||
78 | |||
79 | #define EXPLODESP(v,vc,vs,ve,vm) \ | ||
80 | {\ | ||
81 | vs = SPSIGN(v);\ | ||
82 | ve = SPBEXP(v);\ | ||
83 | vm = SPMANT(v);\ | ||
84 | if(ve == SP_EMAX+1+SP_EBIAS){\ | ||
85 | if(vm == 0)\ | ||
86 | vc = IEEE754_CLASS_INF;\ | ||
87 | else if(vm & SP_MBIT(SP_MBITS-1)) \ | ||
88 | vc = IEEE754_CLASS_SNAN;\ | ||
89 | else \ | ||
90 | vc = IEEE754_CLASS_QNAN;\ | ||
91 | } else if(ve == SP_EMIN-1+SP_EBIAS) {\ | ||
92 | if(vm) {\ | ||
93 | ve = SP_EMIN;\ | ||
94 | vc = IEEE754_CLASS_DNORM;\ | ||
95 | } else\ | ||
96 | vc = IEEE754_CLASS_ZERO;\ | ||
97 | } else {\ | ||
98 | ve -= SP_EBIAS;\ | ||
99 | vm |= SP_HIDDEN_BIT;\ | ||
100 | vc = IEEE754_CLASS_NORM;\ | ||
101 | }\ | ||
102 | } | ||
103 | #define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm) | ||
104 | #define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym) | ||
105 | |||
106 | |||
107 | #define COMPXDP \ | ||
108 | u64 xm; int xe; int xs; int xc | ||
109 | |||
110 | #define COMPYDP \ | ||
111 | u64 ym; int ye; int ys; int yc | ||
112 | |||
113 | #define EXPLODEDP(v,vc,vs,ve,vm) \ | ||
114 | {\ | ||
115 | vm = DPMANT(v);\ | ||
116 | vs = DPSIGN(v);\ | ||
117 | ve = DPBEXP(v);\ | ||
118 | if(ve == DP_EMAX+1+DP_EBIAS){\ | ||
119 | if(vm == 0)\ | ||
120 | vc = IEEE754_CLASS_INF;\ | ||
121 | else if(vm & DP_MBIT(DP_MBITS-1)) \ | ||
122 | vc = IEEE754_CLASS_SNAN;\ | ||
123 | else \ | ||
124 | vc = IEEE754_CLASS_QNAN;\ | ||
125 | } else if(ve == DP_EMIN-1+DP_EBIAS) {\ | ||
126 | if(vm) {\ | ||
127 | ve = DP_EMIN;\ | ||
128 | vc = IEEE754_CLASS_DNORM;\ | ||
129 | } else\ | ||
130 | vc = IEEE754_CLASS_ZERO;\ | ||
131 | } else {\ | ||
132 | ve -= DP_EBIAS;\ | ||
133 | vm |= DP_HIDDEN_BIT;\ | ||
134 | vc = IEEE754_CLASS_NORM;\ | ||
135 | }\ | ||
136 | } | ||
137 | #define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm) | ||
138 | #define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym) | ||
139 | |||
140 | #define FLUSHDP(v,vc,vs,ve,vm) \ | ||
141 | if(vc==IEEE754_CLASS_DNORM) {\ | ||
142 | if(ieee754_csr.nod) {\ | ||
143 | SETCX(IEEE754_INEXACT);\ | ||
144 | vc = IEEE754_CLASS_ZERO;\ | ||
145 | ve = DP_EMIN-1+DP_EBIAS;\ | ||
146 | vm = 0;\ | ||
147 | v = ieee754dp_zero(vs);\ | ||
148 | }\ | ||
149 | } | ||
150 | |||
151 | #define FLUSHSP(v,vc,vs,ve,vm) \ | ||
152 | if(vc==IEEE754_CLASS_DNORM) {\ | ||
153 | if(ieee754_csr.nod) {\ | ||
154 | SETCX(IEEE754_INEXACT);\ | ||
155 | vc = IEEE754_CLASS_ZERO;\ | ||
156 | ve = SP_EMIN-1+SP_EBIAS;\ | ||
157 | vm = 0;\ | ||
158 | v = ieee754sp_zero(vs);\ | ||
159 | }\ | ||
160 | } | ||
161 | |||
162 | #define FLUSHXDP FLUSHDP(x,xc,xs,xe,xm) | ||
163 | #define FLUSHYDP FLUSHDP(y,yc,ys,ye,ym) | ||
164 | #define FLUSHXSP FLUSHSP(x,xc,xs,xe,xm) | ||
165 | #define FLUSHYSP FLUSHSP(y,yc,ys,ye,ym) | ||
diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c new file mode 100644 index 000000000000..d66896cd8f21 --- /dev/null +++ b/arch/mips/math-emu/ieee754m.c | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * floor, trunc, ceil | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754.h" | ||
29 | |||
30 | ieee754dp ieee754dp_floor(ieee754dp x) | ||
31 | { | ||
32 | ieee754dp i; | ||
33 | |||
34 | if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) | ||
35 | return ieee754dp_sub(i, ieee754dp_one(0)); | ||
36 | else | ||
37 | return i; | ||
38 | } | ||
39 | |||
40 | ieee754dp ieee754dp_ceil(ieee754dp x) | ||
41 | { | ||
42 | ieee754dp i; | ||
43 | |||
44 | if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) | ||
45 | return ieee754dp_add(i, ieee754dp_one(0)); | ||
46 | else | ||
47 | return i; | ||
48 | } | ||
49 | |||
50 | ieee754dp ieee754dp_trunc(ieee754dp x) | ||
51 | { | ||
52 | ieee754dp i; | ||
53 | |||
54 | (void) ieee754dp_modf(x, &i); | ||
55 | return i; | ||
56 | } | ||
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c new file mode 100644 index 000000000000..adda851cd04f --- /dev/null +++ b/arch/mips/math-emu/ieee754sp.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | int ieee754sp_class(ieee754sp x) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | EXPLODEXSP; | ||
34 | return xc; | ||
35 | } | ||
36 | |||
37 | int ieee754sp_isnan(ieee754sp x) | ||
38 | { | ||
39 | return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; | ||
40 | } | ||
41 | |||
42 | int ieee754sp_issnan(ieee754sp x) | ||
43 | { | ||
44 | assert(ieee754sp_isnan(x)); | ||
45 | return (SPMANT(x) & SP_MBIT(SP_MBITS-1)); | ||
46 | } | ||
47 | |||
48 | |||
49 | ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) | ||
50 | { | ||
51 | struct ieee754xctx ax; | ||
52 | |||
53 | if (!TSTX()) | ||
54 | return r; | ||
55 | |||
56 | ax.op = op; | ||
57 | ax.rt = IEEE754_RT_SP; | ||
58 | ax.rv.sp = r; | ||
59 | va_start(ax.ap, op); | ||
60 | ieee754_xcpt(&ax); | ||
61 | return ax.rv.sp; | ||
62 | } | ||
63 | |||
64 | ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) | ||
65 | { | ||
66 | struct ieee754xctx ax; | ||
67 | |||
68 | assert(ieee754sp_isnan(r)); | ||
69 | |||
70 | if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ | ||
71 | return r; | ||
72 | |||
73 | if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { | ||
74 | /* not enabled convert to a quiet NaN */ | ||
75 | SPMANT(r) &= (~SP_MBIT(SP_MBITS-1)); | ||
76 | if (ieee754sp_isnan(r)) | ||
77 | return r; | ||
78 | else | ||
79 | return ieee754sp_indef(); | ||
80 | } | ||
81 | |||
82 | ax.op = op; | ||
83 | ax.rt = 0; | ||
84 | ax.rv.sp = r; | ||
85 | va_start(ax.ap, op); | ||
86 | ieee754_xcpt(&ax); | ||
87 | return ax.rv.sp; | ||
88 | } | ||
89 | |||
90 | ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y) | ||
91 | { | ||
92 | assert(ieee754sp_isnan(x)); | ||
93 | assert(ieee754sp_isnan(y)); | ||
94 | |||
95 | if (SPMANT(x) > SPMANT(y)) | ||
96 | return x; | ||
97 | else | ||
98 | return y; | ||
99 | } | ||
100 | |||
101 | |||
102 | static unsigned get_rounding(int sn, unsigned xm) | ||
103 | { | ||
104 | /* inexact must round of 3 bits | ||
105 | */ | ||
106 | if (xm & (SP_MBIT(3) - 1)) { | ||
107 | switch (ieee754_csr.rm) { | ||
108 | case IEEE754_RZ: | ||
109 | break; | ||
110 | case IEEE754_RN: | ||
111 | xm += 0x3 + ((xm >> 3) & 1); | ||
112 | /* xm += (xm&0x8)?0x4:0x3 */ | ||
113 | break; | ||
114 | case IEEE754_RU: /* toward +Infinity */ | ||
115 | if (!sn) /* ?? */ | ||
116 | xm += 0x8; | ||
117 | break; | ||
118 | case IEEE754_RD: /* toward -Infinity */ | ||
119 | if (sn) /* ?? */ | ||
120 | xm += 0x8; | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | return xm; | ||
125 | } | ||
126 | |||
127 | |||
128 | /* generate a normal/denormal number with over,under handling | ||
129 | * sn is sign | ||
130 | * xe is an unbiased exponent | ||
131 | * xm is 3bit extended precision value. | ||
132 | */ | ||
133 | ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) | ||
134 | { | ||
135 | assert(xm); /* we don't gen exact zeros (probably should) */ | ||
136 | |||
137 | assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */ | ||
138 | assert(xm & (SP_HIDDEN_BIT << 3)); | ||
139 | |||
140 | if (xe < SP_EMIN) { | ||
141 | /* strip lower bits */ | ||
142 | int es = SP_EMIN - xe; | ||
143 | |||
144 | if (ieee754_csr.nod) { | ||
145 | SETCX(IEEE754_UNDERFLOW); | ||
146 | SETCX(IEEE754_INEXACT); | ||
147 | |||
148 | switch(ieee754_csr.rm) { | ||
149 | case IEEE754_RN: | ||
150 | return ieee754sp_zero(sn); | ||
151 | case IEEE754_RZ: | ||
152 | return ieee754sp_zero(sn); | ||
153 | case IEEE754_RU: /* toward +Infinity */ | ||
154 | if(sn == 0) | ||
155 | return ieee754sp_min(0); | ||
156 | else | ||
157 | return ieee754sp_zero(1); | ||
158 | case IEEE754_RD: /* toward -Infinity */ | ||
159 | if(sn == 0) | ||
160 | return ieee754sp_zero(0); | ||
161 | else | ||
162 | return ieee754sp_min(1); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | if (xe == SP_EMIN - 1 | ||
167 | && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) | ||
168 | { | ||
169 | /* Not tiny after rounding */ | ||
170 | SETCX(IEEE754_INEXACT); | ||
171 | xm = get_rounding(sn, xm); | ||
172 | xm >>= 1; | ||
173 | /* Clear grs bits */ | ||
174 | xm &= ~(SP_MBIT(3) - 1); | ||
175 | xe++; | ||
176 | } | ||
177 | else { | ||
178 | /* sticky right shift es bits | ||
179 | */ | ||
180 | SPXSRSXn(es); | ||
181 | assert((xm & (SP_HIDDEN_BIT << 3)) == 0); | ||
182 | assert(xe == SP_EMIN); | ||
183 | } | ||
184 | } | ||
185 | if (xm & (SP_MBIT(3) - 1)) { | ||
186 | SETCX(IEEE754_INEXACT); | ||
187 | if ((xm & (SP_HIDDEN_BIT << 3)) == 0) { | ||
188 | SETCX(IEEE754_UNDERFLOW); | ||
189 | } | ||
190 | |||
191 | /* inexact must round of 3 bits | ||
192 | */ | ||
193 | xm = get_rounding(sn, xm); | ||
194 | /* adjust exponent for rounding add overflowing | ||
195 | */ | ||
196 | if (xm >> (SP_MBITS + 1 + 3)) { | ||
197 | /* add causes mantissa overflow */ | ||
198 | xm >>= 1; | ||
199 | xe++; | ||
200 | } | ||
201 | } | ||
202 | /* strip grs bits */ | ||
203 | xm >>= 3; | ||
204 | |||
205 | assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ | ||
206 | assert(xe >= SP_EMIN); | ||
207 | |||
208 | if (xe > SP_EMAX) { | ||
209 | SETCX(IEEE754_OVERFLOW); | ||
210 | SETCX(IEEE754_INEXACT); | ||
211 | /* -O can be table indexed by (rm,sn) */ | ||
212 | switch (ieee754_csr.rm) { | ||
213 | case IEEE754_RN: | ||
214 | return ieee754sp_inf(sn); | ||
215 | case IEEE754_RZ: | ||
216 | return ieee754sp_max(sn); | ||
217 | case IEEE754_RU: /* toward +Infinity */ | ||
218 | if (sn == 0) | ||
219 | return ieee754sp_inf(0); | ||
220 | else | ||
221 | return ieee754sp_max(1); | ||
222 | case IEEE754_RD: /* toward -Infinity */ | ||
223 | if (sn == 0) | ||
224 | return ieee754sp_max(0); | ||
225 | else | ||
226 | return ieee754sp_inf(1); | ||
227 | } | ||
228 | } | ||
229 | /* gen norm/denorm/zero */ | ||
230 | |||
231 | if ((xm & SP_HIDDEN_BIT) == 0) { | ||
232 | /* we underflow (tiny/zero) */ | ||
233 | assert(xe == SP_EMIN); | ||
234 | if (ieee754_csr.mx & IEEE754_UNDERFLOW) | ||
235 | SETCX(IEEE754_UNDERFLOW); | ||
236 | return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); | ||
237 | } else { | ||
238 | assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ | ||
239 | assert(xm & SP_HIDDEN_BIT); | ||
240 | |||
241 | return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); | ||
242 | } | ||
243 | } | ||
diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h new file mode 100644 index 000000000000..ae82f51297e5 --- /dev/null +++ b/arch/mips/math-emu/ieee754sp.h | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * IEEE754 floating point | ||
3 | * double precision internal header file | ||
4 | */ | ||
5 | /* | ||
6 | * MIPS floating point support | ||
7 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
8 | * http://www.algor.co.uk | ||
9 | * | ||
10 | * ######################################################################## | ||
11 | * | ||
12 | * This program is free software; you can distribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License (Version 2) as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
17 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
19 | * for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License along | ||
22 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
23 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
24 | * | ||
25 | * ######################################################################## | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include "ieee754int.h" | ||
30 | |||
31 | #define assert(expr) ((void)0) | ||
32 | |||
33 | /* 3bit extended single precision sticky right shift */ | ||
34 | #define SPXSRSXn(rs) \ | ||
35 | (xe += rs, \ | ||
36 | xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) | ||
37 | |||
38 | #define SPXSRSX1() \ | ||
39 | (xe++, (xm = (xm >> 1) | (xm & 1))) | ||
40 | |||
41 | #define SPXSRSYn(rs) \ | ||
42 | (ye+=rs, \ | ||
43 | ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) | ||
44 | |||
45 | #define SPXSRSY1() \ | ||
46 | (ye++, (ym = (ym >> 1) | (ym & 1))) | ||
47 | |||
48 | /* convert denormal to normalized with extended exponent */ | ||
49 | #define SPDNORMx(m,e) \ | ||
50 | while( (m >> SP_MBITS) == 0) { m <<= 1; e--; } | ||
51 | #define SPDNORMX SPDNORMx(xm,xe) | ||
52 | #define SPDNORMY SPDNORMx(ym,ye) | ||
53 | |||
54 | static __inline ieee754sp buildsp(int s, int bx, unsigned m) | ||
55 | { | ||
56 | ieee754sp r; | ||
57 | |||
58 | assert((s) == 0 || (s) == 1); | ||
59 | assert((bx) >= SP_EMIN - 1 + SP_EBIAS | ||
60 | && (bx) <= SP_EMAX + 1 + SP_EBIAS); | ||
61 | assert(((m) >> SP_MBITS) == 0); | ||
62 | |||
63 | r.parts.sign = s; | ||
64 | r.parts.bexp = bx; | ||
65 | r.parts.mant = m; | ||
66 | |||
67 | return r; | ||
68 | } | ||
69 | |||
70 | extern int ieee754sp_isnan(ieee754sp); | ||
71 | extern int ieee754sp_issnan(ieee754sp); | ||
72 | extern int ieee754si_xcpt(int, const char *, ...); | ||
73 | extern s64 ieee754di_xcpt(s64, const char *, ...); | ||
74 | extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...); | ||
75 | extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...); | ||
76 | extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp); | ||
77 | extern ieee754sp ieee754sp_format(int, int, unsigned); | ||
78 | |||
79 | |||
80 | #define SPNORMRET2(s,e,m,name,a0,a1) \ | ||
81 | { \ | ||
82 | ieee754sp V = ieee754sp_format(s,e,m); \ | ||
83 | if(TSTX()) \ | ||
84 | return ieee754sp_xcpt(V,name,a0,a1); \ | ||
85 | else \ | ||
86 | return V; \ | ||
87 | } | ||
88 | |||
89 | #define SPNORMRET1(s,e,m,name,a0) SPNORMRET2(s,e,m,name,a0,a0) | ||
diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c new file mode 100644 index 000000000000..7d8ef8965067 --- /dev/null +++ b/arch/mips/math-emu/ieee754xcpt.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * MIPS floating point support | ||
3 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
4 | * http://www.algor.co.uk | ||
5 | * | ||
6 | * ######################################################################## | ||
7 | * | ||
8 | * This program is free software; you can distribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License (Version 2) as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
15 | * for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
20 | * | ||
21 | * ######################################################################## | ||
22 | */ | ||
23 | |||
24 | /************************************************************************** | ||
25 | * Nov 7, 2000 | ||
26 | * Added preprocessor hacks to map to Linux kernel diagnostics. | ||
27 | * | ||
28 | * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com | ||
29 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | ||
30 | *************************************************************************/ | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include "ieee754.h" | ||
34 | |||
35 | /* | ||
36 | * Very naff exception handler (you can plug in your own and | ||
37 | * override this). | ||
38 | */ | ||
39 | |||
40 | static const char *const rtnames[] = { | ||
41 | "sp", "dp", "xp", "si", "di" | ||
42 | }; | ||
43 | |||
44 | void ieee754_xcpt(struct ieee754xctx *xcp) | ||
45 | { | ||
46 | printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n", | ||
47 | xcp->op, rtnames[xcp->rt]); | ||
48 | } | ||
49 | |||
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c new file mode 100644 index 000000000000..04397fec30fc --- /dev/null +++ b/arch/mips/math-emu/kernel_linkage.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com | ||
3 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can distribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License (Version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
17 | * | ||
18 | * Routines corresponding to Linux kernel FP context | ||
19 | * manipulation primitives for the Algorithmics MIPS | ||
20 | * FPU Emulator | ||
21 | */ | ||
22 | #include <linux/config.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <asm/processor.h> | ||
25 | #include <asm/signal.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | |||
28 | #include <asm/fpu_emulator.h> | ||
29 | |||
30 | extern struct mips_fpu_emulator_private fpuemuprivate; | ||
31 | |||
32 | #define SIGNALLING_NAN 0x7ff800007ff80000LL | ||
33 | |||
34 | void fpu_emulator_init_fpu(void) | ||
35 | { | ||
36 | static int first = 1; | ||
37 | int i; | ||
38 | |||
39 | if (first) { | ||
40 | first = 0; | ||
41 | printk("Algorithmics/MIPS FPU Emulator v1.5\n"); | ||
42 | } | ||
43 | |||
44 | current->thread.fpu.soft.fcr31 = 0; | ||
45 | for (i = 0; i < 32; i++) { | ||
46 | current->thread.fpu.soft.fpr[i] = SIGNALLING_NAN; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | |||
51 | /* | ||
52 | * Emulator context save/restore to/from a signal context | ||
53 | * presumed to be on the user stack, and therefore accessed | ||
54 | * with appropriate macros from uaccess.h | ||
55 | */ | ||
56 | |||
57 | int fpu_emulator_save_context(struct sigcontext *sc) | ||
58 | { | ||
59 | int i; | ||
60 | int err = 0; | ||
61 | |||
62 | for (i = 0; i < 32; i++) { | ||
63 | err |= | ||
64 | __put_user(current->thread.fpu.soft.fpr[i], | ||
65 | &sc->sc_fpregs[i]); | ||
66 | } | ||
67 | err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr); | ||
68 | err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir); | ||
69 | |||
70 | return err; | ||
71 | } | ||
72 | |||
73 | int fpu_emulator_restore_context(struct sigcontext *sc) | ||
74 | { | ||
75 | int i; | ||
76 | int err = 0; | ||
77 | |||
78 | for (i = 0; i < 32; i++) { | ||
79 | err |= | ||
80 | __get_user(current->thread.fpu.soft.fpr[i], | ||
81 | &sc->sc_fpregs[i]); | ||
82 | } | ||
83 | err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr); | ||
84 | err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir); | ||
85 | |||
86 | return err; | ||
87 | } | ||
88 | |||
89 | #ifdef CONFIG_MIPS64 | ||
90 | /* | ||
91 | * This is the o32 version | ||
92 | */ | ||
93 | |||
94 | int fpu_emulator_save_context32(struct sigcontext32 *sc) | ||
95 | { | ||
96 | int i; | ||
97 | int err = 0; | ||
98 | |||
99 | for (i = 0; i < 32; i+=2) { | ||
100 | err |= | ||
101 | __put_user(current->thread.fpu.soft.fpr[i], | ||
102 | &sc->sc_fpregs[i]); | ||
103 | } | ||
104 | err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr); | ||
105 | err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir); | ||
106 | |||
107 | return err; | ||
108 | } | ||
109 | |||
110 | int fpu_emulator_restore_context32(struct sigcontext32 *sc) | ||
111 | { | ||
112 | int i; | ||
113 | int err = 0; | ||
114 | |||
115 | for (i = 0; i < 32; i+=2) { | ||
116 | err |= | ||
117 | __get_user(current->thread.fpu.soft.fpr[i], | ||
118 | &sc->sc_fpregs[i]); | ||
119 | } | ||
120 | err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr); | ||
121 | err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir); | ||
122 | |||
123 | return err; | ||
124 | } | ||
125 | #endif | ||
diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c new file mode 100644 index 000000000000..d8c4211bcfbe --- /dev/null +++ b/arch/mips/math-emu/sp_add.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | COMPYSP; | ||
34 | |||
35 | EXPLODEXSP; | ||
36 | EXPLODEYSP; | ||
37 | |||
38 | CLEARCX; | ||
39 | |||
40 | FLUSHXSP; | ||
41 | FLUSHYSP; | ||
42 | |||
43 | switch (CLPAIR(xc, yc)) { | ||
44 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): | ||
45 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): | ||
46 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): | ||
47 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): | ||
48 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): | ||
49 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): | ||
50 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): | ||
51 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): | ||
52 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): | ||
53 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): | ||
54 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y); | ||
57 | |||
58 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): | ||
59 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): | ||
60 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): | ||
61 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): | ||
62 | return y; | ||
63 | |||
64 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | ||
65 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): | ||
66 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): | ||
67 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): | ||
68 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): | ||
69 | return x; | ||
70 | |||
71 | |||
72 | /* Infinity handling | ||
73 | */ | ||
74 | |||
75 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | ||
76 | if (xs == ys) | ||
77 | return x; | ||
78 | SETCX(IEEE754_INVALID_OPERATION); | ||
79 | return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y); | ||
80 | |||
81 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | ||
82 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | ||
83 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | ||
84 | return y; | ||
85 | |||
86 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | ||
87 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | ||
88 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | ||
89 | return x; | ||
90 | |||
91 | /* Zero handling | ||
92 | */ | ||
93 | |||
94 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | ||
95 | if (xs == ys) | ||
96 | return x; | ||
97 | else | ||
98 | return ieee754sp_zero(ieee754_csr.rm == | ||
99 | IEEE754_RD); | ||
100 | |||
101 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | ||
102 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | ||
103 | return x; | ||
104 | |||
105 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | ||
106 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | ||
107 | return y; | ||
108 | |||
109 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | ||
110 | SPDNORMX; | ||
111 | |||
112 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | ||
113 | SPDNORMY; | ||
114 | break; | ||
115 | |||
116 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | ||
117 | SPDNORMX; | ||
118 | break; | ||
119 | |||
120 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | ||
121 | break; | ||
122 | } | ||
123 | assert(xm & SP_HIDDEN_BIT); | ||
124 | assert(ym & SP_HIDDEN_BIT); | ||
125 | |||
126 | /* provide guard,round and stick bit space */ | ||
127 | xm <<= 3; | ||
128 | ym <<= 3; | ||
129 | |||
130 | if (xe > ye) { | ||
131 | /* have to shift y fraction right to align | ||
132 | */ | ||
133 | int s = xe - ye; | ||
134 | SPXSRSYn(s); | ||
135 | } else if (ye > xe) { | ||
136 | /* have to shift x fraction right to align | ||
137 | */ | ||
138 | int s = ye - xe; | ||
139 | SPXSRSXn(s); | ||
140 | } | ||
141 | assert(xe == ye); | ||
142 | assert(xe <= SP_EMAX); | ||
143 | |||
144 | if (xs == ys) { | ||
145 | /* generate 28 bit result of adding two 27 bit numbers | ||
146 | * leaving result in xm,xs,xe | ||
147 | */ | ||
148 | xm = xm + ym; | ||
149 | xe = xe; | ||
150 | xs = xs; | ||
151 | |||
152 | if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ | ||
153 | SPXSRSX1(); | ||
154 | } | ||
155 | } else { | ||
156 | if (xm >= ym) { | ||
157 | xm = xm - ym; | ||
158 | xe = xe; | ||
159 | xs = xs; | ||
160 | } else { | ||
161 | xm = ym - xm; | ||
162 | xe = xe; | ||
163 | xs = ys; | ||
164 | } | ||
165 | if (xm == 0) | ||
166 | return ieee754sp_zero(ieee754_csr.rm == | ||
167 | IEEE754_RD); | ||
168 | |||
169 | /* normalize in extended single precision */ | ||
170 | while ((xm >> (SP_MBITS + 3)) == 0) { | ||
171 | xm <<= 1; | ||
172 | xe--; | ||
173 | } | ||
174 | |||
175 | } | ||
176 | SPNORMRET2(xs, xe, xm, "add", x, y); | ||
177 | } | ||
diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c new file mode 100644 index 000000000000..d3eff6b04b5a --- /dev/null +++ b/arch/mips/math-emu/sp_cmp.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | COMPYSP; | ||
34 | |||
35 | EXPLODEXSP; | ||
36 | EXPLODEYSP; | ||
37 | FLUSHXSP; | ||
38 | FLUSHYSP; | ||
39 | CLEARCX; /* Even clear inexact flag here */ | ||
40 | |||
41 | if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) { | ||
42 | if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) | ||
43 | SETCX(IEEE754_INVALID_OPERATION); | ||
44 | if (cmp & IEEE754_CUN) | ||
45 | return 1; | ||
46 | if (cmp & (IEEE754_CLT | IEEE754_CGT)) { | ||
47 | if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION)) | ||
48 | return ieee754si_xcpt(0, "fcmpf", x); | ||
49 | } | ||
50 | return 0; | ||
51 | } else { | ||
52 | int vx = x.bits; | ||
53 | int vy = y.bits; | ||
54 | |||
55 | if (vx < 0) | ||
56 | vx = -vx ^ SP_SIGN_BIT; | ||
57 | if (vy < 0) | ||
58 | vy = -vy ^ SP_SIGN_BIT; | ||
59 | |||
60 | if (vx < vy) | ||
61 | return (cmp & IEEE754_CLT) != 0; | ||
62 | else if (vx == vy) | ||
63 | return (cmp & IEEE754_CEQ) != 0; | ||
64 | else | ||
65 | return (cmp & IEEE754_CGT) != 0; | ||
66 | } | ||
67 | } | ||
diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c new file mode 100644 index 000000000000..2b437fcfdad9 --- /dev/null +++ b/arch/mips/math-emu/sp_div.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | COMPYSP; | ||
34 | |||
35 | EXPLODEXSP; | ||
36 | EXPLODEYSP; | ||
37 | |||
38 | CLEARCX; | ||
39 | |||
40 | FLUSHXSP; | ||
41 | FLUSHYSP; | ||
42 | |||
43 | switch (CLPAIR(xc, yc)) { | ||
44 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): | ||
45 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): | ||
46 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): | ||
47 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): | ||
48 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): | ||
49 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): | ||
50 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): | ||
51 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): | ||
52 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): | ||
53 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): | ||
54 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y); | ||
57 | |||
58 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): | ||
59 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): | ||
60 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): | ||
61 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): | ||
62 | return y; | ||
63 | |||
64 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | ||
65 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): | ||
66 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): | ||
67 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): | ||
68 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): | ||
69 | return x; | ||
70 | |||
71 | |||
72 | /* Infinity handling | ||
73 | */ | ||
74 | |||
75 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | ||
76 | SETCX(IEEE754_INVALID_OPERATION); | ||
77 | return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); | ||
78 | |||
79 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | ||
80 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | ||
81 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | ||
82 | return ieee754sp_zero(xs ^ ys); | ||
83 | |||
84 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | ||
85 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | ||
86 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | ||
87 | return ieee754sp_inf(xs ^ ys); | ||
88 | |||
89 | /* Zero handling | ||
90 | */ | ||
91 | |||
92 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | ||
93 | SETCX(IEEE754_INVALID_OPERATION); | ||
94 | return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); | ||
95 | |||
96 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | ||
97 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | ||
98 | SETCX(IEEE754_ZERO_DIVIDE); | ||
99 | return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y); | ||
100 | |||
101 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | ||
102 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | ||
103 | return ieee754sp_zero(xs == ys ? 0 : 1); | ||
104 | |||
105 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | ||
106 | SPDNORMX; | ||
107 | |||
108 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | ||
109 | SPDNORMY; | ||
110 | break; | ||
111 | |||
112 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | ||
113 | SPDNORMX; | ||
114 | break; | ||
115 | |||
116 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | ||
117 | break; | ||
118 | } | ||
119 | assert(xm & SP_HIDDEN_BIT); | ||
120 | assert(ym & SP_HIDDEN_BIT); | ||
121 | |||
122 | /* provide rounding space */ | ||
123 | xm <<= 3; | ||
124 | ym <<= 3; | ||
125 | |||
126 | { | ||
127 | /* now the dirty work */ | ||
128 | |||
129 | unsigned rm = 0; | ||
130 | int re = xe - ye; | ||
131 | unsigned bm; | ||
132 | |||
133 | for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) { | ||
134 | if (xm >= ym) { | ||
135 | xm -= ym; | ||
136 | rm |= bm; | ||
137 | if (xm == 0) | ||
138 | break; | ||
139 | } | ||
140 | xm <<= 1; | ||
141 | } | ||
142 | rm <<= 1; | ||
143 | if (xm) | ||
144 | rm |= 1; /* have remainder, set sticky */ | ||
145 | |||
146 | assert(rm); | ||
147 | |||
148 | /* normalise rm to rounding precision ? | ||
149 | */ | ||
150 | while ((rm >> (SP_MBITS + 3)) == 0) { | ||
151 | rm <<= 1; | ||
152 | re--; | ||
153 | } | ||
154 | |||
155 | SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); | ||
156 | } | ||
157 | } | ||
diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c new file mode 100644 index 000000000000..4093723d1aa5 --- /dev/null +++ b/arch/mips/math-emu/sp_fdp.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_fdp(ieee754dp x) | ||
31 | { | ||
32 | COMPXDP; | ||
33 | ieee754sp nan; | ||
34 | |||
35 | EXPLODEXDP; | ||
36 | |||
37 | CLEARCX; | ||
38 | |||
39 | FLUSHXDP; | ||
40 | |||
41 | switch (xc) { | ||
42 | case IEEE754_CLASS_SNAN: | ||
43 | SETCX(IEEE754_INVALID_OPERATION); | ||
44 | return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp"); | ||
45 | case IEEE754_CLASS_QNAN: | ||
46 | nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32) | ||
47 | (xm >> (DP_MBITS - SP_MBITS))); | ||
48 | if (!ieee754sp_isnan(nan)) | ||
49 | nan = ieee754sp_indef(); | ||
50 | return ieee754sp_nanxcpt(nan, "fdp", x); | ||
51 | case IEEE754_CLASS_INF: | ||
52 | return ieee754sp_inf(xs); | ||
53 | case IEEE754_CLASS_ZERO: | ||
54 | return ieee754sp_zero(xs); | ||
55 | case IEEE754_CLASS_DNORM: | ||
56 | /* can't possibly be sp representable */ | ||
57 | SETCX(IEEE754_UNDERFLOW); | ||
58 | SETCX(IEEE754_INEXACT); | ||
59 | if ((ieee754_csr.rm == IEEE754_RU && !xs) || | ||
60 | (ieee754_csr.rm == IEEE754_RD && xs)) | ||
61 | return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x); | ||
62 | return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x); | ||
63 | case IEEE754_CLASS_NORM: | ||
64 | break; | ||
65 | } | ||
66 | |||
67 | { | ||
68 | u32 rm; | ||
69 | |||
70 | /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift | ||
71 | */ | ||
72 | rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) | | ||
73 | ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0); | ||
74 | |||
75 | SPNORMRET1(xs, xe, rm, "fdp", x); | ||
76 | } | ||
77 | } | ||
diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c new file mode 100644 index 000000000000..42d9ed4b9a94 --- /dev/null +++ b/arch/mips/math-emu/sp_fint.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_fint(int x) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | xc = ( 0 ? xc : xc ); | ||
37 | |||
38 | if (x == 0) | ||
39 | return ieee754sp_zero(0); | ||
40 | if (x == 1 || x == -1) | ||
41 | return ieee754sp_one(x < 0); | ||
42 | if (x == 10 || x == -10) | ||
43 | return ieee754sp_ten(x < 0); | ||
44 | |||
45 | xs = (x < 0); | ||
46 | if (xs) { | ||
47 | if (x == (1 << 31)) | ||
48 | xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */ | ||
49 | else | ||
50 | xm = -x; | ||
51 | } else { | ||
52 | xm = x; | ||
53 | } | ||
54 | xe = SP_MBITS + 3; | ||
55 | |||
56 | if (xm >> (SP_MBITS + 1 + 3)) { | ||
57 | /* shunt out overflow bits | ||
58 | */ | ||
59 | while (xm >> (SP_MBITS + 1 + 3)) { | ||
60 | SPXSRSX1(); | ||
61 | } | ||
62 | } else { | ||
63 | /* normalize in grs extended single precision | ||
64 | */ | ||
65 | while ((xm >> (SP_MBITS + 3)) == 0) { | ||
66 | xm <<= 1; | ||
67 | xe--; | ||
68 | } | ||
69 | } | ||
70 | SPNORMRET1(xs, xe, xm, "fint", x); | ||
71 | } | ||
72 | |||
73 | |||
74 | ieee754sp ieee754sp_funs(unsigned int u) | ||
75 | { | ||
76 | if ((int) u < 0) | ||
77 | return ieee754sp_add(ieee754sp_1e31(), | ||
78 | ieee754sp_fint(u & ~(1 << 31))); | ||
79 | return ieee754sp_fint(u); | ||
80 | } | ||
diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c new file mode 100644 index 000000000000..1e26795ccecb --- /dev/null +++ b/arch/mips/math-emu/sp_flong.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_flong(s64 x) | ||
31 | { | ||
32 | COMPXDP; /* <--- need 64-bit mantissa temp */ | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | xc = ( 0 ? xc : xc ); | ||
37 | |||
38 | if (x == 0) | ||
39 | return ieee754sp_zero(0); | ||
40 | if (x == 1 || x == -1) | ||
41 | return ieee754sp_one(x < 0); | ||
42 | if (x == 10 || x == -10) | ||
43 | return ieee754sp_ten(x < 0); | ||
44 | |||
45 | xs = (x < 0); | ||
46 | if (xs) { | ||
47 | if (x == (1ULL << 63)) | ||
48 | xm = (1ULL << 63); /* max neg can't be safely negated */ | ||
49 | else | ||
50 | xm = -x; | ||
51 | } else { | ||
52 | xm = x; | ||
53 | } | ||
54 | xe = SP_MBITS + 3; | ||
55 | |||
56 | if (xm >> (SP_MBITS + 1 + 3)) { | ||
57 | /* shunt out overflow bits | ||
58 | */ | ||
59 | while (xm >> (SP_MBITS + 1 + 3)) { | ||
60 | SPXSRSX1(); | ||
61 | } | ||
62 | } else { | ||
63 | /* normalize in grs extended single precision */ | ||
64 | while ((xm >> (SP_MBITS + 3)) == 0) { | ||
65 | xm <<= 1; | ||
66 | xe--; | ||
67 | } | ||
68 | } | ||
69 | SPNORMRET1(xs, xe, xm, "sp_flong", x); | ||
70 | } | ||
71 | |||
72 | |||
73 | ieee754sp ieee754sp_fulong(u64 u) | ||
74 | { | ||
75 | if ((s64) u < 0) | ||
76 | return ieee754sp_add(ieee754sp_1e63(), | ||
77 | ieee754sp_flong(u & ~(1ULL << 63))); | ||
78 | return ieee754sp_flong(u); | ||
79 | } | ||
diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c new file mode 100644 index 000000000000..359c6483dbfa --- /dev/null +++ b/arch/mips/math-emu/sp_frexp.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | /* close to ieeep754sp_logb | ||
31 | */ | ||
32 | ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr) | ||
33 | { | ||
34 | COMPXSP; | ||
35 | CLEARCX; | ||
36 | EXPLODEXSP; | ||
37 | |||
38 | switch (xc) { | ||
39 | case IEEE754_CLASS_SNAN: | ||
40 | case IEEE754_CLASS_QNAN: | ||
41 | case IEEE754_CLASS_INF: | ||
42 | case IEEE754_CLASS_ZERO: | ||
43 | *eptr = 0; | ||
44 | return x; | ||
45 | case IEEE754_CLASS_DNORM: | ||
46 | SPDNORMX; | ||
47 | break; | ||
48 | case IEEE754_CLASS_NORM: | ||
49 | break; | ||
50 | } | ||
51 | *eptr = xe + 1; | ||
52 | return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT); | ||
53 | } | ||
diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c new file mode 100644 index 000000000000..3c337219ca32 --- /dev/null +++ b/arch/mips/math-emu/sp_logb.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_logb(ieee754sp x) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | EXPLODEXSP; | ||
37 | |||
38 | switch (xc) { | ||
39 | case IEEE754_CLASS_SNAN: | ||
40 | return ieee754sp_nanxcpt(x, "logb", x); | ||
41 | case IEEE754_CLASS_QNAN: | ||
42 | return x; | ||
43 | case IEEE754_CLASS_INF: | ||
44 | return ieee754sp_inf(0); | ||
45 | case IEEE754_CLASS_ZERO: | ||
46 | return ieee754sp_inf(1); | ||
47 | case IEEE754_CLASS_DNORM: | ||
48 | SPDNORMX; | ||
49 | break; | ||
50 | case IEEE754_CLASS_NORM: | ||
51 | break; | ||
52 | } | ||
53 | return ieee754sp_fint(xe); | ||
54 | } | ||
diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c new file mode 100644 index 000000000000..4b1dbac796f8 --- /dev/null +++ b/arch/mips/math-emu/sp_modf.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | /* modf function is always exact for a finite number | ||
31 | */ | ||
32 | ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip) | ||
33 | { | ||
34 | COMPXSP; | ||
35 | |||
36 | CLEARCX; | ||
37 | |||
38 | EXPLODEXSP; | ||
39 | |||
40 | switch (xc) { | ||
41 | case IEEE754_CLASS_SNAN: | ||
42 | case IEEE754_CLASS_QNAN: | ||
43 | case IEEE754_CLASS_INF: | ||
44 | case IEEE754_CLASS_ZERO: | ||
45 | *ip = x; | ||
46 | return x; | ||
47 | case IEEE754_CLASS_DNORM: | ||
48 | /* far to small */ | ||
49 | *ip = ieee754sp_zero(xs); | ||
50 | return x; | ||
51 | case IEEE754_CLASS_NORM: | ||
52 | break; | ||
53 | } | ||
54 | if (xe < 0) { | ||
55 | *ip = ieee754sp_zero(xs); | ||
56 | return x; | ||
57 | } | ||
58 | if (xe >= SP_MBITS) { | ||
59 | *ip = x; | ||
60 | return ieee754sp_zero(xs); | ||
61 | } | ||
62 | /* generate ipart mantissa by clearing bottom bits | ||
63 | */ | ||
64 | *ip = buildsp(xs, xe + SP_EBIAS, | ||
65 | ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) & | ||
66 | ~SP_HIDDEN_BIT); | ||
67 | |||
68 | /* generate fpart mantissa by clearing top bits | ||
69 | * and normalizing (must be able to normalize) | ||
70 | */ | ||
71 | xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe)); | ||
72 | if (xm == 0) | ||
73 | return ieee754sp_zero(xs); | ||
74 | |||
75 | while ((xm >> SP_MBITS) == 0) { | ||
76 | xm <<= 1; | ||
77 | xe--; | ||
78 | } | ||
79 | return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); | ||
80 | } | ||
diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c new file mode 100644 index 000000000000..3f070f82212f --- /dev/null +++ b/arch/mips/math-emu/sp_mul.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | COMPYSP; | ||
34 | |||
35 | EXPLODEXSP; | ||
36 | EXPLODEYSP; | ||
37 | |||
38 | CLEARCX; | ||
39 | |||
40 | FLUSHXSP; | ||
41 | FLUSHYSP; | ||
42 | |||
43 | switch (CLPAIR(xc, yc)) { | ||
44 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): | ||
45 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): | ||
46 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): | ||
47 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): | ||
48 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): | ||
49 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): | ||
50 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): | ||
51 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): | ||
52 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): | ||
53 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): | ||
54 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y); | ||
57 | |||
58 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): | ||
59 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): | ||
60 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): | ||
61 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): | ||
62 | return y; | ||
63 | |||
64 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | ||
65 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): | ||
66 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): | ||
67 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): | ||
68 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): | ||
69 | return x; | ||
70 | |||
71 | |||
72 | /* Infinity handling */ | ||
73 | |||
74 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | ||
75 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | ||
76 | SETCX(IEEE754_INVALID_OPERATION); | ||
77 | return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y); | ||
78 | |||
79 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | ||
80 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | ||
81 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | ||
82 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | ||
83 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | ||
84 | return ieee754sp_inf(xs ^ ys); | ||
85 | |||
86 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | ||
87 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | ||
88 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | ||
89 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | ||
90 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | ||
91 | return ieee754sp_zero(xs ^ ys); | ||
92 | |||
93 | |||
94 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | ||
95 | SPDNORMX; | ||
96 | |||
97 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | ||
98 | SPDNORMY; | ||
99 | break; | ||
100 | |||
101 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | ||
102 | SPDNORMX; | ||
103 | break; | ||
104 | |||
105 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | ||
106 | break; | ||
107 | } | ||
108 | /* rm = xm * ym, re = xe+ye basicly */ | ||
109 | assert(xm & SP_HIDDEN_BIT); | ||
110 | assert(ym & SP_HIDDEN_BIT); | ||
111 | |||
112 | { | ||
113 | int re = xe + ye; | ||
114 | int rs = xs ^ ys; | ||
115 | unsigned rm; | ||
116 | |||
117 | /* shunt to top of word */ | ||
118 | xm <<= 32 - (SP_MBITS + 1); | ||
119 | ym <<= 32 - (SP_MBITS + 1); | ||
120 | |||
121 | /* multiply 32bits xm,ym to give high 32bits rm with stickness | ||
122 | */ | ||
123 | { | ||
124 | unsigned short lxm = xm & 0xffff; | ||
125 | unsigned short hxm = xm >> 16; | ||
126 | unsigned short lym = ym & 0xffff; | ||
127 | unsigned short hym = ym >> 16; | ||
128 | unsigned lrm; | ||
129 | unsigned hrm; | ||
130 | |||
131 | lrm = lxm * lym; /* 16 * 16 => 32 */ | ||
132 | hrm = hxm * hym; /* 16 * 16 => 32 */ | ||
133 | |||
134 | { | ||
135 | unsigned t = lxm * hym; /* 16 * 16 => 32 */ | ||
136 | { | ||
137 | unsigned at = lrm + (t << 16); | ||
138 | hrm += at < lrm; | ||
139 | lrm = at; | ||
140 | } | ||
141 | hrm = hrm + (t >> 16); | ||
142 | } | ||
143 | |||
144 | { | ||
145 | unsigned t = hxm * lym; /* 16 * 16 => 32 */ | ||
146 | { | ||
147 | unsigned at = lrm + (t << 16); | ||
148 | hrm += at < lrm; | ||
149 | lrm = at; | ||
150 | } | ||
151 | hrm = hrm + (t >> 16); | ||
152 | } | ||
153 | rm = hrm | (lrm != 0); | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * sticky shift down to normal rounding precision | ||
158 | */ | ||
159 | if ((int) rm < 0) { | ||
160 | rm = (rm >> (32 - (SP_MBITS + 1 + 3))) | | ||
161 | ((rm << (SP_MBITS + 1 + 3)) != 0); | ||
162 | re++; | ||
163 | } else { | ||
164 | rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) | | ||
165 | ((rm << (SP_MBITS + 1 + 3 + 1)) != 0); | ||
166 | } | ||
167 | assert(rm & (SP_HIDDEN_BIT << 3)); | ||
168 | |||
169 | SPNORMRET2(rs, re, rm, "mul", x, y); | ||
170 | } | ||
171 | } | ||
diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c new file mode 100644 index 000000000000..44ceb87ea944 --- /dev/null +++ b/arch/mips/math-emu/sp_scalb.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_scalb(ieee754sp x, int n) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | EXPLODEXSP; | ||
37 | |||
38 | switch (xc) { | ||
39 | case IEEE754_CLASS_SNAN: | ||
40 | return ieee754sp_nanxcpt(x, "scalb", x, n); | ||
41 | case IEEE754_CLASS_QNAN: | ||
42 | case IEEE754_CLASS_INF: | ||
43 | case IEEE754_CLASS_ZERO: | ||
44 | return x; | ||
45 | case IEEE754_CLASS_DNORM: | ||
46 | SPDNORMX; | ||
47 | break; | ||
48 | case IEEE754_CLASS_NORM: | ||
49 | break; | ||
50 | } | ||
51 | SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); | ||
52 | } | ||
53 | |||
54 | |||
55 | ieee754sp ieee754sp_ldexp(ieee754sp x, int n) | ||
56 | { | ||
57 | return ieee754sp_scalb(x, n); | ||
58 | } | ||
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c new file mode 100644 index 000000000000..c809830dffb4 --- /dev/null +++ b/arch/mips/math-emu/sp_simple.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | int ieee754sp_finite(ieee754sp x) | ||
31 | { | ||
32 | return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS; | ||
33 | } | ||
34 | |||
35 | ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y) | ||
36 | { | ||
37 | CLEARCX; | ||
38 | SPSIGN(x) = SPSIGN(y); | ||
39 | return x; | ||
40 | } | ||
41 | |||
42 | |||
43 | ieee754sp ieee754sp_neg(ieee754sp x) | ||
44 | { | ||
45 | COMPXSP; | ||
46 | |||
47 | EXPLODEXSP; | ||
48 | CLEARCX; | ||
49 | FLUSHXSP; | ||
50 | |||
51 | if (xc == IEEE754_CLASS_SNAN) { | ||
52 | SETCX(IEEE754_INVALID_OPERATION); | ||
53 | return ieee754sp_nanxcpt(ieee754sp_indef(), "neg"); | ||
54 | } | ||
55 | |||
56 | if (ieee754sp_isnan(x)) /* but not infinity */ | ||
57 | return ieee754sp_nanxcpt(x, "neg", x); | ||
58 | |||
59 | /* quick fix up */ | ||
60 | SPSIGN(x) ^= 1; | ||
61 | return x; | ||
62 | } | ||
63 | |||
64 | |||
65 | ieee754sp ieee754sp_abs(ieee754sp x) | ||
66 | { | ||
67 | COMPXSP; | ||
68 | |||
69 | EXPLODEXSP; | ||
70 | CLEARCX; | ||
71 | FLUSHXSP; | ||
72 | |||
73 | if (xc == IEEE754_CLASS_SNAN) { | ||
74 | SETCX(IEEE754_INVALID_OPERATION); | ||
75 | return ieee754sp_nanxcpt(ieee754sp_indef(), "abs"); | ||
76 | } | ||
77 | |||
78 | if (ieee754sp_isnan(x)) /* but not infinity */ | ||
79 | return ieee754sp_nanxcpt(x, "abs", x); | ||
80 | |||
81 | /* quick fix up */ | ||
82 | SPSIGN(x) = 0; | ||
83 | return x; | ||
84 | } | ||
diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c new file mode 100644 index 000000000000..8a934b9f7eb8 --- /dev/null +++ b/arch/mips/math-emu/sp_sqrt.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision square root | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_sqrt(ieee754sp x) | ||
31 | { | ||
32 | int ix, s, q, m, t, i; | ||
33 | unsigned int r; | ||
34 | COMPXSP; | ||
35 | |||
36 | /* take care of Inf and NaN */ | ||
37 | |||
38 | EXPLODEXSP; | ||
39 | CLEARCX; | ||
40 | FLUSHXSP; | ||
41 | |||
42 | /* x == INF or NAN? */ | ||
43 | switch (xc) { | ||
44 | case IEEE754_CLASS_QNAN: | ||
45 | /* sqrt(Nan) = Nan */ | ||
46 | return ieee754sp_nanxcpt(x, "sqrt"); | ||
47 | case IEEE754_CLASS_SNAN: | ||
48 | SETCX(IEEE754_INVALID_OPERATION); | ||
49 | return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); | ||
50 | case IEEE754_CLASS_ZERO: | ||
51 | /* sqrt(0) = 0 */ | ||
52 | return x; | ||
53 | case IEEE754_CLASS_INF: | ||
54 | if (xs) { | ||
55 | /* sqrt(-Inf) = Nan */ | ||
56 | SETCX(IEEE754_INVALID_OPERATION); | ||
57 | return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); | ||
58 | } | ||
59 | /* sqrt(+Inf) = Inf */ | ||
60 | return x; | ||
61 | case IEEE754_CLASS_DNORM: | ||
62 | case IEEE754_CLASS_NORM: | ||
63 | if (xs) { | ||
64 | /* sqrt(-x) = Nan */ | ||
65 | SETCX(IEEE754_INVALID_OPERATION); | ||
66 | return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); | ||
67 | } | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | ix = x.bits; | ||
72 | |||
73 | /* normalize x */ | ||
74 | m = (ix >> 23); | ||
75 | if (m == 0) { /* subnormal x */ | ||
76 | for (i = 0; (ix & 0x00800000) == 0; i++) | ||
77 | ix <<= 1; | ||
78 | m -= i - 1; | ||
79 | } | ||
80 | m -= 127; /* unbias exponent */ | ||
81 | ix = (ix & 0x007fffff) | 0x00800000; | ||
82 | if (m & 1) /* odd m, double x to make it even */ | ||
83 | ix += ix; | ||
84 | m >>= 1; /* m = [m/2] */ | ||
85 | |||
86 | /* generate sqrt(x) bit by bit */ | ||
87 | ix += ix; | ||
88 | q = s = 0; /* q = sqrt(x) */ | ||
89 | r = 0x01000000; /* r = moving bit from right to left */ | ||
90 | |||
91 | while (r != 0) { | ||
92 | t = s + r; | ||
93 | if (t <= ix) { | ||
94 | s = t + r; | ||
95 | ix -= t; | ||
96 | q += r; | ||
97 | } | ||
98 | ix += ix; | ||
99 | r >>= 1; | ||
100 | } | ||
101 | |||
102 | if (ix != 0) { | ||
103 | SETCX(IEEE754_INEXACT); | ||
104 | switch (ieee754_csr.rm) { | ||
105 | case IEEE754_RP: | ||
106 | q += 2; | ||
107 | break; | ||
108 | case IEEE754_RN: | ||
109 | q += (q & 1); | ||
110 | break; | ||
111 | } | ||
112 | } | ||
113 | ix = (q >> 1) + 0x3f000000; | ||
114 | ix += (m << 23); | ||
115 | x.bits = ix; | ||
116 | return x; | ||
117 | } | ||
diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c new file mode 100644 index 000000000000..dbb802c1a086 --- /dev/null +++ b/arch/mips/math-emu/sp_sub.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y) | ||
31 | { | ||
32 | COMPXSP; | ||
33 | COMPYSP; | ||
34 | |||
35 | EXPLODEXSP; | ||
36 | EXPLODEYSP; | ||
37 | |||
38 | CLEARCX; | ||
39 | |||
40 | FLUSHXSP; | ||
41 | FLUSHYSP; | ||
42 | |||
43 | switch (CLPAIR(xc, yc)) { | ||
44 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): | ||
45 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): | ||
46 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): | ||
47 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): | ||
48 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): | ||
49 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): | ||
50 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): | ||
51 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): | ||
52 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): | ||
53 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): | ||
54 | case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): | ||
55 | SETCX(IEEE754_INVALID_OPERATION); | ||
56 | return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y); | ||
57 | |||
58 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): | ||
59 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): | ||
60 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): | ||
61 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): | ||
62 | return y; | ||
63 | |||
64 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | ||
65 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): | ||
66 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): | ||
67 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): | ||
68 | case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): | ||
69 | return x; | ||
70 | |||
71 | |||
72 | /* Infinity handling | ||
73 | */ | ||
74 | |||
75 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | ||
76 | if (xs != ys) | ||
77 | return x; | ||
78 | SETCX(IEEE754_INVALID_OPERATION); | ||
79 | return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y); | ||
80 | |||
81 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | ||
82 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | ||
83 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | ||
84 | return ieee754sp_inf(ys ^ 1); | ||
85 | |||
86 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | ||
87 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | ||
88 | case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | ||
89 | return x; | ||
90 | |||
91 | /* Zero handling | ||
92 | */ | ||
93 | |||
94 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | ||
95 | if (xs != ys) | ||
96 | return x; | ||
97 | else | ||
98 | return ieee754sp_zero(ieee754_csr.rm == | ||
99 | IEEE754_RD); | ||
100 | |||
101 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | ||
102 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | ||
103 | return x; | ||
104 | |||
105 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | ||
106 | case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | ||
107 | /* quick fix up */ | ||
108 | DPSIGN(y) ^= 1; | ||
109 | return y; | ||
110 | |||
111 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | ||
112 | SPDNORMX; | ||
113 | |||
114 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | ||
115 | SPDNORMY; | ||
116 | break; | ||
117 | |||
118 | case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | ||
119 | SPDNORMX; | ||
120 | break; | ||
121 | |||
122 | case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | ||
123 | break; | ||
124 | } | ||
125 | /* flip sign of y and handle as add */ | ||
126 | ys ^= 1; | ||
127 | |||
128 | assert(xm & SP_HIDDEN_BIT); | ||
129 | assert(ym & SP_HIDDEN_BIT); | ||
130 | |||
131 | |||
132 | /* provide guard,round and stick bit space */ | ||
133 | xm <<= 3; | ||
134 | ym <<= 3; | ||
135 | |||
136 | if (xe > ye) { | ||
137 | /* have to shift y fraction right to align | ||
138 | */ | ||
139 | int s = xe - ye; | ||
140 | SPXSRSYn(s); | ||
141 | } else if (ye > xe) { | ||
142 | /* have to shift x fraction right to align | ||
143 | */ | ||
144 | int s = ye - xe; | ||
145 | SPXSRSXn(s); | ||
146 | } | ||
147 | assert(xe == ye); | ||
148 | assert(xe <= SP_EMAX); | ||
149 | |||
150 | if (xs == ys) { | ||
151 | /* generate 28 bit result of adding two 27 bit numbers | ||
152 | */ | ||
153 | xm = xm + ym; | ||
154 | xe = xe; | ||
155 | xs = xs; | ||
156 | |||
157 | if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ | ||
158 | SPXSRSX1(); /* shift preserving sticky */ | ||
159 | } | ||
160 | } else { | ||
161 | if (xm >= ym) { | ||
162 | xm = xm - ym; | ||
163 | xe = xe; | ||
164 | xs = xs; | ||
165 | } else { | ||
166 | xm = ym - xm; | ||
167 | xe = xe; | ||
168 | xs = ys; | ||
169 | } | ||
170 | if (xm == 0) { | ||
171 | if (ieee754_csr.rm == IEEE754_RD) | ||
172 | return ieee754sp_zero(1); /* round negative inf. => sign = -1 */ | ||
173 | else | ||
174 | return ieee754sp_zero(0); /* other round modes => sign = 1 */ | ||
175 | } | ||
176 | /* normalize to rounding precision | ||
177 | */ | ||
178 | while ((xm >> (SP_MBITS + 3)) == 0) { | ||
179 | xm <<= 1; | ||
180 | xe--; | ||
181 | } | ||
182 | } | ||
183 | SPNORMRET2(xs, xe, xm, "sub", x, y); | ||
184 | } | ||
diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c new file mode 100644 index 000000000000..1d73d2abe0b5 --- /dev/null +++ b/arch/mips/math-emu/sp_tint.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include "ieee754sp.h" | ||
30 | |||
31 | int ieee754sp_tint(ieee754sp x) | ||
32 | { | ||
33 | COMPXSP; | ||
34 | |||
35 | CLEARCX; | ||
36 | |||
37 | EXPLODEXSP; | ||
38 | FLUSHXSP; | ||
39 | |||
40 | switch (xc) { | ||
41 | case IEEE754_CLASS_SNAN: | ||
42 | case IEEE754_CLASS_QNAN: | ||
43 | case IEEE754_CLASS_INF: | ||
44 | SETCX(IEEE754_INVALID_OPERATION); | ||
45 | return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); | ||
46 | case IEEE754_CLASS_ZERO: | ||
47 | return 0; | ||
48 | case IEEE754_CLASS_DNORM: | ||
49 | case IEEE754_CLASS_NORM: | ||
50 | break; | ||
51 | } | ||
52 | if (xe >= 31) { | ||
53 | /* look for valid corner case */ | ||
54 | if (xe == 31 && xs && xm == SP_HIDDEN_BIT) | ||
55 | return -0x80000000; | ||
56 | /* Set invalid. We will only use overflow for floating | ||
57 | point overflow */ | ||
58 | SETCX(IEEE754_INVALID_OPERATION); | ||
59 | return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); | ||
60 | } | ||
61 | /* oh gawd */ | ||
62 | if (xe > SP_MBITS) { | ||
63 | xm <<= xe - SP_MBITS; | ||
64 | } else { | ||
65 | u32 residue; | ||
66 | int round; | ||
67 | int sticky; | ||
68 | int odd; | ||
69 | |||
70 | if (xe < -1) { | ||
71 | residue = xm; | ||
72 | round = 0; | ||
73 | sticky = residue != 0; | ||
74 | xm = 0; | ||
75 | } | ||
76 | else { | ||
77 | /* Shifting a u32 32 times does not work, | ||
78 | * so we do it in two steps. Be aware that xe | ||
79 | * may be -1 */ | ||
80 | residue = xm << (xe + 1); | ||
81 | residue <<= 31 - SP_MBITS; | ||
82 | round = (residue >> 31) != 0; | ||
83 | sticky = (residue << 1) != 0; | ||
84 | xm >>= SP_MBITS - xe; | ||
85 | } | ||
86 | odd = (xm & 0x1) != 0x0; | ||
87 | switch (ieee754_csr.rm) { | ||
88 | case IEEE754_RN: | ||
89 | if (round && (sticky || odd)) | ||
90 | xm++; | ||
91 | break; | ||
92 | case IEEE754_RZ: | ||
93 | break; | ||
94 | case IEEE754_RU: /* toward +Infinity */ | ||
95 | if ((round || sticky) && !xs) | ||
96 | xm++; | ||
97 | break; | ||
98 | case IEEE754_RD: /* toward -Infinity */ | ||
99 | if ((round || sticky) && xs) | ||
100 | xm++; | ||
101 | break; | ||
102 | } | ||
103 | if ((xm >> 31) != 0) { | ||
104 | /* This can happen after rounding */ | ||
105 | SETCX(IEEE754_INVALID_OPERATION); | ||
106 | return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); | ||
107 | } | ||
108 | if (round || sticky) | ||
109 | SETCX(IEEE754_INEXACT); | ||
110 | } | ||
111 | if (xs) | ||
112 | return -xm; | ||
113 | else | ||
114 | return xm; | ||
115 | } | ||
116 | |||
117 | |||
118 | unsigned int ieee754sp_tuns(ieee754sp x) | ||
119 | { | ||
120 | ieee754sp hb = ieee754sp_1e31(); | ||
121 | |||
122 | /* what if x < 0 ?? */ | ||
123 | if (ieee754sp_lt(x, hb)) | ||
124 | return (unsigned) ieee754sp_tint(x); | ||
125 | |||
126 | return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) | | ||
127 | ((unsigned) 1 << 31); | ||
128 | } | ||
diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c new file mode 100644 index 000000000000..4be21aa81fbf --- /dev/null +++ b/arch/mips/math-emu/sp_tlong.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* IEEE754 floating point arithmetic | ||
2 | * single precision | ||
3 | */ | ||
4 | /* | ||
5 | * MIPS floating point support | ||
6 | * Copyright (C) 1994-2000 Algorithmics Ltd. | ||
7 | * http://www.algor.co.uk | ||
8 | * | ||
9 | * ######################################################################## | ||
10 | * | ||
11 | * This program is free software; you can distribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (Version 2) as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
18 | * for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
23 | * | ||
24 | * ######################################################################## | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include "ieee754sp.h" | ||
29 | |||
30 | s64 ieee754sp_tlong(ieee754sp x) | ||
31 | { | ||
32 | COMPXDP; /* <-- need 64-bit mantissa tmp */ | ||
33 | |||
34 | CLEARCX; | ||
35 | |||
36 | EXPLODEXSP; | ||
37 | FLUSHXSP; | ||
38 | |||
39 | switch (xc) { | ||
40 | case IEEE754_CLASS_SNAN: | ||
41 | case IEEE754_CLASS_QNAN: | ||
42 | case IEEE754_CLASS_INF: | ||
43 | SETCX(IEEE754_INVALID_OPERATION); | ||
44 | return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); | ||
45 | case IEEE754_CLASS_ZERO: | ||
46 | return 0; | ||
47 | case IEEE754_CLASS_DNORM: | ||
48 | case IEEE754_CLASS_NORM: | ||
49 | break; | ||
50 | } | ||
51 | if (xe >= 63) { | ||
52 | /* look for valid corner case */ | ||
53 | if (xe == 63 && xs && xm == SP_HIDDEN_BIT) | ||
54 | return -0x8000000000000000LL; | ||
55 | /* Set invalid. We will only use overflow for floating | ||
56 | point overflow */ | ||
57 | SETCX(IEEE754_INVALID_OPERATION); | ||
58 | return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); | ||
59 | } | ||
60 | /* oh gawd */ | ||
61 | if (xe > SP_MBITS) { | ||
62 | xm <<= xe - SP_MBITS; | ||
63 | } else if (xe < SP_MBITS) { | ||
64 | u32 residue; | ||
65 | int round; | ||
66 | int sticky; | ||
67 | int odd; | ||
68 | |||
69 | if (xe < -1) { | ||
70 | residue = xm; | ||
71 | round = 0; | ||
72 | sticky = residue != 0; | ||
73 | xm = 0; | ||
74 | } | ||
75 | else { | ||
76 | residue = xm << (32 - SP_MBITS + xe); | ||
77 | round = (residue >> 31) != 0; | ||
78 | sticky = (residue << 1) != 0; | ||
79 | xm >>= SP_MBITS - xe; | ||
80 | } | ||
81 | odd = (xm & 0x1) != 0x0; | ||
82 | switch (ieee754_csr.rm) { | ||
83 | case IEEE754_RN: | ||
84 | if (round && (sticky || odd)) | ||
85 | xm++; | ||
86 | break; | ||
87 | case IEEE754_RZ: | ||
88 | break; | ||
89 | case IEEE754_RU: /* toward +Infinity */ | ||
90 | if ((round || sticky) && !xs) | ||
91 | xm++; | ||
92 | break; | ||
93 | case IEEE754_RD: /* toward -Infinity */ | ||
94 | if ((round || sticky) && xs) | ||
95 | xm++; | ||
96 | break; | ||
97 | } | ||
98 | if ((xm >> 63) != 0) { | ||
99 | /* This can happen after rounding */ | ||
100 | SETCX(IEEE754_INVALID_OPERATION); | ||
101 | return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); | ||
102 | } | ||
103 | if (round || sticky) | ||
104 | SETCX(IEEE754_INEXACT); | ||
105 | } | ||
106 | if (xs) | ||
107 | return -xm; | ||
108 | else | ||
109 | return xm; | ||
110 | } | ||
111 | |||
112 | |||
113 | u64 ieee754sp_tulong(ieee754sp x) | ||
114 | { | ||
115 | ieee754sp hb = ieee754sp_1e63(); | ||
116 | |||
117 | /* what if x < 0 ?? */ | ||
118 | if (ieee754sp_lt(x, hb)) | ||
119 | return (u64) ieee754sp_tlong(x); | ||
120 | |||
121 | return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) | | ||
122 | (1ULL << 63); | ||
123 | } | ||