Hi,

I'm translating porting a Delphi component that uses x86-64 assembly.

So far, most of the asm code compiles and works fine.

The only thing that i could not translate is the .SAVENV directive. See
http://blogs.embarcadero.com/abauer/2011/10/10/38940 and
http://docwiki.embarcadero.com/RADStudio/en/Assembly_Procedures_and_Functions

Seems that is necessary to save and restore the register with a specific
alignment.

I would appreciate any help

The procedure is below.

The component is VirtualTreeView and full source can be found at
http://virtual-treeview.googlecode.com/svn/trunk/Source/VirtualTrees.pas

procedure AlphaBlendLineMaster(Source, Destination: Pointer; Count:
Integer; ConstantAlpha, Bias: Integer);

// Blends a line of Count pixels from Source to Destination using the
source pixel and a constant alpha value.
// The layout of a pixel must be BGRA.
// ConstantAlpha must be in the range 0..255.
// Bias is an additional value which gets added to every component and must
be in the range -128..127

asm

{$ifdef CPU64}
// RCX contains Source
// RDX contains Destination
// R8D contains Count
// R9D contains ConstantAlpha
// Bias is on the stack

        .SAVENV XMM6  //todo see how implement in fpc

        // Load XMM3 with the constant alpha value (replicate it for every
component).
        // Expand it to word size.
        MOVD        XMM3, R9D    // ConstantAlpha
        PUNPCKLWD   XMM3, XMM3
        PUNPCKLDQ   XMM3, XMM3

        // Load XMM5 with the bias value.
        MOV         R10D, [Bias]
        MOVD        XMM5, R10D
        PUNPCKLWD   XMM5, XMM5
        PUNPCKLDQ   XMM5, XMM5

        // Load XMM4 with 128 to allow for saturated biasing.
        MOV         R10D, 128
        MOVD        XMM4, R10D
        PUNPCKLWD   XMM4, XMM4
        PUNPCKLDQ   XMM4, XMM4

@1:     // The pixel loop calculates an entire pixel in one run.
        // Note: The pixel byte values are expanded into the higher bytes
of a word due
        //       to the way unpacking works. We compensate for this with an
extra shift.
        MOVD        XMM1, DWORD PTR [RCX]   // data is unaligned
        MOVD        XMM2, DWORD PTR [RDX]   // data is unaligned
        PXOR        XMM0, XMM0    // clear source pixel register for
unpacking
        PUNPCKLBW   XMM0, XMM1{[RCX]}     // unpack source pixel byte
values into words
        PSRLW       XMM0, 8       // move higher bytes to lower bytes
        PXOR        XMM1, XMM1    // clear target pixel register for
unpacking
        PUNPCKLBW   XMM1, XMM2{[RCX]}     // unpack target pixel byte
values into words
        MOVQ        XMM2, XMM1    // make a copy of the shifted values, we
need them again
        PSRLW       XMM1, 8       // move higher bytes to lower bytes

        // Load XMM6 with the source alpha value (replicate it for every
component).
        // Expand it to word size.
        MOVQ        XMM6, XMM0
        PUNPCKHWD   XMM6, XMM6
        PUNPCKHDQ   XMM6, XMM6
        PMULLW      XMM6, XMM3    // source alpha * master alpha
        PSRLW       XMM6, 8       // divide by 256

        // calculation is: target = (alpha * master alpha * (source -
target) + 256 * target) / 256
        PSUBW       XMM0, XMM1    // source - target
        PMULLW      XMM0, XMM6    // alpha * (source - target)
        PADDW       XMM0, XMM2    // add target (in shifted form)
        PSRLW       XMM0, 8       // divide by 256

        // Bias is accounted for by conversion of range 0..255 to -128..127,
        // doing a saturated add and convert back to 0..255.
        PSUBW       XMM0, XMM4
        PADDSW      XMM0, XMM5
        PADDW       XMM0, XMM4
        PACKUSWB    XMM0, XMM0    // convert words to bytes with saturation
        MOVD        DWORD PTR [RDX], XMM0   // store the result
@3:
        ADD         RCX, 4
        ADD         RDX, 4
        DEC         R8D
        JNZ         @1
{$endif}
end;
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to