Blame | Last modification | View Log | Download
;--------------------------------------------------------------------------; divunsigned.s;; Copyright (C) 2000-2012, Michael Hope, Philipp Klaus Krause, Marco Bodrato;; This library is free software; you can redistribute it and/or modify it; under the terms of the GNU General Public License as published by the; Free Software Foundation; either version 2, or (at your option) any; later version.;; This library is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this library; see the file COPYING. If not, write to the; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,; MA 02110-1301, USA.;; As a special exception, if you link this library with other files,; some of which are compiled with SDCC, to produce an executable,; this library does not by itself cause the resulting executable to; be covered by the GNU General Public License. This exception does; not however invalidate any other reasons why the executable file; might be covered by the GNU General Public License.;--------------------------------------------------------------------------;; Originally from GBDK by Pascal Felber..area _CODE.globl __divuint.globl __divuchar__divuint:pop afpop hlpop depush depush hlpush afjr __divu16__divuchar:ld hl,#2+1add hl,spld e,(hl)dec hlld l,(hl);; Fall through__divu8::ld h,#0x00ld d,h; Fall through to __divu16;; unsigned 16-bit division;;;; Entry conditions;; HL = dividend;; DE = divisor;;;; Exit conditions;; HL = quotient;; DE = remainder;; carry = 0;; If divisor is 0, quotient is set to "infinity", i.e HL = 0xFFFF.;;;; Register used: AF,B,DE,HL__divu16::;; Two algorithms: one assumes divisor <2^7, the second;; assumes divisor >=2^7; choose the applicable one.ld a,eand a,#0x80or a,djr NZ,.morethan7bits;; Both algorithms "rotate" 24 bits (H,L,A) but roles change.;; unsigned 16/7-bit division.atmost7bits:ld b,#16 ; bits in dividend and possible quotient;; Carry cleared by AND/OR, this "0" bit will pass trough HL.[*]adc hl,hl.dvloop7:;; HL holds both dividend and quotient. While we shift a bit from;; MSB of dividend, we shift next bit of quotient in from carry.;; A holds remainder.rla;; If remainder is >= divisor, next bit of quotient is 1. We try;; to compute the difference.sub a,ejr NC,.nodrop7 ; Jump if remainder is >= dividendadd a,e ; Otherwise, restore remainder;; The add above sets the carry, because sbc a,e did set it..nodrop7:ccf ; Complement borrow so 1 indicates a; successful substraction (this is the; next bit of quotient)adc hl,hldjnz .dvloop7;; Carry now contains the same value it contained before;; entering .dvloop7[*]: "0" = valid result.ld e,a ; DE = remainder, HL = quotientret.morethan7bits:ld b,#9 ; at most 9 bits in quotient.ld a,l ; precompute the first 7 shifts, byld l,h ; doing 8ld h,#0rr l ; undoing 1.dvloop:;; Shift next bit of quotient into bit 0 of dividend;; Shift next MSB of dividend into LSB of remainder;; A holds both dividend and quotient. While we shift a bit from;; MSB of dividend, we shift next bit of quotient in from carry;; HL holds remainderadc hl,hl ; HL < 2^(7+9), no carry, ever.;; If remainder is >= divisor, next bit of quotient is 1. We try;; to compute the difference.sbc hl,dejr NC,.nodrop ; Jump if remainder is >= dividendadd hl,de ; Otherwise, restore remainder;; The add above sets the carry, because sbc hl,de did set it..nodrop:ccf ; Complement borrow so 1 indicates a; successful substraction (this is the; next bit of quotient)rladjnz .dvloop;; Take care of the ninth quotient bit! after the loop B=0.rl b ; BA = quotient;; Carry now contains "0" = valid result.ld d,bld e,a ; DE = quotient, HL = remainderex de,hl ; HL = quotient, DE = remainderret