par2有一个很小且相当干净的C++代码库,我认为它可以很好地构建在GNU、OS和MSVC++上。
我想合并一个x86-64ASM版本的一个功能,几乎所有的CPU时间。(有更多详细信息的邮件列表帖子.我的这里的实现/基准.)
本质可能是一个显而易见的解决方案,但gcc并没有生成足够好的代码,可以从64位寄存器中一次获取一个字节作为索引输入LUT。我也可能会花时间来安排指令,这样每个uop缓存行都有4个uop的倍数,因为uop吞吐量是瓶颈,即使输入/输出缓冲区的大小相当大。
我不想引入对yasm的依赖,因为很多人都安装了gcc,但没有安装。
有没有一种方法可以在一个单独的文件中编写一个函数,gcc / clang和MSVC可以组装?的目标是:
Par2cmdline的构建系统是Unix的autoconf/automake,Windows .sln。
我知道GNU汇编有一个.intel_syntax noprefix指令,但它只改变指令格式,而不是其他汇编程序指令。例如.align 16和align 16。我的代码很简单,而且很小,所以可以使用C-预处理程序#define来处理不同的指令,如果可以的话。
我假设在C++中执行CPU检测和根据结果设置函数指针并不是一个问题,即使我必须为此使用一些#ifdef条件编译。
如果没有我所期望的解决方案,我可能会引入一个依赖于yasm的构建,并有一个./configure --no-asm选项来禁用在x86上构建的人的asm加速功能,而不是yasm可用。
在Windows和Linux中处理不同调用约定的首选计划是在我的C原型上为我的asm函数使用__attribute__((sysv_abi))。然后,我只需要为SysV ABI编写函数序言。MSVC有类似的东西吗?根据SysV ABI的某些功能,会把args放到regs中吗?(顺便说一句,这让编译器错误很痒,所以如果您想让代码与当前的gcc一起工作,请注意这个想法。)
发布于 2015-09-25 11:16:54
虽然我没有很好的解决方案来消除对特定汇编程序的依赖,但对于如何处理64位调用约定( Microsoft x64与SysV ABI )这两种不同的调用约定,我确实有一个建议。
最低的通用分母是Microsoft x64调用约定,因为它只能通过寄存器传递前四个值。因此,如果仅限于此,并使用宏定义寄存器,则可以轻松地将代码编译为Unix (Linux/BSD/OSX)和Windows。
例如,查看Agner‘s 阿斯利卜中的文件阿斯利卜
%IFDEF WINDOWS
%define Rpar1 rcx ; function parameter 1
%define Rpar2 rdx ; function parameter 2
%define Rpar3 r8 ; function parameter 3
%ENDIF
%IFDEF UNIX
%define Rpar1 rdi ; function parameter 1
%define Rpar2 rsi ; function parameter 2
%define Rpar3 rdx ; function parameter 3
%ENDIF
push Rpar1 ; dest
push Rpar2 ; src
call A_strlen ; length of dest
push rax ; strlen(dest)
mov Rpar1, [rsp+8] ; src
call A_strlen ; length of src
pop Rpar1 ; strlen(dest)
pop Rpar2 ; src
add Rpar1, [rsp] ; dest + strlen(dest)
lea Rpar3, [rax+1] ; strlen(src)+1
call A_memcpy ; copy
pop rax ; return dest
ret
;A_strcat ENDP我不认为四个寄存器实际上是一个限制,因为如果您想要在程序集中编写某些东西,那么在这种情况下,调用开销的函数与函数本身相比应该是可以忽略不计的,因此,如果需要的话,在调用函数时将一些值推送/弹出不会对性能产生影响。
https://stackoverflow.com/questions/31734263
复制相似问题