From: Andy P. <at...@us...> - 2002-04-10 18:40:57
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/s390/math-emu In directory usw-pr-cvs1:/tmp/cvs-serv28245/s390/math-emu Added Files: Makefile math.c qrnnd.S sfp-util.h Log Message: synch 2.4.15 commit 43 --- NEW FILE --- # # Makefile for the FPU instruction emulation. # O_TARGET := math-emu.o obj-$(CONFIG_MATHEMU) := math.o qrnnd.o EXTRA_CFLAGS = -I. -I$(TOPDIR)/include/math-emu -w include $(TOPDIR)/Rules.make --- NEW FILE --- /* * arch/s390/math-emu/math.c * * S390 version * Copyright (C) 1999-2001 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Martin Schwidefsky (sch...@de...), * * 'math.c' emulates IEEE instructions on a S390 processor * that does not have the IEEE fpu (all processors before G5). */ #include <linux/config.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/mm.h> #include <asm/uaccess.h> #include "sfp-util.h" #include <math-emu/soft-fp.h> [...2192 lines suppressed...] /* broken compiler ... */ long long __negdi2 (long long u) { union lll { long long ll; long s[2]; }; union lll w,uu; uu.ll = u; w.s[1] = -uu.s[1]; w.s[0] = -uu.s[0] - ((int) w.s[1] != 0); return w.ll; } --- NEW FILE --- # S/390 __udiv_qrnnd # r2 : &__r # r3 : upper half of 64 bit word n # r4 : lower half of 64 bit word n # r5 : divisor d # the reminder r of the division is to be stored to &__r and # the quotient q is to be returned .text .globl __udiv_qrnnd __udiv_qrnnd: st %r2,24(%r15) # store pointer to reminder for later lr %r0,%r3 # reload n lr %r1,%r4 ltr %r2,%r5 # reload and test divisor jp 5f # divisor >= 0x80000000 srdl %r0,2 # n/4 srl %r2,1 # d/2 slr %r1,%r2 # special case if last bit of d is set brc 3,0f # (n/4) div (n/2) can overflow by 1 ahi %r0,-1 # trick: subtract n/2, then divide 0: dr %r0,%r2 # signed division ahi %r1,1 # trick part 2: add 1 to the quotient # now (n >> 2) = (d >> 1) * %r1 + %r0 lhi %r3,1 nr %r3,%r1 # test last bit of q jz 1f alr %r0,%r2 # add (d>>1) to r 1: srl %r1,1 # q >>= 1 # now (n >> 2) = (d&-2) * %r1 + %r0 lhi %r3,1 nr %r3,%r5 # test last bit of d jz 2f slr %r0,%r1 # r -= q brc 3,2f # borrow ? alr %r0,%r5 # r += d ahi %r1,-1 2: # now (n >> 2) = d * %r1 + %r0 alr %r1,%r1 # q <<= 1 alr %r0,%r0 # r <<= 1 brc 12,3f # overflow on r ? slr %r0,%r5 # r -= d ahi %r1,1 # q += 1 3: lhi %r3,2 nr %r3,%r4 # test next to last bit of n jz 4f ahi %r0,1 # r += 1 4: clr %r0,%r5 # r >= d ? jl 6f slr %r0,%r5 # r -= d ahi %r1,1 # q += 1 # now (n >> 1) = d * %r1 + %r0 j 6f 5: # divisor < 0x80000000 srdl %r0,1 dr %r0,%r2 # signed division # now (n >> 1) = d * %r1 + %r0 6: alr %r1,%r1 # q <<= 1 alr %r0,%r0 # r <<= 1 brc 12,7f # overflow on r ? slr %r0,%r5 # r -= d ahi %r1,1 # q += 1 7: lhi %r3,1 nr %r3,%r4 # isolate last bit of n alr %r0,%r3 # r += (n & 1) clr %r0,%r5 # r >= d ? jl 8f slr %r0,%r5 # r -= d ahi %r1,1 # q += 1 8: # now n = d * %r1 + %r0 l %r2,24(%r15) st %r0,0(%r2) lr %r2,%r1 br %r14 .end __udiv_qrnnd --- NEW FILE --- #include <linux/kernel.h> #include <linux/sched.h> #include <linux/types.h> #include <asm/byteorder.h> #define add_ssaaaa(sh, sl, ah, al, bh, bl) ({ \ unsigned int __sh = (ah); \ unsigned int __sl = (al); \ __asm__ (" alr %1,%3\n" \ " brc 12,0f\n" \ " ahi %0,1\n" \ "0: alr %0,%2" \ : "+&d" (__sh), "+d" (__sl) \ : "d" (bh), "d" (bl) : "cc" ); \ (sh) = __sh; \ (sl) = __sl; \ }) #define sub_ddmmss(sh, sl, ah, al, bh, bl) ({ \ unsigned int __sh = (ah); \ unsigned int __sl = (al); \ __asm__ (" slr %1,%3\n" \ " brc 3,0f\n" \ " ahi %0,-1\n" \ "0: slr %0,%2" \ : "+&d" (__sh), "+d" (__sl) \ : "d" (bh), "d" (bl) : "cc" ); \ (sh) = __sh; \ (sl) = __sl; \ }) /* a umul b = a mul b + (a>=2<<31) ? b<<32:0 + (b>=2<<31) ? a<<32:0 */ #define umul_ppmm(wh, wl, u, v) ({ \ unsigned int __wh = u; \ unsigned int __wl = v; \ __asm__ (" ltr 1,%0\n" \ " mr 0,%1\n" \ " jnm 0f\n" \ " alr 0,%1\n" \ "0: ltr %1,%1\n" \ " jnm 1f\n" \ " alr 0,%0\n" \ "1: lr %0,0\n" \ " lr %1,1\n" \ : "+d" (__wh), "+d" (__wl) \ : : "0", "1", "cc" ); \ wh = __wh; \ wl = __wl; \ }) #define udiv_qrnnd(q, r, n1, n0, d) \ do { unsigned long __r; \ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ (r) = __r; \ } while (0) extern unsigned long __udiv_qrnnd (unsigned long *, unsigned long, unsigned long , unsigned long); #define UDIV_NEEDS_NORMALIZATION 0 #define abort() return 0 #define __BYTE_ORDER __BIG_ENDIAN |