Tizen 2.1 base
[external/gmp.git] / mpn / m68k / rshift.asm
1 dnl  mc68020 mpn_rshift -- mpn right shift.
2
3 dnl  Copyright 1996, 1999, 2000, 2001, 2002, 2003 Free Software Foundation,
4 dnl  Inc.
5 dnl
6 dnl  This file is part of the GNU MP Library.
7 dnl
8 dnl  The GNU MP Library is free software; you can redistribute it and/or
9 dnl  modify it under the terms of the GNU Lesser General Public License as
10 dnl  published by the Free Software Foundation; either version 3 of the
11 dnl  License, or (at your option) any later version.
12 dnl
13 dnl  The GNU MP Library is distributed in the hope that it will be useful,
14 dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 dnl  Lesser General Public License for more details.
17 dnl
18 dnl  You should have received a copy of the GNU Lesser General Public License
19 dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
20
21 include(`../config.m4')
22
23
24 C           cycles/limb
25 C        shift==1  shift>1
26 C 68040:    9         12
27
28
29 C mp_limb_t mpn_rshift (mp_ptr res_ptr, mp_srcptr s_ptr, mp_size_t s_size,
30 C                       unsigned cnt);
31 C
32 C The "cnt" parameter is either 16 bits or 32 bits depending on
33 C SIZEOF_UNSIGNED (see ABI notes in mpn/m68k/README).  The value is of
34 C course only 1 to 31.  When loaded as 16 bits there's garbage in the upper
35 C half, hence the use of cmpw.  The shift instructions take the their count
36 C modulo 64, so the upper part doesn't matter to them either.
37 C
38
39 C INPUT PARAMETERS
40 C res_ptr       (sp + 4)
41 C s_ptr         (sp + 8)
42 C s_size        (sp + 12)
43 C cnt           (sp + 16)
44
45 define(res_ptr, `a1')
46 define(s_ptr,   `a0')
47 define(s_size,  `d6')
48 define(cnt,     `d4')
49
50 ifdef(`SIZEOF_UNSIGNED',,
51 `m4_error(`SIZEOF_UNSIGNED not defined, should be in config.m4
52 ')')
53
54 PROLOGUE(mpn_rshift)
55 C Save used registers on the stack.
56         moveml  d2-d6/a2, M(-,sp)
57
58 C Copy the arguments to registers.
59         movel   M(sp,28), res_ptr
60         movel   M(sp,32), s_ptr
61         movel   M(sp,36), s_size
62 ifelse(SIZEOF_UNSIGNED,2,
63 `       movew   M(sp,40), cnt',
64 `       movel   M(sp,40), cnt')
65
66         moveql  #1, d5
67         cmpw    d5, cnt
68         bne     L(Lnormal)
69         cmpl    res_ptr, s_ptr
70         bls     L(Lspecial)             C jump if res_ptr >= s_ptr
71
72 ifelse(scale_available_p,1,`
73         lea     M(res_ptr,s_size,l,4), a2
74 ',`
75         movel   s_size, d0
76         asll    #2, d0
77         lea     M(res_ptr,d0,l), a2
78 ')
79         cmpl    s_ptr, a2
80         bls     L(Lspecial)             C jump if s_ptr >= res_ptr + s_size
81
82 L(Lnormal:)
83         moveql  #32, d5
84         subl    cnt, d5
85         movel   M(s_ptr,+), d2
86         movel   d2, d0
87         lsll    d5, d0          C compute carry limb
88
89         lsrl    cnt, d2
90         movel   d2, d1
91         subql   #1, s_size
92         beq     L(Lend)
93         lsrl    #1, s_size
94         bcs     L(L1)
95         subql   #1, s_size
96
97 L(Loop:)
98         movel   M(s_ptr,+), d2
99         movel   d2, d3
100         lsll    d5, d3
101         orl     d3, d1
102         movel   d1, M(res_ptr,+)
103         lsrl    cnt, d2
104 L(L1:)
105         movel   M(s_ptr,+), d1
106         movel   d1, d3
107         lsll    d5, d3
108         orl     d3, d2
109         movel   d2, M(res_ptr,+)
110         lsrl    cnt, d1
111
112         dbf     s_size, L(Loop)
113         subl    #0x10000, s_size
114         bcc     L(Loop)
115
116 L(Lend:)
117         movel   d1, M(res_ptr)  C store most significant limb
118
119 C Restore used registers from stack frame.
120         moveml  M(sp,+), d2-d6/a2
121         rts
122
123 C We loop from most significant end of the arrays, which is only permissable
124 C if the source and destination don't overlap, since the function is
125 C documented to work for overlapping source and destination.
126
127 L(Lspecial:)
128 ifelse(scale_available_p,1,`
129         lea     M(s_ptr,s_size,l,4), s_ptr
130         lea     M(res_ptr,s_size,l,4), res_ptr
131 ',`
132         movel   s_size, d0
133         asll    #2, d0
134         addl    d0, s_ptr
135         addl    d0, res_ptr
136 ')
137
138         clrl    d0                      C initialize carry
139         eorw    #1, s_size
140         lsrl    #1, s_size
141         bcc     L(LL1)
142         subql   #1, s_size
143
144 L(LLoop:)
145         movel   M(-,s_ptr), d2
146         roxrl   #1, d2
147         movel   d2, M(-,res_ptr)
148 L(LL1:)
149         movel   M(-,s_ptr), d2
150         roxrl   #1, d2
151         movel   d2, M(-,res_ptr)
152
153         dbf     s_size, L(LLoop)
154         roxrl   #1, d0          C save cy in msb
155         subl    #0x10000, s_size
156         bcs     L(LLend)
157         addl    d0, d0          C restore cy
158         bra     L(LLoop)
159
160 L(LLend:)
161 C Restore used registers from stack frame.
162         moveml  M(sp,+), d2-d6/a2
163         rts
164
165 EPILOGUE(mpn_rshift)