1/* mc68020 __mpn_rshift -- Shift right a low-level natural-number integer. 2 3Copyright (C) 1996-2022 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library. 6 7The GNU MP Library is free software; you can redistribute it and/or modify 8it under the terms of the GNU Lesser General Public License as published by 9the Free Software Foundation; either version 2.1 of the License, or (at your 10option) any later version. 11 12The GNU MP Library is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15License for more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along with the GNU MP Library. If not, see <https://www.gnu.org/licenses/>. */ 19 20/* 21 INPUT PARAMETERS 22 res_ptr (sp + 4) 23 s_ptr (sp + 8) 24 s_size (sp + 16) 25 cnt (sp + 12) 26*/ 27 28#include "sysdep.h" 29#include "asm-syntax.h" 30 31#define res_ptr a1 32#define s_ptr a0 33#define s_size d6 34#define cnt d4 35 36 TEXT 37ENTRY(__mpn_rshift) 38/* Save used registers on the stack. */ 39 moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) 40 cfi_adjust_cfa_offset (6*4) 41 cfi_rel_offset (R(d2), 0) 42 cfi_rel_offset (R(d3), 4) 43 cfi_rel_offset (R(d4), 8) 44 cfi_rel_offset (R(d5), 12) 45 cfi_rel_offset (R(d6), 16) 46 cfi_rel_offset (R(a2), 20) 47 48/* Copy the arguments to registers. */ 49 movel MEM_DISP(sp,28),R(res_ptr) 50 movel MEM_DISP(sp,32),R(s_ptr) 51 movel MEM_DISP(sp,36),R(s_size) 52 movel MEM_DISP(sp,40),R(cnt) 53 54 moveql #1,R(d5) 55 cmpl R(d5),R(cnt) 56 bne L(Lnormal) 57 cmpl R(res_ptr),R(s_ptr) 58 bls L(Lspecial) /* jump if res_ptr >= s_ptr */ 59#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) 60 lea MEM_INDX1(res_ptr,s_size,l,4),R(a2) 61#else /* not mc68020 */ 62 movel R(s_size),R(d0) 63 asll #2,R(d0) 64 lea MEM_INDX(res_ptr,d0,l),R(a2) 65#endif 66 cmpl R(s_ptr),R(a2) 67 bls L(Lspecial) /* jump if s_ptr >= res_ptr + s_size */ 68 69L(Lnormal:) 70 moveql #32,R(d5) 71 subl R(cnt),R(d5) 72 movel MEM_POSTINC(s_ptr),R(d2) 73 movel R(d2),R(d0) 74 lsll R(d5),R(d0) /* compute carry limb */ 75 76 lsrl R(cnt),R(d2) 77 movel R(d2),R(d1) 78 subql #1,R(s_size) 79 beq L(Lend) 80 lsrl #1,R(s_size) 81 bcs L(L1) 82 subql #1,R(s_size) 83 84L(Loop:) 85 movel MEM_POSTINC(s_ptr),R(d2) 86 movel R(d2),R(d3) 87 lsll R(d5),R(d3) 88 orl R(d3),R(d1) 89 movel R(d1),MEM_POSTINC(res_ptr) 90 lsrl R(cnt),R(d2) 91L(L1:) 92 movel MEM_POSTINC(s_ptr),R(d1) 93 movel R(d1),R(d3) 94 lsll R(d5),R(d3) 95 orl R(d3),R(d2) 96 movel R(d2),MEM_POSTINC(res_ptr) 97 lsrl R(cnt),R(d1) 98 99 dbf R(s_size),L(Loop) 100 subl #0x10000,R(s_size) 101 bcc L(Loop) 102 103L(Lend:) 104 movel R(d1),MEM(res_ptr) /* store most significant limb */ 105 106/* Restore used registers from stack frame. */ 107 moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) 108 cfi_remember_state 109 cfi_adjust_cfa_offset (-6*4) 110 cfi_restore (R(d2)) 111 cfi_restore (R(d3)) 112 cfi_restore (R(d4)) 113 cfi_restore (R(d5)) 114 cfi_restore (R(d6)) 115 cfi_restore (R(a2)) 116 rts 117 118/* We loop from most significant end of the arrays, which is only 119 permissible if the source and destination don't overlap, since the 120 function is documented to work for overlapping source and destination. */ 121 122 cfi_restore_state 123L(Lspecial:) 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(LL1) 138 subql #1,R(s_size) 139 140L(LLoop:) 141 movel MEM_PREDEC(s_ptr),R(d2) 142 roxrl #1,R(d2) 143 movel R(d2),MEM_PREDEC(res_ptr) 144L(LL1:) 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(LLoop) 150 roxrl #1,R(d0) /* save cy in msb */ 151 subl #0x10000,R(s_size) 152 bcs L(LLend) 153 addl R(d0),R(d0) /* restore cy */ 154 bra L(LLoop) 155 156L(LLend:) 157/* Restore used registers from stack frame. */ 158 moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) 159 cfi_adjust_cfa_offset (-6*4) 160 cfi_restore (R(d2)) 161 cfi_restore (R(d3)) 162 cfi_restore (R(d4)) 163 cfi_restore (R(d5)) 164 cfi_restore (R(d6)) 165 cfi_restore (R(a2)) 166 rts 167END(__mpn_rshift) 168