Home | History | Annotate | Line # | Download | only in rl78
divmodsi.S revision 1.1.1.1.4.1
      1          1.1       mrg /* SImode div/mod functions for the GCC support library for the Renesas RL78 processors.
      2  1.1.1.1.4.1  christos    Copyright (C) 2012-2016 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.1.1.1.4.1  christos #if defined __RL78_MUL_G14__
     29  1.1.1.1.4.1  christos 
     30  1.1.1.1.4.1  christos START_FUNC ___divsi3
     31  1.1.1.1.4.1  christos 	;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
     32  1.1.1.1.4.1  christos 
     33  1.1.1.1.4.1  christos 	;; Load and test for a negative denumerator.
     34  1.1.1.1.4.1  christos 	movw	ax, [sp+8]
     35  1.1.1.1.4.1  christos 	movw	de, ax
     36  1.1.1.1.4.1  christos 	movw	ax, [sp+10]
     37  1.1.1.1.4.1  christos 	mov1	cy, a.7
     38  1.1.1.1.4.1  christos 	movw	hl, ax
     39  1.1.1.1.4.1  christos 	bc	$__div_neg_den
     40  1.1.1.1.4.1  christos 
     41  1.1.1.1.4.1  christos 	;; Load and test for a negative numerator.
     42  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
     43  1.1.1.1.4.1  christos 	mov1	cy, a.7
     44  1.1.1.1.4.1  christos 	movw	bc, ax
     45  1.1.1.1.4.1  christos 	movw	ax, [sp+4]
     46  1.1.1.1.4.1  christos 	bc	$__div_neg_num
     47  1.1.1.1.4.1  christos 
     48  1.1.1.1.4.1  christos 	;; Neither are negative - we can use the unsigned divide instruction.
     49  1.1.1.1.4.1  christos __div_no_convert:
     50  1.1.1.1.4.1  christos 	push	psw
     51  1.1.1.1.4.1  christos 	di
     52  1.1.1.1.4.1  christos 	divwu
     53  1.1.1.1.4.1  christos 	pop	psw
     54  1.1.1.1.4.1  christos 
     55  1.1.1.1.4.1  christos 	movw	r8, ax
     56  1.1.1.1.4.1  christos 	movw	ax, bc
     57  1.1.1.1.4.1  christos 	movw	r10, ax
     58  1.1.1.1.4.1  christos 	ret
     59  1.1.1.1.4.1  christos 
     60  1.1.1.1.4.1  christos __div_neg_den:
     61  1.1.1.1.4.1  christos 	;; Negate the denumerator (which is in HLDE)
     62  1.1.1.1.4.1  christos 	clrw	ax
     63  1.1.1.1.4.1  christos 	subw	ax, de
     64  1.1.1.1.4.1  christos 	movw	de, ax
     65  1.1.1.1.4.1  christos 	clrw	ax
     66  1.1.1.1.4.1  christos 	sknc
     67  1.1.1.1.4.1  christos 	decw	ax
     68  1.1.1.1.4.1  christos 	subw	ax, hl
     69  1.1.1.1.4.1  christos 	movw	hl, ax
     70  1.1.1.1.4.1  christos 
     71  1.1.1.1.4.1  christos 	;; Load and test for a negative numerator.
     72  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
     73  1.1.1.1.4.1  christos 	mov1	cy, a.7
     74  1.1.1.1.4.1  christos 	movw	bc, ax
     75  1.1.1.1.4.1  christos 	movw	ax, [sp+4]
     76  1.1.1.1.4.1  christos 	;; If it is not negative then we perform the division and then negate the result.
     77  1.1.1.1.4.1  christos 	bnc	$__div_then_convert
     78  1.1.1.1.4.1  christos 
     79  1.1.1.1.4.1  christos 	;; Otherwise we negate the numerator and then go with a straightforward unsigned division.
     80  1.1.1.1.4.1  christos 	;; The negation is complicated because AX, BC, DE and HL are already in use.
     81  1.1.1.1.4.1  christos 	;;              ax: numL  bc: numH  r8:       r10:
     82  1.1.1.1.4.1  christos 	xchw	ax, bc
     83  1.1.1.1.4.1  christos 	;;              ax: numH  bc: numL  r8:       r10:
     84  1.1.1.1.4.1  christos 	movw	r8, ax
     85  1.1.1.1.4.1  christos 	;;              ax:       bc: numL  r8: numH  r10:
     86  1.1.1.1.4.1  christos 	clrw	ax
     87  1.1.1.1.4.1  christos 	;;              ax:    0  bc: numL  r8: numH  r10:
     88  1.1.1.1.4.1  christos 	subw	ax, bc
     89  1.1.1.1.4.1  christos 	;;              ax: -numL bc:       r8: numH  r10:
     90  1.1.1.1.4.1  christos 	movw	r10, ax
     91  1.1.1.1.4.1  christos 	;;              ax:       bc:       r8: numH  r10: -numL
     92  1.1.1.1.4.1  christos 	movw	ax, r8
     93  1.1.1.1.4.1  christos 	;;              ax: numH  bc:       r8:       r10: -numL
     94  1.1.1.1.4.1  christos 	movw	bc, ax
     95  1.1.1.1.4.1  christos 	;;              ax:       bc: numH  r8:       r10: -numL
     96  1.1.1.1.4.1  christos 	clrw	ax
     97  1.1.1.1.4.1  christos 	;;              ax:    0  bc: numH  r8:       r10: -numL
     98  1.1.1.1.4.1  christos 	sknc
     99  1.1.1.1.4.1  christos 	decw	ax
    100  1.1.1.1.4.1  christos 	;;              ax:    -1 bc: numH  r8:       r10: -numL
    101  1.1.1.1.4.1  christos 	subw	ax, bc
    102  1.1.1.1.4.1  christos 	;;              ax: -numH bc:       r8:       r10: -numL
    103  1.1.1.1.4.1  christos 	movw	bc, ax
    104  1.1.1.1.4.1  christos 	;;              ax:       bc: -numH r8:       r10: -numL
    105  1.1.1.1.4.1  christos 	movw	ax, r10
    106  1.1.1.1.4.1  christos 	;;              ax: -numL bc: -numH r8:       r10:
    107  1.1.1.1.4.1  christos 	br	$!__div_no_convert
    108  1.1.1.1.4.1  christos 
    109  1.1.1.1.4.1  christos __div_neg_num:
    110  1.1.1.1.4.1  christos 	;; Negate the numerator (which is in BCAX)
    111  1.1.1.1.4.1  christos 	;; We know that the denumerator is positive.
    112  1.1.1.1.4.1  christos 	;; Note - we temporarily overwrite DE.  We know that we can safely load it again off the stack again.
    113  1.1.1.1.4.1  christos 	movw	de, ax
    114  1.1.1.1.4.1  christos 	clrw	ax
    115  1.1.1.1.4.1  christos 	subw	ax, de
    116  1.1.1.1.4.1  christos 	movw	de, ax
    117  1.1.1.1.4.1  christos 	clrw	ax
    118  1.1.1.1.4.1  christos 	sknc
    119  1.1.1.1.4.1  christos 	decw	ax
    120  1.1.1.1.4.1  christos 	subw	ax, bc
    121  1.1.1.1.4.1  christos 	movw	bc, ax
    122  1.1.1.1.4.1  christos 
    123  1.1.1.1.4.1  christos 	movw	ax, [sp+8]
    124  1.1.1.1.4.1  christos 	xchw	ax, de
    125  1.1.1.1.4.1  christos 
    126  1.1.1.1.4.1  christos __div_then_convert:
    127  1.1.1.1.4.1  christos 	push	psw
    128  1.1.1.1.4.1  christos 	di
    129  1.1.1.1.4.1  christos 	divwu
    130  1.1.1.1.4.1  christos 	pop	psw
    131  1.1.1.1.4.1  christos 
    132  1.1.1.1.4.1  christos 	;; Negate result (in BCAX) and transfer into r8,r10
    133  1.1.1.1.4.1  christos 	movw	de, ax
    134  1.1.1.1.4.1  christos 	clrw	ax
    135  1.1.1.1.4.1  christos 	subw	ax, de
    136  1.1.1.1.4.1  christos 	movw	r8, ax
    137  1.1.1.1.4.1  christos 	clrw	ax
    138  1.1.1.1.4.1  christos 	sknc
    139  1.1.1.1.4.1  christos 	decw	ax
    140  1.1.1.1.4.1  christos 	subw	ax, bc
    141  1.1.1.1.4.1  christos 	movw	r10, ax
    142  1.1.1.1.4.1  christos 	ret
    143  1.1.1.1.4.1  christos 
    144  1.1.1.1.4.1  christos END_FUNC ___divsi3
    145  1.1.1.1.4.1  christos 
    146  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    147  1.1.1.1.4.1  christos 
    148  1.1.1.1.4.1  christos START_FUNC ___udivsi3
    149  1.1.1.1.4.1  christos 	;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
    150  1.1.1.1.4.1  christos 	;; Used when compiling with -Os specified.
    151  1.1.1.1.4.1  christos 
    152  1.1.1.1.4.1  christos 	movw	ax, [sp+10]
    153  1.1.1.1.4.1  christos 	movw	hl, ax
    154  1.1.1.1.4.1  christos 	movw	ax, [sp+8]
    155  1.1.1.1.4.1  christos 	movw	de, ax
    156  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    157  1.1.1.1.4.1  christos 	movw	bc, ax
    158  1.1.1.1.4.1  christos 	movw    ax, [sp+4]
    159  1.1.1.1.4.1  christos 	push	psw	; Save the current interrupt status
    160  1.1.1.1.4.1  christos 	di		; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E
    161  1.1.1.1.4.1  christos 	divwu   	; bcax = bcax / hlde
    162  1.1.1.1.4.1  christos 	pop	psw	; Restore saved interrupt status
    163  1.1.1.1.4.1  christos 	movw    r8, ax
    164  1.1.1.1.4.1  christos 	movw	ax, bc
    165  1.1.1.1.4.1  christos 	movw    r10, ax
    166  1.1.1.1.4.1  christos 	ret
    167  1.1.1.1.4.1  christos 
    168  1.1.1.1.4.1  christos END_FUNC ___udivsi3
    169  1.1.1.1.4.1  christos 
    170  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    171  1.1.1.1.4.1  christos 
    172  1.1.1.1.4.1  christos START_FUNC ___modsi3
    173  1.1.1.1.4.1  christos 	;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
    174  1.1.1.1.4.1  christos 
    175  1.1.1.1.4.1  christos 	;; Load and test for a negative denumerator.
    176  1.1.1.1.4.1  christos 	movw	ax, [sp+8]
    177  1.1.1.1.4.1  christos 	movw	de, ax
    178  1.1.1.1.4.1  christos 	movw	ax, [sp+10]
    179  1.1.1.1.4.1  christos 	mov1	cy, a.7
    180  1.1.1.1.4.1  christos 	movw	hl, ax
    181  1.1.1.1.4.1  christos 	bc	$__mod_neg_den
    182  1.1.1.1.4.1  christos 
    183  1.1.1.1.4.1  christos 	;; Load and test for a negative numerator.
    184  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    185  1.1.1.1.4.1  christos 	mov1	cy, a.7
    186  1.1.1.1.4.1  christos 	movw	bc, ax
    187  1.1.1.1.4.1  christos 	movw	ax, [sp+4]
    188  1.1.1.1.4.1  christos 	bc	$__mod_neg_num
    189  1.1.1.1.4.1  christos 
    190  1.1.1.1.4.1  christos 	;; Neither are negative - we can use the unsigned divide instruction.
    191  1.1.1.1.4.1  christos __mod_no_convert:
    192  1.1.1.1.4.1  christos 	push	psw
    193  1.1.1.1.4.1  christos 	di
    194  1.1.1.1.4.1  christos 	divwu
    195  1.1.1.1.4.1  christos 	pop	psw
    196  1.1.1.1.4.1  christos 
    197  1.1.1.1.4.1  christos 	movw	ax, de
    198  1.1.1.1.4.1  christos 	movw	r8, ax
    199  1.1.1.1.4.1  christos 	movw	ax, hl
    200  1.1.1.1.4.1  christos 	movw	r10, ax
    201  1.1.1.1.4.1  christos 	ret
    202  1.1.1.1.4.1  christos 
    203  1.1.1.1.4.1  christos __mod_neg_den:
    204  1.1.1.1.4.1  christos 	;; Negate the denumerator (which is in HLDE)
    205  1.1.1.1.4.1  christos 	clrw	ax
    206  1.1.1.1.4.1  christos 	subw	ax, de
    207  1.1.1.1.4.1  christos 	movw	de, ax
    208  1.1.1.1.4.1  christos 	clrw	ax
    209  1.1.1.1.4.1  christos 	sknc
    210  1.1.1.1.4.1  christos 	decw	ax
    211  1.1.1.1.4.1  christos 	subw	ax, hl
    212  1.1.1.1.4.1  christos 	movw	hl, ax
    213  1.1.1.1.4.1  christos 
    214  1.1.1.1.4.1  christos 	;; Load and test for a negative numerator.
    215  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    216  1.1.1.1.4.1  christos 	mov1	cy, a.7
    217  1.1.1.1.4.1  christos 	movw	bc, ax
    218  1.1.1.1.4.1  christos 	movw	ax, [sp+4]
    219  1.1.1.1.4.1  christos 	;; If it is not negative then we perform the modulo operation without conversion
    220  1.1.1.1.4.1  christos 	bnc	$__mod_no_convert
    221  1.1.1.1.4.1  christos 
    222  1.1.1.1.4.1  christos 	;; Otherwise we negate the numerator and then go with a modulo followed by negation.
    223  1.1.1.1.4.1  christos 	;; The negation is complicated because AX, BC, DE and HL are already in use.
    224  1.1.1.1.4.1  christos 	xchw	ax, bc
    225  1.1.1.1.4.1  christos 	movw	r8, ax
    226  1.1.1.1.4.1  christos 	clrw	ax
    227  1.1.1.1.4.1  christos 	subw	ax, bc
    228  1.1.1.1.4.1  christos 	movw	r10, ax
    229  1.1.1.1.4.1  christos 	movw	ax, r8
    230  1.1.1.1.4.1  christos 	movw	bc, ax
    231  1.1.1.1.4.1  christos 	clrw	ax
    232  1.1.1.1.4.1  christos 	sknc
    233  1.1.1.1.4.1  christos 	decw	ax
    234  1.1.1.1.4.1  christos 	subw	ax, bc
    235  1.1.1.1.4.1  christos 	movw	bc, ax
    236  1.1.1.1.4.1  christos 	movw	ax, r10
    237  1.1.1.1.4.1  christos 	br	$!__mod_then_convert
    238  1.1.1.1.4.1  christos 
    239  1.1.1.1.4.1  christos __mod_neg_num:
    240  1.1.1.1.4.1  christos 	;; Negate the numerator (which is in BCAX)
    241  1.1.1.1.4.1  christos 	;; We know that the denumerator is positive.
    242  1.1.1.1.4.1  christos 	;; Note - we temporarily overwrite DE.  We know that we can safely load it again off the stack again.
    243  1.1.1.1.4.1  christos 	movw	de, ax
    244  1.1.1.1.4.1  christos 	clrw	ax
    245  1.1.1.1.4.1  christos 	subw	ax, de
    246  1.1.1.1.4.1  christos 	movw	de, ax
    247  1.1.1.1.4.1  christos 	clrw	ax
    248  1.1.1.1.4.1  christos 	sknc
    249  1.1.1.1.4.1  christos 	decw	ax
    250  1.1.1.1.4.1  christos 	subw	ax, bc
    251  1.1.1.1.4.1  christos 	movw	bc, ax
    252  1.1.1.1.4.1  christos 
    253  1.1.1.1.4.1  christos 	movw	ax, [sp+8]
    254  1.1.1.1.4.1  christos 	xchw	ax, de
    255  1.1.1.1.4.1  christos 
    256  1.1.1.1.4.1  christos __mod_then_convert:
    257  1.1.1.1.4.1  christos 	push	psw
    258  1.1.1.1.4.1  christos 	di
    259  1.1.1.1.4.1  christos 	divwu
    260  1.1.1.1.4.1  christos 	pop	psw
    261  1.1.1.1.4.1  christos 
    262  1.1.1.1.4.1  christos 	;; Negate result (in HLDE) and transfer into r8,r10
    263  1.1.1.1.4.1  christos 	clrw	ax
    264  1.1.1.1.4.1  christos 	subw	ax, de
    265  1.1.1.1.4.1  christos 	movw	r8, ax
    266  1.1.1.1.4.1  christos 	clrw	ax
    267  1.1.1.1.4.1  christos 	sknc
    268  1.1.1.1.4.1  christos 	decw	ax
    269  1.1.1.1.4.1  christos 	subw	ax, hl
    270  1.1.1.1.4.1  christos 	movw	r10, ax
    271  1.1.1.1.4.1  christos 	ret
    272  1.1.1.1.4.1  christos 
    273  1.1.1.1.4.1  christos END_FUNC ___modsi3
    274  1.1.1.1.4.1  christos 
    275  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    276  1.1.1.1.4.1  christos 
    277  1.1.1.1.4.1  christos START_FUNC ___umodsi3
    278  1.1.1.1.4.1  christos 	;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
    279  1.1.1.1.4.1  christos 	;; Used when compiling with -Os specified.
    280  1.1.1.1.4.1  christos 
    281  1.1.1.1.4.1  christos 	movw	ax, [sp+10]
    282  1.1.1.1.4.1  christos 	movw	hl, ax
    283  1.1.1.1.4.1  christos 	movw	ax, [sp+8]
    284  1.1.1.1.4.1  christos 	movw	de, ax
    285  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    286  1.1.1.1.4.1  christos 	movw	bc, ax
    287  1.1.1.1.4.1  christos 	movw    ax, [sp+4]
    288  1.1.1.1.4.1  christos 	push	psw	; Save the current interrupt status
    289  1.1.1.1.4.1  christos 	di		; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E
    290  1.1.1.1.4.1  christos 	divwu   	; hlde = bcax %% hlde
    291  1.1.1.1.4.1  christos 	pop	psw	; Restore saved interrupt status
    292  1.1.1.1.4.1  christos 	movw	ax, de
    293  1.1.1.1.4.1  christos 	movw    r8, ax
    294  1.1.1.1.4.1  christos 	movw	ax, hl
    295  1.1.1.1.4.1  christos 	movw    r10, ax
    296  1.1.1.1.4.1  christos 	ret
    297  1.1.1.1.4.1  christos 
    298  1.1.1.1.4.1  christos END_FUNC   ___umodsi3
    299  1.1.1.1.4.1  christos 
    300  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    301  1.1.1.1.4.1  christos 
    302  1.1.1.1.4.1  christos #elif defined __RL78_MUL_G13__
    303  1.1.1.1.4.1  christos 
    304  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    305  1.1.1.1.4.1  christos 
    306  1.1.1.1.4.1  christos 	;; Hardware registers.  Note - these values match the silicon, not the documentation.
    307  1.1.1.1.4.1  christos 	MDAL = 0xffff0
    308  1.1.1.1.4.1  christos 	MDAH = 0xffff2
    309  1.1.1.1.4.1  christos 	MDBL = 0xffff6
    310  1.1.1.1.4.1  christos 	MDBH = 0xffff4
    311  1.1.1.1.4.1  christos 	MDCL = 0xf00e0
    312  1.1.1.1.4.1  christos 	MDCH = 0xf00e2
    313  1.1.1.1.4.1  christos 	MDUC = 0xf00e8
    314  1.1.1.1.4.1  christos 
    315  1.1.1.1.4.1  christos .macro _Negate low, high
    316  1.1.1.1.4.1  christos 	movw	ax, \low
    317  1.1.1.1.4.1  christos 	movw	bc, ax
    318  1.1.1.1.4.1  christos 	clrw	ax
    319  1.1.1.1.4.1  christos 	subw	ax, bc
    320  1.1.1.1.4.1  christos 	movw	\low, ax
    321  1.1.1.1.4.1  christos 	movw	ax, \high
    322  1.1.1.1.4.1  christos 	movw	bc, ax
    323  1.1.1.1.4.1  christos 	clrw	ax
    324  1.1.1.1.4.1  christos 	sknc
    325  1.1.1.1.4.1  christos 	decw	ax
    326  1.1.1.1.4.1  christos 	subw	ax, bc
    327  1.1.1.1.4.1  christos 	movw	\high, ax
    328  1.1.1.1.4.1  christos .endm
    329  1.1.1.1.4.1  christos 
    330  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    331  1.1.1.1.4.1  christos 
    332  1.1.1.1.4.1  christos START_FUNC ___divsi3
    333  1.1.1.1.4.1  christos 	;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
    334  1.1.1.1.4.1  christos 
    335  1.1.1.1.4.1  christos 	mov	a, #0xC0	; Set DIVMODE=1 and MACMODE=1
    336  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This preps the peripheral for division without interrupt generation
    337  1.1.1.1.4.1  christos 
    338  1.1.1.1.4.1  christos 	;; Load and test for a negative denumerator.
    339  1.1.1.1.4.1  christos 	movw	ax, [sp+8]
    340  1.1.1.1.4.1  christos 	movw	MDBL, ax
    341  1.1.1.1.4.1  christos 	movw	ax, [sp+10]
    342  1.1.1.1.4.1  christos 	mov1	cy, a.7
    343  1.1.1.1.4.1  christos 	movw	MDBH, ax
    344  1.1.1.1.4.1  christos 	bc	$__div_neg_den
    345  1.1.1.1.4.1  christos 
    346  1.1.1.1.4.1  christos 	;; Load and test for a negative numerator.
    347  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    348  1.1.1.1.4.1  christos 	mov1	cy, a.7
    349  1.1.1.1.4.1  christos 	movw	MDAH, ax
    350  1.1.1.1.4.1  christos 	movw	ax, [sp+4]
    351  1.1.1.1.4.1  christos 	movw	MDAL, ax
    352  1.1.1.1.4.1  christos 	bc	$__div_neg_num
    353  1.1.1.1.4.1  christos 
    354  1.1.1.1.4.1  christos 	;; Neither are negative - we can use the unsigned divide hardware.
    355  1.1.1.1.4.1  christos __div_no_convert:
    356  1.1.1.1.4.1  christos 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    357  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This starts the division op
    358  1.1.1.1.4.1  christos 
    359  1.1.1.1.4.1  christos 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    360  1.1.1.1.4.1  christos 	bt	a.0, $1b
    361  1.1.1.1.4.1  christos 
    362  1.1.1.1.4.1  christos   	movw	ax, MDAL	; Read the result
    363  1.1.1.1.4.1  christos 	movw	r8, ax
    364  1.1.1.1.4.1  christos 	movw	ax, MDAH
    365  1.1.1.1.4.1  christos 	movw	r10, ax
    366  1.1.1.1.4.1  christos 	ret
    367  1.1.1.1.4.1  christos 
    368  1.1.1.1.4.1  christos __div_neg_den:
    369  1.1.1.1.4.1  christos 	;; Negate the denumerator (which is in MDBL/MDBH)
    370  1.1.1.1.4.1  christos 	_Negate MDBL MDBH
    371  1.1.1.1.4.1  christos 
    372  1.1.1.1.4.1  christos 	;; Load and test for a negative numerator.
    373  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    374  1.1.1.1.4.1  christos 	mov1	cy, a.7
    375  1.1.1.1.4.1  christos 	movw	MDAH, ax
    376  1.1.1.1.4.1  christos 	movw	ax, [sp+4]
    377  1.1.1.1.4.1  christos 	movw	MDAL, ax
    378  1.1.1.1.4.1  christos 	;; If it is not negative then we perform the division and then negate the result.
    379  1.1.1.1.4.1  christos 	bnc	$__div_then_convert
    380  1.1.1.1.4.1  christos 
    381  1.1.1.1.4.1  christos 	;; Otherwise we negate the numerator and then go with a straightforward unsigned division.
    382  1.1.1.1.4.1  christos 	_Negate MDAL MDAH
    383  1.1.1.1.4.1  christos 	br	$!__div_no_convert
    384  1.1.1.1.4.1  christos 
    385  1.1.1.1.4.1  christos __div_neg_num:
    386  1.1.1.1.4.1  christos 	;; Negate the numerator (which is in MDAL/MDAH)
    387  1.1.1.1.4.1  christos 	;; We know that the denumerator is positive.
    388  1.1.1.1.4.1  christos 	_Negate MDAL MDAH
    389  1.1.1.1.4.1  christos 
    390  1.1.1.1.4.1  christos __div_then_convert:
    391  1.1.1.1.4.1  christos 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    392  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This starts the division op
    393  1.1.1.1.4.1  christos 
    394  1.1.1.1.4.1  christos 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    395  1.1.1.1.4.1  christos 	bt	a.0, $1b
    396  1.1.1.1.4.1  christos 
    397  1.1.1.1.4.1  christos 	;; Negate result and transfer into r8,r10
    398  1.1.1.1.4.1  christos 	_Negate MDAL MDAH    	; FIXME: This could be coded more efficiently.
    399  1.1.1.1.4.1  christos 	movw	r10, ax
    400  1.1.1.1.4.1  christos 	movw	ax, MDAL
    401  1.1.1.1.4.1  christos 	movw	r8, ax
    402  1.1.1.1.4.1  christos 
    403  1.1.1.1.4.1  christos 	ret
    404  1.1.1.1.4.1  christos 
    405  1.1.1.1.4.1  christos END_FUNC ___divsi3
    406  1.1.1.1.4.1  christos 
    407  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    408  1.1.1.1.4.1  christos 
    409  1.1.1.1.4.1  christos START_FUNC ___modsi3
    410  1.1.1.1.4.1  christos 	;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
    411  1.1.1.1.4.1  christos 
    412  1.1.1.1.4.1  christos 	mov	a, #0xC0	; Set DIVMODE=1 and MACMODE=1
    413  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This preps the peripheral for division without interrupt generation
    414  1.1.1.1.4.1  christos 
    415  1.1.1.1.4.1  christos 	;; Load and test for a negative denumerator.
    416  1.1.1.1.4.1  christos 	movw	ax, [sp+8]
    417  1.1.1.1.4.1  christos 	movw	MDBL, ax
    418  1.1.1.1.4.1  christos 	movw	ax, [sp+10]
    419  1.1.1.1.4.1  christos 	mov1	cy, a.7
    420  1.1.1.1.4.1  christos 	movw	MDBH, ax
    421  1.1.1.1.4.1  christos 	bc	$__mod_neg_den
    422  1.1.1.1.4.1  christos 
    423  1.1.1.1.4.1  christos 	;; Load and test for a negative numerator.
    424  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    425  1.1.1.1.4.1  christos 	mov1	cy, a.7
    426  1.1.1.1.4.1  christos 	movw	MDAH, ax
    427  1.1.1.1.4.1  christos 	movw	ax, [sp+4]
    428  1.1.1.1.4.1  christos 	movw	MDAL, ax
    429  1.1.1.1.4.1  christos 	bc	$__mod_neg_num
    430  1.1.1.1.4.1  christos 
    431  1.1.1.1.4.1  christos 	;; Neither are negative - we can use the unsigned divide hardware
    432  1.1.1.1.4.1  christos __mod_no_convert:
    433  1.1.1.1.4.1  christos 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    434  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This starts the division op
    435  1.1.1.1.4.1  christos 
    436  1.1.1.1.4.1  christos 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    437  1.1.1.1.4.1  christos 	bt	a.0, $1b
    438  1.1.1.1.4.1  christos 
    439  1.1.1.1.4.1  christos   	movw	ax, !MDCL	; Read the remainder
    440  1.1.1.1.4.1  christos 	movw	r8, ax
    441  1.1.1.1.4.1  christos 	movw	ax, !MDCH
    442  1.1.1.1.4.1  christos 	movw	r10, ax
    443  1.1.1.1.4.1  christos 	ret
    444  1.1.1.1.4.1  christos 
    445  1.1.1.1.4.1  christos __mod_neg_den:
    446  1.1.1.1.4.1  christos 	;; Negate the denumerator (which is in MDBL/MDBH)
    447  1.1.1.1.4.1  christos 	_Negate MDBL MDBH
    448  1.1.1.1.4.1  christos 
    449  1.1.1.1.4.1  christos 	;; Load and test for a negative numerator.
    450  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    451  1.1.1.1.4.1  christos 	mov1	cy, a.7
    452  1.1.1.1.4.1  christos 	movw	MDAH, ax
    453  1.1.1.1.4.1  christos 	movw	ax, [sp+4]
    454  1.1.1.1.4.1  christos 	movw	MDAL, ax
    455  1.1.1.1.4.1  christos 	;; If it is not negative then we perform the modulo operation without conversion
    456  1.1.1.1.4.1  christos 	bnc	$__mod_no_convert
    457  1.1.1.1.4.1  christos 
    458  1.1.1.1.4.1  christos 	;; Otherwise we negate the numerator and then go with a modulo followed by negation.
    459  1.1.1.1.4.1  christos 	_Negate MDAL MDAH
    460  1.1.1.1.4.1  christos 	br	$!__mod_then_convert
    461  1.1.1.1.4.1  christos 
    462  1.1.1.1.4.1  christos __mod_neg_num:
    463  1.1.1.1.4.1  christos 	;; Negate the numerator (which is in MDAL/MDAH)
    464  1.1.1.1.4.1  christos 	;; We know that the denumerator is positive.
    465  1.1.1.1.4.1  christos 	_Negate MDAL MDAH
    466  1.1.1.1.4.1  christos 
    467  1.1.1.1.4.1  christos __mod_then_convert:
    468  1.1.1.1.4.1  christos 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    469  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This starts the division op
    470  1.1.1.1.4.1  christos 
    471  1.1.1.1.4.1  christos 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    472  1.1.1.1.4.1  christos 	bt	a.0, $1b
    473  1.1.1.1.4.1  christos 
    474  1.1.1.1.4.1  christos 	movw	ax, !MDCL
    475  1.1.1.1.4.1  christos 	movw	bc, ax
    476  1.1.1.1.4.1  christos 	clrw	ax
    477  1.1.1.1.4.1  christos 	subw	ax, bc
    478  1.1.1.1.4.1  christos 	movw	r8, ax
    479  1.1.1.1.4.1  christos 	movw	ax, !MDCH
    480  1.1.1.1.4.1  christos 	movw	bc, ax
    481  1.1.1.1.4.1  christos 	clrw	ax
    482  1.1.1.1.4.1  christos 	sknc
    483  1.1.1.1.4.1  christos 	decw	ax
    484  1.1.1.1.4.1  christos 	subw	ax, bc
    485  1.1.1.1.4.1  christos 	movw	r10, ax
    486  1.1.1.1.4.1  christos 	ret
    487  1.1.1.1.4.1  christos 
    488  1.1.1.1.4.1  christos END_FUNC ___modsi3
    489  1.1.1.1.4.1  christos 
    490  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    491  1.1.1.1.4.1  christos 
    492  1.1.1.1.4.1  christos START_FUNC ___udivsi3
    493  1.1.1.1.4.1  christos 	;; r8,r10 = 4[sp],6[sp] / 8[sp],10[sp]
    494  1.1.1.1.4.1  christos 	;; Used when compilng with -Os specified.
    495  1.1.1.1.4.1  christos 
    496  1.1.1.1.4.1  christos 	mov	a, #0xC0	; Set DIVMODE=1 and MACMODE=1
    497  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This preps the peripheral for division without interrupt generation
    498  1.1.1.1.4.1  christos 
    499  1.1.1.1.4.1  christos 	movw	ax, [sp+4]	; Load the divisor
    500  1.1.1.1.4.1  christos 	movw	MDAL, ax
    501  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    502  1.1.1.1.4.1  christos 	movw	MDAH, ax
    503  1.1.1.1.4.1  christos 	movw	ax, [sp+8]	; Load the dividend
    504  1.1.1.1.4.1  christos 	movw	MDBL, ax
    505  1.1.1.1.4.1  christos 	movw    ax, [sp+10]
    506  1.1.1.1.4.1  christos 	movw	MDBH, ax
    507  1.1.1.1.4.1  christos 
    508  1.1.1.1.4.1  christos 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    509  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This starts the division op
    510  1.1.1.1.4.1  christos 
    511  1.1.1.1.4.1  christos 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    512  1.1.1.1.4.1  christos 	bt	a.0, $1b
    513  1.1.1.1.4.1  christos 
    514  1.1.1.1.4.1  christos   	movw	ax, !MDAL	; Read the result
    515  1.1.1.1.4.1  christos 	movw	r8, ax
    516  1.1.1.1.4.1  christos 	movw	ax, !MDAH
    517  1.1.1.1.4.1  christos 	movw	r10, ax
    518  1.1.1.1.4.1  christos 	ret
    519  1.1.1.1.4.1  christos 
    520  1.1.1.1.4.1  christos END_FUNC   ___udivsi3
    521  1.1.1.1.4.1  christos 
    522  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    523  1.1.1.1.4.1  christos 
    524  1.1.1.1.4.1  christos START_FUNC ___umodsi3
    525  1.1.1.1.4.1  christos 	;; r8,r10 = 4[sp],6[sp] % 8[sp],10[sp]
    526  1.1.1.1.4.1  christos 	;; Used when compilng with -Os specified.
    527  1.1.1.1.4.1  christos 	;; Note - hardware address match the silicon, not the documentation
    528  1.1.1.1.4.1  christos 
    529  1.1.1.1.4.1  christos 	mov	a, #0xC0	; Set DIVMODE=1 and MACMODE=1
    530  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This preps the peripheral for division without interrupt generation
    531  1.1.1.1.4.1  christos 
    532  1.1.1.1.4.1  christos 	movw	ax, [sp+4]	; Load the divisor
    533  1.1.1.1.4.1  christos 	movw	MDAL, ax
    534  1.1.1.1.4.1  christos 	movw	ax, [sp+6]
    535  1.1.1.1.4.1  christos 	movw	MDAH, ax
    536  1.1.1.1.4.1  christos 	movw	ax, [sp+8]	; Load the dividend
    537  1.1.1.1.4.1  christos 	movw	MDBL, ax
    538  1.1.1.1.4.1  christos 	movw    ax, [sp+10]
    539  1.1.1.1.4.1  christos 	movw	MDBH, ax
    540  1.1.1.1.4.1  christos 
    541  1.1.1.1.4.1  christos 	mov	a, #0xC1	; Set the DIVST bit in MDUC
    542  1.1.1.1.4.1  christos 	mov	!MDUC, a	; This starts the division op
    543  1.1.1.1.4.1  christos 
    544  1.1.1.1.4.1  christos 1:	mov	a, !MDUC	; Wait 16 clocks or until DIVST is clear
    545  1.1.1.1.4.1  christos 	bt	a.0, $1b
    546  1.1.1.1.4.1  christos 
    547  1.1.1.1.4.1  christos   	movw	ax, !MDCL	; Read the remainder
    548  1.1.1.1.4.1  christos 	movw	r8, ax
    549  1.1.1.1.4.1  christos 	movw	ax, !MDCH
    550  1.1.1.1.4.1  christos 	movw	r10, ax
    551  1.1.1.1.4.1  christos 	ret
    552  1.1.1.1.4.1  christos 
    553  1.1.1.1.4.1  christos END_FUNC   ___umodsi3
    554  1.1.1.1.4.1  christos 
    555  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
    556  1.1.1.1.4.1  christos 
    557  1.1.1.1.4.1  christos #elif defined __RL78_MUL_NONE__
    558  1.1.1.1.4.1  christos 
    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.1.1.1.4.1  christos ;----------------------------------------------------------------------
    602  1.1.1.1.4.1  christos 
    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.1.1.1.4.1  christos 	.if \need_result
    692  1.1.1.1.4.1  christos 	movw	quotL, #0
    693  1.1.1.1.4.1  christos 	movw	quotH, #0
    694  1.1.1.1.4.1  christos 	.else
    695          1.1       mrg 	movw	numL, #0
    696          1.1       mrg 	movw	numH, #0
    697  1.1.1.1.4.1  christos 	.endif
    698  1.1.1.1.4.1  christos 	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.1.1.1.4.1  christos 
   1075  1.1.1.1.4.1  christos ;----------------------------------------------------------------------
   1076  1.1.1.1.4.1  christos 
   1077  1.1.1.1.4.1  christos #else
   1078  1.1.1.1.4.1  christos 
   1079  1.1.1.1.4.1  christos #error "Unknown RL78 hardware multiply/divide support"
   1080  1.1.1.1.4.1  christos 
   1081  1.1.1.1.4.1  christos #endif
   1082