Search code examples
assemblyriscvinstructionsoperands

How to use C.ADDI4SPN and C.ADDI16SP instructions (compressed subset) of RISC-V architecture?


I can't figure out how to call these two instructions in a proper way. The first operand of the first instruction C.ADDI4SPN should be a register, and the second one, if I'm right, should be a number which is scaled by 4.

But when I try to call the instruction I get the message that the operands are illegal.

The same thing is with the second instruction C.ADDI16SP, the only difference is that the number should be scaled by 16. These are the descriptions of the instructions in the manual:

C.ADDI16SP adds the non-zero sign-extended 6-bit immediate to the value in the stack pointer (sp=x2), where the immediate is scaled to represent multiples of 16 in the range (-512,496).

C.ADDI4SPN is a CIW-format RV32C/RV64C-only instruction that adds a zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, and writes the result to rd0

These are the examples of how I attempt to use the instructions:

c.addi16sp 32
c.addi4spn x10, 8

Solution

  • It seems that for some reason I don't know, that we have to name the sp register when using these instructions:

    c.addi4sp, x10, sp, 8
    c.addi16sp sp, 16
    

    It is possible that this is for consistency with the uncompressed instruction expansion, where you also have to name sp.

    However, while some might count this as a feature, others (such as myself) more likely to count this as a bug or an oddity at best, because an implicit register (that you can't ever change) probably shouldn't be required in the assembly form — when explicitly using the compressed opcode.

    The base instruction set (i.e. sans compression) has no implicit registers — from the machine code perspective — all operands are specified in the machine instruction.

    Certain assembly mnemonics allow omitting the register, which is then filled in by the assembler in generating the machine code: jal and ret (pseudo instructions) for example do not allow or require the assembly program to name a register yet the machine code for these instructions has an rd/rs1 register field (respectively) filled in with x1/ra by the assembler.

    To use c.lwsp, we also specify the sp register, so it looks very much like an lw instruction.  And c.jal looks just like the jal pseudo instruction in assuming x1 as the link register — even though c.jal does hard code x1 as an implicit target register, while jal's translation does not — from the machine code perspective.

    So, I guess what they're going for is maximum compatibility with the uncompressed instructions assembly forms.  And I guess that makes the disassembly a bit more palatable, since it cannot tell whether you originally used a compressed opcode vs. the assembler compressing the instruction (though I'm not sure how worthwhile it is to show disassembly of compressed instructions using uncompressed but compressible forms).


    test.s:

    .text
    c.addi4spn a0, sp, 8  # compressed instruction, must name sp
    addi a0, sp, 8        # non-compressed instruction, gets compressed to c.addi4spn
    
    c.addi16sp sp, 16     # compressed instruction, must name sp
    addi sp, sp, 16       # non-compressed instruction, gets compressed to c.addi
    
    c.addi16sp sp, 128    # compressed instruction, must name sp
    addi sp, sp, 128      # non-compressed instruction, gets compressed to c.addi16sp
    

    Disassembly of section .text:
    
    00000000 <.text>:
       0:   0028                    addi    a0,sp,8    # c.addi4spn
       2:   0028                    addi    a0,sp,8    # c.addi4spn
       4:   6141                    addi    sp,sp,16   # c.addi16sp
       6:   0141                    addi    sp,sp,16   # c.addi
       8:   6109                    addi    sp,sp,128  # c.addi16sp
       a:   6109                    addi    sp,sp,128  # c.addi16sp
    

    As you can see the disassembler assumes you used (or want to see) non-compressed instruction syntax even though the assembler may or may not have converted these to their compressed equivalents.