1/* mc68020 lshift -- Shift left 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_lshift( 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_lshift) 49 50C_SYMBOL_NAME(_gcry_mpih_lshift:) 51PROLOG(_gcry_mpih_lshift) 52 53 /* Save used registers on the stack. */ 54 moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) 55 56 /* Copy the arguments to registers. */ 57 movel MEM_DISP(sp,28),R(res_ptr) 58 movel MEM_DISP(sp,32),R(s_ptr) 59 movel MEM_DISP(sp,36),R(s_size) 60 movel MEM_DISP(sp,40),R(cnt) 61 62 moveql #1,R(d5) 63 cmpl R(d5),R(cnt) 64 bne L(Lnormal) 65 cmpl R(s_ptr),R(res_ptr) 66 bls L(Lspecial) /* jump if s_ptr >= res_ptr */ 67#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) 68 lea MEM_INDX1(s_ptr,s_size,l,4),R(a2) 69#else /* not mc68020 */ 70 movel R(s_size),R(d0) 71 asll #2,R(d0) 72 lea MEM_INDX(s_ptr,d0,l),R(a2) 73#endif 74 cmpl R(res_ptr),R(a2) 75 bls L(Lspecial) /* jump if res_ptr >= s_ptr + s_size */ 76 77L(Lnormal:) 78 moveql #32,R(d5) 79 subl R(cnt),R(d5) 80 81#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) 82 lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) 83 lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) 84#else /* not mc68000 */ 85 movel R(s_size),R(d0) 86 asll #2,R(d0) 87 addl R(s_size),R(s_ptr) 88 addl R(s_size),R(res_ptr) 89#endif 90 movel MEM_PREDEC(s_ptr),R(d2) 91 movel R(d2),R(d0) 92 lsrl R(d5),R(d0) /* compute carry limb */ 93 94 lsll R(cnt),R(d2) 95 movel R(d2),R(d1) 96 subql #1,R(s_size) 97 beq L(Lend) 98 lsrl #1,R(s_size) 99 bcs L(L1) 100 subql #1,R(s_size) 101 102L(Loop:) 103 movel MEM_PREDEC(s_ptr),R(d2) 104 movel R(d2),R(d3) 105 lsrl R(d5),R(d3) 106 orl R(d3),R(d1) 107 movel R(d1),MEM_PREDEC(res_ptr) 108 lsll R(cnt),R(d2) 109L(L1:) 110 movel MEM_PREDEC(s_ptr),R(d1) 111 movel R(d1),R(d3) 112 lsrl R(d5),R(d3) 113 orl R(d3),R(d2) 114 movel R(d2),MEM_PREDEC(res_ptr) 115 lsll R(cnt),R(d1) 116 117 dbf R(s_size),L(Loop) 118 subl #0x10000,R(s_size) 119 bcc L(Loop) 120 121L(Lend:) 122 movel R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */ 123 124/* Restore used registers from stack frame. */ 125 moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) 126 rts 127 128/* We loop from least significant end of the arrays, which is only 129 permissable if the source and destination don't overlap, since the 130 function is documented to work for overlapping source and destination. */ 131 132L(Lspecial:) 133 clrl R(d0) /* initialize carry */ 134 eorw #1,R(s_size) 135 lsrl #1,R(s_size) 136 bcc L(LL1) 137 subql #1,R(s_size) 138 139L(LLoop:) 140 movel MEM_POSTINC(s_ptr),R(d2) 141 addxl R(d2),R(d2) 142 movel R(d2),MEM_POSTINC(res_ptr) 143L(LL1:) 144 movel MEM_POSTINC(s_ptr),R(d2) 145 addxl R(d2),R(d2) 146 movel R(d2),MEM_POSTINC(res_ptr) 147 148 dbf R(s_size),L(LLoop) 149 addxl R(d0),R(d0) /* save cy in lsb */ 150 subl #0x10000,R(s_size) 151 bcs L(LLend) 152 lsrl #1,R(d0) /* restore cy */ 153 bra L(LLoop) 154 155L(LLend:) 156/* Restore used registers from stack frame. */ 157 moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) 158 rts 159EPILOG(_gcry_mpih_lshift) 160 161 162 163 164 165