代码之家  ›  专栏  ›  技术社区  ›  Johan

将常量读入内联程序集中的sse/avx寄存器

  •  6
  • Johan  · 技术社区  · 7 年前

    我正试图导入 .o 从拉撒路到德尔菲的文件。

    function Test: boolean;
    const
      TestData: array[0..15] of byte = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
    asm
      movdqu xmm0,[rip+testData]   //xmm0 should be all zeros
      pcmpeqq xmm1,xmm1        //xmm1 is all ones
      ptest xmm0,xmm1          //ZF = (xmm0 and xmm1) = 0
      setz al                  //return true if test works, false if not
    end;
    

    上面的程序在delphi中有效,但在lazarus中失败。

    我正在使用

       {$L 'C:\pathname\TestUnit.o'}
    
    function TESTUNIT_TEST: boolean; external name 'TESTUNIT_$$_TEST$$BOOLEAN';
    

    拉撒路取代了 TestData 零偏移。

    AVXGENERATE_TEST:
    //never mind the stack frame
    0000000000A0F3B0 488D6424F8       lea rsp,[rsp-$08]
    //                                                        rel 0? why?
    0000000000A0F3B5 F30F6F0500000000 movdqu xmm0,dqword ptr [rel $00000000]
    0000000000A0F3BD 660F3829C9       pcmpeqq xmm1,xmm1
    0000000000A0F3C2 660F3817C1       ptest xmm0,xmm1
    0000000000A0F3C7 0F94C0           setz al
    0000000000A0F3CA 488D642408       lea rsp,[rsp+$08]
    0000000000A0F3CF C3               ret
    

    这是来自“objdump-dr”c:\路径名\testunit.o的输出

    Disassembly of section .text.n_avxgenerate_$$_test$$boolean:
    
    0000000000000000 <AVXGENERATE_$$_TEST$$BOOLEAN>:
       0:   48 8d 64 24 f8          lea    -0x8(%rsp),%rsp
       5:   f3 0f 6f 05 00 00 00    movdqu 0x0(%rip),%xmm0        # d <AVXGENERATE_$$_TEST$$BOOLEAN+0xd>
       c:   00
                            9: R_X86_64_PC32        .data.n_tc_$avxgenerate_$$_testdata
       d:   66 0f 38 29 c9          pcmpeqq %xmm1,%xmm1
      12:   66 0f 38 17 c1          ptest  %xmm1,%xmm0
      17:   0f 94 c0                sete   %al
      1a:   48 8d 64 24 08          lea    0x8(%rsp),%rsp
      1f:   c3
    

    如何让拉撒路把常数正确地读入 xmm 注册?
    这个问题有解决办法吗?

    我计划包括一些 AVX 在Delphi程序中用Lazarus编写的程序集。
    为了测试的目的我只是用 SSE 代码在这里。

    版本信息
    FPC 3.0.0
    Lazarus版本1.6.2

    1 回复  |  直到 7 年前
        1
  •  1
  •   Johan    7 年前

    解决方法是将要导入的例程放入dll。
    这意味着你不再把所有的东西都放在一个独立的 .exe 文件。
    但至少所有的代码链接都是正确的。

    在Lazarus

    library Test_lib;
    
    {$mode delphi}{$H+}
    
    uses
      Classes,
      TestUnit;
    
    {$R *.res}
    
    exports
      Test;
    
    begin
    end.    
    

    在德尔福

    const
      Testlib = 'C:\pathname\Lazarus\Test_lib.dll';
    
    function LazarusTest: boolean; external Testlib name 'Test';
    

    现在输出是:

    0000000110020570 488D6424F8       lea rsp,[rsp-$08]
    {                                 links to the correct location VVVVVV}
    0000000110020575 F30F6F0553930000 movdqu xmm0,dqword ptr [rel $00009353]
    000000011002057D 660F3829C9       pcmpeqq xmm1,xmm1
    0000000110020582 660F3817C1       ptest xmm0,xmm1
    0000000110020587 0F94C0           setz al
    000000011002058A 488D642408       lea rsp,[rsp+$08]
    000000011002058F C3               ret