Hexagon的程序执行顺序(一)
2015-08-11 20:49
246 查看
概述
Hexagon处理器支持如下的程序流程机制l 条件指令
l 硬件循环
l 软件分支
l 暂停
l 异常
软件分支包括了跳转(jump),调用(call)以及返回(return)。Hexagon一共支持四种不同的跳转(jump):
l 推理跳转
l 比较跳转
l 寄存器转移跳转
l 双跳转
条件指令
很多Hexagon内部的处理器可以被选择性的执行。例如:if (P0) R0 = memw(R2) // conditionally loadword if P0 if (!P1) jump label // conditionally jumpif not P1
l 如下的指令可以被指定为条件执行:
l 跳转与调用
l 大部分的load与store指令
l 逻辑指令(包括AND/OR/XOR)
l 半字移位
l 32位的寄存器或立即数加/减
l 有符号与零扩展
l 寄存器立即转移等
更多的指令可以去看我的文章
硬件循环
Hexagon处理器包括了硬件循环指令。硬件循环指令可以实现循环分支,例如:loop0(start,#3) // loop 3 times start: { R0 = mpyi(R0,R0) } :endloop0
loop0和loop1提供了两系列的循环指令,两个循环可以将硬件循环形成一级嵌套。例如:
// Sum the rows of a 100x200 matrix. loop1(outer_start,#100) outer_start: R0 = #0 loop0(inner_start,#200) inner_start: R3 = memw(R1++#4) { R0 = add(R0,R3) }:endloop0 { memw(R2++#4) = R0 }:endloop1
硬件指令主要的应用场景如下:
对于非嵌套循环,可以使用loop0来实现
对于嵌套循环,loop0用于套内循环,loop1用于套外循环
每个硬件循环与一对特定的循环寄存器相关:
l loop start address寄存器SAn被设定为循环中第一条指令的地址(通常该代码以汇编指令表示)
l loop count寄存器LCn是32位的无符号值,用于确定循环的迭代次数。但程序计数器达到了循环的地步,LCn会被检查是否循环需要重复或者是退出
硬件循环设置指令可以一次性设置两个寄存器的值,既然如此我们就没必要分开两次来设置他们。但是,因为循环寄存器需要单独的设置循环状态,他的值可以被保存并且存储(既可以通过中断也可以通过软件执行),这使得循环寄存器可以被重新导入并正常继续。
Hexagon处理器为两个硬件循环提供了两列循环寄存器:
l SA0以及LC0用于loop0
l SA1以及LC1用于loop1
下图列出了硬件循环的指令:
循环的设置
为了设置一个硬件循环,循环寄存器SAn与LCn必须被设置为相应的值。我们可以通过两种方法来实现:一个loopN指令
向SAn以及LCn的寄存器转移指令
loopN指令可实现所有设置SAn和LCn的工作。例如:
loop0(start,#3) // SA0=&start, LC0=3 start: { R0 = mpyi(R0,R0) } :endloop0
在这个案例中,硬件循环被执行了三次。loop0指令设置寄存器SA0的职位start的地址,设置LC0为3.
如果将循环数设置为立即数,则循环数的范围为0-1023。如果期望的循环次数比这个值大,那么我们必须用寄存器的值来定义它。例如:
使用loopN
R0 = #20000; loop0(start,R0) // LC0=20000, SA0=&start start: { R0 = mpyi(R0,R0) } :endloop0
使用寄存器转移:
R0 = #20000 LC0 = R0 // LC0=20000 R0 = #start SA0 = R0 // SA0=&start start: { R0 = mpyi(R0,R0) } :endloop0
如果一个loopN指令与他的循环开始地址距离太远,那么程序寄存器相对移位的值也许会超出指令起始操作数的最大范围。在这种情况下,要么把loopN的指令搬到离地址更近的地方,要么以一个32位的常数值来定义。例如:
R0 = #20000; loop0(##start,R0) // LC0=20000, SA0=&start ...
循环的终止
嵌套硬件循环可以将同样的指令指定为内部或外部循环的终止。例如:// Sum the rows of a 100x200 matrix. // Software pipeline the outer loop. p0 = cmp.gt(R0,R0) // p0 = false loop1(outer_start,#100) outer_start: { if (p0) memw(R2++#4) = R0 p0 = cmp.eq(R0,R0) // p0 = true R0 = #0 loop0(inner_start,#200) } inner_start: R3 = memw(R1++#4) { R0 = add(R0,R3) }:endloop0:endloop1 memw(R2++#4) = R0
虽然endloopN表现的像一个常用的指令,但请注意他不会在任何堆中执行,并且不会在指令包中计数。因此一个单一指令包可以实现超过六个指令,其中包括:
l 四个常规指令
l endloop0指令
l endloop1指令
循环的执行
当我们为Hexagon DSP设置好硬件循环后,循环主体最起码会被执行一次,无论是否定义了循环次数(因为循环次数在执行后才会被检测)。因此,如果一个循环需要选择性的执行0次,那么必须用一个特殊而清晰的条件分支来定义,例如:loop0(start,R1) P0 = cmp.eq(R1,#0) if (P0) jump skip start: { R1 = add(R1,#1) } :endloop0 skip:
在这个案例中,我们在R1寄存器中设置好了一个硬件循环,但是如果R1中的值为1,那么软件分支会直接跳过这个循环主体。
循环结束指令后,Hexagon处理器将检查相应的循环技术寄存器中的值:
l 如果值大于1,那么处理器将循环计数的值建议并实现一个跳转至start地址
l 如果值小于1,那么处理器将会立即继续程序的执行。
循环的限制
l loopN中的循环设置指令包不能包含间接跳转,新值比较跳转或者dealloc_return指令l 循环中的最后一个包不能包括任何程序流程指令(包括跳转和调用)
l loop0中的循环终止包不能包含任何改变寄存器SA0或LC0的指令。同样的,loop1中的循环终止包不包含任何改变寄存器SA1或LC1的指令。
l spNloop0的循环终止包不能包含任何改变P3寄存器的指令
相关文章推荐
- Singapore National Day (SG50 Golden Jubilee)
- GoLang入门5-调试我们自己写的包mymath
- GoLang入门4-编译应用mymath测试
- GoLang入门3-应用目录结构
- GoLang入门1-安装-配置
- go- 特点
- DjangoWeb: 快速搭建Blog
- django安装tinymce
- Go开发工具
- Installing LiteIDE(Go 语言开发工具)
- Gonet2 游戏服务器框架解析之Agent(2)
- MAC OS X 系统设置PAC文件代理教程 又可以访问google了。
- UVA 11292 The Dragon of Loowater
- django orm排序
- CodeForces 5A - Chat Servers Outgoing Traffic
- 电信谜团错综复杂,电信欢go与联通是否合并?
- django Q 函数
- 一款工具可去除Google Play服务 Win10 Mobile可进行安装安卓APK应用
- Django 搭建过程记录
- Django Models的数据类型 汇总