ab_riscv_primitives/instructions/rv32/zce/
zcb.rs1#[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]
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum Rv32ZcbInstruction<Reg> {
17 CLbu { rd: Reg, rs1: Reg, uimm: u8 },
20 CLh { rd: Reg, rs1: Reg, uimm: u8 },
22 CLhu { rd: Reg, rs1: Reg, uimm: u8 },
24 CSb { rs1: Reg, rs2: Reg, uimm: u8 },
26 CSh { rs1: Reg, rs2: Reg, uimm: u8 },
28
29 CZextB { rd: Reg },
32 CSextB { rd: Reg },
34 CZextH { rd: Reg },
36 CSextH { rd: Reg },
38 CNot { rd: Reg },
40
41 CMul { rd: Reg, rs2: Reg },
44}
45
46#[instruction]
47impl<Reg> const Instruction for Rv32ZcbInstruction<Reg>
48where
49 Reg: [const] Register<Type = u32>,
50{
51 type Reg = Reg;
52
53 #[inline(always)]
54 fn try_decode(instruction: u32) -> Option<Self> {
55 #[inline(always)]
57 const fn prime_reg_bits(bits: u8) -> u8 {
58 bits + 8
59 }
60
61 let inst = instruction as u16;
62 let quadrant = inst & 0b11;
63 let funct3 = ((inst >> 13) & 0b111) as u8;
64
65 match quadrant {
66 0b00 if funct3 == 0b100 => {
68 let sub = ((inst >> 10) & 0b111) as u8;
69 let rs1_bits = prime_reg_bits(((inst >> 7) & 0b111) as u8);
70 let rd_rs2_bits = prime_reg_bits(((inst >> 2) & 0b111) as u8);
71
72 match sub {
73 0b000 => {
75 let uimm = ((((inst >> 5) & 1) << 1) | ((inst >> 6) & 1)) as u8;
76 let rs1 = Reg::from_bits(rs1_bits)?;
77 let rd = Reg::from_bits(rd_rs2_bits)?;
78 Some(Self::CLbu { rd, rs1, uimm })
79 }
80 0b001 => {
83 let funct1 = ((inst >> 6) & 1) as u8;
84 let uimm = (((inst >> 5) & 1) as u8) << 1;
85 let rs1 = Reg::from_bits(rs1_bits)?;
86 let rd = Reg::from_bits(rd_rs2_bits)?;
87 if funct1 == 0 {
88 Some(Self::CLhu { rd, rs1, uimm })
89 } else {
90 Some(Self::CLh { rd, rs1, uimm })
91 }
92 }
93 0b010 => {
95 let uimm = ((((inst >> 5) & 1) << 1) | ((inst >> 6) & 1)) as u8;
96 let rs1 = Reg::from_bits(rs1_bits)?;
97 let rs2 = Reg::from_bits(rd_rs2_bits)?;
98 Some(Self::CSb { rs1, rs2, uimm })
99 }
100 0b011 => {
102 if ((inst >> 6) & 1) != 0 {
103 None?;
104 }
105 let uimm = (((inst >> 5) & 1) as u8) << 1;
106 let rs1 = Reg::from_bits(rs1_bits)?;
107 let rs2 = Reg::from_bits(rd_rs2_bits)?;
108 Some(Self::CSh { rs1, rs2, uimm })
109 }
110 _ => None,
111 }
112 }
113
114 0b01 if funct3 == 0b100 => {
122 let funct2_11_10 = ((inst >> 10) & 0b11) as u8;
123 let bit12 = (inst >> 12) & 1;
124
125 if funct2_11_10 != 0b11 || bit12 == 0 {
126 None?;
127 }
128
129 let rd_rs1_bits = prime_reg_bits(((inst >> 7) & 0b111) as u8);
130 let funct2b = ((inst >> 5) & 0b11) as u8;
131 let rs2_sub = ((inst >> 2) & 0b111) as u8;
132
133 match funct2b {
134 0b11 => {
136 let rd = Reg::from_bits(rd_rs1_bits)?;
137 match rs2_sub {
138 0b000 => Some(Self::CZextB { rd }),
139 0b001 => Some(Self::CSextB { rd }),
140 0b010 => Some(Self::CZextH { rd }),
141 0b011 => Some(Self::CSextH { rd }),
142 0b101 => Some(Self::CNot { rd }),
143 _ => None,
145 }
146 }
147 0b10 => {
149 let rd = Reg::from_bits(rd_rs1_bits)?;
150 let rs2 = Reg::from_bits(prime_reg_bits(rs2_sub))?;
151 Some(Self::CMul { rd, rs2 })
152 }
153 _ => None,
155 }
156 }
157 _ => None,
158 }
159 }
160
161 #[inline(always)]
162 fn alignment() -> u8 {
163 align_of::<u16>() as u8
164 }
165
166 #[inline(always)]
167 fn size(&self) -> u8 {
168 size_of::<u16>() as u8
169 }
170}
171
172impl<Reg> fmt::Display for Rv32ZcbInstruction<Reg>
173where
174 Reg: fmt::Display,
175{
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 match self {
178 Self::CLbu { rd, rs1, uimm } => write!(f, "c.lbu {rd}, {uimm}({rs1})"),
179 Self::CLh { rd, rs1, uimm } => write!(f, "c.lh {rd}, {uimm}({rs1})"),
180 Self::CLhu { rd, rs1, uimm } => write!(f, "c.lhu {rd}, {uimm}({rs1})"),
181 Self::CSb { rs1, rs2, uimm } => write!(f, "c.sb {rs2}, {uimm}({rs1})"),
182 Self::CSh { rs1, rs2, uimm } => write!(f, "c.sh {rs2}, {uimm}({rs1})"),
183 Self::CZextB { rd } => write!(f, "c.zext.b {rd}"),
184 Self::CSextB { rd } => write!(f, "c.sext.b {rd}"),
185 Self::CZextH { rd } => write!(f, "c.zext.h {rd}"),
186 Self::CSextH { rd } => write!(f, "c.sext.h {rd}"),
187 Self::CNot { rd } => write!(f, "c.not {rd}"),
188 Self::CMul { rd, rs2 } => write!(f, "c.mul {rd}, {rs2}"),
189 }
190 }
191}