asmkit/x86/features/CET.rs
1use crate::x86::assembler::*;
2use crate::x86::operands::*;
3use super::super::opcodes::*;
4use crate::core::emitter::*;
5use crate::core::operand::*;
6
7/// A dummy operand that represents no register. Here just for simplicity.
8const NOREG: Operand = Operand::new();
9
10/// `CLRSSBSY` (CLRSSBSY).
11/// Clear busy flag in supervisor shadow stack token reference by m64. Subsequent to marking the shadow stack as not busy the SSP is loaded with value 0.
12///
13///
14/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/CLRSSBSY.html).
15///
16/// Supported operand variants:
17///
18/// ```text
19/// +---+----------+
20/// | # | Operands |
21/// +---+----------+
22/// | 1 | Mem |
23/// +---+----------+
24/// ```
25pub trait ClrssbsyEmitter<A> {
26 fn clrssbsy(&mut self, op0: A);
27}
28
29impl<'a> ClrssbsyEmitter<Mem> for Assembler<'a> {
30 fn clrssbsy(&mut self, op0: Mem) {
31 self.emit(CLRSSBSYM, op0.as_operand(), &NOREG, &NOREG, &NOREG);
32 }
33}
34
35/// `ENDBR32` (ENDBR32).
36/// Terminate an indirect branch in 32 bit and compatibility mode.
37///
38///
39/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/ENDBR32.html).
40///
41/// Supported operand variants:
42///
43/// ```text
44/// +---+----------+
45/// | # | Operands |
46/// +---+----------+
47/// | 1 | (none) |
48/// +---+----------+
49/// ```
50pub trait Endbr32Emitter {
51 fn endbr32(&mut self);
52}
53
54impl<'a> Endbr32Emitter for Assembler<'a> {
55 fn endbr32(&mut self) {
56 self.emit(ENDBR32, &NOREG, &NOREG, &NOREG, &NOREG);
57 }
58}
59
60/// `ENDBR64` (ENDBR64).
61/// Terminate an indirect branch in 64 bit mode.
62///
63///
64/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/ENDBR64.html).
65///
66/// Supported operand variants:
67///
68/// ```text
69/// +---+----------+
70/// | # | Operands |
71/// +---+----------+
72/// | 1 | (none) |
73/// +---+----------+
74/// ```
75pub trait Endbr64Emitter {
76 fn endbr64(&mut self);
77}
78
79impl<'a> Endbr64Emitter for Assembler<'a> {
80 fn endbr64(&mut self) {
81 self.emit(ENDBR64, &NOREG, &NOREG, &NOREG, &NOREG);
82 }
83}
84
85/// `INCSSP`.
86///
87/// Supported operand variants:
88///
89/// ```text
90/// +---+----------+
91/// | # | Operands |
92/// +---+----------+
93/// | 1 | Gpd |
94/// | 2 | Gpq |
95/// +---+----------+
96/// ```
97pub trait IncsspEmitter<A> {
98 fn incssp(&mut self, op0: A);
99}
100
101impl<'a> IncsspEmitter<Gpd> for Assembler<'a> {
102 fn incssp(&mut self, op0: Gpd) {
103 self.emit(INCSSP32R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
104 }
105}
106
107impl<'a> IncsspEmitter<Gpq> for Assembler<'a> {
108 fn incssp(&mut self, op0: Gpq) {
109 self.emit(INCSSP64R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
110 }
111}
112
113/// `RDSSP`.
114///
115/// Supported operand variants:
116///
117/// ```text
118/// +---+----------+
119/// | # | Operands |
120/// +---+----------+
121/// | 1 | Gpd |
122/// | 2 | Gpq |
123/// +---+----------+
124/// ```
125pub trait RdsspEmitter<A> {
126 fn rdssp(&mut self, op0: A);
127}
128
129impl<'a> RdsspEmitter<Gpd> for Assembler<'a> {
130 fn rdssp(&mut self, op0: Gpd) {
131 self.emit(RDSSP32R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
132 }
133}
134
135impl<'a> RdsspEmitter<Gpq> for Assembler<'a> {
136 fn rdssp(&mut self, op0: Gpq) {
137 self.emit(RDSSP64R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
138 }
139}
140
141/// `RSTORSSP`.
142///
143/// Supported operand variants:
144///
145/// ```text
146/// +---+----------+
147/// | # | Operands |
148/// +---+----------+
149/// | 1 | Mem |
150/// +---+----------+
151/// ```
152pub trait RstorsspEmitter<A> {
153 fn rstorssp(&mut self, op0: A);
154}
155
156impl<'a> RstorsspEmitter<Mem> for Assembler<'a> {
157 fn rstorssp(&mut self, op0: Mem) {
158 self.emit(RSTORSSPM, op0.as_operand(), &NOREG, &NOREG, &NOREG);
159 }
160}
161
162/// `SAVEPREVSSP`.
163///
164/// Supported operand variants:
165///
166/// ```text
167/// +---+----------+
168/// | # | Operands |
169/// +---+----------+
170/// | 1 | (none) |
171/// +---+----------+
172/// ```
173pub trait SaveprevsspEmitter {
174 fn saveprevssp(&mut self);
175}
176
177impl<'a> SaveprevsspEmitter for Assembler<'a> {
178 fn saveprevssp(&mut self) {
179 self.emit(SAVEPREVSSP, &NOREG, &NOREG, &NOREG, &NOREG);
180 }
181}
182
183/// `SETSSBSY` (SETSSBSY).
184/// The SETSSBSY instruction verifies the presence of a non-busy supervisor shadow stack token at the address in the IA32_PL0_SSP MSR and marks it busy. Following successful execution of the instruction, the SSP is set to the value of the IA32_PL0_SSP MSR.
185///
186///
187/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/SETSSBSY.html).
188///
189/// Supported operand variants:
190///
191/// ```text
192/// +---+----------+
193/// | # | Operands |
194/// +---+----------+
195/// | 1 | (none) |
196/// +---+----------+
197/// ```
198pub trait SetssbsyEmitter {
199 fn setssbsy(&mut self);
200}
201
202impl<'a> SetssbsyEmitter for Assembler<'a> {
203 fn setssbsy(&mut self) {
204 self.emit(SETSSBSY, &NOREG, &NOREG, &NOREG, &NOREG);
205 }
206}
207
208/// `WRSS`.
209///
210/// Supported operand variants:
211///
212/// ```text
213/// +---+----------+
214/// | # | Operands |
215/// +---+----------+
216/// | 1 | Mem, Gpd |
217/// | 2 | Mem, Gpq |
218/// +---+----------+
219/// ```
220pub trait WrssEmitter<A, B> {
221 fn wrss(&mut self, op0: A, op1: B);
222}
223
224impl<'a> WrssEmitter<Mem, Gpd> for Assembler<'a> {
225 fn wrss(&mut self, op0: Mem, op1: Gpd) {
226 self.emit(WRSS32MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
227 }
228}
229
230impl<'a> WrssEmitter<Mem, Gpq> for Assembler<'a> {
231 fn wrss(&mut self, op0: Mem, op1: Gpq) {
232 self.emit(WRSS64MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
233 }
234}
235
236/// `WRUSS`.
237///
238/// Supported operand variants:
239///
240/// ```text
241/// +---+----------+
242/// | # | Operands |
243/// +---+----------+
244/// | 1 | Mem, Gpd |
245/// | 2 | Mem, Gpq |
246/// +---+----------+
247/// ```
248pub trait WrussEmitter<A, B> {
249 fn wruss(&mut self, op0: A, op1: B);
250}
251
252impl<'a> WrussEmitter<Mem, Gpd> for Assembler<'a> {
253 fn wruss(&mut self, op0: Mem, op1: Gpd) {
254 self.emit(WRUSS32MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
255 }
256}
257
258impl<'a> WrussEmitter<Mem, Gpq> for Assembler<'a> {
259 fn wruss(&mut self, op0: Mem, op1: Gpq) {
260 self.emit(WRUSS64MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
261 }
262}
263
264
265impl<'a> Assembler<'a> {
266 /// `CLRSSBSY` (CLRSSBSY).
267 /// Clear busy flag in supervisor shadow stack token reference by m64. Subsequent to marking the shadow stack as not busy the SSP is loaded with value 0.
268 ///
269 ///
270 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/CLRSSBSY.html).
271 ///
272 /// Supported operand variants:
273 ///
274 /// ```text
275 /// +---+----------+
276 /// | # | Operands |
277 /// +---+----------+
278 /// | 1 | Mem |
279 /// +---+----------+
280 /// ```
281 #[inline]
282 pub fn clrssbsy<A>(&mut self, op0: A)
283 where Assembler<'a>: ClrssbsyEmitter<A> {
284 <Self as ClrssbsyEmitter<A>>::clrssbsy(self, op0);
285 }
286 /// `ENDBR32` (ENDBR32).
287 /// Terminate an indirect branch in 32 bit and compatibility mode.
288 ///
289 ///
290 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/ENDBR32.html).
291 ///
292 /// Supported operand variants:
293 ///
294 /// ```text
295 /// +---+----------+
296 /// | # | Operands |
297 /// +---+----------+
298 /// | 1 | (none) |
299 /// +---+----------+
300 /// ```
301 #[inline]
302 pub fn endbr32(&mut self)
303 where Assembler<'a>: Endbr32Emitter {
304 <Self as Endbr32Emitter>::endbr32(self);
305 }
306 /// `ENDBR64` (ENDBR64).
307 /// Terminate an indirect branch in 64 bit mode.
308 ///
309 ///
310 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/ENDBR64.html).
311 ///
312 /// Supported operand variants:
313 ///
314 /// ```text
315 /// +---+----------+
316 /// | # | Operands |
317 /// +---+----------+
318 /// | 1 | (none) |
319 /// +---+----------+
320 /// ```
321 #[inline]
322 pub fn endbr64(&mut self)
323 where Assembler<'a>: Endbr64Emitter {
324 <Self as Endbr64Emitter>::endbr64(self);
325 }
326 /// `INCSSP`.
327 ///
328 /// Supported operand variants:
329 ///
330 /// ```text
331 /// +---+----------+
332 /// | # | Operands |
333 /// +---+----------+
334 /// | 1 | Gpd |
335 /// | 2 | Gpq |
336 /// +---+----------+
337 /// ```
338 #[inline]
339 pub fn incssp<A>(&mut self, op0: A)
340 where Assembler<'a>: IncsspEmitter<A> {
341 <Self as IncsspEmitter<A>>::incssp(self, op0);
342 }
343 /// `RDSSP`.
344 ///
345 /// Supported operand variants:
346 ///
347 /// ```text
348 /// +---+----------+
349 /// | # | Operands |
350 /// +---+----------+
351 /// | 1 | Gpd |
352 /// | 2 | Gpq |
353 /// +---+----------+
354 /// ```
355 #[inline]
356 pub fn rdssp<A>(&mut self, op0: A)
357 where Assembler<'a>: RdsspEmitter<A> {
358 <Self as RdsspEmitter<A>>::rdssp(self, op0);
359 }
360 /// `RSTORSSP`.
361 ///
362 /// Supported operand variants:
363 ///
364 /// ```text
365 /// +---+----------+
366 /// | # | Operands |
367 /// +---+----------+
368 /// | 1 | Mem |
369 /// +---+----------+
370 /// ```
371 #[inline]
372 pub fn rstorssp<A>(&mut self, op0: A)
373 where Assembler<'a>: RstorsspEmitter<A> {
374 <Self as RstorsspEmitter<A>>::rstorssp(self, op0);
375 }
376 /// `SAVEPREVSSP`.
377 ///
378 /// Supported operand variants:
379 ///
380 /// ```text
381 /// +---+----------+
382 /// | # | Operands |
383 /// +---+----------+
384 /// | 1 | (none) |
385 /// +---+----------+
386 /// ```
387 #[inline]
388 pub fn saveprevssp(&mut self)
389 where Assembler<'a>: SaveprevsspEmitter {
390 <Self as SaveprevsspEmitter>::saveprevssp(self);
391 }
392 /// `SETSSBSY` (SETSSBSY).
393 /// The SETSSBSY instruction verifies the presence of a non-busy supervisor shadow stack token at the address in the IA32_PL0_SSP MSR and marks it busy. Following successful execution of the instruction, the SSP is set to the value of the IA32_PL0_SSP MSR.
394 ///
395 ///
396 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/SETSSBSY.html).
397 ///
398 /// Supported operand variants:
399 ///
400 /// ```text
401 /// +---+----------+
402 /// | # | Operands |
403 /// +---+----------+
404 /// | 1 | (none) |
405 /// +---+----------+
406 /// ```
407 #[inline]
408 pub fn setssbsy(&mut self)
409 where Assembler<'a>: SetssbsyEmitter {
410 <Self as SetssbsyEmitter>::setssbsy(self);
411 }
412 /// `WRSS`.
413 ///
414 /// Supported operand variants:
415 ///
416 /// ```text
417 /// +---+----------+
418 /// | # | Operands |
419 /// +---+----------+
420 /// | 1 | Mem, Gpd |
421 /// | 2 | Mem, Gpq |
422 /// +---+----------+
423 /// ```
424 #[inline]
425 pub fn wrss<A, B>(&mut self, op0: A, op1: B)
426 where Assembler<'a>: WrssEmitter<A, B> {
427 <Self as WrssEmitter<A, B>>::wrss(self, op0, op1);
428 }
429 /// `WRUSS`.
430 ///
431 /// Supported operand variants:
432 ///
433 /// ```text
434 /// +---+----------+
435 /// | # | Operands |
436 /// +---+----------+
437 /// | 1 | Mem, Gpd |
438 /// | 2 | Mem, Gpq |
439 /// +---+----------+
440 /// ```
441 #[inline]
442 pub fn wruss<A, B>(&mut self, op0: A, op1: B)
443 where Assembler<'a>: WrussEmitter<A, B> {
444 <Self as WrussEmitter<A, B>>::wruss(self, op0, op1);
445 }
446}