Skip to main content

asmkit/x86/features/
486.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/// `BSWAP` (BSWAP). 
11/// Reverses the byte order of a 32-bit or 64-bit (destination) register. This instruction is provided for converting little-endian values to big-endian format and vice versa. To swap bytes in a word value (16-bit register), use the XCHG instruction. When the BSWAP instruction references a 16-bit register, the result is undefined.
12///
13///
14/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BSWAP.html).
15///
16/// Supported operand variants:
17///
18/// ```text
19/// +---+----------+
20/// | # | Operands |
21/// +---+----------+
22/// | 1 | Gpd      |
23/// | 2 | Gpq      |
24/// | 3 | Gpw      |
25/// +---+----------+
26/// ```
27pub trait BswapEmitter<A> {
28    fn bswap(&mut self, op0: A);
29}
30
31impl<'a> BswapEmitter<Gpw> for Assembler<'a> {
32    fn bswap(&mut self, op0: Gpw) {
33        self.emit(BSWAP16R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
34    }
35}
36
37impl<'a> BswapEmitter<Gpd> for Assembler<'a> {
38    fn bswap(&mut self, op0: Gpd) {
39        self.emit(BSWAP32R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
40    }
41}
42
43impl<'a> BswapEmitter<Gpq> for Assembler<'a> {
44    fn bswap(&mut self, op0: Gpq) {
45        self.emit(BSWAP64R, op0.as_operand(), &NOREG, &NOREG, &NOREG);
46    }
47}
48
49/// `CMPXCHG` (CMPXCHG). 
50/// Compares the value in the AL, AX, EAX, or RAX register with the first operand (destination operand). If the two values are equal, the second operand (source operand) is loaded into the destination operand. Otherwise, the destination operand is loaded into the AL, AX, EAX or RAX register. RAX register is available only in 64-bit mode.
51///
52///
53/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/CMPXCHG.html).
54///
55/// Supported operand variants:
56///
57/// ```text
58/// +---+--------------+
59/// | # | Operands     |
60/// +---+--------------+
61/// | 1 | GpbLo, GpbLo |
62/// | 2 | Gpd, Gpd     |
63/// | 3 | Gpq, Gpq     |
64/// | 4 | Gpw, Gpw     |
65/// | 5 | Mem, GpbLo   |
66/// | 6 | Mem, Gpd     |
67/// | 7 | Mem, Gpq     |
68/// | 8 | Mem, Gpw     |
69/// +---+--------------+
70/// ```
71pub trait CmpxchgEmitter<A, B> {
72    fn cmpxchg(&mut self, op0: A, op1: B);
73}
74
75impl<'a> CmpxchgEmitter<GpbLo, GpbLo> for Assembler<'a> {
76    fn cmpxchg(&mut self, op0: GpbLo, op1: GpbLo) {
77        self.emit(CMPXCHG8RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
78    }
79}
80
81impl<'a> CmpxchgEmitter<Mem, GpbLo> for Assembler<'a> {
82    fn cmpxchg(&mut self, op0: Mem, op1: GpbLo) {
83        self.emit(CMPXCHG8MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
84    }
85}
86
87impl<'a> CmpxchgEmitter<Gpw, Gpw> for Assembler<'a> {
88    fn cmpxchg(&mut self, op0: Gpw, op1: Gpw) {
89        self.emit(CMPXCHG16RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
90    }
91}
92
93impl<'a> CmpxchgEmitter<Mem, Gpw> for Assembler<'a> {
94    fn cmpxchg(&mut self, op0: Mem, op1: Gpw) {
95        self.emit(CMPXCHG16MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
96    }
97}
98
99impl<'a> CmpxchgEmitter<Gpd, Gpd> for Assembler<'a> {
100    fn cmpxchg(&mut self, op0: Gpd, op1: Gpd) {
101        self.emit(CMPXCHG32RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
102    }
103}
104
105impl<'a> CmpxchgEmitter<Mem, Gpd> for Assembler<'a> {
106    fn cmpxchg(&mut self, op0: Mem, op1: Gpd) {
107        self.emit(CMPXCHG32MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
108    }
109}
110
111impl<'a> CmpxchgEmitter<Gpq, Gpq> for Assembler<'a> {
112    fn cmpxchg(&mut self, op0: Gpq, op1: Gpq) {
113        self.emit(CMPXCHG64RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
114    }
115}
116
117impl<'a> CmpxchgEmitter<Mem, Gpq> for Assembler<'a> {
118    fn cmpxchg(&mut self, op0: Mem, op1: Gpq) {
119        self.emit(CMPXCHG64MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
120    }
121}
122
123/// `INVD` (INVD). 
124/// Invalidates (flushes) the processor’s internal caches and issues a special-function bus cycle that directs external caches to also flush themselves. Data held in internal caches is not written back to main memory.
125///
126///
127/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/INVD.html).
128///
129/// Supported operand variants:
130///
131/// ```text
132/// +---+----------+
133/// | # | Operands |
134/// +---+----------+
135/// | 1 | (none)   |
136/// +---+----------+
137/// ```
138pub trait InvdEmitter {
139    fn invd(&mut self);
140}
141
142impl<'a> InvdEmitter for Assembler<'a> {
143    fn invd(&mut self) {
144        self.emit(INVD, &NOREG, &NOREG, &NOREG, &NOREG);
145    }
146}
147
148/// `INVLPG`.
149///
150/// Supported operand variants:
151///
152/// ```text
153/// +---+----------+
154/// | # | Operands |
155/// +---+----------+
156/// | 1 | Mem      |
157/// +---+----------+
158/// ```
159pub trait InvlpgEmitter<A> {
160    fn invlpg(&mut self, op0: A);
161}
162
163impl<'a> InvlpgEmitter<Mem> for Assembler<'a> {
164    fn invlpg(&mut self, op0: Mem) {
165        self.emit(INVLPG8M, op0.as_operand(), &NOREG, &NOREG, &NOREG);
166    }
167}
168
169/// `WBINVD` (WBINVD). 
170/// Writes back all modified cache lines in the processor’s internal cache to main memory and invalidates (flushes) the internal caches. The instruction then issues a special-function bus cycle that directs external caches to also write back modified data and another bus cycle to indicate that the external caches should be invalidated.
171///
172///
173/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/WBINVD.html).
174///
175/// Supported operand variants:
176///
177/// ```text
178/// +---+----------+
179/// | # | Operands |
180/// +---+----------+
181/// | 1 | (none)   |
182/// +---+----------+
183/// ```
184pub trait WbinvdEmitter {
185    fn wbinvd(&mut self);
186}
187
188impl<'a> WbinvdEmitter for Assembler<'a> {
189    fn wbinvd(&mut self) {
190        self.emit(WBINVD, &NOREG, &NOREG, &NOREG, &NOREG);
191    }
192}
193
194/// `XADD` (XADD). 
195/// Exchanges the first operand (destination operand) with the second operand (source operand), then loads the sum of the two values into the destination operand. The destination operand can be a register or a memory location; the source operand is a register.
196///
197///
198/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/XADD.html).
199///
200/// Supported operand variants:
201///
202/// ```text
203/// +---+--------------+
204/// | # | Operands     |
205/// +---+--------------+
206/// | 1 | GpbLo, GpbLo |
207/// | 2 | Gpd, Gpd     |
208/// | 3 | Gpq, Gpq     |
209/// | 4 | Gpw, Gpw     |
210/// | 5 | Mem, GpbLo   |
211/// | 6 | Mem, Gpd     |
212/// | 7 | Mem, Gpq     |
213/// | 8 | Mem, Gpw     |
214/// +---+--------------+
215/// ```
216pub trait XaddEmitter<A, B> {
217    fn xadd(&mut self, op0: A, op1: B);
218}
219
220impl<'a> XaddEmitter<GpbLo, GpbLo> for Assembler<'a> {
221    fn xadd(&mut self, op0: GpbLo, op1: GpbLo) {
222        self.emit(XADD8RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
223    }
224}
225
226impl<'a> XaddEmitter<Mem, GpbLo> for Assembler<'a> {
227    fn xadd(&mut self, op0: Mem, op1: GpbLo) {
228        self.emit(XADD8MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
229    }
230}
231
232impl<'a> XaddEmitter<Gpw, Gpw> for Assembler<'a> {
233    fn xadd(&mut self, op0: Gpw, op1: Gpw) {
234        self.emit(XADD16RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
235    }
236}
237
238impl<'a> XaddEmitter<Mem, Gpw> for Assembler<'a> {
239    fn xadd(&mut self, op0: Mem, op1: Gpw) {
240        self.emit(XADD16MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
241    }
242}
243
244impl<'a> XaddEmitter<Gpd, Gpd> for Assembler<'a> {
245    fn xadd(&mut self, op0: Gpd, op1: Gpd) {
246        self.emit(XADD32RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
247    }
248}
249
250impl<'a> XaddEmitter<Mem, Gpd> for Assembler<'a> {
251    fn xadd(&mut self, op0: Mem, op1: Gpd) {
252        self.emit(XADD32MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
253    }
254}
255
256impl<'a> XaddEmitter<Gpq, Gpq> for Assembler<'a> {
257    fn xadd(&mut self, op0: Gpq, op1: Gpq) {
258        self.emit(XADD64RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
259    }
260}
261
262impl<'a> XaddEmitter<Mem, Gpq> for Assembler<'a> {
263    fn xadd(&mut self, op0: Mem, op1: Gpq) {
264        self.emit(XADD64MR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
265    }
266}
267
268
269impl<'a> Assembler<'a> {
270    /// `BSWAP` (BSWAP). 
271    /// Reverses the byte order of a 32-bit or 64-bit (destination) register. This instruction is provided for converting little-endian values to big-endian format and vice versa. To swap bytes in a word value (16-bit register), use the XCHG instruction. When the BSWAP instruction references a 16-bit register, the result is undefined.
272    ///
273    ///
274    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BSWAP.html).
275    ///
276    /// Supported operand variants:
277    ///
278    /// ```text
279    /// +---+----------+
280    /// | # | Operands |
281    /// +---+----------+
282    /// | 1 | Gpd      |
283    /// | 2 | Gpq      |
284    /// | 3 | Gpw      |
285    /// +---+----------+
286    /// ```
287    #[inline]
288    pub fn bswap<A>(&mut self, op0: A)
289    where Assembler<'a>: BswapEmitter<A> {
290        <Self as BswapEmitter<A>>::bswap(self, op0);
291    }
292    /// `CMPXCHG` (CMPXCHG). 
293    /// Compares the value in the AL, AX, EAX, or RAX register with the first operand (destination operand). If the two values are equal, the second operand (source operand) is loaded into the destination operand. Otherwise, the destination operand is loaded into the AL, AX, EAX or RAX register. RAX register is available only in 64-bit mode.
294    ///
295    ///
296    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/CMPXCHG.html).
297    ///
298    /// Supported operand variants:
299    ///
300    /// ```text
301    /// +---+--------------+
302    /// | # | Operands     |
303    /// +---+--------------+
304    /// | 1 | GpbLo, GpbLo |
305    /// | 2 | Gpd, Gpd     |
306    /// | 3 | Gpq, Gpq     |
307    /// | 4 | Gpw, Gpw     |
308    /// | 5 | Mem, GpbLo   |
309    /// | 6 | Mem, Gpd     |
310    /// | 7 | Mem, Gpq     |
311    /// | 8 | Mem, Gpw     |
312    /// +---+--------------+
313    /// ```
314    #[inline]
315    pub fn cmpxchg<A, B>(&mut self, op0: A, op1: B)
316    where Assembler<'a>: CmpxchgEmitter<A, B> {
317        <Self as CmpxchgEmitter<A, B>>::cmpxchg(self, op0, op1);
318    }
319    /// `INVD` (INVD). 
320    /// Invalidates (flushes) the processor’s internal caches and issues a special-function bus cycle that directs external caches to also flush themselves. Data held in internal caches is not written back to main memory.
321    ///
322    ///
323    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/INVD.html).
324    ///
325    /// Supported operand variants:
326    ///
327    /// ```text
328    /// +---+----------+
329    /// | # | Operands |
330    /// +---+----------+
331    /// | 1 | (none)   |
332    /// +---+----------+
333    /// ```
334    #[inline]
335    pub fn invd(&mut self)
336    where Assembler<'a>: InvdEmitter {
337        <Self as InvdEmitter>::invd(self);
338    }
339    /// `INVLPG`.
340    ///
341    /// Supported operand variants:
342    ///
343    /// ```text
344    /// +---+----------+
345    /// | # | Operands |
346    /// +---+----------+
347    /// | 1 | Mem      |
348    /// +---+----------+
349    /// ```
350    #[inline]
351    pub fn invlpg<A>(&mut self, op0: A)
352    where Assembler<'a>: InvlpgEmitter<A> {
353        <Self as InvlpgEmitter<A>>::invlpg(self, op0);
354    }
355    /// `WBINVD` (WBINVD). 
356    /// Writes back all modified cache lines in the processor’s internal cache to main memory and invalidates (flushes) the internal caches. The instruction then issues a special-function bus cycle that directs external caches to also write back modified data and another bus cycle to indicate that the external caches should be invalidated.
357    ///
358    ///
359    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/WBINVD.html).
360    ///
361    /// Supported operand variants:
362    ///
363    /// ```text
364    /// +---+----------+
365    /// | # | Operands |
366    /// +---+----------+
367    /// | 1 | (none)   |
368    /// +---+----------+
369    /// ```
370    #[inline]
371    pub fn wbinvd(&mut self)
372    where Assembler<'a>: WbinvdEmitter {
373        <Self as WbinvdEmitter>::wbinvd(self);
374    }
375    /// `XADD` (XADD). 
376    /// Exchanges the first operand (destination operand) with the second operand (source operand), then loads the sum of the two values into the destination operand. The destination operand can be a register or a memory location; the source operand is a register.
377    ///
378    ///
379    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/XADD.html).
380    ///
381    /// Supported operand variants:
382    ///
383    /// ```text
384    /// +---+--------------+
385    /// | # | Operands     |
386    /// +---+--------------+
387    /// | 1 | GpbLo, GpbLo |
388    /// | 2 | Gpd, Gpd     |
389    /// | 3 | Gpq, Gpq     |
390    /// | 4 | Gpw, Gpw     |
391    /// | 5 | Mem, GpbLo   |
392    /// | 6 | Mem, Gpd     |
393    /// | 7 | Mem, Gpq     |
394    /// | 8 | Mem, Gpw     |
395    /// +---+--------------+
396    /// ```
397    #[inline]
398    pub fn xadd<A, B>(&mut self, op0: A, op1: B)
399    where Assembler<'a>: XaddEmitter<A, B> {
400        <Self as XaddEmitter<A, B>>::xadd(self, op0, op1);
401    }
402}