基于CEVA DSP BX2的架构分析(六)-加载和存储单元(二)

6.4 指针修改机制

LS0和LS1都包含指针修改机制。当使用间接或索引寻址模式时,指针的修改可以与地址生成并行执行。在间接寻址模式中,指针包含地址,而在变址寻址模式下,指针包含偏移量(有关这些寻址模式的更多详细信息,请参阅第6.3.1节“间接寻址模式”和第6.3.2节“索引寻址模式”)。因为指针是在地址生成后修改的,所以这种修改被称为后期修改。

以下选项可用于指针后期修改:

  • 后期增量:指针按指令中指定的访问宽度递增。访问宽度根据存储器访问操作确定,可以是一个、两个或四个。
  • 步骤修改:将其中一个步骤寄存器添加到指针。可以用作步进寄存器的GRF寄存器子集列在pm(修改后)伪操作数的汇编语法部分,如CEVA-BX2体系结构规范第II卷所述。

步骤寄存器包含一个有符号的值,该值表示字节数。与前一选项相比,步骤修改不会根据访问宽度进行缩放。

该选项在指令中通过使用加号(+)来指定,该加号的步骤寄存器名称跟在地址规范后面。

  • 偏移量修改:将宽度高达32位的有符号立即数添加到指针。立即数包含许多字节。与步长修改类似,偏移修改不根据访问宽度缩放。

该选项在指令中使用符号+#imm指定,其中#imm

表示有符号的立即数。

实施例6-7.间接寻址模式下的后增量

mov #0x100,r5.ui ; r5 is initialized with the value 0x100

nop

nop

ld (r5.ui).us+r20, r2.ui

ld指令应用间接寻址模式,并使用指针r5。访问宽度为两个字节,在r2中进行零扩展。

使用后增量选项,它由符号+r20指定。生成的内存地址为0x100,ld指令后的指针值更新为r20的值。

实施例6-8. 步骤修改

mov #0x10004,r20.i ; Step register initialization.

mov #0x200,r3.ui ; Offset initialization.

nop

nop

ld (r0.ui+r3.i).ui+r20, r2.ui

使用步进寄存器r20对偏移量r3进行后修改。ld后r3的值指令为0x10204。

r20不根据访问宽度缩放,并且r0的内容不改变。

实施例6-9. 偏移量修改

mov #0x100,r5.ui ; r5 is initialized with the value 0x100.

nop

nop

ld (r5.ui).us2+#10,r0.ui,r1.ui

指针r5按立即数#10递增。ld后r5的值指令为0x10A。

6.4.1 修改(modr说明书

modr指令在不访问数据存储器的情况下修改指针。它指定要添加到其中的指针和值,可以由LS0和LS1执行。

该值可以是四个步骤寄存器之一,也可以是有符号立即数。立即数的宽度高达32位。

例6-10. modr指令

mov #0x50,r4.ui

nop

nop

modr (r4.ui).ui+#256

指针r4使用立即数进行后期修改。后面的r4的值, 修改(modr)指令为0x150。

6.4.2 模缓冲区支持

由于地址指针在访问后进行后修改,ld和st指令的子集将地址指针限制在循环模缓冲区中。这些指令使用额外的操作数来指定模缓冲区的大小。此操作数在地址操作数之前指定,并以字节为单位保存缓冲区的大小,其中最大缓冲区大小为64K-1个字节。此操作数从GRF的子集(r22、r23、r28、r29)中选择,并应使用首选缓冲区大小M的值进行初始化。

模数运算意味着间接rN+pm_value上的后修改值保持在数据缓冲区限制内(其中pm_value.表示缩放或阶跃寄存器后修改)。当修改后的值(即rN+pm_value)超出缓冲区的边界时,可能出现以下情况:

  • 如果pm_value>0,则新值为rN+pm_value–M。
  • 如果pm_value<0,则新值为rN+pm_value+M。使用模数模式时,必须遵守以下规则:
  • M必须大于或等于步长的绝对值(pm_value)。
  • 指针应指向缓冲区内的地址。
  • 访问指针加上访问宽度不应超过缓冲区边界。

例如,如果缓冲区结束于地址0x30C,并且指针值为0x30A,则不允许发出4字节访问。

缓冲区的起始地址必须在其k个LSB中包含零,其中k是满足2k大于或等于M的最小正整数。上界是起始地址+M-1。这意味着数据空间自动划分为多个循环缓冲区,以便每个缓冲区的下边界满足前面的条件。起始地址必须仅指向模缓冲区内的位置。

注:使用步进寄存器指定pm_value时,仅使用其低16位。后修改的符号根据步进寄存器的位号16确定。

例6-11. 模数-多个环绕缓冲区

mov #0x6,r0.ui ; Loop counter initialization

mov #0x0c,r22.ui ; Initialize the modulo register with a buffer size of 12 bytes

mov #0x4,r20.i ; Initialize step register with a step of 4 that is ≤ 12

mov #0x308,r4.ui ; Initialize read pointer

mov #0x500,r6.ui ; Initialize write pointer

nop

LP_START:

 brrcmplp {ge, calc3, ds2} r0.i,#-1,#1,#LP_START

 ld r22.ui,(r4.ui).i+r20.i,r2.i

 st r2.i,(r6.ui)+#4

在此示例中,读取指针用值0x308初始化,并位于起始地址为0x300的缓冲区中(四个LSB为零)。结束地址为0x30B(缓冲区大小为12)。

由于缓冲区大小为12,因此每次读取指针被0x4(r20)后修改时,如果生成的指针大于0x30B,则读取指针将被环绕到缓冲区的起始地址。

六次迭代期间r4的值为0x308、0x300、0x304、0x308、0x300和0x304。

6.4.3 加载和存储指令谓词

LSU支持断言(predicate)机制,该机制支持所有加载和存储指令的条件执行。整数、short和char的加载和存储使用单个断言(prX.b)进行谓词,而加载和存储双短类型(s2)则使用双谓词(prX.b2)进行谓语

设置断言时,加载和存储指令根据指令访问内存。清除标量断言时,不会发生加载或存储操作。即使断言被清除,也可以在加载操作中访问内部存储器;然而,由于该指令,没有写入目标寄存器,并且没有断言访问保护评估。清除标量断言时,不会访问外部内存。

6.5 内存访问

LS0和LS1单元都支持对数据存储器的各种类型的存储器访问。以下部分描述了描述每个访问的参数。

​​​​​​​6.5.1 未对齐的内存访问

硬件完全支持未对齐的数据内存访问,没有任何核心暂停周期。支持对齐和未对齐访问而不受惩罚的能力可以具有指令较少的优势,这导致提高核心性能和减少代码大小。

​​​​​​​6.5.2 Access参数

每个访问都具有以下参数:

  • 访问类型:基本类型为8位字符(C)、16位短整型(S)和32位整型(S)。访问也可以是基本类型的倍数(例如,两个字符(C2))。
  • 内存访问宽度:从一个字符(8位)到四个短整数/两个整数(64位),最多四个整数。
  • 数据类型:这是有符号操作数或无符号操作数,在指令的语法中描述。默认情况下,内存操作数是符号扩展的。如果在指令中指定[,u]参数,则内存操作数将被视为无符号操作数,并进行零扩展。

​​​​​​​6.5.3 LSU操作

LSU可以操作加载和存储的数据类型。在加载操作中,LSU可以从内存中读取一个数据元素,更改元素类型,然后将其写入处理器寄存器。在存储操作中,LSU可以从处理器寄存器读取数据元素,更改元素类型,然后将其存储到内存中。

​​​​​​​6.5.4 标量加载和存储操作

标量加载和存储操作用于加载和存储GRF、ARF和SRF寄存器。LS0支持标量加载操作,它可以从内存中读取多达128位。LS1支持标量存储操作,它最多可以将128位写入内存。

例6-12. 标量加载操作

将立即数移动到用作基地址的地址指针:

mov #0x1000r7

使用索引寻址模式的标量调用:

ld#65+r7.ui.us2r10.uir5.ui

假设位置0x1040处的存储器内容是从存储器加载的两个8未整数,零扩展,并写入寄存器r10r5

地址

0x1047

0x1046

0x1045

0x1044

0x1043

0x1042

0x1041

0x1040

数值

0x76

0x1F

0x01

0x1B

0xCD

0x12

0x34

0x55

执行后:

r10 = 0x00001234

r5 = 0x00001BCD

 

6.6 ​​​​​​​​​​​​​​写入序列后读取

写入缓冲区增加写入事务的延迟;然而,它必须对核心读取事务透明。地址匹配机制允许暂停尚未写入内存的核心读取数据。

访问存储器的每个读取事务都会生成额外的访问,以检查所需的数据是否在写入缓冲区中。一组比较器检查所请求的地址或其一部分是在地址延迟线中,还是在等待写入存储器的写入缓冲器中。然后,读取匹配机制为读取事务的每个字节生成暂停。

​​​​​​​6.7 GetBits机制

GetBits是一种可选的硬件可配置机制,它允许从存储器阵列读取数据,并从中提取不同长度的连续位字段。单个指令最多可以读取32位。

​​​​​​​6.7.1 支持寄存器

以下寄存器支持GetBits机制,如表 6-4中所述:

  • StreamBuff:从中提取位字段的64位缓冲区。缓冲区由两个32位寄存器组成:StreamBuff1(MSP)和StreamBuff 0(LSP)。
  • 一种临时32位缓冲区(TstreamBuff),用于存储从内存加载的数据。
  • 一种模式和状态寄存器(GBCTL),其中存储当前字段指针和空状态。

表6-4.GetBits寄存器

寄存器名称

大小[位]

描述

StreamBuff0

32

流缓冲区的下部

StreamBuff1

32

流缓冲区的上部

TstreamBuff

32

从内存加载的传入数据的临时缓冲区

GBCTL

6

专用GetBits模式和状态寄存器:

Bit[31]=诱人

设置何时可以将数据加载到TstreamBuff,即Tstream Buff为空。

位[4:0]=流式处理器

保存指向StreamBuff1中的位的指针,从中可以读取下一个字段

6.7.2 getbits指令

执行GetBits指令时,GetBits机制被激活。支持的格式为:

getbits{[show][,big]}(rN.ui).ui+#4,rA.ui,rZ.ui getbits{[显示][,大]}

其中:

  • rA或immB6指定要提取的字段的宽度,以位为单位。
  • rZ指定存储提取字段的目标寄存器。
  • rN指定在需要时将位流的延续从中加载到流缓冲区的内存指针。
  • {big}确定如何处理数据:
  • 如果指定,则数据被视为Big Endian。
  • 如果不是,则将数据视为Little Endian。
  • {show}在不更新缓冲区和streampter字段的情况下提取数据

GBCTL寄存器,如第6.7.4节“显示比特流”中所述。

在使用getbits提取位之前,应按照第6.7.5节“流初始化”中的描述初始化缓冲区。

有关getbits指令的结构和操作的更多详细信息,请参阅CEVA-BX2体系结构规范第二卷。

​​​​​​​6.7.3 作业流程图

getbits指令指定要从缓冲区提取的位数,以及该字段将更新的目标字段。StreamBuff1寄存器中要从中提取字段的指针在GBCTL寄存器的streampter字段中指定。指针以StreamBuff的MSB开始(在StreamBuff1中),字段向右扩展,朝向StreamBuffef的LSB。该字段最长可达32位,并且可以从StreamBuff1寄存器扩展到StreamBuffe0寄存器。

当执行getbits指令时,提取位字段,并将流指针与要在streampter字段中更新的提取字段的长度相加。如果添加后指针超过32位,则会发生以下情况:

  1. 实际写入streampter的值环绕(即,从中减去32),以便streamptor始终指向StreamBuff1内部。
  2. StreamBuff0复制到StreamBuff 1。
  3. TstreamBuff被复制到StreamBuff0。
  4. 设置了GBCTL寄存器中的temply字段,表示TstreamBuff不包含有效数据。

如果在执行getbits指令时设置了试探指示,则对由getbits指针操作数的值指向的TstreamBuff执行32位内存加载。指针更新为4。

图 6-2 显示了getbits指令期间的功能数据流。

基于CEVA DSP BX2的架构分析(六)-加载和存储单元(二)_第1张图片

图6-2. getbits指令的高级数据流

流中的位以Little Endian或Big Endian顺序从内存中读取(根据getbits指令中的{Big}开关),使内核能够以正确的方式读取流。

例6-13.使用getbits指令读取比特流

获取位(r0.ui).ui+#4,#0xa,r3;从streamBuff寄存器读取10位。

此指令从streamBuff寄存器读取10位。r3被零扩展到32位。

假设:

  • 流缓冲=0xd4c2_981a_77ef_01ba
  • Ptr=25执行后:
  • r3=0x0000_00d3
  • Ptr=3个

如果设置了试探指示,则从存储器中r0指向的地址加载32位,并且r0更新4。

​​​​​​​6.7.4 显示位流

当在getbits指令中设置{show}开关时,位仅直接从streamBuff寄存器读取到目标操作数,并且GBCTL寄存器中的streamPtr字段不会更改。

此指令仅用于显示streamBuff的内容,而不修改它。指令读取的位数由另一个寄存器或指令中的立即数指定。并对此进行演示。

例6-14.使用getbits指令显示比特流

getbits (r0.ui).ui+#4, #0xa, r3 ; Read 10 bits from the streamBuff register.

This instruction reads 10 bits from the streamBuff register. r3 is zero-extended to 32

bits.

Assuming:

• streamBuff = 0xd4c2_981a_77ef_01ba

• streamPtr = 25

Then after execution:

• r3 = 0x0000_00d3

• streamPtr = 3

If the tempty indication is set, 32 bits are loaded from the address pointed at by r0 in

the memory, and r0 is updated by 4.

基于CEVA DSP BX2的架构分析(六)-加载和存储单元(二)_第2张图片

图6-3.使用getbits指令显示比特流

6.7.5 ​​​​​​​​​​​​​​流初始化

要初始化位流读取机制,请执行以下操作:

  1. 将流的前64位加载到streamBuff1和StreamBuff0中
  2. 寄存器(每个寄存器通过单独的指令)。
  3. 清除GBCTL寄存器中的streamPtr字段,以指示streamBuff已满。
  4. 将temply字段设置为1,以指示TstreamBuff寄存器为空。

例6-15.GetBits流初始化

r0 is assumed to point to the start of the bit stream in memory.

          ld (r0.ui).ui+#4, r5.ui

          mov r5.ui, streamBuff1.ui ; initializing streamBuff high part.

          ld (r0.ui).ui+#4, r5.ui

          mov r5.ui, streamBuff0.ui ; initializing streamBuff low part.

          mov #0x80000000, r5.ui

          mov r5.ui, gbctl           ; Clear streamptr,

                                     ;Set the TstreamBuff empty indication

你可能感兴趣的:(架构,学习,笔记)