X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=device%2Flib%2Fz80%2Fdiv.s;h=305cd67ab13a1c39bf6d0f790723b975af3ffe0e;hb=5a1d5e778e85664f4e6657019348b4756b16eacb;hp=5ef13688034b938d9828736e12914cb41e746c1e;hpb=f888fe111c14e94fd2c4c306467c69943addef00;p=fw%2Fsdcc diff --git a/device/lib/z80/div.s b/device/lib/z80/div.s index 5ef13688..305cd67a 100644 --- a/device/lib/z80/div.s +++ b/device/lib/z80/div.s @@ -1,254 +1,143 @@ ;; Originally from GBDK by Pascal Felber. - .area CODE -__divschar_rrx_s:: - ld hl,#2+1 - add hl,sp - - ld e,(hl) - dec hl - ld l,(hl) + .area _CODE - ;; Fall through -__divschar_rrx_hds:: - ld c,l - - call .div8 +__divuint_rrx_s:: + pop af + pop hl + pop de + push de + push hl + push af - ld l,c - ld h,b + jr __divu16 - ret - -__modschar_rrx_s:: +__divsuchar_rrx_s:: ld hl,#2+1 add hl,sp ld e,(hl) dec hl ld l,(hl) + xor a - ;; Fall through -__modschar_rrx_hds:: - ld c,l - - call .div8 - - ld l,e - ld h,d - - ret - -__divsint_rrx_s:: - ld hl,#2+3 - add hl,sp - - ld d,(hl) - dec hl - ld e,(hl) - dec hl - ld a,(hl) - dec hl - ld l,(hl) - ld h,a - - ;; Fall through -__divsint_rrx_hds:: - ld b,h - ld c,l - - call .div16 - - ld l,c - ld h,b - - ret + jr signexte -__modsint_rrx_s:: - ld hl,#2+3 - add hl,sp - - ld d,(hl) - dec hl - ld e,(hl) - dec hl - ld a,(hl) - dec hl - ld l,(hl) - ld h,a - - ;; Fall through -__modsint_rrx_hds:: - ld b,h - ld c,l - - call .div16 - - ld l,e - ld h,d - - ret - - ;; Unsigned -__divuchar_rrx_s:: +__modsuchar_rrx_s:: ld hl,#2+1 add hl,sp ld e,(hl) dec hl ld l,(hl) + xor a - ;; Fall through -__divuchar_rrx_hds:: - ld c,l - call .divu8 - - ld l,c - ld h,b + call signexte + ex de,hl ret -__moduchar_rrx_s:: +__divuschar_rrx_s:: ld hl,#2+1 + ld d, h add hl,sp ld e,(hl) dec hl ld l,(hl) - ;; Fall through -__moduchar_rrx_hds:: - ld c,l - call .divu8 - - ld l,e - ld h,d - - ret - -__divuint_rrx_s:: - ld hl,#2+3 - add hl,sp - - ld d,(hl) - dec hl - ld e,(hl) - dec hl - ld a,(hl) - dec hl - ld l,(hl) + ld a,l ; Sign extend + rlca + sbc a ld h,a - ;; Fall through -__divuint_rrx_hds:: - ld b,h - ld c,l - call .divu16 - - ld l,c - ld h,b + jr __div16 - ret - -__moduint_rrx_s:: - ld hl,#2+3 +__divschar_rrx_s:: + ld hl,#2+1 add hl,sp - ld d,(hl) - dec hl ld e,(hl) dec hl - ld a,(hl) - dec hl ld l,(hl) - ld h,a - ;; Fall through - -__moduint_rrx_hds:: - ld b,h - ld c,l - - call .divu16 - - ld l,e - ld h,d - - ret -.div8:: -.mod8:: - ld a,c ; Sign extend + ;; Fall through +__divschar_rrx_hds:: +__div8:: + ld a,l ; Sign extend rlca sbc a - ld b,a +signexte: + ld h,a ld a,e ; Sign extend rlca sbc a ld d,a + ; Fall through to __div16 - ; Fall through to .div16 - - ;; 16-bit division + ;; signed 16-bit division ;; ;; Entry conditions - ;; BC = dividend + ;; HL = dividend ;; DE = divisor ;; ;; Exit conditions - ;; BC = quotient + ;; HL = quotient ;; DE = remainder ;; If divisor is non-zero, carry=0 ;; If divisor is 0, carry=1 and both quotient and remainder are 0 ;; ;; Register used: AF,BC,DE,HL -.div16:: -.mod16:: +__divsint_rrx_hds:: +__div16:: ;; Determine sign of quotient by xor-ing high bytes of dividend ;; and divisor. Quotient is positive if signs are the same, negative ;; if signs are different ;; Remainder has same sign as dividend - ld a,b ; Get high byte of dividend - ld (.srem),a ; Save as sign of remainder + ld a,h ; Get high byte of dividend xor d ; Xor with high byte of divisor - ld (.squot),a ; Save sign of quotient + rla ; Sign of quotient goes into the carry + ld a,h ; Get high byte of dividend + push af ; Save sign of both quotient and reminder + + ;; Take absolute value of dividend + rla + jr NC,.chkde ; Jump if dividend is positive + sub a ; Substract dividend from 0 + sub l + ld l,a + sbc a ; Propagate borrow (A=0xFF if borrow) + sub h + ld h,a ;; Take absolute value of divisor +.chkde: bit 7,d - jp Z,.chkde ; Jump if divisor is positive + jr Z,.dodiv ; Jump if divisor is positive sub a ; Substract divisor from 0 sub e ld e,a sbc a ; Propagate borrow (A=0xFF if borrow) sub d ld d,a - ;; Take absolute value of dividend -.chkde: - bit 7,b - jp Z,.dodiv ; Jump if dividend is positive - sub a ; Substract dividend from 0 - sub c - ld c,a - sbc a ; Propagate borrow (A=0xFF if borrow) - sub b - ld b,a ;; Divide absolute values .dodiv: - call .divu16 - ret C ; Exit if divide by zero + call __divu16 + jr C,.exit ; Exit if divide by zero ;; Negate quotient if it is negative - ld a,(.squot) - and #0x80 - jp Z,.dorem ; Jump if quotient is positive + pop af ; recover sign of quotient + jr NC,.dorem ; Jump if quotient is positive + ld b,a sub a ; Substract quotient from 0 - sub c - ld c,a + sub l + ld l,a sbc a ; Propagate borrow (A=0xFF if borrow) - sub b - ld b,a + sub h + ld h,a + ld a,b .dorem: ;; Negate remainder if it is negative - ld a,(.srem) - and #0x80 - ret Z ; Return if remainder is positive + rla + ret NC ; Return if remainder is positive sub a ; Substract remainder from 0 sub e ld e,a @@ -256,84 +145,86 @@ __moduint_rrx_hds:: sub d ld d,a ret +.exit: + pop af + +.dividebyzero: + ld h,d ; Divide by zero error: D=E=0 + ld l,e + scf ; Set carry, invalid result + ret -.divu8:: -.modu8:: - ld b,#0x00 - ld d,b + ;; Unsigned +__divuchar_rrx_s:: + ld hl,#2+1 + add hl,sp + + ld e,(hl) + dec hl + ld l,(hl) + + ;; Fall through +__divuchar_rrx_hds:: +__divu8:: + ld h,#0x00 + ld d,h ; Fall through to divu16 -.divu16:: -.modu16:: + ;; unsigned 16-bit division + ;; Restructured on April 2009 by Marco Bodrato(http://bodrato.it/ ) + ;; + ;; Entry conditions + ;; HL = dividend + ;; DE = divisor + ;; + ;; Exit conditions + ;; HL = quotient + ;; DE = remainder + ;; If divisor is non-zero, carry=0 + ;; If divisor is 0, carry=1 and both quotient and remainder are 0 + ;; + ;; Register used: AF,B,DE,HL +__divuint_rrx_hds:: +__divu16:: ;; Check for division by zero ld a,e or d - jp NZ,.divide ; Branch if divisor is non-zero - ld bc,#0x00 ; Divide by zero error - ld d,b - ld e,c - scf ; Set carry, invalid result - ret -.divide: + jr Z,.dividebyzero ; Branch if divisor is non-zero + ld a,h + ld c,l ld hl,#0 -; ld l,c ; L = low byte of dividend/quotient -; ld h,b ; H = high byte of dividend/quotient -; ld bc,#0x00 ; BC = remainder - or a ; Clear carry to start - ex af,af - ld a,#16 ; 16 bits in dividend + ;; Carry was cleared by OR, this "0" bit will pass trough AC.[*] + ld b,#16 ; 16 bits in dividend .dvloop: + ;; Cleaned up on April 2009 by Marco Bodrato(http://bodrato.it/ ) ;; Shift next bit of quotient into bit 0 of dividend ;; Shift next MSB of dividend into LSB of remainder - ;; BC holds both dividend and quotient. While we shift a bit from + ;; AC 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 remainder - ;; Do a 32-bit left shift, shifting carry to L, L to H, - ;; H to C, C to B - ex af,af' + ;; Do a 32-bit left shift, shifting carry to C, C to A, + ;; A to HL rl c ; Carry (next bit of quotient) to bit 0 - rl b ; Clears carry since BC was 0 - adc hl,hl + rla + adc hl,hl ; HL < 32768 before, no carry, ever. - ;; If remainder is >= divisor, next bit of quotient is 1. This - ;; bit goes to carry - push hl ; Save current remainder + ;; If remainder is >= divisor, next bit of quotient is 1. We try + ;; to compute the difference. sbc hl,de -; ld a,c ; Substract divisor from remainder -; sbc e -; ld c,a -; ld a,b -; sbc d -; ld b,a + jr NC,.nodrop ; Jump if remainder is >= dividend + add 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) - jp C,.drop ; Jump if remainder is >= dividend - pop hl ; Otherwise, restore remainder - jp .nodrop -.drop: - inc sp - inc sp -.nodrop: - ex af,af' - dec a ; DEC does not affect carry flag - jp NZ,.dvloop - ex af,af' + djnz .dvloop ;; Shift last carry bit into quotient - ld d,h ; DE = remainder - ld e,l - rl c ; Carry to L -; ld c,l ; C = low byte of quotient - rl b -; ld b,h ; B = high byte of quotient - or a ; Clear carry, valid result + rl c ; Carry to C + rla + ;; Carry now contains the same value it contained before + ;; entering .dvloop[*]: "0" = valid result. + ld d,a + ld e,c ; DE = quotient, HL = remainder + ex de,hl ; HL = quotient, DE = remainder ret - - .area BSS - -.srem: - .ds 0x01 ; Sign of quotient -.squot: - .ds 0x01 ; Sign of remainder -.dcnt: - .ds 0x01 ; Counter for division