96 lines
2.3 KiB
ArmAsm
96 lines
2.3 KiB
ArmAsm
.define .mli
|
|
.sect .text
|
|
.sect .rom
|
|
.sect .data
|
|
.sect .bss
|
|
|
|
! signed long mulitply
|
|
!-----------------------------------------------------------------------------
|
|
! rewritten by Kai-Uwe Bloem (i5110401@dbstu1.bitnet) for speed.
|
|
! #1 01/12/90 initial revision
|
|
!-----------------------------------------------------------------------------
|
|
! 3 cases worth to recognize :
|
|
! 1) both the upper word of u and v are zero
|
|
! => 1 mult : Low*Low
|
|
! 2) only one of the upper words is zero
|
|
! => 2 mult : Low*HighLow
|
|
! 3) both upper words are not zero
|
|
! => 4 mult : HighLow*HighLow
|
|
! there are other cases (e.g. lower word is zero but high word is not, or
|
|
! one operand is all zero). However, this seems not to be very common, so
|
|
! they are ignored for the price of superfluous multiplications in these
|
|
! cases.
|
|
!-----------------------------------------------------------------------------
|
|
|
|
! entry : d0 multiplicand
|
|
! d1 multiplier
|
|
! exit : d0 high order result
|
|
! d1 low order result
|
|
! d2,a0,a1 : destroyed
|
|
|
|
.sect .text
|
|
.mli:
|
|
move.l (sp)+,a1 ! return address
|
|
move.l d3,a0 ! save register
|
|
movem.w (sp)+,d0-d3 ! get v and u
|
|
move.w d5,-(sp) ! save sign register
|
|
move.w d2,d5
|
|
bge 0f ! negate u if neccessary
|
|
neg.w d1
|
|
negx.w d0
|
|
0: tst.w d0
|
|
bge 0f ! negate v if neccessary
|
|
eor.w d0,d5
|
|
neg.w d1
|
|
negx.w d0
|
|
0: bne 1f ! case 2) or 3)
|
|
tst.w d2
|
|
bne 2f ! case 2)
|
|
! === case 1: _l x _l ===
|
|
mulu d3,d1 ! r.l = u.l x v.l
|
|
9: ! (r.h is already zero)
|
|
tst.w d5 ! negate result if neccessary
|
|
bpl 0f
|
|
neg.l d1
|
|
negx.l d0
|
|
0: move.w (sp)+,d5 ! return
|
|
move.l a0,d3
|
|
jmp (a1)
|
|
! === possibly case 2) or case 3) ===
|
|
1:
|
|
tst.w d2
|
|
bne 3f ! case 3)
|
|
! === case 2: _l x hl ===
|
|
exg d0,d2 ! exchange u and v
|
|
exg d1,d3 ! (minimizes number of distinct cases)
|
|
2:
|
|
mulu d1,d2 ! a = v.l x u.h
|
|
mulu d3,d1 ! r.l = v.l x u.l
|
|
swap d2 ! a = a << 16
|
|
clr.l d3
|
|
move.w d2,d3
|
|
clr.w d2
|
|
add.l d2,d1 ! r += a
|
|
addx.l d3,d0
|
|
bra 9b
|
|
! === case 3: hl x hl ===
|
|
3:
|
|
move.l d4,-(sp) ! need more registers
|
|
move.w d2,d4
|
|
mulu d1,d4 ! a = v.l x u.h
|
|
mulu d3,d1 ! r.l = u.l x v.l
|
|
mulu d0,d3 ! b = v.h x u.l
|
|
mulu d2,d0 ! r.h = u.h x v.h
|
|
swap d1 ! (just for simplicity)
|
|
add.w d4,d1 ! r += a << 16
|
|
clr.w d4
|
|
swap d4
|
|
addx.l d4,d0
|
|
add.w d3,d1 ! r += b << 16
|
|
clr.w d3
|
|
swap d3
|
|
addx.l d3,d0
|
|
swap d1
|
|
move.l (sp)+,d4 ! return
|
|
bra 9b
|