1use ckb_vm_definitions::instructions as insts;
5
6use super::utils::{self, funct3, funct7, opcode, rd, rs1, rs2};
7use super::{set_instruction_length_4, Instruction, Itype, Register, Rtype};
8
9pub fn factory<R: Register>(instruction_bits: u32, _: u32) -> Option<Instruction> {
10 let bit_length = R::BITS;
11 if bit_length != 32 && bit_length != 64 {
12 return None;
13 }
14 let rv64 = bit_length == 64;
15 let inst = match opcode(instruction_bits) {
16 0b_0111011 => {
17 let funct3_value = funct3(instruction_bits);
18 let funct7_value = funct7(instruction_bits);
19 let inst_opt = match (funct3_value, funct7_value) {
20 (0b_000, 0b_0000100) => Some(insts::OP_ADDUW),
21 (0b_001, 0b_0110000) => Some(insts::OP_ROLW),
22 (0b_010, 0b_0010000) => Some(insts::OP_SH1ADDUW),
23 (0b_100, 0b_0000100) => {
24 if rv64 && rs2(instruction_bits) == 0 {
25 Some(insts::OP_ZEXTH)
26 } else {
27 None
28 }
29 }
30 (0b_100, 0b_0010000) => Some(insts::OP_SH2ADDUW),
31 (0b_101, 0b_0110000) => Some(insts::OP_RORW),
32 (0b_110, 0b_0010000) => Some(insts::OP_SH3ADDUW),
33 _ => None,
34 };
35 inst_opt.map(|inst| {
36 Rtype::new(
37 inst,
38 rd(instruction_bits),
39 rs1(instruction_bits),
40 rs2(instruction_bits),
41 )
42 .0
43 })
44 }
45 0b_0110011 => {
46 let funct3_value = funct3(instruction_bits);
47 let funct7_value = funct7(instruction_bits);
48 let inst_opt = match (funct3_value, funct7_value) {
49 (0b_111, 0b_0100000) => Some(insts::OP_ANDN),
50 (0b_110, 0b_0100000) => Some(insts::OP_ORN),
51 (0b_100, 0b_0100000) => Some(insts::OP_XNOR),
52 (0b_001, 0b_0110000) => Some(insts::OP_ROL),
53 (0b_101, 0b_0110000) => Some(insts::OP_ROR),
54 (0b_001, 0b_0110100) => Some(insts::OP_BINV),
55 (0b_001, 0b_0010100) => Some(insts::OP_BSET),
56 (0b_001, 0b_0100100) => Some(insts::OP_BCLR),
57 (0b_101, 0b_0100100) => Some(insts::OP_BEXT),
58 (0b_010, 0b_0010000) => Some(insts::OP_SH1ADD),
59 (0b_100, 0b_0010000) => Some(insts::OP_SH2ADD),
60 (0b_110, 0b_0010000) => Some(insts::OP_SH3ADD),
61 (0b_001, 0b_0000101) => Some(insts::OP_CLMUL),
62 (0b_011, 0b_0000101) => Some(insts::OP_CLMULH),
63 (0b_010, 0b_0000101) => Some(insts::OP_CLMULR),
64 (0b_100, 0b_0000101) => Some(insts::OP_MIN),
65 (0b_101, 0b_0000101) => Some(insts::OP_MINU),
66 (0b_110, 0b_0000101) => Some(insts::OP_MAX),
67 (0b_111, 0b_0000101) => Some(insts::OP_MAXU),
68 _ => None,
69 };
70 inst_opt.map(|inst| {
71 Rtype::new(
72 inst,
73 rd(instruction_bits),
74 rs1(instruction_bits),
75 rs2(instruction_bits),
76 )
77 .0
78 })
79 }
80 0b_0010011 => {
81 let funct3_value = funct3(instruction_bits);
82 let funct7_value = funct7(instruction_bits);
83 let rs2_value = rs2(instruction_bits);
84 let inst_opt = match (funct7_value, funct3_value, rs2_value) {
85 (0b_0010100, 0b_101, 0b_00111) => Some(insts::OP_ORCB),
86 (0b_0110101, 0b_101, 0b_11000) => Some(insts::OP_REV8),
87 (0b_0110000, 0b_001, 0b_00000) => Some(insts::OP_CLZ),
88 (0b_0110000, 0b_001, 0b_00010) => Some(insts::OP_CPOP),
89 (0b_0110000, 0b_001, 0b_00001) => Some(insts::OP_CTZ),
90 (0b_0110000, 0b_001, 0b_00100) => Some(insts::OP_SEXTB),
91 (0b_0110000, 0b_001, 0b_00101) => Some(insts::OP_SEXTH),
92 _ => None,
93 };
94 if let Some(inst) = inst_opt {
95 Some(
96 Rtype::new(
97 inst,
98 rd(instruction_bits),
99 rs1(instruction_bits),
100 rs2(instruction_bits),
101 )
102 .0,
103 )
104 } else {
105 let inst_opt = match (funct7_value >> 1, funct3_value) {
106 (0b_010010, 0b_001) => Some(insts::OP_BCLRI),
107 (0b_010010, 0b_101) => Some(insts::OP_BEXTI),
108 (0b_011010, 0b_001) => Some(insts::OP_BINVI),
109 (0b_001010, 0b_001) => Some(insts::OP_BSETI),
110 (0b_011000, 0b_101) => Some(insts::OP_RORI),
111 _ => None,
112 };
113 inst_opt.map(|inst| {
114 Itype::new_u(
115 inst,
116 rd(instruction_bits),
117 rs1(instruction_bits),
118 utils::x(instruction_bits, 20, 6, 0),
119 )
120 .0
121 })
122 }
123 }
124 0b_0011011 => {
125 let funct3_value = funct3(instruction_bits);
126 let funct7_value = funct7(instruction_bits);
127 let rs2_value = rs2(instruction_bits);
128
129 match funct7_value {
130 0b_0110000 => match funct3_value {
131 0b_001 => {
132 let inst_opt = match rs2_value {
133 0b_00000 => Some(insts::OP_CLZW),
134 0b_00010 => Some(insts::OP_CPOPW),
135 0b_00001 => Some(insts::OP_CTZW),
136 _ => None,
137 };
138 inst_opt.map(|inst| {
139 Rtype::new(inst, rd(instruction_bits), rs1(instruction_bits), rs2_value)
140 .0
141 })
142 }
143 0b_101 => Some(
144 Itype::new_u(
145 insts::OP_RORIW,
146 rd(instruction_bits),
147 rs1(instruction_bits),
148 utils::x(instruction_bits, 20, 5, 0),
149 )
150 .0,
151 ),
152 _ => None,
153 },
154 _ => {
155 if funct7_value >> 1 == 0b_000010 && funct3_value == 0b_001 {
156 Some(
157 Itype::new_u(
158 insts::OP_SLLIUW,
159 rd(instruction_bits),
160 rs1(instruction_bits),
161 utils::x(instruction_bits, 20, 6, 0),
162 )
163 .0,
164 )
165 } else {
166 None
167 }
168 }
169 }
170 }
171 _ => None,
172 };
173
174 inst.map(set_instruction_length_4)
175}