- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在尝试回答 Embedded broadcasts with intrinsics and assembly 时,我正在尝试做这样的事情:
__m512 mul_bcast(__m512 a, float b) {
asm(
"vbroadcastss %k[scalar], %q[scalar]\n\t" // want vbcast.. %xmm0, %zmm0
"vmulps %q[scalar], %[vec], %[vec]\n\t"
: [vec] "+x" (a), [scalar] "+&x" (b)
: :
);
return a;
}
GNU C x86 Operand Modifiers doc 仅指定最大 q
的修饰符(DI (DoubleInt) 大小,64 位)。在 vector 寄存器上使用 q
将始终将其降低到 xmm
(来自 ymm
或 zmm
)。例如标量寄存器:
long scratch = 0; // not useful instructions, just syntax demo
asm(
"movw symbol(%q[inttmp]), %w[inttmp]\n\t" // movw symbol(%rax), %ax
"movsbl %h[inttmp], %k[inttmp]\n\t" // movsx %ah, %eax
: [inttmp] "+r" (scratch)
:: "memory" // we read some index in symbol[]
);
在 vector 寄存器大小之间更改的修饰符是什么?
此外,输入或输出操作数是否有任何特定的大小限制?不同于通用 x
的东西,它最终可能是 xmm、ymm 或 zmm,具体取决于您放在括号中的表达式的类型。
题外话:
clang 似乎有一些 Yi
/Yt
约束(不是修饰符),但我也找不到相关文档。 clang 甚至不会编译它,即使 vector 指令被注释掉,因为它不喜欢 +x
作为 __m512
vector 的约束。
我可以通过将标量作为输入操作数传递来获得我想要的结果,它被限制在与更广泛的输出操作数相同的寄存器中,但它比较笨拙。 (此用例的最大缺点是 AFAIK 匹配约束只能通过操作数编号引用,而不是 [symbolic_name]
,因此在添加/删除输出约束时很容易损坏。)
// does what I want, by using a paired output and input constraint
__m512 mul_bcast(__m512 a, float b) {
__m512 tmpvec;
asm(
"vbroadcastss %[scalar], %[tmpvec]\n\t"
"vmulps %[tmpvec], %[vec], %[vec]\n\t"
: [vec] "+x" (a), [tmpvec] "=&x" (tmpvec)
: [scalar] "1" (b)
:
);
return a;
}
此外,我认为我试图解决的问题的整个方法将是死胡同,因为 Multi-Alternative constraints不要让您为不同的约束模式提供不同的 asm。我希望 x
和 r
约束最终从寄存器发出 vbroadcastss
,而 m
约束结束发射 vmulps (mem_src){1to16}, %zmm_src2, %zmm_dst
(折叠广播负载)。使用内联 asm 这样做的目的是 gcc 还不知道如何将 set1()
内存操作数折叠到广播负载中(但 clang 知道)。
无论如何,这个具体问题是关于 vector 寄存器的操作数修饰符和约束。请关注这一点,但欢迎对另一个问题发表评论和回答。 (或者更好,只是评论/回答 Z Boson 关于嵌入式广播的问题。)
最佳答案
来自文件gcc/config/i386/i386.c GCC 来源:
b -- print the QImode name of the register for the indicated operand. %b0 would print %al if operands[0] is reg 0. w -- likewise, print the HImode name of the register. k -- likewise, print the SImode name of the register. q -- likewise, print the DImode name of the register. x -- likewise, print the V4SFmode name of the register. t -- likewise, print the V8SFmode name of the register. g -- likewise, print the V16SFmode name of the register. h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
类似于gcc/config/i386/contraints.md :
;; We use the Y prefix to denote any number of conditional register sets: ;; z First SSE register. ;; i SSE2 inter-unit moves to SSE register enabled ;; j SSE2 inter-unit moves from SSE register enabled ;; m MMX inter-unit moves to MMX register enabled ;; n MMX inter-unit moves from MMX register enabled ;; a Integer register when zero extensions with AND are disabled ;; p Integer register when TARGET_PARTIAL_REG_STALL is disabled ;; f x87 register when 80387 floating point arithmetic is enabled ;; r SSE regs not requiring REX prefix when prefixes avoidance is enabled ;; and all SSE regs otherwise
此文件还定义了一个“Yk”约束,但我不知道它在 asm 语句中的效果如何:
(define_register_constraint "Yk" "TARGET_AVX512F ? MASK_EVEX_REGS : NO_REGS" "@internal Any mask register that can be used as predicate, i.e. k1-k7.")
请注意,这都是从最新的 SVN 修订版复制而来的。我不知道 GCC 的哪个版本(如果有)添加了您感兴趣的特定修饰符和约束。
关于c - 在 GNU C 内联汇编中,单个操作数的 xmm/ymm/zmm 的大小覆盖修饰符是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34459803/
Intel x86 汇编中执行以下操作最有效的方法是什么(a、b 是 32 位 float ): 从 xmm1: [-, -, a, b] 到 xmm1: [a, a, b, b] 我找不到任何有用的
Intel x86 汇编中执行以下操作最有效的方法是什么(a、b 是 32 位 float ): 从 xmm1: [-, -, a, b] 到 xmm1: [a, a, b, b] 我找不到任何有用的
从 SIMD 寄存器加载和存储生成用途寄存器的最佳方式是什么?到目前为止,我一直使用堆栈作为临时的。例如, mov [rsp + 0x00], r8 mov [rsp + 0x08], r9 mov
我正在尝试实现一些内联汇编器(在 C/C++ 代码中)以利用 SSE。我想将值(从 XMM 寄存器或内存)复制并复制到另一个 XMM 寄存器。例如,假设我在内存中有一些值 {1, 2, 3, 4}。我
在多核 CPU 中,每个核是否都可以访问自己的 XMM 寄存器组?例如,如果一个芯片被列为具有 16 个 XMM 寄存器 (XMM0-XMM15),那么每个内核 16 个寄存器还是 16 个共享? 我
我发现很难在 Visual Studio 的寄存器窗口中解释 xmm 寄存器的值。窗口显示以下内容: XMM0 = 00000000000000004018000000000000 XMM1 = 00
pushf //couldnt store this in other registers movd xmm0,eax//storing in xmm registers
我正在使用 AES-NI在内核代码中。 AES 新指令使用 XMM 寄存器,我想确保从用户模式到内核模式的转换以及返回到用户模式的转换将保留 XMM 寄存器的状态。 MSDN link读到: In 6
有没有办法将压缩双字整数从 XMM 寄存器推送到堆栈?然后在需要时将其弹出? 理想情况下,我正在为通用寄存器寻找 PUSH 或 POP 之类的东西,我已经检查过英特尔手册,但我要么错过了命令,要么没有
是将值移动到 xmm 寄存器的唯一方法,首先将值移动到整数寄存器中,不知道它们叫什么,然后进入 xmm 寄存器,例如 mov [eax], (float)1000 ; store to mem
如何仅访问 128 位 xmm 寄存器的特定部分(字节)?我必须在整个空间上循环(按字节),逐字节比较并在明确定义的条件下复制它*。 因此,我必须将这个 16 字节寄存器的每个字节与 \0 进行比较,
我在xmm1寄存器加载了一些内容,假设它可以被视为 xmm1 = | bgra | bgra | bgra | bgra | (each one a dw) 现在,我想将每个双字逻辑右移 1 个字节,
我正在尝试使用 XMM 寄存器使用 SSE2 指令将 4 个数字添加到其他 4 个汇编语言中的数字。我确实成功了,但是我遇到了一些我不明白的事情。如果我以这种方式添加: movdqu xmm0, ow
我想知道,有没有办法增加 xmm 寄存器中的值,或者只能将一个值移到一个寄存器中? 我的意思是,你可以这样做: inc eax 或者像这样: inc [ebp+7F00F000] 有没有办法对 xmm
我需要能够采用 4 个压缩整数,并使用“或”运算将它们(一个在另一个之上)折叠成一个组合整数。 最有效的方法是什么?请注意,打包整数中的 1 永远不会有公共(public)位置,因此我认为无符号“ad
我正在尝试使用 XMM 寄存器使用 SSE2 指令将 4 个数字添加到其他 4 个汇编语言中的数字。我确实成功了,但是我遇到了一些我不明白的事情。如果我以这种方式添加: movdqu xmm0, ow
使用 nasm 在 x86 汇编中编程... 使用 MOVQ 指令,我将 m64 设置为 xmm MOVQ xmm1, qword [mymem64] 现在我想将它与零进行比较,以便我可以使用 Jcc
给定一个 128 位 xmm包含两个四字(即两个 64 位整数)的寄存器: ╭──────────────────┬──────────────────╮ xmm0 │ ffeeddccbb
我正在开发一个涉及 SSE 内在函数和 XMM 寄存器的项目,并且我想使用提供的所有 16 个寄存器。我试图明确告诉编译器执行此操作,但它似乎不起作用。例如,我可能会写这样一行: register _
我正在尝试使用 GCC 风格的内联汇编将 xmm 寄存器推送到 x86_64 C 代码中的堆栈上。我查看了this的答案问题并正在使用此代码 int main(void) { asm vola
我是一名优秀的程序员,十分优秀!