ab_riscv_primitives/instructions/rv64/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 Rv64ZcbInstruction<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 CZextW { rd: Reg },
40 CNot { rd: Reg },
42
43 CMul { rd: Reg, rs2: Reg },
46}
47
48#[instruction]
49impl<Reg> const Instruction for Rv64ZcbInstruction<Reg>
50where
51 Reg: [const] Register<Type = u64>,
52{
53 type Reg = Reg;
54
55 #[inline(always)]
56 fn try_decode(instruction: u32) -> Option<Self> {
57 #[inline(always)]
59 const fn prime_reg_bits(bits: u8) -> u8 {
60 bits + 8
61 }
62
63 let inst = instruction as u16;
64 let quadrant = inst & 0b11;
65 let funct3 = ((inst >> 13) & 0b111) as u8;
66
67 match quadrant {
68 0b00 if funct3 == 0b100 => {
70 let sub = ((inst >> 10) & 0b111) as u8;
71 let rs1_bits = prime_reg_bits(((inst >> 7) & 0b111) as u8);
72 let rd_rs2_bits = prime_reg_bits(((inst >> 2) & 0b111) as u8);
73
74 match sub {
75 0b000 => {
77 let uimm = ((((inst >> 5) & 1) << 1) | ((inst >> 6) & 1)) as u8;
78 let rs1 = Reg::from_bits(rs1_bits)?;
79 let rd = Reg::from_bits(rd_rs2_bits)?;
80 Some(Self::CLbu { rd, rs1, uimm })
81 }
82 0b001 => {
85 let funct1 = ((inst >> 6) & 1) as u8;
86 let uimm = (((inst >> 5) & 1) as u8) << 1;
87 let rs1 = Reg::from_bits(rs1_bits)?;
88 let rd = Reg::from_bits(rd_rs2_bits)?;
89 if funct1 == 0 {
90 Some(Self::CLhu { rd, rs1, uimm })
91 } else {
92 Some(Self::CLh { rd, rs1, uimm })
93 }
94 }
95 0b010 => {
97 let uimm = ((((inst >> 5) & 1) << 1) | ((inst >> 6) & 1)) as u8;
98 let rs1 = Reg::from_bits(rs1_bits)?;
99 let rs2 = Reg::from_bits(rd_rs2_bits)?;
100 Some(Self::CSb { rs1, rs2, uimm })
101 }
102 0b011 => {
104 if ((inst >> 6) & 1) != 0 {
105 None?;
106 }
107 let uimm = (((inst >> 5) & 1) as u8) << 1;
108 let rs1 = Reg::from_bits(rs1_bits)?;
109 let rs2 = Reg::from_bits(rd_rs2_bits)?;
110 Some(Self::CSh { rs1, rs2, uimm })
111 }
112 _ => None,
113 }
114 }
115
116 0b01 if funct3 == 0b100 => {
124 let funct2_11_10 = ((inst >> 10) & 0b11) as u8;
125 let bit12 = (inst >> 12) & 1;
126
127 if funct2_11_10 != 0b11 || bit12 == 0 {
128 None?;
129 }
130
131 let rd_rs1_bits = prime_reg_bits(((inst >> 7) & 0b111) as u8);
132 let funct2b = ((inst >> 5) & 0b11) as u8;
133 let rs2_sub = ((inst >> 2) & 0b111) as u8;
134
135 match funct2b {
136 0b11 => {
138 let rd = Reg::from_bits(rd_rs1_bits)?;
139 match rs2_sub {
140 0b000 => Some(Self::CZextB { rd }),
141 0b001 => Some(Self::CSextB { rd }),
142 0b010 => Some(Self::CZextH { rd }),
143 0b011 => Some(Self::CSextH { rd }),
144 0b100 => Some(Self::CZextW { rd }),
145 0b101 => Some(Self::CNot { rd }),
146 _ => None,
148 }
149 }
150 0b10 => {
152 let rd = Reg::from_bits(rd_rs1_bits)?;
153 let rs2 = Reg::from_bits(prime_reg_bits(rs2_sub))?;
154 Some(Self::CMul { rd, rs2 })
155 }
156 _ => None,
158 }
159 }
160
161 _ => None,
162 }
163 }
164
165 #[inline(always)]
166 fn alignment() -> u8 {
167 align_of::<u16>() as u8
168 }
169
170 #[inline(always)]
171 fn size(&self) -> u8 {
172 size_of::<u16>() as u8
173 }
174}
175
176impl<Reg> fmt::Display for Rv64ZcbInstruction<Reg>
177where
178 Reg: fmt::Display,
179{
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 match self {
182 Self::CLbu { rd, rs1, uimm } => write!(f, "c.lbu {rd}, {uimm}({rs1})"),
183 Self::CLh { rd, rs1, uimm } => write!(f, "c.lh {rd}, {uimm}({rs1})"),
184 Self::CLhu { rd, rs1, uimm } => write!(f, "c.lhu {rd}, {uimm}({rs1})"),
185 Self::CSb { rs1, rs2, uimm } => write!(f, "c.sb {rs2}, {uimm}({rs1})"),
186 Self::CSh { rs1, rs2, uimm } => write!(f, "c.sh {rs2}, {uimm}({rs1})"),
187 Self::CZextB { rd } => write!(f, "c.zext.b {rd}"),
188 Self::CSextB { rd } => write!(f, "c.sext.b {rd}"),
189 Self::CZextH { rd } => write!(f, "c.zext.h {rd}"),
190 Self::CSextH { rd } => write!(f, "c.sext.h {rd}"),
191 Self::CZextW { rd } => write!(f, "c.zext.w {rd}"),
192 Self::CNot { rd } => write!(f, "c.not {rd}"),
193 Self::CMul { rd, rs2 } => write!(f, "c.mul {rd}, {rs2}"),
194 }
195 }
196}