LoongArch-Documentation
LoongArch-Documentation copied to clipboard
Proposal: 操作原生宽度(GRLen)的指令助记符别名
背景
在目前的移植适配实践中,对绝大部分涉及手写汇编的软件,都需要根据 GRLen、FRLen 不同,选择不同的基本操作助记符。不像 RISC-V,LoongArch 所有指令的操作宽度都是固定的(由后缀表示),这要求我们必须反复根据 is64Bit 之类的条件选择不同的指令编码。例如:
// LLVM D136074
BuildMI(MBB, MBBI, DL,
TII->get(STI.is64Bit() ? LoongArch::SRLI_D : LoongArch::SRLI_W),
VR)
.addReg(SPReg)
.addImm(ShiftAmount)
.setMIFlag(MachineInstr::FrameSetup);
BuildMI(MBB, MBBI, DL,
TII->get(STI.is64Bit() ? LoongArch::SLLI_D : LoongArch::SLLI_W),
SPReg)
.addReg(VR)
.addImm(ShiftAmount)
.setMIFlag(MachineInstr::FrameSetup);
// libffi
#if __SIZEOF_POINTER__ == 8
# define PTRS 8
# define LARG ld.d
# define SARG st.d
#else
# define PTRS 4
# define LARG ld.w
# define SARG st.w
#endif
// glibc
// REG_L & ADDI & BSTRINS 是这个 issue 所示问题的受害者
LA a0, t0, main
REG_L a1, sp, 0 // actually ld.d
ADDI a2, sp, SZREG // actually addi.d
/* Adjust $sp for 16-aligned */
BSTRINS sp, zero, 3, 0 // actually bstrins.d
// linux
// 情况与 glibc 类似
copy_word:
/* copy page word by word */
REG_L s4, s1, 0
REG_S s4, s3, 0
PTR_ADDI s3, s3, SZREG
PTR_ADDI s1, s1, SZREG
LONG_ADDI s5, s5, -1
beqz s5, process_entry
b copy_word
b process_entry
类似的糟心事在每个项目都要重复发生一遍。
多数时候,LoongArch 汇编相关的开发工作都仅涉及手写汇编文本,而非直接生成、操作机器码。(上文的例子中,只有 LLVM 的使用姿势不被覆盖。)
如果在汇编语法层面可以提供语法糖,根据当前 -march 配置自动选择相应指令的相应宽度的形式,可能对下游汇编开发者是一种生产力的解放。
提议
- 新增
*.n、*.nu操作符宽度后缀,用来表示与当前汇编器所 target 的march的 GRLen 相同的宽度。 - 所有语义上适合以原生宽度对待的、单操作符宽度后缀的指令,都应支持
.n[u]后缀,作为相应.w[u]或.d[u]具体指令的别名。例如ld.n、mulh.nu、slli.n。 - 语义上已经非常局限于某个领域/场景,因而不适合以原生宽度对待的指令;以及带多个操作符宽度后缀的指令,不增加相应
.n[u]后缀的支持。例如mulw.d.w、crc.w.w.w等等。
讨论
- Bikeshedding(不要后缀,跟其他只操作原生宽度的指令如
xor一样?取别的后缀?)
@xry111 @ChenghuaXu @scylaac @FreeFlyingSheep @yetist 大家怎么看?
- 新增
*.n、*.nu操作符宽度后缀,用来表示与当前汇编器所 target 的march的 GRLen 相同的宽度。
我觉得根据 -mabi= 的值更合理,因为我们进行这种操作的时候一般是操作指针(地址),而不是真的关心硬件寄存器多宽。
那么后缀用 *.p 似乎更好?