了解更多开源请访问:开源基础软件社区https://ost.51cto.com前言龙芯近日宣布龙芯2K0500开发板完成了OpenHarmony(开源鸿蒙系统)适配验证,龙拱平台已初步支持OpenHarmony。本系列文章将介绍loonarch架构。LoongArch是龙芯中科自主设计的精简指令集计算机(RISC)式指令系统架构。分为32位和64位两个版本,分别称为LA32架构和LA64架构。本文主要介绍基础部分。本文主要信息来源于龙芯当前的公开信息。1.指令编码格式下图为龙芯架构的典型指令编码格式。大多数指令格式都符合这些格式:上图说明:指令长度固定为32位,无论是LA32还是LA64,都有2R型,3R型,2RI8等9种编码格式-type等,其中R表示寄存器,I表示立即值。例如2RI8-type表示指令格式中除了opcode操作码外,还指定了2个寄存器和一个8位的立即数。2、指令汇编格式loonarch的指令汇编格式主要包括指令名和操作数两部分,指令名格式比较特殊。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分别表示半精度、单精度、双精度浮点数、signedWord、signed双字,无符号字,无符号双字的整数。双字只在LA64中存在,如下:add.wrd,rj,rk:表示寄存器rj和rk相加,结果写入rd。无前缀,后缀.w表示运算数据的位数为32位。fadd.sfd,fj,fk:表示将浮点寄存器fj和fk相加,结果写入fd。前缀是f,表示非向量浮点运算指令。后缀为.s,表示运算数据为单精度浮点数。mulw.d.wurd,rj,rk:表示寄存器rj乘以rk,结果写入rd。没有前缀。该指令有两个后缀,.d表示rd中的结果为双精度浮点数,.wu表示rj和rk中的数据为无符号32位整数。3、基本指令介绍(1)整数运算类loonarch中共有32个通用寄存器,LA32和LA64的长度分别为32位和64位。这些寄存器可以在loongarch中用于执行类似整数的指令。Loongarch支持基本的整数运算,包括:add、sub、mul、div等加减乘除指令。例如addi.wrd,rj,si12表示对寄存器rj和有符号立即数si12进行32位加法运算,并将结果写入rd。逻辑移位、算术移位sll、srl、sra、rotr等指令。例如srl.wrd,rj,rk表示将寄存器rj逻辑右移rk位,并将移位结果的符号扩展写入寄存器rd。and,or,nor,xor,andi,ori等指??令用于AND或NOT等操作。例如,andrd,rj,rk表示寄存器rj和rk按位与,结果写入rd。slt、sltu、slti和sltui指令用于小于比较。例如,sltrd,rj,rk表示将寄存器rj和rk视为有符号整数进行小于比较,并将结果写入rd。例如slturd,rj,rk表示将寄存器rj和rk当做无符号整数进行小于比较,结果写入rdlu12i.w,lu32i.d等指令,立即数据连接。例如lu12i.wrd,si20表示将20位立即数si20的最低位与12位0相连,符合扩展后写入rd。一些位操作指令包括clo、clz、ctz等指令,以及用于符号扩展的ext指令。例如ext.w.brd,rj表示将rj中的低8位数据进行符号扩展后写入rd。例如clz.wrd,rj表示从第31位开始统计寄存器rj中连续0的个数,并将结果写入rd。(2)浮点运算类loongarch中有32个浮点寄存器,LA32和LA64都是64位的。这些寄存器可以在loongarch中用于浮点指令。Loongarch支持基本的浮点运算,包括:fadd、fsub、fmul、fdiv、fmadd、fnmsub等与加减乘除相关的指令。例如fadd.sfd,fj,fk表示对浮点寄存器fj和fk进行单精度加法运算,结果写入fd。例如fmsub.dfd,fj,fk,fa表示对浮点寄存器fj和fk进行双精度乘法运算,再与fa进行双精度减法运算,并将结果写入fd。fcmp.cond指令与浮点比较操作有关。其中.cond可以是各种比较意义的助记符。比如fcmp.ceq.scc,fj,fk代表相等比较。浮点转换类的fcvt、ffint、frint等指令。例如fcvt.s.dfd,fj表示将浮点寄存器fj中的双精度浮点数转换为单精度写入fd。例如ftintrne.w.sfd,fj表示将浮点寄存器fj中的单精度浮点数转换为32位整数写入fd,并采用“四舍五入到最接近的偶数”。浮点传送类型指令,包括fmov、fsel、movgr2fr等指令。例如fselfd,fj,fk,ca表示如果条件标志寄存器ca的值为0,则将浮点寄存器fj写入fd,否则将fk写入fd。例如movgr2fr.wfd,rj表示将rj的低32位写入浮点寄存器fj的低32位。一些特殊的浮点运算指令包括最小值/最大值运算的fmax、fmin、fmaxa、fmina指令,绝对值运算的fabs指令,取反运算的fneg指令,平方根和倒数运算相关的fsqrt和frecip指令等。例如、fmaxa.sfd、fj、fk代表fd中写入的浮点寄存器fj、fk的绝对值较大者。(3)内存访问指令与一般的RISC相同。Loongarch使用加载/存储指令访问内存,包括:ld/st指令。例如ld.brd,rj,si12表示以rj+有符号立即数si12作为虚拟地址,从该地址取出一个字节的数据写入rd。例如st.wrd,rj,si12表示将rj+有符号立即数si12作为虚拟地址,将rd的低32位数据写入该地址。ldx/stx指令。与ld/st指令相比,区别在于虚拟地址表示不同:例如ldx.brd,rj,rk表示将rj+rk作为虚拟地址,从中取出一个字节的数据这个地址并写入rd。ldptr/stptr指令。与ld/st指令相比,区别在于立即数的表示方式不同,即立即数的最大位数不同,其表示的偏移量以4字节对齐。例如stptr.wrd,rj,si14表示以rj+有符号立即数si14*4作为虚拟地址,从该地址取出32位数据写入rd。ldgt/stgt、ldle/stle等边界检查内存访问指令。例如ldgt.brd,rj,rk表示rj作为虚拟地址。如果rj大于rk,则从该地址取一个字节的数据到rd。否则会引发异常。浮点内存访问指令,包括fld/fst、fldx/fstx、fldgt/fstgt指令等,含义与前面的指令基本相同,只是将浮点寄存器作为目标寄存器。例如fld.sfd,rj,si12表示以rj+有符号立即数si12作为虚拟地址,从该地址取出一个单精度浮点数数据写入fd。(4)转移指令下面介绍loongarch中的转移指令:无条件跳转指令b.例如boffs26表示无条件跳转到地址pc+offs26*4,其中offs26为26位立即数偏移量,4字节对齐。无条件跳转指令jirl。与b不同的是,pc+4的值会被保存。比如jirlrd,rj,offs16表示无条件跳转到地址pc+offs16*4,然后将pc+4写入rd。其中offs16为16位立即数偏移量,4字节对齐。无条件跳转指令bl。与jirl不同的是pc+4的值是固定在r1中的。r1别名ra,一般用来保存返回地址。例如bloffs26表示无条件跳转到地址pc+offs26*4,然后将pc+4写入r1。其中offs26为26位立即数偏移量,4字节对齐。条件转移指令beq、bne、blt等。例如beqrj、rd、offs16表示当rj和rd相等时跳转到地址pc+offs16*4。(5)一些补充的基础指令在阅读linux上loongarch架构相关的代码时,遇到了一些loongarch资料中没有写的指令。这些说明列在本小节中,其中说明的含义是从上下文中推断出来的。move:如moverd,rj将rj中的值复制到rd中。li:如li.wrd,1将rd的中值设为1。la:如la.absrd,label将label对应的地址赋值给rd。jr:如果jrra跳转到ra中的地址,可能会有一些额外的操作。4.汇编案例说明上图描述了loongarch中寄存器的使用约定,与其他架构类似。有堆栈指针寄存器、通用和浮点参数传送寄存器以及返回地址寄存器。代码将在下面解释。下面是一段c语言代码:...externlongnested(longa,longb,longc,longd,longe,longf,longg,longh,longi);longnormal(void){returnnested(1,2,3,4,5,6,7,8,9);}对应的loongarch程序集如下:normal://allocatestackframeaddi.d$sp,$sp,-32//传递参数9,pass引用寄存器不够,存入栈addi.w$t0,$zero,9stptr.d$t0,$sp,0//传递参数8-1、使用输出寄存器a7-a0addi.w$a7,$zero,8addi.w$a6,$zero,7addi.w$a5,$zero,6addi.w$a4,$zero,5addi。w$a3,$zero,4addi.w$a2,$zero,3addi.w$a1,$zero,2addi.w$a0,$zero,1//将返回地址保存在栈上st.d$ra,$sp,24//调用嵌套函数bl%plt(nested)//恢复返回地址到rald.d$ra,$sp,24//恢复栈帧addi.d$sp,$sp,32//返回jr$raloongarch的函数的栈帧可以用下图来表示:ns,和内存访问指令,并结合案例讲解loonarch汇编语言的编写方法。下一篇文章将介绍原子指令、屏障指令以及它们在loonarch中的用法。了解更多开源请访问:开源基础软件社区https://ost.51cto.com
