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 规范中所述,详见 参考文献

名称

别名

用法

跨调用保留

$r0

$zero

常数零

未使用

$r1

$ra

返回地址

$r2

$tp

TLS/线程指针

未使用

$r3

$sp

栈指针

$r4-$r11

$a0-$a7

参数寄存器

$r4-$r5

$v0-$v1

返回值

$r12-$r20

$t0-$t8

临时寄存器

$r21

$u0

Per-CPU 基地址

未使用

$r22

$fp

帧指针

$r23-$r31

$s0-$s8

静态寄存器

注意

寄存器 $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 规范中所述相同

名称

别名

用法

跨调用保留

$f0-$f7

$fa0-$fa7

参数寄存器

$f0-$f1

$fv0-$fv1

返回值

$f8-$f23

$ft0-$ft15

临时寄存器

$f24-$f31

$fs0-$fs7

静态寄存器

注意

你可能还会在一些旧代码中看到 $fv0$fv1,然而它们分别是 $fa0$fa1 的已弃用别名。

1.1.3. 向量寄存器(VR)

目前 LoongArch 有 2 个向量扩展

  • LSX(龙芯 SIMD 扩展),具有 128 位向量,

  • LASX(龙芯高级 SIMD 扩展),具有 256 位向量。

LSX 引入了 $v0 ~ $v31,而 LASX 引入了 $x0 ~ $x31 作为向量寄存器。

向量寄存器与浮点寄存器重叠:例如,在实现 LSX 和 LASX 的核心上,$x0 的低 128 位与 $v0 共享,$v0 的低 64 位与 $f0 共享;所有其他向量寄存器也同样如此。

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 重填异常出错(产生故障的)虚拟地址

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

Opcode + Rj + Rd

3R

Opcode + Rk + Rj + Rd

4R

Opcode + Ra + Rk + Rj + Rd

2RI8

Opcode + I8 + Rj + Rd

2RI12

Opcode + I12 + Rj + Rd

2RI14

Opcode + I14 + Rj + Rd

2RI16

Opcode + I16 + Rj + Rd

1RI21

Opcode + I21L + Rj + I21H

I26

Opcode + I26L + I26H

Rd 是目的寄存器操作数,而 Rj、Rk 和 Ra(“a” 代表 “additional”,即附加)是源寄存器操作数。I8/I12/I14/I16/I21/I26 是对应位宽的立即数操作数。较长的 I21 和 I26 存储在指令字的独立高低部分中,由“L”和“H”后缀表示。

1.2.2. 指令列表

为简起见,此处仅列出指令名称(助记符);详情请参见 参考文献

  1. 算术指令

    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
    
  2. 位移指令

    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
    
  3. 位操作指令

    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
    
  4. 分支指令

    BEQ BNE BLT BGE BLTU BGEU BEQZ BNEZ B BL JIRL
    
  5. 加载/存储指令

    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
    
  6. 原子操作指令

    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
    
  7. 屏障指令

    IBAR DBAR
    
  8. 特殊指令

    SYSCALL BREAK CPUCFG NOP IDLE ERTN(ERET) DBCL(DBGCALL) RDTIMEL.W RDTIMEH.W RDTIME.D
    ASRTLE.D ASRTGT.D
    
  9. 特权指令

    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 的整个虚拟地址空间配置如下

名称

地址范围

属性

UVRANGE

0x00000000 - 0x7FFFFFFF

页映射,可缓存,PLV0~3

KPRANGE0

0x80000000 - 0x9FFFFFFF

直接映射,不可缓存,PLV0

KPRANGE1

0xA0000000 - 0xBFFFFFFF

直接映射,可缓存,PLV0

KVRANGE

0xC0000000 - 0xFFFFFFFF

页映射,可缓存,PLV0

用户模式(PLV3)只能访问 UVRANGE。对于直接映射的 KPRANGE0 和 KPRANGE1,PA 等于清除了第 30~31 位的 VA。例如,0x00001000 的不可缓存直接映射 VA 是 0x80001000,而 0x00001000 的可缓存直接映射 VA 是 0xA0001000。

默认情况下,LA64 的整个虚拟地址空间配置如下

名称

地址范围

属性

XUVRANGE

0x0000000000000000 - 0x3FFFFFFFFFFFFFFF

页映射,可缓存,PLV0~3

XSPRANGE

0x4000000000000000 - 0x7FFFFFFFFFFFFFFF

直接映射,可缓存 / 不可缓存,PLV0

XKPRANGE

0x8000000000000000 - 0xBFFFFFFFFFFFFFFF

直接映射,可缓存 / 不可缓存,PLV0

XKVRANGE

0xC000000000000000 - 0xFFFFFFFFFFFFFFFF

页映射,可缓存,PLV0

用户模式(PLV3)只能访问 XUVRANGE。对于直接映射的 XSPRANGE 和 XKPRANGE,PA 等于清除了第 60~63 位的 VA,且缓存属性由 VA 中的第 60~61 位配置:0 表示强序不可缓存,1 表示一致性可缓存,2 表示弱序不可缓存。

目前我们仅将 XKPRANGE 用于直接映射,而 XSPRANGE 是保留的。

付诸实践:0x00000000_00001000 的强序不可缓存直接映射 VA(在 XKPRANGE 中)为 0x80000000_00001000,一致性可缓存直接映射 VA(在 XKPRANGE 中)为 0x90000000_00001000,而弱序不可缓存直接映射 VA(在 XKPRANGE 中)为 0xA0000000_00001000。

1.4. 龙芯(Loongson)与 LoongArch 的关系

LoongArch 是一种不同于任何其他现有指令集的 RISC ISA,而龙芯(Loongson)是一个处理器系列。龙芯包括 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 内核仓库