1 1.1.1.11 mrg /* Copyright (C) 2006-2024 Free Software Foundation, Inc. 2 1.1 mrg 3 1.1 mrg This file is free software; you can redistribute it and/or modify it 4 1.1 mrg under the terms of the GNU General Public License as published by the 5 1.1 mrg Free Software Foundation; either version 3, or (at your option) any 6 1.1 mrg later version. 7 1.1 mrg 8 1.1 mrg This file is distributed in the hope that it will be useful, but 9 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of 10 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 1.1 mrg General Public License for more details. 12 1.1 mrg 13 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 14 1.1 mrg permissions described in the GCC Runtime Library Exception, version 15 1.1 mrg 3.1, as published by the Free Software Foundation. 16 1.1 mrg 17 1.1 mrg You should have received a copy of the GNU General Public License and 18 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 19 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 20 1.1 mrg <http://www.gnu.org/licenses/>. */ 21 1.1 mrg 22 1.1 mrg /* Moderately Space-optimized libgcc routines for the Renesas SH / 23 1.1 mrg STMicroelectronics ST40 CPUs. 24 1.1 mrg Contributed by J"orn Rennecke joern.rennecke (at) st.com. */ 25 1.1 mrg 26 1.1 mrg #include "lib1funcs.h" 27 1.1 mrg 28 1.1 mrg #ifdef L_udivsi3_i4i 29 1.1 mrg 30 1.1 mrg /* 88 bytes; sh4-200 cycle counts: 31 1.1 mrg divisor >= 2G: 11 cycles 32 1.1 mrg dividend < 2G: 48 cycles 33 1.1 mrg dividend >= 2G: divisor != 1: 54 cycles 34 1.1 mrg dividend >= 2G, divisor == 1: 22 cycles */ 35 1.1 mrg #if defined (__SH_FPU_DOUBLE__) || defined (__SH4_SINGLE_ONLY__) 36 1.1 mrg !! args in r4 and r5, result in r0, clobber r1 37 1.1 mrg 38 1.1 mrg .global GLOBAL(udivsi3_i4i) 39 1.1 mrg FUNC(GLOBAL(udivsi3_i4i)) 40 1.1 mrg GLOBAL(udivsi3_i4i): 41 1.1 mrg mova L1,r0 42 1.1 mrg cmp/pz r5 43 1.1 mrg sts fpscr,r1 44 1.1 mrg lds.l @r0+,fpscr 45 1.1 mrg sts.l fpul,@-r15 46 1.1 mrg bf LOCAL(huge_divisor) 47 1.1 mrg mov.l r1,@-r15 48 1.1 mrg lds r4,fpul 49 1.1 mrg cmp/pz r4 50 1.1 mrg #ifdef FMOVD_WORKS 51 1.1 mrg fmov.d dr0,@-r15 52 1.1 mrg float fpul,dr0 53 1.1 mrg fmov.d dr2,@-r15 54 1.1 mrg bt LOCAL(dividend_adjusted) 55 1.1 mrg mov #1,r1 56 1.1 mrg fmov.d @r0,dr2 57 1.1 mrg cmp/eq r1,r5 58 1.1 mrg bt LOCAL(div_by_1) 59 1.1 mrg fadd dr2,dr0 60 1.1 mrg LOCAL(dividend_adjusted): 61 1.1 mrg lds r5,fpul 62 1.1 mrg float fpul,dr2 63 1.1 mrg fdiv dr2,dr0 64 1.1 mrg LOCAL(div_by_1): 65 1.1 mrg fmov.d @r15+,dr2 66 1.1 mrg ftrc dr0,fpul 67 1.1 mrg fmov.d @r15+,dr0 68 1.1 mrg #else /* !FMOVD_WORKS */ 69 1.1 mrg fmov.s DR01,@-r15 70 1.1 mrg mov #1,r1 71 1.1 mrg fmov.s DR00,@-r15 72 1.1 mrg float fpul,dr0 73 1.1 mrg fmov.s DR21,@-r15 74 1.1 mrg bt/s LOCAL(dividend_adjusted) 75 1.1 mrg fmov.s DR20,@-r15 76 1.1 mrg cmp/eq r1,r5 77 1.1 mrg bt LOCAL(div_by_1) 78 1.1 mrg fmov.s @r0+,DR20 79 1.1 mrg fmov.s @r0,DR21 80 1.1 mrg fadd dr2,dr0 81 1.1 mrg LOCAL(dividend_adjusted): 82 1.1 mrg lds r5,fpul 83 1.1 mrg float fpul,dr2 84 1.1 mrg fdiv dr2,dr0 85 1.1 mrg LOCAL(div_by_1): 86 1.1 mrg fmov.s @r15+,DR20 87 1.1 mrg fmov.s @r15+,DR21 88 1.1 mrg ftrc dr0,fpul 89 1.1 mrg fmov.s @r15+,DR00 90 1.1 mrg fmov.s @r15+,DR01 91 1.1 mrg #endif /* !FMOVD_WORKS */ 92 1.1 mrg lds.l @r15+,fpscr 93 1.1 mrg sts fpul,r0 94 1.1 mrg rts 95 1.1 mrg lds.l @r15+,fpul 96 1.1 mrg 97 1.1 mrg #ifdef FMOVD_WORKS 98 1.1 mrg .p2align 3 ! make double below 8 byte aligned. 99 1.1 mrg #endif 100 1.1 mrg LOCAL(huge_divisor): 101 1.1 mrg lds r1,fpscr 102 1.1 mrg add #4,r15 103 1.1 mrg cmp/hs r5,r4 104 1.1 mrg rts 105 1.1 mrg movt r0 106 1.1 mrg 107 1.1 mrg .p2align 2 108 1.1 mrg L1: 109 1.1 mrg #ifndef FMOVD_WORKS 110 1.1 mrg .long 0x80000 111 1.1 mrg #else 112 1.1 mrg .long 0x180000 113 1.1 mrg #endif 114 1.1 mrg .double 4294967296 115 1.1 mrg 116 1.1 mrg ENDFUNC(GLOBAL(udivsi3_i4i)) 117 1.1 mrg #elif !defined (__sh1__) /* !__SH_FPU_DOUBLE__ */ 118 1.1 mrg 119 1.1 mrg #if 0 120 1.1 mrg /* With 36 bytes, the following would probably be the most compact 121 1.1 mrg implementation, but with 139 cycles on an sh4-200, it is extremely slow. */ 122 1.1 mrg GLOBAL(udivsi3_i4i): 123 1.1 mrg mov.l r2,@-r15 124 1.1 mrg mov #0,r1 125 1.1 mrg div0u 126 1.1 mrg mov r1,r2 127 1.1 mrg mov.l r3,@-r15 128 1.1 mrg mov r1,r3 129 1.1 mrg sett 130 1.1 mrg mov r4,r0 131 1.1 mrg LOCAL(loop): 132 1.1 mrg rotcr r2 133 1.1 mrg ; 134 1.1 mrg bt/s LOCAL(end) 135 1.1 mrg cmp/gt r2,r3 136 1.1 mrg rotcl r0 137 1.1 mrg bra LOCAL(loop) 138 1.1 mrg div1 r5,r1 139 1.1 mrg LOCAL(end): 140 1.1 mrg rotcl r0 141 1.1 mrg mov.l @r15+,r3 142 1.1 mrg rts 143 1.1 mrg mov.l @r15+,r2 144 1.1 mrg #endif /* 0 */ 145 1.1 mrg 146 1.1 mrg /* Size: 186 bytes jointly for udivsi3_i4i and sdivsi3_i4i 147 1.1 mrg sh4-200 run times: 148 1.1 mrg udiv small divisor: 55 cycles 149 1.1 mrg udiv large divisor: 52 cycles 150 1.1 mrg sdiv small divisor, positive result: 59 cycles 151 1.1 mrg sdiv large divisor, positive result: 56 cycles 152 1.1 mrg sdiv small divisor, negative result: 65 cycles (*) 153 1.1 mrg sdiv large divisor, negative result: 62 cycles (*) 154 1.1 mrg (*): r2 is restored in the rts delay slot and has a lingering latency 155 1.1 mrg of two more cycles. */ 156 1.1 mrg .balign 4 157 1.1 mrg .global GLOBAL(udivsi3_i4i) 158 1.1 mrg FUNC(GLOBAL(udivsi3_i4i)) 159 1.1 mrg FUNC(GLOBAL(sdivsi3_i4i)) 160 1.1 mrg GLOBAL(udivsi3_i4i): 161 1.1 mrg sts pr,r1 162 1.1 mrg mov.l r4,@-r15 163 1.1 mrg extu.w r5,r0 164 1.1 mrg cmp/eq r5,r0 165 1.1 mrg swap.w r4,r0 166 1.1 mrg shlr16 r4 167 1.1 mrg bf/s LOCAL(large_divisor) 168 1.1 mrg div0u 169 1.1 mrg mov.l r5,@-r15 170 1.1 mrg shll16 r5 171 1.1 mrg LOCAL(sdiv_small_divisor): 172 1.1 mrg div1 r5,r4 173 1.1 mrg bsr LOCAL(div6) 174 1.1 mrg div1 r5,r4 175 1.1 mrg div1 r5,r4 176 1.1 mrg bsr LOCAL(div6) 177 1.1 mrg div1 r5,r4 178 1.1 mrg xtrct r4,r0 179 1.1 mrg xtrct r0,r4 180 1.1 mrg bsr LOCAL(div7) 181 1.1 mrg swap.w r4,r4 182 1.1 mrg div1 r5,r4 183 1.1 mrg bsr LOCAL(div7) 184 1.1 mrg div1 r5,r4 185 1.1 mrg xtrct r4,r0 186 1.1 mrg mov.l @r15+,r5 187 1.1 mrg swap.w r0,r0 188 1.1 mrg mov.l @r15+,r4 189 1.1 mrg jmp @r1 190 1.1 mrg rotcl r0 191 1.1 mrg LOCAL(div7): 192 1.1 mrg div1 r5,r4 193 1.1 mrg LOCAL(div6): 194 1.1 mrg div1 r5,r4; div1 r5,r4; div1 r5,r4 195 1.1 mrg div1 r5,r4; div1 r5,r4; rts; div1 r5,r4 196 1.1 mrg 197 1.1 mrg LOCAL(divx3): 198 1.1 mrg rotcl r0 199 1.1 mrg div1 r5,r4 200 1.1 mrg rotcl r0 201 1.1 mrg div1 r5,r4 202 1.1 mrg rotcl r0 203 1.1 mrg rts 204 1.1 mrg div1 r5,r4 205 1.1 mrg 206 1.1 mrg LOCAL(large_divisor): 207 1.1 mrg mov.l r5,@-r15 208 1.1 mrg LOCAL(sdiv_large_divisor): 209 1.1 mrg xor r4,r0 210 1.1 mrg .rept 4 211 1.1 mrg rotcl r0 212 1.1 mrg bsr LOCAL(divx3) 213 1.1 mrg div1 r5,r4 214 1.1 mrg .endr 215 1.1 mrg mov.l @r15+,r5 216 1.1 mrg mov.l @r15+,r4 217 1.1 mrg jmp @r1 218 1.1 mrg rotcl r0 219 1.1 mrg ENDFUNC(GLOBAL(udivsi3_i4i)) 220 1.1 mrg 221 1.1 mrg .global GLOBAL(sdivsi3_i4i) 222 1.1 mrg GLOBAL(sdivsi3_i4i): 223 1.1 mrg mov.l r4,@-r15 224 1.1 mrg cmp/pz r5 225 1.1 mrg mov.l r5,@-r15 226 1.1 mrg bt/s LOCAL(pos_divisor) 227 1.1 mrg cmp/pz r4 228 1.1 mrg neg r5,r5 229 1.1 mrg extu.w r5,r0 230 1.1 mrg bt/s LOCAL(neg_result) 231 1.1 mrg cmp/eq r5,r0 232 1.1 mrg neg r4,r4 233 1.1 mrg LOCAL(pos_result): 234 1.1 mrg swap.w r4,r0 235 1.1 mrg bra LOCAL(sdiv_check_divisor) 236 1.1 mrg sts pr,r1 237 1.1 mrg LOCAL(pos_divisor): 238 1.1 mrg extu.w r5,r0 239 1.1 mrg bt/s LOCAL(pos_result) 240 1.1 mrg cmp/eq r5,r0 241 1.1 mrg neg r4,r4 242 1.1 mrg LOCAL(neg_result): 243 1.1 mrg mova LOCAL(negate_result),r0 244 1.1 mrg ; 245 1.1 mrg mov r0,r1 246 1.1 mrg swap.w r4,r0 247 1.1 mrg lds r2,macl 248 1.1 mrg sts pr,r2 249 1.1 mrg LOCAL(sdiv_check_divisor): 250 1.1 mrg shlr16 r4 251 1.1 mrg bf/s LOCAL(sdiv_large_divisor) 252 1.1 mrg div0u 253 1.1 mrg bra LOCAL(sdiv_small_divisor) 254 1.1 mrg shll16 r5 255 1.1 mrg .balign 4 256 1.1 mrg LOCAL(negate_result): 257 1.1 mrg neg r0,r0 258 1.1 mrg jmp @r2 259 1.1 mrg sts macl,r2 260 1.1 mrg ENDFUNC(GLOBAL(sdivsi3_i4i)) 261 1.1 mrg #endif /* !__SH_FPU_DOUBLE__ */ 262 1.1 mrg #endif /* L_udivsi3_i4i */ 263 1.1 mrg 264 1.1 mrg #ifdef L_sdivsi3_i4i 265 1.1 mrg #if defined (__SH_FPU_DOUBLE__) || defined (__SH4_SINGLE_ONLY__) 266 1.1 mrg /* 48 bytes, 45 cycles on sh4-200 */ 267 1.1 mrg !! args in r4 and r5, result in r0, clobber r1 268 1.1 mrg 269 1.1 mrg .global GLOBAL(sdivsi3_i4i) 270 1.1 mrg FUNC(GLOBAL(sdivsi3_i4i)) 271 1.1 mrg GLOBAL(sdivsi3_i4i): 272 1.1 mrg sts.l fpscr,@-r15 273 1.1 mrg sts fpul,r1 274 1.1 mrg mova L1,r0 275 1.1 mrg lds.l @r0+,fpscr 276 1.1 mrg lds r4,fpul 277 1.1 mrg #ifdef FMOVD_WORKS 278 1.1 mrg fmov.d dr0,@-r15 279 1.1 mrg float fpul,dr0 280 1.1 mrg lds r5,fpul 281 1.1 mrg fmov.d dr2,@-r15 282 1.1 mrg #else 283 1.1 mrg fmov.s DR01,@-r15 284 1.1 mrg fmov.s DR00,@-r15 285 1.1 mrg float fpul,dr0 286 1.1 mrg lds r5,fpul 287 1.1 mrg fmov.s DR21,@-r15 288 1.1 mrg fmov.s DR20,@-r15 289 1.1 mrg #endif 290 1.1 mrg float fpul,dr2 291 1.1 mrg fdiv dr2,dr0 292 1.1 mrg #ifdef FMOVD_WORKS 293 1.1 mrg fmov.d @r15+,dr2 294 1.1 mrg #else 295 1.1 mrg fmov.s @r15+,DR20 296 1.1 mrg fmov.s @r15+,DR21 297 1.1 mrg #endif 298 1.1 mrg ftrc dr0,fpul 299 1.1 mrg #ifdef FMOVD_WORKS 300 1.1 mrg fmov.d @r15+,dr0 301 1.1 mrg #else 302 1.1 mrg fmov.s @r15+,DR00 303 1.1 mrg fmov.s @r15+,DR01 304 1.1 mrg #endif 305 1.1 mrg lds.l @r15+,fpscr 306 1.1 mrg sts fpul,r0 307 1.1 mrg rts 308 1.1 mrg lds r1,fpul 309 1.1 mrg 310 1.1 mrg .p2align 2 311 1.1 mrg L1: 312 1.1 mrg #ifndef FMOVD_WORKS 313 1.1 mrg .long 0x80000 314 1.1 mrg #else 315 1.1 mrg .long 0x180000 316 1.1 mrg #endif 317 1.1 mrg 318 1.1 mrg ENDFUNC(GLOBAL(sdivsi3_i4i)) 319 1.1 mrg #endif /* __SH_FPU_DOUBLE__ */ 320 1.1 mrg #endif /* L_sdivsi3_i4i */ 321