关键词:
作者:蒋卫峰 李涛
前言
最近龙芯中科宣布,龙芯2K0500开发板已与OpenHarmony(开源鸿蒙系统)完成了适配验证,LoongArch平台实现初步支持OpenHarmony。本系列文章将对loongarch架构进行介绍。
龙芯架构LoongArch是龙芯中科公司自主设计的一种精简指令集计算机(RISC)风格的指令系统架构。其分为32位和64位两个版本,分别称为LA32架构和LA64架构。本文主要对其中的基础部分进行介绍。本文中的主要信息来源于龙芯目前公开的资料。
1. 指令编码格式
下图为龙芯架构的典型指令编码格式,大部分指令格式都符合这些格式:
上图中解释:
-
指令长度固定为32位,无论是LA32还是LA64
-
上图中共有2R-type、3R-type、2RI8-type等9种编码格式,其中R表示寄存器,I表示立即数。如2RI8-type表示指令格式中除了操作码opcode外,还指定了2个寄存器和一个8位的立即数。
2. 指令汇编格式
loongarch的指令汇编格式主要包括指令名和操作数这两部分,其中指令名格式比较特别。loongarch中指令名可以有前缀和后缀字母,前缀字母有:
-
V:128位向量指令
-
XV:256位向量指令
-
F:非向量浮点指令
-
VF:128位向量浮点指令
-
XVF:256位向量浮点指令
后缀字母有:
-
对于整数类型指令:.B、.H、.W、.D、.BU、.HU、.WU、.DU分别表示有符号字节、有符号半字、有符号字、有符号双字、无符号字节、无符号半字、无符号字、无符号双字。其中双字仅存在于LA64
-
对于浮点类型指令:.H、.S、.D、.W、.L、.WU、.LU分别表示半精度、单精度、双精度的浮点数,以及有符号字、有符号双字、无符号字、无符号双字的整数。其中双字仅存在于LA64
举例如下:
-
add.w rd, rj, rk
: 表示寄存器rj和rk相加,结果写入rd。无前缀,后缀.w表示操作数据的位数为32位。 -
fadd.s fd, fj, fk
:表示浮点寄存器fj和fk相加,结果写入fd。前缀为f,表示为非向量浮点运算指令。后缀为.s,表示操作数据为单精度浮点数。 -
mulw.d.wu rd, rj, rk
:表示寄存器rj和rk相乘,结果写入rd。无前缀。该指令有两个后缀,.d表示rd中结果为双精度浮点数,.wu表示rj和rk中数据为无符号32位整数。
3. 基础指令介绍
3.1 整数运算类
loongarch中有32个通用寄存器,LA32和LA64中分别为32位和64位长度。loongarch中可用这些寄存器执行整数类的指令。
loongarch支持基本的整数运算,有:
-
加减乘除的add、sub、mul、div等指令。
如
addi.w rd, rj, si12
表示将寄存器rj和有符号立即数si12进行32位加法运算,结果写入rd。 -
逻辑移位、算术移位的sll、srl、sra、rotr等指令。
如
srl.w rd, rj, rk
表示将寄存器rj作逻辑右移rk位,移位结果符号扩展写入寄存器rd。 -
与或非等操作的and、or、nor、xor、andi、ori等指令。
如
and rd, rj, rk
表示将寄存器rj和rk作位与运算,结果写入rd。 -
slt、sltu、slti、sltui指令用于小于比较。
-
如
slt rd, rj, rk
表示将寄存器rj和rk视为有符号整数作小于比较,将结果写入rd。 -
如
sltu rd, rj, rk
表示将寄存器rj和rk视为无符号整数作小于比较,将结果写入rd
-
-
lu12i.w、lu32i.d等指令用于立即数连接。
如
lu12i.w rd, si20
表示将20位立即数si20最低位连接上12位的0,然后符合扩展后写入rd。 -
一些位操作指令,有clo、clz、ctz等指令、用于符号扩展的ext指令等。
-
如
ext.w.b rd, rj
表示将rj中低8位数据进行符号扩展后写入rd。 -
如
clz.w rd, rj
表示从第31位开始计数寄存器rj中连续0的个数,结果写入rd。
-
3.2 浮点运算类
loongarch中有32个浮点寄存器,在LA32和LA64中均为64位。loongarch中可用这些寄存器进行浮点类指令。
loongarch中支持基本的浮点运算,有:
-
加减乘除相关的fadd、fsub、fmul、fdiv、fmadd、fnmsub等指令。
-
如
fadd.s fd, fj, fk
表示将浮点寄存器fj和fk进行单精度加法运算,结果写入fd。 -
如
fmsub.d fd, fj, fk, fa
表示将浮点寄存器fj和fk进行双精度乘法运算,然后再与fa进行双精度减法运算,结果写入fd。
-
-
浮点比较运算相关的fcmp.cond指令。其中.cond可以为多种比较含义的助记符。
如
fcmp.ceq.s cc, fj, fk
表示进行相等比较。 -
浮点转换类的fcvt、ffint、frint等指令。
-
如
fcvt.s.d fd, fj
表示将浮点寄存器fj中的双精度浮点数转换为单精度,并写入fd。 -
如
ftintrne.w.s fd, fj
表示将浮点寄存器fj中的单精度浮点数转换为32位整数写入到fd,并采用“向最近的偶数舍入”。
-
-
浮点搬运类型指令,包括fmov、fsel、movgr2fr等指令。
-
如
fsel fd, fj, fk, ca
表示如果条件标志寄存器ca的值为0,则将浮点寄存器fj写入fd,否则将fk写入fd。 -
如
movgr2fr.w fd, rj
表示将rj的低32位写入浮点寄存器fj的低32位。
-
-
一些特殊浮点运算指令,有取最小/最大值运算的fmax、fmin、fmaxa、fmina指令、取绝对值的fabs指令、取反的fneg指令、开方和倒数运算相关的fsqrt和frecip等指令,等等。
如
fmaxa.s fd, fj, fk
表示fd中写入浮点寄存器fj、fk中绝对值的较大者。
3.3 访存指令
和一般RISC一样,loongarch中通过load/store类指令进行访存,有:
-
ld/st指令。
-
如
ld.b rd, rj, si12
表示将rj+有符号立即数si12作为虚拟地址,从该地址取出一个字节数据写入rd。 -
如
st.w rd, rj, si12
表示将rj+有符号立即数si12作为虚拟地址,将rd低32位数据写入该地址。
-
-
ldx/stx指令。相比ld/st指令,区别是虚拟地址表示不同:
如
ldx.b rd, rj, rk
表示将rj+rk作为虚拟地址,从该地址取出一个字节数据写入rd。 -
ldptr/stptr指令。相比ld/st指令,区别是立即数表示不同,即立即数的最大位数不同以及其表示的偏移以4字节对齐。
如
stptr.w rd, rj, si14
表示将rj+有符号立即数si14*4作为虚拟地址,从该地址取出32位数据写入rd。 -
ldgt/stgt、ldle/stle等边界检查访存指令。
如
ldgt.b rd, rj, rk
表示将rj作为虚拟地址,如果rj大于rk,则从该地址中取出一个字节数据到rd。否则触发异常。 -
浮点访存指令,包括fld/fst、fldx/fstx、fldgt/fstgt指令等。与前面指令含义基本一致,只不过是用浮点寄存器作为目标寄存器。
如
fld.s fd, rj, si12
表示将rj+有符号立即数si12作为虚拟地址,从该地址取出一个单精度浮点数数据写入fd。
3.4 转移指令
下面对loongarch中的转移指令进行介绍:
-
无条件跳转指令b。
如
b offs26
表示无条件跳转到地址pc+offs26*4,其中offs26为26位的立即数偏移量,且4字节对齐。 -
无条件跳转指令jirl。和b的区别是,会将pc+4的值进行保存。
如
jirl rd, rj, offs16
表示无条件跳转到地址pc+offs16*4,然后将pc+4写入rd。其中offs16为16位的立即数偏移量,且4字节对齐。 -
无条件跳转指令bl。和jirl的区别是,pc+4的值固定保存在r1中。r1别名ra,一般用作保存返回地址。
如
bl offs26
表示无条件跳转到地址pc+offs26*4,然后将pc+4写入r1。其中offs26为26位的立即数偏移量,且4字节对齐。 -
条件转移指令beq、bne、blt等。
如
beq rj, rd, offs16
表示当rj和rd相等时才跳转到地址pc+offs16*4。
3.5 一些补充的基础指令
在阅读linux上loongarch架构相关代码的时候,遇到了一些loongarch资料中没有写出来的指令。本小节中将这些指令列出,其中指令的含义是根据上下文推测出来的。
- move:如
move rd, rj
将rj中值复制到rd - li:如
li.w rd, 1
将rd中值置为1 - la:如
la.abs rd, label
将label对应地址赋值给rd - jr:如
jr ra
跳转到ra中地址,可能会有一些额外的操作
4. 汇编案例说明
上图中描述了loongarch中寄存器的使用约定,与其他的架构其实大同小异。有栈指针寄存器,有通用和浮点的传参寄存器,有返回地址寄存器等。下面结合代码进行说明。
以下为一段c语言代码:
...
extern long
nested(long a, long b, long c, long d,
long e, long f, long g, long h, long i);
long normal(void)
return nested(1, 2, 3, 4, 5, 6, 7, 8, 9);
对应loongarch汇编如下:
normal:
// 分配栈帧
addi.d $sp, $sp, -32
// 传参9,传参寄存器不够,储存在栈上
addi.w $t0, $zero, 9
stptr.d $t0, $sp, 0
// 传参8-1,使用传出寄存器a7-a0
addi.w $a7, $zero, 8
addi.w $a6, $zero, 7
addi.w $a5, $zero, 6
addi.w $a4, $zero, 5
addi.w $a3, $zero, 4
addi.w $a2, $zero, 3
addi.w $a1, $zero, 2
addi.w $a0, $zero, 1
// 将返回地址保存到栈上
st.d $ra, $sp, 24
// 调用nested函数
bl %plt(nested)
// 恢复返回地址到ra
ld.d $ra, $sp, 24
// 恢复栈帧
addi.d $sp, $sp, 32
// 函数返回
jr $ra
loongarch的栈帧可用下图表示:
总结
本文介绍了loongarch架构中的一些基础指令,如整数和浮点运算指令、转移指令、访存指令,并结合案例对loongarch汇编语言的写法进行了说明。下一篇文章将会介绍loongarch中的原子指令、栅障指令,及其用法。
更多原创内容请关注:深开鸿技术团队
入门到精通、技巧到案例,系统化分享OpenHarmony开发技术,欢迎投稿和订阅,让我们一起携手前行共建生态。
https://ost.51cto.com/#bkwz
loongarch架构之指令集(代码片段)
...码格式1.指令编码要求2.指令汇编助记格式前言龙芯架构LoongArch是一种精简指令集计算机(RISC)。提示:以下是本篇文章正文内容,下面案例可供参考一、龙芯架构是什么?1、龙芯架构具有RISC指令架构的典型... 查看详情
优化系列详解龙芯loongarch指令集架构
...TE:2021.8.5文章目录1、参考2、龙芯介绍3、龙芯相关资料4、LoongArch架构1、参考详解龙芯LoongArch指令集架构2、龙芯介绍龙芯–维基百科【优化系列】龙芯loongson简介3、龙芯相关资料龙芯官网:首页(loongson.cn)龙芯社区:https://... 查看详情
国际主流固件接口组织uefi全面支持loongarch,龙架构已完成上游tianocoreedk2代码合并...
...;UEFI官方组织在发布的UEFIspecificationV2.10规范中全面支持了LoongArch64架构以及部分LoongArch32架构。近期,龙芯团队又完成了LoongArch基础代码与UEFI上游TianoCoreEDK2的合并,LoongArch进入TianoCoreEDK2主分支,并成为继X86、ARM、Ri 查看详情
重磅|linux内核5.19初步支持loongarch架构
...ff0c;北京时间2022年6月4日清晨,Linux内核社区正式合并LoongArch架构支持代码。随着Linux-5.19的rc1版本的正式发布,LoongArch体系结构主体部分的源码已合并到内核主线之中,其余相关代码正在进行审查。滑动查看更多1LA架... 查看详情
国际主流产品信息管理规范smbios支持loongarch架构
SMBIOS支持龙架构(LoongArch™)龙芯生态标准统一近日,DMTF(分布式管理任务组)宣布SMBIOS规范支持龙架构(LoongArch™),自此基于龙架构平台开发的基础硬件信息都将规范统一显示,龙架构也... 查看详情
基础篇.arm架构介绍(代码片段)
ARM架构介绍(1)本章主要介绍ARM架构通用知识,不仅仅包括ARMv7\\ARMv8/ARMv91.ARM体系结构介绍ARM公司主要向客户提供处理器IP。ARM体系结构是一种硬件规范,主要用来约定指令集、芯片内部体系结构等。以指令集为... 查看详情
jvm基础认知篇(下)(代码片段)
JVM基础认知篇1.JVM的执行流程2.JVM的架构模型3.JVM的生命周期4.JVM的发展历史5.JVM的版本历史1.JVM的执行流程2.JVM的架构模型Java编译器输入的指令流基本上是一种基于栈的指令集架构,另外一种指令集架构则是基于寄存器的指令... 查看详情
android_一如何获取linux中的可执行文件指令之termux使用介绍(代码片段)
...令的技术必不可少。我们知道linux操作系统大多数都是x86架构,而Android现在基本都是arm架构,那么直接从Linux操作系统中拷贝指令到android,势必是无法使用的 查看详情
计基2—riscv指令集介绍与汇编(代码片段)
和学校里学的x86架构不同,RISC-V指令格式的设计十分简洁、高效。为了在下一节课能够更好地理解如何搭建CPU,首先需要对RISC-V指令集有基本的了解。该文章大部分图片来自彭东老师的计算机基础实战。什么是指令集ÿ... 查看详情
计基2—riscv指令集介绍与汇编(代码片段)
和学校里学的x86架构不同,RISC-V指令格式的设计十分简洁、高效。为了在下一节课能够更好地理解如何搭建CPU,首先需要对RISC-V指令集有基本的了解。该文章大部分图片来自彭东老师的计算机基础实战。什么是指令集ÿ... 查看详情
并发基础线程介绍(代码片段)
一、线程的简介线程,有时被称为轻量级进程(LightweightProcess,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(有一个程序计数器,它的作用是存放下一条指令所在单元的地址的地方),寄存器集合(... 查看详情
自主生态再进一步,龙芯中科完成.net3.1-loongarch64平台研发
近日,龙芯中科.NET团队完成了.NET3.1-LoongArch64平台研发工作,研发的成功标志着围绕龙芯自主指令系统LoongArch的生态建设成果再进一步。龙芯自主指令系统LoongArch基于龙芯二十年的CPU研制和生态建设积累,LoongArch从顶... 查看详情
prometheus入门(代码片段)
prometheus入门(一)大纲基础架构介绍官方站点以及后期用到的软件包介绍prometheus以及各类exporter的使用告警配置高可用架构docker&k8s监控基础架构介绍官方站点:https://prometheus.io官方架构图:大体组成部分以及流程介绍数据采集... 查看详情
龙芯ceph集群手动部署(loongarch架构cephn版手动部署monosdmgrdashboard服务)(代码片段)
基础环境信息CPU:龙芯3C5000L×4硬盘:一块256的nvme用于安装操作,3块2T的HDD盘用作Ceph存储盘。OS版本:Loongnix-server8.3Ceph版本:Ceph14.2.21(Nautilus)部署目标进行Ceph集群典型架构(最小化)手动... 查看详情
计算机系统基础:程序的执行和存储访问---学习心得
...执行过程。我们在计算机系统基础(一)中主要是以IA-32架构来讲解程序的机器级表示的,所以,我们这里会介绍在IA-32中一条指令的执行过程,最后简单介绍一下CPU的基本功能和基本结构,包括数据通路和控制器的基本功能和... 查看详情
国际知名计算机视觉和机器学习软件开源平台opencv正式支持龙架构
...介绍近期,OpenCV开源社区正式合入了对龙架构(LoongArch™)支持的代码,基于龙架构自主指令系统,优化后的OpenCV性能显著提升。OpenCV是一款跨平台的计算机视觉和机器学习软件平台,在计算机视觉领域广... 查看详情
cpu开发与存算一体技术
...队”。中科龙芯引进消化吸收MIPS,推出了自主指令系统LoongArch,是底层自主化程度最高的国产化CP 查看详情
celery基础(代码片段)
目录一、celery介绍二、celery架构消息中间件任务执行单元任务结果存储使用场景三、celery使用方式一:在一个文件夹内的三个页面方式二:worker单独做一个项目文件,添加任务和获取结果分离出来(执行异步任务)执行延迟任务... 查看详情