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]
22impl<Reg> const Instruction for Rv64ZcmpInstruction<Reg>
23where
24 Reg: [const] Register<Type = u64>,
25{
26 type Reg = Reg;
27
28 #[inline(always)]
29 fn try_decode(instruction: u32) -> Option<Self> {
30 None
31 }
32
33 #[inline(always)]
34 fn alignment() -> u8 {
35 align_of::<u16>() as u8
36 }
37
38 #[inline(always)]
39 fn size(&self) -> u8 {
40 size_of::<u16>() as u8
41 }
42}
43
44#[instruction]
45impl<Reg> fmt::Display for Rv64ZcmpInstruction<Reg>
46where
47 Reg: Register,
48{
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match self {}
51 }
52}
53
54#[instruction]
56#[derive(Debug, Clone, Copy, 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]
94impl<Reg> const Instruction for Rv64ZcmpOnlyInstruction<Reg>
95where
96 Reg: [const] ZcmpRegister<Type = u64>,
97{
98 type Reg = Reg;
99
100 #[inline(always)]
101 fn try_decode(instruction: u32) -> Option<Self> {
102 #[inline(always)]
105 const fn sreg_bits(field: u8) -> u8 {
106 match field {
107 0 => 8,
108 1 => 9,
109 f => f + 16,
110 }
111 }
112
113 let inst = instruction as u16;
114 let quadrant = inst & 0b11;
115 let funct3 = ((inst >> 13) & 0b111) as u8;
116
117 if quadrant != 0b10 || funct3 != 0b101 {
119 None?;
120 }
121
122 let funct2_12_11 = ((inst >> 11) & 0b11) as u8;
123
124 match funct2_12_11 {
125 0b11 => {
127 let op_sel = ((inst >> 9) & 0b11) as u8;
128 let urlist = ZcmpUrlist::try_from_raw(((inst >> 4) & 0xf) as u8)?;
129 let spimm = ((inst >> 2) & 0b11) as u8;
130 let stack_adj = urlist.stack_adj_base() + spimm * 16;
131 match op_sel {
132 0b00 => Some(Self::CmPush { urlist, stack_adj }),
133 0b01 => Some(Self::CmPop { urlist, stack_adj }),
134 0b10 => Some(Self::CmPopretz { urlist, stack_adj }),
135 0b11 => Some(Self::CmPopret { urlist, stack_adj }),
136 _ => None,
137 }
138 }
139 0b01 => {
141 if (inst >> 10) & 1 != 1 {
142 None?;
143 }
144
145 let r1s_bits = ((inst >> 7) & 0b111) as u8;
146 let funct2 = ((inst >> 5) & 0b11) as u8;
147 let r2s_bits = ((inst >> 2) & 0b111) as u8;
148
149 let r1s = Reg::from_bits(sreg_bits(r1s_bits))?;
154 let r2s = Reg::from_bits(sreg_bits(r2s_bits))?;
155
156 match funct2 {
158 0b11 => Some(Self::CmMva01s { rs1: r1s, rs2: r2s }),
159 0b01 => {
160 if r1s_bits == r2s_bits {
162 None?;
163 }
164 Some(Self::CmMvsa01 { rs1: r1s, rs2: r2s })
165 }
166 _ => None,
167 }
168 }
169 _ => None,
171 }
172 }
173
174 #[inline(always)]
175 fn alignment() -> u8 {
176 align_of::<u16>() as u8
177 }
178
179 #[inline(always)]
180 fn size(&self) -> u8 {
181 size_of::<u16>() as u8
182 }
183}
184
185#[instruction]
186impl<Reg> fmt::Display for Rv64ZcmpOnlyInstruction<Reg>
187where
188 Reg: Register,
189{
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 match self {
192 Self::CmPush { urlist, stack_adj } => {
193 write!(f, "cm.push {urlist}, -{stack_adj}")
194 }
195 Self::CmPop { urlist, stack_adj } => {
196 write!(f, "cm.pop {urlist}, {stack_adj}")
197 }
198 Self::CmPopretz { urlist, stack_adj } => {
199 write!(f, "cm.popretz {urlist}, {stack_adj}")
200 }
201 Self::CmPopret { urlist, stack_adj } => {
202 write!(f, "cm.popret {urlist}, {stack_adj}")
203 }
204 Self::CmMva01s { rs1, rs2 } => write!(f, "cm.mva01s {rs1}, {rs2}"),
205 Self::CmMvsa01 { rs1, rs2 } => write!(f, "cm.mvsa01 {rs1}, {rs2}"),
206 }
207 }
208}