; 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