跳转至

内联汇编

一般来说,clang与GCC的内联汇编扩展是高度兼容的,允许使用与GCC内联汇编相同的约束、修饰符和操作数。本小节主要基于LinxISA介绍内联汇编的常用写法。通用内联汇编格式:

 asm [ volatile ] (  
         汇编序列
         [ : 输出操作数 ]                      /* 可选 */
         [ : 输入操作数  ]                     /* 可选 */
         [ : list of clobbered registers ]     /* 可选 */
         );

基本格式主要包括四个部分,必须包含汇编序列,其他部分可选。汇编示意如下:

void foo(void)
{
   int output, val1, val2;
   ...
   asm volatile ("BSTART\n"
        "sub %1, %2, ->t\n"
        "add a1, t#1, ->%0\n"
        "BSTOP\n"
        :"=r"(output):"r"(val1),"r"(val2):);
   ...
   return;
}

'volatile'为可选关键字,表示不需要编译器对下面的汇编代码做任何优化。关键字也支持'asm'和'volatile'的写法。下表展示了操作数类型描述及输出操作数的修饰:

操作数约束 描述
r 寄存器类型的操作数
i 立即数类型的操作数
m 内存类型的操作数
修饰约束 描述
= 输出操作数(只写)
+ 输入/输出操作数(读写)

并行块内联汇编

支持编写单指令的并行块内联汇编。目的是便于支持fp8的类型转换,做到只修改库就能支持。

输入:

void __vec__ foo(...) {
  asm volatile ("l.fcvt %1.fd, ->%0.fb" : "=vr"(to) : "vr"(from));
  p[...] = to;
}

输出:

foo:
  l.fcvt vt#1.fd, ->vt.fb
  l.sb vt#1.sb, [...]

约束: 只支持单条微指令。如果写了多条微指令,后端在计算寄存器索引时会出现错误。


内联汇编报错规则:

  1. 标准块:以标量BSTART或者模板块开头的内联汇编。暂时不做特殊检查,支持随便写。
  2. tile指令:以Tile伪指令开头或者BSTART.PAR开头的内联汇编。仅接收块修饰指令,遇到微指令或者新的块头等非块修饰指令直接报错
  3. 并行块指令多指令:以微指令开头,如果有多条微指令,则必须以bstop结尾。用于通过内联汇编手写完整的并行块函数体
  4. 并行块指令单指令:仅有一条微指令
  5. 逃逸:可能后面对报错规则会有扩展或者改动。先提供.unsafeasm directive 保证这些规则可以绕过去。

    并行块内联汇编有疑问可联系 牟良雨 30030301