DSP汇编指令学习笔记

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Knowledge
问题
谁在DSP的汇编语言中加入了NOP指令?
NOP指令加入的条件是什么?
About DSP
1.DSP是实时数字信号处理的核心和标志。

2.DSP分为专用和通用两种类型。

专用DSP一般采用定点数据结构(一般不支持小数),
数据结构简单,处理速度快;通用DSP灵活性好,但是处理速度有所降低。

3.DSP采用取指、译码、执行三个阶段的流水线(Pipeline)技术,缩短了执行时间,提高了
运行速率。

DSP具有8个Functional unit,如果并行处理的话,以600MHz的时钟计算,如果执行的指令是single cycle指令,则可以4800MIPS(指令每秒)。

4.DSP的8个functional Unit,具有独特的功能,对滤波、矩阵运算、FFT(傅里叶变换)
具有
哈弗结构
把指令空间与数据空间隔离的存储方式。

这样实现是为了实现指令的连续读取,而实现pipeline流水线结构。

传统哈弗结构:两个独立的存储空间,还使用独立总线。

让取指与执行存储独立,加快执行速度。

改进型哈弗结构:指令与数据的存储空间还是独立的。

但是使用公共的总线(地址总线与数据总线)。

这样实现的原因是因为出现了CACHE,数据的存储动作大部分被内部的CACHE 总线承接了,所以总线冲突的情况会大大减少。

同时让总线的结构与控制变得简单,CACHE 存储的速度也明显快于外设存储器。

冯诺依曼结构:是指令空间与数据空间共享的存放方式。

它不能实现pipeline的执行过程。

Pipeline(流水线)技术
是把指令的取指-译码和指令的执行独立开来的技术。

虽然每条指令的过程还是要经过取指-译码-执行三个阶段最少3个CPU Cycle。

但是多个指令同时并行先后进行,保证总体的指
令吞吐速率理想情况下可以保证在每个指令只要一个CPU CYCLE。

Pipeline技术必须要有哈弗结构支持,即必须把指令空间与数据空间隔离存放。

流水线阻断
流水线中阻断现象也十分普遍,下面就各种阻断情况下的流水线性能进行详细分析。

流水线阻断总体有两种情况:
1.资源冲突阻断:
a)如果前一指令的某Stage与后一指令某Stage在同一个Cycle执行,但是
前一指令此Stage占用了后一指此Stage的资源,则后一指令此Stage的
工作会被延迟执行。

b)被延迟执行的动作会停留在前一个Stage状态,则前一个Stage的状态就
不能进入新的指令的动作。

c)依次前推,则总有一个取指Stage的指令被阻断,那么其后一个指令也被阻
断而不能被取指。

d)所以,每产生一个Cycle的阻断,就会让CPU的执行延迟一个Cycle。

即此
指令后面的所有指令都会被延迟一个Cycle被执行。

e)解决的方法是:使用Cache让存放变得更快;变量集群使用,记录减少变量
存放到memory的需要。

2.跳转阻断:
a)跳转阻断有很多情况产生,比如函数调用/返回,循环的break/continue,
if等条件判断,循环跳转,中断跳转的产生。

b)一旦某条指令要进行跳转时,它就会设置LR寄存器,阻止后续的指令进入执
行Stage,并修改PC指针,执行跳转后的目标代码。

c)解决的方法是:减少循环、条件判断、分支结构的使用。

DSP Pipeline技术
DSP具有8个独立的执行单元,所以每个CYCLE可以执行8条指令(要求其总线宽度是256bit)。

即DSP是8个pipeline并行处理的技术。

所以DSP每个阶段取8个指令,然后在译码阶段把8个指令分配到8个执行单元去处理。

所以必须保证被同时取的指令之间没有相关性(即一个指令的执行不需要其他指令的结果参
与),否则会得到错误的结果。

所以,DSP引入了NOP指令,如果不能实现这一的要求,则DSP的编译器,则DSP优化器会在其编译的指令后面添加NOP指令。

表示此Cycle不能执行8条有效指令,只能擦入空指令。

则这样就会有某些执行单元在此CYCLE空闲了。

DSP Pipeline阻断
DSP Pipleline的阻断处理相对比较复杂一些,因为它涉及到8独立执行单元的阻断。

1.资源冲突阻断:
a)如果某个Unit因为资源冲突阻断,或者因为一个指令需要多个Cycle执行。

则此
Unit会被阻断。

b)当某个Unit被阻断时,其上一个阶段的指令就不能往下传递。

一直阻断到此Unit
的取值动作。

c)所以当有阻断发生是,FG并不会请求8条指令,而是请求1-7条,或者不请求(8
个Unit全部阻断了)。

这样没有被阻断的Unit还是能够充分运行的。

2.跳转阻断:/p-908395009795.html
a)
NOP
Not dispatched instruction
It is an empty instruction in DP packet.
如果一个指令标识需要Delay N个slot,则需要在这个指令后面跟N个NOP指令(对于那些自身不带NOP的指令,比如B)(但是对于BNOP则不需要的)。

通过寄存器的定位技巧
1.查看NRP寄存器的值,则可以直接查看在哪个周期的指令异常了(NRP指令的前一周期就是crash
的指令)(使用A10/B10……可以看到此函数的参数)
2.查看B3寄存器的值,跳到此代码段查看前面一个的Jump指令。

看是jump到哪个函数了,则是在此
函数中出异常了。

则可以看到是谁调用的此crash的函数。

(使用A4/B4……可以看到parent的参数)3.如果参数是二维指针,则此参数所在类存一般都是栈内的某个地址。

(可以根据栈空间的特点知道具
体应该是哪个地址)
CPU data path & control
说明:
1.Register A也是由两片寄存器组组成的,A0:A1/ … /A30:A31的pair是分布在两个组片
中的
2.ST path是把寄存器的值写入内存的路径
3.LD path是把内存的值加载到寄存器中的路径
4.DA path是读写寄存器的路径
5.X path是跨组读写寄存器的路径
A &
B path general purpose registers
1.Each A & B path has 32 32-bit register, named A0-A31, B0-B31.
2.It supports 40bit & 64bit value. If value is larger than 32 bit, it needs
register-pair. The 32LSB stores in even-numbered register, such A0, and the 8 or 32 MSB stores in odd-numbered register, such A1.
3.General purpose registers can be used for data, address pointers,
condition registers.
8 functional units
1.8 functional units can be divided into 2 groups, G1: L1, S1, M1, D1
for A register path, and G2: L2, S2, M2, D2 for B register path. 2.Each function units has its special function, such as +/-/*/>/<. But
some operations can be deal in all units
Unit path
The C6000 CPU has 2 generous purpose register files ( A & B), 8 function units (L1/S1/D1/M1 & L2/S2/M2/D1).
The 8 function units have different path to access data or data addres s:
1.L Path:LD1/LD2: Access data path of A & B register files
a)从A/B中读取数据
2.DA1/DA2: access data address path of A & B register files
a)把数据保存到A/B中
3.ST1/ST2: write data path of A & B register files
a)把立即数或者控制寄存器保存到A/B中
4.1X/2X: cross path of A & B register files, to access opposite-side.
a)跨A/B读取数据
5.说明:
a)前面三个路径统称为T路径(LD、ST、DA)。

在具体汇编指
令上,只会显示为T或者X路径,不会具体显示某一种T路
径。

b)X路径是在跨A/B寄存器使用的,用或不用情况是一定的
c)现在只有使用了X路径,或者LDW、STW指令会显示具体使
用的路径名称。

Register File Cross Paths
1.G1 units can read/write data from/into A registers. And the G2 units
can read/write data from/into B registers. So G1 units have cross path to A registers, and G2 units have cross path to B register.
2.At the same time, A registers have cross paths to opposite-B registers,
such as Ax is connect to Bx. So function units of A registers can access B register.
Normal registers
Reserved by表示谁负责保存这个寄存器中的值,如果是Parent,则是Caller;如果是Child 则是called function。

这里的Parent与child是与某此调用动作相关。

如果脱离具体的某此调用,基本所有的函数都即是parent又是child。

或者说,在某此函数调用时,哪些寄存器是在调用之前就要压栈保存(可能同时赋值的)——parent类的寄存器;哪些寄存器是在调用后如果使用到了才需要压栈保存的——child类寄存器。

寄存器中的值,始终是根据此次调用(即Crash时的调用)的参数状态。

即Parent寄存器保
存的Crash function的Caller的参数;而child寄存器保存的是crash本函数的参数。

所以可以查看A10、B10……查看异常函数的参数;查看A4/B4……查看上层函数的参数。

同一指令周期并行执行的指令,不能同时使用同一寄存器。

SP /B15 & FP/A15 & PC & DP
1.SP /B15:是栈顶指针(B15可以在gPdb查看)。

启动时需要手动初始化。

2.FP/A15:是本函数的栈底指针。

现在没有使用,FP始终等于SP。

A15没有使用。

3.PC:是PFC(program fetch counter),是取指位置,是jump指令操作的寄存器(不能在
gPdb中查看,也没有具体意义,因为异常处理时PC也会变)
4.DP:初始化是.bss(为全局变量和静态变量保留(不包含const类全局变量))段的起始
地址。

用于指示全局变量的基址。

启动时需要手动初始化。

5.
SP & B15 (stack pointer)
B15就是SP的值,它们是同一个寄存器。

表示栈顶指针。

SP指针必须是8字节对齐的。

Unaligned SP Can Cause Application Crash。

B15 is the stack pointer (SP), which points to the next unused location on
the stack。

FP & A15 (frame pointer)
A15就是SP寄存器。

The frame pointer is used to read arguments from the stack and to handle register spilling instructions.
A4:A5 & A3 (function return value)
A4 (或者A4:A5):是函数返回值(非结构体返回值)存放的寄存器。

通常其值的来源是上一函数的返回值。

A3:如果返回的是一个结构,则返回结构的支持存放在这里。

B3 & IRP & NRP (function return address)
B3:普通函数,当前调用的返回地址。

之前调用的返回值已经压入栈中了。

IRP:可掩中断调用返回地址。

NRP:不可掩中断调用返回地址。

B3:
836178A0 AaSysComMsgRelay:
836178A0 2246 MV.L1 A4,A1//T1
836178A2 0247 || MV.L2 B4,B0
836178A4 01BC94F6 || STW.D2T2 B3,*SP--[4]
836178A8 9014A121 [!A1] BNOP.S1 C$L37 (PC+40 = 0x836178c8),5//T2
836178AC 80040264 || [ A1] LDW.D1T1 *+A1[0],A0
836178B0 D014A120 [!A0] BNOP.S1 C$L37 (PC+40 = 0x836178c8),5//T3
836178B4 1000C813 CALLP.S2 $Tramp$L$PI$$_AaSysComMsgSend (PC+1600 = 0x83617ee0),B3//T4 //跳转到AaSysComMsgSend函数(FP AaSysComMsgSend),并把T5的代码的地址保存在B3中836178B8 00002276 || STW.D1T2 B0,*+A0[1]
836178BC E0200003 .fphead n, l, W, BU, nobr, nosat, 0000001
836178C0 01BC92E6 LDW.D2T2 *++SP[4],B3//下一周期T5
836178C4 6C6E NOP 4
PFC & retPC & PCE1
1. PFC is the program fetch counter
2. retPC represents the address of the first instruction of the execute packet in the DC
stage of the pipeline
3. PCE1 (program counter) represents the address of the first instruction in the fetch
packet in the E1 stage of the pipeline..
Control register file
Table 2-6. Control Registers
Acronym Register Name Section
AMR Addressing mode register Section 2.8.3
CSR Control status register Section 2.8.4
GFPGFR Galois field multiply control register Section 2.8.5
ICR Interrupt clear register Section 2.8.6
IER Interrupt enable register Section 2.8.7
IFR Interrupt flag register Section 2.8.8
IRP Interrupt return pointer register Section 2.8.9
ISR Interrupt set register Section 2.8.10
ISTP Interrupt service table pointer register Section 2.8.11
NRP Nonmaskable interrupt return pointer register Section 2.8.12
PCE1 Program counter, E1 phase Section 2.8.13
Control Register File Extensions (C64x+ DSP)
DIER Debug interrupt enable register Section 2.9.1
DNUM DSP core number register Section 2.9.2
ECR Exception clear register Section 2.9.3
EFR Exception flag register Section 2.9.4
GPLYA GMPY A-side polynomial register Section 2.9.5
GPLYB GMPY B-side polynomial register Section 2.9.6
IERR Internal exception report register Section 2.9.7
ILC Inner loop count register Section 2.9.8
ITSR Interrupt task state register Section 2.9.9
NTSR NMI/Exception task state register Section 2.9.10
REP Restricted entry point address register Section 2.9.11
RILC Reload inner loop count register Section 2.9.12
SSR Saturation status register Section 2.9.13
TSCH Time-stamp counter (high 32) register Section 2.9.14
TSCL Time-stamp counter (low 32) register Section 2.9.14
TSR Task state register
这些控制寄存器,直接使用就可以了。

TI会把他们定义为全局变量。

比如
extern __cregister volatile unsigned int EFR;
这任何时刻,EFR表示“EFR”寄存器的值。

Exceptions
Exceptions
1.外部中断:由CPU的外围设备产生的,输入到CPU内,产生的中断叫外部中断。

如果
是外部严重错误(Fatal error)将会产生NMI中断。

2.内部中断:CPU内部自己产生的,比如溢出异常、指令异常、内存访问异常、资源冲
突、等,称为内部中断。

内部中断会有寄存器记录其产生的原因的。

3.Reset Interrupt: GPIO 23,强制重启中断。

不可掩。

4.NMI - EXCPHNDL_EFR_NXF(non-maskable interrupt): 是CPU硬件错误
a)The NMIE bit in TSR must be set, then NMI will occur
b)Setting the global exception enable (GEE) bit in the task state register (TSR) to 1,
this interrupt will behave as an exception.
5.IXF - EXCPHNDL_EFR_IXF: 是CPU计算异常
a)比如指令异常、内存异常,资源异常、除0溢出异常等
6.EXF - EXCPHNDL_EFR_EXF: 是外设上报到CPU的异常
7.SXF - EXCPHNDL_EFR_SXF: 是软件通过SWE指令特意触发的异常,相当于error2。

8.所有的异常,在执行结束后都会继续执行(出了断电异常)。

一般芯片的异常后停止运
行的现象,是APP软件自己实现的,即在底层运行一个死循环。

CPU control registers
1.PC(PCE1)是用来指示下一条要执行的指令的,即存放的是下一条要执行的指令的地址。

几乎所有的MCU都不允许MOV指令修改PC值,这是一个常识。

2.中断服务表指针寄存器ISTP(interrupt servicetable pointer)用于确定中断服务程序在中断服务表中的地址。

ISTP中的字段ISTB确定IST的地址的基值,另一字段HPEINT确定特定的中断,并给出这一特定中断取指包在IST中的位置。

3.IFR(中断标志寄存器):显示出有终端请求但尚未得到服务的中断。

4.IER(中断使能寄存器):使能后禁止中断处理。

5.IRP(可屏蔽中断返回指针寄存器):包含从可屏蔽中断返回的地址,该中断返回通过指令BIRP完成。

6.NRP(不可屏蔽中断返回指针寄存器):包含从不可屏蔽中断返回的地址,该中断返回通过指令BNRP完成。

7.CSR(控制状态寄存器):控制全局使能或禁止中断。

8.AMR(寻址模式寄存器):制定是否使用线性或循环寻址,若循环寻址还指定循环地址大小。

9.EN(端结方式):1=小端终结;0=大端终结。

10.Event Encoder (事件编码器):事件寄存器ER(包括ERL和ERH)用于捕获对应于64个EDMA通道的事件。

在事件编码器中只是负责提交请求,事件的优先局依赖于EDMA通道参数的设定,并且在Transfer Crossbar中才正式排定。

11.协处理器控制位
CR0中的位1~4分别标记位MP(算术存在位)、EM(模拟位)、TS(任务切换位)和ET (扩展类型位),它们控制浮点协处理器的操作。

EM位控制浮点指令的执行是用软件模拟,还是由硬件执行。

EM=0时,硬件控制浮点指令传送到协处理器;EM=1时,浮点指令由软件模拟。

12.中断描述符表寄存器IDTR
IDTR长48位,高32位存段基址,低16位存段界线。

由于80386只支持256个中断/异常,所以IDT表的最大长度是2K,以字节位单位的段界线为7FFH。

IDTR表示IDT表的方式与GDTR表示GDT表的方式相同。

Pipeline
Pipeline Stages
All instructions require the same number of pipeline phases for fetch and decode, but require a varying number of execute phase s.
Fetch -- Decode – Execute
Knowledge points
Network materials
5stage的
F/D - Fetch (from cache) and decode four instructions
G - Group up to four instructions
R - Read register file and forward operands
E - Execute operations, read memory
W - Updates select control registers, complete writes
Fetch packet
就是一次获取的指令。

即||获取的指令包。

一个指令包最少1条指令,最多8条。

Execute packet
是执行单元内部的概念。

即一条被执行的指令。

一个Fetch packet可以包含1-8个Execute packet
Fetch package steps
1.PG: generate a program address
2.PS: send a request to read program
3.PW: wait for response
4.PR: Receive a program instruction
Decode package steps(P512)
1. DP: Instruction dispatch
a) 从fetch packet中提取execute packets并送到对应的执行单元中。

2. DC: Instruction decode
a) 在执行单元中的第一个动作,解析DP送进来的execute packet。

Execute stage
Execute stage has 5 phase, E1-E5. Each phase need which
Each phase has its own special functions. Different instructions require different E phases to complete their executions.
执行阶段最多需要5个步骤。

不同的指令需要的步骤也是不一样的。

从执行的步骤的角度看,DSP相关的指令,大致可以分为6类(包括NOP有7类),下图是每类指令需要的执行步骤,以及执行完这些步骤所需要的Slot (CPU Cycle)。

Delay slot:是E1步骤执行完后,此类指令后续执(或者等待)行还需要的CPU Cycle数。

只有在Delay Slot之后,指令的结果才是可用的。

6类指令的具体情况是:
1.Single Cycle类:单Cycle指令类,只有数据的计算存储。

这类指令只需要E1步骤,需
要一个CPU Cycle。

这个指令是计算立即数,并把计算的结果保存的AB寄存器中。

2.16bit * 16bit (.M Unit执行)指令:这个指令需要2个Cycle。

3.store:是指存放到memory中。

它需要3个步骤E1、E2、E3,但是只需要1个Cycle。

这是因为,在数据Access memory后,如果后面是Load动作,则直接可以从E4开始了,所以相当于Store只用了1个Cycle。

Summary
1.取值是根据PC指令,从内存中取出指令;取数是值根据寄存器记录的内存地址,从此
地址中获取数据。

2.此DSP指令读取与数据读取是走同一Pipeline中的,但是在不同的阶段完成的。

指令获
取是在PG/PS/PW/PR/DP中完成的,它把指令送到执行单元。

执行单元经过DC,后开始执行指令。

在执行指令时,如果需要Load数据,则会在E1/.../E5中完成对数据的操作。

3.取指令的5个阶段与取数据的5个阶段的过程是类似的。

如下图:
4.当数据或者指令都L1cache中(L1D、L1P中),则取值与取数都不会有额外的CPU stall
产生。

a)但是如果指令不在L1P中,则取值会在PW阶段产生大等于1个Cycle的stall。

b)但是如果指令不在L1D中,则取值会在E3阶段产生大等于1个Cycle的stall。

c)当CPU产生Stall,则会前向传递进行Stall积压指令。

5.Stall就是CPU需要额外的N周期去获取资源时,则会停止取指N周期。

6 types of instructions
Single cycle instructions
Most DSP instructions are single-cycle instructions, which means they have only one execution phase (E1).
Store Instructions
Three steps E1/E2/E3:
E1: get target address from register file, and calculate the access address of memory. E2: send this address to Memory controller. Get data from register file and send it to memory controller
E3: operating the memory. Write the data into the memory. Branch Instructions
Instructions
Units of Instruction
Conditional Operations
执行条件寄存器判断。

A0/A1/A2 B0/B1/B2 为0(Z=0)时才执行;或者不为0(Z = 1)是才执行。

Creg 3bit决定对哪个寄存器进行判断。

Operations
1.Src → dst : 32 bit data
2.Src_h:Src_l → dst_h:dst_l : 40 bit data. H is 8msb
3.src_o:Src_e → dst_o:dst_e : 64 bit data o is 32 msb
Instruction description
Description format
EXAMPLE (.unit) src, dst
.unit = .L1, .L2, .S1, .S2, .D1, .D2
src and dst indicate source and destination, respectively. The (.unit) dictates which
functional unit the instruction is mapped to (.L1, .L2, .S1, .S2, .M1, .M2, .D1, or .D2).
可见,DSP的汇编已经制定命令执行的Unit了,dispatch动作仅仅是根据指令进行分发而已。

指令格式有以下特点:
1.在同一个指令中,使用不同的unit,与操作数的bit数什么的都有关系。

所以从指令使
用的unit,可以看到很多关于操作数的性质。

2.指令中已经包含了指令的unit,所以dispatch动作仅仅是根据指令进行分发
3.
ABS
A BS Absolute Value With Saturation
Syntax ABS (.unit) src2, dst //for 32bit data
or
ABS (.unit) src2_h:src2_l, dst_h:dst_l //for 40bit data
unit = .L1 or .L2
Instruction Type Single-cycle Delay Slots 0
Compatibility C62x, C64x, and C64x+ CPU
Examples Example 1
ABS .L1 A1,A5
Examples Example 2
ABS .L1 A1:A0,A5:A4
x cross path for src2; 0 = do not use cross path, 1 = use cross path
op opfield; field w ithin opcode that specifies a unique instruction:指令号
p parallel execution; 0 = next instruction i s not executed in parallel, 1 = next instruction is executed in parallel
s side A or B for destination; 0 = side A, 1 = side B.
ABS2 (for 16bit)
A BS2 Absolute Value With Saturation, Signed, Packed 16-Bit
Syntax ABS2 (.unit) src2, dst
unit = .L1 or .L2
Instruction Type Single-cycle Delay Slots 0
Compatibility C64x and C64x+ CPU
Src2:是两个独立的16bit的数据。

Dst:是两个独立的16bit的数据。

ADD系列(ADD/ADDAB/ADDKPC)
ADD
A DD Add Two Signed Integers Without Saturation
Syntax ADD (.unit) src1, src2, dst
or
ADD (.L1 or .L2) src1, src2_h:src2_l, dst_h:dst_l
or
ADD (.D1 or .D2) src2, src1, dst (if the cross path form is not used)
or
ADD (.D1 or .D2) src1, src2, dst (if the cross path form is used)
or
ADD (.D1 or .D2) src2, src1, dst (if the cross path form is used with a constant) unit = .D1, .D2, .L1, .L2, .S1, .S2
Instruction Type Single-cycle Delay Slots 0
Compatibility C62x, C64x, and C64x+ CPU
Execution:
Src1 + Src2 --> dst
ADDAB
A DDA
B Add Using Byte Addressing Mode
Syntax ADDAB (.unit) src2, src1, dst (C64x and C64x+ CPU) or
ADDAB (.unit) B14/B15, ucst15, dst (C64x+ CPU)
unit = .D1 or .D2
Compatibility C62x, C64x, and C64x+ CPU
sint Signed 32-bit integer value
ucst n n-bit unsigned constant field (for example, ucst5)
Execution:
src2 + src1 → dst
ADDK
Syntax ADDK (.unit) cst, dst
unit = .S1 or .S2
Description A 16-bit signed constan t, cst16, is added to the dst register specified. The result is placed in dst.
Execution
if (cond) cst16 + dst → dst
else nop
ADDKPC
ADDKPC (.unit) src1, dst, src2
1. 把Src1的值设置到dst中,并NOP src2 个cycle.
2. 即本指令需要src2 + 1个slot才能完成。

3. 这个指令并不是跳转指令,仅仅是同时完成了高低16bit赋值以及NOP控制的一个指
令。

如果NOP为0此,则高低16bit赋值仅仅为1个cycle
SWE
SWE Software Exception
Syntax SWE
unit = none
Compatibility C64x+ CPU
Description:
Software sprint an exception by this instruction. It will set SXF bit in EFR to 1.
And when it complete, CPU will continue with the instructions specified by NRP register SWENR no-return SWE
It is the same as SWE, but NRP will be invalid.
MV系列
1.MV (.unit) src2, dst:Move From Register to Register AB寄存器之前的MV
2.MVC (.unit) src2, dst:Move Data from AB register to Control register, such as ARM/IRP
3.MVD (.unit) src2, dst:Move From Register to Register, 和MV一样,但是需要3个NOP。

4.MVK (.Unit) src dst 把有符号数的立即数赋值到dst中
5.MVKH (.unit) cst, dst:把立即数的MSB 16bit 赋值到dst的MSB 16bit
6.MVKLH (.unit) cst, dst:把立即数的LSB 16bit赋值到dst的MSB 16bit
大小对比操作
1.CMPLT (.unit) src1, src2, dst
a)if (src1 < src2), 1 → dst else else 0 → dst
b) src1是否小于src2,是的话dst=1;否则等0
c) Delay Slots 0
2.CMPEQ (.unit) src1, src2, dst
a)if (src1 == src2), 1 → dst else else 0 → dst
b)Delay Slots 0
逻辑操作系列
AND Src1 Src2 dst:Src1安位与Src2 结果赋值到dst
Store系列(STDW/)
1.所有的store指令的delay slot都是0,但是数据真正写入内存的delay slot = 3.
2.就是说,如果要从内存中直接去看数值的改变需要4个slot后。

3.但是在第一个slot后,如果代码去Load此地址的值,则能够Load新的值。

因为系统
并没有真正的直接从内存中获取,而是半路拦截了正在保存的数据(因为是同一地址),所delay slot为0了。

STB
STB Store Byte to Memory With a 5-Bit Unsigned Constant Offset or Register Offset
存储寄存器的低8bit到内存中。

SIZE = 1B
STH
SIZE = 2B
STW
SIZE = 4B
STDW (DW store (8Bytes))
SIZE = 8B
STDW (.unit) src, *+baseR[ucst5]
DW store
if (cond) src → mem
mem = *BaseR + (ucst5 * 8)
或者
STDW (.unit) src, *+baser(ucst5)
if (cond) src → mem
mem = *BaseR + ucst5
Delay Slots 0
Load系列(LDW)
LDW
Syntax
Register Offse t Unsigned Constant Offset
LDW (.unit) *+baseR[offsetR], dst LDW (.unit) *+baseR[ucst5], dst
unit = .D1 or .D2
Delay Slots 4 for loaded value
Example
LDW .D1 *A10,B1
把*A10的值Load到B1.但是B1只有在执行后4 slot后才会有可用的值。

也就是说,这个指令要5个slot才能完成。

jump(B/BNOP/BDEC/ CALLP)
Only PFC jump(B/BNOP/BDEC)
1.B:
a)修改FP指针的值,让程序后面从一个新的位置开始取指(PG、PS、PW、PR的开
始)
b) B Src:Src→ PFC B IRP: IRP→ PFC B NRP: NRP→ PFC
c)Delay 5个slot,即在执行此指令后5个slot时才开始真正的跳转。

2.BNOP:
a)修改PFC指针的值的同时,后面添加N个NOP指令。

一般都要添加4个,因为B
指令跳转到新的地方取指后,新取的指令需要等待取指、分发才会进入执行阶段,所以需要等待。

b)Delay 5个slot(不包括其包含的NOP数),即在执行此指令后5个slot时才开始真
正的跳转。

3.BDEC (BDEC (.unit) src, dst):
a)如果dst>=0,则先dst -= 1, 后PFC = src。

b)否则,直接PFC = src
c)Delay Slots 5
PCE1 jump(CALLP/)
1.CALLP (.unit) label, A3/B3:
Execution(跳转到label,并把返回值保存在A3或B3中)
(cst21 << 2) + PCE1 →PFC(label –> PFC)
if (unit = S2), retPC → B3
else if (unit = S1), retPC → A3
nop 5 (Delay Slots 5)
(注:cst21 = (label - PCE1) >> 2)
a)这个在修改FP的同时,会保存retPC指针,用于返回return地址。

在return后会
把这个地址赋值给PFC,然后从这条指令开始重新执行。

b)Delay Slots 5
SPLOOP系列(SPLOOPD/
SPLOOP
Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing
是通过延时,获取L2/Ext 内存的数据Copy到L1 Memory中。

典型汇编语句解析
STXX REG *B15--[1]
把REG的值保存到内存中。

具体的操作SIZE要看存储的指令。

STB = 1B;
STDW = 8B;
REG *B15- - [x]
REG *B15++ [x]
先把REG的值赋值到*B15开始的地址中,然后B15减、加x个REG SIZE
REG *-- B15[x]
REG *++B15[x]
先B15减、加x个REG SIZE,然后先把REG的值赋值到*B15开始的地址中。

例子:
83689CB0 8577 STDW.D2T1 A11:A10,*B15--[1]
83689CB2 4646 || MV.L1 A4,A10 //写A10会在读A10之后执行
*B15 = A11:A10
*B15 -= 8 (A11:A10是8Byte)
注:每个cycle,写是在读之前完成的,所以此语言写入*B15还是老的A10的值。

SPLOOP & SPLOOP buff
指令软件流水循环和软件流水缓存
Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing
1.它是C64X+新增的一个硬件模块,目的是为了快速完成循环指令。

即实现DSP汇编指
令循环。

2.SPLOOP通过把循环指令的每次循环的Kernel指令打包存放在SPLOOP buff中,可以
最多存放14个指令包(即循环体最多可以有14个指令包):
a)SPLOOP buff最多可以缓存14个指令包,每个指令包是一个8*32bit的单元,用于
存放多条要被执行的指令。

b)CPU可以直接从此buff中读取指令包,而不需要到L1P去获取,这样减少L1P取
指令压力。

c)
是通过延时,获取L2/Ext 内存的数据Copy到L1 Memory中。

SPLOOP Prolog/Kernel/epilog
做SPLOOP Prolog的目的和特点:
1.会按照需要指令的特点(比如LWD指令需要5个cycle),对即Kernel区域的所有寄存
器进行初始,保证在Kernel阶段,所有的寄存器中的值都是有效的。

2.即会把SPLOOP和SPKERNEL之间的指令都执行一遍(SPKERNEL和与SPKERNEL
并行的指令不会被执行)
做SPLOOP Kernel的目的和特点:
1.会把循环体内所有的指针都运行到。

并彻底完成第一次到第N此的循环动作。

做SPLOOP epilog的目的和特点:
1.它与Prolog是互补的。

如果某个指令在Prolog中被运行了多次,则在epilog中就不会
被运行了。

2.总之,所有循环体内的指令,在Prolog/Kernel/epilog中运行的总次数是一样的,即是循
环的次数。

SPKERNEL
是SPLOOP的结尾标志,与主体代码的最后一条指令并行(||)。

SPLOOP
SPLOOP ii
1.它表示一个循环体的开始,会启动SPLOOP Prolog。

2.ii表示单循环体单次循环需要的CPU cycle的个数
3.做SPLOOP Prolog的目的和特点:
a)会按照需要指令的特点(比如LWD指令需要5个cycle),对即Kernel区域的所有
寄存器进行初始,保证在Kernel阶段,所有的寄存器中的值都是有效的值。

Memset的部分代码
SPLOOPD
SPLOOPW
Stalls
就是CPU的等待cycles。

(注意,并不是IDEL,而是WAIT)。

区别是stalls是硬件加入的,不需要NOP指令。

1.当CPU要用一份数据,而这一份数据还没有准备好,则CPU只有等待。

2.或者为了避免混乱,CPU的某个ACTION就要多个Cycle才能完成,CPU会在那里等
待。

Cross Path register file read Stall
1. 当指令通过Cross path(X path, such as S1X, S2X, D1X, D2X等)读取某寄存器时,
如果此寄存器是在上一个周期被另一path指令更改(LDW指令改变除外,LWD指令获取的数据本来就要在5个cycles后才可以使用),则此需要等待一个Stall(即一个Cycle)
a) 此Stall是通过硬件插入的,不需要NOP指令
b) 但是如果寄存器的改变是作为LDW指令的目标寄存器而改变时,则下一指令用
它时不需要插入此stall(具体原因可以参考LDW指令的实现)
2. 避免此stall的方法
a) 通过指令排序,避免读取这样的寄存器
b) TMS320C6000 Optimizing Compiler and Assembly Optimizer automatically perform
this scheduling
Memory stall(L1 Cache miss stall)
A memory stall occurs when memory is not ready to respond to an access from the CPU.
1.当数据或者指令都L1cache中(L1D、L1P中),则取值与取数都不会有额外的CPU stall
产生。

a)但是如果指令不在L1P中,则取值会在PW阶段产生大等于1个Cycle的stall。

b)但是如果指令不在L1D中,则取值会在E3阶段产生大等于1个Cycle的stall。

2.Stall就是CPU需要额外的N周期去获取资源时,则会停止取指N周期。

Atomic operation
shared_ctr: //原子操作开始
LL *A8, A6 ; //从目标地址LDW一个Word到A6,此时会HW设置一个原子操作标志为True,如果以后目标地址中的值被重写则此标志会变
为False
NOP 4
ADD A6,A9,A6 ;
SL A6, *A8 ; //准备新值,如果新值buff的地址不是目标地址,标志也会变为False. 即LL & SL是配对操作
CMTL *A8, A1;//提交新值。

此目录会先获取HW标志到A1中,然后把SL buff 的数据提交store到内存中,之后硬件标志也会变为false NOP 4
[!A1] B shared_ctr;//如果目标地址在CMTL之前已经被重写,则此过程
重新执行,保证原子操作
可见这是一个通过汇编代码逻辑来实现的原子操作过程。

实际是在汇编层面实现的一种逻辑锁。

Function call conventions
Knowledge about function call
1.当函数被调用时,栈顶指针的位置,应该与函数return后回到parent函数时栈顶的位置
一样。

即,从SP指针看,一个被返回的函数不会对它的位置有任何改变。

Register type
1.Parent type:即由本函数设置的,但是一旦调用了其它函数再返回来时,这些寄存器中
的值就不可再用了(也可以说是不需要了),有A0/B0……A8/B8(包括A9/B9),和A16/B16……A31/B31。

2.child type:即本函数设置的,不管怎么调用child函数,只要本函数自己没有修改这些
寄存器的值,则这些值就不会被改变,还是可以用的。

有A10/B10……A15/B15 (16对)。

3.除了这些AB数据寄存器外,控制寄存器也具有这两种属性。

How a parent function makes a call
1.首先,每次函数调用如果有参数需传入,都是从A4/B4、A6/B6……A12/B12的顺序开
始传递参数的。

a)如果Parent函数用到了A4/B4……A8/B8(比如它自己的入参),则要保存这些参
数到stack中,然后开始使用它们传递参数到child函数。

在child函数返回的时候,
这些寄存器的值不能再使用了,除非进行恢复。

b)如果参数超过6个,则需要使用A10/B10、A12/B12,则需要先把这些参数保存到
stack中(不管本函数之前是否使用过这些寄存器)。

在child函数返回时,一定要
恢复这些寄存器的值。

i.因为A10/B10、A12/B12此类寄存器是child属性的寄存器,所有的caller都
认为其中的值时不会变的。

但是所有的child都可能使用这写寄存器,处理的
办法就是,每层函数(即是parent又是child)使用这些寄存器时,先保存其
中的值,等用完后,再恢复其中的值。

则对于其上层函数来说,则其保存在这
些寄存器中的值是没有被改变的。

ii.A4/B4……A8/B8这些寄存器则是parent属性的寄存器。

它们用于传递参数。

默认认为,当parent调用了child的函数时,则child函数就可以改变其中的值。

所以当函数进入时,如果某个传入的参数在调用第一个child函数后还要使用,
则这样的参数需要保存。

因为不能保证child函数返回后,这些寄存器中的值
是没有变化的。

c)如果参数超过10个,则需要把第11个以及之后的所有参数保存到stack中。

在child
的函数中,则从stack中获取这些参数。

如果这些要参与到运算,则还要Load到
寄存器中使用。

i.参数压栈在stack中的哪个位置,而child函数又怎么来使用它们,则是编译
器在生成汇编代码是自己控制的。

ii.在child函数返回时,parent函数要回收这些栈空间。

因为这些栈空间是为child 函数分配的,再child函数返回后,就没有任何作用了。

所以要第一时间收回。

iii.在被压栈的参数中,还有Parent函数的return address寄存器B3。

因为parent 需要设置本次调用的返回函数。

d)如果传入的参数是一个结构体,则函数实际使用寄存器传入的是此结构体在parent
函数中的指针。

Child函数接收到时,先要通常此寄存器,在栈中分配一片空间,
把整个结构体copy下来。

i.可见结构参数实际传入的是一个指针。

相关文档
最新文档