Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2012-10

Same 64bit assembly code compiles under windows but not in linux (fpc 260)

8 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

luiz americo pereira camara

Hi,

I'm porting some Delphi assembly code.

It worked fine with fpc 2.6.0 i386-64bit windows compiler

When i tried the same code with fpc 2.6.0 i386-64bit for linux it failed to compile with the following error:

Error: Asm: 16 or 32 Bit references not supported

at the line

         // Load XMM5 with the bias value.
        MOVD        XMM5, [Bias]  //Bias = Integer

Is it a know issue or a limitation of linux version?

There's a workaround to this issue?

The complete procedure:

{$ASMMODE INTEL}
procedure AlphaBlendLineConstant(Source, Destination: Pointer; Count:
Integer; ConstantAlpha, Bias: Integer);

asm

{$ifdef CPU64}
// RCX contains Source
// RDX contains Destination
// R8D contains Count
// R9D contains ConstantAlpha
// Bias is on the stack
        //.NOFRAME
        // 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.
        MOVD        XMM5, [Bias]
        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{[RDX]} // 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

        // calculation is: target = (alpha * (source - target) + 256 *

target) / 256
PSUBW XMM0, XMM1 // source - target
PMULLW XMM0, XMM3 // 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;

Reply by email

Jeppe Græsdal Johansen
to luiz americo pereira camara

Integer is not a specifically sized type. It might differ based on what platform you are on. For example, it's 16bit on i386-linux when compiled with mode fpc. With mode objfpc on the same platform it's 32bit.

Also, wouldn't MOVD XMM5, [Bias] imply that you are moving from the address stored in the Bias variable? That would make a whole lot more sense as to why it generates this error

luiz americo pereira camara wrote 102 lines
Hi, I'm porting some Delphi assembly code. It worked fine with fpc 2.6.0 i386-64bit windows compiler When i tried the same code with fpc 2.6.0 i386-64bit for linux it failed to compile with the following error: Error: Asm: 16 or 32 Bit references not supported at the line // Load XMM5 with the bias value. MOVD XMM5, [Bias] //Bias = Integer Is it a know issue or a limitation of linux version? There's a workaround to this issue? The complete procedure: {$ASMMODE INTEL} procedure AlphaBlendLineConstant(Source, Destination: Pointer; Count: Integer; ConstantAlpha, Bias: Integer); asm {$ifdef CPU64} // RCX contains Source // RDX contains Destination // R8D contains Count // R9D contains ConstantAlpha // Bias is on the stack //.NOFRAME // 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. MOVD XMM5, [Bias] 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{[RDX]} // 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 // calculation is: target = (alpha * (source - target) + 256 * target) / 256 PSUBW XMM0, XMM1 // source - target PMULLW XMM0, XMM3 // 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;

Reply by email

luiz americo pereira camara
to Jeppe Græsdal Johansen

2012/10/2 Jeppe Græsdal Johansen

Integer is not a specifically sized type. It might differ based on what platform you are on. For example, it's 16bit on i386-linux when compiled with mode fpc. With mode objfpc on the same platform it's 32bit.

The code is compiled under mode Delphi both in linux and windows

Both compilers are i386-64bit version 2.6.0

Both OS are 64bit

Show quoted text 5 lines
Also, wouldn't MOVD XMM5, [Bias] imply that you are moving from the address stored in the Bias variable? That would make a whole lot more sense as to why it generates this error

The question is why it compiles and works under windows (both in fpc and in Delphi) and not under Linux?

A specific bug under Linux?
A missing configuration?

Luiz

Reply by email

Nikolai Zhubr
to luiz americo pereira camara: I'm porting some Delphi assembly code. It worked fine with fpc 2.6.0 i386-64bit windows…

Hi,
03.10.2012 5:29, luiz americo pereira camara:
[...]

Show quoted text 15 lines
The complete procedure: {$ASMMODE INTEL} procedure AlphaBlendLineConstant(Source, Destination: Pointer; Count: Integer; ConstantAlpha, Bias: Integer); asm {$ifdef CPU64} // RCX contains Source // RDX contains Destination // R8D contains Count // R9D contains ConstantAlpha // Bias is on the stack

The procedure declaration above is not specific enough for the assembler block listed below, because
- the size of "integer" generally may vary;
- calling convention generally may vary;
I'd suggest to
- replace "integer" by "longint" or "word", according to what assembler code expects;
- specify some calling convention according to what assembler code expects (IIRC in this case it is cdecl but I'm not completely sure).

HTH
Nikolai

Show quoted text 72 lines
//.NOFRAME // 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. MOVD XMM5, [Bias] 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{[RDX]} // 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 // calculation is: target = (alpha * (source - target) + 256 * target) / 256 PSUBW XMM0, XMM1 // source - target PMULLW XMM0, XMM3 // 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-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Kostas Michalopoulos
to Jeppe Græsdal Johansen: Integer is not a specifically sized type. It might differ based on what platform you are…

It depends on the compiler mode, not the platform - at least according to the docs in http://www.freepascal.org/docs-html/ref/refsu5.html:

---
The integer type maps to the smallint type in the default Free Pascal mode. It maps to either a longint in either Delphi or ObjFPC mode. The cardinal type is currently always mapped to the longword type. ---

Kostas "Bad Sector" Michalopoulos

Jeppe Græsdal Johansen wrote 116 lines
Integer is not a specifically sized type. It might differ based on what platform you are on. For example, it's 16bit on i386-linux when compiled with mode fpc. With mode objfpc on the same platform it's 32bit. Also, wouldn't MOVD XMM5, [Bias] imply that you are moving from the address stored in the Bias variable? That would make a whole lot more sense as to why it generates this error Den 03-10-2012 03:29, luiz americo pereira camara skrev: Hi, I'm porting some Delphi assembly code. It worked fine with fpc 2.6.0 i386-64bit windows compiler When i tried the same code with fpc 2.6.0 i386-64bit for linux it failed to compile with the following error: Error: Asm: 16 or 32 Bit references not supported at the line // Load XMM5 with the bias value. MOVD XMM5, [Bias] //Bias = Integer Is it a know issue or a limitation of linux version? There's a workaround to this issue? The complete procedure: {$ASMMODE INTEL} procedure AlphaBlendLineConstant(Source, Destination: Pointer; Count: Integer; ConstantAlpha, Bias: Integer); asm {$ifdef CPU64} // RCX contains Source // RDX contains Destination // R8D contains Count // R9D contains ConstantAlpha // Bias is on the stack //.NOFRAME // 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. MOVD XMM5, [Bias] 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{[RDX]} // 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 // calculation is: target = (alpha * (source - target) + 256 * target) / 256 PSUBW XMM0, XMM1 // source - target PMULLW XMM0, XMM3 // 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-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Jonas Maebe
to luiz americo pereira camara: I'm porting some Delphi assembly code. It worked fine with fpc 2.6.0 i386-64bit windows…
luiz americo pereira camara wrote 15 lines
I'm porting some Delphi assembly code. It worked fine with fpc 2.6.0 i386-64bit windows compiler When i tried the same code with fpc 2.6.0 i386-64bit for linux it failed to compile with the following error: Error: Asm: 16 or 32 Bit references not supported at the line // Load XMM5 with the bias value. MOVD XMM5, [Bias] //Bias = Integer Is it a know issue or a limitation of linux version?

Win64 uses a different calling convention compared to every other x86-64 operating system (Microsoft probably started working on it before the x86-64 ABI was finalized). One of the differences is that only passes the first three integer parameters in registers, while other operating systems pass the first six integer parameters in registers. This means that on Win64, the above translates into

movd xmm5, [rpb + some_offset]

while on other platforms, it translates into

movd xmm5, [r8d]

So you are creating a reference with r8d as base register, which is invalid (because it's a 32 bit register)

Jonas

Reply by email

luiz americo pereira camara
to Jonas Maebe

2012/10/3 Jonas Maebe

Show quoted text 28 lines
On 03 Oct 2012, at 03:29, luiz americo pereira camara wrote: at the line // Load XMM5 with the bias value. MOVD XMM5, [Bias] //Bias = Integer Is it a know issue or a limitation of linux version? Win64 uses a different calling convention compared to every other x86-64 operating system (Microsoft probably started working on it before the x86-64 ABI was finalized). One of the differences is that only passes the first three integer parameters in registers, while other operating systems pass the first six integer parameters in registers. This means that on Win64, the above translates into movd xmm5, [rpb + some_offset] while on other platforms, it translates into movd xmm5, [r8d] So you are creating a reference with r8d as base register, which is invalid (because it's a 32 bit register)

Why it compiles and works with fpc 2.6.0 64bit under windows (and also Delphi)?

Luiz

Show quoted text 8 lines
Jonas _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

luiz americo pereira camara
to luiz americo pereira camara

2012/10/4 luiz americo pereira camara

Show quoted text 36 lines
2012/10/3 Jonas Maebe > > On 03 Oct 2012, at 03:29, luiz americo pereira camara wrote: > > > at the line > // Load XMM5 with the bias value. > MOVD XMM5, [Bias] //Bias = Integer > > Is it a know issue or a limitation of linux version? > > > Win64 uses a different calling convention compared to every other x86-64 > operating system (Microsoft probably started working on it before the > x86-64 ABI was finalized). One of the differences is that only passes the > first three integer parameters in registers, while other operating systems > pass the first six integer parameters in registers. This means that on > Win64, the above translates into > > movd xmm5, [rpb + some_offset] > > while on other platforms, it translates into > > movd xmm5, [r8d] > > So you are creating a reference with r8d as base register, which is > invalid (because it's a 32 bit register) > > Why it compiles and works with fpc 2.6.0 64bit under windows (and also Delphi)?

Forget about the above question

Now i understand

Luiz

Show quoted text 13 lines
Luiz > > Jonas > > _______________________________________________ > fpc-devel maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-devel > >

Reply by email