ckb_vm/instructions/
b.rs

1// RISC-V Bitmanip (Bit Manipulation) Extension
2// See https://github.com/riscv/riscv-bitmanip/releases/download/1.0.0/bitmanip-1.0.0.pdf
3
4use 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}