1dnl mc68020 mpn_rshift -- mpn right shift. 2 3dnl Copyright 1996, 1999-2003 Free Software Foundation, Inc. 4 5dnl This file is part of the GNU MP Library. 6dnl 7dnl The GNU MP Library is free software; you can redistribute it and/or modify 8dnl it under the terms of either: 9dnl 10dnl * the GNU Lesser General Public License as published by the Free 11dnl Software Foundation; either version 3 of the License, or (at your 12dnl option) any later version. 13dnl 14dnl or 15dnl 16dnl * the GNU General Public License as published by the Free Software 17dnl Foundation; either version 2 of the License, or (at your option) any 18dnl later version. 19dnl 20dnl or both in parallel, as here. 21dnl 22dnl The GNU MP Library is distributed in the hope that it will be useful, but 23dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 24dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25dnl for more details. 26dnl 27dnl You should have received copies of the GNU General Public License and the 28dnl GNU Lesser General Public License along with the GNU MP Library. If not, 29dnl see https://www.gnu.org/licenses/. 30 31include(`../config.m4') 32 33 34C cycles/limb 35C shift==1 shift>1 36C 68040: 9 12 37 38 39C mp_limb_t mpn_rshift (mp_ptr res_ptr, mp_srcptr s_ptr, mp_size_t s_size, 40C unsigned cnt); 41C 42C The "cnt" parameter is either 16 bits or 32 bits depending on 43C SIZEOF_UNSIGNED (see ABI notes in mpn/m68k/README). The value is of 44C course only 1 to 31. When loaded as 16 bits there's garbage in the upper 45C half, hence the use of cmpw. The shift instructions take the their count 46C modulo 64, so the upper part doesn't matter to them either. 47C 48 49C INPUT PARAMETERS 50C res_ptr (sp + 4) 51C s_ptr (sp + 8) 52C s_size (sp + 12) 53C cnt (sp + 16) 54 55define(res_ptr, `a1') 56define(s_ptr, `a0') 57define(s_size, `d6') 58define(cnt, `d4') 59 60ifdef(`SIZEOF_UNSIGNED',, 61`m4_error(`SIZEOF_UNSIGNED not defined, should be in config.m4 62')') 63 64PROLOGUE(mpn_rshift) 65C Save used registers on the stack. 66 moveml d2-d6/a2, M(-,sp) 67 68C Copy the arguments to registers. 69 movel M(sp,28), res_ptr 70 movel M(sp,32), s_ptr 71 movel M(sp,36), s_size 72ifelse(SIZEOF_UNSIGNED,2, 73` movew M(sp,40), cnt', 74` movel M(sp,40), cnt') 75 76 moveql #1, d5 77 cmpw d5, cnt 78 bne L(Lnormal) 79 cmpl res_ptr, s_ptr 80 bls L(Lspecial) C jump if res_ptr >= s_ptr 81 82ifelse(scale_available_p,1,` 83 lea M(res_ptr,s_size,l,4), a2 84',` 85 movel s_size, d0 86 asll #2, d0 87 lea M(res_ptr,d0,l), a2 88') 89 cmpl s_ptr, a2 90 bls L(Lspecial) C jump if s_ptr >= res_ptr + s_size 91 92L(Lnormal): 93 moveql #32, d5 94 subl cnt, d5 95 movel M(s_ptr,+), d2 96 movel d2, d0 97 lsll d5, d0 C compute carry limb 98 99 lsrl cnt, d2 100 movel d2, d1 101 subql #1, s_size 102 beq L(Lend) 103 lsrl #1, s_size 104 bcs L(L1) 105 subql #1, s_size 106 107L(Loop): 108 movel M(s_ptr,+), d2 109 movel d2, d3 110 lsll d5, d3 111 orl d3, d1 112 movel d1, M(res_ptr,+) 113 lsrl cnt, d2 114L(L1): 115 movel M(s_ptr,+), d1 116 movel d1, d3 117 lsll d5, d3 118 orl d3, d2 119 movel d2, M(res_ptr,+) 120 lsrl cnt, d1 121 122 dbf s_size, L(Loop) 123 subl #0x10000, s_size 124 bcc L(Loop) 125 126L(Lend): 127 movel d1, M(res_ptr) C store most significant limb 128 129C Restore used registers from stack frame. 130 moveml M(sp,+), d2-d6/a2 131 rts 132 133C We loop from most significant end of the arrays, which is only permissable 134C if the source and destination don't overlap, since the function is 135C documented to work for overlapping source and destination. 136 137L(Lspecial): 138ifelse(scale_available_p,1,` 139 lea M(s_ptr,s_size,l,4), s_ptr 140 lea M(res_ptr,s_size,l,4), res_ptr 141',` 142 movel s_size, d0 143 asll #2, d0 144 addl d0, s_ptr 145 addl d0, res_ptr 146') 147 148 clrl d0 C initialize carry 149 eorw #1, s_size 150 lsrl #1, s_size 151 bcc L(LL1) 152 subql #1, s_size 153 154L(LLoop): 155 movel M(-,s_ptr), d2 156 roxrl #1, d2 157 movel d2, M(-,res_ptr) 158L(LL1): 159 movel M(-,s_ptr), d2 160 roxrl #1, d2 161 movel d2, M(-,res_ptr) 162 163 dbf s_size, L(LLoop) 164 roxrl #1, d0 C save cy in msb 165 subl #0x10000, s_size 166 bcs L(LLend) 167 addl d0, d0 C restore cy 168 bra L(LLoop) 169 170L(LLend): 171C Restore used registers from stack frame. 172 moveml M(sp,+), d2-d6/a2 173 rts 174 175EPILOGUE(mpn_rshift) 176