Difference between revisions of "Z80 Routines:Math:Multiplication"
From WikiTI
(→16*16 multiplication) |
Thepenguin77 (Talk | contribs) |
||
Line 89: | Line 89: | ||
ret | ret | ||
+ | </nowiki> | ||
+ | |||
+ | === 24*24 multiplication === | ||
+ | |||
+ | The following routine multiplies bcd by ehl and places the result in bcdehl. It uses 2 bytes of ram, but those can be substituted for IX half registers. (By thepenguin77) | ||
+ | |||
+ | <nowiki> | ||
+ | multDBCbyEHL: | ||
+ | |||
+ | push de | ||
+ | push hl | ||
+ | |||
+ | ld ix, $8000 | ||
+ | ld (ix), l | ||
+ | xor a | ||
+ | ld h, a | ||
+ | ld l, a | ||
+ | |||
+ | call do8Bits | ||
+ | |||
+ | ld (ix+1), a | ||
+ | pop af | ||
+ | ld (ix), a | ||
+ | push de | ||
+ | ld a, (ix+1) | ||
+ | |||
+ | call do8Bits | ||
+ | |||
+ | ld (ix+1), a | ||
+ | pop af ;least sig number | ||
+ | ex de, hl | ||
+ | ex (sp), hl ;D and 2nd least sig in for new number | ||
+ | ld (ix), l | ||
+ | pop hl ;D and 2nd least sig | ||
+ | push af ;least sig number | ||
+ | push hl ;2nd least sig number | ||
+ | ex de, hl | ||
+ | ld a, (ix+1) | ||
+ | |||
+ | call do8Bits | ||
+ | |||
+ | ld b, a | ||
+ | ld c, h | ||
+ | ld d, l | ||
+ | pop hl | ||
+ | ld a, l | ||
+ | pop hl | ||
+ | ld h, a | ||
+ | ret | ||
+ | |||
+ | ;#### | ||
+ | ;input: DBC = 1 number | ||
+ | ; AHL = running number | ||
+ | ; (ix) = to multiply by | ||
+ | ;output: AHLE = output | ||
+ | ; E is done | ||
+ | ; DBC = 1 number | ||
+ | |||
+ | do8Bits: | ||
+ | ld (ix+1), 8 | ||
+ | loop: | ||
+ | srl (ix) | ||
+ | jr nc, skip | ||
+ | |||
+ | add hl, bc | ||
+ | adc a, d | ||
+ | skip: | ||
+ | rra | ||
+ | rr h | ||
+ | rr l | ||
+ | rr e | ||
+ | dec (ix+1) | ||
+ | jr nz, loop | ||
+ | ret | ||
</nowiki> | </nowiki> | ||
Revision as of 16:54, 8 December 2011
Contents
Introduction
All these routines use the restoring multiplication algorithm, adapted to the z80 architecture to maximize speed. They can easily be unrolled to gain some speed.
Unsigned versions
8*8 multiplication
The following routine multiplies h by e and places the result in hl
mult_h_e ld l, 0 ld d, l sla h ; optimised 1st iteration jr nc, $+3 ld l, e ld b, 7 _loop: add hl, hl jr nc, $+3 add hl, de djnz _loop ret
16*8 multiplication
The following routine multiplies de by a and places the result in ahl (which means a is the most significant byte of the product, l the least significant and h the intermediate one...)
mult_a_de ld c, 0 ld h, c ld l, h add a, a ; optimised 1st iteration jr nc, $+4 ld h,d ld l,e ld b, 7 _loop: add hl, hl rla jr nc, $+4 add hl, de adc a, c ; yes this is actually adc a, 0 but since c is free we set it to zero and so we can save 1 byte and up to 3 T-states per iteration djnz _loop ret
16*16 multiplication
The following routine multiplies bc by de and places the result in dehl.
mult_de_bc ld hl, 0 sla e ; optimised 1st iteration rl d jr nc, $+4 ld h, b ld l, c ld a, 15 _loop: add hl, hl rl e rl d jr nc, $+6 add hl, bc jr nc, $+3 inc de dec a jr nz, _loop ret
24*24 multiplication
The following routine multiplies bcd by ehl and places the result in bcdehl. It uses 2 bytes of ram, but those can be substituted for IX half registers. (By thepenguin77)
multDBCbyEHL: push de push hl ld ix, $8000 ld (ix), l xor a ld h, a ld l, a call do8Bits ld (ix+1), a pop af ld (ix), a push de ld a, (ix+1) call do8Bits ld (ix+1), a pop af ;least sig number ex de, hl ex (sp), hl ;D and 2nd least sig in for new number ld (ix), l pop hl ;D and 2nd least sig push af ;least sig number push hl ;2nd least sig number ex de, hl ld a, (ix+1) call do8Bits ld b, a ld c, h ld d, l pop hl ld a, l pop hl ld h, a ret ;#### ;input: DBC = 1 number ; AHL = running number ; (ix) = to multiply by ;output: AHLE = output ; E is done ; DBC = 1 number do8Bits: ld (ix+1), 8 loop: srl (ix) jr nc, skip add hl, bc adc a, d skip: rra rr h rr l rr e dec (ix+1) jr nz, loop ret