Updated from /src/gmp-1.937
[kopensolaris-gnu/glibc.git] / sysdeps / m68k / rshift.S
1 /* mc68020 __mpn_rshift -- Shift right a low-level natural-number integer.
2
3 Copyright (C) 1996 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Library General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
11
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 Library General Public
15 License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
19 the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 /*
22   INPUT PARAMETERS
23   res_ptr       (sp + 4)
24   s_ptr         (sp + 8)
25   s_size        (sp + 16)
26   cnt           (sp + 12)
27 */
28
29 #include "sysdep.h"
30 #include "asm-syntax.h"
31
32 #define res_ptr a1
33 #define s_ptr a0
34 #define s_size d6
35 #define cnt d4
36
37         TEXT
38         ALIGN
39         GLOBL   C_SYMBOL_NAME(__mpn_rshift)
40
41 C_SYMBOL_NAME(__mpn_rshift:)
42 PROLOG(__mpn_rshift)
43 /* Save used registers on the stack.  */
44         moveml  R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
45
46 /* Copy the arguments to registers.  */
47         movel   MEM_DISP(sp,28),R(res_ptr)
48         movel   MEM_DISP(sp,32),R(s_ptr)
49         movel   MEM_DISP(sp,36),R(s_size)
50         movel   MEM_DISP(sp,40),R(cnt)
51
52         moveql  #1,R(d5)
53         cmpl    R(d5),R(cnt)
54         bne     L(Lnormal)
55         cmpl    R(res_ptr),R(s_ptr)
56         bls     L(Lspecial)             /* jump if res_ptr >= s_ptr */
57 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
58         lea     MEM_INDX1(res_ptr,s_size,l,4),R(a2)
59 #else /* not mc68020 */
60         movel   R(s_size),R(d0)
61         asll    #2,R(d0)
62         lea     MEM_INDX(res_ptr,d0,l),R(a2)
63 #endif
64         cmpl    R(s_ptr),R(a2)
65         bls     L(Lspecial)             /* jump if s_ptr >= res_ptr + s_size */
66
67 L(Lnormal:)
68         moveql  #32,R(d5)
69         subl    R(cnt),R(d5)
70         movel   MEM_POSTINC(s_ptr),R(d2)
71         movel   R(d2),R(d0)
72         lsll    R(d5),R(d0)             /* compute carry limb */
73    
74         lsrl    R(cnt),R(d2)
75         movel   R(d2),R(d1)
76         subql   #1,R(s_size)
77         beq     L(Lend)
78         lsrl    #1,R(s_size)
79         bcs     L(L1)
80         subql   #1,R(s_size)
81
82 L(Loop:)
83         movel   MEM_POSTINC(s_ptr),R(d2)
84         movel   R(d2),R(d3)
85         lsll    R(d5),R(d3)
86         orl     R(d3),R(d1)
87         movel   R(d1),MEM_POSTINC(res_ptr)
88         lsrl    R(cnt),R(d2)
89 L(L1:)
90         movel   MEM_POSTINC(s_ptr),R(d1)
91         movel   R(d1),R(d3)
92         lsll    R(d5),R(d3)
93         orl     R(d3),R(d2)
94         movel   R(d2),MEM_POSTINC(res_ptr)
95         lsrl    R(cnt),R(d1)
96
97         dbf     R(s_size),L(Loop)
98         subl    #0x10000,R(s_size)
99         bcc     L(Loop)
100
101 L(Lend:)
102         movel   R(d1),MEM(res_ptr) /* store most significant limb */
103
104 /* Restore used registers from stack frame.  */
105         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
106         rts
107
108 /* We loop from most significant end of the arrays, which is only
109    permissable if the source and destination don't overlap, since the
110    function is documented to work for overlapping source and destination.  */
111
112 L(Lspecial:)
113 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
114         lea     MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
115         lea     MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
116 #else /* not mc68000 */
117         movel   R(s_size),R(d0)
118         asll    #2,R(d0)
119         addl    R(s_size),R(s_ptr)
120         addl    R(s_size),R(res_ptr)
121 #endif
122
123         clrl    R(d0)                   /* initialize carry */
124         eorw    #1,R(s_size)
125         lsrl    #1,R(s_size)
126         bcc     L(LL1)
127         subql   #1,R(s_size)
128
129 L(LLoop:)
130         movel   MEM_PREDEC(s_ptr),R(d2)
131         roxrl   #1,R(d2)
132         movel   R(d2),MEM_PREDEC(res_ptr)
133 L(LL1:)
134         movel   MEM_PREDEC(s_ptr),R(d2)
135         roxrl   #1,R(d2)
136         movel   R(d2),MEM_PREDEC(res_ptr)
137
138         dbf     R(s_size),L(LLoop)
139         roxrl   #1,R(d0)                /* save cy in msb */
140         subl    #0x10000,R(s_size)
141         bcs     L(LLend)
142         addl    R(d0),R(d0)             /* restore cy */
143         bra     L(LLoop)
144
145 L(LLend:)
146 /* Restore used registers from stack frame.  */
147         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
148         rts
149 EPILOG(__mpn_rshift)