home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari FTP
/
ATARI_FTP_0693.zip
/
ATARI_FTP_0693
/
Mint
/
mntlib25.zoo
/
sozobon
/
sozolong.s
< prev
next >
Wrap
Text File
|
1992-05-15
|
3KB
|
118 lines
; long arithmetic routines
;
; written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
;
; Names changed and converted from MIT to Motorola syntax by Dave Gymer for SC
;
; 5/5/92 sb -- separated unsigned routines to sozulong.s to reduce library drag
.text
.even
.globl lmul
.globl ldiv
.globl lrem
ldiv:
move.l d2,a0 ; save registers
move.l d3,a1
clr.w -(sp) ; sign flag
clr.l d0 ; prepare result
move.l 10(sp),d2 ; get divisor
beq L9 ; divisor = 0 causes a division trap
bpl J0 ; divisor < 0 ?
neg.l d2 ; negate it
not.w (sp) ; remember sign
J0: move.l 6(sp),d1 ; get dividend
bpl J1 ; dividend < 0 ?
neg.l d1 ; negate it
not.w (sp) ; remember sign
J1:
;== case 1) divident < divisor
cmp.l d2,d1 ; is divident smaller then divisor ?
bcs L8 ; yes, return immediately
;== case 2) divisor has <= 16 significant bits
tst.w 10(sp)
bne L2 ; divisor has only 16 bits
move.w d1,d3 ; save dividend
clr.w d1 ; divide dvd.h by dvs
swap d1
beq J2 ; (no division necessary if dividend zero)
divu d2,d1
J2: move.w d1,d0 ; save quotient.h
swap d0
move.w d3,d1 ; (d0.h = remainder of prev divu)
divu d2,d1 ; divide dvd.l by dvs
move.w d1,d0 ; save quotient.l
clr.w d1 ; get remainder
swap d1
bra L8 ; and return
;== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
L2:
moveq #31,d3 ; loop count
L3:
add.l d1,d1 ; shift divident ...
addx.l d0,d0 ; ... into d0
cmp.l d2,d0 ; compare with divisor
bcs J3
sub.l d2,d0 ; big enough, subtract
add.w #1,d1 ; and note bit into result
J3:
dbra d3,L3
exg d0,d1 ; put quotient and remainder in their registers
L8:
tst.w 6(sp) ; must the remainder be corrected ?
bpl J4
neg.l d1 ; yes, apply sign
; the following line would be correct if modulus is defined as in algebra
; add.l 6(sp),d1 ; algebraic correction: modulus can only be >= 0
J4: tst.w (sp)+ ; result should be negative ?
bpl J5
neg.l d0 ; yes, negate it
J5:
move.l a1,d3
move.l a0,d2
rts
L9:
divu d2,d1 ; cause division trap
bra L8 ; back to user
lrem:
move.l 8(sp),-(sp) ; push divisor
move.l 8(sp),-(sp) ; push dividend
bsr ldiv
lea 8(sp),sp
move.l d1,d0 ; return the remainder in d0
rts
lmul:
move.l d2,a0 ; save registers
move.l d3,a1
movem.w 4(sp),d0-d3 ; get the two longs. u = d0-d1, v = d2-d3
move.w d0,-(sp) ; sign flag
bpl J6 ; is u negative ?
neg.w d1 ; yes, force it positive
negx.w d0
J6: tst.w d2 ; is v negative ?
bpl J7
neg.w d3 ; yes, force it positive ...
negx.w d2
not.w (sp) ; ... and modify flag word
J7:
ext.l d0 ; u.h <> 0 ?
beq M1
mulu d3,d0 ; r = v.l * u.h
M1: tst.w d2 ; v.h <> 0 ?
beq M2
mulu d1,d2 ; r += v.h * u.l
add.w d2,d0
M2: swap d0
clr.w d0
mulu d3,d1 ; r += v.l * u.l
add.l d1,d0
move.l a1,d3
move.l a0,d2
tst.w (sp)+ ; should the result be negated ?
bpl M3 ; no, just return
neg.l d0 ; else r = -r
M3: rts