Go, x64 assembly and CMOVLMI: Where is this opcode described?

huangapple go评论82阅读模式
英文:

Go, x64 assembly and CMOVLMI: Where is this opcode described?

问题

我正在阅读Go源代码,就像其他人一样,当我阅读fastrand()函数时,它在我的机器上应该在asm_amd64.s文件中,我遇到了这段代码:

    XORL    $0x88888eef, DX
    CMOVLMI BX, DX
    MOVL    DX, m_fastrand(AX)

但是我无法理解CMOVLMI应该做什么。搜索结果显示,只有Go似乎知道它的存在;我可以找到许多在AMD X86_64参考手册中定义的CMOVxx操作码,而且Wikipedia页面上有很长一段关于条件移动指令的历史,但是这个指令在那个列表中找不到。

CMOVLMI是在哪里定义的?它是Go内部汇编器特有的吗?

英文:

I was reading through the Go source code, as one does, and as I was reading the fastrand() function, which for my machine would be in the asm_amd64.s file, I came across this snippet:

    XORL    $0x88888eef, DX
    CMOVLMI BX, DX
    MOVL    DX, m_fastrand(AX)

For the life of me, I cannot figure out what CMOVLMI is supposed to be doing. A search for it reveals that only Go seems to know anything about it; I can find plenty of CMOVxx opcodes defined in the AMD X86_64 reference, and the Wikipedia Page has a long history of conditional move instructions, but this doesn't appear anywhere on that list.

Where is CMOVLMI defined? Is it unique to Go's internal assembler?

答案1

得分: 5

Go汇编器是基于Plan 9汇编器进行了一些小的改动而来的。Plan 9汇编器的设计理念是在所有体系结构上具有共同的语法和命名约定。虽然在Go工具链的框架内使汇编代码更加一致,但对于那些更熟悉传统汇编器的人来说,阅读这样的汇编代码有时可能会非常困惑。

至于所提问题中的指令CMOVLMI BX, DX,它展示了Go汇编器一些奇特的设计选择。助记符CMOVLMI必须像ARM助记符一样阅读,其中CMOV是操作,L是操作数大小(长字,32位),MI是执行条件(minus,即符号标志设置)。操作数大小遵循已建立的DEC约定,其中BWLQO分别代表字节长字四字八字。条件码遵循M68k约定;下面是一个方便的翻译表:

Go语法     Intel语法     读作
---------  ------------  ----
OS         o             溢出设置
OC         no            溢出清除
CS, LO     b, c, nae     进位设置/低于
CC, HS     nb, nc, ae    进位清除/高于或等于
EQ         e, z          等于
NE         ne, nz        不等于
LS         be, na        低于或等于
HI         nbe, a        高于
MI         s             负数
PL         ns            正数
PS         p, pe         奇偶设置
PC         np, po        奇偶清除
LT         l, nge        小于
GE         nl, ge        大于或等于
LE         le, ng        小于或等于
GT         nle, g        大于

对于像ARM那样借位的目标,助记符LOHS被交换了。对于跳转指令,Intel语法变体被识别为替代助记符,以便简化过渡。但对于其他指令,情况并非如此。

此外,Go汇编器不通过为不同的寄存器大小赋予不同的名称来区分通用寄存器大小(除了为了与AHBHCHDH的一致性而支持的ALBLCLDL)。寄存器BX可以引用任何blbxebxrbx,具体取决于指令的操作数大小。

最后,操作数的顺序遵循AT&T约定,即源操作数在前,目标操作数在后。

因此,该指令对应于Intel指令

cmovs edx, ebx

为了比较不同的表示方式,Go工具链附带的objdump实用程序支持-gnu标志。这将以GNU语法和Plan 9语法的形式转储指令,便于进行比较。

英文:

The Go assemblers are derived from the Plan 9 assemblers with little changes. The design concept of the Plan 9 assemblers is that they were supposed to have common syntax and naming conventions across all architectures. While making assembly code more consistent within the framework of the Go toolchain, it can at time be very confusing to read such assembly code for people more familiar with conventional assemblers.

As for the instruction in question, CMOVLMI BX, DX, specifically; it demonstrates some of the peculiar design choices of the Go assembler. The mnemonic CMOVLMI has to be read like an ARM mnemonic where CMOV is the operation, L is the operand size (long word, 32 bit) and MI is the condition on which it is executed (minus, i.e. sign flag set). The operand size follows the established DEC conventions where B, W, L, Q, and O stand for byte, word, long word, quad word, and octa word respectively. The condition codes follow M68k conventions; here is a handy translation table:

Go syntax  Intel syntax  read
---------  ------------  ----
OS         o             Overflow Set
OC         no            Overflow Clear
CS, LO     b, c, nae     Carry Set / LOwer
CC, HS     nb, nc, ae    Carry Clear / Higher or Same
EQ         e, z          EQual
NE         ne, nz        Not Equal
LS         be, na        Lower or Same
HI         nbe, a        Higher
MI         s             MInus
PL         ns            PLus
PS         p, pe         Parity Set
PC         np, po        Parity Clear
LT         l, nge        Less Than
GE         nl, ge        Greater or Equal
LE         le, ng        Less or Equal
GT         nle, g        Greater Than

The mnemonics LO and HS are swapped for targets where carry is the inverse of borrow, like ARM. For jump instructions, the Intel syntax variants are recognised as alternative mnemonics to ease the transition. This is however not the case for other instructions.

Additionally, the Go assembler does not distinguish general purpose register sizes by given the different register sizes different names (except for AL, BL, CL, and DL supported for consistency with AH, BH, CH, and DH). The register BX can refer to any of bl, bx, ebx, and rbx depending on the instruction's operand size.

Lastly, operand ordering follows AT&T conventions, i.e. source, then destination.

The instruction thus corresponds to the Intel instruction

cmovs edx, ebx

To compare the different representations, the objdump utility shipped with the Go toolchain supports a -gnu flag. This dumps instructions in GNU syntax in addition to Plan 9 syntax, making it easy to compare the two.

huangapple
  • 本文由 发表于 2016年12月10日 01:55:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/41066226.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定