RISC-V 명령어에는 4가지 포맷이 있다.
R-Type
Register-type이라는 의미로 3개의 레지스터 operand를 사용한다.
이외에 연산코드를 담는 op 필드와 opcode에 부연설명을 하는 funct7, funct3 필드가 있다.

예) add, sub, sll, xor 등
I-Type
Immediate-type이라는 의미로 2개의 레지스터와 immediate를 operand로 사용한다.
이외에 op 필드와 funct3 필드가 있다.

예) addi, lw, lh 등
S/B-Type
Store-type, Branch-type으로 사용하는 operand와 op, funct 필드는 동일하나 immediate 인코딩 방식에 차이가 있다.

S-type에서는 rs1과 imm의 12-bit tw's complement immediate를 이용해 메모리 주소를 계산한다.
예) sw 등
B-type의 imm 필드에는 12-bit two's complement immediate가 들어가는데 이것이 주소 offset 역할을 한다.
예) beq 등
엄밀히 따지자면 B-type에서 offset으로 사용하는 immediate는 13-bit이다. 그러나, RISC-V의 jump는 짝수 주소로만 갈 수 있다. 즉, lsb가 0으로 고정된다.
따라서 포맷에는 12bit만 들어가 있다.
U/J-Type
Upper-immediate-type과 Jump-type으로 이 둘도 사용하는 포맷이 rd, imm 2개의 operand와 op 필드로 동일하나 imm 인코딩 방식에 차이가 있다.

U-type은 lui 같은 명령어에서 사용하는 타입이다. imm 필드에는 32-bit immediate 중 상위 20bit를 저장한다.
예) lui 등
J-type은 jump and link 명령에서 사용하는 타입이다. J-type도 아까 살펴봤던 B-type과 동일하게 lsb가 0으로 고정되는 점을 이용해서 엄밀히 따지면 21bit지만 마지막 0을 제외하고 20bit만 imm 필드에 저장한다.
예) jal 등
요약

하지만 설계 원칙 4번에 따라 유연함을 허용한다.
명령어를 기계어로 인코딩하는 포맷에서 signed immediate를 사용한다. immedate의 msb를 사용하면 여러모로 편리한 점이 많기 때문에 imm 필드를 instruction bit의 msb 쪽에 놓게 되었다.

먼저 op코드를 보고 머신 코드를 어떻게 파싱할지 결정한다.
이후 위에서 배운 대로 해석한다.
주소를 처리하는 방식은 다음과 같다.
<참고자료>
Harris & Harris, Digital Design and Computer Architecture, RISC-V Edition, 2022.