Difference between revisions of "Z80 Routines:Math:Division"

From WikiTI
Jump to: navigation, search
(Fixed 24/8 and 32/8.)
(I'm just going to assume Rounded 16/8 was also broken.)
Line 41: Line 41:
 
   add hl, hl
 
   add hl, hl
 
   rla
 
   rla
  jr c, $+5
 
 
   cp c
 
   cp c
 
   jr c, $+4
 
   jr c, $+4
 
 
   sub c
 
   sub c
 
   inc l
 
   inc l
Line 89: Line 87:
 
   rl e
 
   rl e
 
   rla
 
   rla
  jr c, $+5
 
 
   cp d
 
   cp d
 
   jr c, $+4
 
   jr c, $+4
 
 
   sub d
 
   sub d
 
   inc l
 
   inc l
Line 115: Line 111:
 
   rl d
 
   rl d
 
   rla
 
   rla
  jr c, $+5
 
 
   cp c
 
   cp c
 
   jr c, $+4
 
   jr c, $+4
 
 
   sub c
 
   sub c
 
   inc l
 
   inc l
Line 125: Line 119:
 
    
 
    
 
   ret
 
   ret
</nowiki>
 
== 32/16 division ==
 
 
The following routine divides acix by de and places the quotient in acix and the remainder in hl
 
 
<nowiki>
 
Div32By16:
 
; IN: ACIX=dividend, DE=divisor
 
; OUT: ACIX=quotient, DE=divisor, HL=remainder, B=0
 
ld hl,0
 
ld b,32
 
Div32By16_Loop:
 
add ix,ix
 
rl c
 
rla
 
adc hl,hl
 
jr c,Div32By16_Overflow
 
sbc hl,de
 
jr nc,Div32By16_SetBit
 
add hl,de
 
djnz Div32By16_Loop
 
ret
 
Div32By16_Overflow:
 
or a
 
sbc hl,de
 
Div32By16_SetBit:
 
.db $DD,$2C ; inc ixl, change to inc ix to avoid undocumented
 
djnz Div32By16_Loop
 
ret
 
 
  </nowiki>
 
  </nowiki>
  
Line 168: Line 133:
 
   add hl, hl
 
   add hl, hl
 
   rla
 
   rla
 +
  jr c, $+5
 
   cp c
 
   cp c
 
   jr c, $+4
 
   jr c, $+4

Revision as of 04:09, 15 March 2017


Introduction

All these routines use the restoring division algorithm, adapted to the z80 architecture to maximize speed. They can easily be unrolled to gain some speed.

8/8 division

The following routine divides d by e and places the quotient in d and the remainder in a

div_d_e:
   xor	a
   ld	b, 8

_loop:
   sla	d
   rla
   cp	e
   jr	c, $+4
   sub	e
   inc	d
   
   djnz	_loop
   
   ret
 

16/8 division

The following routine divides hl by c and places the quotient in hl and the remainder in a

div_hl_c:
   xor	a
   ld	b, 16

_loop:
   add	hl, hl
   rla
   cp	c
   jr	c, $+4
   sub	c
   inc	l
   
   djnz	_loop
   
   ret
 

16/16 division

The following routine divides ac by de and places the quotient in ac and the remainder in hl

div_ac_de:
   ld	hl, 0
   ld	b, 16

_loop:
   sll	c
   rla
   adc	hl, hl
   sbc	hl, de
   jr	nc, $+4
   add	hl, de
   dec	c
   
   djnz	_loop
   
   ret
 

24/8 division

The following routine divides ehl by d and places the quotient in ehl and the remainder in a

div_ehl_d:
   xor	a
   ld	b, 24

_loop:
   add	hl, hl
   rl	e
   rla
   cp	d
   jr	c, $+4
   sub	d
   inc	l
   
   djnz	_loop
   
   ret
 

32/8 division

The following routine divides dehl by c and places the quotient in dehl and the remainder in a

div_dehl_c:
   xor	a
   ld	b, 32

_loop:
   add	hl, hl
   rl	e
   rl	d
   rla
   cp	c
   jr	c, $+4
   sub	c
   inc	l
   
   djnz	_loop
   
   ret
 

Rounded 16/8 division

The following routine divides hl by c and places the rounded quotient in hl and twice the prerounded remainder in a.

RoundHL_Div_C:
   xor	a
   ld	b, 16

_loop:
   add	hl, hl
   rla
   jr	c, $+5
   cp	c
   jr	c, $+4
   sub	c
   inc	l   
   djnz	_loop
;This part is the rounding
   add a,a
   cp	c
   ret	c
   inc hl
   ret