DSP开发宝典
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.4.1 TMS320C6000系列DSP指令集

本节主要讲述了TMS320C62x/C64x/C67x数字信号处理器通用的指令集,同时介绍了操作码映射、并行操作、条件操作和资源限制,同时介绍了常用指令的用法。

1.指令和功能单元之间的映射

TMS320C6000汇编语言的每一条指令只能在特定的功能单元执行,从而形成了指令与功能单元之间的映射关系,参见表2-17。

表2-17 TMS320C62x/C67x/C64x指令与功能单元之间的映射关系

注:†仅能使用S2;‡仅能使用D2。

2.延迟时隙

TMS320C62x指令的执行可由延迟时隙来定义。延迟时隙在数量上与从读取指令的源操作数到访问其执行结果所使用指令周期相等。对于单周期指令而言,在第i周期读取源操作数,则在第i+1周期得到执行结果;对于4周期指令(MPY),如果在i周期读取源操作数,则周期i+4得到结果。

TMS320C62x的所有指令都适用于TMS320C67x,但是有一些特定的指令仅对TMS320C67x适用。这些指令中包括双精度浮点类型加法、减法、乘法、比较,以及32位的整数乘法等。它们的功能单元等待时间大于1,即占用功能单元的CPU周期数大于1。例如,ADDDP指令的功能单元等待时间为2,在第ii+1周期读取操作数,因此只能在第i+2周期开始执行下一条指令,而非i+1周期。因为ADDDP指令的延迟时隙为6,所以其结果只能在第i+7周期被读取。TMS320C62x和TMS320C67x的各种指令的延迟时隙和功能单元等待时间参见表2-18和表2-19。

表2-18 TMS320C62x的各种指令的延迟时隙和功能单元等待时间

注:†第i周期发生在E1节拍;‡跳转到标记,IRP和NRP的跳转指令不读任何寄存器;§周期i+4的写使用不同于.D单元指令的另一个写口。

表2-19 TMS320C67x的各种指令的延迟时隙和功能单元等待时间

注:†第i周期发生在E1节拍;‡周期i+4的写使用不同于.D单元指令的另一个写口。

3.并行操作

CPU运行时总是一次取8条指令,组成一个取指包。取指包的基本格式如图2-30所示。

图2-30 取指包的基本格式

取指包由256位边界定位。

取指包中的每一条指令的执行部分由每条指令的并行执行位(p)控制。P位决定本条指令与取指包中的其他指令是否并行执行。CPU对P位从左至右扫描:如果指令i的P位是1,则指令i+1就将与指令i在同一周期内并行执行;如果指令i的P位为0,则指令i+1将在i指令的下一周期内执行。所有的并行执行的指令组成一个执行包,其中最多可以包括8条指令。执行包中的每一条指令使用的功能单元要求必须各不相同。

执行包不能超过256位的边界,因此,取指包最后一条指令的P位总是设置为0,而每一取指包的开始也将是一个执行包的开始。

下面说明不同的P位设置将导致不同执行顺序。

(1)完全串行P位模式

取指包完全串行P位模式,如图2-31所示。

图2-31 完全串行P位模式

此模式下的执行顺序参见表2-20。

表2-20 取指包完全串行P位模式执行顺序

这8条指令按顺序执行。

(2)完全并行P位模式

取指包完全并行P位模式,如图2-32所示。

图2-32 完全并行P位模式

此模式下的执行顺序参见表2-21。

表2-21 取指包完全并行P位模式执行顺序

所有的8条指令并行执行。

(3)部分串行P位模式

取指包部分串行P位模式,如图2-33所示。

图2-33 部分串行P位模式

此模式的执行结果参见表2-22。

表2-22 取指包部分串行P位模式执行结果

注:指令C,D和E不能使用相同的功能单元,交叉通路或其他通路资源;同样适用于指令F,G和H。

此例指令包的指令如下:

    instruction A
    instruction B
    instruction C
||  instruction D
||  instruction E
    instruction F
||  instruction G
||  instruction H

其中||表示本指令与前一条指令之间是并行操作。

4.条件操作

TMS320C6000系列中所有的指令都是条件操作,由指令的4个最高有效位控制。其中,3位操作码字段Creg指定条件寄存器,1位字段Z指定测试是零测试还是非零的测试。在流水线的E1节拍中对指定的条件寄存器进行测试,如果Z=1,进行零测试;如果Z=0,则进行非零测试。如果Creg=0,Z=0,则允许指令无条件地执行。

Creg的字段编码在指令操作码中参见表2-23。

表2-23 Creg的字段编码

注:x为任意值,C64x也能使用A0作为条件寄存器;†该值保留作为仿真的软件断点。

在代码中使用方括号对条件操作进行描述,方括号内为条件寄存器名。下面的执行包含有两条并行的ADD指令。第一条指令在寄存器B0非零时执行,第二条ADD指令在B0为零时执行。

    [B0] ADD .L1 A1,A2,A3
||  [!B0] ADD .L2 B1,B2,B3

以上两条指令中只执行一条指令。互斥指令安排为并行执行时有一定的限制,将在下面“资源限制”中进行介绍。

5.资源限制

在同一执行包中,任何两条指令都不能使用相同资源。在同一个指令周期,也不能存在两条指令对相同的寄存器执行写操作。下面将就一条指令如何使用每个资源做详细讲述。

(1)使用相同功能单元指令的限制

使用相同功能单元的两条指令不能被安排在同一个执行包。

下面的执行包是无效的:

    ADD .S1 A0, A1, A2
||  SHR .S1 A3, 15, A4                  ;.S1 被两条指令同时使用

下面的执行包是有效的:

    ADD .L1 A0, A1, A2
||  SHR .S1 A3, 15, A4                  ;使用两个不同功能单元

(2)使用交叉通路的限制

在一个执行包中,每个数据通路的功能单元(.L,.S或.M)可以通过交叉通路访问另一侧数据通路的寄存器组。

使用同一条交叉通路的两条指令不能安排在同一个执行包中,因为从寄存器组A到组B或从寄存器组B到组A都只存在一条交叉通路。

下面的执行指令包是无效的:

    ADD.L1X A0,B1,A1
||  MPY.M1X A4,B4,A5                    ;1×同时被两条指令使用

下面的执行指令包是有效的:

    ADD.L1X A0,B1,A1
||  MPY.M2X B4,A4,B2                    ;使用了1×和2×两条通路

(3)数据读/写的限制

使用相同的寄存器组作为目的地址/源地址的两条读/写指令不能被安排在同一个执行指令包中。同时,数据读/写使用的地址寄存器必须与所使用的功能单元处于同一个数据通路。

下面执行指令包是无效的:

    LDW.D1 *A0,A1
||  LDW.D2 *A2,B2                       ;.D2必须用寄存器组B作为地址指针

下面的执行指令包是有效的:

    LDW.D1 *A0,A1
||  LDW.D2 *B0,B2                       ;寄存器所在组正确

将数据读出(或存储自)相同寄存器组的两条读(或写)指令,将数据读出到和存储自相同寄存器组的两条读和写指令不能被安排在同一个执行指令包中。

下面执行指令包是无效的:

    LDW.D1 *A4,A5
||  STW.D2 A6,*B4                       ;读出到/存储自相同寄存器组

下面执行指令包是有效的:

    LDW.D1 *A4,B5
||  STW.D2 A6,*B4                       ;读出到/存储自不同寄存器组

(4)使用长定点型(40位)数据的限制

.S和.L单元共用一套为长定点型的源操作数准备的读寄存器通路和为长定点型的结果准备的写寄存器通路,所以每一个执行包只能允许每一寄存器组处理一个长定点类型数据。

下面的执行指令包是无效的:

ADD.L1 A5:A4,A1,A3:A2
||  SHL.S1 A8,A9,A7:A6                  ;两个长数据写入同一寄存器组

下面的执行指令包是有效的:

    ADD.L1 A5:A4,A1,A3:A2
||  SHL.S2 B8,B9,B7:B6                  ;每一组一个长整型数据

因为.S和.L单元的一个长数据读通路与数据存储通路共用,所以涉及同一.S或.L单元的长数据读出和存储操作不能安排在同一个执行包中。

下面的执行指令包是无效的:

ADD .L1 A5:A4,A1,A3:A2
||  STW .D1 A8,*A9                      ;长数据读出操作与存储操作冲突

下面的执行指令包是有效的:

    ADD.L1 A4, A1, A3:A2
||  STW.D1 A8,*A9                       ;去掉长数据读出操作

(5)寄存器读取的限制

一个指令周期对同一寄存器读出操作多于4次,条件寄存器不在此限制内。

下面代码序列是无效的:

    MPY .M1 A1,A1,A4                    ;对寄存器A1五次读出操作
||  ADD .L1 A1,A1,A5
||  SUB .D1 A1,A2,A3
    MPY .M1 A1,A1,A4                    ;对寄存器A1五次读出操作
||  ADD .L1 A1,A1,A5
||  SUB .D2x A1,B2,B3

如下的代码序列是有效的:

    MPY .M1 A1,A1,A4                    ;对寄存器A1仅四次读出操作
||  [A1] ADD .L1 A0,A1,A5
||   SUB .D1 A1,A2,A3

(6)寄存器写的限制

在同一周期内两条指令不能同时写入到同一个寄存器。因此对于同一目标的两条指令可以设置为并行执行。例如,MPY指令在第i周期发生,发生在第i+1周期的ADD不能写入到同一寄存器,因为这两条指令都在第i+1周期写入结果。如下代码顺序除非在MPY指令后发生跳转才有效,ADD指令是不会发生的。

MPY .M1 A0,A1,A2
ADD .L1 A4,A5,A2

如下代码是有效的:

    MPY .M1 A0,A1,A2
||  ADD .L1 A4,A5,A2

例2.2为不同的写指令产生冲突。

【例2.2】 汇编器对写冲突的检测能力。

L1:  ADD.L2         B5,B6,B7                ;可以检测, 冲突
||   SUB.S2         B8,B9,B7
L2:  MPY.M2         B0,B1,B2                ;不能检测
L3:  ADD.L2         B3,B4,B2
L4:  [!B0]ADD.L2    B5,B6,B7                ;能检测, 无冲突
||   [B0]SUB.S2     B8,B9,B7
L5:  [!B1]ADD.L2    B5,B6,B7                ;不能检测
||   [B0]SUB.S2     8,B9,B7

在执行包L1的ADD指令和SUB指令写入相同的寄存器,该冲突很容易被检测到。L2包内的MPY指令和L3包内的ADD指令同时写到B2内,但是如果在L2执行包发生跳转指令,则不会产生冲突,因此L2和L3的潜在冲突不会被汇编器检测到。L4的指令不会构成写冲突,因为它们是互斥的。相反,因为L5的指令可以是或者不是互斥的,因此汇编器不能检测一个冲突。

6.常用指令描述

(1)ABS整型数饱和绝对值

语法:ABS (.unit)    src2,dst

.unit = .L1,.L2

描述:将src2的绝对值放入dst。

if (cond) abs(src2)→dst else nop

① 当src2是sint绝对值时,如下处理:

src2≥0,则src2→dst

src2<0且src2 ≠-231,则-src2→dst

src2 =-231,则231- 1→dst

② 当src2是slong绝对值时,如下处理:

src2≥0, 则src2→dst

src2<0且src2 ≠-239,则-src2→dst

src2 = -239,则239-1→dst

指令类型:单周期指令 延迟时隙:0\

例如:

ABS  .L1A1,A5
指令前                              指令后1个周期
A1 8000 4E3Dh(-2147463619)         8000 4E3Dh(-2147463619)
A5 XXXX XXXXh                      7FFF B1C3h(2147463619)

例如:

ABS  .L1   A1, A5
指令前                              指令后1个周期
A1 3FF6 0010h(1073086480)          3FF6 0010h(1073086480)
A5 XXXX XXXXh                      3FF6 0010h(1073086480)

(2)ADD(U)有符号/无符号整型饱和加

语法:ADD (.unit) src1, src2,dst

ADDU (.L1 or .L2) src1,src2, dst

ADD (.D1 or .D2) src2, src1, dst
.unit=.L1, .L2, .S1, .S2
      .L1, .L2 和 .S1,.S2操作数描述:src2加到src1,将结果放入dst。
if(cond)  src1+src2→dst else   nop
      .D1, .D2操作数描述:src1加到src2,将结果放入dst。
if(cond)  src2+src1→dst else   nop
    指令类型:单周期指令       延迟时隙:0
例如:ADD  .L2X   A1,B1,B2
指令前                          指令后1个周期
A1 0000 325Ah(12890)           0000 325Ah
B1 FFFF FF12h(-238)            7FFF B1C3h
B2 XXXX XXXXh                  0000 316Ch(12652)
例如:ADDU  .L1  A1,A2,A5:A4
指令前                          指令后1个周期
A1     0000 325Ah(12890†)       0000 325Ah
A2     FFFF FF12h(4294967058†)  FFFF FF12h
A5:A4  XXXX XXXXh               0000 0001h 0000 316Ch(4294979948‡)
例如:ADDU  .L1  A1, A3:A2, A5:A4
指令前                          指令后1个周期
A1 0000 325Ah(12890†)          0000 325Ah
A3:A2  0000 00FFh FFFF FF12h(1099511627538‡)0000 00FFh FFFF FF12h
A5:A4  0000 0000h 0000 0000h(0)     0000 0000h 0000 316Ch(12652‡)
注:† 32位无符号整型;
    ‡ 40位无符号(长)整型。

(3)ADDK 16位整型常量加

语法:ADDK (.unit) cst,dst
.unit=.S1 或 .S2
描述:一个16位的有符号常量加到指定的dst寄存器,结果移入dst。
if(cond) cst+dst→dst      else  nop
指令类型:单周期指令       延迟时隙:0
例如:ADDK .S1  15401,A1
指令前                          指令后1个周期
A1 0021 37E1h(2176993)          0021 740Ah(2192394)

(4)AND按位与

语法:AND (.unit) src1,src2, dst
.unit=.L1 或 .L2, .S1 或 .S2
描述:在src1和src2之间进行按位与,结果移入dst。
if(cond)   src1 and src2→dst  else  nop
指令类型:单周期指令       延迟时隙:0
例如:AND .L1X    A1,B1,A2
指令前                          指令后1个周期
A1 F7A1 302Ah                  F7A1 302Ah
A2 XXXX XXXXh                  02A0 2020h
B1 02B6 E724h                  02B6 E724h
例如:AND .L1   15,A1,A3
指令前                          指令后1个周期
A1 32E4 6936h                  32E4 6936h
A3 XXXX XXXXh                  0000 0006h

5)CLR清除一个位段

语法:CLR (.unit) src2, csta, cstb, dst

CLR (.unit) src2, src1, dst
.unit=.S1 或 .S2
描述:
① 使用常量形式。
    if(cond) src2 clear csta, cstb→dst    else  nop
② 使用寄存器形式。
    if(cond) src2 clear src19…5, src14…0→dst     else  nop
指令类型:周期指令         延迟时隙:0
例如:CLR .S1 A1,4,19,A2
指令前                          指令后1个周期
A1 07A4 3F2Ah                  07A4 3F2Ah
A2 XXXX XXXXh                  07A0 000Ah
例如:CLR .S2 B1,B3,B2
指令前                          指令后1个周期
B1 03B6 E7D5h                  03B6 E7D5h
B2 XXXX XXXXh                  03B0 0001h
B3 0000 0052h                  0000 0052h

(6)CMPEQ整型相等比较

语法:CMPEQ (.unit) src1,src2,dst
.unit=.L1 或 .L2
描述:该指令比较src1与src2。如果src1和src2相等,则在dst写入1,否则写入0。
if(cond)
{
}
else   nop

if(src1==src2)1→dst else 0→dst

例如:CMPEQ .L1X A1,B1,A2
指令前                          指令后1个周期
A1 0000 4B8h(1208)             0000 4B8h
A2 XXXX XXXXh                  0000 0000h(False)
B1 0000 4B7h(1207)             0000 4B7h
例如:CMPEQ .L1 Ch,A1,A2
指令前                          指令后1个周期
A1 0000 000Ch(12)                0000 000Ch
A2 XXXX XXXXh                    0000 0001h(True)
例如:CMPEQ  .L2X A1,B3:B2,B1
指令前                          指令后1个周期
A1 F23A 3789h                  F23A 3789h
B1 XXXX XXXXh                  0000 0001h(True)
B3:B2  0000 0FFh F23A 3789h    0000 00FFh F23A 3789h

(7)MVC在控制文件和寄存器组之间转移数据

语法:MVC (.unit) src2, dst
.unit = .S2
描述:if(cond)   src→dst    else  nop
例如:MVC .S2 B1,AMR
指令前                          指令后1个周期
B1 F009 0001h                  F009 0001h
AMR   0000 0000h               0009 0001h

(8)MVK将一个16位的符号常量移入一个寄存器并进行符号扩展

语法:MVK (.unit)   cst,dst
.unit=.S1 或 .S2
描述:该16位常量符号扩展并移入dst。
if(cond)scst16→dst    else  nop
例如:MVK .S1 293,A1
指令前                          指令后1个周期
A1 XXXX XXXXh                  0000 0125h(293)
例如:MVK .S2 125h,B1
指令前                          指令后1个周期
B1 XXXX XXXXh                  0000 0125h(293)
MVK .S1 0FF12h,A1
指令前                          指令后1个周期
A1 XXXX XXXXh                  FFFF FF12h(-238)

(9)SUB(U) 有符号/无符号整数饱和减

语法:SUB (.unit) src1, src2, dst

SUBU (.unit) src1, src2, dst

SUB (.D1 or .D2) src2, src1, dst
.unit=.L1, .L2, .S1, .S2
对于.L1, .L2 和 .S1, .S2操作数描述:
    if(cond)  src1-src2→dst   else  nop
对于.D1, .D2操作数描述:
    if(cond) src2-src1→dst    else  nop
例如:SUB .L1 A1,A2,A3
指令前                              指令后1个周期
A1 0000 325Ah(12810)               0000 325Ah
A2 FFFF FF12h(-238)                FFFF FF12h
A3 XXXX XXXXh                      0000 00FFh(13128)
例如:SUBU .L1 A1,A2,A5:A4
指令前                              指令后1个周期
A1 0000 325Ah(12810†)              0000 325Ah
A2 FFFF FF12h(4294967058‡)         FFFF FF12h
A5:A4  XXXX XXXXh XXXX XXXXh       0000 00FFh 0000 3348h(-4294954168‡)
注:†32位无符号整型;
    ‡40位有符号(long)整型。