Skip to main content

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}