vst1.8和vst1.32有区别吗?

0xc*_*aff 1 assembly arm neon

在ARM Neon ISA中,这两条指令有区别吗?

vst1.32 {d12, d13, d14, d15}, [r4]
Run Code Online (Sandbox Code Playgroud)

vst1.8 {d12, d13, d14, d15}, [r4]
Run Code Online (Sandbox Code Playgroud)

基于文档中的伪代码

case type of
    when '0111'
        regs = 1;  if align<1> == '1' then UNDEFINED;
    when '1010'
        regs = 2;  if align == '11' then UNDEFINED;
    when '0110'
        regs = 3;  if align<1> == '1' then UNDEFINED;
    when '0010'
        regs = 4;
    otherwise
        SEE "Related encodings";
alignment = if align == '00' then 1 else 4 << UInt(align);
ebytes = 1 << UInt(size);  esize = 8 * ebytes;  elements = 8 DIV ebytes;
d = UInt(D:Vd);  n = UInt(Rn);  m = UInt(Rm);
wback = (m != 15);  register_index = (m != 15 && m != 13);
if n == 15 || d+regs > 32 then UNPREDICTABLE;


if ConditionPassed() then
    EncodingSpecificOperations();  CheckAdvSIMDEnabled();  NullCheckIfThumbEE(n);
    address = R[n];  if (address MOD alignment) != 0 then GenerateAlignmentException();
    if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
    for r = 0 to regs-1
        for e = 0 to elements-1
            if ebytes != 8 then 
                MemU[address,ebytes] = Elem[D[d+r],e,esize]; 
            else 
                data =Elem[D[d+r],e,esize]; 
                MemU[address,4] = if BigEndian() then data<63:32> else data<31:0>;
                MemU[address+4,4] = if BigEndian() then data<31:0> else data<63:32>;
            address = address + ebytes;

Run Code Online (Sandbox Code Playgroud)

其中size是一个两位值,似乎无论指定什么大小,D 寄存器的整个值(64 位,8 字节)都会被复制到内存中。看起来无论指定的大小如何,vst1.32 和 vst1.8、vst1.16 都是等效的。

如果是这种情况,则大小参数将存储至少一位额外的信息(因为需要知道对于字节顺序特殊情况是否为 ebytes == 8)。我希望 ARM ISA 不会定义额外信息的存储,因此我的推理中一定存在缺陷,或者我的假设之一是错误的。

Pet*_*ell 5

这两条指令在常见情况下(小端、对齐地址)实际上表现相同,但它们在两个方面有所不同:

对齐方式——由于两者都没有指定对齐方式,因此您得到了 Arm ARM 所称的“标准对齐方式”。这意味着“应与元素大小对齐,但仅当 SCTLR.A 为 1 时才会出错”。如果设置了 SCTLR.A 并且地址不是 4 对齐,vst1.32 将出现故障,但 vst1.8 不会。

字节顺序——如果设置了 CPSR.E,则存储的每个元素都将进行字节交换。这意味着,对于 vst1.8,没有字节被交换(它是一个字节数组),但对于 vst1.32,每个 4 字节元素的字节都被交换。

对这两件事的处理都隐藏在MemU[] 的伪代码中,这就是为什么仅查看指令的伪代码并不能立即明显看出。