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 count -= 1;
455
456 let finished = match rep {
457 Rep::Z | Rep::NZ => match (rep, instruction) {
458 (Rep::Z, Instruction::Cmps) => src_val != dst_val || count == 0,
459 (Rep::Z, Instruction::Scas) => src_val != dst_val || count == 0,
460 (Rep::NZ, Instruction::Cmps) => src_val == dst_val || count == 0,
461 (Rep::NZ, Instruction::Scas) => src_val == dst_val || count == 0,
462 (Rep::NZ | Rep::Z, Instruction::Movs) => {
463 if count == 0 {
464 true
465 }
466 else if movs_reenter_fast_path {
467 *instruction_pointer = *previous_ip;
468 true
469 }
470 else {
471 false
472 }
473 },
474 _ => count == 0,
475 },
476 Rep::None => true,
477 };
478
479 if finished {
480 match instruction {
481 Instruction::Scas | Instruction::Cmps => match size {
482 Size::B => cmp8(src_val, dst_val),
483 Size::W => cmp16(src_val, dst_val),
484 Size::D => cmp32(src_val, dst_val),
485 },
486 _ => {},
487 }
488 break;
489 }
490 }
491 }
492
493 match instruction {
494 Instruction::Movs
495 | Instruction::Cmps
496 | Instruction::Stos
497 | Instruction::Scas
498 | Instruction::Ins => set_reg_asize(is_asize_32, EDI, dst),
499 _ => {},
500 }
501 match instruction {
502 Instruction::Movs | Instruction::Cmps | Instruction::Lods | Instruction::Outs => {
503 set_reg_asize(is_asize_32, ESI, src)
504 },
505 _ => {},
506 };
507
508 match rep {
509 Rep::Z | Rep::NZ => {
510 set_reg_asize(is_asize_32, ECX, count as i32);
511 },
512 Rep::None => {},
513 }
514}
515
516#[no_mangle]
517pub unsafe fn movsb_rep(is_asize_32: bool, seg: i32) {
518 string_instruction(is_asize_32, seg, Instruction::Movs, Size::B, Rep::Z)
519}
520#[no_mangle]
521pub unsafe fn movsw_rep(is_asize_32: bool, seg: i32) {
522 string_instruction(is_asize_32, seg, Instruction::Movs, Size::W, Rep::Z)
523}
524#[no_mangle]
525pub unsafe fn movsd_rep(is_asize_32: bool, seg: i32) {
526 string_instruction(is_asize_32, seg, Instruction::Movs, Size::D, Rep::Z)
527}
528pub unsafe fn movsb_no_rep(is_asize_32: bool, seg: i32) {
529 string_instruction(is_asize_32, seg, Instruction::Movs, Size::B, Rep::None)
530}
531pub unsafe fn movsw_no_rep(is_asize_32: bool, seg: i32) {
532 string_instruction(is_asize_32, seg, Instruction::Movs, Size::W, Rep::None)
533}
534pub unsafe fn movsd_no_rep(is_asize_32: bool, seg: i32) {
535 string_instruction(is_asize_32, seg, Instruction::Movs, Size::D, Rep::None)
536}
537
538#[no_mangle]
539pub unsafe fn lodsb_rep(is_asize_32: bool, seg: i32) {
540 string_instruction(is_asize_32, seg, Instruction::Lods, Size::B, Rep::Z)
541}
542#[no_mangle]
543pub unsafe fn lodsw_rep(is_asize_32: bool, seg: i32) {
544 string_instruction(is_asize_32, seg, Instruction::Lods, Size::W, Rep::Z)
545}
546#[no_mangle]
547pub unsafe fn lodsd_rep(is_asize_32: bool, seg: i32) {
548 string_instruction(is_asize_32, seg, Instruction::Lods, Size::D, Rep::Z)
549}
550pub unsafe fn lodsb_no_rep(is_asize_32: bool, seg: i32) {
551 string_instruction(is_asize_32, seg, Instruction::Lods, Size::B, Rep::None)
552}
553pub unsafe fn lodsw_no_rep(is_asize_32: bool, seg: i32) {
554 string_instruction(is_asize_32, seg, Instruction::Lods, Size::W, Rep::None)
555}
556pub unsafe fn lodsd_no_rep(is_asize_32: bool, seg: i32) {
557 string_instruction(is_asize_32, seg, Instruction::Lods, Size::D, Rep::None)
558}
559
560#[no_mangle]
561pub unsafe fn stosb_rep(is_asize_32: bool) {
562 string_instruction(is_asize_32, 0, Instruction::Stos, Size::B, Rep::Z)
563}
564#[no_mangle]
565pub unsafe fn stosw_rep(is_asize_32: bool) {
566 string_instruction(is_asize_32, 0, Instruction::Stos, Size::W, Rep::Z)
567}
568#[no_mangle]
569pub unsafe fn stosd_rep(is_asize_32: bool) {
570 string_instruction(is_asize_32, 0, Instruction::Stos, Size::D, Rep::Z)
571}
572pub unsafe fn stosb_no_rep(is_asize_32: bool) {
573 string_instruction(is_asize_32, 0, Instruction::Stos, Size::B, Rep::None)
574}
575pub unsafe fn stosw_no_rep(is_asize_32: bool) {
576 string_instruction(is_asize_32, 0, Instruction::Stos, Size::W, Rep::None)
577}
578pub unsafe fn stosd_no_rep(is_asize_32: bool) {
579 string_instruction(is_asize_32, 0, Instruction::Stos, Size::D, Rep::None)
580}
581
582#[no_mangle]
583pub unsafe fn cmpsb_repz(is_asize_32: bool, seg: i32) {
584 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::B, Rep::Z)
585}
586#[no_mangle]
587pub unsafe fn cmpsw_repz(is_asize_32: bool, seg: i32) {
588 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::W, Rep::Z)
589}
590#[no_mangle]
591pub unsafe fn cmpsd_repz(is_asize_32: bool, seg: i32) {
592 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::D, Rep::Z)
593}
594#[no_mangle]
595pub unsafe fn cmpsb_repnz(is_asize_32: bool, seg: i32) {
596 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::B, Rep::NZ)
597}
598#[no_mangle]
599pub unsafe fn cmpsw_repnz(is_asize_32: bool, seg: i32) {
600 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::W, Rep::NZ)
601}
602#[no_mangle]
603pub unsafe fn cmpsd_repnz(is_asize_32: bool, seg: i32) {
604 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::D, Rep::NZ)
605}
606#[no_mangle]
607pub unsafe fn cmpsb_no_rep(is_asize_32: bool, seg: i32) {
608 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::B, Rep::None)
609}
610#[no_mangle]
611pub unsafe fn cmpsw_no_rep(is_asize_32: bool, seg: i32) {
612 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::W, Rep::None)
613}
614#[no_mangle]
615pub unsafe fn cmpsd_no_rep(is_asize_32: bool, seg: i32) {
616 string_instruction(is_asize_32, seg, Instruction::Cmps, Size::D, Rep::None)
617}
618
619#[no_mangle]
620pub unsafe fn scasb_repz(is_asize_32: bool) {
621 string_instruction(is_asize_32, 0, Instruction::Scas, Size::B, Rep::Z)
622}
623#[no_mangle]
624pub unsafe fn scasw_repz(is_asize_32: bool) {
625 string_instruction(is_asize_32, 0, Instruction::Scas, Size::W, Rep::Z)
626}
627#[no_mangle]
628pub unsafe fn scasd_repz(is_asize_32: bool) {
629 string_instruction(is_asize_32, 0, Instruction::Scas, Size::D, Rep::Z)
630}
631#[no_mangle]
632pub unsafe fn scasb_repnz(is_asize_32: bool) {
633 string_instruction(is_asize_32, 0, Instruction::Scas, Size::B, Rep::NZ)
634}
635#[no_mangle]
636pub unsafe fn scasw_repnz(is_asize_32: bool) {
637 string_instruction(is_asize_32, 0, Instruction::Scas, Size::W, Rep::NZ)
638}
639#[no_mangle]
640pub unsafe fn scasd_repnz(is_asize_32: bool) {
641 string_instruction(is_asize_32, 0, Instruction::Scas, Size::D, Rep::NZ)
642}
643pub unsafe fn scasb_no_rep(is_asize_32: bool) {
644 string_instruction(is_asize_32, 0, Instruction::Scas, Size::B, Rep::None)
645}
646pub unsafe fn scasw_no_rep(is_asize_32: bool) {
647 string_instruction(is_asize_32, 0, Instruction::Scas, Size::W, Rep::None)
648}
649pub unsafe fn scasd_no_rep(is_asize_32: bool) {
650 string_instruction(is_asize_32, 0, Instruction::Scas, Size::D, Rep::None)
651}
652
653#[no_mangle]
654pub unsafe fn outsb_rep(is_asize_32: bool, seg: i32) {
655 string_instruction(is_asize_32, seg, Instruction::Outs, Size::B, Rep::Z)
656}
657#[no_mangle]
658pub unsafe fn outsw_rep(is_asize_32: bool, seg: i32) {
659 string_instruction(is_asize_32, seg, Instruction::Outs, Size::W, Rep::Z)
660}
661#[no_mangle]
662pub unsafe fn outsd_rep(is_asize_32: bool, seg: i32) {
663 string_instruction(is_asize_32, seg, Instruction::Outs, Size::D, Rep::Z)
664}
665#[no_mangle]
666pub unsafe fn outsb_no_rep(is_asize_32: bool, seg: i32) {
667 string_instruction(is_asize_32, seg, Instruction::Outs, Size::B, Rep::None)
668}
669#[no_mangle]
670pub unsafe fn outsw_no_rep(is_asize_32: bool, seg: i32) {
671 string_instruction(is_asize_32, seg, Instruction::Outs, Size::W, Rep::None)
672}
673#[no_mangle]
674pub unsafe fn outsd_no_rep(is_asize_32: bool, seg: i32) {
675 string_instruction(is_asize_32, seg, Instruction::Outs, Size::D, Rep::None)
676}
677
678#[no_mangle]
679pub unsafe fn insb_rep(is_asize_32: bool) {
680 string_instruction(is_asize_32, 0, Instruction::Ins, Size::B, Rep::Z)
681}
682#[no_mangle]
683pub unsafe fn insw_rep(is_asize_32: bool) {
684 string_instruction(is_asize_32, 0, Instruction::Ins, Size::W, Rep::Z)
685}
686#[no_mangle]
687pub unsafe fn insd_rep(is_asize_32: bool) {
688 string_instruction(is_asize_32, 0, Instruction::Ins, Size::D, Rep::Z)
689}
690#[no_mangle]
691pub unsafe fn insb_no_rep(is_asize_32: bool) {
692 string_instruction(is_asize_32, 0, Instruction::Ins, Size::B, Rep::None)
693}
694#[no_mangle]
695pub unsafe fn insw_no_rep(is_asize_32: bool) {
696 string_instruction(is_asize_32, 0, Instruction::Ins, Size::W, Rep::None)
697}
698#[no_mangle]
699pub unsafe fn insd_no_rep(is_asize_32: bool) {
700 string_instruction(is_asize_32, 0, Instruction::Ins, Size::D, Rep::None)
701}