9

I am working on RISC-V 32I instructions recently. I got a question about NOP instruction, which the specification says it is equal to ADDI x0, x0, 0.

However, x0 is not a general register which can be modified by the programmer. Thus, why x0 serves as a destination register here for the NOP instruction?

Can anyone please shed some lights on this point?

JFMR
  • 23,265
  • 4
  • 52
  • 76
Betty
  • 161
  • 1
  • 2
  • 6
  • 4
    x0 is a read-only register, that means every write to it is ignored. – fsasm Jun 13 '18 at 12:46
  • 2
    just like MIPS or many other RISC architectures, writes to the zero register are discarded: [How does a zero register improve performance?](https://stackoverflow.com/q/24646101/995714), [Is Zero Register 'zr' in aarch64 essentially ground?](https://stackoverflow.com/q/52410521/995714), [Why the %r0 of SPARC or MIPS, is always 0?](https://stackoverflow.com/q/19130790/995714) – phuclv Aug 03 '19 at 10:23

3 Answers3

6

NOP is a pseudoinstruction that expands to ADDI x0, x0, 0. The x0 (or zero) is a read-only register dedicated to the value zero, i.e., it is hardwired to zero for every single bit. Whatever is written to this register is simply discarded since its value can't be modified.

From The RISC-V Instruction Set Manual Volume I: Unprivileged ISA:

The NOP instruction does not change any architecturally visible state, except for advancing the pc and incrementing any applicable performance counters. NOP is encoded as ADDI x0, x0, 0.

Keeping in mind that RISC-V has no arithmetic flags (i.e., carry, overflow, zero, sign flags), any arithmetic operation whose destination register is x0 will do as a no operation instruction regardless of the source registers since the net result will consist of advancing the program counter to the next instruction without changing any other relevant processor's state.

JFMR
  • 23,265
  • 4
  • 52
  • 76
3

oystercatcher quotes a correct statement, x0 holds the constant 0 and cannot be written to another value.

The instruction ADDI x0, x0, 0 performs x0 <- x0 + 0, where 0 is an immediate encoded in the instruction. Such instruction has no effect on the state of RISCV and therefore is a NOP.

Other alternative for a NOP on RISCV : ADDI x0, x1, 0 . Even ADD x0, x1, x2 will have no effect on RISCV (there is no Carry flag on RISCV) and therefore behaves like a NOP.

Pierre G.
  • 4,346
  • 1
  • 12
  • 25
  • 4
    Using `x1` as the source would introduce a false dependency that would stop the `nop` from executing until after the last instruction that wrote `x1`, if it wasn't special-cased by the hardware as a true `nop`. Architecturally it's still of course a NOP but microarchitecturally it can be worse on a superscalar (and/or out-of-order) core. – Peter Cordes Nov 30 '19 at 09:49
2

https://github.com/riscv/riscv-asm-manual/blob/master/riscv-asm.md

or on page109 of https://riscv.org/specifications/

register x0 hard wired to zero