struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / device / lib / r800 / divunsigned.s
blob677d144376913050125b4fce0bf9593356cd1730
1 ;--------------------------------------------------------------------------
2 ; divunsigned.s
4 ; Copyright (C) 2000-2021, Michael Hope, Philipp Klaus Krause, Marco Bodrato
6 ; This library is free software; you can redistribute it and/or modify it
7 ; under the terms of the GNU General Public License as published by the
8 ; Free Software Foundation; either version 2, or (at your option) any
9 ; later version.
11 ; This library is distributed in the hope that it will be useful,
12 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ; GNU General Public License for more details.
16 ; You should have received a copy of the GNU General Public License
17 ; along with this library; see the file COPYING. If not, write to the
18 ; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19 ; MA 02110-1301, USA.
21 ; As a special exception, if you link this library with other files,
22 ; some of which are compiled with SDCC, to produce an executable,
23 ; this library does not by itself cause the resulting executable to
24 ; be covered by the GNU General Public License. This exception does
25 ; not however invalidate any other reasons why the executable file
26 ; might be covered by the GNU General Public License.
27 ;--------------------------------------------------------------------------
29 ;; Originally from GBDK by Pascal Felber.
31 .area _CODE
33 .globl __divuint
34 .globl __divuchar
37 __divuchar:
38 ld e, l
39 ld l, a
41 ;; Fall through
42 __divu8::
43 ld h,#0x00
44 ld d,h
45 ; Fall through to __divu16
47 ;; unsigned 16-bit division
49 ;; Entry conditions
50 ;; HL = dividend
51 ;; DE = divisor
53 ;; Exit conditions
54 ;; DE = quotient
55 ;; HL = remainder
56 ;; carry = 0
57 ;; If divisor is 0, quotient is set to "infinity", i.e HL = 0xFFFF.
59 ;; Register used: AF,B,DE,HL
60 __divuint:
61 __divu16::
62 ;; Two algorithms: one assumes divisor <2^7, the second
63 ;; assumes divisor >=2^7; choose the applicable one.
64 ld a,e
65 and a,#0x80
66 or a,d
67 jr NZ,.morethan7bits
68 ;; Both algorithms "rotate" 24 bits (H,L,A) but roles change.
70 ;; unsigned 16/7-bit division
71 .atmost7bits:
72 ld b,#16 ; bits in dividend and possible quotient
73 ;; Carry cleared by AND/OR, this "0" bit will pass trough HL.[*]
74 adc hl,hl
75 .dvloop7:
76 ;; HL holds both dividend and quotient. While we shift a bit from
77 ;; MSB of dividend, we shift next bit of quotient in from carry.
78 ;; A holds remainder.
79 rla
81 ;; If remainder is >= divisor, next bit of quotient is 1. We try
82 ;; to compute the difference.
83 sub a,e
84 jr NC,.nodrop7 ; Jump if remainder is >= dividend
85 add a,e ; Otherwise, restore remainder
86 ;; The add above sets the carry, because sbc a,e did set it.
87 .nodrop7:
88 ccf ; Complement borrow so 1 indicates a
89 ; successful subtraction (this is the
90 ; next bit of quotient)
91 adc hl,hl
92 djnz .dvloop7
93 ;; Carry now contains the same value it contained before
94 ;; entering .dvloop7[*]: "0" = valid result.
95 ld e,a ; DE = remainder, HL = quotient
96 ex de, hl
97 ret
99 .morethan7bits:
100 ld b,#9 ; at most 9 bits in quotient.
101 ld a,l ; precompute the first 7 shifts, by
102 ld l,h ; doing 8
103 ld h,#0
104 rr l ; undoing 1
105 .dvloop:
106 ;; Shift next bit of quotient into bit 0 of dividend
107 ;; Shift next MSB of dividend into LSB of remainder
108 ;; A holds both dividend and quotient. While we shift a bit from
109 ;; MSB of dividend, we shift next bit of quotient in from carry
110 ;; HL holds remainder
111 adc hl,hl ; HL < 2^(7+9), no carry, ever.
113 ;; If remainder is >= divisor, next bit of quotient is 1. We try
114 ;; to compute the difference.
115 sbc hl,de
116 jr NC,.nodrop ; Jump if remainder is >= dividend
117 add hl,de ; Otherwise, restore remainder
118 ;; The add above sets the carry, because sbc hl,de did set it.
119 .nodrop:
120 ccf ; Complement borrow so 1 indicates a
121 ; successful subtraction (this is the
122 ; next bit of quotient)
124 djnz .dvloop
125 ;; Take care of the ninth quotient bit! after the loop B=0.
126 rl b ; BA = quotient
127 ;; Carry now contains "0" = valid result.
128 ld d,b
129 ld e,a ; DE = quotient, HL = remainder