Skip to main content

wasm_pvm/pvm/
opcode.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2#[repr(u8)]
3pub enum Opcode {
4    Trap = 0,
5    Fallthrough = 1,
6    Ecalli = 10,
7    LoadImm64 = 20,
8    // Store immediate to absolute address (TwoImm)
9    StoreImmU8 = 30,
10    StoreImmU16 = 31,
11    StoreImmU32 = 32,
12    StoreImmU64 = 33,
13    Jump = 40,
14    JumpInd = 50,
15    LoadImm = 51,
16    // Load/store absolute address (OneRegOneImm)
17    LoadU8 = 52,
18    LoadI8 = 53,
19    LoadU16 = 54,
20    LoadI16 = 55,
21    LoadU32 = 56,
22    LoadI32 = 57,
23    LoadU64 = 58,
24    StoreU8 = 59,
25    StoreU16 = 60,
26    StoreU32 = 61,
27    StoreU64 = 62,
28    // Store immediate indirect (OneRegTwoImm)
29    StoreImmIndU8 = 70,
30    StoreImmIndU16 = 71,
31    StoreImmIndU32 = 72,
32    StoreImmIndU64 = 73,
33    // Compound jump (OneRegOneImmOneOff)
34    LoadImmJump = 80,
35    // Branch with immediate comparison (OneRegOneImmOneOff)
36    BranchEqImm = 81,
37    BranchNeImm = 82,
38    BranchLtUImm = 83,
39    BranchLeUImm = 84,
40    BranchGeUImm = 85,
41    BranchGtUImm = 86,
42    BranchLtSImm = 87,
43    BranchLeSImm = 88,
44    BranchGeSImm = 89,
45    BranchGtSImm = 90,
46    MoveReg = 100,
47    Sbrk = 101,
48    CountSetBits64 = 102,
49    CountSetBits32 = 103,
50    LeadingZeroBits64 = 104,
51    LeadingZeroBits32 = 105,
52    TrailingZeroBits64 = 106,
53    TrailingZeroBits32 = 107,
54    SignExtend8 = 108,
55    SignExtend16 = 109,
56    ZeroExtend16 = 110,
57    ReverseBytes = 111,
58    StoreIndU8 = 120,
59    StoreIndU16 = 121,
60    StoreIndU32 = 122,
61    StoreIndU64 = 123,
62    LoadIndU8 = 124,
63    LoadIndI8 = 125,
64    LoadIndU16 = 126,
65    LoadIndI16 = 127,
66    LoadIndU32 = 128,
67    LoadIndI32 = 129,
68    LoadIndU64 = 130,
69    AddImm32 = 131,
70    AndImm = 132,
71    XorImm = 133,
72    OrImm = 134,
73    MulImm32 = 135,
74    // Set if less/greater than immediate (TwoRegOneImm)
75    SetLtUImm = 136,
76    SetLtSImm = 137,
77    // Shift by immediate (TwoRegOneImm)
78    ShloLImm32 = 138,
79    ShloRImm32 = 139,
80    SharRImm32 = 140,
81    NegAddImm32 = 141,
82    SetGtUImm = 142,
83    SetGtSImm = 143,
84    // Alternate shift immediates: dst = imm OP src (reversed operands, 32-bit)
85    ShloLImmAlt32 = 144,
86    ShloRImmAlt32 = 145,
87    SharRImmAlt32 = 146,
88    // Conditional move with immediate (TwoRegOneImm)
89    CmovIzImm = 147,
90    CmovNzImm = 148,
91    AddImm64 = 149,
92    MulImm64 = 150,
93    ShloLImm64 = 151,
94    ShloRImm64 = 152,
95    SharRImm64 = 153,
96    NegAddImm64 = 154,
97    // Alternate shift immediates: dst = imm OP src (reversed operands, 64-bit)
98    ShloLImmAlt64 = 155,
99    ShloRImmAlt64 = 156,
100    SharRImmAlt64 = 157,
101    // Rotate right by immediate (TwoRegOneImm)
102    RotRImm64 = 158,
103    RotRImmAlt64 = 159,
104    RotRImm32 = 160,
105    RotRImmAlt32 = 161,
106    // Branch with two registers (TwoRegOneOff)
107    BranchEq = 170,
108    BranchNe = 171,
109    BranchLtU = 172,
110    BranchLtS = 173,
111    BranchGeU = 174,
112    BranchGeS = 175,
113    // Compound indirect jump (TwoRegTwoImm)
114    LoadImmJumpInd = 180,
115    // 32-bit three-register arithmetic
116    Add32 = 190,
117    Sub32 = 191,
118    Mul32 = 192,
119    DivU32 = 193,
120    DivS32 = 194,
121    RemU32 = 195,
122    RemS32 = 196,
123    // 32-bit shift operations (ThreeReg)
124    ShloL32 = 197,
125    ShloR32 = 198,
126    SharR32 = 199,
127    // 64-bit three-register arithmetic
128    Add64 = 200,
129    Sub64 = 201,
130    Mul64 = 202,
131    DivU64 = 203,
132    DivS64 = 204,
133    RemU64 = 205,
134    RemS64 = 206,
135    ShloL64 = 207,
136    ShloR64 = 208,
137    SharR64 = 209,
138    // Bitwise operations (ThreeReg)
139    And = 210,
140    Xor = 211,
141    Or = 212,
142    // Upper multiply (ThreeReg)
143    MulUpperSS = 213,
144    MulUpperUU = 214,
145    MulUpperSU = 215,
146    // Comparison (ThreeReg) - result is 0 or 1
147    SetLtU = 216,
148    SetLtS = 217,
149    // Conditional move (ThreeReg)
150    CmovIz = 218,
151    CmovNz = 219,
152    // Rotate (ThreeReg)
153    RotL64 = 220,
154    RotL32 = 221,
155    RotR64 = 222,
156    RotR32 = 223,
157    // Inverted bitwise (ThreeReg)
158    AndInv = 224,
159    OrInv = 225,
160    Xnor = 226,
161    // Min/Max (ThreeReg)
162    Max = 227,
163    MaxU = 228,
164    Min = 229,
165    MinU = 230,
166}
167
168impl Opcode {
169    #[must_use]
170    pub const fn from_u8(opcode: u8) -> Option<Self> {
171        match opcode {
172            0 => Some(Self::Trap),
173            1 => Some(Self::Fallthrough),
174            10 => Some(Self::Ecalli),
175            20 => Some(Self::LoadImm64),
176            30 => Some(Self::StoreImmU8),
177            31 => Some(Self::StoreImmU16),
178            32 => Some(Self::StoreImmU32),
179            33 => Some(Self::StoreImmU64),
180            40 => Some(Self::Jump),
181            50 => Some(Self::JumpInd),
182            51 => Some(Self::LoadImm),
183            52 => Some(Self::LoadU8),
184            53 => Some(Self::LoadI8),
185            54 => Some(Self::LoadU16),
186            55 => Some(Self::LoadI16),
187            56 => Some(Self::LoadU32),
188            57 => Some(Self::LoadI32),
189            58 => Some(Self::LoadU64),
190            59 => Some(Self::StoreU8),
191            60 => Some(Self::StoreU16),
192            61 => Some(Self::StoreU32),
193            62 => Some(Self::StoreU64),
194            70 => Some(Self::StoreImmIndU8),
195            71 => Some(Self::StoreImmIndU16),
196            72 => Some(Self::StoreImmIndU32),
197            73 => Some(Self::StoreImmIndU64),
198            80 => Some(Self::LoadImmJump),
199            81 => Some(Self::BranchEqImm),
200            82 => Some(Self::BranchNeImm),
201            83 => Some(Self::BranchLtUImm),
202            84 => Some(Self::BranchLeUImm),
203            85 => Some(Self::BranchGeUImm),
204            86 => Some(Self::BranchGtUImm),
205            87 => Some(Self::BranchLtSImm),
206            88 => Some(Self::BranchLeSImm),
207            89 => Some(Self::BranchGeSImm),
208            90 => Some(Self::BranchGtSImm),
209            100 => Some(Self::MoveReg),
210            101 => Some(Self::Sbrk),
211            102 => Some(Self::CountSetBits64),
212            103 => Some(Self::CountSetBits32),
213            104 => Some(Self::LeadingZeroBits64),
214            105 => Some(Self::LeadingZeroBits32),
215            106 => Some(Self::TrailingZeroBits64),
216            107 => Some(Self::TrailingZeroBits32),
217            108 => Some(Self::SignExtend8),
218            109 => Some(Self::SignExtend16),
219            110 => Some(Self::ZeroExtend16),
220            111 => Some(Self::ReverseBytes),
221            120 => Some(Self::StoreIndU8),
222            121 => Some(Self::StoreIndU16),
223            122 => Some(Self::StoreIndU32),
224            123 => Some(Self::StoreIndU64),
225            124 => Some(Self::LoadIndU8),
226            125 => Some(Self::LoadIndI8),
227            126 => Some(Self::LoadIndU16),
228            127 => Some(Self::LoadIndI16),
229            128 => Some(Self::LoadIndU32),
230            129 => Some(Self::LoadIndI32),
231            130 => Some(Self::LoadIndU64),
232            131 => Some(Self::AddImm32),
233            132 => Some(Self::AndImm),
234            133 => Some(Self::XorImm),
235            134 => Some(Self::OrImm),
236            135 => Some(Self::MulImm32),
237            136 => Some(Self::SetLtUImm),
238            137 => Some(Self::SetLtSImm),
239            138 => Some(Self::ShloLImm32),
240            139 => Some(Self::ShloRImm32),
241            140 => Some(Self::SharRImm32),
242            141 => Some(Self::NegAddImm32),
243            142 => Some(Self::SetGtUImm),
244            143 => Some(Self::SetGtSImm),
245            144 => Some(Self::ShloLImmAlt32),
246            145 => Some(Self::ShloRImmAlt32),
247            146 => Some(Self::SharRImmAlt32),
248            147 => Some(Self::CmovIzImm),
249            148 => Some(Self::CmovNzImm),
250            149 => Some(Self::AddImm64),
251            150 => Some(Self::MulImm64),
252            151 => Some(Self::ShloLImm64),
253            152 => Some(Self::ShloRImm64),
254            153 => Some(Self::SharRImm64),
255            154 => Some(Self::NegAddImm64),
256            155 => Some(Self::ShloLImmAlt64),
257            156 => Some(Self::ShloRImmAlt64),
258            157 => Some(Self::SharRImmAlt64),
259            158 => Some(Self::RotRImm64),
260            159 => Some(Self::RotRImmAlt64),
261            160 => Some(Self::RotRImm32),
262            161 => Some(Self::RotRImmAlt32),
263            170 => Some(Self::BranchEq),
264            171 => Some(Self::BranchNe),
265            172 => Some(Self::BranchLtU),
266            173 => Some(Self::BranchLtS),
267            174 => Some(Self::BranchGeU),
268            175 => Some(Self::BranchGeS),
269            180 => Some(Self::LoadImmJumpInd),
270            190 => Some(Self::Add32),
271            191 => Some(Self::Sub32),
272            192 => Some(Self::Mul32),
273            193 => Some(Self::DivU32),
274            194 => Some(Self::DivS32),
275            195 => Some(Self::RemU32),
276            196 => Some(Self::RemS32),
277            197 => Some(Self::ShloL32),
278            198 => Some(Self::ShloR32),
279            199 => Some(Self::SharR32),
280            200 => Some(Self::Add64),
281            201 => Some(Self::Sub64),
282            202 => Some(Self::Mul64),
283            203 => Some(Self::DivU64),
284            204 => Some(Self::DivS64),
285            205 => Some(Self::RemU64),
286            206 => Some(Self::RemS64),
287            207 => Some(Self::ShloL64),
288            208 => Some(Self::ShloR64),
289            209 => Some(Self::SharR64),
290            210 => Some(Self::And),
291            211 => Some(Self::Xor),
292            212 => Some(Self::Or),
293            213 => Some(Self::MulUpperSS),
294            214 => Some(Self::MulUpperUU),
295            215 => Some(Self::MulUpperSU),
296            216 => Some(Self::SetLtU),
297            217 => Some(Self::SetLtS),
298            218 => Some(Self::CmovIz),
299            219 => Some(Self::CmovNz),
300            220 => Some(Self::RotL64),
301            221 => Some(Self::RotL32),
302            222 => Some(Self::RotR64),
303            223 => Some(Self::RotR32),
304            224 => Some(Self::AndInv),
305            225 => Some(Self::OrInv),
306            226 => Some(Self::Xnor),
307            227 => Some(Self::Max),
308            228 => Some(Self::MaxU),
309            229 => Some(Self::Min),
310            230 => Some(Self::MinU),
311            _ => None,
312        }
313    }
314
315    #[must_use]
316    pub const fn is_terminating(self) -> bool {
317        matches!(
318            self,
319            Self::Trap
320                | Self::Fallthrough
321                | Self::Jump
322                | Self::LoadImmJump
323                | Self::JumpInd
324                | Self::BranchEqImm
325                | Self::BranchNeImm
326                | Self::BranchLtUImm
327                | Self::BranchLeUImm
328                | Self::BranchGeUImm
329                | Self::BranchGtUImm
330                | Self::BranchLtSImm
331                | Self::BranchLeSImm
332                | Self::BranchGeSImm
333                | Self::BranchGtSImm
334                | Self::BranchEq
335                | Self::BranchNe
336                | Self::BranchLtU
337                | Self::BranchLtS
338                | Self::BranchGeU
339                | Self::BranchGeS
340                | Self::LoadImmJumpInd
341        )
342    }
343}
344
345impl TryFrom<u8> for Opcode {
346    type Error = ();
347
348    fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
349        Self::from_u8(value).ok_or(())
350    }
351}