Home | History | Annotate | Line # | Download | only in rl78
divmodhi.S revision 1.1
      1  1.1  mrg /* HImode div/mod functions for the GCC support library for the Renesas RL78 processors.
      2  1.1  mrg    Copyright (C) 2012-2015 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.1  mrg .macro MAKE_GENERIC  which,need_result
     29  1.1  mrg 
     30  1.1  mrg 	.if \need_result
     31  1.1  mrg 	quot = r8
     32  1.1  mrg 	num = r10
     33  1.1  mrg 	den = r12
     34  1.1  mrg 	bit = r14
     35  1.1  mrg 	.else
     36  1.1  mrg 	num = r8
     37  1.1  mrg 	quot = r10
     38  1.1  mrg 	den = r12
     39  1.1  mrg 	bit = r14
     40  1.1  mrg 	.endif
     41  1.1  mrg 
     42  1.1  mrg 	quotB0 = quot
     43  1.1  mrg 	quotB1 = quot+1
     44  1.1  mrg 
     45  1.1  mrg 	numB0 = num
     46  1.1  mrg 	numB1 = num+1
     47  1.1  mrg 
     48  1.1  mrg 	denB0 = den
     49  1.1  mrg 	denB1 = den+1
     50  1.1  mrg 
     51  1.1  mrg 	bitB0 = bit
     52  1.1  mrg 	bitB1 = bit+1
     53  1.1  mrg 
     54  1.1  mrg #define bit	bc
     55  1.1  mrg #define bitB0	c
     56  1.1  mrg #define bitB1	b
     57  1.1  mrg 
     58  1.1  mrg 	START_FUNC __generic_hidivmod\which
     59  1.1  mrg 
     60  1.1  mrg num_lt_den\which:
     61  1.1  mrg 	.if \need_result
     62  1.1  mrg 	movw	r8, #0
     63  1.1  mrg 	.else
     64  1.1  mrg 	movw	ax, [sp+8]
     65  1.1  mrg 	movw	r8, ax
     66  1.1  mrg 	.endif
     67  1.1  mrg 	ret
     68  1.1  mrg 
     69  1.1  mrg 	;; These routines leave DE alone - the signed functions use DE
     70  1.1  mrg 	;; to store sign information that must remain intact
     71  1.1  mrg 
     72  1.1  mrg 	.if \need_result
     73  1.1  mrg 	.global __generic_hidiv
     74  1.1  mrg __generic_hidiv:
     75  1.1  mrg 
     76  1.1  mrg 	.else
     77  1.1  mrg 
     78  1.1  mrg 	.global __generic_himod
     79  1.1  mrg __generic_himod:
     80  1.1  mrg 
     81  1.1  mrg 	.endif
     82  1.1  mrg 
     83  1.1  mrg 	;; (quot,rem) = 8[sp] /% 10[sp]
     84  1.1  mrg 
     85  1.1  mrg 	movw	hl, sp
     86  1.1  mrg 	movw	ax, [hl+10] ; denH
     87  1.1  mrg 	cmpw	ax, [hl+8] ; numH
     88  1.1  mrg 	bh	$num_lt_den\which
     89  1.1  mrg 
     90  1.1  mrg 	;; (quot,rem) = 16[sp] /% 20[sp]
     91  1.1  mrg 
     92  1.1  mrg 	;; copy numerator
     93  1.1  mrg 	movw	ax, [hl+8]
     94  1.1  mrg 	movw	num, ax
     95  1.1  mrg 
     96  1.1  mrg 	;; copy denomonator
     97  1.1  mrg 	movw	ax, [hl+10]
     98  1.1  mrg 	movw	den, ax
     99  1.1  mrg 
    100  1.1  mrg 	movw	ax, den
    101  1.1  mrg 	cmpw	ax, #0
    102  1.1  mrg 	bnz	$den_not_zero\which
    103  1.1  mrg 	movw	num, #0
    104  1.1  mrg 	ret
    105  1.1  mrg 
    106  1.1  mrg den_not_zero\which:
    107  1.1  mrg 	.if \need_result
    108  1.1  mrg 	;; zero out quot
    109  1.1  mrg 	movw	quot, #0
    110  1.1  mrg 	.endif
    111  1.1  mrg 
    112  1.1  mrg 	;; initialize bit to 1
    113  1.1  mrg 	movw	bit, #1
    114  1.1  mrg 
    115  1.1  mrg ; while (den < num && !(den & (1L << BITS_MINUS_1)))
    116  1.1  mrg 
    117  1.1  mrg shift_den_bit\which:
    118  1.1  mrg 	movw	ax, den
    119  1.1  mrg 	mov1	cy,a.7
    120  1.1  mrg 	bc	$enter_main_loop\which
    121  1.1  mrg 	cmpw	ax, num
    122  1.1  mrg 	bh	$enter_main_loop\which
    123  1.1  mrg 
    124  1.1  mrg 	;; den <<= 1
    125  1.1  mrg ;	movw	ax, den		; already has it from the cmpw above
    126  1.1  mrg 	shlw	ax, 1
    127  1.1  mrg 	movw	den, ax
    128  1.1  mrg 
    129  1.1  mrg 	;; bit <<= 1
    130  1.1  mrg 	.if \need_result
    131  1.1  mrg #ifdef bit
    132  1.1  mrg 	shlw	bit, 1
    133  1.1  mrg #else
    134  1.1  mrg 	movw	ax, bit
    135  1.1  mrg 	shlw	ax, 1
    136  1.1  mrg 	movw	bit, ax
    137  1.1  mrg #endif
    138  1.1  mrg 	.else
    139  1.1  mrg 	;; if we don't need to compute the quotent, we don't need an
    140  1.1  mrg 	;; actual bit *mask*, we just need to keep track of which bit
    141  1.1  mrg 	inc	bitB0
    142  1.1  mrg 	.endif
    143  1.1  mrg 
    144  1.1  mrg 	br	$shift_den_bit\which
    145  1.1  mrg 
    146  1.1  mrg main_loop\which:
    147  1.1  mrg 
    148  1.1  mrg 	;; if (num >= den) (cmp den > num)
    149  1.1  mrg 	movw	ax, den
    150  1.1  mrg 	cmpw	ax, num
    151  1.1  mrg 	bh	$next_loop\which
    152  1.1  mrg 
    153  1.1  mrg 	;; num -= den
    154  1.1  mrg 	movw	ax, num
    155  1.1  mrg 	subw	ax, den
    156  1.1  mrg 	movw	num, ax
    157  1.1  mrg 
    158  1.1  mrg 	.if \need_result
    159  1.1  mrg 	;; res |= bit
    160  1.1  mrg 	mov	a, quotB0
    161  1.1  mrg 	or	a, bitB0
    162  1.1  mrg 	mov	quotB0, a
    163  1.1  mrg 	mov	a, quotB1
    164  1.1  mrg 	or	a, bitB1
    165  1.1  mrg 	mov	quotB1, a
    166  1.1  mrg 	.endif
    167  1.1  mrg 
    168  1.1  mrg next_loop\which:
    169  1.1  mrg 
    170  1.1  mrg 	;; den >>= 1
    171  1.1  mrg 	movw	ax, den
    172  1.1  mrg 	shrw	ax, 1
    173  1.1  mrg 	movw	den, ax
    174  1.1  mrg 
    175  1.1  mrg 	.if \need_result
    176  1.1  mrg 	;; bit >>= 1
    177  1.1  mrg 	movw	ax, bit
    178  1.1  mrg 	shrw	ax, 1
    179  1.1  mrg 	movw	bit, ax
    180  1.1  mrg 	.else
    181  1.1  mrg 	dec	bitB0
    182  1.1  mrg 	.endif
    183  1.1  mrg 
    184  1.1  mrg enter_main_loop\which:
    185  1.1  mrg 	.if \need_result
    186  1.1  mrg 	movw	ax, bit
    187  1.1  mrg 	cmpw	ax, #0
    188  1.1  mrg 	.else
    189  1.1  mrg 	cmp0	bitB0
    190  1.1  mrg 	.endif
    191  1.1  mrg 	bnz	$main_loop\which
    192  1.1  mrg 
    193  1.1  mrg main_loop_done\which:
    194  1.1  mrg 	ret
    195  1.1  mrg 	END_FUNC __generic_hidivmod\which
    196  1.1  mrg .endm
    197  1.1  mrg ;----------------------------------------------------------------------
    198  1.1  mrg 
    199  1.1  mrg 	MAKE_GENERIC _d 1
    200  1.1  mrg 	MAKE_GENERIC _m 0
    201  1.1  mrg 
    202  1.1  mrg ;----------------------------------------------------------------------
    203  1.1  mrg 
    204  1.1  mrg START_FUNC ___udivhi3
    205  1.1  mrg 	;; r8 = 4[sp] / 6[sp]
    206  1.1  mrg 	call	$!__generic_hidiv
    207  1.1  mrg 	ret
    208  1.1  mrg END_FUNC ___udivhi3
    209  1.1  mrg 
    210  1.1  mrg 
    211  1.1  mrg START_FUNC ___umodhi3
    212  1.1  mrg 	;; r8 = 4[sp] % 6[sp]
    213  1.1  mrg 	call	$!__generic_himod
    214  1.1  mrg 	ret
    215  1.1  mrg END_FUNC ___umodhi3
    216  1.1  mrg 
    217  1.1  mrg ;----------------------------------------------------------------------
    218  1.1  mrg 
    219  1.1  mrg .macro NEG_AX
    220  1.1  mrg 	movw	hl, ax
    221  1.1  mrg 	movw	ax, #0
    222  1.1  mrg 	subw	ax, [hl]
    223  1.1  mrg 	movw	[hl], ax
    224  1.1  mrg .endm
    225  1.1  mrg 
    226  1.1  mrg ;----------------------------------------------------------------------
    227  1.1  mrg 
    228  1.1  mrg START_FUNC ___divhi3
    229  1.1  mrg 	;; r8 = 4[sp] / 6[sp]
    230  1.1  mrg 	movw	de, #0
    231  1.1  mrg 	mov	a, [sp+5]
    232  1.1  mrg 	mov1	cy, a.7
    233  1.1  mrg 	bc	$div_signed_num
    234  1.1  mrg 	mov	a, [sp+7]
    235  1.1  mrg 	mov1	cy, a.7
    236  1.1  mrg 	bc	$div_signed_den
    237  1.1  mrg 	call	$!__generic_hidiv
    238  1.1  mrg 	ret
    239  1.1  mrg 
    240  1.1  mrg div_signed_num:
    241  1.1  mrg 	;; neg [sp+4]
    242  1.1  mrg 	movw	ax, sp
    243  1.1  mrg 	addw	ax, #4
    244  1.1  mrg 	NEG_AX
    245  1.1  mrg 	mov	d, #1
    246  1.1  mrg 	mov	a, [sp+7]
    247  1.1  mrg 	mov1	cy, a.7
    248  1.1  mrg 	bnc	$div_unsigned_den
    249  1.1  mrg div_signed_den:
    250  1.1  mrg 	;; neg [sp+6]
    251  1.1  mrg 	movw	ax, sp
    252  1.1  mrg 	addw	ax, #6
    253  1.1  mrg 	NEG_AX
    254  1.1  mrg 	mov	e, #1
    255  1.1  mrg div_unsigned_den:
    256  1.1  mrg 	call	$!__generic_hidiv
    257  1.1  mrg 
    258  1.1  mrg 	mov	a, d
    259  1.1  mrg 	cmp0	a
    260  1.1  mrg 	bz	$div_skip_restore_num
    261  1.1  mrg 	;;  We have to restore the numerator [sp+4]
    262  1.1  mrg 	movw	ax, sp
    263  1.1  mrg 	addw	ax, #4
    264  1.1  mrg 	NEG_AX
    265  1.1  mrg 	mov	a, d
    266  1.1  mrg div_skip_restore_num:
    267  1.1  mrg 	xor	a, e
    268  1.1  mrg 	bz	$div_no_neg
    269  1.1  mrg 	movw	ax, #r8
    270  1.1  mrg 	NEG_AX
    271  1.1  mrg div_no_neg:
    272  1.1  mrg 	mov	a, e
    273  1.1  mrg 	cmp0	a
    274  1.1  mrg 	bz	$div_skip_restore_den
    275  1.1  mrg 	movw	ax, sp
    276  1.1  mrg 	addw	ax, #6
    277  1.1  mrg 	NEG_AX
    278  1.1  mrg div_skip_restore_den:
    279  1.1  mrg 	ret
    280  1.1  mrg END_FUNC ___divhi3
    281  1.1  mrg 
    282  1.1  mrg 
    283  1.1  mrg START_FUNC ___modhi3
    284  1.1  mrg 	;; r8 = 4[sp] % 6[sp]
    285  1.1  mrg 	movw	de, #0
    286  1.1  mrg 	mov	a, [sp+5]
    287  1.1  mrg 	mov1	cy, a.7
    288  1.1  mrg 	bc	$mod_signed_num
    289  1.1  mrg 	mov	a, [sp+7]
    290  1.1  mrg 	mov1	cy, a.7
    291  1.1  mrg 	bc	$mod_signed_den
    292  1.1  mrg 	call	$!__generic_himod
    293  1.1  mrg 	ret
    294  1.1  mrg 
    295  1.1  mrg mod_signed_num:
    296  1.1  mrg 	;; neg [sp+4]
    297  1.1  mrg 	movw	ax, sp
    298  1.1  mrg 	addw	ax, #4
    299  1.1  mrg 	NEG_AX
    300  1.1  mrg 	mov	d, #1
    301  1.1  mrg 	mov	a, [sp+7]
    302  1.1  mrg 	mov1	cy, a.7
    303  1.1  mrg 	bnc	$mod_unsigned_den
    304  1.1  mrg mod_signed_den:
    305  1.1  mrg 	;; neg [sp+6]
    306  1.1  mrg 	movw	ax, sp
    307  1.1  mrg 	addw	ax, #6
    308  1.1  mrg 	NEG_AX
    309  1.1  mrg mod_unsigned_den:
    310  1.1  mrg 	call	$!__generic_himod
    311  1.1  mrg 
    312  1.1  mrg 	mov	a, d
    313  1.1  mrg 	cmp0	a
    314  1.1  mrg 	bz	$mod_no_neg
    315  1.1  mrg 	movw	ax, #r8
    316  1.1  mrg 	NEG_AX
    317  1.1  mrg 	;;  Also restore numerator
    318  1.1  mrg 	movw 	ax, sp
    319  1.1  mrg 	addw	ax, #4
    320  1.1  mrg 	NEG_AX
    321  1.1  mrg mod_no_neg:
    322  1.1  mrg 	mov	a, e
    323  1.1  mrg 	cmp0	a
    324  1.1  mrg 	bz	$mod_skip_restore_den
    325  1.1  mrg 	movw	ax, sp
    326  1.1  mrg 	addw	ax, #6
    327  1.1  mrg 	NEG_AX
    328  1.1  mrg mod_skip_restore_den:
    329  1.1  mrg 	ret
    330  1.1  mrg END_FUNC ___modhi3
    331