在英特尔上的任何端口运行且具有只写目标的x86非mov指令是什么?

3
有没有整数 2 操作数的 x86-64 指令,只将第一个操作数用作目的地,而不用作源 + 目的地1或仅用作源2,并且可以在Intel Haswell和/或更高版本的CPU上运行 p0156
不感兴趣的是带有 mov 的指令,即任何名称中带有 mov 的指令。
例如,BMI1 blsi eax, edx 是具有写入目的地的 2 操作数指令,但仅能在 Skylake 的端口 1 或端口 5 上执行。
1 大多数指令属于此类别,例如 add eax, ebx 表示 eax = eax + ebx2 少数 2 操作数整数指令仅使用其第一个操作数作为源,例如 cmp eax,ebx

1
ldsfriends?类似于 mov 但名称中没有 mov。显然还有 lea。不过 p0156 我不知道。 - Jester
@Jester - 问题在于lea只能在2个端口上运行。希望有一些可以在p0156上运行的东西。 - BeeOnRope
1
还有,使用哪个CPU?对于Haswell架构,Agner Fog的表格显示lea r16, mp1 p0156,不管这意味着什么。 - Jester
“in”,“lar”和“lsl”应该也符合要求,但我对端口还没有概念。 - Jester
1
“blsi”(等等)也是p15..这种模式的深层原因是什么? - harold
显示剩余4条评论
2个回答

6
以下Python脚本搜索uops.info XML文件中的指令(https://uops.info/xml.html):
#!/usr/bin/python
import xml.etree.ElementTree as ET
import re

def main():
   for XMLInstr in ET.parse('instructions.xml').iter('instruction'):
      if len(XMLInstr.findall("./operand[@type='reg']")) != 2:
         continue
      if not any(True for op in XMLInstr.findall("./operand[@type='reg']") if op.attrib.get('w', '0') == '1' and op.attrib.get('r', '0') == '0'):
         continue
      if any(re.search("\A\d*\*p0156\Z", m.attrib.get('ports', '')) for m in XMLInstr.findall("./architecture/measurement")):
         print XMLInstr.attrib['string']

if __name__ == "__main__":
    main()

如果我们从结果中排除名称中带有MOV的指令,那么剩下的指令只有CBWCWDECDQE。但是,这些指令只有隐式操作数,这可能不是您想要的内容。

此外,那些在RAX内进行符号扩展的指令都具有相同的寄存器作为源和目标,与问题所要求的不同。 (可能cwde解码为与movsx eax,ax相同的uop。)没有带有端口6 ALU(HSW及更高版本)的英特尔CPU对低8或低16寄存器进行部分寄存器重命名(SnB或IvB及更早版本需要进行IvB测试),因此您甚至不能认为单独重命名的AL或AX算作一个单独的寄存器。 - Peter Cordes
@PeterCordes 尽管它们使用相同的寄存器,https://github.com/intelxed/xed/blob/master/datafiles/xed-isa.txt 认为该指令有两个操作数(一个只写目标和一个只读源);uops.info 文件是基于此规范编写的。 - Andreas Abel
当然,AL和AX被视为不同的寄存器并不奇怪,我只是想指出我们有更好的理由来排除它们。如果cdq(edx = eax的符号位)在任何端口上运行,即使两个操作数都是隐式的,这肯定值得一提。(但它在标量移位端口p06上运行) - Peter Cordes

4

我尝试在Agner Fog的表中搜索0156。一些指令不完全符合您的要求,但似乎值得一提。


我知道您想排除mov类型的指令,但是movsx r32, r16/r8绝对没有被消除,并且绝对可以在任何p0156整数ALU端口上运行。同样的情况也适用于movsxd r64, r32。只有mov r32,r32mov r64, r64movzx r32, r8 可以被消除(0延迟,无未融合域uop)。

如果您因可能的mov-elimination而排除了movzx/sx,请再次查看movsx。它可能是唯一的这样的指令。


bextr r,r,r是2p0156。但实际上它可能是p06 + p15或其他类似的东西,使用类似移位(p06)+ BZHI(p15)uops之类的方式来实现。通过将其与一些移位或p15指令混合使用,可以测试此假设。

xchg r64, r64对于p0156来说是3个uops。根据我的反向工程,我认为每个uop都是一个不受mov-elimination影响的reg-reg mov,实际上需要一个ALU端口。其中一个涉及到的寄存器是内部的只用于微代码的寄存器,其在体系结构上不可见,但参与寄存器重命名。(我认为我们还有其他证据表明有一些额外的逻辑寄存器没有x86名称,例如使用PRF条目)。但当然整个x86指令的任何一个目的地也不是仅写入的。 leave也具有2p0156(可能不使用堆栈引擎)。

salc3p0156(从进位设置AL:未记录,不适用于64位模式),但这可能是sbb same,same和合并成RAX的uop。因此,它可能类似于lea r16,[m]imul r16,r/m16,immmovsx r16,m8,这些指令也有一个合并成体系结构写入只读目标的uop。

movbe r64, m64 可以在 SKL 上的 2p0156 p23 上运行。但是 movbe r32, m32 只能在 p15 p23 上运行,所以可能只有一个额外的 p0156 uop,或者一个 p06 uop。 bswap r64p15 p06,因此我们可以非常确定这就是 movbe 使用的指令。我假设 movbe r64,m64 实际上是 p15 p06 p23,即加载 + bswap,但 Agner 无法分解。

因此除了使用 Agner Fog 表中可能的 p0156 指令,此答案主要否定/排除其他指令,包括 movsxmovzx dst,r16


1
那个假设可以通过与一些移位或者 p15 指令混合来进行测试。确实:https://uops.info/html-ports/SKL/BEXTR_R64_R64_R64-Measurements.html - Andreas Abel
@AndreasAbel:哦,好的,应该直接查看uops.info而不是猜测Agner的结果中缺少的细节 >.< - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接