2

我正在查看一段将编写一对 32 位寄存器的 ARM 代码,如下所示:

ldm r9!, {r0, r1}
sub r8, r8, #2
stm r10!, {r0, r1}

当 r10 输出指针是字对齐但并不总是 dword 对齐时,上面的代码是否写入一个 64 位值?我对文档的阅读使我认为在这种情况下会写入 64 位值,但我担心 8 字高速缓存行可能已经包含 7 个字然后此代码执行 64 位写入并拆分一半的情况缓存行末尾的双字。

我在想,如果 stm 改为执行 2 个 32 位字写入,那可能会避免这个问题。所以,我的问题是使用两个不相邻的寄存器会强制 stm 写 2 个单词而不是 dword 吗?

ldm r9!, {r0, r2}
sub r8, r8, #2
stm r10!, {r0, r2}

上面的代码是否与以下代码基本相同:

ldm r9!, {r0, r1}
sub r8, r8, #2
str r0, [r10], #4
str r1, [r10], #4
4

1 回答 1

2

您正在写入或读取两个的寄存器编号与 AMBA/AXI 总线事务无关。唯一的联系是数据量。

这个问题有点含糊,我对所有不同的实现都不太了解,但是如果你有一个 64 位 AXI 总线并且你的 64 位数据没有被写入一个 64 位对齐的地址(这是完全合法的,写 2例如,注册到地址 0x1004)然后它需要两个总线事务,一个用于未对齐地址(0x1004)上的第一项,另一个用于另一个(0x1008)。假设您使用的是对齐地址,那么只要其中有两个,它将执行独立于寄存器编号的单个 64 位事务。

缓存是另一个完全独立的主题。如果地址不是双字对齐的,我相信您将获得两个单独的事务,并且这些事务将由缓存单独处理。了解 L1 缓存,如果您有一个位于内核内部而不是在 AXI 总线上,则 L2 缓存(如果存在)位于内核与供应商 AXI 内存控制器之间的内核外部。所以 L1 行为和 L2 行为可能会有所不同,我不知道 L1 的核心接口是什么样的,以及它是否以及如何分解这些事务。我怀疑无论您使用什么品牌或型号的处理器,如果某些东西在内存系统或缓存逻辑中的某个点越过缓存线边界,它必须打破该事务并分别处理两个缓存线。

据我所见,stm/ldm 在必要时将单个指令转换为单独的总线事务。例如,对 0x1004 的 4 个寄存器写入会变成 3 个单独的事务,一个 32 位在 0x1004,一个 64 位在 0x1008,一个 32 位在 0x1010。自己这样做只会浪费指令获取周期,在这种情况下使用 stm 。

于 2013-07-08T14:29:32.553 回答