ab_riscv_primitives/instructions/rv64/zce/
zcmp.rs1#[cfg(test)]
4mod tests;
5
6use crate::instructions::Instruction;
7use crate::instructions::rv32::zce::zcmp::{ZcmpRegister, ZcmpUrlist};
8use crate::instructions::rv64::c::zca::Rv64ZcaInstruction;
9use crate::instructions::utils::I24;
10use crate::registers::general_purpose::Register;
11use ab_riscv_macros::instruction;
12use core::fmt;
13
14#[instruction(
16 inherit = [Rv64ZcaInstruction, Rv64ZcmpOnlyInstruction],
17)]
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum Rv64ZcmpInstruction<Reg> {}
20
21#[instruction]
22const impl<Reg> Instruction for Rv64ZcmpInstruction<Reg>
23where
24 Reg: [const] Register<Type = u64>,
25{
26 type Reg = Reg;
27
28 #[inline(always)]
29 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
30 fn try_decode(instruction: u32) -> Option<Self> {
31 None
32 }
33
34 #[inline(always)]
35 fn alignment() -> u8 {
36 align_of::<u16>() as u8
37 }
38
39 #[inline(always)]
40 fn size(&self) -> u8 {
41 size_of::<u16>() as u8
42 }
43}
44
45#[instruction]
46impl<Reg> fmt::Display for Rv64ZcmpInstruction<Reg>
47where
48 Reg: Register,
49{
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match self {}
52 }
53}
54
55#[instruction]
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58#[doc(hidden)]
59pub enum Rv64ZcmpOnlyInstruction<Reg> {
60 CmPush {
64 urlist: ZcmpUrlist<Reg>,
65 stack_adj: u8,
66 },
67 CmPop {
69 urlist: ZcmpUrlist<Reg>,
70 stack_adj: u8,
71 },
72 CmPopretz {
74 urlist: ZcmpUrlist<Reg>,
75 stack_adj: u8,
76 },
77 CmPopret {
79 urlist: ZcmpUrlist<Reg>,
80 stack_adj: u8,
81 },
82 CmMva01s { rs1: Reg, rs2: Reg },
87 CmMvsa01 { rs1: Reg, rs2: Reg },
92}
93
94#[instruction]
95const impl<Reg> Instruction for Rv64ZcmpOnlyInstruction<Reg>
96where
97 Reg: [const] ZcmpRegister<Type = u64>,
98{
99 type Reg = Reg;
100
101 #[inline(always)]
102 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
103 fn try_decode(instruction: u32) -> Option<Self> {
104 #[inline(always)]
107 const fn sreg_bits(field: u8) -> u8 {
108 match field {
109 0 => 8,
110 1 => 9,
111 f => f + 16,
112 }
113 }
114
115 let inst = instruction as u16;
116 let quadrant = inst & 0b11;
117 let funct3 = ((inst >> 13) & 0b111) as u8;
118
119 if quadrant != 0b10 || funct3 != 0b101 {
121 None?;
122 }
123
124 let funct2_12_11 = ((inst >> 11) & 0b11) as u8;
125
126 match funct2_12_11 {
127 0b11 => {
129 let op_sel = ((inst >> 9) & 0b11) as u8;
130 let urlist = ZcmpUrlist::try_from_raw(((inst >> 4) & 0xf) as u8)?;
131 let spimm = ((inst >> 2) & 0b11) as u8;
132 let stack_adj = urlist.stack_adj_base() + spimm * 16;
133 match op_sel {
134 0b00 => Some(Self::CmPush { urlist, stack_adj }),
135 0b01 => Some(Self::CmPop { urlist, stack_adj }),
136 0b10 => Some(Self::CmPopretz { urlist, stack_adj }),
137 0b11 => Some(Self::CmPopret { urlist, stack_adj }),
138 _ => None,
139 }
140 }
141 0b01 => {
143 if (inst >> 10) & 1 != 1 {
144 None?;
145 }
146
147 let r1s_bits = ((inst >> 7) & 0b111) as u8;
148 let funct2 = ((inst >> 5) & 0b11) as u8;
149 let r2s_bits = ((inst >> 2) & 0b111) as u8;
150
151 let r1s = Reg::from_bits(sreg_bits(r1s_bits))?;
156 let r2s = Reg::from_bits(sreg_bits(r2s_bits))?;
157
158 match funct2 {
160 0b11 => Some(Self::CmMva01s { rs1: r1s, rs2: r2s }),
161 0b01 => {
162 if r1s_bits == r2s_bits {
164 None?;
165 }
166 Some(Self::CmMvsa01 { rs1: r1s, rs2: r2s })
167 }
168 _ => None,
169 }
170 }
171 _ => None,
173 }
174 }
175
176 #[inline(always)]
177 fn alignment() -> u8 {
178 align_of::<u16>() as u8
179 }
180
181 #[inline(always)]
182 fn size(&self) -> u8 {
183 size_of::<u16>() as u8
184 }
185}
186
187#[instruction]
188impl<Reg> fmt::Display for Rv64ZcmpOnlyInstruction<Reg>
189where
190 Reg: Register,
191{
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 match self {
194 Self::CmPush { urlist, stack_adj } => {
195 write!(f, "cm.push {urlist}, -{stack_adj}")
196 }
197 Self::CmPop { urlist, stack_adj } => {
198 write!(f, "cm.pop {urlist}, {stack_adj}")
199 }
200 Self::CmPopretz { urlist, stack_adj } => {
201 write!(f, "cm.popretz {urlist}, {stack_adj}")
202 }
203 Self::CmPopret { urlist, stack_adj } => {
204 write!(f, "cm.popret {urlist}, {stack_adj}")
205 }
206 Self::CmMva01s { rs1, rs2 } => write!(f, "cm.mva01s {rs1}, {rs2}"),
207 Self::CmMvsa01 { rs1, rs2 } => write!(f, "cm.mvsa01 {rs1}, {rs2}"),
208 }
209 }
210}