Upload Tizen:Base source
[external/gmp.git] / mpn / m68k / lshift.asm
1 dnl  mc68020 mpn_lshift -- mpn left 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:    5         12
27
28
29 C mp_limb_t mpn_lshift (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_lshift)
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    s_ptr, res_ptr
70         bls     L(Lspecial)             C jump if s_ptr >= res_ptr
71
72 ifelse(scale_available_p,1,`
73         lea     M(s_ptr,s_size,l,4), a2
74 ',`
75         movel   s_size, d0
76         asll    #2, d0
77         lea     M(s_ptr,d0,l), a2
78 ')
79         cmpl    res_ptr, a2
80         bls     L(Lspecial)             C jump if res_ptr >= s_ptr + s_size
81
82 L(Lnormal):
83         moveql  #32, d5
84         subl    cnt, d5
85
86 ifelse(scale_available_p,1,`
87         lea     M(s_ptr,s_size,l,4), s_ptr
88         lea     M(res_ptr,s_size,l,4), res_ptr
89 ',`
90         movel   s_size, d0
91         asll    #2, d0
92         addl    d0, s_ptr
93         addl    d0, res_ptr
94 ')
95         movel   M(-,s_ptr), d2
96         movel   d2, d0
97         lsrl    d5, d0          C compute carry limb
98
99         lsll    cnt, d2
100         movel   d2, d1
101         subql   #1, s_size
102         beq     L(Lend)
103         lsrl    #1, s_size
104         bcs     L(L1)
105         subql   #1, s_size
106
107 L(Loop:)
108         movel   M(-,s_ptr), d2
109         movel   d2, d3
110         lsrl    d5, d3
111         orl     d3, d1
112         movel   d1, M(-,res_ptr)
113         lsll    cnt, d2
114 L(L1:)
115         movel   M(-,s_ptr), d1
116         movel   d1, d3
117         lsrl    d5, d3
118         orl     d3, d2
119         movel   d2, M(-,res_ptr)
120         lsll    cnt, d1
121
122         dbf     s_size, L(Loop)
123         subl    #0x10000, s_size
124         bcc     L(Loop)
125
126 L(Lend:)
127         movel   d1, M(-,res_ptr)        C store least significant limb
128
129 C Restore used registers from stack frame.
130         moveml  M(sp,+), d2-d6/a2
131         rts
132
133 C We loop from least significant end of the arrays, which is only
134 C permissable if the source and destination don't overlap, since the
135 C function is documented to work for overlapping source and destination.
136
137 L(Lspecial):
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         addxl   d2, d2
147         movel   d2, M(res_ptr,+)
148 L(LL1):
149         movel   M(s_ptr,+), d2
150         addxl   d2, d2
151         movel   d2, M(res_ptr,+)
152
153         dbf     s_size, L(LLoop)
154         addxl   d0, d0          C save cy in lsb
155         subl    #0x10000, s_size
156         bcs     L(LLend)
157         lsrl    #1, 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_lshift)