励志!他设计了先进的指令集,申请三项专利,并设计出了自己的CPU!
在论坛CPU板块看到一个帖子,作者介绍了自己发明的关于CPU指令集的三个专利。大概看过之后,感觉到相当励志!了不起!也更佩服作者的CPU设计功底!前不久也在微信推送过部分帖子内容,但是比较凌乱,也不完整。经过作者一段时间的完善与整理,终于完成了完整版。今天我们就把完整版的内容发给大家,以下内容的PDF文件作者也上传到了论坛,可以登录论坛下载:http://bbs.eetop.cn/thread-628380-1-1.html
酷能指令集
作者:李朝波
一、前言
计算机指令集和操作系统是IT界最重要的基础标准,标准就是话语权,美国人凭借在计算机指令集和操作系统的支配地位而领导整个IT行业30多年,成功演绎了标准创造财富的传奇,30年来没有受到过其他人挑战, 他们经常把计算机指令集和操作系统当做国家的核心利益来捍卫!而我们国家IT界连这种意识都没有,更不用说行动了。
指令集是决定计算机性能的关键因素之一,指令集的先进与否直接关系CPU的性能发挥,直接影响执行程序的效能,世界上先进的计算机公司都在研究CPU指令集,其中美国最为进取,凭借在开发C语言编译器的丰富经验和强大实力,他们毫不费力就推出一套全新的指令集架构,唯恐领导权旁落。
本人从事MCU应用开发已有10多年了,应用了很多类型的MCU,由于有些项目要求中断服务程序非常紧凑,所以要经常优化中断服务程序的汇编代码,观察这些汇编代码后发现当前的CPU指令集仍然有进一步改进的空间。由于本人非计算机系出身,没有这方面底子,但是出于好奇,自己经常苦思冥想,来回琢磨,终于想出以下3项专利技术方案,并且根据这3项专利方案设计本套指令集----酷能指令集,然后再经过1年的努力终于设计出运行这套指令集的CPU,该CPU使用verilog HDL编写,经典五级流水线,其运行表现达到预期效果,振奋人心,现在就差C语言编译器了。
二、专利技术介绍
如果要新推出一套指令集,那么这套指令集就必须具有创新性和先进性,作为后来者不能是平庸之辈,特别像我这种不是体制内的人,如果指令集是平庸之辈,那就不可能获得大家的认可,也没有推出的必要,只会被别人嘲笑,可以看看一位网友给我的留言就知道:“我觉得指令集这东西没必要重复造轮子。开源的riscv、OpenRISC甚至免费、久经考验的nios都足够优秀了,后者连整个cpu架构都跟你搞好了,只管用就行。何必自寻烦恼呢。”,这种消极论调在我国的IT界非常盛行。好在我的这3项专利足够优秀,基于这3项专利设计出来的指令集具有了创新性和先进性,否者也没脸面介绍给大家。
2.1 专利一:《一种在计算机数据处理指令中附加跳转功能的方法及CPU模块》
技术背景:现有的每套计算机指令系统中都由2大类指令构成,它们是跳转指令和数据处理指令。其中跳转指令又分为直接跳转指令、子程序调用指令;而数据处理指令又分为数据传送指令、数据运算指令。这些指令分工非常明确,功能单一。应用程序就是由这些功能单一的指令根据程序逻辑运算要求组合而成的。如下面这段简单的C语言程序代码:
if(a<b)a=b+c;
else a=d+e;
f++;
为了通俗易懂,在此借用流行的MCS-51汇编语言来翻译这段C语言程序代码,得到汇编程序例1如下:
汇编程序例1:
行号 标号 汇编指令(其中A为累加器,C为进位标记)
1 C001: MOV A,a,
2 C002: CLR C;
3 C003: SUBB A,b;
4 C004: JNC C009;
5 C005: MOV A,b;
6 C006: ADD A,c;
7 C007: MOV a,A,
8 C008: JMP C00C;
9 C009: MOV A,d;
10 C00A: ADD A,e;
11 C00B: MOV a,A;
12 C00C: INC f;
从上面的汇编程序例1可以看出,第1、2、3、5、6、7、9、10、11、12行是数据处理指令,这些数据处理指令只能做有关数据传送和数据运算的操作,而且只能顺序执行;第4行和第8行是跳转指令,跳转指令只能做程序跳转的操作,程序逻辑需要跳转的地方就要使用跳转指令来完成, CPU在执行跳转指令时数据处理模块是闲置的,资源白白浪费掉了。
发明的主要内容是:
1、在计算机的数据处理指令中增设一个被称为跳转矢量的操作数,该跳转矢量用于更改PC(即程序计数器)的数值,从而为在数据处理指令中附加跳转功能提供跳转的方向和距离;
2、在计算机的数据处理指令中增设一个被称为条件码的操作数,只有在PSW(程序状态寄存器)中的状态码匹配该指令的条件码时,数据处理指令才能执行,该条件码也是在数据处理指令中附加跳转功能的执行条件之一;
3、在计算机的数据处理指令中增设一位被称为反条件码的操作数,该反条件码用于指示在数据处理指令中附加的跳转功能的执行条件和该指令中的条件码是相同还是相反,如果相同则表示同条件跳转,如果相反则表示反条件跳转,该条件码和反条件码共同组成在数据处理指令中附加的跳转功能的执行条件。通过在计算机数据处理指令(包含数据转送指令,以下同)中增加设置执行的条件码、反条件码和跳转矢量,使得数据处理指令不再是单一的数据处理,而且具备跳转能力,其好处是提高指令的密度和执行效率。
通过上述技术方法实施后数据处理指令具有跳转功能了,在此我称之为具有跳转功能的数据处理指令。这些具有跳转功能的数据处理指令的汇编格式如下所示:
操作码<条件码> [操作数1] , [操作数2], [操作数3],[E][JMP 跳转矢量]
其中E是反条件码,跳转矢量是相对PC的跳转矢量。
注意观察该汇编指令格式,我们发现比现在传统的数据处理指令指令多出了“[E][JMP 跳转标号]”字段,这个字段就是用于描述跳转功能。其中E是反条件码助记符,JMP是立即跳转助记符。如果E被隐去,则表示同条件跳转,即附加的跳转条件和操作码后缀的条件码相同;如果E被显现,则表示反条件跳转,即附加的跳转条件和操作码后缀的条件码相反。
汇编指令格式:操作符<cond> 操作数1,操作数2,..,[E][JMP #v]
其中:
cond----条件码,其意思是:如果满足条件码的要求,则执行操作符定义的操作;如果没有条件码,其意思是:无条件执行操作符定义的操作。
E—--反条件码,意思是否则(Else)。
JMP #v---意思是立即跳转#v条指令。
例如:SUB<cond> Rd, Rn, Rj, [E][JMP #v_6]
实际应用举例如下:
SUBEQ R3, R1, R2,EJMP lab_1; //如果相等,则执行R3=R1-R2;否则立即跳到lab_1处。属于反条件跳转。这种情况下它顶得2条MIPS指令。
SUBEQ R3, R1, R2,JMP lab_1; //如果相等,则执行R3=R1-R2,并且立即跳到lab_1处。属于同条件跳转。这种情况下它顶得2条MIPS指令。
SUB R3, R1, R2; //无条件执行R3=R1-R2。没有跳转功能,属于反条件跳转。这种情况下它只顶得1条MIPS指令。
SUB R3, R1, R2,JMP lab_1; // 无条件执行R3=R1-R2,并且立即跳到lab_1处。属于同条件跳转。这种情况下它顶得2条MIPS指令。
从上面可以看出:在数据处理指令(含数据转送指令)中附加执行条件码、反条件码和跳转矢量后,可以使得数据处理指令不但有条件执行,而且具有跳转功能。这种指令的效率显然高于现在主流的RISC指令,不过由于附加的跳转矢量位数有限(32位指令集是6位,16位指令集是7位),所以跳转的范围都比较小,属于短跳转。
2.2 专利二:《一种将计算机指令中立即数扩展的方法和装置》
技术背景:RISC指令可以携带的立即数一般都不大,比如ARM的数据运算指令携带的立即数最大是12位,而MIPS指令系统的数据运算指令携带的立即数最大是16位,要这些RISC指令系统携带32位的立即数是不可能的,因为其指令长度只有32位,所以在RISC指令系统中要取得32位立即数就费不少周折了,目前常用的方法有两种:第一种是分段读取法,具体是先读取高16位的立即数,再读取低16位的立即数,从而组成32位立即数,为了支持这种分段读取法,几乎所有的RISC指令系统都是专门制定了相应的指令,比如ARM的MOVW和MOVT指令、MIPS的LUI和ADDIU指令;第二种是访存法,具体是把32位立即数当做常数放在离当前PC值不太远的地方,然后使用一条与PC相关的访存指令读取它。但是不管使用哪种读取方法,要获取一个32位的立即数都是费时,怎么都要花2个周期才能完成。 比如要处理表达式:R2=R3&0x87654321,当前ARM的做法是:
使用分段读取法的是:
MOVT R1,#8765H;(取得高16位常数,要花1个周期时间)
MOVW R1,#4321H;(取得低16位常数,要花1个周期时间)
AND R2,R3,R1;
使用访存法的是:
LDR R1, [PC, #offest];(这条指令要花2个周期时间)
AND R2,R3,R1;
由此可见,ARM处理R2=R3&0x87654321共需要花3个周期时间,其中获取32位常数0x87654321需要花2个周期时间。
发明内容:在RISC指令系统中新增加至少一条立即数扩展指令,该指令包含有操作码和立即数域,具体应用是将一个大的立即数分成两段,一段是高位立即数,另一段是低位立即数,将高位立即数经过有符号或无符号扩展后装入该立即数扩展指令的立即数域,而将低位立即数装入执行指令的立即数域,并且规定该立即数扩展指令要前缀于携带该低位立即数的执行指令,中间不能插入别的指令。在取指令时,取指令电路将该立即数扩展指令和紧随其后的执行指令同步送入它们各自的译码器进行译码,立即数扩展指令译码器输出高位立即数经过逻辑左移位后再和执行指令译码器输出的低位立即数进行合并,合并后的立即数再经过有符号数或无符号数扩展后还原为原来的大的立即数。该立即数扩展指令是一条非执行指令,它到译码这一阶段就终结了,它不需要经历执行、回写的阶段。
通过使用本发明的方法,同样要处理上述的表达式:R2=R3&0x87654321,其做法是:
HIMM #8765h; (这是新增的立即数扩展指令,其携带高位立即数#8765h)
AND R2, R3, #4321h;(执行指令携带低16位立即数#4321h)
如果取指令电路工作于单倍速取指令模式(即程序存贮器每次只能在其接口总线上输出1条指令),则处理R2=R3&0x87654321共需要花2个周期时间,其中立即数扩展指令(HIMM #8765h)需要延迟 1条指令的时间,以等待紧随其后的执行指令(AND R2, R3, #4321h)的到来,才能同步译码。
如果取指令电路工作于双倍速取指令模式(即程序存贮器每次都能在其接口总线上输出2条指令),则处理R2=R3&0x87654321仅需要花1个周期时间,此时立即数扩展指令(HIMM #8765h)不需要任何延迟就可以和紧随其后的执行指令(AND R2, R3, #4321h)同步译码,所以它不花任何时间!
对比ARM和本发明的做法可以看出,使用本发明的方法可以极大改善RISC指令集计算机执行程序的效率,既节省时间又节省空间。
2.3 专利三:《一种处理C语言SWITCH/CASE语句的方法 》
技术背景:C语言SWITCH/CASE语句是大家经常用到的语句,从字面上看程序逻辑清晰,结构一目了然,很受程序员欢迎,但是基于现有的指令集,C编译器编译C语言SWITCH/CASE语句成汇编指令时相当费劲。目前C编译器处理C语言SWITCH/CASE语句时通常使用两种方法,它们是:列表驱动法和逐项查找法。其中列表驱动法是在程序存贮器中建立一个常数的数组,该数组是所有CASE常数项所对应的跳转矢量的集合,所以该数组被称为CASE跳转矢量表,某个CASE常数项对应的跳转矢量在该表格的位置等于该CASE常数项与最小CASE常数项的差值,然后使用SWITCH的表达式的值减去最小CASE常数项的差值去索引所述的CASE跳转矢量表,从而得到跳转的目标,这种方法处理速度很快,也是C编译器优先使用的方法;而逐项查找法是使用SWITCH的表达式的值和CASE常数项逐个比较,如果有相等,则跳转到该CASE常数项所对应的地址,也就是说C编译器使用if/else的方法从上往下逐个比较,从而找到跳转的目标, 这就造成了越靠后的case项查找的时间就越长,所以这种方法处理速度很慢。
虽然列表驱动法具有快速的优点,但是那是用空间换取时间。该方法的缺点是CASE跳转矢量表的规模往往很大,其大小等于CASE常数项的最大值与最小值的差值+1。在实际应用中, CASE常数项的离散性往往很大,没有规律可循,那么CASE跳转矢量表就有很多空白项,这会浪费很多程序空间。如果浪费程序的空间过多,C编译器只好使用逐项查找法进行编译。另外,如果case项比较少,C编译器也会使用逐项查找法进行编译。
例如下面这段C语言代码,如果使用列表驱动法进行编译,则CASE跳转矢量表长达247项(246=0xf7-0x01+1),而实际有用的case项只有4个(0x01,0x22,0x4c,0xf7),显然浪费的程序空间太多了,所以C编译器就会使用逐项查找法进行编译。
switch (test){
case 0x01: c=a&b;break;
case 0x22: c=a|b;break;
case 0x4c: c=a+b;break;
case 0xf7: c=a-b;break;
default:break;
}
汇编代码如下:(逐项查找法,使用ARM指令集)
;switch (test){
0x080002ec LDR r0, [pc, #92]
0x080002ee LDRB r0, [r0,#0x00]; r0 <= test
0x080002f0 CMP r0, #0x01
0x080002f2 BEQ 0x08000302;if(test== 0x01) than jump to 0x08000302
0x080002f4 CMP r0, #0x22
0x080002f6 BEQ 0x08000312;if(test== 0x22) than jump to 0x08000312
0x080002f8 CMP r0, #0x4c
0x080002fa BEQ 0x08000322;if(test == 0x4c)than jump to 0x08000322
0x080002fc CMP r0, #0xf7
0x080002fe BEQ 0x08000332 ;if(test ==0xf7) than jump to 0x08000332
…
从上面的汇编代码可以看出,在使用逐项查找法时,越靠后的case项查找的时间就越长,因此改善逐项查找法的执行效率具有重要意义。
观察C程序中的SWITCH/CASE语句不难发现,在绝大多数SWITCH/CASE语句中:SWITCH表达式的值的字长为8位或16位,CASE常数项所对应的跳转都是小范围相对跳转,而且都是往前跳转。
发明内容:在现有的指令系统中增加3条指令,它们是字节型查找指令、半字型查找指令、散转指令。
所述的字节型查找指令包含目的寄存器、第一源寄存器和第二源操作数;其中,所述字节型查找指令的目的寄存器是通用寄存器或PSR(即程序状态寄存器),所述字节型查找指令的第一源寄存器是通用寄存器,所述字节型查找指令的第二源操作数是通用寄存器或立即数;所述的字节型查找指令的助记符采用为CASEB,那么该字节型查找指令的汇编格式是:CASEB Rd,Rs,Rt或者CASEB Rd,Rs,#imm ,其中Rd是目的寄存器,Rs是第一源寄存器,Rt是第二源寄存器,#imm是立即数;对于指令CASEB Rd,Rs,Rt来说:如果Rt是32位通用寄存器,那么Rt里面装载的是4个字长为字节的常数,如果Rt是64位通用寄存器,那么Rt里面装载的是8个字长为字节的常数;对于指令CASEB Rd,Rs,#imm来说:如果#imm是32位立即数,那么该#imm是由4个字长为字节的常数组成,如果#imm是16位立即数,那么该#imm是由2个字长为字节的常数组成;
所述的字节型查找指令的处理内容是:将字节型查找指令的第一源寄存器(Rs)中的第0字节同时分别与字节型查找指令的第二源操作数(Rt或#imm)中的所有字长为字节的常数进行比较,如果在这些比较运算中有一个运算结果为相等,那么置相等标记z为1,否则置相等标记z为0,并且按照一定的优先级顺序来选择其中一个运算结果为相等的、参与该比较运算的常数处于字节型查找指令的第二源操作数(Rs或#imm)中的位置编号位置序号n,再把该位置编号位置序号n以及相等标记z保存到字节型查找指令的目的寄存器Rd;
所述的半字型查找指令包含目的寄存器、第一源寄存器和第二源操作数;其中,所述半字型查找指令的目的寄存器是通用寄存器或PSR(即程序状态寄存器),所述半字型查找指令的第一源寄存器是通用寄存器,所述半字型查找指令的第二源操作数是通用寄存器或立即数;所述的半字型查找指令的助记符采用为CASEH,那么字节型查找指令的汇编格式是那么半字型查找指令的汇编格式是:CASEH Rd,Rs,Rt,或者CASEH Rd,Rs,#imm ,其中Rd是目的寄存器,Rs是第一源寄存器,Rt是第二源寄存器,#imm是立即数;对于指令CASEH Rd,Rs,Rt来说:如果Rt是32位通用寄存器,那么Rt里面装载的是2个字长为半字的常数,如果Rt是64位通用寄存器,那么Rt里面装载的是4个字长为半字的常数;对于指令CASEH Rd,Rs,#imm来说:如果#imm是32位立即数,那么该#imm是由2个字长为半字的常数组成;
所述的半字型查找指令的处理内容是:将半字型查找指令的第一源寄存器(Rs)中的第0半字同时分别与半字型查找指令的第二源操作数(Rt或#imm)中的所有字长为半字的常数进行比较,如果在这些比较运算中有一个运算结果为相等,那么置相等标记z为1,否则置相等标记z为0,并且按照一定的优先级顺序来选择其中一个运算结果为相等的、参与该比较运算的常数处于半字型查找指令的第二源操作数(Rs或#imm)中的位置编号位置序号n,再把该位置编号位置序号n以及相等标记z保存到半字型查找指令的目的寄存器Rd;
所述的散转指令包含第一源寄存器和第二源操作数;其中,所述散转指令的第一源寄存器是通用寄存器或PSR(即程序状态寄存器),该散转指令的第一源寄存器包含使能位z和索引值n;所述散转指令的第二源操作数是通用寄存器或立即数;所述的散转指令的助记符采用为MJZ,那么该散转指令的汇编格式是:MJZ Rs,Rt 或SWITCH Rs, #imm,其中Rs是第一源寄存器,Rt是第二源寄存器,#imm是立即数;如果Rt是32位通用寄存器,那么Rt里面装载的是4个字长为字节的常数;如果Rt是64位通用寄存器,那么Rt里面装载的是8个字长为字节的常数;如果#imm是32位立即数,那么该#imm是由4个字长为字节的常数组成,如果#imm是16位立即数,那么该#imm是由2个字长为字节的常数组成;
所述的散转指令的处理内容是:如果散转指令的Rs中的能使位z为真,那么使用散转指令的Rs中的索引值n选择第二源操作数(Rt或#imm)中的一个字长为字节的常数作为跳转矢量(该跳转矢量是无符号数),然后用该跳转矢量与当前的PC值相加,相加的结果就是跳转的目标地址,从而完成跳转;如果散转指令的Rs中的能使位z为假,则顺序执行;
另外还规定设定:散转指令的第一源寄存器中的能使位z是对应于字节型查找指令和半字型查找指令的目的寄存器中的相等标记z,而散转指令的第一源寄存器中的索引值n是对应于字节型查找指令和半字型查找指令的目的寄存器中的位置编号位置序号n,这样做就使得字节型查找指令和半字型查找指令的执行结果值直接被散转指令使用。
在编译C语言SWITCH/CASE语句时,采用如下编译步骤:
第一步是根据C语言SWITCH表达式的值的字长来选择字节型查找指令或半字型查找指令,查找相等的CASE常数项,具体是:如果C语言SWITCH表达式的值的字长为8位,那么CASE常数项的字长也是8位,所以要使用字节型查找指令(CASEB Rd,Rs,Rt或者CASEB Rd,Rs,#imm)来查找相等的CASE常数项;如果C语言SWITCH表达式的值的字长为16位,那么CASE常数项的字长也是16位,所以要使用半字型查找指令(CASEH Rd,Rs,Rt或者CASEH Rd,Rs,#imm)来查找相等的CASE常数项。查找的方法是:将若干个待查找的CASE常数项按照一定的顺序填满第二源操作数(Rt或#imm)和把SWITCH表达式的值装入源寄存器(Rs)中,执行字节型查找指令或半字型查找指令后,在其目的寄存器(Rd)就得到相等标记z和位置编号位置序号n。另外,如果待查找的CASE常数项不够填满第二源操作数(Rt或#imm),那么重复使用其中某一个待查找的CASE常数项来填充,直到填满为止。
第二步是使用所述的散转指令根据上述第一步的字节型查找指令或半字型查找指令的结果值来索引跳转矢量,完成分支转移。方法具体是:将构成第一步的字节型查找指令或半字型查找指令的第二源操作数(Rt或#imm)的CASE常数项所对应的跳转矢量装入散转指令的第二源操作数(Rt或#imm)中,并且要求各CASE常数项所对应的跳转矢量处于该散转指令的第二源操作数(Rt或#imm)中的位置顺序是与该CASE常数项处于字节型查找指令或半字型查找指令的第二源操作数(Rt或#imm)的位置顺序相同。由于散转指令的第一源寄存器中的能使位z是对应于字节型查找指令和半字型查找指令的目的寄存器中的相等标记z,还有散转指令的第一源寄存器中的索引值n是对应于字节型查找指令和半字型查找指令的目的寄存器中的位置编号位置序号n,所以如果散转指令的第一源寄存器等于字节型查找指令或半字型查找指令的目的寄存器,那么执行散转指令就可以索引到正确的跳转矢量,并根据其能使位z的状态决定跳转还是顺序执行。
使用本发明的方法,同样要处理背景技术所述的C程序:
switch (test){
case 0x01: c=a&b;break; //假设此处的分支地址偏移为0x12
case 0x22: c=a|b;break; //假设此处的分支地址偏移为0x34
case 0x4c: c=a+b;break; //假设此处的分支地址偏移为0x56
case 0xf7: c=a-b;break; //假设此处的分支地址偏移为0x78
default:break;
}
假设test的字长为字节,指令系统可以携带32位立即数,那么使用本发明的方法,其汇编代码如下:
;switch(test){
LDR r0, [pc, #92]
LDRB r0, [r0,#0x00];r0 <= test
CASEB r1, r0, #0xf74C2201
;字节型查找指令(CASEB Rd,Rs,#imm),查找
;相等的CASE常数项,32位立即数#imm是由CASE
;常数项0xf7, 0x4C,0x22,0x01组成,结果存入
;r1
MJZ r1, #0x78563412 ;散转指令(MJZ Rs, #imm) ,32位立即数
;#imm是由跳转矢量0x78,0x56,0x34, 0x12组
;成,由r1索引跳转矢量,完成跳转
…
如果test的字长为半字, 指令系统可以携带32位立即数,那么使用本发明的方法,其汇编代码如下:
;switch(test){
LDR r0, [pc,#92]
LDRH r0, [r0, #0x00]; r0 <= test
CASEH r1,r0, #0x00220001 ;半字型查找指令(CASEH Rd,Rs,#imm),查找
;相等的CASE常数项,32位立即数#imm是由CASE
;常数项0x0022,0x0001组成,结果存入r1
MJZ r1, #0x00003412 ;散转指令(MJZ Rs, #imm) ,32位立即数
;#imm是由跳转矢量0x00,0x00,0x34,0x12组成,
;由r1索引跳转矢量,完成跳转
CASEH r1,r0, #0x00f7004c ;半字型查找指令(CASEH Rd,Rs,#imm),查找
;相等的CASE常数项,32位立即数#imm是由CASE
;常数项0x00f7,0x004c组成,结果存入r1
MJZ r1, #0x00007856 ;散转指令(MJZ Rs, #imm) ,32位立即数
;#imm是由跳转矢量0x00,0x00,0x78,0x56组成,
;由r1索引跳转矢量,完成跳转
…
从以上的汇编代码可以看到,由CASE常数项构成的字节型查找指令或半字型查找指令的第二源操作数(通用寄存器或立即数)的位置顺序是与由该CASE常数项所对应的跳转矢量所构成的散转指令的第二源操作数(通用寄存器或立即数)的位置顺序完全相同。
对比处理技术背景所述的汇编代码不难发现,使用本发明的方法,其汇编代码非常简短,能够显著提高计算机的执行效率。
为了应用这3项专利方案,本人设计了本酷能指令集架构,并且已经完成基于这3项专利的CPU设计,根据仿真结果表明,设计达到预期效果,使用verilog HDL编写,经典五级流水线,同时支持本酷能指令集的16位指令集(78条指令)和32位指令集(89条指令)。
三、寄存器组
本CPU寄存器共设有32个通用寄存器和2个系统控制寄存器。其寄存器组织结构如下所示。
寄存器组构成图
寄存器介绍:
寄存器的宽度是32位,所以本CPU是32位CPU。
当CPU处于16位指令模式时,其通用寄存器为R0—R15,R16(HR0)--R31(HR15)用特别的指令访问。当CPU处于32位指令模式时,其通用寄存器为R0—R31。 另外,在这些通用寄存器中有些寄存器有特别的用途,其中:
R0----零寄存器,读出总是0值。
R1----UMAC指令的目的寄存器。
R26---LO寄存器,用于存贮乘法或乘加的64位结果的低32位,或者用于存贮32位除法运算的商。R27---HI寄存器,用于存贮乘法或乘加的64位结果的高32位,或者用于存贮32位除法运算的余数。 R29---INT,存贮硬件中断或软件中断的信息。
R30---SP寄存器,即推栈指针。本CPU有2个推栈指针,当CPU处于用户态时是PSP,而当CPU处于特权态时是PSP或MSP。
R31---LR寄存器,即子程序返回链接寄存器。
另外,CPU设置2个系统控制寄存器,即PC和PSR寄存器,其中
PC----程序计数器。
PSR---程序状态寄存器,里面有程序状态标志位以及系统状态和控制信息。
PC、PSR寄存器各位定义
PC和PSR寄存器各位段的意义如下:
PC.M-----指令集模式控制位。当PC.M==0,则系统处于16位指令集模式;当PC.M==1,则系统处于32位指令集模式。本CPU系统规定:只有CALL指令、软件中断指令int、硬件中断响应、中断返回指令iret和子程序返回指令ret才可以改变PC.M的状态值,中断响应(软件中断或硬件中断)时系统进入16位指令集模式。
PSR.T----特权态/用户态控制位。当PSR.T为1时,系统工作状态处于特权态;当PSR.T为0时,系统工作状态处于用户态,此时特权级指令不能使用。中断响应(软件中断或硬件中断)时系统自动将PSR.T=1,CPU进入特权态,中断返回指令IRET也可以更新该值。
PSR.I----中断开关控制位。当PSR.I为1时,允许中断;当PSR.I为0时,禁止中断,只有特权态才可以改变该值。
PSR.P----指示当前选择的堆栈指针SP使用的是MSP还是PSP 。当PSR.P为1时,SP=MSP;当PSR.P为0时,SP=PSP。只有特权态才可以改变该值。
PSR.B----中断响应时PSR.P的备份,中断返回时用于恢复PSR.P的数值。其动作类似于LR的效果。只有特权态才可以改变该值。
PSR.n----第3项专利的查找指令CASEB/CASEH的结果值(Z,n)中的一个。
PSR.V----溢出标志位。
PSR.N----负数标志位。
PSR.C----进位标志位。
PSR.Z----零标志位。
PSR.RC---重复计数器。本指令集专门设置控制该PSR.RC(重复计数器)工作的执行条件码(即RP、RE、RN),只要指令的执行条件码是RP、RE、RN,重复计数器PSR.RC就会无条件进行减1操作。
四、执行条件码
本指令集使用的条件码有16种,如下条件码表所示。
从上述的条件码表可以看出本指令集使用的条件码和ARM有所不同,主要是加入了与RC(重复计数器)相关的条件码(RE、RN、RP),本系统就是靠这3个条件码控制PSR.RC(重复计数器)进行减1操作的。这3个条件码不只是指令的执行条件码 ,它们也同时无条件的将PSR.RC(重复计数器)进行自减1操作,也就是说,指令是有条件执行,而PSR.RC(重复计数器)是无条件自动减1。例如指令: SUBRE R3, R1, R2,JMP lab_1,该指令的操作有:无条件执行RC=RC-1的操作;如果Z==1&&RC>0,则执行R3=R1-R2和立即跳到lab_1处,属于同条件跳转。这种情况下有最高效率,它顶得4条MIPS指令!
本指令集并不是每条指令都带有执行条件码。
五、立即数扩展指令
虽然第二项专利只是说扩展立即数,但是使用该专利的方法也是可以扩展其它操作数的。本指令集定义4条立即数扩展指令,它们是:RIMM指令、CIMM指令、HIMM指令和WIMM指令,其中:
RIMM指令----用于扩展寄存器号,指令长度为16位。
CIMM指令----用于扩展条件码(cond)、反条件码(E)、跳转矢量(V7) ,指令长度为16位。
HIMM指令----用于扩展高12位立即数,指令长度为16位。
WIMM指令----用于扩展高28位立即数,指令长度为32位。
在16位指令集中,可以使用的立即数扩展指令是RIMM、CIMM、HIMM以及WIMM,为紧随其后的执行指令提供扩展的操作数。 在32位指令集中,只能使用的立即数扩展指令WIMM,用于扩展32位立即数。
立即数扩展指令结构图如下所示:
立即数扩展指令结构图
从立即数扩展指令结构图可以看到各操作数的编码情况。
六、酷能指令集介绍
6.1 指令集特点
本指令集包含有16位指令集(78条指令)和32位指令集(89条指令), 这16位指令集和32位指令集是相互独立的,自成一体,16位指令集不用借助32位指令集就能实现所有功能,这与ARM或MIPS有所不同。本指令系统规定:一个子程序(即函数)只能使用一套指令集,也就是说:在一个子程序(即函数)中,要么全部使用16位指令集,或要么全部使用32位指令集!当然了,16位指令集的函数可以CALL32位指令集的函数,反之亦然,这是因为指令译码器是根据该指令的地址的第0位(即PC.M)的状态来区分该指令是16位指令集还是32位指令集,而只有CALL指令、软件中断指令int、硬件中断响应、中断返回指令iret和子程序返回指令ret才可以改变PC.M的状态值。本CPU设定:当PC.M为0时,指令为16位指令集;当PC.M为1时,指令为32位指令集。
16位指令集可以前缀的立即数扩展指令为16位或32位,因此组合之后的指令长度等效于16位(无立即数扩展指令)、32和48位;32位指令集前缀的立即数扩展指令位32位,因此组合之后的指令长度等效于32位(无立即数扩展指令)或64位。
本16位指令集的技术特点:
1.支持的通用寄存器16个,即R0---R15(其中R0是零寄存器),这比其它16位指令集(比如ARM和MIPS)大一倍,为用户提供更多的寄存器变量空间,有利于提高效能。
2.可以携带16位或32位的立即数,这一优势是其他16位指令集不能比拟的。
3、访存指令LOAD/STORE寻址方式灵活多样,支持的偏移量offset = #0、#imm12、#imm28或Ra,比其他16位指令集强。
4、许多数据处理指令可以有跳转功能。
本32位指令集的技术特点:
1.支持的通用寄存器32个,即R0---R31(其中R0是零寄存器)。
2.可以携带32位的立即数,这一优势是其他32位指令集不能比拟的。
3、访存指令LOAD/STORE寻址方式灵活多样,支持的偏移量offset = #imm16、#imm32或Rj,比其他32位指令集强。
4、许多数据处理指令具有跳转功能。
本指令集包含有布尔处理指令,有位与指令BITA、位或指令BITO、位异或指令BITX、位取反指令BITN、位运算结果保存指令ZMB。这一特点比MCS-51或ARM的位操作指令更通用,位变量定义不再受限制。
本指令集特有的计算多维数组指针指令UMAC,UMAC指令能够显著提高计算多维数组指针的效能。
举例:有个二维数组int a[30][20],如果想要访问a[x][y]单元,先转化为一维数组a[k],其中k=x*20 + y。而计算表达式(k=x*20 + y)就是由1条UMAC指令完成(UMAC Ry, Rx, #20),耗时为1个周期,这时R1就是k,因为R1是通用寄存器,所以可以直接使用LD/STR Rd, [Ra, R1]访问了,一步到位。如果使用ARM或MIPS指令,光计算表达式(k=x*20+ y)就要用3条指令才能完成(耗时为3个周期):首先取得立即数#20,第二步相乘,第三步再相加。
本指令集支持的数据类型有4种:
1、1位(bit);
2、8位(字节byte)有符号数或无符号数;
3、16位(半字half)有符号数或无符号数,双字节对齐;
4、32位(字word)有符号数或无符号数,四字节对齐;
本CPU不支持非对齐访问。
6.2 32位指令集V1.0
(共89条指令)
(32位指令集的寄存器号d,n,j∈0~31)
表6.2.1 加法、减法运算指令(10条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
ADD Rd, Rn, #uimm16 |
Rd=Rn + #uimm16 |
NZCV |
1 |
|
SUB Rd, Rn, #uimm16 |
Rd=Rn - #uimm16 |
NZCV |
1 |
|
RSB Rd, Rn, #uimm16 |
Rd=#uimm16 - Rn |
NZCV |
1 |
|
ADD<cond> Rd, #uimm5, [E]JMP #v6 |
Rd=Rd + #uimm5 |
NZCV |
1 |
|
SUB<cond> Rd,#uimm5, [E]JMP #v6 |
Rd=Rd - #uimm5 |
NZCV |
1 |
|
ADD<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn + Rj |
/WIMM |
NZCV |
1 |
SUB<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn - Rj |
/WIMM |
NZCV |
1 |
ADD Rd, PC, #uimm16 |
Rd={PC[31:2], 2’b0}+ #uimm16 |
1 |
||
CASEB<cond> Rd, Rj, [E]JMP #v6 |
查找相等的字节 |
/WIMM |
n,Z |
1 |
CASEH<cond> Rd, Rj, [E]JMP #v6 |
查找相等的半字 |
/WIMM |
n,Z |
1 |
说明:
1、如果前缀有WIMM #imm28指令,此时Rj就变为#imm4,两者组成32位立即数。
2、指令CASEB/H<cond> Rd,Rj, [E]JMP #v6是专利三的指令。
表6.2.2 乘法、除法运算指令(11条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
MUL<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn*Rj |
/WIMM |
1~3 |
|
MUL Rd, Rn, #simm16 |
Rd=Rn * #simm16 |
1~2 |
||
UMAC Rd, Rn, #uimm16 |
R1=Rd+ Rn[15:0] * #uimm16 |
1 |
||
SMULT<cond> Rd, Rj, [E]JMP #v6 |
(有符号) {HI,LO}=Rd*Rj |
/WIMM |
1~4 |
|
UMULT<cond> Rd, Rj, [E]JMP #v6 |
(无符号) {HI,LO}=Rd*Rj |
/WIMM |
1~4 |
|
SMLA<cond> Rd, Rj, [E]JMP #v6 |
(有符号) {HI,LO}={HI,LO}+Rd*Rj |
/WIMM |
2~5 |
|
UMLA<cond> Rd, Rj, [E]JMP #v6 |
(无符号) {HI,LO}={HI,LO}+Rd*Rj |
/WIMM |
2~5 |
|
SMLS<cond> Rd, Rj, [E]JMP #v6 |
(有符号) {HI,LO}={HI,LO}-Rd*Rj |
/WIMM |
2~5 |
|
UMLS<cond> Rd, Rj, [E]JMP #v6 |
(无符号) {HI,LO}={HI,LO}-Rd*Rj |
/WIMM |
2~5 |
|
SDIV<cond> Rd, Rj, [E]JMP #v6 |
(有符号) LO=Rd/Rj, HI=Rd%Rj |
/WIMM |
4~16 |
|
UDIV<cond> Rd, Rj, [E]JMP #v6 |
(无符号)LO=Rd/Rj, HI=Rd%Rj |
/WIMM |
4~16 |
说明:
1、UMAC指令主要用于数组指针的计算,其目的寄存器是R1。
2、如果前缀有WIMM #imm28指令,此时Rj就变为#imm4,两者组成32位立即数。
表6.2.3 逻辑运算指令(6条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
AND Rd, Rn, #uimm16 |
Rd=Rn& #uimm16 |
NZ |
1 |
|
OR Rd, Rn, #uimm16 |
Rd=Rn| #uimm16 |
NZ |
1 |
|
XOR Rd, Rn, #uimm16 |
Rd=Rn^ #uimm16 |
NZ |
1 |
|
AND<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn&Rj |
/WIMM |
NZ |
1 |
OR<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn|Rj |
/WIMM |
NZ |
1 |
XOR<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn^Rj |
/WIMM |
NZ |
1 |
说明:
如果前缀有WIMM #imm28指令,此时Rj就变为#imm4,两者组成32位立即数。
表6.2.4 移位操作指令(8条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
LSL<cond> Rd, Rn, #uimm5, [E]JMP #v6 |
Rd=Rn<< #uimm5 |
NZC |
1 |
|
LSR<cond> Rd, Rn, #uimm5, [E]JMP #v6 |
Rd=Rn>> #uimm5 |
NZC |
1 |
|
ASR<cond> Rd, Rn, #uimm5, [E]JMP #v6 |
Rd=(signed)Rn>>#uimm5 |
NZC |
1 |
|
ROR<cond> Rd, Rn, #uimm5, [E]JMP #v6 |
Rd=Rn右环移 #uimm5位 |
NZC |
1 |
|
LSL<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn<<Rj |
NZC |
1 |
|
LSR<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn>>Rj |
NZC |
1 |
|
ASR<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=(signed)Rn>>Rj |
NZC |
1 |
|
ROR<cond> Rd, Rn, Rj, [E]JMP #v6 |
Rd=Rn>> Rn右环移Rj位 |
NZC |
1 |
说明:
表6.2.5 位操作指令(8条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
BFEX Rd, Rj, #width5,#lsb5 |
位段提取 |
NZ |
1 |
|
BFIN Rd, Rj, #width5,#lsb5 |
位段插入 |
NZ |
1 |
|
BITA Rd, Rj, #x, #y |
(布尔)与 Z=~(Rd.x & Rj.y) |
Z |
1 |
|
BITO Rd, Rj, #x, #y |
(布尔)或 Z=~(Rd.x | Rj.y) |
Z |
1 |
|
BITX Rd, Rj, #x, #y |
(布尔)异或 Z=~(Rd.x ^ Rj.y) |
Z |
1 |
|
BITN Rd, Rj, #x, #y |
(布尔)取反 Z= Rj.y, Rd.x= ~ Rj.y |
Z |
1 |
|
ZMB<cond> Rd, #x, [E]JMP #v6 |
保存~Z位,即Rd. x = ~ Z |
1 |
||
RBIT<cond> Rd, Rj, [E]JMP #v6 |
按位反转 |
1 |
表6.2.6 数制转换指令(3条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
SEXTB<cond> Rd, Rj, [E]JMP #v6 |
字节符号位扩展 |
NZ |
1 |
|
SEXTH<cond> Rd, Rj, [E]JMP #v6 |
半字符号位扩展 |
NZ |
1 |
|
CLZ<cond> Rn, Rj, [E]JMP #v6 |
计算前导0的个数 |
Z |
1 |
说明:
表6.2.7 数据转送指令(27条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
MOV<cond> Rd, Rj, [E]JMP #v6 |
Rd=Rj |
/WIMM |
1 |
|
CPL<cond> Rd, Rj, [E]JMP #v6 |
Rd=~Rj |
/WIMM |
NZ |
1 |
MOV<cond> RC, Rj, [E]JMP #v6 |
RC=Rj |
/WIMM |
1 |
|
MOV<cond> Rd, RC, [E]JMP #v6 |
Rd=RC |
1 |
||
MOV<cond> Rd, PSR, [E]JMP #v6 |
Rd=PSR |
1 |
||
MOV<cond> PSR, Rj, [E]JMP #v6 |
PSR=Rj |
/WIMM |
1 |
|
XCHG<cond> Rd, [Rn], Rj, [E]JMP #v6 |
Rd=[Rn], [Rn]=Rj |
1 |
||
SLB<cond> Rd, [Rn, Rj], [E]JMP #v6 |
Rd=(Sbyte)MEM[Rn+Rj] |
/WIMM |
1 |
|
SLB Rd, [Rn, #uimm16] |
Rd=(Sbyte)MEM[Rn+ #uimm16] |
1 |
||
SLH<cond> Rd, [Rn, Rj], [E]JMP #v6 |
Rd=(Shalf)MEM[Rn+Rj<<1] |
/WIMM |
1 |
|
SLH Rd, [Rn, #uimm16] |
Rd=(Shalf)MEM[Rn+ #uimm16<<1] |
1 |
||
ULB<cond> Rd, [Rn, Rj], [E]JMP #v6 |
Rd=(Ubyte)MEM[Rn+Rj] |
/WIMM |
1 |
|
ULB Rd, [Rn, #uimm16] |
Rd=(Ubyte)MEM[Rn+ #uimm16] |
1 |
||
ULH<cond> Rd, [Rn, Rj], [E]JMP #v6 |
Rd=(Uhalf)MEM[Rn+Rj<<1] |
/WIMM |
1 |
|
ULH Rd, [Rn, #uimm16] |
Rd=(Uhalf)MEM[Rn+ #uimm16<<1] |
1 |
||
ULW<cond> Rd, [Rn, Rj], [E]JMP #v6 |
Rd=(Uword)MEM[Rn+Rj<<2] |
/WIMM |
1 |
|
ULW Rd, [Rn, #uimm16] |
Rd=(Uword)MEM[Rn+ #uimm16<<2] |
1 |
||
STRB<cond> Rd, [Rn, Rj], [E]JMP #v6 |
(byte)MEM[Rn+Rj]=Rd |
/WIMM |
1 |
|
STRB Rd, [Rn, #uimm16] |
(byte)MEM[Rn+ #uimm16]=Rd |
1 |
||
STRH<cond> Rd, [Rn, Rj], [E]JMP #v6 |
(half)MEM[Rn+Rj<<1]=Rd |
/WIMM |
1 |
|
STRH Rd, [Rn, #uimm16] |
(half)MEM[Rn+ #uimm16<<1]=Rd |
1 |
||
STRW<cond> Rd, [Rn, Rj], [E]JMP #v6 |
(word)MEM[Rn+Rj<<2]=Rd |
/WIMM |
1 |
|
STRW Rd, [Rn, #uimm16] |
(word)MEM[Rn+ #uimm16<<2]=Rd |
1 |
||
ULD<cond> Rd, [SP, #uimm5], [E]JMP #v6 |
Rd=(Uword)MEM[SP+ #uimm5<<2] |
1 |
||
STR<cond> Rd, [SP, #uimm5], [E]JMP #v6 |
(Uword)MEM[SP+ #uimm5<<2] = Rd |
1 |
||
PUSH<cond> Rd, #uimm5, [E]JMP #v6 |
(#uimm5+1)个寄存器入栈 |
#uimm5 +1 |
||
POP<cond> Rd, #uimm5, [E]JMP #v6 |
(#uimm5+1)个寄存器出栈 |
#uimm5 +1 |
说明:
1、如果前缀有WIMM #imm28指令,此时Rj就变为#imm4,两者组成32位立即数。
2、指令 MOV<cond> Rd, PSR, [E]JMP #v6和MOV<cond> PSR, Rj, [E]JMP #v6都是特权级指令。
表6.2.8 程序转移指令(12条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
MJZ #uimm16 |
分散转移指令 |
/WIMM |
2 |
|
CALL #simm26 |
PC={PC[31:2], 2’b00}+#simm26 |
/WIMM |
2 |
|
CALL Rj |
PC=Rj |
2 |
||
J<cond> #simm16 |
PC=PC+{#simm16, 2’b00} |
2 |
||
JMP Rj |
PC={Rj[31:2], 2’b01} |
2 |
||
CJZ Rd, Rj,#simm11 |
If (Rd^Rj)==0 then jmp |
/WIMM |
2 |
|
CJNZ Rd, Rj,#simm11 |
If (Rd^Rj)!=0 then jmp |
/WIMM |
2 |
|
TJZ Rd, Rj,#simm11 |
If (Rd&Rj)==0 then jmp |
/WIMM |
2 |
|
TJNZ Rd, Rj,#simm11 |
If (Rd&Rj)!=0 then jmp |
/WIMM |
2 |
|
INT #uimm16 |
软件中断 |
2 |
||
IRET |
中断返回 |
2 |
||
RET |
子程序返回PC=LR, POP LR |
2 |
说明:
1、指令MJZ #uimm16是专利三的指令。如果前缀有WIMM #imm28指令,此时#uimm16就变为#imm4,两者组成32位无符号立即数。
2、指令CALL #simm26如果前缀有WIMM #imm28指令,此时#simm26就变为#imm4,两者组成32位有符号立即数。
3、指令CJZ/CJNZ/TJZ/TJNZ Rd, Rj, #simm11如果前缀有WIMM #imm28指令,此时Rj就变为#imm4,两者组成32位立即数。
4、指令IRET是特权级指令。
5、指令INT #uimm16操作有:PC=0x400(进入16位指令集模式),R29=#uimm16,PUSH LR ,PUSH PSR,psr.T= 1(进入特权级模式),psr.I = 0(禁止中断),psr.P = 1(使用MSP),psr.B= psr.P(保存sp选择位)。
6、指令IRET的操作有:PC=LR, POP LR,POP PSR。
表6.2.9 控制指令(3条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
SLEEP |
睡眠,等待中断唤醒 |
1 |
||
SET PSR, #uimm4 |
将PSR的控制位I,P,B置1 |
I,P,B |
1 |
|
CLR PSR, #uimm4 |
将PSR的控制位I,P,B清0 |
I,P,B |
1 |
说明: 表中这3条指令都是特权级指令。
表6.2.10 立即数扩展指令(1条)
汇编指令 |
操作说明 |
WIMM #imm28 |
提供高28位立即数 |
-----------------------32位指令集到这里结束---------------------------
6.3 16位指令集V1.0
(共78条指令)
(16位指令集的寄存器号d,n,j,a,b,c∈0~15)
表6.3.1 加法、减法运算指令(10条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
ADD Rd, Rn, Rj |
Rd=Rn+Rj |
/WIMM/HIMM/CIMM |
NZCV |
1 |
SUB Rd, Rn, Rj |
Rd=Rn-Rj |
/WIMM/HIMM/CIMM |
NZCV |
1 |
ADD Rd, #uimm4 |
Rd=Rd+ #uimm4 |
/WIMM/HIMM/CIMM |
NZCV |
1 |
SUB Rd, #uimm4 |
Rd=Rd- #uimm4 |
/WIMM/HIMM/CIMM |
NZCV |
1 |
ADD Rd, SP, #uimm4 |
Rd=SP+ #uimm4<<2 |
/WIMM/HIMM/CIMM |
1 |
|
ADD SP, #uimm4 |
SP=SP+ #uimm4<<2 |
/WIMM/HIMM/CIMM |
1 |
|
SUB SP,#uimm4 |
SP=SP- #uimm4<<2 |
/WIMM/HIMM/CIMM |
1 |
|
ADD Rd, PC, #0 |
Rd={PC[31:1], 1’b0}+#0 |
/WIMM/HIMM/CIMM |
1 |
|
CASEB Rn, Rj |
查找相等的字节 |
/WIMM/HIMM/CIMM |
Z, n |
1 |
CASEH Rn, Rj |
查找相等的半字 |
/WIMM/HIMM/CIMM |
Z, n |
1 |
说明:
1、WIMM指令为紧随其后的执行指令的第二源操作数提供高28位立即数,低位立即数由执行指令的第二源操作数提供(Rj变为#imm4)。
2、HIMM指令为紧随其后的执行指令的第二源操作数提供高12位立即数,低位立即数由执行指令的第二源操作数提供(Rj变为#imm4)。
3、CIMM指令为紧随其后的执行指令提供条件码(cond)、反条件码(E)、跳转矢量(V7)。
4、指令CASEB/H Rd, Rj是专利三的指令。
表6.3.2 乘法、除法运算指令(10条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
MUL Rd, Rn, Rj |
Rd=Rn*Rj |
/WIMM/CIMM |
1~3 |
|
UMAC Rd, Rn, #uimm4 |
R1=Rd+Rn[15:0] * #uimm16 |
HIMM |
1 |
|
SMULT Rd, Rj |
(有符号){HI,LO}=Rd*Rj |
/WIMM/HIMM/CIMM |
1~4 |
|
UMULT Rd, Rj |
(无符号){HI,LO}=Rd*Rj |
/WIMM/HIMM/CIMM |
1~4 |
|
SMLA Rd, Rj |
(有符号){HI,LO}={HI,LO}+Rd*Rj |
/WIMM/HIMM/CIMM |
2~5 |
|
UMLA Rd, Rj |
(无符号){HI,LO}={HI,LO}+Rd*Rj |
/WIMM/HIMM/CIMM |
2~5 |
|
SMLS Rd, Rj |
(有符号){HI,LO}={HI,LO}-Rd*Rj |
/WIMM/HIMM/CIMM |
2~5 |
|
UMLS Rd, Rj |
(无符号){HI,LO}={HI,LO}-Rd*Rj |
/WIMM/HIMM/CIMM |
2~5 |
|
SDIV Rd, Rj |
(有符号)LO=Rd/Rj, HI=Rd%Rj |
/WIMM/HIMM/CIMM |
4~16 |
|
UDIV Rd, Rj |
(无符号)LO=Rd/Rj, HI=Rd%Rj |
/WIMM/HIMM/CIMM |
4~16 |
说明:
1、WIMM指令为紧随其后的执行指令的第二源操作数提供高28位立即数,低位立即数由执行指令的第二源操作数提供(Rj变为#imm4)。
2、HIMM指令为紧随其后的执行指令的第二源操作数提供高12位立即数,低位立即数由执行指令的第二源操作数提供(Rj变为#imm4)。
3、CIMM指令为紧随其后的执行指令提供条件码(cond)、反条件码(E)、跳转矢量(V7)。
4、UMAC指令主要用于数组指针的计算,其目的寄存器是R1,必须使用HIMM指令前缀。
表6.3.3 逻辑运算指令(3条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
AND Rd, Rn, Rj |
Rd=Rn&Rj |
/WIMM/HIMM/CIMM |
NZ |
1 |
OR Rd, Rn, Rj |
Rd=Rn|Rj |
/WIMM/HIMM/CIMM |
NZ |
1 |
XOR Rd, Rn, Rj |
Rd=Rn^Rj |
/WIMM/HIMM/CIMM |
NZ |
1 |
说明:
1、WIMM指令为紧随其后的执行指令的第二源操作数提供高28位立即数,低位立即数由执行指令的第二源操作数提供(Rj变为#imm4)。
2、HIMM指令为紧随其后的执行指令的第二源操作数提供高12位立即数,低位立即数由执行指令的第二源操作数提供(Rj变为#imm4)。
3、CIMM指令为紧随其后的执行指令提供条件码(cond)、反条件码(E)、跳转矢量(V7)。
表6.3.4 移位操作指令(4条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
LSL Rd, Rj |
Rd=Rd<<Rj |
/CIMM/RIMM/HIMM |
NZC |
1 |
LSR Rd, Rj |
Rd=Rd>>Rj |
/CIMM/RIMM/HIMM |
NZC |
1 |
ASR Rd, Rj |
Rd=(signed)Rd>>Rj |
/CIMM/RIMM/HIMM |
NZC |
1 |
ROR Rd, Rj |
Rd=Rd右环移Rj |
/CIMM/RIMM/HIMM |
NZC |
1 |
说明:
1、HIMM指令为紧随其后的执行指令提供第二源操作数(12位立即数),从而构成三元式操作,比如LSL Rd, Rj,#uimm12。
2、RIMM指令为紧随其后的执行指令提供第二源操作数(寄存器号Ra),从而构成三元式操作,比如LSL Rd,Rj,Ra。
3、CIMM指令为紧随其后的执行指令提供条件码(cond)、反条件码(E)、跳转矢量(V7)。
表6.3.5 位操作指令(8条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
BFEX Rd, Rj, #width5,#lsb5 |
位段提取 |
HIMM |
NZ |
1 |
BFIN Rd, Rj, #width5,#lsb5 |
位段插入 |
HIMM |
NZ |
1 |
BITA Rd, Rj, #x, #y |
布尔与 Z=~(Rd.x & Rj.y) |
HIMM |
Z |
1 |
BITO Rd, Rj, #x, #y |
布尔或 Z=~(Rd.x | Rj.y) |
HIMM |
Z |
1 |
BITX Rd, Rj, #x, #y |
布尔异或Z=~(Rd.x ^ Rj.y) |
HIMM |
Z |
1 |
BITN Rd, Rj, #x, #y |
布尔反Z=Rj.y, Rd.x= ~ Rj.y |
HIMM |
Z |
1 |
ZMB Rd, #x |
保存~Z Rd. x =~Z |
/CIMM |
1 |
|
RBIT Rd, Rj |
按位反转 |
/CIMM |
1 |
说明:
1、HIMM指令为紧随其后的执行指令提供第二源操作数(12位立即数)。
2、CIMM指令为紧随其后的执行指令提供条件码(cond)、反条件码(E)、跳转矢量(V7)。
表6.3.6 数制转换指令(3条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
SEXTB Rj |
字节符号位扩展 |
/CIMM |
NZ |
1 |
SEXTH Rj |
半字符号位扩展 |
/CIMM |
NZ |
1 |
CLZ Rd, Rj |
计算前导0的个数 |
/CIMM |
Z |
1 |
说明:CIMM指令为紧随其后的执行指令提供条件码(cond)、反条件码(E)、跳转矢量(V7)。
表6.3.7 数据转送指令(21条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
MOV Rd, Rj |
Rd=Rj |
/WIMM/HIMM/CIMM |
1 |
|
CPL Rd, Rj |
Rd=~Rj |
/CIMM |
NZ |
1 |
MOV Rd, HRj |
Rd=HRj |
/CIMM |
1 |
|
MOV HRd, Rj |
HRd=Rj |
/WIMM/HIMM/CIMM |
1 |
|
MOV RC, Rj |
RC=Rj |
/WIMM/HIMM/CIMM |
1 |
|
MOV Rj, RC |
Rj=RC |
/CIMM |
1 |
|
MOV Rj, PSR |
Rj=PSR |
/CIMM |
1 |
|
MOV PSR, Rj |
PSR=Rj |
/WIMM/HIMM/CIMM |
1 |
|
XCHG Ra, [Rb], Rc |
Ra=[Rb], [Rb]=Rc |
RIMM |
1 |
|
SLB Rd, [Rn, #0] |
Rd=(Sbyte)MEM[Rn+ #0] |
/WIMM/HIMM/CIMM/RIMM |
1 |
|
SLH Rd, [Rn, #0] |
Rd=(Shalf)MEM[Rn+ #0<<1] |
/WIMM/HIMM/CIMM/RIMM |
1 |
|
ULB Rd, [Rn, #0] |
Rd=(Ubyte)MEM[Rn+ #0] |
/WIMM/HIMM/CIMM/RIMM |
1 |
|
ULH Rd, [Rn, #0] |
Rd=(Uhalf)MEM[Rn+ #0<<1] |
/WIMM/HIMM/CIMM/RIMM |
1 |
|
ULW Rd, [Rn, #0] |
Rd=(Uword)MEM[Rn+ #0<<2] |
/WIMM/HIMM/CIMM/RIMM |
1 |
|
STRB Rd, [Rn, #0] |
(byte)MEM[Rn+ #0]=Rd |
/WIMM/HIMM/CIMM/RIMM |
1 |
|
STRH Rd, [Rn, #0] |
(half)MEM[Rn+ #0<<1]=Rd |
/WIMM/HIMM/CIMM/RIMM |
1 |
|
STRW Rd, [Rn, #0] |
(word)MEM[Rn+ #0<<2]=Rd |
/WIMM/HIMM/CIMM/RIMM |
1 |
|
ULD Rd, [SP, #uimm4] |
Rd=(Uword)MEM[SP+ #uimm4<<2] |
/WIMM/HIMM/CIMM/ |
1 |
|
STR Rd, [SP, #uimm4] |
(Uword)MEM[SP+ #uimm4<<2]=Rd |
/WIMM/HIMM/CIMM/ |
1 |
|
PUSH Rd, #uimm4 |
(#uimm4+1)个寄存器入栈 |
/CIMM |
#uimm4+1 |
|
POP Rd, #uimm4 |
(#uimm4+1)个寄存器出栈 |
/CIMM |
#uimm4+1 |
说明:
1、WIMM指令为紧随其后的执行指令的第二源操作数提供高28位立即数,低位立即数由执行指令的第二源操作数提供(Rj变为#imm4)。
2、HIMM指令为紧随其后的执行指令的第二源操作数提供高12位立即数,低位立即数由执行指令的第二源操作数提供(Rj变为#imm4)。
3、CIMM指令为紧随其后的执行指令提供条件码(cond)、反条件码(E)、跳转矢量(V7)。
4、RIMM指令为紧随其后的执行指令提供寄存器号。
5、通过使用立即数扩展指令WIMM/HIMM/ RIMM,使得访存指令LD/STR寻址方式灵活多样,支持偏移量为#0、#uimm12、#uimm28或Ra。
6、指令 MOV Rj, PSR和MOV PSR, Rj都是特权级指令。
表6.3.8 程序转移指令(12条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
MJZ #uimm4 |
分散转移指令 |
WIMM/HIMM |
2 |
|
CALL #simm12 |
PC={PC[31:1], 1’b0}+#simm12 |
/WIMM/HIMM |
2 |
|
CALL Rj |
PC=Rj |
2 |
||
J<cond> #simm4 |
PC=PC+{#simm4, 1’b0} |
/WIMM/HIMM |
2 |
|
JMP Rj |
PC={Rd[31:1], 1’b0} |
2 |
||
CJZ Rd, Rj,#simm12 |
If (Rd^Rj)==0 then jmp |
HIMM |
2 |
|
CJNZ Rd, Rj,#simm12 |
If (Rd^Rj)!=0 then jmp |
HIMM |
2 |
|
TJZ Rd, Rj,#simm12 |
If (Rd&Rj)==0 then jmp |
HIMM |
2 |
|
TJNZ Rd, Rj,#simm12 |
If (Rd&Rj)!=0 then jmp |
HIMM |
2 |
|
INT #uimm8 |
软件中断 |
/HIMM |
2 |
|
IRET |
中断返回 |
2 |
||
RET |
子程序返回PC=LR, POP LR |
2 |
说明:
1、指令MJZ #uimm4是专利三的指令。其必须使用立即数扩展指令WIMM或HIMM,低4位立即数由MJZ #uimm4提供,高位立即数由WIMM(提供高28位)或HIMM(提供高12位)提供,从而构成32位或16位无符号数。
2、指令CALL #simm12如果使用立即数扩展指令WIMM或HIMM,那么该立即数扩展指令提供高位有符号数(WIMM提供高位20位有符号数,HIMM提供高位12位有符号数), CALL #simm12指令提供低12位无符号数,两者构成32位或24位的跳转矢量。
3、指令J<cond>#simm4如果使用立即数扩展指令WIMM或HIMM,那么立即数扩展指令提供高位有符号数(WIMM提供高位28位有符号数,HIMM提供高位12位有符号数),J<cond> #simm4指令提供低4位无符号数,两者构成32位或16位的跳转矢量。
4、指令CJZ/CJNZ/TJZ/TJNZ Rd, Rj,#simm12必须使用立即数扩展指令HIMM,跳转矢量由立即数扩展指令HIMM提供12位跳转矢量。
5、指令IRET是特权级指令。
6、指令INT #uimm8操作有:PC=0x400(进入16位指令集模式),R29=#uimm8,PUSH LR ,PUSH PSR,psr.T= 1(进入特权级模式),psr.I = 0(禁止中断),psr.P = 1(使用MSP),psr.B= psr.P(保存sp选择位)。可以使用HIMM指令扩展立即数,变为INT #uimm16。
7、指令IRET的操作有:PC=LR, POP LR,POP PSR。
表6.3.9 控制指令(3条)
汇编指令 |
操作说明 |
IMM |
PSR |
周期 |
SLEEP |
睡眠,等待中断唤醒 |
1 |
||
SET PSR, #uimm4 |
将PSR的控制位I,P,B置1 |
I,P,B |
1 |
|
CLR PSR, #uimm4 |
将PSR的控制位I,P,B清0 |
I,P,B |
1 |
说明:表中这3条指令都是特权级指令。
表6.3.10 立即数扩展指令(4条)
汇编指令 |
操作说明 |
WIMM #imm28 |
提供高28位立即数 |
HIMM #imm12 |
提供高12位立即数 |
RIMM Ra, Rb, Rc |
提供寄存器号操作数Ra, Rb, Rc |
CIMM cond [E]JMP #v7 |
提供执行条件码cond、反条件码E和跳转矢量#v7 |
--------------------------16位指令集到这里结束-----------------------------
(全文完)
关注EETOP公众号,后台输入:百宝箱 阅读CPU相关文章:
处理器
科普:GPU是如何工作的?与CPU、DSP有什么区别?
看ARM如何抢走英特尔的X86市场––CPU市场上的逆袭!
科普:ARM与X86 CPU架构对比区别
在CPU IP授权上,ARM 是怎样战胜MIPS的?
海思CPU的设计制造过程,看了以后真觉得华为不容易
普及贴:CPU的发展历程(X86篇)
最美CPU!人类看清冥王星归功于它
扫盲帖:CPU的相关知识
历数CPU恶性BUG!原来曾有过这么多!
干货!韩国大学CPU设计课件分享
CPU DIE Photo 大全
众多国产CPU和操作系统大揭底、
服务器架构:x86、RISC、ARM谁主江湖?
RISC-V资料大全中文版!
基于RISC-V架构的开源处理器及SoC研究综述
我的处理器之路