summaryrefslogtreecommitdiffstats
path: root/arch/s390/math-emu/qrnnd.S
blob: b01c2b648e227dcb81cc79bb0231d4a35f7632b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# 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
OpenPOWER on IntegriCloud