1. LoongArch 简介¶
LoongArch 是一种新的 RISC ISA,有点像 MIPS 或 RISC-V。 目前有 3 种变体:简化的 32 位版本 (LA32R)、标准的 32 位版本 (LA32S) 和 64 位版本 (LA64)。 LoongArch 中定义了 4 个特权级别 (PLV):PLV0~PLV3,从高到低。 内核在 PLV0 运行,而应用程序在 PLV3 运行。 本文档介绍了 LoongArch 的寄存器、基本指令集、虚拟内存和一些其他主题。
1.1. 寄存器¶
LoongArch 寄存器包括通用寄存器 (GPR)、浮点寄存器 (FPR)、向量寄存器 (VR) 和在特权模式 (PLV0) 下使用的控制状态寄存器 (CSR)。
1.1.1. GPR¶
LoongArch 有 32 个 GPR($r0
~ $r31
); 在 LA32 中,每个寄存器都是 32 位宽,而在 LA64 中是 64 位宽。 $r0
硬连接到零,而其他寄存器在架构上没有特殊之处。(除了 $r1
,它被硬连接为 BL 指令的链接寄存器。)
内核使用 LoongArch 寄存器约定的一个变体,如 LoongArch ELF psABI 规范中所述,请参见参考文献
名称 |
别名 |
用途 |
跨调用保留 |
---|---|---|---|
|
|
常量零 |
未使用 |
|
|
返回地址 |
否 |
|
|
TLS/线程指针 |
未使用 |
|
|
堆栈指针 |
是 |
|
|
参数寄存器 |
否 |
|
|
返回值 |
否 |
|
|
临时寄存器 |
否 |
|
|
Percpu 基地址 |
未使用 |
|
|
帧指针 |
是 |
|
|
静态寄存器 |
是 |
注意
寄存器 $r21
在 ELF psABI 中保留,但 Linux 内核使用它来存储 percpu 基地址。 它通常没有 ABI 名称,但在内核中被称为 $u0
。 您可能还在一些旧代码中看到 $v0
或 $v1
,但它们分别是 $a0
和 $a1
的已弃用别名。
1.1.2. FPR¶
当存在 FPU 时,LoongArch 有 32 个 FPR($f0
~ $f31
)。 在 LA64 内核上,每个寄存器都是 64 位宽。
浮点寄存器约定与 LoongArch ELF psABI 规范中描述的相同
名称 |
别名 |
用途 |
跨调用保留 |
---|---|---|---|
|
|
参数寄存器 |
否 |
|
|
返回值 |
否 |
|
|
临时寄存器 |
否 |
|
|
静态寄存器 |
是 |
注意
您可能在一些旧代码中看到 $fv0
或 $fv1
,但它们分别是 $fa0
和 $fa1
的已弃用别名。
1.1.3. VR¶
目前 LoongArch 有 2 个向量扩展
具有 128 位向量的 LSX(Loongson SIMD eXtension),
具有 256 位向量的 LASX(Loongson Advanced SIMD eXtension)。
LSX 引入了 $v0
~ $v31
,而 LASX 引入了 $x0
~ $x31
作为向量寄存器。
VR 与 FPR 重叠:例如,在实现 LSX 和 LASX 的内核上,$x0
的低 128 位与 $v0
共享,而 $v0
的低 64 位与 $f0
共享;所有其他 VR 也是如此。
1.1.4. CSR¶
CSR 只能从特权模式 (PLV0) 访问
地址 |
全名 |
缩写名称 |
---|---|---|
0x0 |
当前模式信息 |
CRMD |
0x1 |
异常前模式信息 |
PRMD |
0x2 |
扩展单元使能 |
EUEN |
0x3 |
杂项控制 |
MISC |
0x4 |
异常配置 |
ECFG |
0x5 |
异常状态 |
ESTAT |
0x6 |
异常返回地址 |
ERA |
0x7 |
错误(故障)虚拟地址 |
BADV |
0x8 |
错误(故障)指令字 |
BADI |
0xC |
异常入口点地址 |
EENTRY |
0x10 |
TLB 索引 |
TLBIDX |
0x11 |
TLB 条目高位 |
TLBEHI |
0x12 |
TLB 条目低位 0 |
TLBELO0 |
0x13 |
TLB 条目低位 1 |
TLBELO1 |
0x18 |
地址空间标识符 |
ASID |
0x19 |
低半地址空间的页面全局目录地址 |
PGDL |
0x1A |
高半地址空间的页面全局目录地址 |
PGDH |
0x1B |
页面全局目录地址 |
PGD |
0x1C |
低半地址空间的页面遍历控制 |
PWCL |
0x1D |
高半地址空间的页面遍历控制 |
PWCH |
0x1E |
STLB 页面大小 |
STLBPS |
0x1F |
缩减的虚拟地址配置 |
RVACFG |
0x20 |
CPU 标识符 |
CPUID |
0x21 |
特权资源配置 1 |
PRCFG1 |
0x22 |
特权资源配置 2 |
PRCFG2 |
0x23 |
特权资源配置 3 |
PRCFG3 |
0x30+n (0≤n≤15) |
保存的数据寄存器 |
SAVEn |
0x40 |
计时器标识符 |
TID |
0x41 |
计时器配置 |
TCFG |
0x42 |
计时器值 |
TVAL |
0x43 |
计时器计数的补偿 |
CNTC |
0x44 |
计时器中断清除 |
TICLR |
0x60 |
LLBit 控制 |
LLBCTL |
0x80 |
特定于实现的控制 1 |
IMPCTL1 |
0x81 |
特定于实现的控制 2 |
IMPCTL2 |
0x88 |
TLB 重新填充异常入口点地址 |
TLBRENTRY |
0x89 |
TLB 重新填充异常 BAD(故障)虚拟地址 |
TLBRBADV |
0x8A |
TLB 重新填充异常返回地址 |
TLBRERA |
0x8B |
TLB 重新填充异常保存的数据寄存器 |
TLBRSAVE |
0x8C |
TLB 重新填充异常条目低位 0 |
TLBRELO0 |
0x8D |
TLB 重新填充异常条目低位 1 |
TLBRELO1 |
0x8E |
TLB 重新填充异常条目高位 |
TLBEHI |
0x8F |
TLB 重新填充异常异常前模式信息 |
TLBRPRMD |
0x90 |
机器错误控制 |
MERRCTL |
0x91 |
机器错误信息 1 |
MERRINFO1 |
0x92 |
机器错误信息 2 |
MERRINFO2 |
0x93 |
机器错误异常入口点地址 |
MERRENTRY |
0x94 |
机器错误异常返回地址 |
MERRERA |
0x95 |
机器错误异常保存的数据寄存器 |
MERRSAVE |
0x98 |
缓存 TAG |
CTAG |
0x180+n (0≤n≤3) |
直接映射配置窗口 n |
DMWn |
0x200+2n (0≤n≤31) |
性能监视器配置 n |
PMCFGn |
0x201+2n (0≤n≤31) |
性能监视器总计数器 n |
PMCNTn |
0x300 |
内存加载/存储观察点总控制 |
MWPC |
0x301 |
内存加载/存储观察点总状态 |
MWPS |
0x310+8n (0≤n≤7) |
内存加载/存储观察点 n 配置 1 |
MWPnCFG1 |
0x311+8n (0≤n≤7) |
内存加载/存储观察点 n 配置 2 |
MWPnCFG2 |
0x312+8n (0≤n≤7) |
内存加载/存储观察点 n 配置 3 |
MWPnCFG3 |
0x313+8n (0≤n≤7) |
内存加载/存储观察点 n 配置 4 |
MWPnCFG4 |
0x380 |
指令获取观察点总控制 |
FWPC |
0x381 |
指令获取观察点总状态 |
FWPS |
0x390+8n (0≤n≤7) |
指令获取观察点 n 配置 1 |
FWPnCFG1 |
0x391+8n (0≤n≤7) |
指令获取观察点 n 配置 2 |
FWPnCFG2 |
0x392+8n (0≤n≤7) |
指令获取观察点 n 配置 3 |
FWPnCFG3 |
0x393+8n (0≤n≤7) |
指令获取观察点 n 配置 4 |
FWPnCFG4 |
0x500 |
调试寄存器 |
DBG |
0x501 |
调试异常返回地址 |
DERA |
0x502 |
调试异常保存的数据寄存器 |
DSAVE |
ERA、TLBRERA、MERRERA 和 DERA 有时也分别称为 EPC、TLBREPC、MERREPC 和 DEPC。
1.2. 基本指令集¶
1.2.1. 指令格式¶
LoongArch 指令是 32 位宽,属于 9 种基本指令格式(及其变体)
格式名称 |
组成 |
---|---|
2R |
操作码 + Rj + Rd |
3R |
操作码 + Rk + Rj + Rd |
4R |
操作码 + Ra + Rk + Rj + Rd |
2RI8 |
操作码 + I8 + Rj + Rd |
2RI12 |
操作码 + I12 + Rj + Rd |
2RI14 |
操作码 + I14 + Rj + Rd |
2RI16 |
操作码 + I16 + Rj + Rd |
1RI21 |
操作码 + I21L + Rj + I21H |
I26 |
操作码 + I26L + I26H |
Rd 是目标寄存器操作数,而 Rj、Rk 和 Ra(“a” 代表 “additional”)是源寄存器操作数。 I8/I12/I14/I16/I21/I26 是各自宽度的立即数操作数。 较长的 I21 和 I26 存储在指令字中的单独的较高和较低部分中,用 “L” 和 “H” 后缀表示。
1.2.2. 指令列表¶
为简洁起见,此处仅列出指令名称(助记符); 请参阅参考文献以了解详细信息。
算术指令
ADD.W SUB.W ADDI.W ADD.D SUB.D ADDI.D SLT SLTU SLTI SLTUI AND OR NOR XOR ANDN ORN ANDI ORI XORI MUL.W MULH.W MULH.WU DIV.W DIV.WU MOD.W MOD.WU MUL.D MULH.D MULH.DU DIV.D DIV.DU MOD.D MOD.DU PCADDI PCADDU12I PCADDU18I LU12I.W LU32I.D LU52I.D ADDU16I.D
位移指令
SLL.W SRL.W SRA.W ROTR.W SLLI.W SRLI.W SRAI.W ROTRI.W SLL.D SRL.D SRA.D ROTR.D SLLI.D SRLI.D SRAI.D ROTRI.D
位操作指令
EXT.W.B EXT.W.H CLO.W CLO.D SLZ.W CLZ.D CTO.W CTO.D CTZ.W CTZ.D BYTEPICK.W BYTEPICK.D BSTRINS.W BSTRINS.D BSTRPICK.W BSTRPICK.D REVB.2H REVB.4H REVB.2W REVB.D REVH.2W REVH.D BITREV.4B BITREV.8B BITREV.W BITREV.D MASKEQZ MASKNEZ
分支指令
BEQ BNE BLT BGE BLTU BGEU BEQZ BNEZ B BL JIRL
加载/存储指令
LD.B LD.BU LD.H LD.HU LD.W LD.WU LD.D ST.B ST.H ST.W ST.D LDX.B LDX.BU LDX.H LDX.HU LDX.W LDX.WU LDX.D STX.B STX.H STX.W STX.D LDPTR.W LDPTR.D STPTR.W STPTR.D PRELD PRELDX
原子操作指令
LL.W SC.W LL.D SC.D AMSWAP.W AMSWAP.D AMADD.W AMADD.D AMAND.W AMAND.D AMOR.W AMOR.D AMXOR.W AMXOR.D AMMAX.W AMMAX.D AMMIN.W AMMIN.D
屏障指令
IBAR DBAR
特殊指令
SYSCALL BREAK CPUCFG NOP IDLE ERTN(ERET) DBCL(DBGCALL) RDTIMEL.W RDTIMEH.W RDTIME.D ASRTLE.D ASRTGT.D
特权指令
CSRRD CSRWR CSRXCHG IOCSRRD.B IOCSRRD.H IOCSRRD.W IOCSRRD.D IOCSRWR.B IOCSRWR.H IOCSRWR.W IOCSRWR.D CACOP TLBP(TLBSRCH) TLBRD TLBWR TLBFILL TLBCLR TLBFLUSH INVTLB LDDIR LDPTE
1.3. 虚拟内存¶
LoongArch 支持直接映射的虚拟内存和页面映射的虚拟内存。
直接映射的虚拟内存由 CSR.DMWn (n=0~3) 配置,它在虚拟地址 (VA) 和物理地址 (PA) 之间具有简单的关系
VA = PA + FixedOffset
页面映射的虚拟内存在 VA 和 PA 之间具有任意关系,该关系记录在 TLB 和页表中。 LoongArch 的 TLB 包括一个全相联 MTLB(多页面大小 TLB)和一个组相联 STLB(单页面大小 TLB)。
默认情况下,LA32 的整个虚拟地址空间配置如下
名称 |
地址范围 |
属性 |
---|---|---|
|
|
页映射,缓存,PLV0~3 |
|
|
直接映射,非缓存,PLV0 |
|
|
直接映射,缓存,PLV0 |
|
|
页映射,缓存,PLV0 |
用户模式 (PLV3) 只能访问 UVRANGE。 对于直接映射的 KPRANGE0 和 KPRANGE1,物理地址 (PA) 等于虚拟地址 (VA) 清除 bit30~31 后的值。 例如,0x00001000 的非缓存直接映射 VA 是 0x80001000,缓存直接映射 VA 是 0xA0001000。
默认情况下,LA64 的整个虚拟地址空间配置如下
名称 |
地址范围 |
属性 |
---|---|---|
|
|
页映射,缓存,PLV0~3 |
|
|
直接映射,缓存/非缓存,PLV0 |
|
|
直接映射,缓存/非缓存,PLV0 |
|
|
页映射,缓存,PLV0 |
用户模式 (PLV3) 只能访问 XUVRANGE。 对于直接映射的 XSPRANGE 和 XKPRANGE,物理地址 (PA) 等于虚拟地址 (VA) 清除 bit60~63 后的值,缓存属性由 VA 中的 bit60~61 配置:0 代表强顺序非缓存,1 代表一致性缓存,2 代表弱顺序非缓存。
目前我们只使用 XKPRANGE 进行直接映射,XSPRANGE 被保留。
举例说明:0x00000000_00001000 的强顺序非缓存直接映射 VA(在 XKPRANGE 中)是 0x80000000_00001000,0x00000000_00001000 的一致性缓存直接映射 VA(在 XKPRANGE 中)是 0x90000000_00001000,0x00000000 _00001000 的弱顺序非缓存直接映射 VA(在 XKPRANGE 中)是 0xA0000000_00001000。
1.4. 龙芯和LoongArch的关系¶
LoongArch 是一种 RISC ISA,与任何其他现有的 ISA 不同,而龙芯是一个处理器系列。 龙芯包括 3 个系列:龙芯-1 是 32 位处理器系列,龙芯-2 是低端 64 位处理器系列,龙芯-3 是高端 64 位处理器系列。 老的龙芯基于 MIPS,而新的龙芯基于 LoongArch。 以龙芯-3 为例:龙芯-3A1000/3B1500/3A2000/3A3000/3A4000 与 MIPS 兼容,而龙芯-3A5000(以及未来的修订版)都基于 LoongArch。
1.5. 参考文献¶
龙芯中科技术股份有限公司官方网站
龙芯和LoongArch的开发者网站(软件和文档)
LoongArch ISA 文档
LoongArch ELF psABI 文档
龙芯和LoongArch的Linux内核仓库