ARM Cortex M 中的 ISB 指令

ISB instruction in ARM Cortex M

到目前为止,我使用了 3 个 NOP 来 "clean" 管道。 最近我遇到了为我做那件事的 ISB 指令。 查看arm信息中心我注意到这个命令需要4个周期(在Cortex M0下)而3个NOP只需要3个。

为什么要使用这个命令?它与 3 个 NOP 有什么不同?

您应该使用 ISB 指令来确保流水线畅通。正如上面的评论所述,不同 ARM 处理器之间的流水线可能不同(例如,M7 有 6 级流水线,而 M3/4 有 3 级流水线)。根据M4技术参考手册"For ISB, the minimum number of cycles is equivalent to the number required for a pipeline refill.".

为什么这是 4 个周期而不是 3 个我不确定,这可能与确保分支预测逻辑正确有关。无论您是否希望您的代码可移植,我都建议使用 ARM 为这项工作提供的功能,如果他们认为您需要 4 个周期,那么我希望您这样做。如果你只有 3.

,在某些情况下你可能会得到错误的操作。

这是 NOP (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/CHDJJGFB.html) 的问题:

Operation

NOP performs no operation and is not guaranteed to be time consuming. The processor might remove it from the pipeline before it reaches the execution stage.

Use NOP for padding, for example to place the subsequent instructions on a 64-bit boundary.

其他 ARM Cortex 设备的文档中有相同的信息,因此将该指令用于填充以外的 任何 目的根本不可靠。您唯一能保证的是这条指令将占用 2 (nop) 或 4 个字节 (nop.w),并且它不会执行任何操作 - 仅此而已。

3个NOP并不保证消耗3个周期。在某些情况下,他们会在 Cortex-M3 上消耗 2 个周期 - 在这些情况下,您可能需要使用 3 个以上的 NOP 才能获得所需的效果。

'interesting' 场景很可能不会出现在通用代码中,或者还需要其他事件的特定时间 - 因此您可能不太可能观察到它们。关键是没有保证,而且这种故障的可观察性通常很低。

即使您在某处错误地只使用了 2 个 NOP,您的代码也可能在大部分时间都有效 - 直到其他地方的更改可能对对齐产生影响并暴露出故障。

ISB指令是4个周期的原因很简单。 Cortex-M 指令集是 16 位和 32 位指令的混合体。 Cortex-M 设计(例如 Cortex-M0)支持 6 种 32 位指令:BL、MSR、MRS、ISB、DMB、DSB。

所有这6条指令都可以在16位指令中混合使用。

问题是处理器如何知道哪条指令是 16 位的,哪条指令是 32 位的?为了回答这个问题,处理器读取前 16 位并将其解码(1 个周期)。如果操作码与 32 位指令匹配,那么它知道下一条 16 位指令实际上是 32 位指令的后半部分并尝试执行它(3 个周期)。

这使得 Cortex-M 内核中的所有 32 位指令为 1+3 个周期 = 4 个周期。

如果您确定核心实现,您可以使用 3 个 NOP 来刷新管道。您必须确保核心没有分支预测和动态指令优化,它会删除连续的 NOP。如果您确定没有此功能,则使用 3 个 NOP 指令,您将节省 1 个周期。但是如果你不使用并且你还希望你的 ARM 代码可以移植到其他体系结构,如 ARMv7 等。那么你必须使用 ISB 指令,这是一个 32 位指令,需要 4 个周期。