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