home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d169
/
src
/
dres
/
notinlib
/
muldiv.asm
< prev
Wrap
Assembly Source File
|
1988-11-22
|
5KB
|
211 lines
;FUNC= MulDiv D0/D1/D2
;FUNC= UMulDiv D0/D1/D2
;FUNC= MulShift D0/D1/D2
;FUNC= UMulShift D0/D1/D2
; MulDiv (a ,b ,c) 32x32->64 64/32->32 (signed)
; MulShift(a ,b ,n) 32x32->64 64>>n->32 (signed)
; D0,D1,D2
;
; 32x32->64 64/32->32
; 32x32->64 64>>n->32
;
; note: n is a word
public _MulDiv
public _UMulDiv
public _MulShift
public _UMulShift
; Various connotations specifying which arguments are
; unsigned (you gain a bit when using unsigned arguments)
REGS eqr D2-D7
_UMulDiv movem.l REGS,-(sp)
clr.w D7
bra .md10
_MulDiv movem.l REGS,-(sp)
clr.w D7
tst.l D0
bpl .md2
neg.l D0
tst.l D1 ; neg
bpl .md1 ; neg
neg.l D1
tst.l D2 ; neg neg
bpl .md10 ; neg neg
neg.l D2
bra .md9 ; neg neg neg
.md1 tst.l D2 ; neg
bpl .md9 ; neg
neg.l D2
bra .md10 ; neg neg
.md2 tst.l D1
bpl .md3
neg.l D1
tst.l D2 ; neg
bpl .md9 ; neg
neg.l D2
bra .md10 ; neg neg
.md3 tst.l D2
bpl .md10
neg.l D2
bra .md9
_UMulShift movem.l REGS,-(sp)
clr.w D7
bra .md6
_MulShift movem.l REGS,-(sp)
clr.w D7
tst.l D0
bpl .md4
neg.l D0
tst.l D1
bpl .md5
neg.l D0
bra .md6
.md4 tst.l D1
bpl .md6
neg.l D1
.md5 addq.w #1,D7
.md6 swap D0
swap D1
tst.w D0
beq .md601
bsr .md0huge
beq .md602a
bra .md603
.md601 tst.w D1
beq .md602
bsr .md1huge
beq .md602a
bra .md603
.md602 swap D0
swap D1
mulu D1,D0
.md602a lsr.l D2,D0
bra .mddone
.md603 subq.w #1,D2
bmi .mddone
.md604 lsr.l #1,D3
roxr.l #1,D0
dbf D2,.md604
bra .mddone
.md10 swap D0
swap D1
tst.w D0
beq .md101
bsr .md0huge
beq .mdsdiv
bsr div64
bra .mddone
.md101 tst.w D1
beq .md105
bsr .md1huge
beq .mdsdiv
bsr div64
bra .mddone
.md105 swap D0 ; both word sized
swap D1
mulu D1,D0 ; D1.WxD0.W -> D0.L
.mdsdiv move.l D2,D1
jsr .divu#
;
;
.md9 addq.w #1,D7
; All elements now unsigned, D7.W determines whether to
; negate at end.
.mddone btst.l #0,D7
beq .mddone2
neg.l D0
.mddone2 movem.l (sp)+,REGS
rts
; NOTE: entered with register halves reversed
;
; D2 not effected
; Test D3 on return
.md0huge tst.w D1
beq .md1hugex ; D0.L, D1.W
; D0.L, D1.L (long x long)
move.w D0,D4 ; save ah
move.w D0,D3 ; ah bh
mulu.w D1,D3
swap D0 ; al bh
move.w D0,D5
mulu.w D1,D5
swap D1
mulu.w D1,D0 ; al bl
mulu.w D4,D1 ; ah bl
add.l D1,D5 ; combine blah and bhal
bcc .mud1
add.l #$10000,D3
.mud1 swap D0 ; LSB MSB
add.w D5,D0
swap D0
clr.w D5
swap D5
addx.l D5,D3 ;64 bit mul result: D3|D0
rts ;Test D3
; D2 not effected
.md1huge exg D0,D1
.md1hugex
; D0.L, D1.W al ah
; bl
move.w D0,D3
mulu.w D1,D3 ; D3 = bl x ah
swap D0
mulu.w D1,D0 ; D0 = bl x al
swap D0 ; add lsb byte of D3 to msb byte of D0
add.w D3,D0
swap D0
clr.w D3 ; doesn't effect X
swap D3 ; msb of D3 actually lsb of second longword
moveq.l #0,D1
addx D1,D3 ; possible x(carry) from previous addition
; 64 bit mul result: D3|D0
; Test D3
rts
; DIV64
;
; 64/32->32 D3|D0 / D2 -> D0
div64:
move.l #0,A0 ;Divide! D1 into D3|D0, D2 = cntr, A0 = rslt
move.w #31,D2 ;(no initial compare). 31 + 1 iterations
.mud10 adda.l A0,A0 ;shift result left
asl.l #1,D0 ;Shift left
roxl.l #1,D3
cmp.l D1,D3
blo .mud11 ;if D3 < D1, skip
sub.l D1,D3 ; D3 >= D1
addq.l #1,A0 ;result = result | 1
.mud11 dbf D2,.mud10
; If remainder (D3) larger than 1/2 C (D1 >> 1), then
; round up result.
lsr.l #1,D1
cmp.l D1,D3
blo .mud12 ; skip if remainder < 1/2C
addq.l #1,A0
.mud12
move.l A0,D0 ;return result
rts