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