1/* SImode div/mod functions for the GCC support library for the Renesas RL78 processors. 2 Copyright (C) 2012-2015 Free Software Foundation, Inc. 3 Contributed by Red Hat. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published 9 by the Free Software Foundation; either version 3, or (at your 10 option) any later version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 Under Section 7 of GPL version 3, you are granted additional 18 permissions described in the GCC Runtime Library Exception, version 19 3.1, as published by the Free Software Foundation. 20 21 You should have received a copy of the GNU General Public License and 22 a copy of the GCC Runtime Library Exception along with this program; 23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 <http://www.gnu.org/licenses/>. */ 25 26#include "vregs.h" 27 28.macro MAKE_GENERIC which,need_result 29 30 .if \need_result 31 quot = r8 32 num = r12 33 den = r16 34 bit = r20 35 .else 36 num = r8 37 quot = r12 38 den = r16 39 bit = r20 40 .endif 41 42 quotH = quot+2 43 quotL = quot 44 quotB0 = quot 45 quotB1 = quot+1 46 quotB2 = quot+2 47 quotB3 = quot+3 48 49 numH = num+2 50 numL = num 51 numB0 = num 52 numB1 = num+1 53 numB2 = num+2 54 numB3 = num+3 55 56#define denH bc 57 denL = den 58 denB0 = den 59 denB1 = den+1 60#define denB2 c 61#define denB3 b 62 63 bitH = bit+2 64 bitL = bit 65 bitB0 = bit 66 bitB1 = bit+1 67 bitB2 = bit+2 68 bitB3 = bit+3 69 70START_FUNC __generic_sidivmod\which 71 72num_lt_den\which: 73 .if \need_result 74 movw r8, #0 75 movw r10, #0 76 .else 77 movw ax, [sp+8] 78 movw r8, ax 79 movw ax, [sp+10] 80 movw r10, ax 81 .endif 82 ret 83 84shift_den_bit16\which: 85 movw ax, denL 86 movw denH, ax 87 movw denL, #0 88 .if \need_result 89 movw ax, bitL 90 movw bitH, ax 91 movw bitL, #0 92 .else 93 mov a, bit 94 add a, #16 95 mov bit, a 96 .endif 97 br $shift_den_bit\which 98 99 ;; These routines leave DE alone - the signed functions use DE 100 ;; to store sign information that must remain intact 101 102 .if \need_result 103 .global __generic_sidiv 104__generic_sidiv: 105 106 .else 107 108 .global __generic_simod 109__generic_simod: 110 111 .endif 112 113 ;; (quot,rem) = 8[sp] /% 12[sp] 114 115 movw hl, sp 116 movw ax, [hl+14] ; denH 117 cmpw ax, [hl+10] ; numH 118 movw ax, [hl+12] ; denL 119 sknz 120 cmpw ax, [hl+8] ; numL 121 bh $num_lt_den\which 122 123#ifdef __RL78_G10__ 124 movw ax, denL 125 push ax 126 movw ax, bitL 127 push ax 128 movw ax, bitH 129 push ax 130#else 131 sel rb2 132 push ax ; denL 133; push bc ; denH 134 push de ; bitL 135 push hl ; bitH - stored in BC 136 sel rb0 137#endif 138 139 ;; (quot,rem) = 16[sp] /% 20[sp] 140 141 ;; copy numerator 142 movw ax, [hl+8] 143 movw numL, ax 144 movw ax, [hl+10] 145 movw numH, ax 146 147 ;; copy denomonator 148 movw ax, [hl+12] 149 movw denL, ax 150 movw ax, [hl+14] 151 movw denH, ax 152 153 movw ax, denL 154 or a, denB2 155 or a, denB3 ; not x 156 cmpw ax, #0 157 bnz $den_not_zero\which 158 movw numL, #0 159 movw numH, #0 160 ret 161 162den_not_zero\which: 163 .if \need_result 164 ;; zero out quot 165 movw quotL, #0 166 movw quotH, #0 167 .endif 168 169 ;; initialize bit to 1 170 movw bitL, #1 171 movw bitH, #0 172 173; while (den < num && !(den & (1L << BITS_MINUS_1))) 174 175 .if 1 176 ;; see if we can short-circuit a bunch of shifts 177 movw ax, denH 178 cmpw ax, #0 179 bnz $shift_den_bit\which 180 movw ax, denL 181 cmpw ax, numH 182 bnh $shift_den_bit16\which 183 .endif 184 185shift_den_bit\which: 186 movw ax, denH 187 mov1 cy,a.7 188 bc $enter_main_loop\which 189 cmpw ax, numH 190 movw ax, denL ; we re-use this below 191 sknz 192 cmpw ax, numL 193 bh $enter_main_loop\which 194 195 ;; den <<= 1 196; movw ax, denL ; already has it from the cmpw above 197 shlw ax, 1 198 movw denL, ax 199; movw ax, denH 200 rolwc denH, 1 201; movw denH, ax 202 203 ;; bit <<= 1 204 .if \need_result 205 movw ax, bitL 206 shlw ax, 1 207 movw bitL, ax 208 movw ax, bitH 209 rolwc ax, 1 210 movw bitH, ax 211 .else 212 ;; if we don't need to compute the quotent, we don't need an 213 ;; actual bit *mask*, we just need to keep track of which bit 214 inc bitB0 215 .endif 216 217 br $shift_den_bit\which 218 219 ;; while (bit) 220main_loop\which: 221 222 ;; if (num >= den) (cmp den > num) 223 movw ax, numH 224 cmpw ax, denH 225 movw ax, numL 226 sknz 227 cmpw ax, denL 228 skz 229 bnh $next_loop\which 230 231 ;; num -= den 232; movw ax, numL ; already has it from the cmpw above 233 subw ax, denL 234 movw numL, ax 235 movw ax, numH 236 sknc 237 decw ax 238 subw ax, denH 239 movw numH, ax 240 241 .if \need_result 242 ;; res |= bit 243 mov a, quotB0 244 or a, bitB0 245 mov quotB0, a 246 mov a, quotB1 247 or a, bitB1 248 mov quotB1, a 249 mov a, quotB2 250 or a, bitB2 251 mov quotB2, a 252 mov a, quotB3 253 or a, bitB3 254 mov quotB3, a 255 .endif 256 257next_loop\which: 258 259 ;; den >>= 1 260 movw ax, denH 261 shrw ax, 1 262 movw denH, ax 263 mov a, denB1 264 rorc a, 1 265 mov denB1, a 266 mov a, denB0 267 rorc a, 1 268 mov denB0, a 269 270 ;; bit >>= 1 271 .if \need_result 272 movw ax, bitH 273 shrw ax, 1 274 movw bitH, ax 275 mov a, bitB1 276 rorc a, 1 277 mov bitB1, a 278 mov a, bitB0 279 rorc a, 1 280 mov bitB0, a 281 .else 282 dec bitB0 283 .endif 284 285enter_main_loop\which: 286 .if \need_result 287 movw ax, bitH 288 cmpw ax, #0 289 bnz $main_loop\which 290 .else 291 cmp bitB0, #15 292 bh $main_loop\which 293 .endif 294 ;; bit is HImode now; check others 295 movw ax, numH ; numerator 296 cmpw ax, #0 297 bnz $bit_high_set\which 298 movw ax, denH ; denominator 299 cmpw ax, #0 300 bz $switch_to_himode\which 301bit_high_set\which: 302 .if \need_result 303 movw ax, bitL 304 cmpw ax, #0 305 .else 306 cmp0 bitB0 307 .endif 308 bnz $main_loop\which 309 310switch_to_himode\which: 311 .if \need_result 312 movw ax, bitL 313 cmpw ax, #0 314 .else 315 cmp0 bitB0 316 .endif 317 bz $main_loop_done_himode\which 318 319 ;; From here on in, r22, r14, and r18 are all zero 320 ;; while (bit) 321main_loop_himode\which: 322 323 ;; if (num >= den) (cmp den > num) 324 movw ax, denL 325 cmpw ax, numL 326 bh $next_loop_himode\which 327 328 ;; num -= den 329 movw ax, numL 330 subw ax, denL 331 movw numL, ax 332 movw ax, numH 333 sknc 334 decw ax 335 subw ax, denH 336 movw numH, ax 337 338 .if \need_result 339 ;; res |= bit 340 mov a, quotB0 341 or a, bitB0 342 mov quotB0, a 343 mov a, quotB1 344 or a, bitB1 345 mov quotB1, a 346 .endif 347 348next_loop_himode\which: 349 350 ;; den >>= 1 351 movw ax, denL 352 shrw ax, 1 353 movw denL, ax 354 355 .if \need_result 356 ;; bit >>= 1 357 movw ax, bitL 358 shrw ax, 1 359 movw bitL, ax 360 .else 361 dec bitB0 362 .endif 363 364 .if \need_result 365 movw ax, bitL 366 cmpw ax, #0 367 .else 368 cmp0 bitB0 369 .endif 370 bnz $main_loop_himode\which 371 372main_loop_done_himode\which: 373#ifdef __RL78_G10__ 374 pop ax 375 movw bitH, ax 376 pop ax 377 movw bitL, ax 378 pop ax 379 movw denL, ax 380#else 381 sel rb2 382 pop hl ; bitH - stored in BC 383 pop de ; bitL 384; pop bc ; denH 385 pop ax ; denL 386 sel rb0 387#endif 388 389 ret 390END_FUNC __generic_sidivmod\which 391.endm 392 393;---------------------------------------------------------------------- 394 395 MAKE_GENERIC _d 1 396 MAKE_GENERIC _m 0 397 398;---------------------------------------------------------------------- 399 400START_FUNC ___udivsi3 401 ;; r8 = 4[sp] / 8[sp] 402 call $!__generic_sidiv 403 ret 404END_FUNC ___udivsi3 405 406 407START_FUNC ___umodsi3 408 ;; r8 = 4[sp] % 8[sp] 409 call $!__generic_simod 410 ret 411END_FUNC ___umodsi3 412 413;---------------------------------------------------------------------- 414 415.macro NEG_AX 416 movw hl, ax 417 movw ax, #0 418 subw ax, [hl] 419 movw [hl], ax 420 movw ax, #0 421 sknc 422 decw ax 423 subw ax, [hl+2] 424 movw [hl+2], ax 425.endm 426 427;---------------------------------------------------------------------- 428 429START_FUNC ___divsi3 430 ;; r8 = 4[sp] / 8[sp] 431 movw de, #0 432 mov a, [sp+7] 433 mov1 cy, a.7 434 bc $div_signed_num 435 mov a, [sp+11] 436 mov1 cy, a.7 437 bc $div_signed_den 438 call $!__generic_sidiv 439 ret 440 441div_signed_num: 442 ;; neg [sp+4] 443 movw ax, sp 444 addw ax, #4 445 NEG_AX 446 mov d, #1 447 mov a, [sp+11] 448 mov1 cy, a.7 449 bnc $div_unsigned_den 450div_signed_den: 451 ;; neg [sp+8] 452 movw ax, sp 453 addw ax, #8 454 NEG_AX 455 mov e, #1 456div_unsigned_den: 457 call $!__generic_sidiv 458 459 mov a, d 460 cmp0 a 461 bz $div_skip_restore_num 462 ;; We have to restore the numerator [sp+4] 463 movw ax, sp 464 addw ax, #4 465 NEG_AX 466 mov a, d 467div_skip_restore_num: 468 xor a, e 469 bz $div_no_neg 470 movw ax, #r8 471 NEG_AX 472div_no_neg: 473 mov a, e 474 cmp0 a 475 bz $div_skip_restore_den 476 ;; We have to restore the denominator [sp+8] 477 movw ax, sp 478 addw ax, #8 479 NEG_AX 480div_skip_restore_den: 481 ret 482END_FUNC ___divsi3 483 484 485START_FUNC ___modsi3 486 ;; r8 = 4[sp] % 8[sp] 487 movw de, #0 488 mov a, [sp+7] 489 mov1 cy, a.7 490 bc $mod_signed_num 491 mov a, [sp+11] 492 mov1 cy, a.7 493 bc $mod_signed_den 494 call $!__generic_simod 495 ret 496 497mod_signed_num: 498 ;; neg [sp+4] 499 movw ax, sp 500 addw ax, #4 501 NEG_AX 502 mov d, #1 503 mov a, [sp+11] 504 mov1 cy, a.7 505 bnc $mod_unsigned_den 506mod_signed_den: 507 ;; neg [sp+8] 508 movw ax, sp 509 addw ax, #8 510 NEG_AX 511 mov e, #1 512mod_unsigned_den: 513 call $!__generic_simod 514 515 mov a, d 516 cmp0 a 517 bz $mod_no_neg 518 movw ax, #r8 519 NEG_AX 520 ;; We have to restore [sp+4] as well. 521 movw ax, sp 522 addw ax, #4 523 NEG_AX 524mod_no_neg: 525 .if 1 526 mov a, e 527 cmp0 a 528 bz $mod_skip_restore_den 529 movw ax, sp 530 addw ax, #8 531 NEG_AX 532mod_skip_restore_den: 533 .endif 534 ret 535END_FUNC ___modsi3 536