                              1         ;; Originally from GBDK by Pascal Felber.
                              2         .area   _CODE
                              3 
   0000                       4 __divschar_rrx_s::
   0000 21 03 00              5         ld      hl,#2+1
   0003 39                    6         add     hl,sp
                              7 
   0004 5E                    8         ld      e,(hl)
   0005 2B                    9         dec     hl
   0006 6E                   10         ld      l,(hl)
                             11 
                             12         ;; Fall through
   0007                      13 __divschar_rrx_hds::
   0007 4D                   14         ld      c,l
                             15 
   0008 CDr88s00             16         call    .div8
                             17 
   000B 69                   18         ld      l,c
   000C 60                   19         ld      h,b
                             20 
   000D C9                   21         ret
                             22 
   000E                      23 __modschar_rrx_s::
   000E 21 03 00             24         ld      hl,#2+1
   0011 39                   25         add     hl,sp
                             26 
   0012 5E                   27         ld      e,(hl)
   0013 2B                   28         dec     hl
   0014 6E                   29         ld      l,(hl)
                             30 
                             31         ;; Fall through
   0015                      32 __modschar_rrx_hds::
   0015 4D                   33         ld      c,l
                             34 
   0016 CDr88s00             35         call    .div8
                             36 
   0019 6B                   37         ld      l,e
   001A 62                   38         ld      h,d
                             39 
   001B C9                   40         ret
                             41 
   001C                      42 __divsint_rrx_s::
   001C 21 05 00             43         ld      hl,#2+3
   001F 39                   44         add     hl,sp
                             45 
   0020 56                   46         ld      d,(hl)
   0021 2B                   47         dec     hl
   0022 5E                   48         ld      e,(hl)
   0023 2B                   49         dec     hl
   0024 7E                   50         ld      a,(hl)
   0025 2B                   51         dec     hl
   0026 6E                   52         ld      l,(hl)
   0027 67                   53         ld      h,a
                             54 
                             55         ;; Fall through
   0028                      56 __divsint_rrx_hds::
   0028 44                   57         ld      b,h
   0029 4D                   58         ld      c,l
                             59 
   002A CDr90s00             60         call    .div16
                             61 
   002D 69                   62         ld      l,c
   002E 60                   63         ld      h,b
                             64 
   002F C9                   65         ret
                             66 
   0030                      67 __modsint_rrx_s::
   0030 21 05 00             68         ld      hl,#2+3
   0033 39                   69         add     hl,sp
                             70 
   0034 56                   71         ld      d,(hl)
   0035 2B                   72         dec     hl
   0036 5E                   73         ld      e,(hl)
   0037 2B                   74         dec     hl
   0038 7E                   75         ld      a,(hl)
   0039 2B                   76         dec     hl
   003A 6E                   77         ld      l,(hl)
   003B 67                   78         ld      h,a
                             79 
                             80         ;; Fall through
   003C                      81 __modsint_rrx_hds::
   003C 44                   82         ld      b,h
   003D 4D                   83         ld      c,l
                             84 
   003E CDr90s00             85         call    .div16
                             86 
   0041 6B                   87         ld      l,e
   0042 62                   88         ld      h,d
                             89 
   0043 C9                   90         ret
                             91 
                             92         ;; Unsigned
   0044                      93 __divuchar_rrx_s::
   0044 21 03 00             94         ld      hl,#2+1
   0047 39                   95         add     hl,sp
                             96 
   0048 5E                   97         ld      e,(hl)
   0049 2B                   98         dec     hl
   004A 6E                   99         ld      l,(hl)
                            100 
                            101         ;; Fall through
   004B                     102 __divuchar_rrx_hds::
   004B 4D                  103         ld      c,l
   004C CDrCDs00            104         call    .divu8
                            105 
   004F 69                  106         ld      l,c
   0050 60                  107         ld      h,b
                            108 
   0051 C9                  109         ret
                            110 
   0052                     111 __moduchar_rrx_s::
   0052 21 03 00            112         ld      hl,#2+1
   0055 39                  113         add     hl,sp
                            114 
   0056 5E                  115         ld      e,(hl)
   0057 2B                  116         dec     hl
   0058 6E                  117         ld      l,(hl)
                            118 
                            119         ;; Fall through
   0059                     120 __moduchar_rrx_hds::
   0059 4D                  121         ld      c,l
   005A CDrCDs00            122         call    .divu8
                            123 
   005D 6B                  124         ld      l,e
   005E 62                  125         ld      h,d
                            126 
   005F C9                  127         ret
                            128 
   0060                     129 __divuint_rrx_s::
   0060 21 05 00            130         ld      hl,#2+3
   0063 39                  131         add     hl,sp
                            132 
   0064 56                  133         ld      d,(hl)
   0065 2B                  134         dec     hl
   0066 5E                  135         ld      e,(hl)
   0067 2B                  136         dec     hl
   0068 7E                  137         ld      a,(hl)
   0069 2B                  138         dec     hl
   006A 6E                  139         ld      l,(hl)
   006B 67                  140         ld      h,a
                            141 
                            142         ;; Fall through
   006C                     143 __divuint_rrx_hds::
   006C 44                  144         ld      b,h
   006D 4D                  145         ld      c,l
   006E CDrD0s00            146         call    .divu16
                            147 
   0071 69                  148         ld      l,c
   0072 60                  149         ld      h,b
                            150 
   0073 C9                  151         ret
                            152 
   0074                     153 __moduint_rrx_s::
   0074 21 05 00            154         ld      hl,#2+3
   0077 39                  155         add     hl,sp
                            156 
   0078 56                  157         ld      d,(hl)
   0079 2B                  158         dec     hl
   007A 5E                  159         ld      e,(hl)
   007B 2B                  160         dec     hl
   007C 7E                  161         ld      a,(hl)
   007D 2B                  162         dec     hl
   007E 6E                  163         ld      l,(hl)
   007F 67                  164         ld      h,a
                            165         ;; Fall through
                            166 
   0080                     167 __moduint_rrx_hds::
   0080 44                  168         ld      b,h
   0081 4D                  169         ld      c,l
                            170 
   0082 CDrD0s00            171         call    .divu16
                            172 
   0085 6B                  173         ld      l,e
   0086 62                  174         ld      h,d
                            175 
   0087 C9                  176         ret
                            177 
   0088                     178 .div8::
   0088                     179 .mod8::
   0088 79                  180         ld      a,c             ; Sign extend
   0089 07                  181         rlca
   008A 9F                  182         sbc     a
   008B 47                  183         ld      b,a
   008C 7B                  184         ld      a,e             ; Sign extend
   008D 07                  185         rlca
   008E 9F                  186         sbc     a
   008F 57                  187         ld      d,a
                            188 
                            189         ; Fall through to .div16
                            190 
                            191         ;; 16-bit division
                            192         ;;
                            193         ;; Entry conditions
                            194         ;;   BC = dividend
                            195         ;;   DE = divisor
                            196         ;;
                            197         ;; Exit conditions
                            198         ;;   BC = quotient
                            199         ;;   DE = remainder
                            200         ;;   If divisor is non-zero, carry=0
                            201         ;;   If divisor is 0, carry=1 and both quotient and remainder are 0
                            202         ;;
                            203         ;; Register used: AF,BC,DE,HL
   0090                     204 .div16::
   0090                     205 .mod16::
                            206         ;; Determine sign of quotient by xor-ing high bytes of dividend
                            207         ;;  and divisor. Quotient is positive if signs are the same, negative
                            208         ;;  if signs are different
                            209         ;; Remainder has same sign as dividend
   0090 78                  210         ld      a,b             ; Get high byte of dividend
   0091 32r00s00            211         ld      (.srem),a       ; Save as sign of remainder
   0094 AA                  212         xor     d               ; Xor with high byte of divisor
   0095 32r01s00            213         ld      (.squot),a      ; Save sign of quotient
                            214         ;; Take absolute value of divisor
   0098 CB 7A               215         bit     7,d
   009A CArA3s00            216         jp      Z,.chkde        ; Jump if divisor is positive
   009D 97                  217         sub     a               ; Substract divisor from 0
   009E 93                  218         sub     e
   009F 5F                  219         ld      e,a
   00A0 9F                  220         sbc     a               ; Propagate borrow (A=0xFF if borrow)
   00A1 92                  221         sub     d
   00A2 57                  222         ld      d,a
                            223         ;; Take absolute value of dividend
   00A3                     224 .chkde:
   00A3 CB 78               225         bit     7,b
   00A5 CArAEs00            226         jp      Z,.dodiv        ; Jump if dividend is positive
   00A8 97                  227         sub     a               ; Substract dividend from 0
   00A9 91                  228         sub     c
   00AA 4F                  229         ld      c,a
   00AB 9F                  230         sbc     a               ; Propagate borrow (A=0xFF if borrow)
   00AC 90                  231         sub     b
   00AD 47                  232         ld      b,a
                            233         ;; Divide absolute values
   00AE                     234 .dodiv:
   00AE CDrD0s00            235         call    .divu16
   00B1 D8                  236         ret     C               ; Exit if divide by zero
                            237         ;; Negate quotient if it is negative
   00B2 3Ar01s00            238         ld      a,(.squot)
   00B5 E6 80               239         and     #0x80
   00B7 CArC0s00            240         jp      Z,.dorem        ; Jump if quotient is positive
   00BA 97                  241         sub     a               ; Substract quotient from 0
   00BB 91                  242         sub     c
   00BC 4F                  243         ld      c,a
   00BD 9F                  244         sbc     a               ; Propagate borrow (A=0xFF if borrow)
   00BE 90                  245         sub     b
   00BF 47                  246         ld      b,a
   00C0                     247 .dorem:
                            248         ;; Negate remainder if it is negative
   00C0 3Ar00s00            249         ld      a,(.srem)
   00C3 E6 80               250         and     #0x80
   00C5 C8                  251         ret     Z               ; Return if remainder is positive
   00C6 97                  252         sub     a               ; Substract remainder from 0
   00C7 93                  253         sub     e
   00C8 5F                  254         ld      e,a
   00C9 9F                  255         sbc     a               ; Propagate remainder (A=0xFF if borrow)
   00CA 92                  256         sub     d
   00CB 57                  257         ld      d,a
   00CC C9                  258         ret
                            259 
   00CD                     260 .divu8::
   00CD                     261 .modu8::
   00CD 06 00               262         ld      b,#0x00
   00CF 50                  263         ld      d,b
                            264         ; Fall through to divu16
                            265 
   00D0                     266 .divu16::
   00D0                     267 .modu16::
                            268         ;; Check for division by zero
   00D0 7B                  269         ld      a,e
   00D1 B2                  270         or      d
   00D2 C2rDCs00            271         jp      NZ,.divide      ; Branch if divisor is non-zero
   00D5 01 00 00            272         ld      bc,#0x00        ; Divide by zero error
   00D8 50                  273         ld      d,b
   00D9 59                  274         ld      e,c
   00DA 37                  275         scf                     ; Set carry, invalid result
   00DB C9                  276         ret
   00DC                     277 .divide:
   00DC 21 00 00            278         ld      hl,#0
                            279 ;       ld      l,c             ; L = low byte of dividend/quotient
                            280 ;       ld      h,b             ; H = high byte of dividend/quotient
                            281 ;       ld      bc,#0x00        ; BC = remainder
   00DF B7                  282         or      a               ; Clear carry to start
   00E0 08                  283         ex      af,af
   00E1 3E 10               284         ld      a,#16           ; 16 bits in dividend
   00E3                     285 .dvloop:
                            286         ;; Shift next bit of quotient into bit 0 of dividend
                            287         ;; Shift next MSB of dividend into LSB of remainder
                            288         ;; BC holds both dividend and quotient. While we shift a bit from
                            289         ;;  MSB of dividend, we shift next bit of quotient in from carry
                            290         ;; HL holds remainder
                            291         ;; Do a 32-bit left shift, shifting carry to L, L to H,
                            292         ;;  H to C, C to B
   00E3 08                  293         ex      af,af'
   00E4 CB 11               294         rl      c               ; Carry (next bit of quotient) to bit 0
   00E6 CB 10               295         rl      b               ; Clears carry since BC was 0
   00E8 ED 6A               296         adc     hl,hl
                            297 
                            298         ;; If remainder is >= divisor, next bit of quotient is 1. This
                            299         ;;  bit goes to carry
   00EA E5                  300         push    hl              ; Save current remainder
   00EB ED 52               301         sbc     hl,de
                            302 ;       ld      a,c             ; Substract divisor from remainder
                            303 ;       sbc     e
                            304 ;       ld      c,a
                            305 ;       ld      a,b
                            306 ;       sbc     d
                            307 ;       ld      b,a
   00ED 3F                  308         ccf                     ; Complement borrow so 1 indicates a
                            309                                 ;  successful substraction (this is the
                            310                                 ;  next bit of quotient)
   00EE DArF5s00            311         jp      C,.drop         ; Jump if remainder is >= dividend
   00F1 E1                  312         pop     hl              ; Otherwise, restore remainder
   00F2 C3rF7s00            313         jp      .nodrop
   00F5                     314 .drop:
   00F5 33                  315         inc     sp
   00F6 33                  316         inc     sp
   00F7                     317 .nodrop:
   00F7 08                  318         ex      af,af'
   00F8 3D                  319         dec     a               ; DEC does not affect carry flag
   00F9 C2rE3s00            320         jp      NZ,.dvloop
   00FC 08                  321         ex      af,af'
                            322         ;; Shift last carry bit into quotient
   00FD 54                  323         ld      d,h             ; DE = remainder
   00FE 5D                  324         ld      e,l
   00FF CB 11               325         rl      c               ; Carry to L
                            326 ;       ld      c,l             ; C = low byte of quotient
   0101 CB 10               327         rl      b
                            328 ;       ld      b,h             ; B = high byte of quotient
   0103 B7                  329         or      a               ; Clear carry, valid result
   0104 C9                  330         ret
                            331 
                            332         .area   _BSS
                            333 
   0000                     334 .srem:
   0000                     335         .ds 0x01                ; Sign of quotient
   0001                     336 .squot:
   0001                     337         .ds 0x01                ; Sign of remainder
   0002                     338 .dcnt:
   0002                     339         .ds 0x01                ; Counter for division
