1/* mc68020 rshift -- Shift right a low-level natural-number integer. 2 * 3 * Copyright (C) 1996, 1998, 2001, 2002 Free Software Foundation, Inc. 4 * 5 * This file is part of Libgcrypt. 6 * 7 * Libgcrypt is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser General Public License as 9 * published by the Free Software Foundation; either version 2.1 of 10 * the License, or (at your option) any later version. 11 * 12 * Libgcrypt 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 Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License 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 */ 27 28 29#include "sysdep.h" 30#include "asm-syntax.h" 31 32 33/******************* 34 * mpi_limb_t 35 * _gcry_mpih_rshift( mpi_ptr_t wp, (sp + 4) 36 * mpi_ptr_t up, (sp + 8) 37 * mpi_size_t usize, (sp + 12) 38 * unsigned cnt) (sp + 16) 39 */ 40 41#define res_ptr a1 42#define s_ptr a0 43#define s_size d6 44#define cnt d4 45 46 TEXT 47 ALIGN 48 GLOBL C_SYMBOL_NAME(_gcry_mpih_rshift) 49 50C_SYMBOL_NAME(_gcry_mpih_rshift:) 51PROLOG(_gcry_mpih_rshift) 52 /* Save used registers on the stack. */ 53 moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) 54 55 /* Copy the arguments to registers. */ 56 movel MEM_DISP(sp,28),R(res_ptr) 57 movel MEM_DISP(sp,32),R(s_ptr) 58 movel MEM_DISP(sp,36),R(s_size) 59 movel MEM_DISP(sp,40),R(cnt) 60 61 moveql #1,R(d5) 62 cmpl R(d5),R(cnt) 63 bne L(Rnormal) 64 cmpl R(res_ptr),R(s_ptr) 65 bls L(Rspecial) /* jump if res_ptr >= s_ptr */ 66#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) 67 lea MEM_INDX1(res_ptr,s_size,l,4),R(a2) 68#else /* not mc68020 */ 69 movel R(s_size),R(d0) 70 asll #2,R(d0) 71 lea MEM_INDX(res_ptr,d0,l),R(a2) 72#endif 73 cmpl R(s_ptr),R(a2) 74 bls L(Rspecial) /* jump if s_ptr >= res_ptr + s_size */ 75 76L(Rnormal:) 77 moveql #32,R(d5) 78 subl R(cnt),R(d5) 79 movel MEM_POSTINC(s_ptr),R(d2) 80 movel R(d2),R(d0) 81 lsll R(d5),R(d0) /* compute carry limb */ 82 83 lsrl R(cnt),R(d2) 84 movel R(d2),R(d1) 85 subql #1,R(s_size) 86 beq L(Rend) 87 lsrl #1,R(s_size) 88 bcs L(R1) 89 subql #1,R(s_size) 90 91L(Roop:) 92 movel MEM_POSTINC(s_ptr),R(d2) 93 movel R(d2),R(d3) 94 lsll R(d5),R(d3) 95 orl R(d3),R(d1) 96 movel R(d1),MEM_POSTINC(res_ptr) 97 lsrl R(cnt),R(d2) 98L(R1:) 99 movel MEM_POSTINC(s_ptr),R(d1) 100 movel R(d1),R(d3) 101 lsll R(d5),R(d3) 102 orl R(d3),R(d2) 103 movel R(d2),MEM_POSTINC(res_ptr) 104 lsrl R(cnt),R(d1) 105 106 dbf R(s_size),L(Roop) 107 subl #0x10000,R(s_size) 108 bcc L(Roop) 109 110L(Rend:) 111 movel R(d1),MEM(res_ptr) /* store most significant limb */ 112 113/* Restore used registers from stack frame. */ 114 moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) 115 rts 116 117/* We loop from most significant end of the arrays, which is only 118 permissable if the source and destination don't overlap, since the 119 function is documented to work for overlapping source and destination. */ 120 121L(Rspecial:) 122#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) 123 lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) 124 lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) 125#else /* not mc68000 */ 126 movel R(s_size),R(d0) 127 asll #2,R(d0) 128 addl R(s_size),R(s_ptr) 129 addl R(s_size),R(res_ptr) 130#endif 131 132 clrl R(d0) /* initialize carry */ 133 eorw #1,R(s_size) 134 lsrl #1,R(s_size) 135 bcc L(LR1) 136 subql #1,R(s_size) 137 138L(LRoop:) 139 movel MEM_PREDEC(s_ptr),R(d2) 140 roxrl #1,R(d2) 141 movel R(d2),MEM_PREDEC(res_ptr) 142L(LR1:) 143 movel MEM_PREDEC(s_ptr),R(d2) 144 roxrl #1,R(d2) 145 movel R(d2),MEM_PREDEC(res_ptr) 146 147 dbf R(s_size),L(LRoop) 148 roxrl #1,R(d0) /* save cy in msb */ 149 subl #0x10000,R(s_size) 150 bcs L(LRend) 151 addl R(d0),R(d0) /* restore cy */ 152 bra L(LRoop) 153 154L(LRend:) 155/* Restore used registers from stack frame. */ 156 moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) 157 rts 158EPILOG(_gcry_mpih_rshift) 159 160 161 162 163