Fun thing I've learned about RISC-V recently:

There is no easy way of writing a 32-bit nop in RISC-V assembly.

RISC-V tries to make the C extension transparent. You don't need to write compressed variants of instructions, you just write as if you're targeting the 32-bit encoding and the assembler transparently shrinks some things for you. The C extension is entirely duplicated instructions: every 16-bit instruction in the C extension can also be written as a 32-bit instruction and this leaves it to the assembler to figure out which.

The exact same logic is applied to NOPs (which aren't really nops, they're add 0 to 0 and store the result in the zero register). There is a NOP and a C.NOP variant, but because NOP is an alias for ADDI x0, x0, 0 and C.NOP is an alias for C.ADDI x0, 0 (which is equivalent), the assembler will always emit C.NOP (a.k.a. C.ADDI x0, 0) if you write NOP. You can generate a non-canonical nop by doing something like ADDI x0, x15, 0x200, which can't be compressed (currently), but that's fragile.

This is an issue if you want to guarantee padding space in the instruction stream for later patching or linker relaxations.

As far as I am aware, RISC-V is the only variable-length architecture whose assembler makes this mistake. x86 and Thumb-2, for example, both have explicit mnemonics for longer nops. Thumb-2 has NOP and NOP.W. x86 has a baroque list of arguments you add to NOP to make it 2-15 bytes (it's one byte with no operands).

@david_chisnall Depending on the assembler, there may be something like ".option norvc" to tell it not to generate compressed instructions.

Example here, in the second code block: https://osblog.stephenmarz.com/ch1.html

They're using Rust in that project, so I guess it's whatever LLVM does.

Taking control of RISC-V: RISCV OS in Rust

@darkling

You, you can do that, it's just frustratingly verbose, especially in inline assembly.

relaxation alignment issues when both rvc and norvc code present · Issue #445 · riscv-collab/riscv-gnu-toolchain

Consider this testcase: .option rvc add a0, a0, a1 add a1, a1, a2 .balign 4 .option norvc add a0, a1, a2 call Label # rvc relaxable .balign 8 var: .dword 100 Label: Compiling for rv32 gives a linke...

GitHub