Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / m68k / m680x0 / rshift.S
blobe2d335405c5de62475e4d5e16b139725eab579de
1 /* mc68020 __mpn_rshift -- Shift right a low-level natural-number integer.
3 Copyright (C) 1996-2014 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library.  If not, see <http://www.gnu.org/licenses/>.  */
21   INPUT PARAMETERS
22   res_ptr       (sp + 4)
23   s_ptr         (sp + 8)
24   s_size        (sp + 16)
25   cnt           (sp + 12)
28 #include "sysdep.h"
29 #include "asm-syntax.h"
31 #define res_ptr a1
32 #define s_ptr a0
33 #define s_size d6
34 #define cnt d4
36         TEXT
37 ENTRY(__mpn_rshift)
38 /* Save used registers on the stack.  */
39         moveml  R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
40         cfi_adjust_cfa_offset (6*4)
41         cfi_rel_offset (R(d2), 0)
42         cfi_rel_offset (R(d3), 4)
43         cfi_rel_offset (R(d4), 8)
44         cfi_rel_offset (R(d5), 12)
45         cfi_rel_offset (R(d6), 16)
46         cfi_rel_offset (R(a2), 20)
48 /* Copy the arguments to registers.  */
49         movel   MEM_DISP(sp,28),R(res_ptr)
50         movel   MEM_DISP(sp,32),R(s_ptr)
51         movel   MEM_DISP(sp,36),R(s_size)
52         movel   MEM_DISP(sp,40),R(cnt)
54         moveql  #1,R(d5)
55         cmpl    R(d5),R(cnt)
56         bne     L(Lnormal)
57         cmpl    R(res_ptr),R(s_ptr)
58         bls     L(Lspecial)             /* jump if res_ptr >= s_ptr */
59 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
60         lea     MEM_INDX1(res_ptr,s_size,l,4),R(a2)
61 #else /* not mc68020 */
62         movel   R(s_size),R(d0)
63         asll    #2,R(d0)
64         lea     MEM_INDX(res_ptr,d0,l),R(a2)
65 #endif
66         cmpl    R(s_ptr),R(a2)
67         bls     L(Lspecial)             /* jump if s_ptr >= res_ptr + s_size */
69 L(Lnormal:)
70         moveql  #32,R(d5)
71         subl    R(cnt),R(d5)
72         movel   MEM_POSTINC(s_ptr),R(d2)
73         movel   R(d2),R(d0)
74         lsll    R(d5),R(d0)             /* compute carry limb */
76         lsrl    R(cnt),R(d2)
77         movel   R(d2),R(d1)
78         subql   #1,R(s_size)
79         beq     L(Lend)
80         lsrl    #1,R(s_size)
81         bcs     L(L1)
82         subql   #1,R(s_size)
84 L(Loop:)
85         movel   MEM_POSTINC(s_ptr),R(d2)
86         movel   R(d2),R(d3)
87         lsll    R(d5),R(d3)
88         orl     R(d3),R(d1)
89         movel   R(d1),MEM_POSTINC(res_ptr)
90         lsrl    R(cnt),R(d2)
91 L(L1:)
92         movel   MEM_POSTINC(s_ptr),R(d1)
93         movel   R(d1),R(d3)
94         lsll    R(d5),R(d3)
95         orl     R(d3),R(d2)
96         movel   R(d2),MEM_POSTINC(res_ptr)
97         lsrl    R(cnt),R(d1)
99         dbf     R(s_size),L(Loop)
100         subl    #0x10000,R(s_size)
101         bcc     L(Loop)
103 L(Lend:)
104         movel   R(d1),MEM(res_ptr) /* store most significant limb */
106 /* Restore used registers from stack frame.  */
107         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
108         cfi_remember_state
109         cfi_adjust_cfa_offset (-6*4)
110         cfi_restore (R(d2))
111         cfi_restore (R(d3))
112         cfi_restore (R(d4))
113         cfi_restore (R(d5))
114         cfi_restore (R(d6))
115         cfi_restore (R(a2))
116         rts
118 /* We loop from most significant end of the arrays, which is only
119    permissible if the source and destination don't overlap, since the
120    function is documented to work for overlapping source and destination.  */
122         cfi_restore_state
123 L(Lspecial:)
124 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
125         lea     MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
126         lea     MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
127 #else /* not mc68000 */
128         movel   R(s_size),R(d0)
129         asll    #2,R(d0)
130         addl    R(s_size),R(s_ptr)
131         addl    R(s_size),R(res_ptr)
132 #endif
134         clrl    R(d0)                   /* initialize carry */
135         eorw    #1,R(s_size)
136         lsrl    #1,R(s_size)
137         bcc     L(LL1)
138         subql   #1,R(s_size)
140 L(LLoop:)
141         movel   MEM_PREDEC(s_ptr),R(d2)
142         roxrl   #1,R(d2)
143         movel   R(d2),MEM_PREDEC(res_ptr)
144 L(LL1:)
145         movel   MEM_PREDEC(s_ptr),R(d2)
146         roxrl   #1,R(d2)
147         movel   R(d2),MEM_PREDEC(res_ptr)
149         dbf     R(s_size),L(LLoop)
150         roxrl   #1,R(d0)                /* save cy in msb */
151         subl    #0x10000,R(s_size)
152         bcs     L(LLend)
153         addl    R(d0),R(d0)             /* restore cy */
154         bra     L(LLoop)
156 L(LLend:)
157 /* Restore used registers from stack frame.  */
158         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
159         cfi_adjust_cfa_offset (-6*4)
160         cfi_restore (R(d2))
161         cfi_restore (R(d3))
162         cfi_restore (R(d4))
163         cfi_restore (R(d5))
164         cfi_restore (R(d6))
165         cfi_restore (R(a2))
166         rts
167 END(__mpn_rshift)