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