valheim_asm/asm/
encode32.rs

1use crate::isa::data::Fin;
2use crate::isa::rv32::RV32Instr;
3use crate::isa::rv64::RV64Instr;
4use crate::isa::typed::{AQ, Instr, Rd, Reg, RL, RoundingMode, Rs1, Rs2, Rs3};
5use crate::isa::typed::Reg::{F, FCSR, PC, X, ZERO};
6
7pub trait Encode32 {
8  fn encode32(self) -> u32;
9}
10
11impl Encode32 for Instr {
12  fn encode32(self) -> u32 {
13    match self {
14      Instr::RV32(i) => i.encode32(),
15      Instr::RV64(i) => i.encode32(),
16      Instr::NOP => panic!("No nop instruction in 32-bit length encoding"),
17    }
18  }
19}
20
21impl Encode32 for RV32Instr {
22  fn encode32(self) -> u32 {
23    match self {
24      // RVI
25      RV32Instr::LUI(rd, imm) => emit_u(0b0110111, rd, imm.decode()),
26      RV32Instr::AUIPC(rd, imm) => emit_u(0b0010111, rd, imm.decode()),
27      RV32Instr::JAL(rd, imm) => emit_j(0b1101111, rd, imm.decode_sext()),
28      RV32Instr::JALR(rd, rs1, imm) => emit_i(0b1100111, 0b000, rd, rs1, imm.decode_sext()),
29      RV32Instr::BEQ(rs1, rs2, imm) => emit_b(0b1100011, 0b000, rs1, rs2, imm.decode_sext()),
30      RV32Instr::BNE(rs1, rs2, imm) => emit_b(0b1100011, 0b001, rs1, rs2, imm.decode_sext()),
31      RV32Instr::BLT(rs1, rs2, imm) => emit_b(0b1100011, 0b100, rs1, rs2, imm.decode_sext()),
32      RV32Instr::BGE(rs1, rs2, imm) => emit_b(0b1100011, 0b101, rs1, rs2, imm.decode_sext()),
33      RV32Instr::BLTU(rs1, rs2, imm) => emit_b(0b1100011, 0b110, rs1, rs2, imm.decode_sext()),
34      RV32Instr::BGEU(rs1, rs2, imm) => emit_b(0b1100011, 0b111, rs1, rs2, imm.decode_sext()),
35      RV32Instr::LB(rd, rs1, imm) => emit_i(0b0000011, 0b000, rd, rs1, imm.decode_sext()),
36      RV32Instr::LH(rd, rs1, imm) => emit_i(0b0000011, 0b001, rd, rs1, imm.decode_sext()),
37      RV32Instr::LW(rd, rs1, imm) => emit_i(0b0000011, 0b010, rd, rs1, imm.decode_sext()),
38      RV32Instr::LBU(rd, rs1, imm) => emit_i(0b0000011, 0b100, rd, rs1, imm.decode_sext()),
39      RV32Instr::LHU(rd, rs1, imm) => emit_i(0b0000011, 0b101, rd, rs1, imm.decode_sext()),
40      RV32Instr::SB(rs1, rs2, imm) => emit_s(0b0100011, 0b000, rs1, rs2, imm.decode_sext()),
41      RV32Instr::SH(rs1, rs2, imm) => emit_s(0b0100011, 0b001, rs1, rs2, imm.decode_sext()),
42      RV32Instr::SW(rs1, rs2, imm) => emit_s(0b0100011, 0b010, rs1, rs2, imm.decode_sext()),
43      RV32Instr::ADDI(rd, rs1, imm) => emit_i(0b0010011, 0b000, rd, rs1, imm.decode_sext()),
44      RV32Instr::SLTI(rd, rs1, imm) => emit_i(0b0010011, 0b010, rd, rs1, imm.decode_sext()),
45      RV32Instr::SLTIU(rd, rs1, imm) => emit_i(0b0010011, 0b011, rd, rs1, imm.decode_sext()),
46      RV32Instr::XORI(rd, rs1, imm) => emit_i(0b0010011, 0b100, rd, rs1, imm.decode_sext()),
47      RV32Instr::ORI(rd, rs1, imm) => emit_i(0b0010011, 0b110, rd, rs1, imm.decode_sext()),
48      RV32Instr::ANDI(rd, rs1, imm) => emit_i(0b0010011, 0b111, rd, rs1, imm.decode_sext()),
49      RV32Instr::SLLI(rd, rs1, shamt5) => emit_r(0b0010011, 0b0000000, 0b001, rd, rs1, Rs2(X(Fin::new(shamt5.0 as u32)))),
50      RV32Instr::SRLI(rd, rs1, shamt5) => emit_r(0b0010011, 0b0000000, 0b101, rd, rs1, Rs2(X(Fin::new(shamt5.0 as u32)))),
51      RV32Instr::SRAI(rd, rs1, shamt5) => emit_r(0b0010011, 0b0100000, 0b101, rd, rs1, Rs2(X(Fin::new(shamt5.0 as u32)))),
52      RV32Instr::ADD(rd, rs1, rs2) => emit_r(0b0110011, 0b0000000, 0b000, rd, rs1, rs2),
53      RV32Instr::SUB(rd, rs1, rs2) => emit_r(0b0110011, 0b0100000, 0b000, rd, rs1, rs2),
54      RV32Instr::SLL(rd, rs1, rs2) => emit_r(0b0110011, 0b0000000, 0b001, rd, rs1, rs2),
55      RV32Instr::SLT(rd, rs1, rs2) => emit_r(0b0110011, 0b0000000, 0b010, rd, rs1, rs2),
56      RV32Instr::SLTU(rd, rs1, rs2) => emit_r(0b0110011, 0b0000000, 0b011, rd, rs1, rs2),
57      RV32Instr::XOR(rd, rs1, rs2) => emit_r(0b0110011, 0b0000000, 0b100, rd, rs1, rs2),
58      RV32Instr::SRL(rd, rs1, rs2) => emit_r(0b0110011, 0b0000000, 0b101, rd, rs1, rs2),
59      RV32Instr::SRA(rd, rs1, rs2) => emit_r(0b0110011, 0b0100000, 0b101, rd, rs1, rs2),
60      RV32Instr::OR(rd, rs1, rs2) => emit_r(0b0110011, 0b0000000, 0b110, rd, rs1, rs2),
61      RV32Instr::AND(rd, rs1, rs2) => emit_r(0b0110011, 0b0000000, 0b111, rd, rs1, rs2),
62      RV32Instr::FENCE(rd, rs1, succ, pred, fm) => {
63        // 31:28 = fm, 27:24 = pred, 23:20 = succ, 19:15 = rs1, 14:12 = 0b000, 11:7 = rd, 6:0 = opcode
64        0b0001111
65          | ((rd.encode32() & 0b11111) << 7)
66          | ((rs1.encode32() & 0b11111) << 15)
67          | ((succ.0 & 0b1111) << 20)
68          | ((pred.0 & 0b1111) << 24)
69          | ((fm.0 & 0b1111) << 28)
70      }
71      RV32Instr::FENCE_TSO => 0b1000_0011_0011_00000_000_00000_0001111,
72      RV32Instr::PAUSE => 0b0000_0001_0000_00000_000_00000_0001111,
73      RV32Instr::ECALL => 0b000000000000_00000_000_00000_1110011,
74      RV32Instr::EBREAK => 0b000000000001_00000_000_00000_1110011,
75      // RVM
76      RV32Instr::MUL(rd, rs1, rs2) => emit_r(0b0110011, 0b0000001, 0b000, rd, rs1, rs2),
77      RV32Instr::MULH(rd, rs1, rs2) => emit_r(0b0110011, 0b0000001, 0b001, rd, rs1, rs2),
78      RV32Instr::MULHSU(rd, rs1, rs2) => emit_r(0b0110011, 0b0000001, 0b010, rd, rs1, rs2),
79      RV32Instr::MULHU(rd, rs1, rs2) => emit_r(0b0110011, 0b0000001, 0b011, rd, rs1, rs2),
80      RV32Instr::DIV(rd, rs1, rs2) => emit_r(0b0110011, 0b0000001, 0b100, rd, rs1, rs2),
81      RV32Instr::DIVU(rd, rs1, rs2) => emit_r(0b0110011, 0b0000001, 0b101, rd, rs1, rs2),
82      RV32Instr::REM(rd, rs1, rs2) => emit_r(0b0110011, 0b0000001, 0b110, rd, rs1, rs2),
83      RV32Instr::REMU(rd, rs1, rs2) => emit_r(0b0110011, 0b0000001, 0b111, rd, rs1, rs2),
84      // RVA
85      RV32Instr::LR_W(rd, rs1, aq, rl) => emit_r_amo(0b0101111, 0b00010, 0b010, aq, rl, rd, rs1, Rs2(ZERO)),
86      RV32Instr::SC_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b00011, 0b010, aq, rl, rd, rs1, rs2),
87      RV32Instr::AMOSWAP_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b00001, 0b010, aq, rl, rd, rs1, rs2),
88      RV32Instr::AMOADD_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b00000, 0b010, aq, rl, rd, rs1, rs2),
89      RV32Instr::AMOXOR_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b00100, 0b010, aq, rl, rd, rs1, rs2),
90      RV32Instr::AMOAND_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b01100, 0b010, aq, rl, rd, rs1, rs2),
91      RV32Instr::AMOOR_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b01000, 0b010, aq, rl, rd, rs1, rs2),
92      RV32Instr::AMOMIN_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b10000, 0b010, aq, rl, rd, rs1, rs2),
93      RV32Instr::AMOMAX_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b10100, 0b010, aq, rl, rd, rs1, rs2),
94      RV32Instr::AMOMINU_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b11000, 0b010, aq, rl, rd, rs1, rs2),
95      RV32Instr::AMOMAXU_W(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b11100, 0b010, aq, rl, rd, rs1, rs2),
96      // RVF
97      RV32Instr::FLW(rd, rs1, imm) => emit_i(0b0000111, 0b010, rd, rs1, imm.decode_sext()),
98      RV32Instr::FSW(rs1, rs2, imm) => emit_s(0b0100111, 0b010, rs1, rs2, imm.decode_sext()),
99      RV32Instr::FMADD_S(rd, rs1, rs2, rs3, rm) => emit_r4(0b1000011, 0b00, rm.encode32(), rd, rs1, rs2, rs3),
100      RV32Instr::FMSUB_S(rd, rs1, rs2, rs3, rm) => emit_r4(0b1000111, 0b00, rm.encode32(), rd, rs1, rs2, rs3),
101      RV32Instr::FNMSUB_S(rd, rs1, rs2, rs3, rm) => emit_r4(0b1001011, 0b00, rm.encode32(), rd, rs1, rs2, rs3),
102      RV32Instr::FNMADD_S(rd, rs1, rs2, rs3, rm) => emit_r4(0b1001111, 0b00, rm.encode32(), rd, rs1, rs2, rs3),
103      RV32Instr::FADD_S(rd, rs1, rs2, rm) => emit_r(0b1010011, 0b0000000, rm.encode32(), rd, rs1, rs2),
104      RV32Instr::FSUB_S(rd, rs1, rs2, rm) => emit_r(0b1010011, 0b0000100, rm.encode32(), rd, rs1, rs2),
105      RV32Instr::FMUL_S(rd, rs1, rs2, rm) => emit_r(0b1010011, 0b0001000, rm.encode32(), rd, rs1, rs2),
106      RV32Instr::FDIV_S(rd, rs1, rs2, rm) => emit_r(0b1010011, 0b0001100, rm.encode32(), rd, rs1, rs2),
107      RV32Instr::FSQRT_S(rd, rs1, rm) => emit_r(0b1010011, 0b0101100, rm.encode32(), rd, rs1, Rs2(ZERO)),
108      RV32Instr::FSGNJ_S(rd, rs1, rs2) => emit_r(0b1010011, 0b0010000, 0b000, rd, rs1, rs2),
109      RV32Instr::FSGNJN_S(rd, rs1, rs2) => emit_r(0b1010011, 0b0010000, 0b001, rd, rs1, rs2),
110      RV32Instr::FSGNJX_S(rd, rs1, rs2) => emit_r(0b1010011, 0b0010000, 0b010, rd, rs1, rs2),
111      RV32Instr::FMIN_S(rd, rs1, rs2) => emit_r(0b1010011, 0b0010100, 0b000, rd, rs1, rs2),
112      RV32Instr::FMAX_S(rd, rs1, rs2) => emit_r(0b1010011, 0b0010100, 0b001, rd, rs1, rs2),
113      RV32Instr::FCVT_W_S(rd, rs1, rm) => emit_r(0b1010011, 0b1100000, rm.encode32(), rd, rs1, Rs2(ZERO)),
114      RV32Instr::FCVT_WU_S(rd, rs1, rm) => emit_r(0b1010011, 0b1100000, rm.encode32(), rd, rs1, Rs2(X(Fin::new(1)))),
115      RV32Instr::FMV_X_W(rd, rs1) => emit_r(0b1010011, 0b1110000, 0b000, rd, rs1, Rs2(ZERO)),
116      RV32Instr::FEQ_S(rd, rs1, rs2) => emit_r(0b1010011, 0b1010000, 0b010, rd, rs1, rs2),
117      RV32Instr::FLT_S(rd, rs1, rs2) => emit_r(0b1010011, 0b1010000, 0b001, rd, rs1, rs2),
118      RV32Instr::FLE_S(rd, rs1, rs2) => emit_r(0b1010011, 0b1010000, 0b000, rd, rs1, rs2),
119      RV32Instr::FCLASS_S(rd, rs1) => emit_r(0b1010011, 0b1110000, 0b001, rd, rs1, Rs2(ZERO)),
120      RV32Instr::FCVT_S_W(rd, rs1, rm) => emit_r(0b1010011, 0b1101000, rm.encode32(), rd, rs1, Rs2(ZERO)),
121      RV32Instr::FCVT_S_WU(rd, rs1, rm) => emit_r(0b1010011, 0b1101000, rm.encode32(), rd, rs1, Rs2(X(Fin::new(1)))),
122      RV32Instr::FMV_W_X(rd, rs1) => emit_r(0b1010011, 0b1111000, 0b000, rd, rs1, Rs2(ZERO)),
123      // FVD
124      RV32Instr::FLD(rd, rs1, imm) => emit_i(0b0000111, 0b011, rd, rs1, imm.decode_sext()),
125      RV32Instr::FSD(rs1, rs2, imm) => emit_s(0b0100111, 0b011, rs1, rs2, imm.decode_sext()),
126      RV32Instr::FMADD_D(rd, rs1, r2, rs3, rm) => emit_r4(0b1000011, 0b01, rm.encode32(), rd, rs1, r2, rs3),
127      RV32Instr::FMSUB_D(rd, rs1, r2, rs3, rm) => emit_r4(0b1000111, 0b01, rm.encode32(), rd, rs1, r2, rs3),
128      RV32Instr::FNMSUB_D(rd, rs1, r2, rs3, rm) => emit_r4(0b1001011, 0b01, rm.encode32(), rd, rs1, r2, rs3),
129      RV32Instr::FNMADD_D(rd, rs1, r2, rs3, rm) => emit_r4(0b1001111, 0b01, rm.encode32(), rd, rs1, r2, rs3),
130      RV32Instr::FADD_D(rd, rs1, rs2, rm) => emit_r(0b1010011, 0b0000001, rm.encode32(), rd, rs1, rs2),
131      RV32Instr::FSUB_D(rd, rs1, rs2, rm) => emit_r(0b1010011, 0b0000101, rm.encode32(), rd, rs1, rs2),
132      RV32Instr::FMUL_D(rd, rs1, rs2, rm) => emit_r(0b1010011, 0b0001001, rm.encode32(), rd, rs1, rs2),
133      RV32Instr::FDIV_D(rd, rs1, rs2, rm) => emit_r(0b1010011, 0b0001101, rm.encode32(), rd, rs1, rs2),
134      RV32Instr::FSQRT_D(rd, rs1, rm) => emit_r(0b1010011, 0b0101101, rm.encode32(), rd, rs1, Rs2(ZERO)),
135      RV32Instr::FSGNJ_D(rd, rs1, rs2) => emit_r(0b1010011, 0b0010001, 0b000, rd, rs1, rs2),
136      RV32Instr::FSGNJN_D(rd, rs1, rs2) => emit_r(0b1010011, 0b0010001, 0b001, rd, rs1, rs2),
137      RV32Instr::FSGNJX_D(rd, rs1, rs2) => emit_r(0b1010011, 0b0010001, 0b010, rd, rs1, rs2),
138      RV32Instr::FMIN_D(rd, rs1, rs2) => emit_r(0b1010011, 0b0010101, 0b000, rd, rs1, rs2),
139      RV32Instr::FMAX_D(rd, rs1, rs2) => emit_r(0b1010011, 0b0010101, 0b001, rd, rs1, rs2),
140      RV32Instr::FCVT_S_D(rd, rs1, rm) => emit_r(0b1010011, 0b0100000, rm.encode32(), rd, rs1, Rs2(X(Fin::new(1)))),
141      RV32Instr::FCVT_D_S(rd, rs1, rm) => emit_r(0b1010011, 0b0100001, rm.encode32(), rd, rs1, Rs2(ZERO)),
142      RV32Instr::FEQ_D(rd, rs1, rs2) => emit_r(0b1010011, 0b1010001, 0b010, rd, rs1, rs2),
143      RV32Instr::FLT_D(rd, rs1, rs2) => emit_r(0b1010011, 0b1010001, 0b001, rd, rs1, rs2),
144      RV32Instr::FLE_D(rd, rs1, rs2) => emit_r(0b1010011, 0b1010001, 0b000, rd, rs1, rs2),
145      RV32Instr::FCLASS_D(rd, rs1) => emit_r(0b1010011, 0b1110001, 0b001, rd, rs1, Rs2(ZERO)),
146      RV32Instr::FCVT_W_D(rd, rs1, rm) => emit_r(0b1010011, 0b1100001, rm.encode32(), rd, rs1, Rs2(ZERO)),
147      RV32Instr::FCVT_WU_D(rd, rs1, rm) => emit_r(0b1010011, 0b1100001, rm.encode32(), rd, rs1, Rs2(X(Fin::new(1)))),
148      RV32Instr::FCVT_D_W(rd, rs1, rm) => emit_r(0b1010011, 0b1101001, rm.encode32(), rd, rs1, Rs2(ZERO)),
149      RV32Instr::FCVT_D_WU(rd, rs1, rm) => emit_r(0b1010011, 0b1101001, rm.encode32(), rd, rs1, Rs2(X(Fin::new(1)))),
150    }
151  }
152}
153
154impl Encode32 for RV64Instr {
155  fn encode32(self) -> u32 {
156    match self {
157      // RV64I
158      RV64Instr::LWU(rd, rs1, imm) => emit_i(0b0000011, 0b110, rd, rs1, imm.decode_sext()),
159      RV64Instr::LD(rd, rs1, imm) => emit_i(0b0000011, 0b011, rd, rs1, imm.decode_sext()),
160      RV64Instr::SD(rs1, rs2, imm) => emit_s(0b0100011, 0b011, rs1, rs2, imm.decode_sext()),
161      RV64Instr::SLLI(rd, rs1, shamt6) => emit_r_shamt6(0b0010011, 0b000000, 0b001, rd, rs1, shamt6.0 as u32),
162      RV64Instr::SRLI(rd, rs1, shamt6) => emit_r_shamt6(0b0010011, 0b000000, 0b101, rd, rs1, shamt6.0 as u32),
163      RV64Instr::SRAI(rd, rs1, shamt6) => emit_r_shamt6(0b0010011, 0b010000, 0b101, rd, rs1, shamt6.0 as u32),
164      RV64Instr::ADDIW(rd, rs1, imm) => emit_i(0b0011011, 0b000, rd, rs1, imm.decode_sext()),
165      RV64Instr::SLLIW(rd, rs1, shamt5) => emit_r(0b0011011, 0b0000000, 0b001, rd, rs1, Rs2(X(Fin::new(shamt5.0 as u32)))),
166      RV64Instr::SRLIW(rd, rs1, shamt5) => emit_r(0b0011011, 0b0000000, 0b101, rd, rs1, Rs2(X(Fin::new(shamt5.0 as u32)))),
167      RV64Instr::SRAIW(rd, rs1, shamt5) => emit_r(0b0011011, 0b0100000, 0b101, rd, rs1, Rs2(X(Fin::new(shamt5.0 as u32)))),
168      RV64Instr::ADDW(rd, rs1, rs2) => emit_r(0b0111011, 0b0000000, 0b000, rd, rs1, rs2),
169      RV64Instr::SUBW(rd, rs1, rs2) => emit_r(0b0111011, 0b0100000, 0b000, rd, rs1, rs2),
170      RV64Instr::SLLW(rd, rs1, rs2) => emit_r(0b0111011, 0b0000000, 0b001, rd, rs1, rs2),
171      RV64Instr::SRLW(rd, rs1, rs2) => emit_r(0b0111011, 0b0000000, 0b101, rd, rs1, rs2),
172      RV64Instr::SRAW(rd, rs1, rs2) => emit_r(0b0111011, 0b0100000, 0b101, rd, rs1, rs2),
173      // RV64M
174      RV64Instr::MULW(rd, rs1, rs2) => emit_r(0b0111011, 0b0000001, 0b000, rd, rs1, rs2),
175      RV64Instr::DIVW(rd, rs1, rs2) => emit_r(0b0111011, 0b0000001, 0b100, rd, rs1, rs2),
176      RV64Instr::DIVUW(rd, rs1, rs2) => emit_r(0b0111011, 0b0000001, 0b101, rd, rs1, rs2),
177      RV64Instr::REMW(rd, rs1, rs2) => emit_r(0b0111011, 0b0000001, 0b110, rd, rs1, rs2),
178      RV64Instr::REMUW(rd, rs1, rs2) => emit_r(0b0111011, 0b0000001, 0b111, rd, rs1, rs2),
179      // RV64A
180      RV64Instr::LR_D(rd, rs1, aq, rl) => emit_r_amo(0b0101111, 0b00010, 0b011, aq, rl, rd, rs1, Rs2(ZERO)),
181      RV64Instr::SC_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b00011, 0b011, aq, rl, rd, rs1, rs2),
182      RV64Instr::AMOSWAP_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b00001, 0b011, aq, rl, rd, rs1, rs2),
183      RV64Instr::AMOADD_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b00000, 0b011, aq, rl, rd, rs1, rs2),
184      RV64Instr::AMOXOR_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b00100, 0b011, aq, rl, rd, rs1, rs2),
185      RV64Instr::AMOAND_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b01100, 0b011, aq, rl, rd, rs1, rs2),
186      RV64Instr::AMOOR_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b01000, 0b011, aq, rl, rd, rs1, rs2),
187      RV64Instr::AMOMIN_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b10000, 0b011, aq, rl, rd, rs1, rs2),
188      RV64Instr::AMOMAX_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b10100, 0b011, aq, rl, rd, rs1, rs2),
189      RV64Instr::AMOMINU_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b11000, 0b011, aq, rl, rd, rs1, rs2),
190      RV64Instr::AMOMAXU_D(rd, rs1, rs2, aq, rl) => emit_r_amo(0b0101111, 0b11100, 0b011, aq, rl, rd, rs1, rs2),
191      // RV64F
192      RV64Instr::FCVT_L_S(rd, rs1, rm) => emit_r(0b1010011, 0b1100000, rm.encode32(), rd, rs1, Rs2(X(Fin::new(0b00010)))),
193      RV64Instr::FCVT_LU_S(rd, rs1, rm) => emit_r(0b1010011, 0b1100000, rm.encode32(), rd, rs1, Rs2(X(Fin::new(0b00011)))),
194      RV64Instr::FCVT_S_L(rd, rs1, rm) => emit_r(0b1010011, 0b1101000, rm.encode32(), rd, rs1, Rs2(X(Fin::new(0b00010)))),
195      RV64Instr::FCVT_S_LU(rd, rs1, rm) => emit_r(0b1010011, 0b1101000, rm.encode32(), rd, rs1, Rs2(X(Fin::new(0b00011)))),
196      // RV64D
197      RV64Instr::FCVT_L_D(rd, rs1, rm) => emit_r(0b1010011, 0b1100001, rm.encode32(), rd, rs1, Rs2(X(Fin::new(0b00010)))),
198      RV64Instr::FCVT_LU_D(rd, rs1, rm) => emit_r(0b1010011, 0b1100001, rm.encode32(), rd, rs1, Rs2(X(Fin::new(0b00011)))),
199      RV64Instr::FMV_X_D(rd, rs1) => emit_r(0b1010011, 0b1111001, 0b000, rd, rs1, Rs2(ZERO)),
200      RV64Instr::FCVT_D_L(rd, rs1, rm) => emit_r(0b1010011, 0b1101001, rm.encode32(), rd, rs1, Rs2(X(Fin::new(0b00010)))),
201      RV64Instr::FCVT_D_LU(rd, rs1, rm) => emit_r(0b1010011, 0b1101001, rm.encode32(), rd, rs1, Rs2(X(Fin::new(0b00011)))),
202      RV64Instr::FMV_D_X(rd, rs1) => emit_r(0b1010011, 0b1111001, 0b000, rd, rs1, Rs2(ZERO)),
203      // RV32/RV64 Zicsr
204      RV64Instr::CSRRW(rd, rs1, csr) => emit_i(0b1110011, 0b001, rd, rs1, csr.value() as i32),
205      RV64Instr::CSRRS(rd, rs1, csr) => emit_i(0b1110011, 0b010, rd, rs1, csr.value() as i32),
206      RV64Instr::CSRRC(rd, rs1, csr) => emit_i(0b1110011, 0b011, rd, rs1, csr.value() as i32),
207      RV64Instr::CSRRWI(rd, uimm, csr) => emit_i(0b1110011, 0b101, rd, Rs1(X(Fin::new(uimm.value()))), csr.value() as i32),
208      RV64Instr::CSRRSI(rd, uimm, csr) => emit_i(0b1110011, 0b110, rd, Rs1(X(Fin::new(uimm.value()))), csr.value() as i32),
209      RV64Instr::CSRRCI(rd, uimm, csr) => emit_i(0b1110011, 0b111, rd, Rs1(X(Fin::new(uimm.value()))), csr.value() as i32),
210      // RV32/RV64 Zifencei
211      RV64Instr::FENCE_I(rd, rs1, imm) => emit_i(0b0001111, 0b001, rd, rs1, imm.decode_sext()),
212      // RV32/64 Privileged
213      RV64Instr::SRET => 0b0001000_00010_00000_000_00000_1110011,
214      RV64Instr::MRET => 0b0011000_00010_00000_000_00000_1110011,
215      RV64Instr::WFI => 0b0001000_00010_00000_000_00000_1110011,
216      RV64Instr::SFENCE_VMA(rs1, rs2) => emit_r(0b1110011, 0b0001001, 0b000, Rd(ZERO), rs1, rs2),
217      RV64Instr::SINVAL_VMA(rs1, rs2) => emit_r(0b1110011, 0b0001011, 0b000, Rd(ZERO), rs1, rs2),
218      RV64Instr::SFENCE_W_INVAL =>  0b0001100_00000_00000_000_00000_1110011,
219      RV64Instr::SFENCE_INVAL_IR => 0b0001100_00001_00000_000_00000_1110011,
220    }
221  }
222}
223
224impl Encode32 for Reg {
225  fn encode32(self) -> u32 {
226    match self {
227      ZERO => 0,
228      X(x) => x.value(),
229      F(f) => f.value(),
230      PC => panic!("No direct pc access in RISC-V instruction encoding"),
231      FCSR => panic!("No direct fcsr access in RISC-V instruction encoding"),
232    }
233  }
234}
235
236impl Encode32 for Rd {
237  fn encode32(self) -> u32 {
238    self.0.encode32()
239  }
240}
241
242impl Encode32 for Rs1 {
243  fn encode32(self) -> u32 {
244    self.0.encode32()
245  }
246}
247
248impl Encode32 for Rs2 {
249  fn encode32(self) -> u32 {
250    self.0.encode32()
251  }
252}
253
254impl Encode32 for Rs3 {
255  fn encode32(self) -> u32 {
256    self.0.encode32()
257  }
258}
259
260impl Encode32 for RoundingMode {
261  fn encode32(self) -> u32 {
262    match self {
263      RoundingMode::RNE => 0b000,
264      RoundingMode::RTZ => 0b001,
265      RoundingMode::RDN => 0b010,
266      RoundingMode::RUP => 0b011,
267      RoundingMode::RMM => 0b100,
268      RoundingMode::DYN => 0b111,
269    }
270  }
271}
272
273// Copilot wrote these `emit_*`, thank you for saving my life!
274
275/// Convert RISC-V R-type instruction to u32
276fn emit_r(opcode: u32, funct7: u32, funct3: u32, rd: Rd, rs1: Rs1, rs2: Rs2) -> u32 {
277  // 31:25 = funct7, 24:20 = rs2, 19:15 = rs1, 14:12 = funct3, 11:7 = rd, 6:0 = opcode
278  (opcode & 0b1111111)
279    | ((rd.encode32() & 0b11111) << 7)
280    | ((funct3 & 0b111) << 12)
281    | ((rs1.encode32() & 0b11111) << 15)
282    | ((rs2.encode32() & 0b11111) << 20)
283    | ((funct7 & 0b1111111) << 25)
284}
285
286/// Convert RISC-V R-type (shamt 6, used by RV64I: SLLI, SRLI, SRAI) to u32
287fn emit_r_shamt6(opcode: u32, funct6: u32, funct3: u32, rd: Rd, rs1: Rs1, shamt6: u32) -> u32 {
288  // 31:26 = funct6, 25:20 = shamt6, 19:15 = rs1, 14:12 = funct3, 11:7 = rd, 6:0 = opcode
289  (opcode & 0b1111111)
290    | ((rd.encode32() & 0b11111) << 7)
291    | ((funct3 & 0b111) << 12)
292    | ((rs1.encode32() & 0b11111) << 15)
293    | ((shamt6 & 0b111111) << 20)
294    | ((funct6 & 0b111111) << 26)
295}
296
297/// Convert RISC-V R-type (aq, rl, used by RVA) instruction to u32
298fn emit_r_amo(opcode: u32, funct5: u32, funct3: u32, aq: AQ, rl: RL, rd: Rd, rs1: Rs1, rs2: Rs2) -> u32 {
299  // 31:27 = funct7, 26 = aq, 25 = rl, 24:20 = rs2, 19:15 = rs1, 14:12 = funct3, 11:7 = rd, 6:0 = opcode
300  (opcode & 0b1111111)
301    | ((rd.encode32() & 0b11111) << 7)
302    | ((funct3 & 0b111) << 12)
303    | ((rs1.encode32() & 0b11111) << 15)
304    | ((rs2.encode32() & 0b11111) << 20)
305    | ((rl.0 as u32) << 25)
306    | ((aq.0 as u32) << 26)
307    | ((funct5 & 0b1111111) << 27)
308}
309
310/// Convert RISC-V I-type instruction to u32
311fn emit_i(opcode: u32, funct3: u32, rd: Rd, rs1: Rs1, imm: i32) -> u32 {
312  // 31:20 = imm, 19:15 = rs1, 14:12 = funct3, 11:7 = rd, 6:0 = opcode
313  (opcode & 0b1111111)
314    | ((rd.encode32() & 0b11111) << 7)
315    | ((funct3 & 0b111) << 12)
316    | ((rs1.encode32() & 0b11111) << 15)
317    | ((imm as u32 & 0b111111111111) << 20)
318}
319
320/// Convert RISC-V S-type instruction to u32
321fn emit_s(opcode: u32, funct3: u32, rs1: Rs1, rs2: Rs2, imm: i32) -> u32 {
322  // 31:25 = imm[11:5], 24:20 = rs2, 19:15 = rs1, 14:12 = funct3, 11:7 = imm[4:0], 6:0 = opcode
323  (opcode & 0b1111111)
324    | ((imm as u32 & 0b11111) << 7)
325    | ((funct3 & 0b111) << 12)
326    | ((rs1.encode32() & 0b11111) << 15)
327    | ((rs2.encode32() & 0b11111) << 20)
328    | ((imm as u32 & 0b111111100000) << 20)
329}
330
331/// Convert RISC-V R4-type instruction to u32
332fn emit_r4(opcode: u32, funct2: u32, funct3: u32, rd: Rd, rs1: Rs1, rs2: Rs2, rs3: Rs3) -> u32 {
333  // 31:27 = rs3, 26:25 = funct2, 24:20 = rs2, 19:15 = rs1, 14:12 = funct3, 11:7 = rd, 6:0 = opcode
334  (opcode & 0b1111111)
335    | ((rd.encode32() & 0b11111) << 7)
336    | ((funct3 & 0b111) << 12)
337    | ((rs1.encode32() & 0b11111) << 15)
338    | ((rs2.encode32() & 0b11111) << 20)
339    | ((funct2 & 0b11) << 25)
340    | ((rs3.encode32() & 0b11111) << 27)
341}
342
343/// Convert RISC-V U-type instruction to u32
344fn emit_u(opcode: u32, rd: Rd, imm: u32) -> u32 {
345  // 31:12 = imm, 11:7 = rd, 6:0 = opcode
346  (opcode & 0b1111111)
347    | ((rd.encode32() & 0b11111) << 7)
348    | ((imm as u32 & 0b11111111111111111111) << 12)
349}
350
351/// Convert RISC-V B-type instruction to u32
352fn emit_b(opcode: u32, funct3: u32, rs1: Rs1, rs2: Rs2, imm: i32) -> u32 {
353  // 31:31 = imm[12], 30:25 = imm[10:5], 24:20 = rs2, 19:15 = rs1, 14:12 = funct3, 11:8 = imm[4:1], 7:7 = imm[11], 6:0 = opcode
354  (opcode & 0b1111111)
355    | ((imm as u32 & 0b1) << 7)
356    | ((imm as u32 & 0b11110) << 7)
357    | ((funct3 & 0b111) << 12)
358    | ((rs1.encode32() & 0b11111) << 15)
359    | ((rs2.encode32() & 0b11111) << 20)
360    | ((imm as u32 & 0b11111100000) << 20)
361    | ((imm as u32 & 0b100000000000) << 19)
362    | ((imm as u32 & 0b111111000000000000000) << 12)
363}
364
365/// Convert RISC-V J-type instruction to u32
366fn emit_j(opcode: u32, rd: Rd, imm: i32) -> u32 {
367  // 31:31 = imm[20], 30:21 = imm[10:1], 20:20 = imm[11], 19:12 = imm[19:12], 11:7 = rd, 6:0 = opcode
368  (opcode & 0b1111111)
369    | ((rd.encode32() & 0b11111) << 7)
370    | ((imm as u32 & 0b11111111) << 12)
371    | ((imm as u32 & 0b111111110000000000000) << 12)
372    | ((imm as u32 & 0b100000000000000000000) << 11)
373    | ((imm as u32 & 0b1000000000000000000000) << 9)
374    | ((imm as u32 & 0b11111100000000000000000000000000) >> 11)
375}
376
377#[cfg(test)]
378mod tests {
379  use crate::asm::encode32::Encode32;
380  use crate::isa::data::Fin;
381  use crate::isa::rv32::RV32Instr;
382  use crate::isa::typed::{Instr, Rd, RoundingMode, Rs1, Rs2, Rs3};
383  use crate::isa::typed::Reg::{F, X};
384
385  #[test]
386  pub fn xlb_step2() {
387    let x = vec![
388      (RV32Instr::FADD_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2))), RoundingMode::DYN), "FADD_D"),
389      (RV32Instr::FSUB_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2))), RoundingMode::DYN), "FSUB_D"),
390      (RV32Instr::FMUL_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2))), RoundingMode::DYN), "FMUL_D"),
391      (RV32Instr::FDIV_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2))), RoundingMode::DYN), "FDIV_D"),
392      (RV32Instr::FSGNJ_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FSGNJ_D"),
393      (RV32Instr::FSGNJN_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FSGNJN_D"),
394      (RV32Instr::FSGNJX_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FSGNJX_D"),
395      (RV32Instr::FSGNJX_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FSGNJX_D"),
396      (RV32Instr::FMIN_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FMIN_D"),
397      (RV32Instr::FMIN_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FMIN_D"),
398      (RV32Instr::FMIN_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FMIN_D"),
399      (RV32Instr::FMAX_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FMAX_D"),
400      (RV32Instr::FMAX_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FMAX_D"),
401      (RV32Instr::FMAX_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FMAX_D"),
402      (RV32Instr::FEQ_D(Rd(X(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FEQ_D"),
403      (RV32Instr::FEQ_D(Rd(X(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FEQ_D"),
404      (RV32Instr::FEQ_D(Rd(X(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FEQ_D"),
405      (RV32Instr::FEQ_D(Rd(X(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FEQ_D"),
406      (RV32Instr::FLT_D(Rd(X(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FLT_D"),
407      (RV32Instr::FLT_D(Rd(X(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FLT_D"),
408      (RV32Instr::FLE_D(Rd(X(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FLE_D"),
409      (RV32Instr::FLE_D(Rd(X(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2)))), "FLE_D"),
410      (RV32Instr::FMADD_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2))), Rs3(F(Fin::new(8))), RoundingMode::DYN), "FMADD_D"),
411      (RV32Instr::FMSUB_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2))), Rs3(F(Fin::new(8))), RoundingMode::DYN), "FMSUB_D"),
412      (RV32Instr::FNMSUB_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2))), Rs3(F(Fin::new(8))), RoundingMode::DYN), "FNMSUB_D"),
413      (RV32Instr::FNMADD_D(Rd(F(Fin::new(4))), Rs1(F(Fin::new(3))), Rs2(F(Fin::new(2))), Rs3(F(Fin::new(8))), RoundingMode::DYN), "FNMADD_D"),
414    ];
415
416    for (i, _) in x {
417      let asm = i.encode32();
418      let ii = Instr::decode32(asm).unwrap();
419      assert_eq!(Instr::RV32(i), ii);
420    }
421  }
422}