1use crate::cpu::arith::{cmp16, cmp32, cmp8};
13use crate::cpu::cpu::{
14 get_seg, io_port_read16, io_port_read32, io_port_read8, io_port_write16, io_port_write32,
15 io_port_write8, read_reg16, read_reg32, safe_read16, safe_read32s, safe_read8, safe_write16,
16 safe_write32, safe_write8, set_reg_asize, test_privileges_for_io, translate_address_read,
17 translate_address_write_and_can_skip_dirty, writable_or_pagefault, write_reg16, write_reg32,
18 write_reg8, AL, AX, DX, EAX, ECX, EDI, ES, ESI, FLAG_DIRECTION,
19};
20use crate::cpu::global_pointers::{flags, instruction_pointer, previous_ip};
21use crate::cpu::memory;
22use crate::jit;
23use crate::page::Page;
24
25fn count_until_end_of_page(direction: i32, size: i32, addr: u32) -> u32 {
26 (if direction == 1 {
27 (0x1000 - (addr & 0xFFF)) / size as u32
28 }
29 else {
30 (addr & 0xFFF) / size as u32 + 1
31 }) as u32
32}
33
34#[derive(Copy, Clone, PartialEq)]
35enum Instruction {
36 Movs,
37 Lods,
38 Stos,
39 Scas,
40 Cmps,
41 Ins,
42 Outs,
43}
44#[derive(PartialEq)]
45enum Size {
46 B,
47 W,
48 D,
49}
50#[derive(Copy, Clone)]
51enum Rep {
52 None,
53 Z,
54 NZ,
55}
56
57#[inline(always)]
60unsafe fn string_instruction(
61 is_asize_32: bool,
62 ds_or_prefix: i32,
63 instruction: Instruction,
64 size: Size,
65 rep: Rep,
66) {
67 let asize_mask = if is_asize_32 { -1 } else { 0xFFFF };
68
69 let direction = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 };
70
71 let mut count = match rep {
72 Rep::Z | Rep::NZ => {
73 let c = (read_reg32(ECX) & asize_mask) as u32;
74 if c == 0 {
75 return;
76 };
77 c
78 },
79 Rep::None => 0,
80 };
81
82 let es = match instruction {
83 Instruction::Movs
84 | Instruction::Cmps
85 | Instruction::Stos
86 | Instruction::Scas
87 | Instruction::Ins => return_on_pagefault!(get_seg(ES)),
88 _ => 0,
89 };
90 let ds = match instruction {
91 Instruction::Movs
92 | Instruction::Cmps
93 | Instruction::Lods
94 | Instruction::Scas
95 | Instruction::Outs => return_on_pagefault!(get_seg(ds_or_prefix)),
96 _ => 0,
97 };
98
99 let size_bytes = match size {
100 Size::B => 1,
101 Size::W => 2,
102 Size::D => 4,
103 };
104 let size_mask = match size {
105 Size::B => 0xFF,
106 Size::W => 0xFFFF,
107 Size::D => -1,
108 };
109
110 let increment = direction * size_bytes;
111
112 let data = match instruction {
113 Instruction::Stos | Instruction::Scas => read_reg32(EAX),
114 _ => 0,
115 };
116
117 let mut src = match instruction {
118 Instruction::Movs | Instruction::Cmps | Instruction::Lods | Instruction::Outs => {
119 read_reg32(ESI) & asize_mask
120 },
121 _ => 0,
122 };
123 let mut dst = match instruction {
124 Instruction::Movs
125 | Instruction::Cmps
126 | Instruction::Stos
127 | Instruction::Scas
128 | Instruction::Ins => read_reg32(EDI) & asize_mask,
129 _ => 0,
130 };
131
132 let port = match instruction {
133 Instruction::Ins | Instruction::Outs => {
134 let port = read_reg16(DX);
135 if !test_privileges_for_io(port, size_bytes) {
136 return;
137 }
138 port
139 },
140 _ => 0,
141 };
142
143 let is_aligned = (ds + src) & (size_bytes - 1) == 0 && (es + dst) & (size_bytes - 1) == 0;
144
145 let mut rep_fast = (instruction == Instruction::Movs || is_aligned)
147 && is_asize_32 && match rep {
149 Rep::NZ | Rep::Z => true,
150 Rep::None => false,
151 };
152
153 let mut phys_dst = 0;
154 let mut phys_src = 0;
155 let mut skip_dirty_page = false;
156
157 let mut movs_into_svga_lfb = false;
158 let mut movs_reenter_fast_path = false;
159
160 let count_until_end_of_page = if rep_fast {
161 match instruction {
162 Instruction::Movs => {
163 let (addr, skip) =
164 return_on_pagefault!(translate_address_write_and_can_skip_dirty(es + dst));
165 movs_into_svga_lfb = memory::in_svga_lfb(addr);
166 rep_fast = rep_fast && (!memory::in_mapped_range(addr) || movs_into_svga_lfb);
167 phys_dst = addr;
168 skip_dirty_page = skip;
169 },
170 Instruction::Stos | Instruction::Ins => {
171 let (addr, skip) =
172 return_on_pagefault!(translate_address_write_and_can_skip_dirty(es + dst));
173 rep_fast = rep_fast && !memory::in_mapped_range(addr);
174 phys_dst = addr;
175 skip_dirty_page = skip;
176 },
177 Instruction::Cmps | Instruction::Scas => {
178 let addr = return_on_pagefault!(translate_address_read(es + dst));
179 rep_fast = rep_fast && !memory::in_mapped_range(addr);
180 phys_dst = addr;
181 skip_dirty_page = true;
182 },
183 _ => {},
184 };
185
186 match instruction {
187 Instruction::Movs | Instruction::Cmps | Instruction::Lods | Instruction::Outs => {
188 let addr = return_on_pagefault!(translate_address_read(ds + src));
189 rep_fast = rep_fast && !memory::in_mapped_range(addr);
190 phys_src = addr;
191 },
192 _ => {},
193 };
194
195 let count_until_end_of_page = u32::min(
196 count,
197 match instruction {
198 Instruction::Movs | Instruction::Cmps => u32::min(
199 count_until_end_of_page(direction, size_bytes, phys_src),
200 count_until_end_of_page(direction, size_bytes, phys_dst),
201 ),
202 Instruction::Stos | Instruction::Ins | Instruction::Scas => {
203 count_until_end_of_page(direction, size_bytes, phys_dst)
204 },
205 Instruction::Lods | Instruction::Outs => {
206 count_until_end_of_page(direction, size_bytes, phys_src)
207 },
208 },
209 );
210
211 match instruction {
212 Instruction::Movs => {
213 let c = count_until_end_of_page * size_bytes as u32;
214
215 let overlap_interferes = if phys_src < phys_dst {
216 phys_dst - phys_src < c && direction == 1
218 }
219 else if phys_src > phys_dst {
220 phys_src - phys_dst < c && direction == -1
222 }
223 else {
224 false
225 };
226 rep_fast = rep_fast && !overlap_interferes;
227
228 movs_reenter_fast_path = rep_fast;
231 rep_fast = rep_fast
232 && (phys_src & 0xFFF <= 0x1000 - size_bytes as u32)
233 && (phys_dst & 0xFFF <= 0x1000 - size_bytes as u32);
234 },
235 _ => {},
236 }
237
238 count_until_end_of_page
239 }
240 else {
241 0 };
243
244 if rep_fast {
245 dbg_assert!(count_until_end_of_page > 0);
246
247 if !skip_dirty_page {
248 jit::jit_dirty_page(Page::page_of(phys_dst));
249 }
250
251 let mut rep_cmp_finished = false;
252
253 let mut i = 0;
254 while i < count_until_end_of_page {
255 i += 1;
256
257 let src_val = match instruction {
258 Instruction::Movs | Instruction::Cmps | Instruction::Lods | Instruction::Outs => {
259 match size {
260 Size::B => memory::read8_no_mmap_check(phys_src),
261 Size::W => memory::read16_no_mmap_check(phys_src),
262 Size::D => memory::read32_no_mmap_check(phys_src),
263 }
264 },
265 Instruction::Scas | Instruction::Stos => data & size_mask,
266 Instruction::Ins => match size {
267 Size::B => io_port_read8(port),
268 Size::W => io_port_read16(port),
269 Size::D => io_port_read32(port),
270 },
271 };
272
273 let mut dst_val = 0;
274
275 match instruction {
276 Instruction::Cmps | Instruction::Scas => match size {
277 Size::B => dst_val = memory::read8_no_mmap_check(phys_dst),
278 Size::W => dst_val = memory::read16_no_mmap_check(phys_dst),
279 Size::D => dst_val = memory::read32_no_mmap_check(phys_dst),
280 },
281 Instruction::Outs => match size {
282 Size::B => io_port_write8(port, src_val),
283 Size::W => io_port_write16(port, src_val),
284 Size::D => io_port_write32(port, src_val),
285 },
286 Instruction::Lods => match size {
287 Size::B => write_reg8(AL, src_val),
288 Size::W => write_reg16(AX, src_val),
289 Size::D => write_reg32(EAX, src_val),
290 },
291 Instruction::Ins => match size {
292 Size::B => memory::write8_no_mmap_or_dirty_check(phys_dst, src_val),
293 Size::W => memory::write16_no_mmap_or_dirty_check(phys_dst, src_val),
294 Size::D => memory::write32_no_mmap_or_dirty_check(phys_dst, src_val),
295 },
296 Instruction::Movs => {
297 if direction == -1 {
298 phys_src -= (count_until_end_of_page - 1) * size_bytes as u32;
299 phys_dst -= (count_until_end_of_page - 1) * size_bytes as u32;
300 }
301 if movs_into_svga_lfb {
302 memory::memcpy_into_svga_lfb(
303 phys_src,
304 phys_dst,
305 count_until_end_of_page * size_bytes as u32,
306 );
307 }
308 else {
309 memory::memcpy_no_mmap_or_dirty_check(
310 phys_src,
311 phys_dst,
312 count_until_end_of_page * size_bytes as u32,
313 );
314 }
315 i = count_until_end_of_page;
316 break;
317 },
318 Instruction::Stos => match size {
319 Size::B => {
320 if direction == -1 {
321 phys_dst -= count_until_end_of_page - 1
322 }
323 memory::memset_no_mmap_or_dirty_check(
324 phys_dst,
325 src_val as u8,
326 count_until_end_of_page,
327 );
328 i = count_until_end_of_page;
329 break;
330 },
331 Size::W => memory::write16_no_mmap_or_dirty_check(phys_dst, src_val),
332 Size::D => memory::write32_no_mmap_or_dirty_check(phys_dst, src_val),
333 },
334 };
335
336 match instruction {
337 Instruction::Movs
338 | Instruction::Cmps
339 | Instruction::Stos
340 | Instruction::Scas
341 | Instruction::Ins => {
342 phys_dst += increment as u32;
343 },
344 _ => {},
345 }
346 match instruction {
347 Instruction::Movs | Instruction::Cmps | Instruction::Lods | Instruction::Outs => {
348 phys_src += increment as u32;
349 },
350 _ => {},
351 };
352
353 match instruction {
354 Instruction::Scas | Instruction::Cmps => {
355 let rep_cmp = match rep {
356 Rep::Z => src_val == dst_val,
357 Rep::NZ => src_val != dst_val,
358 Rep::None => {
359 dbg_assert!(false);
360 true
361 },
362 };
363 if !rep_cmp || count == i {
364 match size {
365 Size::B => cmp8(src_val, dst_val),
366 Size::W => cmp16(src_val, dst_val),
367 Size::D => cmp32(src_val, dst_val),
368 };
369 rep_cmp_finished = true;
370 break;
371 }
372 },
373 _ => {},
374 }
375 }
376
377 dbg_assert!(i <= count);
378 count -= i;
379
380 if !rep_cmp_finished && count != 0 {
381 *instruction_pointer = *previous_ip;
383 }
384
385 src += i as i32 * increment;
386 dst += i as i32 * increment;
387 }
388 else {
389 loop {
390 match instruction {
391 Instruction::Ins => {
392 break_on_pagefault!(writable_or_pagefault(es + dst, size_bytes));
395 },
396 _ => {},
397 };
398 let src_val = match instruction {
399 Instruction::Movs | Instruction::Cmps | Instruction::Lods | Instruction::Outs => {
400 break_on_pagefault!(match size {
401 Size::B => safe_read8(ds + src),
402 Size::W => safe_read16(ds + src),
403 Size::D => safe_read32s(ds + src),
404 })
405 },
406 Instruction::Scas | Instruction::Stos => data & size_mask,
407 Instruction::Ins => match size {
408 Size::B => io_port_read8(port),
409 Size::W => io_port_read16(port),
410 Size::D => io_port_read32(port),
411 },
412 };
413
414 let mut dst_val = 0;
415
416 match instruction {
417 Instruction::Cmps | Instruction::Scas => match size {
418 Size::B => dst_val = break_on_pagefault!(safe_read8(es + dst)),
419 Size::W => dst_val = break_on_pagefault!(safe_read16(es + dst)),
420 Size::D => dst_val = break_on_pagefault!(safe_read32s(es + dst)),
421 },
422 Instruction::Outs => match size {
423 Size::B => io_port_write8(port, src_val),
424 Size::W => io_port_write16(port, src_val),
425 Size::D => io_port_write32(port, src_val),
426 },
427 Instruction::Lods => match size {
428 Size::B => write_reg8(AL, src_val),
429 Size::W => write_reg16(AX, src_val),
430 Size::D => write_reg32(EAX, src_val),
431 },
432 Instruction::Movs | Instruction::Stos | Instruction::Ins => match size {
433 Size::B => break_on_pagefault!(safe_write8(es + dst, src_val)),
434 Size::W => break_on_pagefault!(safe_write16(es + dst, src_val)),
435 Size::D => break_on_pagefault!(safe_write32(es + dst, src_val)),
436 },
437 };
438
439 match instruction {
440 Instruction::Movs
441 | Instruction::Cmps
442 | Instruction::Stos
443 | Instruction::Scas
444 | Instruction::Ins => dst = dst + increment & asize_mask,
445 _ => {},
446 }
447 match instruction {
448 Instruction::Movs | Instruction::Cmps | Instruction::Lods | Instruction::Outs => {
449 src = src + increment & asize_mask
450 },
451 _ => {},
452 };
453
454 if count == 0 {
457 break;
458 }
459 count -= 1;
460
461 let finished = match rep {
462 Rep::Z | Rep::NZ => match (rep, instruction) {
463 (Rep::Z, Instruction::Cmps) => src_val != dst_val || count == 0,
464 (Rep::Z, Instruction::Scas) => src_val != dst_val || count == 0,
465 (Rep::NZ, Instruction::Cmps) => src_val == dst_val || count == 0,
466 (Rep::NZ, Instruction::Scas) => src_val == dst_val || count == 0,
467 (Rep::NZ | Rep::Z, Instruction::Movs) => {
468 if count == 0 {
469 true
470 }
471 else if movs_reenter_fast_path {
472 *instruction_pointer = *previous_ip;
473 true
474 }
475 else {
476 false
477 }
478 },
479 _ => count == 0,
480 },
481 Rep::None => true,
482 };
483
484 if finished {
485 match instruction {
486 Instruction::Scas | Instruction::Cmps => match size {
487 Size::B => cmp8(src_val, dst_val),
488 Size::W => cmp16(src_val, dst_val),
489 Size::D => cmp32(src_val, dst_val),
490 },
491 _ => {},
492 }
493 break;
494 }
495 }
496 }
497
498 match instruction {
499 Instruction::Movs
500 | Instruction::Cmps
501 | Instruction::Stos
502 | Instruction::Scas
503 | Instruction::Ins => set_reg_asize(is_asize_32, EDI, dst),
504 _ => {},
505 }
506 match instruction {
507 Instruction::Movs | Instruction::Cmps | Instruction::Lods | Instruction::Outs => {
508 set_reg_asize(is_asize_32, ESI, src)
509 },
510 _ => {},
511 };
512
513 match rep {
514 Rep::Z | Rep::NZ => {
515 set_reg_asize(is_asize_32, ECX, count as i32);
516 },
517 Rep::None => {},
518 }
519}
520
521#[no_mangle]
522pub unsafe fn movsb_rep(is_asize_32: bool, seg: i32) {
523 string_instruction(is_asize_32, seg, Instruction::Movs, Size::B, Rep::Z)
524}
525#[no_mangle]
526pub unsafe fn movsw_rep(is_asize_32: bool, seg: i32) {
527 string_instruction(is_asize_32, seg, Instruction::Movs, Size::W, Rep::Z)
528}
529#[no_mangle]
530pub unsafe fn movsd_rep(is_asize_32: bool, seg: i32) {
531 string_instruction(is_asize_32, seg, Instruction::Movs, Size::D, Rep::Z)
532}
533pub unsafe fn movsb_no_rep(is_asize_32: bool, seg: i32) {
534 string_instruction(is_asize_32, seg, Instruction::Movs, Size::B, Rep::None)
535}
536pub unsafe fn movsw_no_rep(is_asize_32: bool, seg: i32) {
537 string_instruction(is_asize_32, seg, Instruction::Movs, Size::W, Rep::None)
538}
539pub unsafe fn movsd_no_rep(is_asize_32: bool, seg: i32) {
540 string_instruction(is_asize_32, seg, Instruction::Movs, Size::D, Rep::None)
541}
542
543#[no_mangle]
544pub unsafe fn lodsb_rep(is_asize_32: bool, seg: i32) {
545 string_instruction(is_asize_32, seg, Instruction::Lods, Size::B, Rep::Z)
546}
547#[no_mangle]
548pub unsafe fn lodsw_rep(is_asize_32: bool, seg: i32) {
549 string_instruction(is_asize_32, seg, Instruction::Lods, Size::W, Rep::Z)
550}
551#[no_mangle]
552pub unsafe fn lodsd_rep(is_asize_32: bool, seg: i32) {
553 string_instruction(is_asize_32, seg, Instruction::Lods, Size::D, Rep::Z)
554}
555pub unsafe fn lodsb_no_rep(is_asize_32: bool, seg: i32) {
556 string_instruction(is_asize_32, seg, Instruction::Lods, Size::B, Rep::None)
557}
558pub unsafe fn lodsw_no_rep(is_asize_32: bool, seg: i32) {
559 string_instruction(is_asize_32, seg, Instruction::Lods, Size::W, Rep::None)
560}
561pub unsafe fn lodsd_no_rep(is_asize_32: bool, seg: i32) {
562 string_instruction(is_asize_32, seg, Instruction::Lods, Size::D, Rep::None)
563}
564
565#[no_mangle]
566pub unsafe fn stosb_rep(is_asize_32: bool) {
567 string_instruction(is_asize_32, 0, Instruction::Stos, Size::B, Rep::Z)
568}
569#[no_mangle]
570pub unsafe fn stosw_rep(is_asize_32: bool) {
571 string_instruction(is_asize_32, 0, Instruction::Stos, Size::W, Rep::Z)
572}
573#[no_mangle]
574pub unsafe fn stosd_rep(is_asize_32: bool) {
575 string_instruction(is_asize_32, 0, Instruction::Stos, Size::D, Rep::Z)
576}
577pub unsafe fn stosb_no_rep(is_asize_32: bool) {
578 string_instruction(is_asize_32, 0, Instruction::Stos, Size::B, Rep::None)
579}
580pub unsafe fn stosw_no_rep(is_asize_32: bool) {
581 string_instruction(is_asize_32, 0, Instruction::Stos, Size::W, Rep::None)
582}
583pub unsafe fn stosd_no_rep(is_asize_32: bool) {
584 string_instruction(is_asize_32, 0, Instruction::Stos, Size::D, Rep::None)
585}
586
587#[no_mangle]
588pub unsafe fn cmpsb_repz(is_asize_32: bool, seg: i32) {
589 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::B, Rep::Z)
590}
591#[no_mangle]
592pub unsafe fn cmpsw_repz(is_asize_32: bool, seg: i32) {
593 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::W, Rep::Z)
594}
595#[no_mangle]
596pub unsafe fn cmpsd_repz(is_asize_32: bool, seg: i32) {
597 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::D, Rep::Z)
598}
599#[no_mangle]
600pub unsafe fn cmpsb_repnz(is_asize_32: bool, seg: i32) {
601 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::B, Rep::NZ)
602}
603#[no_mangle]
604pub unsafe fn cmpsw_repnz(is_asize_32: bool, seg: i32) {
605 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::W, Rep::NZ)
606}
607#[no_mangle]
608pub unsafe fn cmpsd_repnz(is_asize_32: bool, seg: i32) {
609 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::D, Rep::NZ)
610}
611#[no_mangle]
612pub unsafe fn cmpsb_no_rep(is_asize_32: bool, seg: i32) {
613 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::B, Rep::None)
614}
615#[no_mangle]
616pub unsafe fn cmpsw_no_rep(is_asize_32: bool, seg: i32) {
617 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::W, Rep::None)
618}
619#[no_mangle]
620pub unsafe fn cmpsd_no_rep(is_asize_32: bool, seg: i32) {
621 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::D, Rep::None)
622}
623
624#[no_mangle]
625pub unsafe fn scasb_repz(is_asize_32: bool) {
626 string_instruction(is_asize_32, 0, Instruction::Scas, Size::B, Rep::Z)
627}
628#[no_mangle]
629pub unsafe fn scasw_repz(is_asize_32: bool) {
630 string_instruction(is_asize_32, 0, Instruction::Scas, Size::W, Rep::Z)
631}
632#[no_mangle]
633pub unsafe fn scasd_repz(is_asize_32: bool) {
634 string_instruction(is_asize_32, 0, Instruction::Scas, Size::D, Rep::Z)
635}
636#[no_mangle]
637pub unsafe fn scasb_repnz(is_asize_32: bool) {
638 string_instruction(is_asize_32, 0, Instruction::Scas, Size::B, Rep::NZ)
639}
640#[no_mangle]
641pub unsafe fn scasw_repnz(is_asize_32: bool) {
642 string_instruction(is_asize_32, 0, Instruction::Scas, Size::W, Rep::NZ)
643}
644#[no_mangle]
645pub unsafe fn scasd_repnz(is_asize_32: bool) {
646 string_instruction(is_asize_32, 0, Instruction::Scas, Size::D, Rep::NZ)
647}
648pub unsafe fn scasb_no_rep(is_asize_32: bool) {
649 string_instruction(is_asize_32, 0, Instruction::Scas, Size::B, Rep::None)
650}
651pub unsafe fn scasw_no_rep(is_asize_32: bool) {
652 string_instruction(is_asize_32, 0, Instruction::Scas, Size::W, Rep::None)
653}
654pub unsafe fn scasd_no_rep(is_asize_32: bool) {
655 string_instruction(is_asize_32, 0, Instruction::Scas, Size::D, Rep::None)
656}
657
658#[no_mangle]
659pub unsafe fn outsb_rep(is_asize_32: bool, seg: i32) {
660 string_instruction(is_asize_32, seg, Instruction::Outs, Size::B, Rep::Z)
661}
662#[no_mangle]
663pub unsafe fn outsw_rep(is_asize_32: bool, seg: i32) {
664 string_instruction(is_asize_32, seg, Instruction::Outs, Size::W, Rep::Z)
665}
666#[no_mangle]
667pub unsafe fn outsd_rep(is_asize_32: bool, seg: i32) {
668 string_instruction(is_asize_32, seg, Instruction::Outs, Size::D, Rep::Z)
669}
670#[no_mangle]
671pub unsafe fn outsb_no_rep(is_asize_32: bool, seg: i32) {
672 string_instruction(is_asize_32, seg, Instruction::Outs, Size::B, Rep::None)
673}
674#[no_mangle]
675pub unsafe fn outsw_no_rep(is_asize_32: bool, seg: i32) {
676 string_instruction(is_asize_32, seg, Instruction::Outs, Size::W, Rep::None)
677}
678#[no_mangle]
679pub unsafe fn outsd_no_rep(is_asize_32: bool, seg: i32) {
680 string_instruction(is_asize_32, seg, Instruction::Outs, Size::D, Rep::None)
681}
682
683#[no_mangle]
684pub unsafe fn insb_rep(is_asize_32: bool) {
685 string_instruction(is_asize_32, 0, Instruction::Ins, Size::B, Rep::Z)
686}
687#[no_mangle]
688pub unsafe fn insw_rep(is_asize_32: bool) {
689 string_instruction(is_asize_32, 0, Instruction::Ins, Size::W, Rep::Z)
690}
691#[no_mangle]
692pub unsafe fn insd_rep(is_asize_32: bool) {
693 string_instruction(is_asize_32, 0, Instruction::Ins, Size::D, Rep::Z)
694}
695#[no_mangle]
696pub unsafe fn insb_no_rep(is_asize_32: bool) {
697 string_instruction(is_asize_32, 0, Instruction::Ins, Size::B, Rep::None)
698}
699#[no_mangle]
700pub unsafe fn insw_no_rep(is_asize_32: bool) {
701 string_instruction(is_asize_32, 0, Instruction::Ins, Size::W, Rep::None)
702}
703#[no_mangle]
704pub unsafe fn insd_no_rep(is_asize_32: bool) {
705 string_instruction(is_asize_32, 0, Instruction::Ins, Size::D, Rep::None)
706}