Home | History | Annotate | Line # | Download | only in rl78
divmodsi.S revision 1.7
      1  1.1  mrg /* SImode 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 it
      8  1.1  mrg    under the terms of the GNU General Public License as published
      9  1.1  mrg    by the Free Software Foundation; either version 3, or (at your
     10  1.1  mrg    option) any later version.
     11  1.1  mrg 
     12  1.1  mrg    GCC is distributed in the hope that it will be useful, but WITHOUT
     13  1.1  mrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14  1.1  mrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15  1.1  mrg    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 ___divsi3
     31  1.3  mrg 	;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
     32  1.3  mrg 
     33  1.3  mrg 	;; Load and test for a negative denumerator.
     34  1.3  mrg 	movw	ax, [sp+8]
     35  1.3  mrg 	movw	de, ax
     36  1.3  mrg 	movw	ax, [sp+10]
     37  1.3  mrg 	mov1	cy, a.7
     38  1.3  mrg 	movw	hl, ax
     39  1.3  mrg 	bc	$__div_neg_den
     40  1.3  mrg 
     41  1.3  mrg 	;; Load and test for a negative numerator.
     42  1.3  mrg 	movw	ax, [sp+6]
     43  1.3  mrg 	mov1	cy, a.7
     44  1.3  mrg 	movw	bc, ax
     45  1.3  mrg 	movw	ax, [sp+4]
     46  1.3  mrg 	bc	$__div_neg_num
     47  1.3  mrg 
     48  1.3  mrg 	;; Neither are negative - we can use the unsigned divide instruction.
     49  1.3  mrg __div_no_convert:
     50  1.3  mrg 	push	psw
     51  1.3  mrg 	di
     52  1.3  mrg 	divwu
     53  1.3  mrg 	pop	psw
     54  1.3  mrg 
     55  1.3  mrg 	movw	r8, ax
     56  1.3  mrg 	movw	ax, bc
     57  1.3  mrg 	movw	r10, ax
     58  1.3  mrg 	ret
     59  1.3  mrg 
     60  1.3  mrg __div_neg_den:
     61  1.3  mrg 	;; Negate the denumerator (which is in HLDE)
     62  1.3  mrg 	clrw	ax
     63  1.3  mrg 	subw	ax, de
     64  1.3  mrg 	movw	de, ax
     65  1.3  mrg 	clrw	ax
     66  1.3  mrg 	sknc
     67  1.3  mrg 	decw	ax
     68  1.3  mrg 	subw	ax, hl
     69  1.3  mrg 	movw	hl, ax
     70  1.3  mrg 
     71  1.3  mrg 	;; Load and test for a negative numerator.
     72  1.3  mrg 	movw	ax, [sp+6]
     73  1.3  mrg 	mov1	cy, a.7
     74  1.3  mrg 	movw	bc, ax
     75  1.3  mrg 	movw	ax, [sp+4]
     76  1.3  mrg 	;; If it is not negative then we perform the division and then negate the result.
     77  1.3  mrg 	bnc	$__div_then_convert
     78  1.3  mrg 
     79  1.3  mrg 	;; Otherwise we negate the numerator and then go with a straightforward unsigned division.
     80  1.3  mrg 	;; The negation is complicated because AX, BC, DE and HL are already in use.
     81  1.3  mrg 	;;              ax: numL  bc: numH  r8:       r10:
     82  1.3  mrg 	xchw	ax, bc
     83  1.3  mrg 	;;              ax: numH  bc: numL  r8:       r10:
     84  1.3  mrg 	movw	r8, ax
     85  1.3  mrg 	;;              ax:       bc: numL  r8: numH  r10:
     86  1.3  mrg 	clrw	ax
     87  1.3  mrg 	;;              ax:    0  bc: numL  r8: numH  r10:
     88  1.3  mrg 	subw	ax, bc
     89  1.3  mrg 	;;              ax: -numL bc:       r8: numH  r10:
     90  1.3  mrg 	movw	r10, ax
     91  1.3  mrg 	;;              ax:       bc:       r8: numH  r10: -numL
     92  1.3  mrg 	movw	ax, r8
     93  1.3  mrg 	;;              ax: numH  bc:       r8:       r10: -numL
     94  1.3  mrg 	movw	bc, ax
     95  1.3  mrg 	;;              ax:       bc: numH  r8:       r10: -numL
     96  1.3  mrg 	clrw	ax
     97  1.3  mrg 	;;              ax:    0  bc: numH  r8:       r10: -numL
     98  1.3  mrg 	sknc
     99  1.3  mrg 	decw	ax
    100  1.3  mrg 	;;              ax:    -1 bc: numH  r8:       r10: -numL
    101  1.3  mrg 	subw	ax, bc
    102  1.3  mrg 	;;              ax: -numH bc:       r8:       r10: -numL
    103  1.3  mrg 	movw	bc, ax
    104  1.3  mrg 	;;              ax:       bc: -numH r8:       r10: -numL
    105  1.3  mrg 	movw	ax, r10
    106  1.3  mrg 	;;              ax: -numL bc: -numH r8:       r10:
    107  1.3  mrg 	br	$!__div_no_convert
    108  1.3  mrg 
    109  1.3  mrg __div_neg_num:
    110  1.3  mrg 	;; Negate the numerator (which is in BCAX)
    111  1.3  mrg 	;; We know that the denumerator is positive.
    112  1.3  mrg 	;; Note - we temporarily overwrite DE.  We know that we can safely load it again off the stack again.
    113  1.3  mrg 	movw	de, ax
    114  1.3  mrg 	clrw	ax
    115  1.3  mrg 	subw	ax, de
    116  1.3  mrg 	movw	de, ax
    117  1.3  mrg 	clrw	ax
    118  1.3  mrg 	sknc
    119  1.3  mrg 	decw	ax
    120  1.3  mrg 	subw	ax, bc
    121  1.3  mrg 	movw	bc, ax
    122  1.3  mrg 
    123  1.3  mrg 	movw	ax, [sp+8]
    124  1.3  mrg 	xchw	ax, de
    125  1.3  mrg 
    126  1.3  mrg __div_then_convert:
    127  1.3  mrg 	push	psw
    128  1.3  mrg 	di
    129  1.3  mrg 	divwu
    130  1.3  mrg 	pop	psw
    131  1.3  mrg 
    132  1.3  mrg 	;; Negate result (in BCAX) and transfer into r8,r10
    133  1.3  mrg 	movw	de, ax
    134  1.3  mrg 	clrw	ax
    135  1.3  mrg 	subw	ax, de
    136  1.3  mrg 	movw	r8, ax
    137  1.3  mrg 	clrw	ax
    138  1.3  mrg 	sknc
    139  1.3  mrg 	decw	ax
    140  1.3  mrg 	subw	ax, bc
    141  1.3  mrg 	movw	r10, ax
    142  1.3  mrg 	ret
    143  1.3  mrg 
    144  1.3  mrg END_FUNC ___divsi3
    145  1.3  mrg 
    146  1.3  mrg ;----------------------------------------------------------------------
    147  1.3  mrg 
    148  1.3  mrg START_FUNC ___udivsi3
    149  1.3  mrg 	;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
    150  1.3  mrg 	;; Used when compiling with -Os specified.
    151  1.3  mrg 
    152  1.3  mrg 	movw	ax, [sp+10]
    153  1.3  mrg 	movw	hl, ax
    154  1.3  mrg 	movw	ax, [sp+8]
    155  1.3  mrg 	movw	de, ax
    156  1.3  mrg 	movw	ax, [sp+6]
    157  1.3  mrg 	movw	bc, ax
    158  1.3  mrg 	movw    ax, [sp+4]
    159  1.3  mrg 	push	psw	; Save the current interrupt status
    160  1.3  mrg 	di		; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E
    161  1.3  mrg 	divwu   	; bcax = bcax / hlde
    162  1.3  mrg 	pop	psw	; Restore saved interrupt status
    163  1.3  mrg 	movw    r8, ax
    164  1.3  mrg 	movw	ax, bc
    165  1.3  mrg 	movw    r10, ax
    166  1.3  mrg 	ret
    167  1.3  mrg 
    168  1.3  mrg END_FUNC ___udivsi3
    169  1.3  mrg 
    170  1.3  mrg ;----------------------------------------------------------------------
    171  1.3  mrg 
    172  1.3  mrg START_FUNC ___modsi3
    173  1.3  mrg 	;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
    174  1.3  mrg 
    175  1.3  mrg 	;; Load and test for a negative denumerator.
    176  1.3  mrg 	movw	ax, [sp+8]
    177  1.3  mrg 	movw	de, ax
    178  1.3  mrg 	movw	ax, [sp+10]
    179  1.3  mrg 	mov1	cy, a.7
    180  1.3  mrg 	movw	hl, ax
    181  1.3  mrg 	bc	$__mod_neg_den
    182  1.3  mrg 
    183  1.3  mrg 	;; Load and test for a negative numerator.
    184  1.3  mrg 	movw	ax, [sp+6]
    185  1.3  mrg 	mov1	cy, a.7
    186  1.3  mrg 	movw	bc, ax
    187  1.3  mrg 	movw	ax, [sp+4]
    188  1.3  mrg 	bc	$__mod_neg_num
    189  1.3  mrg 
    190  1.3  mrg 	;; Neither are negative - we can use the unsigned divide instruction.
    191  1.3  mrg __mod_no_convert:
    192  1.3  mrg 	push	psw
    193  1.3  mrg 	di
    194  1.3  mrg 	divwu
    195  1.3  mrg 	pop	psw
    196  1.3  mrg 
    197  1.3  mrg 	movw	ax, de
    198  1.3  mrg 	movw	r8, ax
    199  1.3  mrg 	movw	ax, hl
    200  1.3  mrg 	movw	r10, ax
    201  1.3  mrg 	ret
    202  1.3  mrg 
    203  1.3  mrg __mod_neg_den:
    204  1.3  mrg 	;; Negate the denumerator (which is in HLDE)
    205  1.3  mrg 	clrw	ax
    206  1.3  mrg 	subw	ax, de
    207  1.3  mrg 	movw	de, ax
    208  1.3  mrg 	clrw	ax
    209  1.3  mrg 	sknc
    210  1.3  mrg 	decw	ax
    211  1.3  mrg 	subw	ax, hl
    212  1.3  mrg 	movw	hl, ax
    213  1.3  mrg 
    214  1.3  mrg 	;; Load and test for a negative numerator.
    215  1.3  mrg 	movw	ax, [sp+6]
    216  1.3  mrg 	mov1	cy, a.7
    217  1.3  mrg 	movw	bc, ax
    218  1.3  mrg 	movw	ax, [sp+4]
    219  1.3  mrg 	;; If it is not negative then we perform the modulo operation without conversion
    220  1.3  mrg 	bnc	$__mod_no_convert
    221  1.3  mrg 
    222  1.3  mrg 	;; Otherwise we negate the numerator and then go with a modulo followed by negation.
    223  1.3  mrg 	;; The negation is complicated because AX, BC, DE and HL are already in use.
    224  1.3  mrg 	xchw	ax, bc
    225  1.3  mrg 	movw	r8, ax
    226  1.3  mrg 	clrw	ax
    227  1.3  mrg 	subw	ax, bc
    228  1.3  mrg 	movw	r10, ax
    229  1.3  mrg 	movw	ax, r8
    230  1.3  mrg 	movw	bc, ax
    231  1.3  mrg 	clrw	ax
    232  1.3  mrg 	sknc
    233  1.3  mrg 	decw	ax
    234  1.3  mrg 	subw	ax, bc
    235  1.3  mrg 	movw	bc, ax
    236  1.3  mrg 	movw	ax, r10
    237  1.3  mrg 	br	$!__mod_then_convert
    238  1.3  mrg 
    239  1.3  mrg __mod_neg_num:
    240  1.3  mrg 	;; Negate the numerator (which is in BCAX)
    241  1.3  mrg 	;; We know that the denumerator is positive.
    242  1.3  mrg 	;; Note - we temporarily overwrite DE.  We know that we can safely load it again off the stack again.
    243  1.3  mrg 	movw	de, ax
    244  1.3  mrg 	clrw	ax
    245  1.3  mrg 	subw	ax, de
    246  1.3  mrg 	movw	de, ax
    247  1.3  mrg 	clrw	ax
    248  1.3  mrg 	sknc
    249  1.3  mrg 	decw	ax
    250  1.3  mrg 	subw	ax, bc
    251  1.3  mrg 	movw	bc, ax
    252  1.3  mrg 
    253  1.3  mrg 	movw	ax, [sp+8]
    254  1.3  mrg 	xchw	ax, de
    255  1.3  mrg 
    256  1.3  mrg __mod_then_convert:
    257  1.3  mrg 	push	psw
    258  1.3  mrg 	di
    259  1.3  mrg 	divwu
    260  1.3  mrg 	pop	psw
    261  1.3  mrg 
    262  1.3  mrg 	;; Negate result (in HLDE) and transfer into r8,r10
    263  1.3  mrg 	clrw	ax
    264  1.3  mrg 	subw	ax, de
    265  1.3  mrg 	movw	r8, ax
    266  1.3  mrg 	clrw	ax
    267  1.3  mrg 	sknc
    268  1.3  mrg 	decw	ax
    269  1.3  mrg 	subw	ax, hl
    270  1.3  mrg 	movw	r10, ax
    271  1.3  mrg 	ret
    272  1.3  mrg 
    273  1.3  mrg END_FUNC ___modsi3
    274  1.3  mrg 
    275  1.3  mrg ;----------------------------------------------------------------------
    276  1.3  mrg 
    277  1.3  mrg START_FUNC ___umodsi3
    278  1.3  mrg 	;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
    279  1.3  mrg 	;; Used when compiling with -Os specified.
    280  1.3  mrg 
    281  1.3  mrg 	movw	ax, [sp+10]
    282  1.3  mrg 	movw	hl, ax
    283  1.3  mrg 	movw	ax, [sp+8]
    284  1.3  mrg 	movw	de, ax
    285  1.3  mrg 	movw	ax, [sp+6]
    286  1.3  mrg 	movw	bc, ax
    287  1.3  mrg 	movw    ax, [sp+4]
    288  1.3  mrg 	push	psw	; Save the current interrupt status
    289  1.3  mrg 	di		; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E
    290  1.3  mrg 	divwu   	; hlde = bcax %% hlde
    291  1.3  mrg 	pop	psw	; Restore saved interrupt status
    292  1.3  mrg 	movw	ax, de
    293  1.3  mrg 	movw    r8, ax
    294  1.3  mrg 	movw	ax, hl
    295  1.3  mrg 	movw    r10, ax
    296  1.3  mrg 	ret
    297  1.3  mrg 
    298  1.3  mrg END_FUNC   ___umodsi3
    299  1.3  mrg 
    300  1.3  mrg ;----------------------------------------------------------------------
    301  1.3  mrg 
    302  1.3  mrg #elif defined __RL78_MUL_G13__
    303  1.3  mrg 
    304  1.3  mrg ;----------------------------------------------------------------------
    305  1.3  mrg 
    306  1.3  mrg 	;; Hardware registers.  Note - these values match the silicon, not the documentation.
    307  1.3  mrg 	MDAL = 0xffff0
    308  1.3  mrg 	MDAH = 0xffff2
    309  1.3  mrg 	MDBL = 0xffff6
    310  1.3  mrg 	MDBH = 0xffff4
    311  1.3  mrg 	MDCL = 0xf00e0
    312  1.3  mrg 	MDCH = 0xf00e2
    313  1.3  mrg 	MDUC = 0xf00e8
    314  1.3  mrg 
    315  1.3  mrg .macro _Negate low, high
    316  1.3  mrg 	movw	ax, \low
    317  1.3  mrg 	movw	bc, ax
    318  1.3  mrg 	clrw	ax
    319  1.3  mrg 	subw	ax, bc
    320  1.3  mrg 	movw	\low, ax
    321  1.3  mrg 	movw	ax, \high
    322  1.3  mrg 	movw	bc, ax
    323  1.3  mrg 	clrw	ax
    324  1.3  mrg 	sknc
    325  1.3  mrg 	decw	ax
    326  1.3  mrg 	subw	ax, bc
    327  1.3  mrg 	movw	\high, ax
    328  1.3  mrg .endm
    329  1.3  mrg 
    330  1.3  mrg ;----------------------------------------------------------------------
    331  1.3  mrg 
    332  1.3  mrg START_FUNC ___divsi3
    333  1.3  mrg 	;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
    334  1.3  mrg 
    335  1.3  mrg 	mov	a, #0xC0	; Set DIVMODE=1 and MACMODE=1
    336  1.3  mrg 	mov	!MDUC, a	; This preps the peripheral for division without interrupt generation
    337  1.3  mrg 
    338  1.3  mrg 	;; Load and test for a negative denumerator.
    339  1.3  mrg 	movw	ax, [sp+8]
    340  1.3  mrg 	movw	MDBL, ax
    341  1.3  mrg 	movw	ax, [sp+10]
    342  1.3  mrg 	mov1	cy, a.7
    343  1.3  mrg 	movw	MDBH, ax
    344  1.3  mrg 	bc	$__div_neg_den
    345  1.3  mrg 
    346  1.3  mrg 	;; Load and test for a negative numerator.
    347  1.3  mrg 	movw	ax, [sp+6]
    348  1.3  mrg 	mov1	cy, a.7
    349  1.3  mrg 	movw	MDAH, ax
    350  1.3  mrg 	movw	ax, [sp+4]
    351  1.3  mrg 	movw	MDAL, ax
    352  1.3  mrg 	bc	$__div_neg_num
    353  1.3  mrg 
    354  1.3  mrg 	;; Neither are negative - we can use the unsigned divide hardware.
    355  1.3  mrg __div_no_convert:
    356  1.3  mrg 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    357  1.3  mrg 	mov	!MDUC, a	; This starts the division op
    358  1.3  mrg 
    359  1.3  mrg 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    360  1.3  mrg 	bt	a.0, $1b
    361  1.3  mrg 
    362  1.3  mrg   	movw	ax, MDAL	; Read the result
    363  1.3  mrg 	movw	r8, ax
    364  1.3  mrg 	movw	ax, MDAH
    365  1.3  mrg 	movw	r10, ax
    366  1.3  mrg 	ret
    367  1.3  mrg 
    368  1.3  mrg __div_neg_den:
    369  1.3  mrg 	;; Negate the denumerator (which is in MDBL/MDBH)
    370  1.3  mrg 	_Negate MDBL MDBH
    371  1.3  mrg 
    372  1.3  mrg 	;; Load and test for a negative numerator.
    373  1.3  mrg 	movw	ax, [sp+6]
    374  1.3  mrg 	mov1	cy, a.7
    375  1.3  mrg 	movw	MDAH, ax
    376  1.3  mrg 	movw	ax, [sp+4]
    377  1.3  mrg 	movw	MDAL, ax
    378  1.3  mrg 	;; If it is not negative then we perform the division and then negate the result.
    379  1.3  mrg 	bnc	$__div_then_convert
    380  1.3  mrg 
    381  1.3  mrg 	;; Otherwise we negate the numerator and then go with a straightforward unsigned division.
    382  1.3  mrg 	_Negate MDAL MDAH
    383  1.3  mrg 	br	$!__div_no_convert
    384  1.3  mrg 
    385  1.3  mrg __div_neg_num:
    386  1.3  mrg 	;; Negate the numerator (which is in MDAL/MDAH)
    387  1.3  mrg 	;; We know that the denumerator is positive.
    388  1.3  mrg 	_Negate MDAL MDAH
    389  1.3  mrg 
    390  1.3  mrg __div_then_convert:
    391  1.3  mrg 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    392  1.3  mrg 	mov	!MDUC, a	; This starts the division op
    393  1.3  mrg 
    394  1.3  mrg 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    395  1.3  mrg 	bt	a.0, $1b
    396  1.3  mrg 
    397  1.3  mrg 	;; Negate result and transfer into r8,r10
    398  1.3  mrg 	_Negate MDAL MDAH    	; FIXME: This could be coded more efficiently.
    399  1.3  mrg 	movw	r10, ax
    400  1.3  mrg 	movw	ax, MDAL
    401  1.3  mrg 	movw	r8, ax
    402  1.3  mrg 
    403  1.3  mrg 	ret
    404  1.3  mrg 
    405  1.3  mrg END_FUNC ___divsi3
    406  1.3  mrg 
    407  1.3  mrg ;----------------------------------------------------------------------
    408  1.3  mrg 
    409  1.3  mrg START_FUNC ___modsi3
    410  1.3  mrg 	;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
    411  1.3  mrg 
    412  1.3  mrg 	mov	a, #0xC0	; Set DIVMODE=1 and MACMODE=1
    413  1.3  mrg 	mov	!MDUC, a	; This preps the peripheral for division without interrupt generation
    414  1.3  mrg 
    415  1.3  mrg 	;; Load and test for a negative denumerator.
    416  1.3  mrg 	movw	ax, [sp+8]
    417  1.3  mrg 	movw	MDBL, ax
    418  1.3  mrg 	movw	ax, [sp+10]
    419  1.3  mrg 	mov1	cy, a.7
    420  1.3  mrg 	movw	MDBH, ax
    421  1.3  mrg 	bc	$__mod_neg_den
    422  1.3  mrg 
    423  1.3  mrg 	;; Load and test for a negative numerator.
    424  1.3  mrg 	movw	ax, [sp+6]
    425  1.3  mrg 	mov1	cy, a.7
    426  1.3  mrg 	movw	MDAH, ax
    427  1.3  mrg 	movw	ax, [sp+4]
    428  1.3  mrg 	movw	MDAL, ax
    429  1.3  mrg 	bc	$__mod_neg_num
    430  1.3  mrg 
    431  1.3  mrg 	;; Neither are negative - we can use the unsigned divide hardware
    432  1.3  mrg __mod_no_convert:
    433  1.3  mrg 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    434  1.3  mrg 	mov	!MDUC, a	; This starts the division op
    435  1.3  mrg 
    436  1.3  mrg 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    437  1.3  mrg 	bt	a.0, $1b
    438  1.3  mrg 
    439  1.3  mrg   	movw	ax, !MDCL	; Read the remainder
    440  1.3  mrg 	movw	r8, ax
    441  1.3  mrg 	movw	ax, !MDCH
    442  1.3  mrg 	movw	r10, ax
    443  1.3  mrg 	ret
    444  1.3  mrg 
    445  1.3  mrg __mod_neg_den:
    446  1.3  mrg 	;; Negate the denumerator (which is in MDBL/MDBH)
    447  1.3  mrg 	_Negate MDBL MDBH
    448  1.3  mrg 
    449  1.3  mrg 	;; Load and test for a negative numerator.
    450  1.3  mrg 	movw	ax, [sp+6]
    451  1.3  mrg 	mov1	cy, a.7
    452  1.3  mrg 	movw	MDAH, ax
    453  1.3  mrg 	movw	ax, [sp+4]
    454  1.3  mrg 	movw	MDAL, ax
    455  1.3  mrg 	;; If it is not negative then we perform the modulo operation without conversion
    456  1.3  mrg 	bnc	$__mod_no_convert
    457  1.3  mrg 
    458  1.3  mrg 	;; Otherwise we negate the numerator and then go with a modulo followed by negation.
    459  1.3  mrg 	_Negate MDAL MDAH
    460  1.3  mrg 	br	$!__mod_then_convert
    461  1.3  mrg 
    462  1.3  mrg __mod_neg_num:
    463  1.3  mrg 	;; Negate the numerator (which is in MDAL/MDAH)
    464  1.3  mrg 	;; We know that the denumerator is positive.
    465  1.3  mrg 	_Negate MDAL MDAH
    466  1.3  mrg 
    467  1.3  mrg __mod_then_convert:
    468  1.3  mrg 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    469  1.3  mrg 	mov	!MDUC, a	; This starts the division op
    470  1.3  mrg 
    471  1.3  mrg 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    472  1.3  mrg 	bt	a.0, $1b
    473  1.3  mrg 
    474  1.3  mrg 	movw	ax, !MDCL
    475  1.3  mrg 	movw	bc, ax
    476  1.3  mrg 	clrw	ax
    477  1.3  mrg 	subw	ax, bc
    478  1.3  mrg 	movw	r8, ax
    479  1.3  mrg 	movw	ax, !MDCH
    480  1.3  mrg 	movw	bc, ax
    481  1.3  mrg 	clrw	ax
    482  1.3  mrg 	sknc
    483  1.3  mrg 	decw	ax
    484  1.3  mrg 	subw	ax, bc
    485  1.3  mrg 	movw	r10, ax
    486  1.3  mrg 	ret
    487  1.3  mrg 
    488  1.3  mrg END_FUNC ___modsi3
    489  1.3  mrg 
    490  1.3  mrg ;----------------------------------------------------------------------
    491  1.3  mrg 
    492  1.3  mrg START_FUNC ___udivsi3
    493  1.3  mrg 	;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
    494  1.3  mrg 	;; Used when compilng with -Os specified.
    495  1.3  mrg 
    496  1.3  mrg 	mov	a, #0xC0	; Set DIVMODE=1 and MACMODE=1
    497  1.3  mrg 	mov	!MDUC, a	; This preps the peripheral for division without interrupt generation
    498  1.3  mrg 
    499  1.3  mrg 	movw	ax, [sp+4]	; Load the divisor
    500  1.3  mrg 	movw	MDAL, ax
    501  1.3  mrg 	movw	ax, [sp+6]
    502  1.3  mrg 	movw	MDAH, ax
    503  1.3  mrg 	movw	ax, [sp+8]	; Load the dividend
    504  1.3  mrg 	movw	MDBL, ax
    505  1.3  mrg 	movw    ax, [sp+10]
    506  1.3  mrg 	movw	MDBH, ax
    507  1.3  mrg 
    508  1.3  mrg 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    509  1.3  mrg 	mov	!MDUC, a	; This starts the division op
    510  1.3  mrg 
    511  1.3  mrg 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    512  1.3  mrg 	bt	a.0, $1b
    513  1.3  mrg 
    514  1.3  mrg   	movw	ax, !MDAL	; Read the result
    515  1.3  mrg 	movw	r8, ax
    516  1.3  mrg 	movw	ax, !MDAH
    517  1.3  mrg 	movw	r10, ax
    518  1.3  mrg 	ret
    519  1.3  mrg 
    520  1.3  mrg END_FUNC   ___udivsi3
    521  1.3  mrg 
    522  1.3  mrg ;----------------------------------------------------------------------
    523  1.3  mrg 
    524  1.3  mrg START_FUNC ___umodsi3
    525  1.3  mrg 	;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
    526  1.3  mrg 	;; Used when compilng with -Os specified.
    527  1.3  mrg 	;; Note - hardware address match the silicon, not the documentation
    528  1.3  mrg 
    529  1.3  mrg 	mov	a, #0xC0	; Set DIVMODE=1 and MACMODE=1
    530  1.3  mrg 	mov	!MDUC, a	; This preps the peripheral for division without interrupt generation
    531  1.3  mrg 
    532  1.3  mrg 	movw	ax, [sp+4]	; Load the divisor
    533  1.3  mrg 	movw	MDAL, ax
    534  1.3  mrg 	movw	ax, [sp+6]
    535  1.3  mrg 	movw	MDAH, ax
    536  1.3  mrg 	movw	ax, [sp+8]	; Load the dividend
    537  1.3  mrg 	movw	MDBL, ax
    538  1.3  mrg 	movw    ax, [sp+10]
    539  1.3  mrg 	movw	MDBH, ax
    540  1.3  mrg 
    541  1.3  mrg 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    542  1.3  mrg 	mov	!MDUC, a	; This starts the division op
    543  1.3  mrg 
    544  1.3  mrg 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    545  1.3  mrg 	bt	a.0, $1b
    546  1.3  mrg 
    547  1.3  mrg   	movw	ax, !MDCL	; Read the remainder
    548  1.3  mrg 	movw	r8, ax
    549  1.3  mrg 	movw	ax, !MDCH
    550  1.3  mrg 	movw	r10, ax
    551  1.3  mrg 	ret
    552  1.3  mrg 
    553  1.3  mrg END_FUNC   ___umodsi3
    554  1.3  mrg 
    555  1.3  mrg ;----------------------------------------------------------------------
    556  1.3  mrg 
    557  1.3  mrg #elif defined __RL78_MUL_NONE__
    558  1.3  mrg 
    559  1.1  mrg .macro MAKE_GENERIC  which,need_result
    560  1.1  mrg 
    561  1.1  mrg 	.if \need_result
    562  1.1  mrg 	quot = r8
    563  1.1  mrg 	num = r12
    564  1.1  mrg 	den = r16
    565  1.1  mrg 	bit = r20
    566  1.1  mrg 	.else
    567  1.1  mrg 	num = r8
    568  1.1  mrg 	quot = r12
    569  1.1  mrg 	den = r16
    570  1.1  mrg 	bit = r20
    571  1.1  mrg 	.endif
    572  1.1  mrg 
    573  1.1  mrg 	quotH = quot+2
    574  1.1  mrg 	quotL = quot
    575  1.1  mrg 	quotB0 = quot
    576  1.1  mrg 	quotB1 = quot+1
    577  1.1  mrg 	quotB2 = quot+2
    578  1.1  mrg 	quotB3 = quot+3
    579  1.1  mrg 
    580  1.1  mrg 	numH = num+2
    581  1.1  mrg 	numL = num
    582  1.1  mrg 	numB0 = num
    583  1.1  mrg 	numB1 = num+1
    584  1.1  mrg 	numB2 = num+2
    585  1.1  mrg 	numB3 = num+3
    586  1.1  mrg 
    587  1.1  mrg #define	denH bc
    588  1.1  mrg 	denL = den
    589  1.1  mrg 	denB0 = den
    590  1.1  mrg 	denB1 = den+1
    591  1.1  mrg #define	denB2 c
    592  1.1  mrg #define	denB3 b
    593  1.1  mrg 
    594  1.1  mrg 	bitH = bit+2
    595  1.1  mrg 	bitL = bit
    596  1.1  mrg 	bitB0 = bit
    597  1.1  mrg 	bitB1 = bit+1
    598  1.1  mrg 	bitB2 = bit+2
    599  1.1  mrg 	bitB3 = bit+3
    600  1.1  mrg 
    601  1.3  mrg ;----------------------------------------------------------------------
    602  1.3  mrg 
    603  1.1  mrg START_FUNC __generic_sidivmod\which
    604  1.1  mrg 
    605  1.1  mrg num_lt_den\which:
    606  1.1  mrg 	.if \need_result
    607  1.1  mrg 	movw	r8, #0
    608  1.1  mrg 	movw	r10, #0
    609  1.1  mrg 	.else
    610  1.1  mrg 	movw	ax, [sp+8]
    611  1.1  mrg 	movw	r8, ax
    612  1.1  mrg 	movw	ax, [sp+10]
    613  1.1  mrg 	movw	r10, ax
    614  1.1  mrg 	.endif
    615  1.1  mrg 	ret
    616  1.1  mrg 
    617  1.1  mrg shift_den_bit16\which:
    618  1.1  mrg 	movw	ax, denL
    619  1.1  mrg 	movw	denH, ax
    620  1.1  mrg 	movw	denL, #0
    621  1.1  mrg 	.if \need_result
    622  1.1  mrg 	movw	ax, bitL
    623  1.1  mrg 	movw	bitH, ax
    624  1.1  mrg 	movw	bitL, #0
    625  1.1  mrg 	.else
    626  1.1  mrg 	mov	a, bit
    627  1.1  mrg 	add	a, #16
    628  1.1  mrg 	mov	bit, a
    629  1.1  mrg 	.endif
    630  1.1  mrg 	br	$shift_den_bit\which
    631  1.1  mrg 
    632  1.1  mrg 	;; These routines leave DE alone - the signed functions use DE
    633  1.1  mrg 	;; to store sign information that must remain intact
    634  1.1  mrg 
    635  1.1  mrg 	.if \need_result
    636  1.1  mrg 	.global __generic_sidiv
    637  1.1  mrg __generic_sidiv:
    638  1.1  mrg 
    639  1.1  mrg 	.else
    640  1.1  mrg 
    641  1.1  mrg 	.global __generic_simod
    642  1.1  mrg __generic_simod:
    643  1.1  mrg 
    644  1.1  mrg 	.endif
    645  1.1  mrg 
    646  1.1  mrg 	;; (quot,rem) = 8[sp] /% 12[sp]
    647  1.1  mrg 
    648  1.1  mrg 	movw	hl, sp
    649  1.1  mrg 	movw	ax, [hl+14] ; denH
    650  1.1  mrg 	cmpw	ax, [hl+10] ; numH
    651  1.1  mrg 	movw	ax, [hl+12] ; denL
    652  1.1  mrg 	sknz
    653  1.1  mrg 	cmpw	ax, [hl+8] ; numL
    654  1.1  mrg 	bh	$num_lt_den\which
    655  1.1  mrg 
    656  1.1  mrg #ifdef __RL78_G10__
    657  1.1  mrg 	movw	ax, denL
    658  1.1  mrg 	push	ax
    659  1.1  mrg 	movw	ax, bitL
    660  1.1  mrg 	push	ax
    661  1.1  mrg 	movw	ax, bitH
    662  1.1  mrg 	push	ax
    663  1.1  mrg #else
    664  1.1  mrg 	sel	rb2
    665  1.1  mrg 	push	ax		; denL
    666  1.1  mrg ;	push	bc		; denH
    667  1.1  mrg 	push	de		; bitL
    668  1.1  mrg 	push	hl		; bitH - stored in BC
    669  1.1  mrg 	sel	rb0
    670  1.1  mrg #endif
    671  1.1  mrg 
    672  1.1  mrg 	;; (quot,rem) = 16[sp] /% 20[sp]
    673  1.1  mrg 
    674  1.1  mrg 	;; copy numerator
    675  1.1  mrg 	movw	ax, [hl+8]
    676  1.1  mrg 	movw	numL, ax
    677  1.1  mrg 	movw	ax, [hl+10]
    678  1.1  mrg 	movw	numH, ax
    679  1.1  mrg 
    680  1.1  mrg 	;; copy denomonator
    681  1.1  mrg 	movw	ax, [hl+12]
    682  1.1  mrg 	movw	denL, ax
    683  1.1  mrg 	movw	ax, [hl+14]
    684  1.1  mrg 	movw	denH, ax
    685  1.1  mrg 
    686  1.1  mrg 	movw	ax, denL
    687  1.1  mrg 	or	a, denB2
    688  1.1  mrg 	or	a, denB3	; not x
    689  1.1  mrg 	cmpw	ax, #0
    690  1.1  mrg 	bnz	$den_not_zero\which
    691  1.3  mrg 	.if \need_result
    692  1.3  mrg 	movw	quotL, #0
    693  1.3  mrg 	movw	quotH, #0
    694  1.3  mrg 	.else
    695  1.1  mrg 	movw	numL, #0
    696  1.1  mrg 	movw	numH, #0
    697  1.3  mrg 	.endif
    698  1.3  mrg 	br	$!main_loop_done_himode\which
    699  1.1  mrg 
    700  1.1  mrg den_not_zero\which:
    701  1.1  mrg 	.if \need_result
    702  1.1  mrg 	;; zero out quot
    703  1.1  mrg 	movw	quotL, #0
    704  1.1  mrg 	movw	quotH, #0
    705  1.1  mrg 	.endif
    706  1.1  mrg 
    707  1.1  mrg 	;; initialize bit to 1
    708  1.1  mrg 	movw	bitL, #1
    709  1.1  mrg 	movw	bitH, #0
    710  1.1  mrg 
    711  1.1  mrg ; while (den < num && !(den & (1L << BITS_MINUS_1)))
    712  1.1  mrg 
    713  1.1  mrg 	.if 1
    714  1.1  mrg 	;; see if we can short-circuit a bunch of shifts
    715  1.1  mrg 	movw	ax, denH
    716  1.1  mrg 	cmpw	ax, #0
    717  1.1  mrg 	bnz	$shift_den_bit\which
    718  1.1  mrg 	movw	ax, denL
    719  1.1  mrg 	cmpw	ax, numH
    720  1.1  mrg 	bnh	$shift_den_bit16\which
    721  1.1  mrg 	.endif
    722  1.1  mrg 
    723  1.1  mrg shift_den_bit\which:
    724  1.1  mrg 	movw	ax, denH
    725  1.1  mrg 	mov1	cy,a.7
    726  1.1  mrg 	bc	$enter_main_loop\which
    727  1.1  mrg 	cmpw	ax, numH
    728  1.1  mrg 	movw	ax, denL	; we re-use this below
    729  1.1  mrg 	sknz
    730  1.1  mrg 	cmpw	ax, numL
    731  1.1  mrg 	bh	$enter_main_loop\which
    732  1.1  mrg 
    733  1.1  mrg 	;; den <<= 1
    734  1.1  mrg ;	movw	ax, denL	; already has it from the cmpw above
    735  1.1  mrg 	shlw	ax, 1
    736  1.1  mrg 	movw	denL, ax
    737  1.1  mrg ;	movw	ax, denH
    738  1.1  mrg 	rolwc	denH, 1
    739  1.1  mrg ;	movw	denH, ax
    740  1.1  mrg 
    741  1.1  mrg 	;; bit <<= 1
    742  1.1  mrg 	.if \need_result
    743  1.1  mrg 	movw	ax, bitL
    744  1.1  mrg 	shlw	ax, 1
    745  1.1  mrg 	movw	bitL, ax
    746  1.1  mrg 	movw	ax, bitH
    747  1.1  mrg 	rolwc	ax, 1
    748  1.1  mrg 	movw	bitH, ax
    749  1.1  mrg 	.else
    750  1.1  mrg 	;; if we don't need to compute the quotent, we don't need an
    751  1.1  mrg 	;; actual bit *mask*, we just need to keep track of which bit
    752  1.1  mrg 	inc	bitB0
    753  1.1  mrg 	.endif
    754  1.1  mrg 
    755  1.1  mrg 	br	$shift_den_bit\which
    756  1.1  mrg 
    757  1.1  mrg 	;; while (bit)
    758  1.1  mrg main_loop\which:
    759  1.1  mrg 
    760  1.1  mrg 	;; if (num >= den) (cmp den > num)
    761  1.1  mrg 	movw	ax, numH
    762  1.1  mrg 	cmpw	ax, denH
    763  1.1  mrg 	movw	ax, numL
    764  1.1  mrg 	sknz
    765  1.1  mrg 	cmpw	ax, denL
    766  1.1  mrg 	skz
    767  1.1  mrg 	bnh	$next_loop\which
    768  1.1  mrg 
    769  1.1  mrg 	;; num -= den
    770  1.1  mrg ;	movw	ax, numL	; already has it from the cmpw above
    771  1.1  mrg 	subw	ax, denL
    772  1.1  mrg 	movw	numL, ax
    773  1.1  mrg 	movw	ax, numH
    774  1.1  mrg 	sknc
    775  1.1  mrg 	decw	ax
    776  1.1  mrg 	subw	ax, denH
    777  1.1  mrg 	movw	numH, ax
    778  1.1  mrg 
    779  1.1  mrg 	.if \need_result
    780  1.1  mrg 	;; res |= bit
    781  1.1  mrg 	mov	a, quotB0
    782  1.1  mrg 	or	a, bitB0
    783  1.1  mrg 	mov	quotB0, a
    784  1.1  mrg 	mov	a, quotB1
    785  1.1  mrg 	or	a, bitB1
    786  1.1  mrg 	mov	quotB1, a
    787  1.1  mrg 	mov	a, quotB2
    788  1.1  mrg 	or	a, bitB2
    789  1.1  mrg 	mov	quotB2, a
    790  1.1  mrg 	mov	a, quotB3
    791  1.1  mrg 	or	a, bitB3
    792  1.1  mrg 	mov	quotB3, a
    793  1.1  mrg 	.endif
    794  1.1  mrg 
    795  1.1  mrg next_loop\which:
    796  1.1  mrg 
    797  1.1  mrg 	;; den >>= 1
    798  1.1  mrg 	movw	ax, denH
    799  1.1  mrg 	shrw	ax, 1
    800  1.1  mrg 	movw	denH, ax
    801  1.1  mrg 	mov	a, denB1
    802  1.1  mrg 	rorc	a, 1
    803  1.1  mrg 	mov	denB1, a
    804  1.1  mrg 	mov	a, denB0
    805  1.1  mrg 	rorc	a, 1
    806  1.1  mrg 	mov	denB0, a
    807  1.1  mrg 
    808  1.1  mrg 	;; bit >>= 1
    809  1.1  mrg 	.if \need_result
    810  1.1  mrg 	movw	ax, bitH
    811  1.1  mrg 	shrw	ax, 1
    812  1.1  mrg 	movw	bitH, ax
    813  1.1  mrg 	mov	a, bitB1
    814  1.1  mrg 	rorc	a, 1
    815  1.1  mrg 	mov	bitB1, a
    816  1.1  mrg 	mov	a, bitB0
    817  1.1  mrg 	rorc	a, 1
    818  1.1  mrg 	mov	bitB0, a
    819  1.1  mrg 	.else
    820  1.1  mrg 	dec	bitB0
    821  1.1  mrg 	.endif
    822  1.1  mrg 
    823  1.1  mrg enter_main_loop\which:
    824  1.1  mrg 	.if \need_result
    825  1.1  mrg 	movw	ax, bitH
    826  1.1  mrg 	cmpw	ax, #0
    827  1.1  mrg 	bnz	$main_loop\which
    828  1.1  mrg 	.else
    829  1.1  mrg 	cmp	bitB0, #15
    830  1.1  mrg 	bh	$main_loop\which
    831  1.1  mrg 	.endif
    832  1.1  mrg 	;; bit is HImode now; check others
    833  1.1  mrg 	movw	ax, numH	; numerator
    834  1.1  mrg 	cmpw	ax, #0
    835  1.1  mrg 	bnz	$bit_high_set\which
    836  1.1  mrg 	movw	ax, denH	; denominator
    837  1.1  mrg 	cmpw	ax, #0
    838  1.1  mrg 	bz	$switch_to_himode\which
    839  1.1  mrg bit_high_set\which:
    840  1.1  mrg 	.if \need_result
    841  1.1  mrg 	movw	ax, bitL
    842  1.1  mrg 	cmpw	ax, #0
    843  1.1  mrg 	.else
    844  1.1  mrg 	cmp0	bitB0
    845  1.1  mrg 	.endif
    846  1.1  mrg 	bnz	$main_loop\which
    847  1.1  mrg 
    848  1.1  mrg switch_to_himode\which:
    849  1.1  mrg 	.if \need_result
    850  1.1  mrg 	movw	ax, bitL
    851  1.1  mrg 	cmpw	ax, #0
    852  1.1  mrg 	.else
    853  1.1  mrg 	cmp0	bitB0
    854  1.1  mrg 	.endif
    855  1.1  mrg 	bz	$main_loop_done_himode\which
    856  1.1  mrg 
    857  1.1  mrg 	;; From here on in, r22, r14, and r18 are all zero
    858  1.1  mrg 	;; while (bit)
    859  1.1  mrg main_loop_himode\which:
    860  1.1  mrg 
    861  1.1  mrg 	;; if (num >= den) (cmp den > num)
    862  1.1  mrg 	movw	ax, denL
    863  1.1  mrg 	cmpw	ax, numL
    864  1.1  mrg 	bh	$next_loop_himode\which
    865  1.1  mrg 
    866  1.1  mrg 	;; num -= den
    867  1.1  mrg 	movw	ax, numL
    868  1.1  mrg 	subw	ax, denL
    869  1.1  mrg 	movw	numL, ax
    870  1.1  mrg 	movw	ax, numH
    871  1.1  mrg 	sknc
    872  1.1  mrg 	decw	ax
    873  1.1  mrg 	subw	ax, denH
    874  1.1  mrg 	movw	numH, ax
    875  1.1  mrg 
    876  1.1  mrg 	.if \need_result
    877  1.1  mrg 	;; res |= bit
    878  1.1  mrg 	mov	a, quotB0
    879  1.1  mrg 	or	a, bitB0
    880  1.1  mrg 	mov	quotB0, a
    881  1.1  mrg 	mov	a, quotB1
    882  1.1  mrg 	or	a, bitB1
    883  1.1  mrg 	mov	quotB1, a
    884  1.1  mrg 	.endif
    885  1.1  mrg 
    886  1.1  mrg next_loop_himode\which:
    887  1.1  mrg 
    888  1.1  mrg 	;; den >>= 1
    889  1.1  mrg 	movw	ax, denL
    890  1.1  mrg 	shrw	ax, 1
    891  1.1  mrg 	movw	denL, ax
    892  1.1  mrg 
    893  1.1  mrg 	.if \need_result
    894  1.1  mrg 	;; bit >>= 1
    895  1.1  mrg 	movw	ax, bitL
    896  1.1  mrg 	shrw	ax, 1
    897  1.1  mrg 	movw	bitL, ax
    898  1.1  mrg 	.else
    899  1.1  mrg 	dec	bitB0
    900  1.1  mrg 	.endif
    901  1.1  mrg 
    902  1.1  mrg 	.if \need_result
    903  1.1  mrg 	movw	ax, bitL
    904  1.1  mrg 	cmpw	ax, #0
    905  1.1  mrg 	.else
    906  1.1  mrg 	cmp0	bitB0
    907  1.1  mrg 	.endif
    908  1.1  mrg 	bnz	$main_loop_himode\which
    909  1.1  mrg 
    910  1.1  mrg main_loop_done_himode\which:
    911  1.1  mrg #ifdef __RL78_G10__
    912  1.1  mrg 	pop	ax
    913  1.1  mrg 	movw	bitH, ax
    914  1.1  mrg 	pop	ax
    915  1.1  mrg 	movw	bitL, ax
    916  1.1  mrg 	pop	ax
    917  1.1  mrg 	movw	denL, ax
    918  1.1  mrg #else
    919  1.1  mrg 	sel	rb2
    920  1.1  mrg 	pop	hl		; bitH - stored in BC
    921  1.1  mrg 	pop	de		; bitL
    922  1.1  mrg ;	pop	bc		; denH
    923  1.1  mrg 	pop	ax		; denL
    924  1.1  mrg 	sel	rb0
    925  1.1  mrg #endif
    926  1.1  mrg 
    927  1.1  mrg 	ret
    928  1.1  mrg END_FUNC __generic_sidivmod\which
    929  1.1  mrg .endm
    930  1.1  mrg 
    931  1.1  mrg ;----------------------------------------------------------------------
    932  1.1  mrg 
    933  1.1  mrg 	MAKE_GENERIC _d 1
    934  1.1  mrg 	MAKE_GENERIC _m 0
    935  1.1  mrg 
    936  1.1  mrg ;----------------------------------------------------------------------
    937  1.1  mrg 
    938  1.1  mrg START_FUNC ___udivsi3
    939  1.1  mrg 	;; r8 = 4[sp] / 8[sp]
    940  1.1  mrg 	call	$!__generic_sidiv
    941  1.1  mrg 	ret
    942  1.1  mrg END_FUNC ___udivsi3
    943  1.1  mrg 
    944  1.1  mrg 
    945  1.1  mrg START_FUNC ___umodsi3
    946  1.1  mrg 	;; r8 = 4[sp] % 8[sp]
    947  1.1  mrg 	call	$!__generic_simod
    948  1.1  mrg 	ret
    949  1.1  mrg END_FUNC ___umodsi3
    950  1.1  mrg 
    951  1.1  mrg ;----------------------------------------------------------------------
    952  1.1  mrg 
    953  1.1  mrg .macro NEG_AX
    954  1.1  mrg 	movw	hl, ax
    955  1.1  mrg 	movw	ax, #0
    956  1.1  mrg 	subw	ax, [hl]
    957  1.1  mrg 	movw	[hl], ax
    958  1.1  mrg 	movw	ax, #0
    959  1.1  mrg 	sknc
    960  1.1  mrg 	decw	ax
    961  1.1  mrg 	subw	ax, [hl+2]
    962  1.1  mrg 	movw	[hl+2], ax
    963  1.1  mrg .endm
    964  1.1  mrg 
    965  1.1  mrg ;----------------------------------------------------------------------
    966  1.1  mrg 
    967  1.1  mrg START_FUNC ___divsi3
    968  1.1  mrg 	;; r8 = 4[sp] / 8[sp]
    969  1.1  mrg 	movw	de, #0
    970  1.1  mrg 	mov	a, [sp+7]
    971  1.1  mrg 	mov1	cy, a.7
    972  1.1  mrg 	bc	$div_signed_num
    973  1.1  mrg 	mov	a, [sp+11]
    974  1.1  mrg 	mov1	cy, a.7
    975  1.1  mrg 	bc	$div_signed_den
    976  1.1  mrg 	call	$!__generic_sidiv
    977  1.1  mrg 	ret
    978  1.1  mrg 
    979  1.1  mrg div_signed_num:
    980  1.1  mrg 	;; neg [sp+4]
    981  1.1  mrg 	movw	ax, sp
    982  1.1  mrg 	addw	ax, #4
    983  1.1  mrg 	NEG_AX
    984  1.1  mrg 	mov	d, #1
    985  1.1  mrg 	mov	a, [sp+11]
    986  1.1  mrg 	mov1	cy, a.7
    987  1.1  mrg 	bnc	$div_unsigned_den
    988  1.1  mrg div_signed_den:
    989  1.1  mrg 	;; neg [sp+8]
    990  1.1  mrg 	movw	ax, sp
    991  1.1  mrg 	addw	ax, #8
    992  1.1  mrg 	NEG_AX
    993  1.1  mrg 	mov	e, #1
    994  1.1  mrg div_unsigned_den:
    995  1.1  mrg 	call	$!__generic_sidiv
    996  1.1  mrg 
    997  1.1  mrg 	mov	a, d
    998  1.1  mrg 	cmp0	a
    999  1.1  mrg 	bz	$div_skip_restore_num
   1000  1.1  mrg 	;;  We have to restore the numerator [sp+4]
   1001  1.1  mrg 	movw	ax, sp
   1002  1.1  mrg 	addw	ax, #4
   1003  1.1  mrg 	NEG_AX
   1004  1.1  mrg 	mov	a, d
   1005  1.1  mrg div_skip_restore_num:
   1006  1.1  mrg 	xor	a, e
   1007  1.1  mrg 	bz	$div_no_neg
   1008  1.1  mrg 	movw	ax, #r8
   1009  1.1  mrg 	NEG_AX
   1010  1.1  mrg div_no_neg:
   1011  1.1  mrg 	mov	a, e
   1012  1.1  mrg 	cmp0	a
   1013  1.1  mrg 	bz	$div_skip_restore_den
   1014  1.1  mrg 	;;  We have to restore the denominator [sp+8]
   1015  1.1  mrg 	movw	ax, sp
   1016  1.1  mrg 	addw	ax, #8
   1017  1.1  mrg 	NEG_AX
   1018  1.1  mrg div_skip_restore_den:
   1019  1.1  mrg 	ret
   1020  1.1  mrg END_FUNC ___divsi3
   1021  1.1  mrg 
   1022  1.1  mrg 
   1023  1.1  mrg START_FUNC ___modsi3
   1024  1.1  mrg 	;; r8 = 4[sp] % 8[sp]
   1025  1.1  mrg 	movw	de, #0
   1026  1.1  mrg 	mov	a, [sp+7]
   1027  1.1  mrg 	mov1	cy, a.7
   1028  1.1  mrg 	bc	$mod_signed_num
   1029  1.1  mrg 	mov	a, [sp+11]
   1030  1.1  mrg 	mov1	cy, a.7
   1031  1.1  mrg 	bc	$mod_signed_den
   1032  1.1  mrg 	call	$!__generic_simod
   1033  1.1  mrg 	ret
   1034  1.1  mrg 
   1035  1.1  mrg mod_signed_num:
   1036  1.1  mrg 	;; neg [sp+4]
   1037  1.1  mrg 	movw	ax, sp
   1038  1.1  mrg 	addw	ax, #4
   1039  1.1  mrg 	NEG_AX
   1040  1.1  mrg 	mov	d, #1
   1041  1.1  mrg 	mov	a, [sp+11]
   1042  1.1  mrg 	mov1	cy, a.7
   1043  1.1  mrg 	bnc	$mod_unsigned_den
   1044  1.1  mrg mod_signed_den:
   1045  1.1  mrg 	;; neg [sp+8]
   1046  1.1  mrg 	movw	ax, sp
   1047  1.1  mrg 	addw	ax, #8
   1048  1.1  mrg 	NEG_AX
   1049  1.1  mrg 	mov	e, #1
   1050  1.1  mrg mod_unsigned_den:
   1051  1.1  mrg 	call	$!__generic_simod
   1052  1.1  mrg 
   1053  1.1  mrg 	mov	a, d
   1054  1.1  mrg 	cmp0	a
   1055  1.1  mrg 	bz	$mod_no_neg
   1056  1.1  mrg 	movw	ax, #r8
   1057  1.1  mrg 	NEG_AX
   1058  1.1  mrg 	;;  We have to restore [sp+4] as well.
   1059  1.1  mrg 	movw	ax, sp
   1060  1.1  mrg 	addw	ax, #4
   1061  1.1  mrg 	NEG_AX
   1062  1.1  mrg mod_no_neg:
   1063  1.1  mrg  .if 1
   1064  1.1  mrg 	mov	a, e
   1065  1.1  mrg 	cmp0	a
   1066  1.1  mrg 	bz	$mod_skip_restore_den
   1067  1.1  mrg 	movw	ax, sp
   1068  1.1  mrg 	addw	ax, #8
   1069  1.1  mrg 	NEG_AX
   1070  1.1  mrg mod_skip_restore_den:
   1071  1.1  mrg  .endif
   1072  1.1  mrg 	ret
   1073  1.1  mrg END_FUNC ___modsi3
   1074  1.3  mrg 
   1075  1.3  mrg ;----------------------------------------------------------------------
   1076  1.3  mrg 
   1077  1.3  mrg #else
   1078  1.3  mrg 
   1079  1.3  mrg #error "Unknown RL78 hardware multiply/divide support"
   1080  1.3  mrg 
   1081  1.3  mrg #endif
   1082