1#[cfg(test)]
4mod tests;
5
6use crate::instructions::Instruction;
7use crate::registers::general_purpose::Register;
8use ab_riscv_macros::instruction;
9use core::fmt;
10
11#[instruction]
13#[derive(Debug, Clone, Copy)]
14#[derive_const(PartialEq, Eq)]
15pub enum Rv32ZbbInstruction<Reg> {
16 Andn { rd: Reg, rs1: Reg, rs2: Reg },
17 Orn { rd: Reg, rs1: Reg, rs2: Reg },
18 Xnor { rd: Reg, rs1: Reg, rs2: Reg },
19 Clz { rd: Reg, rs1: Reg },
20 Ctz { rd: Reg, rs1: Reg },
21 Cpop { rd: Reg, rs1: Reg },
22 Max { rd: Reg, rs1: Reg, rs2: Reg },
23 Maxu { rd: Reg, rs1: Reg, rs2: Reg },
24 Min { rd: Reg, rs1: Reg, rs2: Reg },
25 Minu { rd: Reg, rs1: Reg, rs2: Reg },
26 Sextb { rd: Reg, rs1: Reg },
27 Sexth { rd: Reg, rs1: Reg },
28 Zexth { rd: Reg, rs1: Reg },
29 Rol { rd: Reg, rs1: Reg, rs2: Reg },
30 Ror { rd: Reg, rs1: Reg, rs2: Reg },
31 Rori { rd: Reg, rs1: Reg, shamt: u8 },
32 Orcb { rd: Reg, rs1: Reg },
33 Rev8 { rd: Reg, rs1: Reg },
34}
35
36#[instruction]
37const impl<Reg> Instruction for Rv32ZbbInstruction<Reg>
38where
39 Reg: [const] Register<Type = u32>,
40{
41 const ALIGNMENT: u8 = align_of::<u32>() as u8;
42
43 type Reg = Reg;
44
45 #[inline(always)]
46 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
47 fn try_decode(instruction: u32) -> Option<Self> {
48 let opcode = (instruction & 0b111_1111) as u8;
49 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
50 let funct3 = ((instruction >> 12) & 0b111) as u8;
51 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
52 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
53 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
54 let low5 = ((instruction >> 20) & 0x1f) as u8;
56 let funct12 = ((instruction >> 20) & 0xfff) as u16;
57
58 match opcode {
59 0b001_0011 => {
61 let rd = Reg::from_bits(rd_bits)?;
62 let rs1 = Reg::from_bits(rs1_bits)?;
63 match funct3 {
64 0b001 => {
65 if funct7 == 0b011_0000 {
67 match rs2_bits {
68 0 => Some(Self::Clz { rd, rs1 }),
69 1 => Some(Self::Ctz { rd, rs1 }),
70 2 => Some(Self::Cpop { rd, rs1 }),
71 4 => Some(Self::Sextb { rd, rs1 }),
72 5 => Some(Self::Sexth { rd, rs1 }),
73 _ => None,
74 }
75 } else {
76 None
77 }
78 }
79 0b101 => {
80 if funct12 == 0b0010_1000_0111 {
85 Some(Self::Orcb { rd, rs1 })
86 } else if funct12 == 0b0110_1001_1000 {
87 Some(Self::Rev8 { rd, rs1 })
88 } else if funct7 == 0b011_0000 {
89 Some(Self::Rori {
90 rd,
91 rs1,
92 shamt: low5,
93 })
94 } else {
95 None
96 }
97 }
98 _ => None,
99 }
100 }
101 0b011_0011 => {
103 let rd = Reg::from_bits(rd_bits)?;
104 let rs1 = Reg::from_bits(rs1_bits)?;
105 let rs2 = Reg::from_bits(rs2_bits)?;
106 match funct3 {
107 0b001 => {
108 if funct7 == 0b011_0000 {
109 Some(Self::Rol { rd, rs1, rs2 })
110 } else {
111 None
112 }
113 }
114 0b100 => match funct7 {
115 0b010_0000 => Some(Self::Xnor { rd, rs1, rs2 }),
116 0b000_0101 => Some(Self::Min { rd, rs1, rs2 }),
117 0b000_0100 => {
119 if rs2_bits == 0 {
120 Some(Self::Zexth { rd, rs1 })
121 } else {
122 None
123 }
124 }
125 _ => None,
126 },
127 0b101 => match funct7 {
128 0b011_0000 => Some(Self::Ror { rd, rs1, rs2 }),
129 0b000_0101 => Some(Self::Minu { rd, rs1, rs2 }),
130 _ => None,
131 },
132 0b110 => match funct7 {
133 0b010_0000 => Some(Self::Orn { rd, rs1, rs2 }),
134 0b000_0101 => Some(Self::Max { rd, rs1, rs2 }),
135 _ => None,
136 },
137 0b111 => match funct7 {
138 0b010_0000 => Some(Self::Andn { rd, rs1, rs2 }),
139 0b000_0101 => Some(Self::Maxu { rd, rs1, rs2 }),
140 _ => None,
141 },
142 _ => None,
143 }
144 }
145 _ => None,
146 }
147 }
148
149 #[inline(always)]
150 fn size(&self) -> u8 {
151 size_of::<u32>() as u8
152 }
153}
154
155#[instruction]
156impl<Reg> fmt::Display for Rv32ZbbInstruction<Reg>
157where
158 Reg: fmt::Display,
159{
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 match self {
162 Self::Andn { rd, rs1, rs2 } => write!(f, "andn {rd}, {rs1}, {rs2}"),
163 Self::Orn { rd, rs1, rs2 } => write!(f, "orn {rd}, {rs1}, {rs2}"),
164 Self::Xnor { rd, rs1, rs2 } => write!(f, "xnor {rd}, {rs1}, {rs2}"),
165 Self::Clz { rd, rs1 } => write!(f, "clz {rd}, {rs1}"),
166 Self::Ctz { rd, rs1 } => write!(f, "ctz {rd}, {rs1}"),
167 Self::Cpop { rd, rs1 } => write!(f, "cpop {rd}, {rs1}"),
168 Self::Max { rd, rs1, rs2 } => write!(f, "max {rd}, {rs1}, {rs2}"),
169 Self::Maxu { rd, rs1, rs2 } => write!(f, "maxu {rd}, {rs1}, {rs2}"),
170 Self::Min { rd, rs1, rs2 } => write!(f, "min {rd}, {rs1}, {rs2}"),
171 Self::Minu { rd, rs1, rs2 } => write!(f, "minu {rd}, {rs1}, {rs2}"),
172 Self::Sextb { rd, rs1 } => write!(f, "sext.b {rd}, {rs1}"),
173 Self::Sexth { rd, rs1 } => write!(f, "sext.h {rd}, {rs1}"),
174 Self::Zexth { rd, rs1 } => write!(f, "zext.h {rd}, {rs1}"),
175 Self::Rol { rd, rs1, rs2 } => write!(f, "rol {rd}, {rs1}, {rs2}"),
176 Self::Ror { rd, rs1, rs2 } => write!(f, "ror {rd}, {rs1}, {rs2}"),
177 Self::Rori { rd, rs1, shamt } => write!(f, "rori {rd}, {rs1}, {shamt}"),
178 Self::Orcb { rd, rs1 } => write!(f, "orc.b {rd}, {rs1}"),
179 Self::Rev8 { rd, rs1 } => write!(f, "rev8 {rd}, {rs1}"),
180 }
181 }
182}