campo-sirio/gfm/mul10ad.asm
alex ba237a9d91 Patch level : no patch
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
Aggiunti i sorgenti per Greenleaf Math Library (gfm.dll)


git-svn-id: svn://10.65.10.50/trunk@10079 c028cbd2-c16b-5b4b-a496-9718f37d4682
2002-02-26 12:19:02 +00:00

323 lines
8.7 KiB
NASM
Executable File

; int _MulUnsArrP10AndAddInt(pa,c);
;
; ARGUMENT
; unsigned *pa points to a pa[5], or 80-bit number
; int c # to add after mult by 10
;
; DESCRIPTION
; multiplies the number (<=80-bits) in the int array by decimal 10
; and adds 'c' to it. Used in the divide routines for adjusting
; the result.
;
; SIDE EFFECTS
; The value in the source array is indeterminate on overflow.
;
; RETURNS
; Returns GM_OVERFLOW on overflow, otherwise GM_SUCCESS.
;
; AUTHOR
; Andy Anderson 27-JUL-87 80-bit
; Copyright (C) 1987-90 Greenleaf Software Inc. All Rights Reserved.
;
; MODIFICATIONS
;
;
.SFCOND
include model.h
include prologue.h
include gm.equ
ReferVar wGMTemp1,<cWord>
ReferVar wrgGMPartProd,<cWord>
dseg _gm
endds
pseg gmath
;
; if large memory model then:
;
; parm1_ = ptr to source 1
; parm3_ = number to add to a*10
;
; for if small model then
; parm1_ = ptr to source1
; parm2_ = number to add to result of a * 10
;
cproc _MulUnsArrP10AndAddInt,,_mul10ad
if _LDATA
push ds
push es
lds si,parm1_ ; ptr to dst (=src)
else
mov si,parm1_
endif
;
; to multiply by 10, we mult by 4 using 2 shifts, add the
; original number making 5 times the original, then multiply
; that by 2 giving a multiplication by 10. This is many times
; FASTER than the mul instruction!!!
;
mov ax,[si+8] ; get msd for possible overflow
cmp ax,3000h ; overflow if sign sets during the
jl nxt ; first shift set
jmp overf
nxt: cmp ax,0bffh ; if < this, no overflow possible
jl ct ; no possibility of overflow
jmp tstover ; further testing needed
ct: xor ax,ax ; start clear for test
mov bx,8 ; offset to last int
mov cx,5 ; max number of ints in 80-bit value
numints:
or ax,[bx+si] ; see if upper 80 bits are set
jnz gotdig ; and stop when first one seen
dec bx
dec bx
loop numints ; if we find all of them zero
if _LDATA
mov ax,parm3_
else
mov ax,parm2_
endif
mov [si],ax ; just put it in low-order word
jmp gexit
gotdig:
ifdef DSNOTHING
push ds
mov ax, seg wGMTemp1
mov ds,ax
mov wGMTemp1,cx ; save # of digits in source
pop ds
else
mov wGMTemp1,cx ; save # of digits in source
endif
;
; then shift the number of ints figured for each loop
;
ifdef DSNOTHING
mov ax, seg wrgGMPartProd
mov es,ax
endif
lea di,wrgGMPartProd ; ptr to work area
xor bx,bx
mov dx,bx
shlp:
mov ax,[bx+si] ; do 16-bits at a time
clc
rcl dx,1 ; dummy first time thru
rcl ax,1 ; multiply by 2
rcl dx,1 ; save carry in dh (d1-d0)
rcl ax,1 ; now original * 4
rcl dx,1 ; and dx has shifted out bits
ifdef DSNOTHING
mov es:[bx+di],ax ; store temp result
else
mov [bx+di],ax ; store temp result
endif
ror dx,1
ror dx,1
inc bx
inc bx
loop shlp
;
; if we have bits shifted out into dx left over, then
; we have gained 1 int. This is overflow if we were already
; doing 5 int's!
;
or dx,0000h ; was max size number, if dx!=0
jz addin ; no bits shifted into carry
ifdef DSNOTHING
push ds
mov ax,seg wGMTemp1
mov ds,ax
inc wGMTemp1 ; otherwise, one more int in number
pop ds
else
inc wGMTemp1 ; otherwise, one more int in number
endif
rol dx,1 ; bits to low-order of next msd
rol dx,1 ; in lifo order
ifdef DSNOTHING
mov es:[bx+di],dx
else
mov [bx+di],dx
endif
;
; Then add the original for sum of 5 X original
;
addin: xor bx,bx
mov dx,bx
ifdef DSNOTHING
push ds
mov ax, seg wGMTemp1
mov ds,ax
mov cx,wGMTemp1 ; k int's in new number
pop ds
else
mov cx,wGMTemp1 ; k int's in new number
endif
clc
if _LDATA
les di,parm1_
else
mov di,parm1_
endif
ifdef DSNOTHING
mov ds,ax ; scrap old DS, get global one
endif
lea si,wrgGMPartProd
addlp:
if _LDATA
mov ax,[bx+si] ; do 16-bits at a time
adc es:[bx+di],ax
else
mov ax,[bx+si] ; do 16-bits at a time
adc [bx+di],ax
endif
inc bx
inc bx
loop addlp
; stop as soon as we get an overflow
rcl dx,1 ; save possible overflow
or dx,0000h ; see if bits left over
jz finshft ; no possible overflow or increase
inc wGMTemp1
if _LDATA
add es:[bx+di],dx
else
add [bx+di],dx
endif
jno finshft ; if sign-bit or carry didn't set: continue
xor dx,dx
inc dx
if _LDATA
mov es:[bx+di+2],dx
else
mov [bx+di+2],dx
endif
inc wGMTemp1 ; increase number of digits in dst
finshft:
xor bx,bx
mov dx,bx
mov cx,wGMTemp1 ; number of int's to shift
if _LDATA
lds si,parm1_
else
mov si,parm1_
endif
shlp3:
rcl Word Ptr [bx+si],1 ; multiply by 2= times 10
inc bx
inc bx
loop shlp3
;
; high-order bit of int 10 can't be set either
;
rcl dx,1 ; save carry bit
or dx,0000h ; was max size number, if dx!=0
jz cout ; no bits shifted into carry
ifdef DSNOTHING
push ds
mov ax,seg wGMTemp1
mov ds,ax
inc wGMTemp1 ; otherwise, one more int in number
cmp wGMTemp1,5 ; if working with 5-int number
pop ds
else
inc wGMTemp1 ; otherwise, one more int in number
cmp wGMTemp1,5 ; if working with 5-int number
endif
jg overf ;overflow: too many digits
mov [bx+si],dx
;
; If no overflow, see if we have mult'd # times requested
;
cout:
test [si+8],8000h ; see if high-order word set sign
jnz overf
xor bx,bx ; clear flags
mov dx,bx
ifdef DSNOTHING
push ds ; save parm1's DS and switch
mov ax,seg wGMTemp1
mov ds,ax ; to global's DS
mov cx,wGMTemp1
pop ds ; then back to parm's DS
else
mov cx,wGMTemp1
endif
if _LDATA
mov ax, Word Ptr parm3_
else
mov ax, Word Ptr parm2_ ; get addend
endif
aloop:
adc [bx+si],ax
mov ax,dx
inc bx
inc bx
loop aloop
rcl dx,1 ; save carry bit
or dx,0000h ; was max size number, if dx!=0
jz nout ; no bits shifted into carry
ifdef DSNOTHING
push ds ; save parm1's DS and switch
mov ax, seg wGMTemp1
mov ds,ax ; to global's DS
inc wGMTemp1 ; otherwise, one more int in number
cmp wGMTemp1,5 ; if working with 5-int number
pop ds
else
inc wGMTemp1 ; otherwise, one more int in number
cmp wGMTemp1,5 ; if working with 5-int number
endif
jg overf ;overflow: too many digits
mov [bx+si],dx
;
; If no overflow, see if we have mult'd # times requested
;
nout:
test [si+8],8000h ; see if high-order word set sign
jnz overf
gexit:
mov ax,GM_SUCCESS
exit:
if _LDATA
pop es
pop ds
endif
cproce
overf:
mov ax,GM_OVERFLOW ; here only on overflow
jmp short exit
;
; if the msd > 0ccch, or if = 0ccch and the high-order hex
; digit of msd -1 > hex c then overflow will occur, otherwise
; it won't
;
tstover:
cmp ax,0ccch ; overflow if sign sets during the
jg overf
jmp ct ; no overflow possible
endps
END