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}