Author Topic: [z80] 16 by 16 signed division  (Read 6707 times)

0 Members and 1 Guest are viewing this topic.

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
[z80] 16 by 16 signed division
« on: July 01, 2013, 12:37:58 pm »
Hello people,

I need a HLbyDE signed division, but I can't find one on Google ...

Does any of you have that ?
« Last Edit: July 01, 2013, 12:38:28 pm by Matrefeytontias »

Offline Hayleia

  • Programming Absol
  • Coder Of Tomorrow
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3367
  • Rating: +393/-7
    • View Profile
Re: [z80] 16 by 16 signed division
« Reply #1 on: July 01, 2013, 12:45:07 pm »
Maybe you can have a look at the one used by Axe ? I believe there is an unsigned routine and a signed routine (one using "/" and the other one using "//").
I own: 83+ ; 84+SE ; 76.fr ; CX CAS ; Prizm ; 84+CSE
Sorry if I answer with something that seems unrelated, English is not my primary language and I might not have understood well. Sorry if I make English mistakes too.

click here to know where you got your last +1s

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: [z80] 16 by 16 signed division
« Reply #2 on: July 01, 2013, 12:48:36 pm »
Yeah it's the case, but they're embedded with other routines to work with Axe, so ...

Offline Xeda112358

  • they/them
  • Moderator
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 4704
  • Rating: +719/-6
  • Calc-u-lator, do doo doo do do do.
    • View Profile
Re: [z80] 16 by 16 signed division
« Reply #3 on: July 01, 2013, 01:06:09 pm »
The easiest way to do it, probably, is to just use a regular division routine and check for the sign of the input:
Code: [Select]
     ld a,d
     xor h       ;now the sign flag is set if the result needs to be negative or positive.
     push af
     xor h       ;now a=d again, but we have the sign flag set appropriately
     jp p,$+9    ;if the sign is minus, negate DE
       xor a
       sub e
       ld e,a
       sbc a,a  ;c flag is set, so this makes A=$FF
       sub d
       ld d,a
     ld a,h
     or a
     jp p,$+9
       xor a
       sub l
       ld l,a
       sbc a,a  ;c flag is set, so this makes A=$FF
       sub h
       ld h,a
     call HL_Div_DE    ;return the result in HL
     pop af
     ret p
     xor a
     sub l
     ld l,a
     sbc a,a
     sub h
     ld h,a
     ret
In the worst case, it is 141 t-states + however long it takes for the regular division.

141 t-states extra if one input is negative
137 t-states extra if both are negative
89 t-states extra if both inputs are positive

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: [z80] 16 by 16 signed division
« Reply #4 on: July 01, 2013, 01:50:41 pm »
Okay, thanks for this quick answer, I'll use that :)

Offline tr1p1ea

  • LV7 Elite (Next: 700)
  • *******
  • Posts: 647
  • Rating: +110/-0
    • View Profile
Re: [z80] 16 by 16 signed division
« Reply #5 on: July 01, 2013, 06:09:56 pm »
Are you cooking up some more 3D stuff? :).

I only ask because sometimes it is faster to multiply by a reciprocal than do a division.
« Last Edit: July 01, 2013, 06:10:41 pm by tr1p1ea »
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."


Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: [z80] 16 by 16 signed division
« Reply #6 on: July 01, 2013, 06:45:59 pm »
Meh, stop always guessing right ;D

I'll post about it later, don't worry.

Offline Xeda112358

  • they/them
  • Moderator
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 4704
  • Rating: +719/-6
  • Calc-u-lator, do doo doo do do do.
    • View Profile
Re: [z80] 16 by 16 signed division
« Reply #7 on: July 02, 2013, 11:33:59 am »
EDIT: Fixed a problem for when HL=8000h.
I have this routine that is larger, but faster than my other division routines:
Code: [Select]
;===============================================================
HL_Div_BC_Signed:
;===============================================================
;Performs HL/BC
;Speed: 1350-55a-2b
;         b is the number of set bits in the result
;         a is the number of leading zeroes in the absolute value of HL, minus 1
;         add 24 if HL is negative
;         add 19 if BC is negative
;         add 28 if the result is negative
;Size:    68 bytes
;Inputs:
;     HL is the numerator
;     BC is the denominator
;Outputs:
;     DE is the quotient
;     HL is the remainder
;     BC is not changed
;Destroys:
;     A
;===============================================================
     ld a,h
     xor b
     push af
;absHL
     xor b
     jp p,$+9
     xor a \ sub l \ ld l,a
     sbc a,a \ sub h \ ld h,a
;absBC:
     bit 7,b
     jr z,$+8
     xor a \ sub c \ ld c,a
     sbc a,a \ sub b \ ld b,a

     ld de,0
     adc hl,hl
     jr z,EndSDiv
     ld a,16

     add hl,hl
     dec a
     jp nc,$-2
     ex de,hl
     jp jumpin
Loop1:
     add hl,bc     ;--
Loop2:
     dec a         ;4
     jr z,EndSDiv  ;12|23
     sla e         ;--
     rl d          ;--
jumpin:            ;
     adc hl,hl     ;15
     sbc hl,bc     ;15
     jr c,Loop1    ;23-2b     ;b is the number of bits in the absolute value of the result.
     inc e         ;--
     jp Loop2      ;--
EndSDiv:
     pop af \ ret p
     xor a \ sub e \ ld e,a
     sbc a,a \ sub d \ ld d,a
     ret
So at its slowest, it is 1396 clock cycles and at its fastest (for non-trivial division) it is can get as low as 572 t-states for non-trivial division.

EDIT: I think I messed up the clock cycle count (but not by much). Anyways, here is a cleaner version that is smaller and more predictable. 1315-2b t-states where b is the number of bits set in the absolute value of the result:
EDIT2: The timings above are correct, now.
Code: [Select]
;===============================================================
HL_Div_BC_Signed:
;===============================================================
;Performs HL/BC
;Speed:   1315-2b cycles
;         **same cycles as the regular HL_Div_BC
;         add 24 if HL is negative
;         add 24 if BC is negative
;         add 28 if only one is negative
;Size:    60 bytes
;Inputs:
;     HL is the numerator
;     BC is the denominator
;Outputs:
;     DE is the quotient
;     HL is the remainder
;     BC is not changed
;     A is 0
;     z flag is set
;     c flag is reset
;===============================================================
     ld a,h
     xor b
     push af
;absHL
     xor b
     jp p,$+9
     xor a \ sub l \ ld l,a
     sbc a,a \ sub h \ ld h,a
;absBC:
     xor b
     jp p,$+9
     xor a \ sub c \ ld c,a
     sbc a,a \ sub b \ ld b,a

     add hl,hl
     ld a,15
     ld de,0
     ex de,hl
     jp jumpin
;89+15*80+26 = 1315-2b
Div_Loop_1:
     add hl,bc   ;--
Loop2:
     dec a       ;4
     jr z,EndSDiv ;12|7
jumpin:
     sla e       ;8
     rl d        ;8
     adc hl,hl   ;15
     sbc hl,bc   ;15
     jr c,Loop1  ;23-2b
     inc e       ;--
     jp Loop2    ;--
EndSDiv:
     pop af \ ret p
     xor a \ sub e \ ld e,a
     sbc a,a \ sub d \ ld d,a
     ret

Offline tr1p1ea

  • LV7 Elite (Next: 700)
  • *******
  • Posts: 647
  • Rating: +110/-0
    • View Profile
Re: [z80] 16 by 16 signed division
« Reply #8 on: July 02, 2013, 07:24:19 pm »
Impressive work Xeda :).
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."


Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: [z80] 16 by 16 signed division
« Reply #9 on: July 03, 2013, 08:12:32 am »
It seems that the second routine is wrong ... it gives me wrong results.

Offline Xeda112358

  • they/them
  • Moderator
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 4704
  • Rating: +719/-6
  • Calc-u-lator, do doo doo do do do.
    • View Profile
Re: [z80] 16 by 16 signed division
« Reply #10 on: July 03, 2013, 08:27:26 am »
Wait, but does the first routine work?

Maybe I made a typo with the second one...

EDIT: Hmm, both seem to work for me, but there could be certain vales that cause problems. What values did you use?

For example, I did -16/3 and it returned -5 (65531) with a remainder of 1.