Skip to main content

asmkit/x86/features/
486.rs

1use super::super::opcodes::*;
2use crate::core::emitter::*;
3use crate::core::operand::*;
4use crate::x86::assembler::*;
5use crate::x86::operands::*;
6
7/// A dummy operand that represents no register. Here just for simplicity.
8const NOREG: Operand = Operand::new();
9
10/// `BSWAP`.
11///
12/// Supported operand variants:
13///
14/// ```text
15/// +---+----------+
16/// | # | Operands |
17/// +---+----------+
18/// | 1 | Gpd      |
19/// | 2 | Gpq      |
20/// | 3 | Gpw      |
21/// +---+----------+
22/// ```
23pub trait BswapEmitter<A> {
24    fn bswap(&mut self, op0: A);
25}
26
27impl<'a> BswapEmitter<Gpw> for Assembler<'a> {
28    fn bswap(&mut self, op0: Gpw) {
29        self.emit(BSWAP16R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
30    }
31}
32
33impl<'a> BswapEmitter<Gpd> for Assembler<'a> {
34    fn bswap(&mut self, op0: Gpd) {
35        self.emit(BSWAP32R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
36    }
37}
38
39impl<'a> BswapEmitter<Gpq> for Assembler<'a> {
40    fn bswap(&mut self, op0: Gpq) {
41        self.emit(BSWAP64R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
42    }
43}
44
45/// `CMPXCHG`.
46///
47/// Supported operand variants:
48///
49/// ```text
50/// +---+--------------+
51/// | # | Operands     |
52/// +---+--------------+
53/// | 1 | GpbLo, GpbLo |
54/// | 2 | Gpd, Gpd     |
55/// | 3 | Gpq, Gpq     |
56/// | 4 | Gpw, Gpw     |
57/// | 5 | Mem, GpbLo   |
58/// | 6 | Mem, Gpd     |
59/// | 7 | Mem, Gpq     |
60/// | 8 | Mem, Gpw     |
61/// +---+--------------+
62/// ```
63pub trait CmpxchgEmitter<A, B> {
64    fn cmpxchg(&mut self, op0: A, op1: B);
65}
66
67impl<'a> CmpxchgEmitter<GpbLo, GpbLo> for Assembler<'a> {
68    fn cmpxchg(&mut self, op0: GpbLo, op1: GpbLo) {
69        self.emit(
70            CMPXCHG8RR,
71            op0.as_operand(),
72            op1.as_operand(),
73            &NOREG,
74            &NOREG,
75        );
76    }
77}
78
79impl<'a> CmpxchgEmitter<Mem, GpbLo> for Assembler<'a> {
80    fn cmpxchg(&mut self, op0: Mem, op1: GpbLo) {
81        self.emit(
82            CMPXCHG8MR,
83            op0.as_operand(),
84            op1.as_operand(),
85            &NOREG,
86            &NOREG,
87        );
88    }
89}
90
91impl<'a> CmpxchgEmitter<Gpw, Gpw> for Assembler<'a> {
92    fn cmpxchg(&mut self, op0: Gpw, op1: Gpw) {
93        self.emit(
94            CMPXCHG16RR,
95            op0.as_operand(),
96            op1.as_operand(),
97            &NOREG,
98            &NOREG,
99        );
100    }
101}
102
103impl<'a> CmpxchgEmitter<Mem, Gpw> for Assembler<'a> {
104    fn cmpxchg(&mut self, op0: Mem, op1: Gpw) {
105        self.emit(
106            CMPXCHG16MR,
107            op0.as_operand(),
108            op1.as_operand(),
109            &NOREG,
110            &NOREG,
111        );
112    }
113}
114
115impl<'a> CmpxchgEmitter<Gpd, Gpd> for Assembler<'a> {
116    fn cmpxchg(&mut self, op0: Gpd, op1: Gpd) {
117        self.emit(
118            CMPXCHG32RR,
119            op0.as_operand(),
120            op1.as_operand(),
121            &NOREG,
122            &NOREG,
123        );
124    }
125}
126
127impl<'a> CmpxchgEmitter<Mem, Gpd> for Assembler<'a> {
128    fn cmpxchg(&mut self, op0: Mem, op1: Gpd) {
129        self.emit(
130            CMPXCHG32MR,
131            op0.as_operand(),
132            op1.as_operand(),
133            &NOREG,
134            &NOREG,
135        );
136    }
137}
138
139impl<'a> CmpxchgEmitter<Gpq, Gpq> for Assembler<'a> {
140    fn cmpxchg(&mut self, op0: Gpq, op1: Gpq) {
141        self.emit(
142            CMPXCHG64RR,
143            op0.as_operand(),
144            op1.as_operand(),
145            &NOREG,
146            &NOREG,
147        );
148    }
149}
150
151impl<'a> CmpxchgEmitter<Mem, Gpq> for Assembler<'a> {
152    fn cmpxchg(&mut self, op0: Mem, op1: Gpq) {
153        self.emit(
154            CMPXCHG64MR,
155            op0.as_operand(),
156            op1.as_operand(),
157            &NOREG,
158            &NOREG,
159        );
160    }
161}
162
163/// `INVD`.
164///
165/// Supported operand variants:
166///
167/// ```text
168/// +---+----------+
169/// | # | Operands |
170/// +---+----------+
171/// | 1 | (none)   |
172/// +---+----------+
173/// ```
174pub trait InvdEmitter {
175    fn invd(&mut self);
176}
177
178impl<'a> InvdEmitter for Assembler<'a> {
179    fn invd(&mut self) {
180        self.emit(INVD, &NOREG, &NOREG, &NOREG, &NOREG);
181    }
182}
183
184/// `INVLPG`.
185///
186/// Supported operand variants:
187///
188/// ```text
189/// +---+----------+
190/// | # | Operands |
191/// +---+----------+
192/// | 1 | Mem      |
193/// +---+----------+
194/// ```
195pub trait InvlpgEmitter<A> {
196    fn invlpg(&mut self, op0: A);
197}
198
199impl<'a> InvlpgEmitter<Mem> for Assembler<'a> {
200    fn invlpg(&mut self, op0: Mem) {
201        self.emit(INVLPG8M, op0.as_operand(), &NOREG, &NOREG, &NOREG);
202    }
203}
204
205/// `WBINVD`.
206///
207/// Supported operand variants:
208///
209/// ```text
210/// +---+----------+
211/// | # | Operands |
212/// +---+----------+
213/// | 1 | (none)   |
214/// +---+----------+
215/// ```
216pub trait WbinvdEmitter {
217    fn wbinvd(&mut self);
218}
219
220impl<'a> WbinvdEmitter for Assembler<'a> {
221    fn wbinvd(&mut self) {
222        self.emit(WBINVD, &NOREG, &NOREG, &NOREG, &NOREG);
223    }
224}
225
226/// `XADD`.
227///
228/// Supported operand variants:
229///
230/// ```text
231/// +---+--------------+
232/// | # | Operands     |
233/// +---+--------------+
234/// | 1 | GpbLo, GpbLo |
235/// | 2 | Gpd, Gpd     |
236/// | 3 | Gpq, Gpq     |
237/// | 4 | Gpw, Gpw     |
238/// | 5 | Mem, GpbLo   |
239/// | 6 | Mem, Gpd     |
240/// | 7 | Mem, Gpq     |
241/// | 8 | Mem, Gpw     |
242/// +---+--------------+
243/// ```
244pub trait XaddEmitter<A, B> {
245    fn xadd(&mut self, op0: A, op1: B);
246}
247
248impl<'a> XaddEmitter<GpbLo, GpbLo> for Assembler<'a> {
249    fn xadd(&mut self, op0: GpbLo, op1: GpbLo) {
250        self.emit(XADD8RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
251    }
252}
253
254impl<'a> XaddEmitter<Mem, GpbLo> for Assembler<'a> {
255    fn xadd(&mut self, op0: Mem, op1: GpbLo) {
256        self.emit(XADD8MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
257    }
258}
259
260impl<'a> XaddEmitter<Gpw, Gpw> for Assembler<'a> {
261    fn xadd(&mut self, op0: Gpw, op1: Gpw) {
262        self.emit(XADD16RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
263    }
264}
265
266impl<'a> XaddEmitter<Mem, Gpw> for Assembler<'a> {
267    fn xadd(&mut self, op0: Mem, op1: Gpw) {
268        self.emit(XADD16MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
269    }
270}
271
272impl<'a> XaddEmitter<Gpd, Gpd> for Assembler<'a> {
273    fn xadd(&mut self, op0: Gpd, op1: Gpd) {
274        self.emit(XADD32RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
275    }
276}
277
278impl<'a> XaddEmitter<Mem, Gpd> for Assembler<'a> {
279    fn xadd(&mut self, op0: Mem, op1: Gpd) {
280        self.emit(XADD32MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
281    }
282}
283
284impl<'a> XaddEmitter<Gpq, Gpq> for Assembler<'a> {
285    fn xadd(&mut self, op0: Gpq, op1: Gpq) {
286        self.emit(XADD64RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
287    }
288}
289
290impl<'a> XaddEmitter<Mem, Gpq> for Assembler<'a> {
291    fn xadd(&mut self, op0: Mem, op1: Gpq) {
292        self.emit(XADD64MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
293    }
294}
295
296impl<'a> Assembler<'a> {
297    /// `BSWAP`.
298    ///
299    /// Supported operand variants:
300    ///
301    /// ```text
302    /// +---+----------+
303    /// | # | Operands |
304    /// +---+----------+
305    /// | 1 | Gpd      |
306    /// | 2 | Gpq      |
307    /// | 3 | Gpw      |
308    /// +---+----------+
309    /// ```
310    #[inline]
311    pub fn bswap<A>(&mut self, op0: A)
312    where
313        Assembler<'a>: BswapEmitter<A>,
314    {
315        <Self as BswapEmitter<A>>::bswap(self, op0);
316    }
317    /// `CMPXCHG`.
318    ///
319    /// Supported operand variants:
320    ///
321    /// ```text
322    /// +---+--------------+
323    /// | # | Operands     |
324    /// +---+--------------+
325    /// | 1 | GpbLo, GpbLo |
326    /// | 2 | Gpd, Gpd     |
327    /// | 3 | Gpq, Gpq     |
328    /// | 4 | Gpw, Gpw     |
329    /// | 5 | Mem, GpbLo   |
330    /// | 6 | Mem, Gpd     |
331    /// | 7 | Mem, Gpq     |
332    /// | 8 | Mem, Gpw     |
333    /// +---+--------------+
334    /// ```
335    #[inline]
336    pub fn cmpxchg<A, B>(&mut self, op0: A, op1: B)
337    where
338        Assembler<'a>: CmpxchgEmitter<A, B>,
339    {
340        <Self as CmpxchgEmitter<A, B>>::cmpxchg(self, op0, op1);
341    }
342    /// `INVD`.
343    ///
344    /// Supported operand variants:
345    ///
346    /// ```text
347    /// +---+----------+
348    /// | # | Operands |
349    /// +---+----------+
350    /// | 1 | (none)   |
351    /// +---+----------+
352    /// ```
353    #[inline]
354    pub fn invd(&mut self)
355    where
356        Assembler<'a>: InvdEmitter,
357    {
358        <Self as InvdEmitter>::invd(self);
359    }
360    /// `INVLPG`.
361    ///
362    /// Supported operand variants:
363    ///
364    /// ```text
365    /// +---+----------+
366    /// | # | Operands |
367    /// +---+----------+
368    /// | 1 | Mem      |
369    /// +---+----------+
370    /// ```
371    #[inline]
372    pub fn invlpg<A>(&mut self, op0: A)
373    where
374        Assembler<'a>: InvlpgEmitter<A>,
375    {
376        <Self as InvlpgEmitter<A>>::invlpg(self, op0);
377    }
378    /// `WBINVD`.
379    ///
380    /// Supported operand variants:
381    ///
382    /// ```text
383    /// +---+----------+
384    /// | # | Operands |
385    /// +---+----------+
386    /// | 1 | (none)   |
387    /// +---+----------+
388    /// ```
389    #[inline]
390    pub fn wbinvd(&mut self)
391    where
392        Assembler<'a>: WbinvdEmitter,
393    {
394        <Self as WbinvdEmitter>::wbinvd(self);
395    }
396    /// `XADD`.
397    ///
398    /// Supported operand variants:
399    ///
400    /// ```text
401    /// +---+--------------+
402    /// | # | Operands     |
403    /// +---+--------------+
404    /// | 1 | GpbLo, GpbLo |
405    /// | 2 | Gpd, Gpd     |
406    /// | 3 | Gpq, Gpq     |
407    /// | 4 | Gpw, Gpw     |
408    /// | 5 | Mem, GpbLo   |
409    /// | 6 | Mem, Gpd     |
410    /// | 7 | Mem, Gpq     |
411    /// | 8 | Mem, Gpw     |
412    /// +---+--------------+
413    /// ```
414    #[inline]
415    pub fn xadd<A, B>(&mut self, op0: A, op1: B)
416    where
417        Assembler<'a>: XaddEmitter<A, B>,
418    {
419        <Self as XaddEmitter<A, B>>::xadd(self, op0, op1);
420    }
421}