Loading Data Into a Register on RISC-V

I was recently chatting with an old friend and the subject of RISC-V came up.

"Oh heck, that thing?" he said, "I heard it takes 6 instructions just to load a register."

Now this seemed like an odd thing to say. I've seen plenty of RISC-V assembly and certainly didn't see anyone using 6 instructions just to load a register. But with a bit of digging, however, I think I understand what he meant.

But let's back up a bit. If you're reading this, I'm going to assume you've got a passing familiarity with assembly language and how assemblers convert assembly language statements into op-codes and how those opcodes are interpreted by an ARM, x86 or RISC-V CPU. I'm also going to assume you know what RISC-V is and that the specs specify a CPU with 32 registers that are either 32 or 64 bits wide. (Bonus points if you know the hidden secret about register x0.)

After thinking about my friends statement, I started thinking about the many different ways you can load data into a register. Relatively quickly I figured out he was talking about the "Load Immediate" instruction. This is an assembly language instruction that loads an arbitrary 32 or 64 bit value into a register. If you pick up a copy of the RISC-V specs or the RISC-V Reader, you'll find the Load Immediate (LI) instruction well documented.

But even a cursory examination of the documentation reveals that "LI" is a Pseudo-Instruction. That is, it's a valid assembly language instruction that's converted into a sequence of