;=================================================================
;
; Copyright (c) Microsoft Corporation 1999 - All Rights Reserved.
;
;=================================================================

	.486
	.model	flat, c
;	OPTION	PROC:PRIVATE		; only public procs explicitly
	OPTION	CASEMAP:NONE		; mixed case allowed for C compatibility
	OPTION	SCOPED			; labels are local inside PROCs
	OPTION	EXPR32			; 32-bit expression word size

.DATA


.CODE

include grf.inc

OPTION PROLOGUE:    NONE
OPTION EPILOGUE:    NONE

; 75% of divisions are for scan lines are under 8 pixels, so special case the division
IntegerDivide proc C N:SDWORD, D:SDWORD

Numerator equ [esp+4]
Denominator equ [esp+8]

    mov     ecx,Denominator
    mov     eax,Numerator

    cmp ecx,1   ; most common case
    jne @F
    ret             ; eax already has return value

@@:
    cmp ecx,2   ; next most common case
    jne @F
    sar eax,1
    ret
@@:
    cmp ecx,0   ; not going to handle negatives...
    jl  @F
    cmp ecx,8
    jg  @F

    jmp DivTable[ecx*4]

@@:
; uncomment these for more power of 2 handling. or do a fast count bits so can use lookup table
;    cmp ecx,16
;    je  DivBy16
;    cmp ecx,32
;    je  DivBy32
;
;    cmp ecx,64
;    je  DivBy64
;
;    cmp ecx,128
;    je  DivBy128
;
;    cmp ecx,256
;    je  DivBy256
;
;    cmp ecx,512
;    je  DivBy512

HandleDefault:

    mov edx,eax
    sar edx,31  ; sign extend for division
    idiv ecx
done:
    ret

; todo: handle overflow where multiply below.  if mul by r32, then
; overflow will automatically go into edx (ie. result in edx:eax).
; then need to shift double (shrd)

DivByZero:
    int 3
    jmp HandleDefault; generate the exception so don't ship with bug
    ret
DivBy1:
    ret
DivBy2:
    sar eax,1
    ret
DivBy3: ;return (N*43)>>7;  // 43/128 = 0.3359, error = 0.0026
    imul    eax,43
    sar eax,7
    ret
DivBy4:
    sar eax,2
    ret
DivBy5: ;    return (N*26)>>7;  // 26/128 = .203125, error = .003125
    imul    eax,26
    sar eax,7
    ret
DivBy6: ; return (N*21)>>7;  // 21/128 = .1640625, error = .0026
    imul    eax,21
    sar eax,7
    ret
DivBy7: ; return (N*18)>>7;  // 18/128 = .140625, error = .002232
    imul    eax,18
    sar     eax,7
    ret
DivBy8:
    sar     eax,3
    ret
DivBy16:
    sar     eax,4
    ret
DivBy32:
    sar     eax,5
    ret
DivBy64:
    sar     eax,6
    ret
DivBy128:
    sar     eax,7
    ret
DivBy256:
    sar     eax,8
    ret
DivBy512:
    sar     eax,9
    ret

DivTable    dd  DivByZero,DivBy1,DivBy2,DivBy3,DivBy4,DivBy5,DivBy6,DivBy7,DivBy8
    
IntegerDivide endp


OPTION PROLOGUE:    PrologueDef
OPTION EPILOGUE:    EpilogueDef

END