divunsigned.s (4989B)
1;-------------------------------------------------------------------------- 2; divunsigned.s 3; 4; Copyright (C) 2000-2021, Michael Hope, Philipp Klaus Krause, Marco Bodrato 5; 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. 10; 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. 15; 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. 20; 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;-------------------------------------------------------------------------- 28 29 ;; Originally from GBDK by Pascal Felber. 30 31.area _CODE 32 33.globl __divuint 34.globl __divuchar 35 36 37__divuchar: 38 ld e, l 39 ld l, a 40 41 ;; Fall through 42__divu8:: 43 ld h,#0x00 44 ld d,h 45 ; Fall through to __divu16 46 47 ;; unsigned 16-bit division 48 ;; 49 ;; Entry conditions 50 ;; HL = dividend 51 ;; DE = divisor 52 ;; 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. 58 ;; 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. 69 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 80 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 substraction (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 98 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. 112 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 substraction (this is the 122 ; next bit of quotient) 123 rla 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 130 ret 131