cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

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