【问题标题】:Are PUSH/POP instructions considered RISC or CISC?PUSH/POP 指令被认为是 RISC 还是 CISC?
【发布时间】:2017-04-23 04:41:07
【问题描述】:

我在一次采访中被问到 PUSHPOP 是 RISC 还是 CISC 指令。我说它们是 RISC,但他们告诉我它们实际上是 CISC 指令。我建议 ARM(一种常见的 RISC 实现)有这些指令,但他们指出 ARM 是混合的,不再是纯粹的 RISC。

我在网上找不到任何明确的证据。 PUSHPOP 指令真的被认为是 CISC 架构的标志,还是会在 RISC 系统上找到它们?为什么?

【问题讨论】:

  • 我做过,他们说 Arm 是混合的,它不再是纯粹的 RISC
  • ARM 一直支持使用单个指令执行 push 或 pop,但不支持专门的 PUSH/POP 指令。它是通过自动后递增和预递减寻址模式完成的。
  • 在 x86/x86-64 上,push 和 pop 进行了高度优化。如此优化以至于他们对连续推送的堆栈指针的依赖性进行了特殊处理 - 第二次推送不会等到第一次推送更新堆栈指针。推送只是存储到(通常)预先递减的堆栈指针寄存器。具有某种寻址模式的商店具体是 CISC 还是 RISC?这是有争议的。
  • @doug65536:对“堆栈引擎”的更清晰解释,它通过跟踪与无序核心中存在的 RSP 值的偏移量来提高推送/弹出效率:stackoverflow.com/questions/36631576/… .幸运的是,由于专利共享协议,AMD 和英特尔都有非常相似的堆栈引擎。
  • @Jonas 这个问题与特定架构无关,risc 标签实际上确实适用。 (您可能会争辩说它与堆栈溢出无关,因为它是关于 CPU 架构分类法(即关于命名的哲学辩论),而不是编程......)也就是说,不要从它确实适用的问题中删除它,直到/ 除非它的销毁已在 meta 上达成一致。

标签: assembly cpu-architecture instruction-set risc


【解决方案1】:

“RISC”对不同的人有不同的含义。我见过的定义包括:

  • 指令数量减少

  • 固定大小的说明(可能很多)

  • 加载/存储架构(可能包含大量可变大小的指令)

  • 不将指令转换为微操作且没有“微代码”的 CPU(例如 8086、8088、80186...,但没有 80486、Pentium...)

  • 以上两项或多项的任意组合

  • 为了降低开发成本而牺牲性能的任何事情

PUSH/POP 指令被认为是 RISC 还是 CISC?

是(PUSH/POP 指令被认为是 RISC 或 CISC,或两者兼有,或两者都不是;取决于何时应用 RISC 或 CISC 的定义)。

问题本身大多是错误的二分法;比如问“灰色是黑色还是白色?”。

【讨论】:

  • 我认为 RISC 最重要的方面是最大的复杂性 单个指令:它们可以由单个(流水线)执行单元完成,例如 FP 乘法或整数加法,但不能像 x86 的 rep movsb 或 ARM 的 push {r0, r1, r4, lr} (带有其中 regs 的位图)推动,几乎不可能在恒定时间内运行。ARM 不像 RISCy,这是标准 RISC 纯度的例外之一;related。)
  • 我已经看到这被称为 Reduced Insn Set Complexity,它是首字母缩写词 IMO 的更有用的扩展。这意味着它是一个加载存储 ISA,并且绝对没有任何内存-destination RMW 指令,因为这意味着多个不同的执行单元。
  • @PeterCordes:说实话;我认为“RISC”是基于一个简单的 CPU 可以在更高的频率下运行并完成与复杂 CPU 相同的工作量(在较低频率下)的想法;并且(在 1990 年代末)每个人都发现提高时钟频率是一场巨大的灾难,并开始“创造性地重新定义”“RISC”的含义,以挽救十年来的营销炒作;导致“RISC”CPU 比原来的 CISC 复杂得多(因为“提高并行度”取代了“提高时钟频率”作为提高性能的一种手段)。
  • 是的,这是公平的,早期的 RISC 哲学确实经常倾向于保持硬件更简单,即使这会损害每时钟性能。我想我的定义归结为“管道很好,尤其是超标量/OoO”,或者因为早期 RISC 机器实现 RISC 的方式具有允许高时钟(甚至在电源墙之前的管道宽度,例如 R10k)的好处。这并不是什么大问题:标量有序流水线中的“流水线良好”的东西仍然很好,包括用于轻松获取/解码的固定宽度指令,然后现在允许高效的并行解码。
  • 只有在更精细的细节中,哲学才真正发生了转变。那时候,是的,保持硬件简单,这样它就可以时钟频率更高,而不是仍然流水线足够好,以在流水线中用更少的操作完成更多的工作。例如Andy Glew 评论说在一条指令的 uops 中缺乏对 TLB 一致性的硬件支持使内存目标adc 花费额外的 uops:他说 我在加入 P6 时是 RISC 支持者,我的态度是“让 SW (微码)做它”。作为评论线程(quoted here)的一部分,关于后悔那个选择。
【解决方案2】:

RISC 表示“精简指令集”(通常是 LOAD reg、STORE 寄存器、ADD 寄存器、CMP 寄存器、条件分支 + 其他一些)。

这个概念和经验是,复杂指令通常无法实现更简单的指令序列无法实现的有用效果,特别是如果将用于实现此类复杂指令的额外逻辑投入到使简单的指令序列中RISC 指令运行速度更快。

PUSH 和 POP 基本上是 STORE/LOAD 间接的简单组合,并在寄存器中添加一个常量。因此,如果一个专用寄存器用于堆栈指针,则很容易模拟 PUSH 和 POP,并且快速流水线机器执行 PUSH 和 POP 的速度可能与相应的 RISC 指令一样快。所以大多数人认为 PUSH 和 POP 是 CISC 指令;他们并没有真正给你买很多东西。

如果您考虑 CALL (== PUSH PC + JMP) 和 RET (POP PC),生活会变得更加有趣。这些也很容易在正确的 RISC 架构上进行模拟。但是,POP PC 会引发管道泡沫,因为处理器很难预测新 PC 的位置,因此无法进行预取。由于内存“在时间上很遥远”,这可能是具有大量子例程调用的代码的主要性能抑制因素。

在这里,有点想去 CISC。您真正想要的是某种方式来预测返回 PC。许多现代 CPU 通过在硬件中保留“影子调用堆栈”来做到这一点。每个 CALL 将 PC 推入内存堆栈,同时也推入影子堆栈;每个 RET 从内存堆栈中弹出一个 PC 值,但使用影子堆栈的顶部条目预测指令流流,它本质上是零时间访问(当然,弹出影子堆栈)。这样指令流就不会中断,因此 CISC 机器会在性能上获胜。

(有人想知道,如果一台具有大量寄存器的 RISC 机器,编译后的叶函数调用总是使用一个寄存器来存储返回的 PC,可能不如影子堆栈有效。Sun Sparc 用它的寄存器来做这件事窗口)。

这告诉我们,RISC 与 CISC 过度简化了设计权衡。你想要的很简单,除非更多的复杂性实际上给你带来了一些东西。例如,硬件中的 IEEE 浮点比使用 RISC 指令的任何模拟都快很多

因此,大多数现代机器都不是 RISC 或 CISC。性能分析选择。

【讨论】:

  • ARM 是这些权衡的一个很好的例子。主要是 RISC(加载/存储机器),但在代码大小值得时偏离 RISC 教条:带有寄存器位域的推送/弹出指令。 (在 ARM 模式下,不是 thumb,store-multiple / load-multiple 可以使用任何寄存器作为基数。)还有一些不太简单的寻址模式。例如,ARM 的 RISCy 比 MIPS 低很多。
猜你喜欢
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 2021-01-28
  • 2014-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多