内联汇编¶
一般来说,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;
}
输出:
约束: 只支持单条微指令。如果写了多条微指令,后端在计算寄存器索引时会出现错误。
内联汇编报错规则:
- 标准块:以标量BSTART或者模板块开头的内联汇编。暂时不做特殊检查,支持随便写。
- tile指令:以Tile伪指令开头或者BSTART.PAR开头的内联汇编。仅接收块修饰指令,遇到微指令或者新的块头等非块修饰指令直接报错
- 并行块指令多指令:以微指令开头,如果有多条微指令,则必须以bstop结尾。用于通过内联汇编手写完整的并行块函数体
- 并行块指令单指令:仅有一条微指令
- 逃逸:可能后面对报错规则会有扩展或者改动。先提供
.unsafeasmdirective 保证这些规则可以绕过去。并行块内联汇编有疑问可联系 牟良雨 30030301