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