You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
387 lines
12 KiB
387 lines
12 KiB
dnl----------------------------------------------------------------------------
|
|
dnl
|
|
dnl x86 assembly code generating macros for attribute handlers.
|
|
dnl
|
|
dnl Copyright (C) Microsoft Corporation, 1997.
|
|
dnl
|
|
dnl----------------------------------------------------------------------------
|
|
dnl
|
|
dnl d_AddAttrsCode
|
|
dnl
|
|
dnl Macro to generate fld/fadd/fstp for each argument with
|
|
dnl pipelining across all arguments.
|
|
dnl Achieves complete pipelining with four arguments, so
|
|
dnl care should be taken to batch up at least four things.
|
|
dnl A max of seven things should be added to avoid FP stack overflow.
|
|
dnl
|
|
define(`d_AddAttrsCodeLoop',
|
|
` fld DWORD PTR [ecx+d_Nth1($1, d_shift(d_shift($@)))]
|
|
fadd DWORD PTR [edx+d_Nth1($1, d_shift(d_shift($@)))]
|
|
ifelse(eval($2 > 1), `1',
|
|
`d_AddAttrsCodeLoop(incr($1), decr($2), d_shift(d_shift($@)))')dnl
|
|
ifelse(eval($1 > $2), `1',
|
|
` fxch st(eval($1 - $2))
|
|
')dnl
|
|
fstp DWORD PTR [ecx+d_Nth1($2, d_shift(d_shift($@)))]
|
|
')dnl
|
|
define(`d_AddAttrsCode', `d_AddAttrsCodeLoop(`1', $#, $@)')dnl
|
|
dnl
|
|
dnl d_AddScaledAttrsCode
|
|
dnl
|
|
dnl Macro to generate fld/fmul/fadd/fstp for each argument with
|
|
dnl pipelining across all arguments.
|
|
dnl Achieves complete pipelining with four arguments, so
|
|
dnl care should be taken to batch up at least four things.
|
|
dnl A max of seven things should be added to avoid FP stack overflow.
|
|
dnl
|
|
define(`d_AddScaledAttrsLoadLoop',
|
|
` fld DWORD PTR [edx+d_Nth1($1, d_shift(d_shift($@)))]
|
|
fmul fScaleVal
|
|
ifelse(eval($2 > 1), `1',
|
|
`d_AddScaledAttrsLoadLoop(incr($1), decr($2), d_shift(d_shift($@)))')dnl
|
|
ifelse(eval($1 > 1), `1',
|
|
` fxch st(decr($1))
|
|
',
|
|
` fxch st(decr($2))
|
|
')dnl
|
|
fld DWORD PTR [ecx+d_Nth1($2, d_shift(d_shift($@)))]
|
|
faddp st(1), st(0)
|
|
')dnl
|
|
define(`d_AddScaledAttrsStoreLoop',
|
|
`ifelse(eval($2 > 1), `1',
|
|
`d_AddScaledAttrsStoreLoop(incr($1), decr($2), d_shift(d_shift($@)))')dnl
|
|
ifelse(eval($1 > $2), `1',
|
|
` fxch st(eval($1 - $2))
|
|
')dnl
|
|
ifelse($1, `1',
|
|
` fxch st(1)
|
|
')dnl
|
|
fstp DWORD PTR [ecx+d_Nth1($2, d_shift(d_shift($@)))]
|
|
')dnl
|
|
define(`d_AddScaledAttrsCode',
|
|
`d_AddScaledAttrsLoadLoop(`1', $#, $@)dnl
|
|
d_AddScaledAttrsStoreLoop(`0', $#, $@)')dnl
|
|
dnl
|
|
dnl d_AddFloatAttrsBody
|
|
dnl
|
|
dnl Generates the body of an FP attribute adder routine.
|
|
dnl Attributes are processed in cache order as much as possible.
|
|
dnl
|
|
dnl $1 is one of Z_Diff, Z_Diff_Spec, Z_Diff_Tex1, Z_Diff_Spec_Tex1,
|
|
dnl Z_Tex1_Tex2, Z_DIdx, Z_DIdx_Tex1, Z_Tex1.
|
|
dnl
|
|
define(`d_AddFloatAttrsBody',
|
|
`
|
|
; Add surface pointers.
|
|
mov eax, [edx+ATTRSET_ipSurface]
|
|
add eax, [ecx+ATTRSET_pSurface]
|
|
mov [ecx+ATTRSET_pSurface], eax
|
|
mov eax, [edx+ATTRSET_ipZ]
|
|
add eax, [ecx+ATTRSET_pZ]
|
|
mov [ecx+ATTRSET_pZ], eax
|
|
|
|
; Do FP additions.
|
|
ifelse(`$1', `Z_Diff',
|
|
`d_AddAttrsCode(`ATTRSET_fZ', `ATTRSET_fB',
|
|
`ATTRSET_fG', `ATTRSET_fR',
|
|
`ATTRSET_fA')dnl
|
|
')dnl
|
|
ifelse(`$1', `Z_Diff_Spec',
|
|
`d_AddAttrsCode(`ATTRSET_fZ', `ATTRSET_fB',
|
|
`ATTRSET_fG', `ATTRSET_fR')dnl
|
|
d_AddAttrsCode(`ATTRSET_fA', `ATTRSET_fBS',
|
|
`ATTRSET_fGS', `ATTRSET_fRS')dnl
|
|
')dnl
|
|
ifelse(`$1', `Z_Diff_Tex1',
|
|
`d_AddAttrsCode(`ATTRSET_fZ', `ATTRSET_fOoW',
|
|
`ATTRSET_fUoW1', `ATTRSET_fVoW1')dnl
|
|
d_AddAttrsCode(`ATTRSET_fB', `ATTRSET_fG',
|
|
`ATTRSET_fR', `ATTRSET_fA')dnl
|
|
')dnl
|
|
ifelse(`$1', `Z_Diff_Spec_Tex1',
|
|
`d_AddAttrsCode(`ATTRSET_fZ', `ATTRSET_fOoW',
|
|
`ATTRSET_fUoW1', `ATTRSET_fVoW1',
|
|
`ATTRSET_fB')dnl
|
|
d_AddAttrsCode(`ATTRSET_fG', `ATTRSET_fR',
|
|
`ATTRSET_fA', `ATTRSET_fBS',
|
|
`ATTRSET_fGS', `ATTRSET_fRS')dnl
|
|
')dnl
|
|
ifelse(`$1', `Z_Tex1_Tex2',
|
|
`d_AddAttrsCode(`ATTRSET_fZ', `ATTRSET_fOoW',
|
|
`ATTRSET_fUoW1', `ATTRSET_fVoW1',
|
|
`ATTRSET_fUoW2', `ATTRSET_fVoW2')dnl
|
|
')dnl
|
|
ifelse(`$1', `Z_DIdx',
|
|
`d_AddAttrsCode(`ATTRSET_fZ',
|
|
`ATTRSET_fDIdx', `ATTRSET_fDIdxA')dnl
|
|
')dnl
|
|
ifelse(`$1', `Z_DIdx_Tex1',
|
|
`d_AddAttrsCode(`ATTRSET_fZ', `ATTRSET_fOoW',
|
|
`ATTRSET_fUoW1', `ATTRSET_fVoW1',
|
|
`ATTRSET_fDIdx', `ATTRSET_fDIdxA')dnl
|
|
')dnl
|
|
ifelse(`$1', `Z_Tex1',
|
|
`d_AddAttrsCode(`ATTRSET_fZ', `ATTRSET_fOoW',
|
|
`ATTRSET_fUoW1', `ATTRSET_fVoW1')dnl
|
|
')dnl
|
|
')dnl
|
|
dnl
|
|
dnl d_AddFixedAttrsBody
|
|
dnl
|
|
dnl Generates the body of a fixed attribute adder routine.
|
|
dnl Attributes are processed in cache order as much as possible.
|
|
dnl
|
|
dnl $1 contains substrings Z, Diff, Spec, DIdx, Tex1 and Tex2 in any mix.
|
|
dnl
|
|
define(`d_AddFixedAttrsBody',
|
|
`
|
|
; Add surface pointers.
|
|
mov eax, [edx+ATTRSET_ipSurface]
|
|
add eax, [ecx+ATTRSET_pSurface]
|
|
mov [ecx+ATTRSET_pSurface], eax
|
|
mov eax, [edx+ATTRSET_ipZ]
|
|
add eax, [ecx+ATTRSET_pZ]
|
|
mov [ecx+ATTRSET_pZ], eax
|
|
|
|
; Add attributes.
|
|
ifelse(eval(d_index(`$1', `Z') >= 0), `1',
|
|
`
|
|
mov eax, [edx+ATTRSET_iZ]
|
|
add eax, [ecx+ATTRSET_iZ]
|
|
mov [ecx+ATTRSET_iZ], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Tex') >= 0), `1',
|
|
`
|
|
mov eax, [edx+ATTRSET_iOoW]
|
|
add eax, [ecx+ATTRSET_iOoW]
|
|
mov [ecx+ATTRSET_iOoW], eax
|
|
|
|
mov eax, [edx+ATTRSET_iUoW1]
|
|
add eax, [ecx+ATTRSET_iUoW1]
|
|
mov [ecx+ATTRSET_iUoW1], eax
|
|
mov eax, [edx+ATTRSET_iVoW1]
|
|
add eax, [ecx+ATTRSET_iVoW1]
|
|
mov [ecx+ATTRSET_iVoW1], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Tex2') >= 0), `1',
|
|
`
|
|
mov eax, [edx+ATTRSET_iUoW2]
|
|
add eax, [ecx+ATTRSET_iUoW2]
|
|
mov [ecx+ATTRSET_iUoW2], eax
|
|
mov eax, [edx+ATTRSET_iVoW2]
|
|
add eax, [ecx+ATTRSET_iVoW2]
|
|
mov [ecx+ATTRSET_iVoW2], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Diff') >= 0), `1',
|
|
`
|
|
mov eax, [edx+ATTRSET_iB]
|
|
add eax, [ecx+ATTRSET_iB]
|
|
mov [ecx+ATTRSET_iB], eax
|
|
mov eax, [edx+ATTRSET_iG]
|
|
add eax, [ecx+ATTRSET_iG]
|
|
mov [ecx+ATTRSET_iG], eax
|
|
mov eax, [edx+ATTRSET_iR]
|
|
add eax, [ecx+ATTRSET_iR]
|
|
mov [ecx+ATTRSET_iR], eax
|
|
mov eax, [edx+ATTRSET_iA]
|
|
add eax, [ecx+ATTRSET_iA]
|
|
mov [ecx+ATTRSET_iA], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Spec') >= 0), `1',
|
|
`
|
|
mov eax, [edx+ATTRSET_iBS]
|
|
add eax, [ecx+ATTRSET_iBS]
|
|
mov [ecx+ATTRSET_iBS], eax
|
|
mov eax, [edx+ATTRSET_iGS]
|
|
add eax, [ecx+ATTRSET_iGS]
|
|
mov [ecx+ATTRSET_iGS], eax
|
|
mov eax, [edx+ATTRSET_iRS]
|
|
add eax, [ecx+ATTRSET_iRS]
|
|
mov [ecx+ATTRSET_iRS], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `DIdx') >= 0), `1',
|
|
`
|
|
mov eax, [edx+ATTRSET_iDIdx]
|
|
add eax, [ecx+ATTRSET_iDIdx]
|
|
mov [ecx+ATTRSET_iDIdx], eax
|
|
mov eax, [edx+ATTRSET_iDIdxA]
|
|
add eax, [ecx+ATTRSET_iDIdxA]
|
|
mov [ecx+ATTRSET_iDIdxA], eax
|
|
')dnl
|
|
')dnl
|
|
dnl
|
|
dnl d_FillSpanFloatAttrsBody
|
|
dnl
|
|
dnl Generates the body of a FP span filler routine.
|
|
dnl Suboptimal cache ordering due to attempt to overlap OoW divide with
|
|
dnl integer ops.
|
|
dnl
|
|
dnl $1 contains substrings Z, Diff, Spec, DIdx, Tex1 and Tex2 in any mix.
|
|
dnl
|
|
define(`d_FillSpanFloatAttrsBody',
|
|
`ifelse(eval(d_index(`$1', `Tex') >= 0), `1',
|
|
`
|
|
fld DWORD PTR [ecx+ATTRSET_fOoW]
|
|
fist DWORD PTR [edx+RASTSPAN_iOoW]
|
|
fdivr DWORD PTR OOW_W_SCALE
|
|
')dnl
|
|
|
|
; Set surface pointers.
|
|
mov eax, [ecx+ATTRSET_pSurface]
|
|
mov [edx+RASTSPAN_pSurface], eax
|
|
mov eax, [ecx+ATTRSET_pZ]
|
|
mov [edx+RASTSPAN_pZ], eax
|
|
ifelse(eval(d_index(`$1', `Tex') >= 0), `1',
|
|
`
|
|
; Clears both iLOD and iDLOD.
|
|
xor eax, eax
|
|
mov [edx+RASTSPAN_iLOD], eax
|
|
fistp DWORD PTR [edx+RASTSPAN_iW]
|
|
|
|
fld DWORD PTR [ecx+ATTRSET_fUoW1]
|
|
fistp DWORD PTR [edx+RASTSPAN_iUoW1]
|
|
fld DWORD PTR [ecx+ATTRSET_fVoW1]
|
|
fistp DWORD PTR [edx+RASTSPAN_iVoW1]
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Tex2') >= 0), `1',
|
|
`
|
|
fld DWORD PTR [ecx+ATTRSET_fUoW2]
|
|
fistp DWORD PTR [edx+RASTSPAN_iUoW2]
|
|
fld DWORD PTR [ecx+ATTRSET_fVoW2]
|
|
fistp DWORD PTR [edx+RASTSPAN_iVoW2]
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Z') >= 0), `1',
|
|
`
|
|
fld DWORD PTR [ecx+ATTRSET_fZ]
|
|
fistp DWORD PTR [edx+RASTSPAN_uZ]
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Diff') >= 0), `1',
|
|
`
|
|
; Directly store DWORD-aligned fields, then whack in
|
|
; half DWORDs.
|
|
; ATTENTION - 8.8 color fields could use the FP fixing trick
|
|
; to use fstp instead of fistp. Adds could be overlapped
|
|
; so itd be free cycles?
|
|
|
|
fld DWORD PTR [ecx+ATTRSET_fG]
|
|
fistp DWORD PTR iVal
|
|
|
|
fld DWORD PTR [ecx+ATTRSET_fB]
|
|
fistp DWORD PTR [edx+RASTSPAN_uB]
|
|
|
|
mov ax, WORD PTR iVal
|
|
fld DWORD PTR [ecx+ATTRSET_fA]
|
|
fistp DWORD PTR iVal
|
|
mov WORD PTR [edx+RASTSPAN_uG], ax
|
|
|
|
fld DWORD PTR [ecx+ATTRSET_fR]
|
|
fistp DWORD PTR [edx+RASTSPAN_uR]
|
|
|
|
mov ax, WORD PTR iVal
|
|
mov WORD PTR [edx+RASTSPAN_uA], ax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Spec') >= 0), `1',
|
|
`
|
|
fld DWORD PTR [ecx+ATTRSET_fGS]
|
|
fistp DWORD PTR iVal
|
|
|
|
fld DWORD PTR [ecx+ATTRSET_fBS]
|
|
fistp DWORD PTR [edx+RASTSPAN_uBS]
|
|
|
|
mov ax, WORD PTR iVal
|
|
mov WORD PTR [edx+RASTSPAN_uGS], ax
|
|
|
|
; Trashes uFog, but thats OK because fog isnt getting used.
|
|
fld DWORD PTR [ecx+ATTRSET_fRS]
|
|
fistp DWORD PTR [edx+RASTSPAN_uRS]
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `DIdx') >= 0), `1',
|
|
`
|
|
fld DWORD PTR [ecx+ATTRSET_fDIdx]
|
|
fistp DWORD PTR [edx+RASTSPAN_iIdx]
|
|
fld DWORD PTR [ecx+ATTRSET_fDIdxA]
|
|
fistp DWORD PTR [edx+RASTSPAN_iIdxA]
|
|
')dnl
|
|
')dnl
|
|
dnl
|
|
dnl d_FillSpanFixedAttrsBody
|
|
dnl
|
|
dnl Generates the body of a fixed span filler routine.
|
|
dnl Cache ordered except for the overlap of the OoW divide.
|
|
dnl
|
|
dnl $1 contains substrings Z, Diff, Spec, DIdx, Tex1 and Tex2 in any mix.
|
|
dnl
|
|
define(`d_FillSpanFixedAttrsBody',
|
|
`ifelse(eval(d_index(`$1', `Tex') >= 0), `1',
|
|
`
|
|
fild DWORD PTR [ecx+ATTRSET_iOoW]
|
|
fdivr DWORD PTR OOW_W_SCALE
|
|
')dnl
|
|
|
|
; Set surface pointers.
|
|
mov eax, [ecx+ATTRSET_pSurface]
|
|
mov [edx+RASTSPAN_pSurface], eax
|
|
mov eax, [ecx+ATTRSET_pZ]
|
|
mov [edx+RASTSPAN_pZ], eax
|
|
ifelse(eval(d_index(`$1', `Z') >= 0), `1',
|
|
`
|
|
mov eax, [ecx+ATTRSET_uZ]
|
|
mov [edx+RASTSPAN_uZ], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Tex') >= 0), `1',
|
|
`
|
|
; Clears both iLOD and iDLOD.
|
|
xor eax, eax
|
|
mov [edx+RASTSPAN_iLOD], eax
|
|
|
|
mov eax, [ecx+ATTRSET_iOoW]
|
|
mov [edx+RASTSPAN_iOoW], eax
|
|
|
|
mov eax, [ecx+ATTRSET_iUoW1]
|
|
mov [edx+RASTSPAN_iUoW1], eax
|
|
mov eax, [ecx+ATTRSET_iVoW1]
|
|
mov [edx+RASTSPAN_iVoW1], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Tex2') >= 0), `1',
|
|
`
|
|
mov eax, [ecx+ATTRSET_iUoW2]
|
|
mov [edx+RASTSPAN_iUoW2], eax
|
|
mov eax, [ecx+ATTRSET_iVoW2]
|
|
mov [edx+RASTSPAN_iVoW2], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Diff') >= 0), `1',
|
|
`
|
|
; Directly store DWORD-aligned fields, then whack in
|
|
; half DWORDs.
|
|
; ATTENTION - Keep word pairs shifted and OR together to store
|
|
; as DWORDs instead?
|
|
mov eax, [ecx+ATTRSET_uB]
|
|
mov [edx+RASTSPAN_uB], eax
|
|
mov eax, [ecx+ATTRSET_uR]
|
|
mov [edx+RASTSPAN_uR], eax
|
|
mov ax, [ecx+ATTRSET_uG]
|
|
mov [edx+RASTSPAN_uG], ax
|
|
mov ax, [ecx+ATTRSET_uA]
|
|
mov [edx+RASTSPAN_uA], ax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Spec') >= 0), `1',
|
|
`
|
|
mov eax, [ecx+ATTRSET_uBS]
|
|
mov [edx+RASTSPAN_uBS], eax
|
|
mov eax, [ecx+ATTRSET_uRS]
|
|
mov [edx+RASTSPAN_uRS], eax
|
|
mov ax, [ecx+ATTRSET_uGS]
|
|
mov [edx+RASTSPAN_uGS], ax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `DIdx') >= 0), `1',
|
|
`
|
|
mov eax, [ecx+ATTRSET_uDIdx]
|
|
mov [edx+RASTSPAN_iIdx], eax
|
|
mov eax, [ecx+ATTRSET_uDIdxA]
|
|
mov [edx+RASTSPAN_iIdxA], eax
|
|
')dnl
|
|
ifelse(eval(d_index(`$1', `Tex') >= 0), `1',
|
|
`
|
|
fistp DWORD PTR [edx+RASTSPAN_iW]
|
|
')dnl
|
|
')dnl
|