.module Maths .module Mul U8U8 ; HL = E*A ld hl,0 ld d,h .rept 8 rrca jp nc,{+} add hl,de + sla e rl d .loop ret S8S8 ; HL = E*B ld d,0 ld h,d bit 7,e jp z,{+} inc h ld a,e neg ld e,a + ld a,b bit 7,a jp z,{+} inc h neg + bit 0,h jp z,U8U8 call U8U8 dec hl ld a,h \ cpl \ ld h,a ld a,l \ cpl \ ld l,a ret S8U8 ; sHL = sE*uA bit 7,e jp z,U8U8 ld b,a ld a,e neg ld e,a ld a,b call U8U8 dec hl ld a,h \ cpl \ ld h,a ld a,l \ cpl \ ld l,a ret U16U8 ; AHL = uA*uDE ld hl,0 ld c,0 add a,a jr nc,$+4 ld h,d ld l,e .rept 7 add hl,hl rla jr nc,$+4 add hl,de adc a,c .loop ret S16S8 ; AHL = sA*sDE ld h,0 bit 7,a jp z,{+} inc h neg + bit 7,d jp z,{+} inc h push af dec de ld a,d \ cpl \ ld d,a ld a,e \ cpl \ ld e,a pop af + bit 0,h jp z,U16U8 call U16U8 ld e,a dec hl ld a,h \ cpl \ ld h,a ld a,l \ cpl \ ld l,a ld a,e neg ret U16U16 ; DEHL = sDE*sBC ld hl,0 .rept 16 add hl,hl rl e rl d jp nc,{+} add hl,bc jp nc,{+} inc de + .loop ret S16S16 ; sDEHL = sDE*sBC ld l,0 bit 7,d jp z,{+} ; DE is -ve inc l dec de ld a,d \ cpl \ ld d,a ld a,e \ cpl \ ld e,a + bit 7,b jp z,{+} ; BC is signed. inc l dec bc ld a,b \ cpl \ ld b,a ld a,c \ cpl \ ld c,a + ld a,l call U16U16 and 1 ret z ; No need to flip sign of DEHL ld a,h \ or l dec hl jp nz,{+} dec de + ld a,d \ cpl \ ld d,a ld a,e \ cpl \ ld e,a ld a,h \ cpl \ ld h,a ld a,l \ cpl \ ld l,a ret A72 ; hl = a * 72 push de ld l,a ld h,0 add hl,hl ; 2 add hl,hl ; 4 add hl,hl ; 8 ld d,h ld e,l add hl,hl ; 16 add hl,hl ; 32 add hl,hl ; 64 add hl,de ; 72 pop de ret A24 ; hl = a * 24 push de ld l,a ld h,0 add hl,hl ; 2 add hl,hl ; 4 add hl,hl ; 8 ld d,h ld e,l add hl,hl ; 16 add hl,de ; 24 pop de ret .endmodule .module Div U16U8 ; HL rA = uHL / uC xor a .rept 16 add hl,hl rla cp c jr c,$+4 sub c inc l .loop ret U16S8 ; HL = uHL / sC bit 7,c jp z,U16U8 ld a,c neg ld c,a xor a .rept 16 add hl,hl rla cp c jr c,$+4 sub c inc l .loop dec hl ld a,h \ cpl \ ld h,a ld a,l \ cpl \ ld l,a ret .endmodule Sqr16 ld de,$0040 ld a,l ld l,h ld h,d or a ld b,8 - sbc hl,de jr nc,+ add hl,de + ccf rl d add a,a adc hl,hl add a,a adc hl,hl djnz - ret Sqr32: ; DE = sqrt(HL:DE) ;------------------------------------------------------------------- ; Process the high 16-bits of square using 8-bit registers. This is ; faster and also allows us to clear some registers for the 16-bit ; code later on. ;------------------------------------------------------------------- xor a ; [4] initial remainder ld c, a ; [4] initial root ld b, 4 ; [7] counter call _sqrt8 ; [*] process H ld h, l ; [4] ld b, 4 ; [7] counter call _sqrt8 ; [*] process L ;------------------------------------------------------------------- ; The last iteration of the 8-bit code might carry. It will return ; immediately with the carry flag set if this happens. Here we ; catch and correct for it. ;------------------------------------------------------------------- jr nc, _8bitok ; [12/7] sub c ; [4] remainder > C (bit 8 "set") ccf ; [4] rl h ; [8] adc a, a ; [4] rl h ; [8] ld l, a ; [4] dec hl ; [6] inc c ; [4] dec a ; [4] dec a to allow fall-through... ;------------------------------------------------------------------- ; We are now ready to do process the low 16-bits using 16-bit ; registers. But the registers need a bit of juggling. ;------------------------------------------------------------------- _8bitok: ld l, a ; [4] HL = remainder ld a, e ; [4] ld e, c ; [4] ld c, a ; [4] C = final byte holding location ld a, d ; [4] A = next byte ld d, 0 ; [7] DE = root ld b, 4 ; [4] call _sqrt16 ; [*] ld a, c ; [4] ld b, 4 ; [7] call _sqrt16 ; [*] ret nc ; [11/5] inc e ; [4] ret ; [10] ;------------------------------------------------------------------- ; _sqrt8 - performs the square root whilst the variables are ; restrained to 8 bits (first 16 bits of squared value). ; ; B - counter ; C = root ; A = remainder ; H = input ;------------------------------------------------------------------- _sqrt8: sla c ; [8] root *= 2 sla h ; [8] shift bit into remainder rla ; [4] ret c ; [11/5] can only happen on last iteration. sub c ; [4] remainder -= root jr c, _ltZero8 ; [12/7] jr nz, _gtZero8 ; [12/7] ;------------------------------------------------------------------- ; remainder -= root == 0 ;------------------------------------------------------------------- sla h ; [8] rotate next bit jr c, _gtZero8 + 2 ; [12/7] add a, c ; [4] restore remainder and shift zero. add a, a ; [4] djnz _sqrt8 ; [13/8] rl h ; [8] rotate carry to H after final loop. ret ; [10] ;------------------------------------------------------------------- ; remainder -= root > 0 ;------------------------------------------------------------------- _gtZero8: sla h ; [8] adc a, a ; [4] watch for carry on last iteration dec a ; [4] inc c ; [4] djnz _sqrt8 ; [13/8] rl h ; [8] rotate carry to H after final loop. ret ; [10] ;------------------------------------------------------------------- ; remainder -= root carried: restore remainder and rotate square. ;------------------------------------------------------------------- _ltZero8: add a, c ; [4] sla h ; [8] rla ; [4] djnz _sqrt8 ; [13/8] ret ; [10] ;------------------------------------------------------------------- ; _sqrt16 - performs the square root whilst the variables are ; restrained to 16 bits (last 16 bits of squared value). ; ; B = counter ; DE = root ; A = input byte ; HL = remainder ;------------------------------------------------------------------- _sqrt16: sla e ; [8] root *= 2 rl d ; [8] add a, a ; [4] rotate next bit of square adc hl, hl ; [15] ret c ; [11/5] can only happen on final iteration sbc hl, de ; [11] jr c, _ltZero16 ; [12/7] jr nz, _gtZero16 ; [12/7] ;------------------------------------------------------------------- ; remainder -= root == 0 ;------------------------------------------------------------------- add a, a ; [4] jr c, _gtZero16 +1 ; [12/7] add hl, de ; [11] restore remainder add hl, hl ; [11] and shift zero djnz _sqrt16 ; [13/8] ret ; [10] ;------------------------------------------------------------------- ; remainder -= root > 0 ;------------------------------------------------------------------- _gtZero16: add a, a ; [4] adc hl, hl ; [15] dec hl ; [6] inc e ; [4] djnz _sqrt16 ; [13/8] ret ; [10] ;------------------------------------------------------------------- ; remainder -= root carried: restore remainder and rotate square. ;------------------------------------------------------------------- _ltZero16: add hl, de ; [11] restore remainder add a, a ; [4] adc hl, hl ; [15] djnz _sqrt16 ; [13/8] ret ; [10] .endmodule