; 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, ReferVar wrgGMPartProd, 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