; 1. lea MemoryAddress(pc), a0
auipc a0, [upper 20 bits of (MemoryAddress - label)]
addi a0, a0, [lower 12 bits of (MemoryAddress - label)]
label:
; 2. move.l #$00bfe001, a1
lui a1, 0x00bfe000
addi a1, a1, 0x001
; 3. rts
jalr x0, x1, 0
It is cumbersome in that sense. But it will probably be handled by an assembler (as a macro or builtin). The spec contains an appendix of "pseudoinstructions", which gives the first translation above. There isn't even a dedicated "move" instruction—it's just "addi dst, src, 0" by convention! Clearly anyone writing assembly will use at least that pseudoinstruction.If there's a canonical format for "pseudoinstructions", and all assemblers handle them in the same way, and the abstraction doesn't leak in any way (i.e. the only temporary registers you use are ones you overwrite fully by the end; it is true that now some "instructions" have longer encodings, but that comes with the compressed instructions anyway; and it is true that an interrupt could happen between the two halves of the "instruction", but I think that shouldn't make a difference), then I don't think there's much of a problem.
Any RISC processor has that issue, because encoding is fixed at 32-bits to keep the hardware simple. That's not what I'm referring to.
Look at that retardation, "auipc". Because "auipc" is intuitive, right? (For the record, I'm being sarcastic.) What the hell was the instruction designer smoking? Then there is the square bracket notation, like on intel, and intel has some of the most idiotic, non-conventional assembler syntax -- and this thing mimics something so bad? Every other processor uses parenthesis, that's a well understood norm.
Then there is more intel retardation in the form of dst, src (or dst, src, src on RISC). What kind of a warped, twisted mind came up with that? What was going on in that person's head to work in such twisted ways?
Then there's the "cherry on top":
jalr x0, x1, 0 ; because "jalr" is intuitive as well, it immediately tells you what it does?
You'll know a bad processor design by its instruction set. Always and forever.Bad names are harder to work around. However, about those names: "auipc" is certainly letter salad, but (a) it stands for "Add Upper Immediate to Program Counter", and its effect is to add an immediate value (multiplied by 2^12) to the program counter and put the result in a register, so the name is entirely logical given its task; and (b) except in the rare case where the PC-relative offset is exactly a multiple of 2^12, an AUIPC will be immediately followed by an add (to load a full PC-relative address), or perhaps a load-with-offset (to load a value at a full PC-relative address), or a jump-with-offset (to jump to a label at a full PC-relative address); and all three of these AUIPC+(add|load|jump) combinations are given as pseudoinstructions as well (e.g. "la" for "load address"), so the programmer will probably never need to write a bare "auipc". As for "jalr", well, it stands for "jump and link register", which jumps to the "register" argument and stores the return address in the "link" argument. There's a set of pseudo-instructions based off x0 being the "always-zero" register and x1 being the conventional "return address" register:
Pseudo Real Description
j offset jal x0, offset Jump
jal offset jal x1, offset Jump and link
jr rs jalr x0, rs, 0 Jump register
jalr rs jalr x1, rs, 0 Jump and link register
ret jalr x0, x1, 0 Return from subroutine
Seems logical enough to me. You can just use "jal offset" and "ret" if you prefer.Anyway, if your goal was to convince me there are serious flaws in RISC-V, then criticizing the naming conventions and surface syntax has led me away from the hypothesis that you know any.
The assembler reads almost like a high level programming language. The register scheme is intuitive as well, from a0-a7 being the address, to d0-d7 being the data registers.
Now, let's do a mental exercise: I'm going to load an effective address relative to the program counter, 32-bits wide, into the 1st address register. Then, I'm going to load an arbitrary value from an arbitrary memory location into the second address register. Do the same in RISC-V; compare intuitiveness.