1 1.1 mrg /* HImode div/mod functions for the GCC support library for the Renesas RL78 processors. 2 1.7 mrg Copyright (C) 2012-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Red Hat. 4 1.1 mrg 5 1.1 mrg This file is part of GCC. 6 1.1 mrg 7 1.1 mrg GCC is free software; you can redistribute it and/or modify 8 1.1 mrg it under the terms of the GNU General Public License as published by 9 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 10 1.1 mrg any later version. 11 1.1 mrg 12 1.1 mrg GCC is distributed in the hope that it will be useful, 13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 mrg GNU General Public License for more details. 16 1.1 mrg 17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 18 1.1 mrg permissions described in the GCC Runtime Library Exception, version 19 1.1 mrg 3.1, as published by the Free Software Foundation. 20 1.1 mrg 21 1.1 mrg You should have received a copy of the GNU General Public License and 22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 1.1 mrg <http://www.gnu.org/licenses/>. */ 25 1.1 mrg 26 1.1 mrg #include "vregs.h" 27 1.1 mrg 28 1.3 mrg #if defined __RL78_MUL_G14__ 29 1.3 mrg 30 1.3 mrg START_FUNC ___divhi3 31 1.3 mrg ;; r8 = 4[sp] / 6[sp] 32 1.3 mrg 33 1.3 mrg ;; Test for a negative denumerator. 34 1.3 mrg movw ax, [sp+6] 35 1.3 mrg mov1 cy, a.7 36 1.3 mrg movw de, ax 37 1.3 mrg bc $__div_neg_den 38 1.3 mrg 39 1.3 mrg ;; Test for a negative numerator. 40 1.3 mrg movw ax, [sp+4] 41 1.3 mrg mov1 cy, a.7 42 1.3 mrg bc $__div_neg_num 43 1.3 mrg 44 1.3 mrg ;; Neither are negative - we can use the unsigned divide instruction. 45 1.3 mrg __div_no_convert: 46 1.3 mrg push psw 47 1.3 mrg di 48 1.3 mrg divhu 49 1.3 mrg pop psw 50 1.3 mrg 51 1.3 mrg movw r8, ax 52 1.3 mrg ret 53 1.3 mrg 54 1.3 mrg __div_neg_den: 55 1.3 mrg ;; Negate the denumerator (which is in DE) 56 1.3 mrg clrw ax 57 1.3 mrg subw ax, de 58 1.3 mrg movw de, ax 59 1.3 mrg 60 1.3 mrg ;; Test for a negative numerator. 61 1.3 mrg movw ax, [sp+4] 62 1.3 mrg mov1 cy, a.7 63 1.3 mrg ;; If it is not negative then we perform the division and then negate the result. 64 1.3 mrg bnc $__div_then_convert 65 1.3 mrg 66 1.3 mrg ;; Otherwise we negate the numerator and then go with an unsigned division. 67 1.3 mrg movw bc, ax 68 1.3 mrg clrw ax 69 1.3 mrg subw ax, bc 70 1.3 mrg br $__div_no_convert 71 1.3 mrg 72 1.3 mrg __div_neg_num: 73 1.3 mrg ;; Negate the numerator (which is in AX) 74 1.3 mrg ;; We know that the denumerator is positive. 75 1.3 mrg movw bc, ax 76 1.3 mrg clrw ax 77 1.3 mrg subw ax, bc 78 1.3 mrg 79 1.3 mrg __div_then_convert: 80 1.3 mrg push psw 81 1.3 mrg di 82 1.3 mrg divhu 83 1.3 mrg pop psw 84 1.3 mrg 85 1.3 mrg ;; Negate result and transfer into r8 86 1.3 mrg movw bc, ax 87 1.3 mrg clrw ax 88 1.3 mrg subw ax, bc 89 1.3 mrg movw r8, ax 90 1.3 mrg ret 91 1.3 mrg 92 1.3 mrg END_FUNC ___divhi3 93 1.3 mrg 94 1.3 mrg ;---------------------------------------------------------------------- 95 1.3 mrg 96 1.3 mrg START_FUNC ___modhi3 97 1.3 mrg ;; r8 = 4[sp] % 6[sp] 98 1.3 mrg 99 1.3 mrg ;; Test for a negative denumerator. 100 1.3 mrg movw ax, [sp+6] 101 1.3 mrg mov1 cy, a.7 102 1.3 mrg movw de, ax 103 1.3 mrg bc $__mod_neg_den 104 1.3 mrg 105 1.3 mrg ;; Test for a negative numerator. 106 1.3 mrg movw ax, [sp+4] 107 1.3 mrg mov1 cy, a.7 108 1.3 mrg bc $__mod_neg_num 109 1.3 mrg 110 1.3 mrg ;; Neither are negative - we can use the unsigned divide instruction. 111 1.3 mrg __mod_no_convert: 112 1.3 mrg push psw 113 1.3 mrg di 114 1.3 mrg divhu 115 1.3 mrg pop psw 116 1.3 mrg 117 1.3 mrg movw ax, de 118 1.3 mrg movw r8, ax 119 1.3 mrg ret 120 1.3 mrg 121 1.3 mrg __mod_neg_den: 122 1.3 mrg ;; Negate the denumerator (which is in DE) 123 1.3 mrg clrw ax 124 1.3 mrg subw ax, de 125 1.3 mrg movw de, ax 126 1.3 mrg 127 1.3 mrg ;; Test for a negative numerator. 128 1.3 mrg movw ax, [sp+4] 129 1.3 mrg mov1 cy, a.7 130 1.3 mrg ;; If it is not negative then we perform the modulo operation without conversion. 131 1.3 mrg bnc $__mod_no_convert 132 1.3 mrg 133 1.3 mrg ;; Otherwise we negate the numerator and then go with an unsigned modulo operation. 134 1.3 mrg movw bc, ax 135 1.3 mrg clrw ax 136 1.3 mrg subw ax, bc 137 1.3 mrg br $__mod_then_convert 138 1.3 mrg 139 1.3 mrg __mod_neg_num: 140 1.3 mrg ;; Negate the numerator (which is in AX) 141 1.3 mrg ;; We know that the denumerator is positive. 142 1.3 mrg movw bc, ax 143 1.3 mrg clrw ax 144 1.3 mrg subw ax, bc 145 1.3 mrg 146 1.3 mrg __mod_then_convert: 147 1.3 mrg push psw 148 1.3 mrg di 149 1.3 mrg divhu 150 1.3 mrg pop psw 151 1.3 mrg 152 1.3 mrg ;; Negate result and transfer into r8 153 1.3 mrg clrw ax 154 1.3 mrg subw ax, de 155 1.3 mrg movw r8, ax 156 1.3 mrg ret 157 1.3 mrg 158 1.3 mrg END_FUNC ___modhi3 159 1.3 mrg 160 1.3 mrg ;---------------------------------------------------------------------- 161 1.3 mrg 162 1.3 mrg #elif defined __RL78_MUL_G13__ 163 1.3 mrg 164 1.3 mrg ;; The G13 S2 core does not have a 16 bit divide peripheral. 165 1.3 mrg ;; So instead we perform a 32-bit divide and twiddle the inputs 166 1.3 mrg ;; as necessary. 167 1.3 mrg 168 1.3 mrg ;; Hardware registers. Note - these values match the silicon, not the documentation. 169 1.3 mrg MDAL = 0xffff0 170 1.3 mrg MDAH = 0xffff2 171 1.3 mrg MDBL = 0xffff6 172 1.3 mrg MDBH = 0xffff4 173 1.3 mrg MDCL = 0xf00e0 174 1.3 mrg MDCH = 0xf00e2 175 1.3 mrg MDUC = 0xf00e8 176 1.3 mrg 177 1.3 mrg .macro _Negate src, dest 178 1.3 mrg movw ax, !\src 179 1.3 mrg movw bc, ax 180 1.3 mrg clrw ax 181 1.3 mrg subw ax, bc 182 1.3 mrg movw \dest, ax 183 1.3 mrg .endm 184 1.3 mrg 185 1.3 mrg ;---------------------------------------------------------------------- 186 1.3 mrg 187 1.3 mrg START_FUNC ___divhi3 188 1.3 mrg ;; r8 = 4[sp] / 6[sp] (signed division) 189 1.3 mrg 190 1.3 mrg mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 191 1.3 mrg mov !MDUC, a ; This preps the peripheral for division without interrupt generation 192 1.3 mrg 193 1.3 mrg clrw ax ; Clear the top 16-bits of the divisor and dividend 194 1.3 mrg movw MDBH, ax 195 1.3 mrg movw MDAH, ax 196 1.3 mrg 197 1.3 mrg ;; Load and test for a negative denumerator. 198 1.3 mrg movw ax, [sp+6] 199 1.3 mrg movw MDBL, ax 200 1.3 mrg mov1 cy, a.7 201 1.3 mrg bc $__div_neg_den 202 1.3 mrg 203 1.3 mrg ;; Load and test for a negative numerator. 204 1.3 mrg movw ax, [sp+4] 205 1.3 mrg mov1 cy, a.7 206 1.3 mrg movw MDAL, ax 207 1.3 mrg bc $__div_neg_num 208 1.3 mrg 209 1.3 mrg ;; Neither are negative - we can use the unsigned divide hardware. 210 1.3 mrg __div_no_convert: 211 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC 212 1.3 mrg mov !MDUC, a ; This starts the division op 213 1.3 mrg 214 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear 215 1.3 mrg bt a.0, $1b 216 1.3 mrg 217 1.3 mrg movw ax, MDAL ; Read the result 218 1.3 mrg movw r8, ax 219 1.3 mrg ret 220 1.3 mrg 221 1.3 mrg __div_neg_den: 222 1.3 mrg ;; Negate the denumerator (which is in MDBL) 223 1.3 mrg _Negate MDBL MDBL 224 1.3 mrg 225 1.3 mrg ;; Load and test for a negative numerator. 226 1.3 mrg movw ax, [sp+4] 227 1.3 mrg mov1 cy, a.7 228 1.3 mrg movw MDAL, ax 229 1.3 mrg ;; If it is not negative then we perform the division and then negate the result. 230 1.3 mrg bnc $__div_then_convert 231 1.3 mrg 232 1.3 mrg ;; Otherwise we negate the numerator and then go with a straightforward unsigned division. 233 1.3 mrg _Negate MDAL MDAL 234 1.3 mrg br $!__div_no_convert 235 1.3 mrg 236 1.3 mrg __div_neg_num: 237 1.3 mrg ;; Negate the numerator (which is in MDAL) 238 1.3 mrg ;; We know that the denumerator is positive. 239 1.3 mrg _Negate MDAL MDAL 240 1.3 mrg 241 1.3 mrg __div_then_convert: 242 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC 243 1.3 mrg mov !MDUC, a ; This starts the division op 244 1.3 mrg 245 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear 246 1.3 mrg bt a.0, $1b 247 1.3 mrg 248 1.3 mrg ;; Negate result and transfer into r8 249 1.3 mrg _Negate MDAL r8 250 1.3 mrg ret 251 1.3 mrg 252 1.3 mrg END_FUNC ___divhi3 253 1.3 mrg 254 1.3 mrg ;---------------------------------------------------------------------- 255 1.3 mrg 256 1.3 mrg START_FUNC ___modhi3 257 1.3 mrg ;; r8 = 4[sp] % 6[sp] (signed modulus) 258 1.3 mrg 259 1.3 mrg mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 260 1.3 mrg mov !MDUC, a ; This preps the peripheral for division without interrupt generation 261 1.3 mrg 262 1.3 mrg clrw ax ; Clear the top 16-bits of the divisor and dividend 263 1.3 mrg movw MDBH, ax 264 1.3 mrg movw MDAH, ax 265 1.3 mrg 266 1.3 mrg ;; Load and test for a negative denumerator. 267 1.3 mrg movw ax, [sp+6] 268 1.3 mrg movw MDBL, ax 269 1.3 mrg mov1 cy, a.7 270 1.3 mrg bc $__mod_neg_den 271 1.3 mrg 272 1.3 mrg ;; Load and test for a negative numerator. 273 1.3 mrg movw ax, [sp+4] 274 1.3 mrg mov1 cy, a.7 275 1.3 mrg movw MDAL, ax 276 1.3 mrg bc $__mod_neg_num 277 1.3 mrg 278 1.3 mrg ;; Neither are negative - we can use the unsigned divide hardware 279 1.3 mrg __mod_no_convert: 280 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC 281 1.3 mrg mov !MDUC, a ; This starts the division op 282 1.3 mrg 283 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear 284 1.3 mrg bt a.0, $1b 285 1.3 mrg 286 1.3 mrg movw ax, !MDCL ; Read the remainder 287 1.3 mrg movw r8, ax 288 1.3 mrg ret 289 1.3 mrg 290 1.3 mrg __mod_neg_den: 291 1.3 mrg ;; Negate the denumerator (which is in MDBL) 292 1.3 mrg _Negate MDBL MDBL 293 1.3 mrg 294 1.3 mrg ;; Load and test for a negative numerator. 295 1.3 mrg movw ax, [sp+4] 296 1.3 mrg mov1 cy, a.7 297 1.3 mrg movw MDAL, ax 298 1.3 mrg ;; If it is not negative then we perform the modulo operation without conversion. 299 1.3 mrg bnc $__mod_no_convert 300 1.3 mrg 301 1.3 mrg ;; Otherwise we negate the numerator and then go with a modulo followed by negation. 302 1.3 mrg _Negate MDAL MDAL 303 1.3 mrg br $!__mod_then_convert 304 1.3 mrg 305 1.3 mrg __mod_neg_num: 306 1.3 mrg ;; Negate the numerator (which is in MDAL) 307 1.3 mrg ;; We know that the denumerator is positive. 308 1.3 mrg _Negate MDAL MDAL 309 1.3 mrg 310 1.3 mrg __mod_then_convert: 311 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC 312 1.3 mrg mov !MDUC, a ; This starts the division op 313 1.3 mrg 314 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear 315 1.3 mrg bt a.0, $1b 316 1.3 mrg 317 1.3 mrg _Negate MDCL r8 318 1.3 mrg ret 319 1.3 mrg 320 1.3 mrg END_FUNC ___modhi3 321 1.3 mrg 322 1.3 mrg ;---------------------------------------------------------------------- 323 1.3 mrg 324 1.3 mrg START_FUNC ___udivhi3 325 1.3 mrg ;; r8 = 4[sp] / 6[sp] (unsigned division) 326 1.3 mrg 327 1.3 mrg mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 328 1.3 mrg mov !MDUC, a ; This preps the peripheral for division without interrupt generation 329 1.3 mrg 330 1.3 mrg movw ax, [sp+4] ; Load the divisor 331 1.3 mrg movw MDAL, ax 332 1.3 mrg movw ax, [sp+6] ; Load the dividend 333 1.3 mrg movw MDBL, ax 334 1.3 mrg clrw ax 335 1.3 mrg movw MDAH, ax 336 1.3 mrg movw MDBH, ax 337 1.3 mrg 338 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC 339 1.3 mrg mov !MDUC, a ; This starts the division op 340 1.3 mrg 341 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear 342 1.3 mrg bt a.0, $1b 343 1.3 mrg 344 1.3 mrg movw ax, !MDAL ; Read the remainder 345 1.3 mrg movw r8, ax 346 1.3 mrg ret 347 1.3 mrg 348 1.3 mrg END_FUNC ___udivhi3 349 1.3 mrg 350 1.3 mrg ;---------------------------------------------------------------------- 351 1.3 mrg 352 1.3 mrg START_FUNC ___umodhi3 353 1.3 mrg ;; r8 = 4[sp] % 6[sp] (unsigned modulus) 354 1.3 mrg 355 1.3 mrg mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 356 1.3 mrg mov !MDUC, a ; This preps the peripheral for division without interrupt generation 357 1.3 mrg 358 1.3 mrg movw ax, [sp+4] ; Load the divisor 359 1.3 mrg movw MDAL, ax 360 1.3 mrg movw ax, [sp+6] ; Load the dividend 361 1.3 mrg movw MDBL, ax 362 1.3 mrg clrw ax 363 1.3 mrg movw MDAH, ax 364 1.3 mrg movw MDBH, ax 365 1.3 mrg 366 1.3 mrg mov a, #0xC1 ; Set the DIVST bit in MDUC 367 1.3 mrg mov !MDUC, a ; This starts the division op 368 1.3 mrg 369 1.3 mrg 1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear 370 1.3 mrg bt a.0, $1b 371 1.3 mrg 372 1.3 mrg movw ax, !MDCL ; Read the remainder 373 1.3 mrg movw r8, ax 374 1.3 mrg ret 375 1.3 mrg 376 1.3 mrg END_FUNC ___umodhi3 377 1.3 mrg 378 1.3 mrg ;---------------------------------------------------------------------- 379 1.3 mrg 380 1.3 mrg #elif defined __RL78_MUL_NONE__ 381 1.3 mrg 382 1.1 mrg .macro MAKE_GENERIC which,need_result 383 1.1 mrg 384 1.1 mrg .if \need_result 385 1.1 mrg quot = r8 386 1.1 mrg num = r10 387 1.1 mrg den = r12 388 1.1 mrg bit = r14 389 1.1 mrg .else 390 1.1 mrg num = r8 391 1.1 mrg quot = r10 392 1.1 mrg den = r12 393 1.1 mrg bit = r14 394 1.1 mrg .endif 395 1.1 mrg 396 1.1 mrg quotB0 = quot 397 1.1 mrg quotB1 = quot+1 398 1.1 mrg 399 1.1 mrg numB0 = num 400 1.1 mrg numB1 = num+1 401 1.1 mrg 402 1.1 mrg denB0 = den 403 1.1 mrg denB1 = den+1 404 1.1 mrg 405 1.1 mrg bitB0 = bit 406 1.1 mrg bitB1 = bit+1 407 1.1 mrg 408 1.1 mrg #define bit bc 409 1.1 mrg #define bitB0 c 410 1.1 mrg #define bitB1 b 411 1.1 mrg 412 1.1 mrg START_FUNC __generic_hidivmod\which 413 1.1 mrg 414 1.1 mrg num_lt_den\which: 415 1.1 mrg .if \need_result 416 1.1 mrg movw r8, #0 417 1.1 mrg .else 418 1.1 mrg movw ax, [sp+8] 419 1.1 mrg movw r8, ax 420 1.1 mrg .endif 421 1.1 mrg ret 422 1.1 mrg 423 1.1 mrg ;; These routines leave DE alone - the signed functions use DE 424 1.1 mrg ;; to store sign information that must remain intact 425 1.1 mrg 426 1.1 mrg .if \need_result 427 1.1 mrg .global __generic_hidiv 428 1.1 mrg __generic_hidiv: 429 1.1 mrg 430 1.1 mrg .else 431 1.1 mrg 432 1.1 mrg .global __generic_himod 433 1.1 mrg __generic_himod: 434 1.1 mrg 435 1.1 mrg .endif 436 1.1 mrg 437 1.1 mrg ;; (quot,rem) = 8[sp] /% 10[sp] 438 1.1 mrg 439 1.1 mrg movw hl, sp 440 1.1 mrg movw ax, [hl+10] ; denH 441 1.1 mrg cmpw ax, [hl+8] ; numH 442 1.1 mrg bh $num_lt_den\which 443 1.1 mrg 444 1.1 mrg ;; (quot,rem) = 16[sp] /% 20[sp] 445 1.1 mrg 446 1.1 mrg ;; copy numerator 447 1.1 mrg movw ax, [hl+8] 448 1.1 mrg movw num, ax 449 1.1 mrg 450 1.1 mrg ;; copy denomonator 451 1.1 mrg movw ax, [hl+10] 452 1.1 mrg movw den, ax 453 1.1 mrg 454 1.1 mrg movw ax, den 455 1.1 mrg cmpw ax, #0 456 1.1 mrg bnz $den_not_zero\which 457 1.3 mrg .if \need_result 458 1.3 mrg movw quot, #0 459 1.3 mrg .else 460 1.1 mrg movw num, #0 461 1.3 mrg .endif 462 1.1 mrg ret 463 1.1 mrg 464 1.1 mrg den_not_zero\which: 465 1.1 mrg .if \need_result 466 1.1 mrg ;; zero out quot 467 1.1 mrg movw quot, #0 468 1.1 mrg .endif 469 1.1 mrg 470 1.1 mrg ;; initialize bit to 1 471 1.1 mrg movw bit, #1 472 1.1 mrg 473 1.1 mrg ; while (den < num && !(den & (1L << BITS_MINUS_1))) 474 1.1 mrg 475 1.1 mrg shift_den_bit\which: 476 1.1 mrg movw ax, den 477 1.1 mrg mov1 cy,a.7 478 1.1 mrg bc $enter_main_loop\which 479 1.1 mrg cmpw ax, num 480 1.1 mrg bh $enter_main_loop\which 481 1.1 mrg 482 1.1 mrg ;; den <<= 1 483 1.1 mrg ; movw ax, den ; already has it from the cmpw above 484 1.1 mrg shlw ax, 1 485 1.1 mrg movw den, ax 486 1.1 mrg 487 1.1 mrg ;; bit <<= 1 488 1.1 mrg .if \need_result 489 1.1 mrg #ifdef bit 490 1.1 mrg shlw bit, 1 491 1.1 mrg #else 492 1.1 mrg movw ax, bit 493 1.1 mrg shlw ax, 1 494 1.1 mrg movw bit, ax 495 1.1 mrg #endif 496 1.1 mrg .else 497 1.1 mrg ;; if we don't need to compute the quotent, we don't need an 498 1.1 mrg ;; actual bit *mask*, we just need to keep track of which bit 499 1.1 mrg inc bitB0 500 1.1 mrg .endif 501 1.1 mrg 502 1.1 mrg br $shift_den_bit\which 503 1.1 mrg 504 1.1 mrg main_loop\which: 505 1.1 mrg 506 1.1 mrg ;; if (num >= den) (cmp den > num) 507 1.1 mrg movw ax, den 508 1.1 mrg cmpw ax, num 509 1.1 mrg bh $next_loop\which 510 1.1 mrg 511 1.1 mrg ;; num -= den 512 1.1 mrg movw ax, num 513 1.1 mrg subw ax, den 514 1.1 mrg movw num, ax 515 1.1 mrg 516 1.1 mrg .if \need_result 517 1.1 mrg ;; res |= bit 518 1.1 mrg mov a, quotB0 519 1.1 mrg or a, bitB0 520 1.1 mrg mov quotB0, a 521 1.1 mrg mov a, quotB1 522 1.1 mrg or a, bitB1 523 1.1 mrg mov quotB1, a 524 1.1 mrg .endif 525 1.1 mrg 526 1.1 mrg next_loop\which: 527 1.1 mrg 528 1.1 mrg ;; den >>= 1 529 1.1 mrg movw ax, den 530 1.1 mrg shrw ax, 1 531 1.1 mrg movw den, ax 532 1.1 mrg 533 1.1 mrg .if \need_result 534 1.1 mrg ;; bit >>= 1 535 1.1 mrg movw ax, bit 536 1.1 mrg shrw ax, 1 537 1.1 mrg movw bit, ax 538 1.1 mrg .else 539 1.1 mrg dec bitB0 540 1.1 mrg .endif 541 1.1 mrg 542 1.1 mrg enter_main_loop\which: 543 1.1 mrg .if \need_result 544 1.1 mrg movw ax, bit 545 1.1 mrg cmpw ax, #0 546 1.1 mrg .else 547 1.1 mrg cmp0 bitB0 548 1.1 mrg .endif 549 1.1 mrg bnz $main_loop\which 550 1.1 mrg 551 1.1 mrg main_loop_done\which: 552 1.1 mrg ret 553 1.1 mrg END_FUNC __generic_hidivmod\which 554 1.1 mrg .endm 555 1.1 mrg ;---------------------------------------------------------------------- 556 1.1 mrg 557 1.1 mrg MAKE_GENERIC _d 1 558 1.1 mrg MAKE_GENERIC _m 0 559 1.1 mrg 560 1.1 mrg ;---------------------------------------------------------------------- 561 1.1 mrg 562 1.1 mrg START_FUNC ___udivhi3 563 1.1 mrg ;; r8 = 4[sp] / 6[sp] 564 1.1 mrg call $!__generic_hidiv 565 1.1 mrg ret 566 1.1 mrg END_FUNC ___udivhi3 567 1.1 mrg 568 1.1 mrg 569 1.1 mrg START_FUNC ___umodhi3 570 1.1 mrg ;; r8 = 4[sp] % 6[sp] 571 1.1 mrg call $!__generic_himod 572 1.1 mrg ret 573 1.1 mrg END_FUNC ___umodhi3 574 1.1 mrg 575 1.1 mrg ;---------------------------------------------------------------------- 576 1.1 mrg 577 1.1 mrg .macro NEG_AX 578 1.1 mrg movw hl, ax 579 1.1 mrg movw ax, #0 580 1.1 mrg subw ax, [hl] 581 1.1 mrg movw [hl], ax 582 1.1 mrg .endm 583 1.1 mrg 584 1.1 mrg ;---------------------------------------------------------------------- 585 1.1 mrg 586 1.1 mrg START_FUNC ___divhi3 587 1.1 mrg ;; r8 = 4[sp] / 6[sp] 588 1.1 mrg movw de, #0 589 1.1 mrg mov a, [sp+5] 590 1.1 mrg mov1 cy, a.7 591 1.1 mrg bc $div_signed_num 592 1.1 mrg mov a, [sp+7] 593 1.1 mrg mov1 cy, a.7 594 1.1 mrg bc $div_signed_den 595 1.1 mrg call $!__generic_hidiv 596 1.1 mrg ret 597 1.1 mrg 598 1.1 mrg div_signed_num: 599 1.1 mrg ;; neg [sp+4] 600 1.1 mrg movw ax, sp 601 1.1 mrg addw ax, #4 602 1.1 mrg NEG_AX 603 1.1 mrg mov d, #1 604 1.1 mrg mov a, [sp+7] 605 1.1 mrg mov1 cy, a.7 606 1.1 mrg bnc $div_unsigned_den 607 1.1 mrg div_signed_den: 608 1.1 mrg ;; neg [sp+6] 609 1.1 mrg movw ax, sp 610 1.1 mrg addw ax, #6 611 1.1 mrg NEG_AX 612 1.1 mrg mov e, #1 613 1.1 mrg div_unsigned_den: 614 1.1 mrg call $!__generic_hidiv 615 1.1 mrg 616 1.1 mrg mov a, d 617 1.1 mrg cmp0 a 618 1.1 mrg bz $div_skip_restore_num 619 1.1 mrg ;; We have to restore the numerator [sp+4] 620 1.1 mrg movw ax, sp 621 1.1 mrg addw ax, #4 622 1.1 mrg NEG_AX 623 1.1 mrg mov a, d 624 1.1 mrg div_skip_restore_num: 625 1.1 mrg xor a, e 626 1.1 mrg bz $div_no_neg 627 1.1 mrg movw ax, #r8 628 1.1 mrg NEG_AX 629 1.1 mrg div_no_neg: 630 1.1 mrg mov a, e 631 1.1 mrg cmp0 a 632 1.1 mrg bz $div_skip_restore_den 633 1.1 mrg movw ax, sp 634 1.1 mrg addw ax, #6 635 1.1 mrg NEG_AX 636 1.1 mrg div_skip_restore_den: 637 1.1 mrg ret 638 1.1 mrg END_FUNC ___divhi3 639 1.1 mrg 640 1.1 mrg 641 1.1 mrg START_FUNC ___modhi3 642 1.1 mrg ;; r8 = 4[sp] % 6[sp] 643 1.1 mrg movw de, #0 644 1.1 mrg mov a, [sp+5] 645 1.1 mrg mov1 cy, a.7 646 1.1 mrg bc $mod_signed_num 647 1.1 mrg mov a, [sp+7] 648 1.1 mrg mov1 cy, a.7 649 1.1 mrg bc $mod_signed_den 650 1.1 mrg call $!__generic_himod 651 1.1 mrg ret 652 1.1 mrg 653 1.1 mrg mod_signed_num: 654 1.1 mrg ;; neg [sp+4] 655 1.1 mrg movw ax, sp 656 1.1 mrg addw ax, #4 657 1.1 mrg NEG_AX 658 1.1 mrg mov d, #1 659 1.1 mrg mov a, [sp+7] 660 1.1 mrg mov1 cy, a.7 661 1.1 mrg bnc $mod_unsigned_den 662 1.1 mrg mod_signed_den: 663 1.1 mrg ;; neg [sp+6] 664 1.1 mrg movw ax, sp 665 1.1 mrg addw ax, #6 666 1.1 mrg NEG_AX 667 1.1 mrg mod_unsigned_den: 668 1.1 mrg call $!__generic_himod 669 1.1 mrg 670 1.1 mrg mov a, d 671 1.1 mrg cmp0 a 672 1.1 mrg bz $mod_no_neg 673 1.1 mrg movw ax, #r8 674 1.1 mrg NEG_AX 675 1.1 mrg ;; Also restore numerator 676 1.1 mrg movw ax, sp 677 1.1 mrg addw ax, #4 678 1.1 mrg NEG_AX 679 1.1 mrg mod_no_neg: 680 1.1 mrg mov a, e 681 1.1 mrg cmp0 a 682 1.1 mrg bz $mod_skip_restore_den 683 1.1 mrg movw ax, sp 684 1.1 mrg addw ax, #6 685 1.1 mrg NEG_AX 686 1.1 mrg mod_skip_restore_den: 687 1.1 mrg ret 688 1.1 mrg END_FUNC ___modhi3 689 1.3 mrg 690 1.3 mrg ;---------------------------------------------------------------------- 691 1.3 mrg 692 1.3 mrg #else 693 1.3 mrg 694 1.3 mrg #error "Unknown RL78 hardware multiply/divide support" 695 1.3 mrg 696 1.3 mrg #endif 697