;New 32-bit Math routines for the z80 ;by Humberto Yeverino Jr. ;August 22, 1998 ;*** Last updated August 27, 1998 *** ;Questions, bugs... complements, ;e-mail: humberto@engr.csufresno.edu ;TI WebPage: www.engr.csufresno.edu/~humberto/tex.html ;You are free to modify them and use them as you wish. ;be careful though, some routines rely on others. ;the shift routines could be smaller but mul32 and div32 use them ;a lot so I optimized for speed. ;If you find a way to optimize one of these routines e-mail me so I ;can update the file. You will of course get credit. ;NOTE: ;To use these routines you must define 5 areas of memory ;three 4 byte chunks named RegA, RegB, and RegC to be used as registers. ;one 11 byte chunk named StringSpace for creating strings from RegA ;REMEMBER: you don't have to leave this space reserved. Just remember that ;these areas will be written over when you use routines. ;For example, wherever you define StringSpace should be a place for all ;sort s of temorary data. ;Here are all the routines included and what they do. ;ld8A, ld8B, ld8C ;load a register into RegA, RegB, or RegC ;destroys b and hl ;There are a lot of ld instructions but they are cheap on space. ;NOT ALL INSTRUCTIONS ARE IN THIS FILE. ;If you want to add another (ld32C for instance) you'll have to write it ;yourself. (but it's really easy) ;Just make sure you add it to this file, that way it will be faster & smaller ;But if you want to rewrite the IntString routine so that it creates a ;differnt format of string you might want to e-mail me. ;Later I will probably post different IntString routines on my z80 rouine ;page. ;LOAD--------------------------------------------------- ;ld8A, ld8B, ld8C ;load register a into RegA/RegB/RegC ;destroys hl and b ;ld16A, ld16B, ld16C ;load register hl into RegA, RegB, or RegC ;detroys hl and b ;ld32 ;copies memory from hl to de ;detroys b ;ld32A, ld32B ;copies memory from hl to RegA, RegB ;destroys bc, de and hl ;ld32AB, ld32AC, ld32BA, ld32BC ;load RegA with RegB/RegC, load RegB with RegA/RegC ;destroys bc, de and hl ;ADD--------------------------------------------------- ;add32 ;(hl):=(hl)+(de) ;destroys a, b, de and hl ;adc32 ;same as add32 only adds carry flag also ;no register routines are supported for this one because it's likely you ;will never use it. But it takes up no space so.. ;add32A, add32C (you get the idea) ;RegA=RegA+(de) ;destroys a, b, de and hl ;add32AB, add32CB ;RegA=RegA+RegB ;destroys a, b, de and hl ;SUB--------------------------------------------------- ;sub32 ;(hl):=(hl)-(de) ;destroys a, b, de and hl ;sbc32 ;same as sub32 accept with carry ;sub32A ;RegA=RegA-(de) ;destroys a, b, de and hl ;sub32AB ;RegA=RegA-RegB ;destroys a, b, de and hl ;CP---------------------------------------------------- ;cp32 ;compares (hl) to (de) ;destroys a, b, de and hl ;cp32A, cp32B ;compares RegA to (de) ;destroys a, b, de and hl ;cp32AB, cp32AC, cp32BA, cp32BC ;compare RegA to RegB ect. ;destroys a, b, de and hl ;ALL of the shift instructions shift in the carry flag. ;SR---------------------------------------------------- ;sr32 ;shift (hl) right ;destroys hl ;sr32A, sr32B sr32C ;shift RegA right ect. ;destroys hl ;SL---------------------------------------------------- ;sl32 ;shift (hl) left ;destroys hl ;sl32A, sl32B, sl32C ;shift RegA left ect. ;destroys hl ;CLEARREG---------------------------------------------- ;ClearReg ;sets (hl) to 0 ;destroys b and hl ;ClearRegA, ClearRegB, ClearRegC ;sets RegA to 0 ect. ;destroys b and hl ;MUL & DIV--------------------------------------------- ;mul32 ;RegC=RegA*RegB ;destroys a, b, de and hl ;div32 ;RegC=RegA/RegB, RegA=Remainder, RegB preserved ;destroys a, bc, de and hl ;INT TO STRING----------------------------------------- ;IntString32 ;convert 32-bit int in RegA to a string. ;hl->string ;RegC=0, RegA destroyed, RegB preserved. ;destroys a, bc and de ld8A: call ClearRegA ld (RegA),a ret ld8B: ;Required for InString32 call ClearRegB ld (RegB),a ret ld8C: call ClearRegC ld (RegC),a ret ld16A: ld (RegA),hl ld hl,0 ld (RegA+2),hl ret ld16B: ld (RegB),hl ld hl,0 ld (RegB+2),hl ret ld16C: ld (RegC),hl ld hl,0 ld (RegC+2),hl ret ;63 bytes for all ld32 routins ld32AB: ld hl,RegB ld32A: ;Total 9 bytes ld de,RegA ;3 ld32: ld bc,4 ;3 ldir ;2 ret ;1 ld32AC: ;Required for IntString32 ld hl,RegC jr ld32A ld32B: ld de,RegB jr ld32 ld32BA: ld hl,RegA jr ld32B ld32BC: ld hl,RegC jr ld32B add32AB: ;Total 16 bytes ld de,RegB ;3 add32A: ld hl,RegA ;3 add32: or a adc32: ld b,4 ;2 add32Loop: ld a,(de) ;1 adc a,(hl) ;1 ld (hl),a ;1 inc hl ;1 inc de ;1 djnz add32Loop ;2 ret ;1 add32C: ;Total 8 bytes ld hl,RegC ;3 jr add32 add32CB: ;Required for mul32 ld de,RegB ;3 jr add32C sub32AB: ;Required for div32 ;IN = RegA, RegB ;OUT = RegA=RegA-RegB ld hl,RegB ;3 sub32A: ld de,RegA ;3 sub32: ;Total 10 bytes or a sbc32: ld b,4 ;2 sub32Loop: ld a,(de) ;1 sbc a,(hl) ;1 ld (de),a ;1 inc de ;1 inc hl ;1 djnz sub32Loop ;2 ret ;1 cp32AB: ;Required for div32 ld hl,RegB+3 cp32A: ld de,RegA+3 cp32: ld b,4 cp32Loop: ld a,(de) cp (hl) ;(hl)-(de) c-hl=de, z-hl=de, nz-hl!=de ret nz ;(hl)!=(de) then done dec hl dec de ;try next bytes djnz cp32Loop cp32Done: ret cp32AC: ld hl,RegC+3 jr cp32A cp32B: ld de,RegB+3 jr cp32 cp32BA: ld hl,RegA+3 jr cp32B cp32BC: ;Required for div32 ld hl,RegC+3 jr cp32B sr32A: ;15 98 Required for mul32 ld hl,RegA+3 ;3 10 sr32: ;12 88 rr (hl) ;2 15 dec hl ;1 6 rr (hl) ;2 15 dec hl ;1 6 rr (hl) ;2 15 dec hl ;1 6 rr (hl) ;2 15 ret ;1 10 sr32B: ;5 110 Required for div32 ld hl,RegB+3 jr sr32 sr32C: ld hl,RegC+3 jr sr32 sl32A: ;15 98 (hl):=(hl)*2 ld hl,RegA sl32: ;12 88 rl (hl) ;2 15 rotate inc hl ;1 6 next byte rl (hl) inc hl rl (hl) inc hl rl (hl) ret sl32B: ;5 110 Required for mul32 and div32 ld hl,RegB ;3 10 jr sl32 ;2 12 sl32C: ;Required for div32 ld hl,RegC jr sl32 ClearRegA: ;Total 11 bytes ld hl,RegA ;3 ClearReg: ;Total 8 bytes ld b,4 ;2 ClearRegLoop: ld (hl),0 ;2 inc hl ;1 djnz ClearRegLoop ;2 ret ;1 ClearRegB: ld hl,RegB jr ClearReg ClearRegC: ;Required for mul32 ld hl,RegC jr ClearReg mul32: call ClearRegC ld b,32 mul32Loop: push bc call sr32A ;3 push least sig bit of RegA into carry jr nc,mul32NoAdd ;2 if carry=0 goto NoAdd call add32CB ;3 RegC=RegC+RegB mul32NoAdd: call sl32B ;3 RegB=RegB*2 pop bc djnz mul32Loop ret div32: ;Total 38 bytes Required for IntString32 call ClearRegC call cp32BC ret z ;check if b=0 ld c,1 ;2 or a ;1 carry=0 div32Loop: ld a,(RegB+3) ;3 13 bit 7,a ;2 8 Test Most sig bit of RegB jr nz,div32Loop2 ;2 7 if it's 1 goto div32Ready else inc c ;1 4 inc c call sl32B ;3 127 shift RegB left jr div32Loop ;2 12 loop time=171 div32Loop2: call cp32AB ;3 jr c,div32NoSub ;2 if RegA