lib1funcs.S revision 1.1.1.2
1/* Copyright (C) 2018-2020 Free Software Foundation, Inc. 2 3This file is free software; you can redistribute it and/or modify it 4under the terms of the GNU General Public License as published by the 5Free Software Foundation; either version 3, or (at your option) any 6later version. 7 8This file is distributed in the hope that it will be useful, but 9WITHOUT ANY WARRANTY; without even the implied warranty of 10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11General Public License for more details. 12 13Under Section 7 of GPL version 3, you are granted additional 14permissions described in the GCC Runtime Library Exception, version 153.1, as published by the Free Software Foundation. 16 17You should have received a copy of the GNU General Public License and 18a copy of the GCC Runtime Library Exception along with this program; 19see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 20<http://www.gnu.org/licenses/>. */ 21 22 23#ifdef L__mulsi3 24 .balign 4 25 .globl __mulsi3 26 .type __mulsi3, @function 27__mulsi3: 28 l.movhi r11, 0 /* initial r */ 29 30 /* Given R = X * Y ... */ 311: l.sfeq r4, r0 /* while (y != 0) */ 32 l.bf 2f 33 l.andi r5, r4, 1 /* if (y & 1) ... */ 34 l.add r12, r11, r3 35 l.sfne r5, r0 36#if defined(__or1k_cmov__) 37 l.cmov r11, r12, r11 /* ... r += x. */ 38 l.srli r4, r4, 1 /* y >>= 1 */ 39#else 40 l.bnf 3f 41 l.srli r4, r4, 1 /* y >>= 1 */ 42 l.ori r11, r12, 0 433: 44#endif 45 l.j 1b 46 l.add r3, r3, r3 /* x <<= 1 */ 47 482: l.jr r9 49 l.nop 50 51 .size __mulsi3, . - __mulsi3 52#endif 53 54#if defined(L__udivsi3) || defined(L__umodsi3) \ 55 || defined(L__divsi3) || defined(L__modsi3) 56 .global __udivmodsi3_internal 57 .hidden __udivmodsi3_internal 58 .type __udivmodsi3_internal, @function 59#endif 60 61#ifdef L__udivsi3 62 .balign 4 63 .global __udivsi3 64 .type __udivsi3, @function 65__udivsi3: 66__udivmodsi3_internal: 67 /* Note that the other division routines assume that r13 68 is not clobbered by this routine, and use that as to 69 save a return address without creating a stack frame. */ 70 71 l.sfeq r4, r0 /* division by zero; return 0. */ 72 l.ori r11, r0, 0 /* initial quotient */ 73 l.bf 9f 74 l.ori r12, r3, 0 /* initial remainder */ 75 76 /* Given X/Y, shift Y left until Y >= X. */ 77 l.ori r6, r0, 1 /* mask = 1 */ 781: l.sflts r4, r0 /* y has msb set */ 79 l.bf 2f 80 l.sfltu r4, r12 /* y < x */ 81 l.add r4, r4, r4 /* y <<= 1 */ 82 l.bf 1b 83 l.add r6, r6, r6 /* mask <<= 1 */ 84 85 /* Shift Y back to the right again, subtracting from X. */ 862: l.add r7, r11, r6 /* tmp1 = quot + mask */ 873: l.srli r6, r6, 1 /* mask >>= 1 */ 88 l.sub r8, r12, r4 /* tmp2 = x - y */ 89 l.sfleu r4, r12 /* y <= x */ 90 l.srli r4, r4, 1 /* y >>= 1 */ 91#if defined(__or1k_cmov__) 92 l.cmov r11, r7, r11 /* if (y <= x) quot = tmp1 */ 93 l.cmov r12, r8, r12 /* if (y <= x) x = tmp2 */ 94#else 95 l.bnf 4f 96 l.nop 97 l.ori r11, r7, 0 98 l.ori r12, r8, 0 994: 100#endif 101 l.sfne r6, r0 /* loop until mask == 0 */ 102 l.bf 3b 103 l.add r7, r11, r6 /* delay fill from loop start */ 104 1059: l.jr r9 106 l.nop 107 108 .size __udivsi3, . - __udivsi3 109 .size __udivmodsi3_internal, . - __udivmodsi3_internal 110#endif 111 112#ifdef L__umodsi3 113 .balign 4 114 .global __umodsi3 115 .type __umodsi3, @function 116 .cfi_startproc 117__umodsi3: 118 /* Know that __udivmodsi3_internal does not clobber r13. */ 119 l.ori r13, r9, 0 120 .cfi_register 9, 13 121 l.jal __udivmodsi3_internal 122 l.nop 123 l.jr r13 /* return to saved lr */ 124 l.ori r11, r12, 0 /* move remainder to rv */ 125 126 .cfi_endproc 127 .size __umodsi3, . - __umodsi3 128#endif 129 130/* For signed division we do: 131 132 -x / y = x / -y = -(x / y) 133 -x % y = -(x % y) 134 x % -y = x % y 135 136 which has the property that (x/y)*y + (x%y) = x. */ 137 138#ifdef L__divsi3 139 .balign 4 140 .global __divsi3 141 .type __divsi3, @function 142 .cfi_startproc 143__divsi3: 144 l.xor r6, r3, r4 /* need result negate? */ 145 146 l.sflts r3, r0 /* abs(x) */ 147#if defined(__or1k_cmov__) 148 l.sub r5, r0, r3 149 l.cmov r3, r5, r3 150#else 151 l.bnf 1f 152 l.sub r5, r0, r3 153 l.ori r3, r5, 0 1541: 155#endif 156 l.sflts r4, r0 /* abs(y) */ 157#if defined(__or1k_cmov__) 158 l.sub r5, r0, r4 159 l.cmov r4, r5, r4 160#else 161 l.bnf 2f 162 l.sub r5, r0, r4 163 l.ori r4, r5, 0 1642: 165#endif 166 167 /* If the result will not require sign flip, tail call. */ 168 l.sflts r6, r0 169 l.bnf __udivmodsi3_internal 170 l.ori r13, r9, 0 /* save lr */ 171 172 /* Otherwise, know that __udivmodsi3_internal does not clobber r13. 173 Perform a normal call, then negate and return via saved lr. */ 174 .cfi_register 9, 13 175 l.jal __udivmodsi3_internal 176 l.nop 177 l.jr r13 178 l.sub r11, r0, r11 179 180 .cfi_endproc 181 .size __divsi3, . - __divsi3 182#endif 183 184#ifdef L__modsi3 185 .balign 4 186 .global __modsi3 187 .type __modsi3, @function 188 .cfi_startproc 189__modsi3: 190 l.sflts r4, r0 /* abs(y) */ 191#if defined(__or1k_cmov__) 192 l.sub r5, r0, r4 193 l.cmov r4, r5, r4 194#else 195 l.bnf 2f 196 l.sub r5, r0, r4 197 l.ori r4, r5, 0 1982: 199#endif 200 201 l.sflts r3, r0 /* x negative? */ 202 l.bf 1f 203 l.ori r13, r9, 0 /* save lr */ 204 205 /* Know that __udivmodsi3_internal does not clobber r13. */ 206 .cfi_register 9, 13 207 208 /* X positive; no negate of the result required. */ 209 l.jal __udivmodsi3_internal 210 l.nop 211 l.jr r13 /* return to saved lr */ 212 l.ori r11, r12, 0 /* move remainder to rv */ 213 214 /* X negative; negate both X and the result. */ 2151: l.jal __udivmodsi3_internal 216 l.sub r3, r0, r3 217 l.jr r13 /* return to saved lr */ 218 l.sub r11, r0, r12 /* negate remainder to rv */ 219 220 .cfi_endproc 221 .size __modsi3, .- __modsi3 222#endif 223