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