Home | History | Annotate | Line # | Download | only in rl78
divmodsi.S revision 1.1
      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 
     70 START_FUNC __generic_sidivmod\which
     71 
     72 num_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 
     84 shift_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 
    162 den_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 
    185 shift_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)
    220 main_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 
    257 next_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 
    285 enter_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
    301 bit_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 
    310 switch_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)
    321 main_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 
    348 next_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 
    372 main_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
    390 END_FUNC __generic_sidivmod\which
    391 .endm
    392 
    393 ;----------------------------------------------------------------------
    394 
    395 	MAKE_GENERIC _d 1
    396 	MAKE_GENERIC _m 0
    397 
    398 ;----------------------------------------------------------------------
    399 
    400 START_FUNC ___udivsi3
    401 	;; r8 = 4[sp] / 8[sp]
    402 	call	$!__generic_sidiv
    403 	ret
    404 END_FUNC ___udivsi3
    405 
    406 
    407 START_FUNC ___umodsi3
    408 	;; r8 = 4[sp] % 8[sp]
    409 	call	$!__generic_simod
    410 	ret
    411 END_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 
    429 START_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 
    441 div_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
    450 div_signed_den:
    451 	;; neg [sp+8]
    452 	movw	ax, sp
    453 	addw	ax, #8
    454 	NEG_AX
    455 	mov	e, #1
    456 div_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
    467 div_skip_restore_num:
    468 	xor	a, e
    469 	bz	$div_no_neg
    470 	movw	ax, #r8
    471 	NEG_AX
    472 div_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
    480 div_skip_restore_den:
    481 	ret
    482 END_FUNC ___divsi3
    483 
    484 
    485 START_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 
    497 mod_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
    506 mod_signed_den:
    507 	;; neg [sp+8]
    508 	movw	ax, sp
    509 	addw	ax, #8
    510 	NEG_AX
    511 	mov	e, #1
    512 mod_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
    524 mod_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
    532 mod_skip_restore_den:
    533  .endif
    534 	ret
    535 END_FUNC ___modsi3
    536