dos_compilers/Zortech C++ v206/SOURCE/CLIB/LMATH.ASM
2024-07-02 07:30:38 -07:00

192 lines
3.2 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;_ lmath.asm Thu Apr 21 1988 Modified by: Walter Bright */
; Copyright (C) 1984-1988 by Walter Bright
; All Rights Reserved
; Written by Walter Bright
include macros.asm
begcode lmath
c_public _LMUL@,_LDIV@,_ULDIV@,_LCMP@
;.386
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Multiply:
; DX,AX = DX,AX * CX,BX
; CX is destroyed
func _LMUL@
if 0
shl ECX,16
mov CX,BX ;ECX = CX,BX
shl EAX,16
shrd EAX,EDX,16 ;EAX = DX,AX
mul ECX
shld EDX,EAX,16 ;DX,AX = EAX
ret
endif
push SI
mov SI,DX ;SI = d
xchg AX,CX ;AX = c, CX = a
tst AX
jz M1
mul CX ;AX = acl
M1: xchg AX,SI ;SI = acl, AX = d
tst AX
jz M2
mul BX ;AX = bdl
add SI,AX ;SI = acl + bdl
M2: mov AX,CX ;AX = a
mul BX ;AX = abl, DX = abh
add DX,SI ;AX = abl, DX = abh + acl + bdl
pop SI
ret
c_endp _LMUL@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Unsigned long divide.
; Input:
; [DX,AX],[CX,BX]
; Output:
; [DX,AX] = [DX,AX] / [CX,BX]
; [CX,BX] = [DX,AX] % [CX,BX]
; SI,DI destroyed
func uldiv
tst DX
jnz D3
;High words are 0, we can use the DIV instruction
div BX
mov BX,DX
mov DX,CX ;DX = CX = 0
ret
D3: ;Divide [DX,AX] by BX
mov CX,AX
mov AX,DX
clr DX
div BX
xchg CX,AX
div BX
;CX,AX = result
;DX = remainder
mov BX,DX
mov DX,CX
clr CX
ret
c_endp uldiv
func _ULDIV@
jcxz uldiv
push BP
;left justify [CX,BX] and leave count of shifts + 1 in BP
mov BP,1 ;at least 1 shift
tst CH ;left justified?
js L1 ;yes
jnz L2
add BP,8
mov CH,CL
mov CL,BH
mov BH,BL
clr BL ;[CX,BX] <<= 8
tst CH
js L1
L2: inc BP ;another shift
shl BX,1
rcl CX,1 ;[CX,BX] <<= 1
jno L2 ;not left justified yet
L1: mov SI,CX
mov DI,BX ;[SI,DI] = divisor
mov CX,DX
mov BX,AX ;[CX,BX] = [DX,AX]
clr AX
cwd ;[DX,AX] = 0
L4: .if SI a CX, L3 ;is [CX,BX] > [SI,DI]?
jb L5 ;definitely less than
.if DI a BX, L3 ;check low order word
L5: sub BX,DI
sbb CX,SI ;[CX,BX] -= [SI,DI]
stc ;rotate in a 1
L3: rcl AX,1
rcl DX,1 ;[DX,AX] = ([DX,AX] << 1) + C
shr SI,1
rcr DI,1 ;[SI,DI] >>= 1
dec BP ;control count
jne L4
pop BP
ret
div0: mov AX,-1
cwd ;quotient is -1
; clr CX
; mov BX,CX ;remainder is 0 (CX and BX already 0)
pop BP
ret
L10: tst CX ;[CX,BX] negative?
jns _ULDIV@ ;no (all is positive)
neg32 CX,BX
callm _ULDIV@
L12: neg32 DX,AX ;quotient is negative
ret
c_endp _ULDIV@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Signed long divide.
; Input:
; [DX,AX],[CX,BX]
; Output:
; [DX,AX] = [DX,AX] / [CX,BX]
; [CX,BX] = [DX,AX] % [CX,BX]
; SI,DI destroyed
func _LDIV@
tst DX ;[DX,AX] negative?
jns L10 ;no
neg32 DX,AX ;[DX,AX] = -[DX,AX]
tst CX ;[CX,BX] negative?
jns L11 ;no
neg32 CX,BX
callm _ULDIV@
neg32 CX,BX ;remainder same sign as DiviDenD
ret
L11: callm _ULDIV@
neg32 CX,BX ;remainder same sign as DiviDenD
jmps L12
c_endp _LDIV@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare [DX,AX] with [CX,BX]
; Signed
func _LCMP@
cmp DX,CX
jne C1
push DX
clr DX
cmp AX,BX
jz C2
ja C3
dec DX
pop DX
ret
C3: inc DX
C2: pop DX
C1: ret
c_endp _LCMP@
endcode lmath
end