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::registers::general_purpose::Register;
9use ab_riscv_macros::instruction;
10use core::fmt;
11
12#[instruction]
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Rv64ZcmpInstruction<Reg> {
16 CmPush {
20 urlist: ZcmpUrlist<Reg>,
21 stack_adj: u8,
22 },
23 CmPop {
25 urlist: ZcmpUrlist<Reg>,
26 stack_adj: u8,
27 },
28 CmPopretz {
30 urlist: ZcmpUrlist<Reg>,
31 stack_adj: u8,
32 },
33 CmPopret {
35 urlist: ZcmpUrlist<Reg>,
36 stack_adj: u8,
37 },
38 CmMva01s { rs1: Reg, rs2: Reg },
43 CmMvsa01 { rs1: Reg, rs2: Reg },
48}
49
50#[instruction]
51impl<Reg> const Instruction for Rv64ZcmpInstruction<Reg>
52where
53 Reg: [const] ZcmpRegister<Type = u64>,
54{
55 type Reg = Reg;
56
57 #[inline(always)]
58 fn try_decode(instruction: u32) -> Option<Self> {
59 #[inline(always)]
62 const fn sreg_bits(field: u8) -> u8 {
63 match field {
64 0 => 8,
65 1 => 9,
66 f => f + 16,
67 }
68 }
69
70 let inst = instruction as u16;
71 let quadrant = inst & 0b11;
72 let funct3 = ((inst >> 13) & 0b111) as u8;
73
74 if quadrant != 0b10 || funct3 != 0b101 {
76 None?;
77 }
78
79 let funct2_12_11 = ((inst >> 11) & 0b11) as u8;
80
81 match funct2_12_11 {
82 0b11 => {
84 let op_sel = ((inst >> 9) & 0b11) as u8;
85 let urlist = ZcmpUrlist::try_from_raw(((inst >> 4) & 0xf) as u8)?;
86 let spimm = ((inst >> 2) & 0b11) as u8;
87 let stack_adj = urlist.stack_adj_base() + spimm * 16;
88 match op_sel {
89 0b00 => Some(Self::CmPush { urlist, stack_adj }),
90 0b01 => Some(Self::CmPop { urlist, stack_adj }),
91 0b10 => Some(Self::CmPopretz { urlist, stack_adj }),
92 0b11 => Some(Self::CmPopret { urlist, stack_adj }),
93 _ => None,
94 }
95 }
96 0b01 => {
98 if (inst >> 10) & 1 != 1 {
99 None?;
100 }
101
102 let r1s_bits = ((inst >> 7) & 0b111) as u8;
103 let funct2 = ((inst >> 5) & 0b11) as u8;
104 let r2s_bits = ((inst >> 2) & 0b111) as u8;
105
106 let r1s = Reg::from_bits(sreg_bits(r1s_bits))?;
111 let r2s = Reg::from_bits(sreg_bits(r2s_bits))?;
112
113 match funct2 {
115 0b11 => Some(Self::CmMva01s { rs1: r1s, rs2: r2s }),
116 0b01 => {
117 if r1s_bits == r2s_bits {
119 None?;
120 }
121 Some(Self::CmMvsa01 { rs1: r1s, rs2: r2s })
122 }
123 _ => None,
124 }
125 }
126 _ => None,
128 }
129 }
130
131 #[inline(always)]
132 fn alignment() -> u8 {
133 align_of::<u16>() as u8
134 }
135
136 #[inline(always)]
137 fn size(&self) -> u8 {
138 size_of::<u16>() as u8
139 }
140}
141
142#[instruction]
143impl<Reg> fmt::Display for Rv64ZcmpInstruction<Reg>
144where
145 Reg: Register,
146{
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 match self {
149 Self::CmPush { urlist, stack_adj } => {
150 write!(f, "cm.push {urlist}, -{stack_adj}")
151 }
152 Self::CmPop { urlist, stack_adj } => {
153 write!(f, "cm.pop {urlist}, {stack_adj}")
154 }
155 Self::CmPopretz { urlist, stack_adj } => {
156 write!(f, "cm.popretz {urlist}, {stack_adj}")
157 }
158 Self::CmPopret { urlist, stack_adj } => {
159 write!(f, "cm.popret {urlist}, {stack_adj}")
160 }
161 Self::CmMva01s { rs1, rs2 } => write!(f, "cm.mva01s {rs1}, {rs2}"),
162 Self::CmMvsa01 { rs1, rs2 } => write!(f, "cm.mvsa01 {rs1}, {rs2}"),
163 }
164 }
165}