Table of Contents

1. WRITE A RISCV ASSEMBLER

1.1. INSTRUCTION ENCODER

U-TYPE ( IMM RD OPCDOE -- INST )
J-TYPE ( IMM RD OPCODE -- INST )
I-TYPE ( IMM RS1 RD FUNCT3 OPCODE -- INST )
S-TYPE ( IMM RS2 RS1 FUNCT3 OPCODE -- INST )
B-TYPE ( IMM RS2 RS1 FUNCT3 OPCODE -- INST )
R-TYPE ( FUNCT7 RS2 RS1 FUNCT3 RD OPCODE -- INST )

1.2. INSTRUCTION

: LUI, ( IMM RD -- ) $37 U-TYPE L, ;

1.3. INSTRCUTION DECODER

DIS-U-TYPE ( INST -- IMM RD OPCDOE )
DIS-J-TYPE ( INST -- IMM RD OPCODE )
DIS-I-TYPE ( INST -- IMM RS1 RD FUNCT3 OPCODE )
DIS-S-TYPE ( INST -- IMM RS2 RS1 FUNCT3 OPCODE )
DIS-B-TYPE ( INST -- IMM RS2 RS1 FUNCT3 OPCODE )
DIS-R-TYPE ( INST -- FUNCT7 RS2 RS1 FUNCT3 RD OPCODE )

1.4. HOW TO TEST

USE INSTRUCTION ENCODER GENERATE DATA, THEN USE GNU GAS GENERATE TEST RESULT, COMPARE OUTPUT

USE INSTRUCTION ENCODER GENERATE DATA, THEN USE INSTRUCTION DECODER DEOCDE IT, COMPARE INPUT

1.5. GAS

I USE GAS TO GENERATE TEST PATTERN, BUT GAS HAVE SOME OPTIMIZE FOR BRANCH INSTRUCTION:

beq x0, x0, 0

WILL GENERATE:

f4:   00001463                bnez    zero,fc <.text+0xfc>
f8:   0000006f                j       f8 <.text+0xf8>

SO I SWITCH TO 'llvm-mc' GENERATE SINGLE BRANCH INSTRUCTION

1.6. LLVM-MC

COMMAND:

llvm-mc -triple=riscv32 -filetype=obj test.S -o a.out

GENERATE COMPRESSED INSTRUCTION, ADD INTO ASM FILE:

.option arch,rv32ic

1.7. FAR CALL

1.8. J TYPE ENCODING

11111111111111110000000000000000
FEDCBA9876543210FEDCBA9876543210
10000000000011110000000000000000
4A987654321B3210FEDC432106543210
O                   R    O
F                   D    P
F                        C
S                        O
E                        D
T                        E



1.9. CJ TYPE ENCODING

FEDCBA9876543210
210B498A67321510
F  O          O
U  F          P
N  F          C
C  S          O
T  E          D
3  T          E

1.10. CB TYPE ENCODING

FEDCBA9876543210
2108432107621510
F  O  R  O    O
U  F  S  F    P
N  F  1  F    C
C  S     S    O
T  E     E    D
3  T     T    E

Created: 2026-03-14 Sat 20:52

Validate