Update head to match stable 1.0
[gnupg.git] / mpi / m68k / mpih-rshift.S
1 /* mc68020 rshift -- Shift right a low-level natural-number integer.
2  *
3  *      Copyright (C) 1996, 1998, 2001 Free Software Foundation, Inc.
4  *       
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  *
21  * Note: This code is heavily based on the GNU MP Library.
22  *       Actually it's the same code with only minor changes in the
23  *       way the data is stored; this is to support the abstraction
24  *       of an optional secure memory allocation which may be used
25  *       to avoid revealing of sensitive data due to paging etc.
26  *       The GNU MP Library itself is published under the LGPL;
27  *       however I decided to publish this code under the plain GPL.
28  */
29
30
31 #include "sysdep.h"
32 #include "asm-syntax.h"
33
34
35 /*******************
36  * mpi_limb_t
37  * mpihelp_rshift( mpi_ptr_t wp,        (sp + 4)
38  *                 mpi_ptr_t up,        (sp + 8)
39  *                 mpi_size_t usize,    (sp + 12)
40  *                 unsigned cnt)        (sp + 16)
41  */
42
43 #define res_ptr a1
44 #define s_ptr a0
45 #define s_size d6
46 #define cnt d4
47
48         TEXT
49         ALIGN
50         GLOBL   C_SYMBOL_NAME(mpihelp_rshift)
51
52 C_SYMBOL_NAME(mpihelp_rshift:)
53 PROLOG(mpihelp_rshift)
54         /* Save used registers on the stack.  */
55         moveml  R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
56
57         /* Copy the arguments to registers.  */
58         movel   MEM_DISP(sp,28),R(res_ptr)
59         movel   MEM_DISP(sp,32),R(s_ptr)
60         movel   MEM_DISP(sp,36),R(s_size)
61         movel   MEM_DISP(sp,40),R(cnt)
62
63         moveql  #1,R(d5)
64         cmpl    R(d5),R(cnt)
65         bne     L(Rnormal)
66         cmpl    R(res_ptr),R(s_ptr)
67         bls     L(Rspecial)             /* jump if res_ptr >= s_ptr */
68 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
69         lea     MEM_INDX1(res_ptr,s_size,l,4),R(a2)
70 #else /* not mc68020 */
71         movel   R(s_size),R(d0)
72         asll    #2,R(d0)
73         lea     MEM_INDX(res_ptr,d0,l),R(a2)
74 #endif
75         cmpl    R(s_ptr),R(a2)
76         bls     L(Rspecial)             /* jump if s_ptr >= res_ptr + s_size */
77
78 L(Rnormal:)
79         moveql  #32,R(d5)
80         subl    R(cnt),R(d5)
81         movel   MEM_POSTINC(s_ptr),R(d2)
82         movel   R(d2),R(d0)
83         lsll    R(d5),R(d0)             /* compute carry limb */
84
85         lsrl    R(cnt),R(d2)
86         movel   R(d2),R(d1)
87         subql   #1,R(s_size)
88         beq     L(Rend)
89         lsrl    #1,R(s_size)
90         bcs     L(R1)
91         subql   #1,R(s_size)
92
93 L(Roop:)
94         movel   MEM_POSTINC(s_ptr),R(d2)
95         movel   R(d2),R(d3)
96         lsll    R(d5),R(d3)
97         orl     R(d3),R(d1)
98         movel   R(d1),MEM_POSTINC(res_ptr)
99         lsrl    R(cnt),R(d2)
100 L(R1:)
101         movel   MEM_POSTINC(s_ptr),R(d1)
102         movel   R(d1),R(d3)
103         lsll    R(d5),R(d3)
104         orl     R(d3),R(d2)
105         movel   R(d2),MEM_POSTINC(res_ptr)
106         lsrl    R(cnt),R(d1)
107
108         dbf     R(s_size),L(Roop)
109         subl    #0x10000,R(s_size)
110         bcc     L(Roop)
111
112 L(Rend:)
113         movel   R(d1),MEM(res_ptr) /* store most significant limb */
114
115 /* Restore used registers from stack frame.  */
116         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
117         rts
118
119 /* We loop from most significant end of the arrays, which is only
120    permissable if the source and destination don't overlap, since the
121    function is documented to work for overlapping source and destination.  */
122
123 L(Rspecial:)
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
133
134         clrl    R(d0)                   /* initialize carry */
135         eorw    #1,R(s_size)
136         lsrl    #1,R(s_size)
137         bcc     L(LR1)
138         subql   #1,R(s_size)
139
140 L(LRoop:)
141         movel   MEM_PREDEC(s_ptr),R(d2)
142         roxrl   #1,R(d2)
143         movel   R(d2),MEM_PREDEC(res_ptr)
144 L(LR1:)
145         movel   MEM_PREDEC(s_ptr),R(d2)
146         roxrl   #1,R(d2)
147         movel   R(d2),MEM_PREDEC(res_ptr)
148
149         dbf     R(s_size),L(LRoop)
150         roxrl   #1,R(d0)                /* save cy in msb */
151         subl    #0x10000,R(s_size)
152         bcs     L(LRend)
153         addl    R(d0),R(d0)             /* restore cy */
154         bra     L(LRoop)
155
156 L(LRend:)
157 /* Restore used registers from stack frame.  */
158         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
159         rts
160 EPILOG(mpihelp_rshift)
161
162
163
164