- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / string.cc
blobefc29597a4d1e8458e8efd66c3af10593093103f
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: string.cc,v 1.69 2008/12/11 21:19:38 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 #define NEED_CPU_REG_SHORTCUTS 1
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
33 #if BX_SUPPORT_X86_64==0
34 #define RSI ESI
35 #define RDI EDI
36 #define RAX EAX
37 #define RCX ECX
38 #endif
41 // Repeat Speedups methods
44 #if BX_SupportRepeatSpeedups
45 Bit32u BX_CPU_C::FastRepMOVSB(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u count)
47 Bit32u bytesFitSrc, bytesFitDst;
48 signed int pointerDelta;
49 bx_address laddrDst, laddrSrc;
50 Bit8u *hostAddrSrc, *hostAddrDst;
52 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
54 bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
55 if (!(srcSegPtr->cache.valid & SegAccessROK))
56 return 0;
57 if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
58 return 0;
60 bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
61 if (!(dstSegPtr->cache.valid & SegAccessWOK))
62 return 0;
63 if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
64 return 0;
66 laddrSrc = BX_CPU_THIS_PTR get_laddr(srcSeg, srcOff);
68 hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl);
69 if (! hostAddrSrc) return 0;
71 laddrDst = BX_CPU_THIS_PTR get_laddr(dstSeg, dstOff);
73 hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
74 // Check that native host access was not vetoed for that page
75 if (!hostAddrDst) return 0;
77 // See how many bytes can fit in the rest of this page.
78 if (BX_CPU_THIS_PTR get_DF()) {
79 // Counting downward.
80 bytesFitSrc = 1 + PAGE_OFFSET(laddrSrc);
81 bytesFitDst = 1 + PAGE_OFFSET(laddrDst);
82 pointerDelta = (signed int) -1;
84 else {
85 // Counting upward.
86 bytesFitSrc = 0x1000 - PAGE_OFFSET(laddrSrc);
87 bytesFitDst = 0x1000 - PAGE_OFFSET(laddrDst);
88 pointerDelta = (signed int) 1;
91 // Restrict word count to the number that will fit in either
92 // source or dest pages.
93 if (count > bytesFitSrc)
94 count = bytesFitSrc;
95 if (count > bytesFitDst)
96 count = bytesFitDst;
97 if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
98 count = bx_pc_system.getNumCpuTicksLeftNextEvent();
100 // If after all the restrictions, there is anything left to do...
101 if (count) {
102 // Transfer data directly using host addresses
103 for (unsigned j=0; j<count; j++) {
104 * (Bit8u *) hostAddrDst = * (Bit8u *) hostAddrSrc;
105 hostAddrDst += pointerDelta;
106 hostAddrSrc += pointerDelta;
109 return count;
112 return 0;
115 Bit32u BX_CPU_C::FastRepMOVSW(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u count)
117 Bit32u wordsFitSrc, wordsFitDst;
118 signed int pointerDelta;
119 bx_address laddrDst, laddrSrc;
120 Bit8u *hostAddrSrc, *hostAddrDst;
122 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
124 bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
125 if (!(srcSegPtr->cache.valid & SegAccessROK))
126 return 0;
127 if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
128 return 0;
130 bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
131 if (!(dstSegPtr->cache.valid & SegAccessWOK))
132 return 0;
133 if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
134 return 0;
136 laddrSrc = BX_CPU_THIS_PTR get_laddr(srcSeg, srcOff);
138 hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl);
139 if (! hostAddrSrc) return 0;
141 laddrDst = BX_CPU_THIS_PTR get_laddr(dstSeg, dstOff);
143 hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
144 // Check that native host access was not vetoed for that page
145 if (!hostAddrDst) return 0;
147 // See how many words can fit in the rest of this page.
148 if (BX_CPU_THIS_PTR get_DF()) {
149 // Counting downward.
150 // Note: 1st word must not cross page boundary.
151 if (((laddrSrc & 0xfff) > 0xffe) || ((laddrDst & 0xfff) > 0xffe))
152 return 0;
153 wordsFitSrc = (2 + PAGE_OFFSET(laddrSrc)) >> 1;
154 wordsFitDst = (2 + PAGE_OFFSET(laddrDst)) >> 1;
155 pointerDelta = (signed int) -2;
157 else {
158 // Counting upward.
159 wordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 1;
160 wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1;
161 pointerDelta = (signed int) 2;
164 // Restrict word count to the number that will fit in either
165 // source or dest pages.
166 if (count > wordsFitSrc)
167 count = wordsFitSrc;
168 if (count > wordsFitDst)
169 count = wordsFitDst;
170 if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
171 count = bx_pc_system.getNumCpuTicksLeftNextEvent();
173 // If after all the restrictions, there is anything left to do...
174 if (count) {
175 // Transfer data directly using host addresses
176 for (unsigned j=0; j<count; j++) {
177 CopyHostWordLittleEndian(hostAddrDst, hostAddrSrc);
178 hostAddrDst += pointerDelta;
179 hostAddrSrc += pointerDelta;
182 return count;
185 return 0;
188 Bit32u BX_CPU_C::FastRepMOVSD(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u count)
190 Bit32u dwordsFitSrc, dwordsFitDst;
191 signed int pointerDelta;
192 bx_address laddrDst, laddrSrc;
193 Bit8u *hostAddrSrc, *hostAddrDst;
195 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
197 bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
198 if (!(srcSegPtr->cache.valid & SegAccessROK))
199 return 0;
200 if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
201 return 0;
203 bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
204 if (!(dstSegPtr->cache.valid & SegAccessWOK))
205 return 0;
206 if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
207 return 0;
209 laddrSrc = BX_CPU_THIS_PTR get_laddr(srcSeg, srcOff);
211 hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl);
212 if (! hostAddrSrc) return 0;
214 laddrDst = BX_CPU_THIS_PTR get_laddr(dstSeg, dstOff);
216 hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
217 // Check that native host access was not vetoed for that page
218 if (!hostAddrDst) return 0;
220 // See how many dwords can fit in the rest of this page.
221 if (BX_CPU_THIS_PTR get_DF()) {
222 // Counting downward.
223 // Note: 1st dword must not cross page boundary.
224 if (((laddrSrc & 0xfff) > 0xffc) || ((laddrDst & 0xfff) > 0xffc))
225 return 0;
226 dwordsFitSrc = (4 + PAGE_OFFSET(laddrSrc)) >> 2;
227 dwordsFitDst = (4 + PAGE_OFFSET(laddrDst)) >> 2;
228 pointerDelta = (signed int) -4;
230 else {
231 // Counting upward.
232 dwordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 2;
233 dwordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 2;
234 pointerDelta = (signed int) 4;
237 // Restrict dword count to the number that will fit in either
238 // source or dest pages.
239 if (count > dwordsFitSrc)
240 count = dwordsFitSrc;
241 if (count > dwordsFitDst)
242 count = dwordsFitDst;
243 if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
244 count = bx_pc_system.getNumCpuTicksLeftNextEvent();
246 // If after all the restrictions, there is anything left to do...
247 if (count) {
248 // Transfer data directly using host addresses
249 for (unsigned j=0; j<count; j++) {
250 CopyHostDWordLittleEndian(hostAddrDst, hostAddrSrc);
251 hostAddrDst += pointerDelta;
252 hostAddrSrc += pointerDelta;
255 return count;
258 return 0;
261 Bit32u BX_CPU_C::FastRepSTOSB(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit8u val, Bit32u count)
263 Bit32u bytesFitDst;
264 signed int pointerDelta;
265 bx_address laddrDst;
266 Bit8u *hostAddrDst;
268 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
270 bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
271 if (!(dstSegPtr->cache.valid & SegAccessWOK))
272 return 0;
273 if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
274 return 0;
276 laddrDst = BX_CPU_THIS_PTR get_laddr(dstSeg, dstOff);
278 hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
279 // Check that native host access was not vetoed for that page
280 if (!hostAddrDst) return 0;
282 // See how many bytes can fit in the rest of this page.
283 if (BX_CPU_THIS_PTR get_DF()) {
284 // Counting downward.
285 bytesFitDst = 1 + PAGE_OFFSET(laddrDst);
286 pointerDelta = (signed int) -1;
288 else {
289 // Counting upward.
290 bytesFitDst = 0x1000 - PAGE_OFFSET(laddrDst);
291 pointerDelta = (signed int) 1;
294 // Restrict word count to the number that will fit in either
295 // source or dest pages.
296 if (count > bytesFitDst)
297 count = bytesFitDst;
298 if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
299 count = bx_pc_system.getNumCpuTicksLeftNextEvent();
301 // If after all the restrictions, there is anything left to do...
302 if (count) {
303 // Transfer data directly using host addresses
304 for (unsigned j=0; j<count; j++) {
305 * (Bit8u *) hostAddrDst = val;
306 hostAddrDst += pointerDelta;
309 return count;
312 return 0;
315 Bit32u BX_CPU_C::FastRepSTOSW(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit16u val, Bit32u count)
317 Bit32u wordsFitDst;
318 signed int pointerDelta;
319 bx_address laddrDst;
320 Bit8u *hostAddrDst;
322 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
324 bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
325 if (!(dstSegPtr->cache.valid & SegAccessWOK))
326 return 0;
327 if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
328 return 0;
330 laddrDst = BX_CPU_THIS_PTR get_laddr(dstSeg, dstOff);
332 hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
333 // Check that native host access was not vetoed for that page
334 if (!hostAddrDst) return 0;
336 // See how many words can fit in the rest of this page.
337 if (BX_CPU_THIS_PTR get_DF()) {
338 // Counting downward.
339 // Note: 1st word must not cross page boundary.
340 if ((laddrDst & 0xfff) > 0xffe) return 0;
341 wordsFitDst = (2 + PAGE_OFFSET(laddrDst)) >> 1;
342 pointerDelta = (signed int) -2;
344 else {
345 // Counting upward.
346 wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1;
347 pointerDelta = (signed int) 2;
350 // Restrict word count to the number that will fit in either
351 // source or dest pages.
352 if (count > wordsFitDst)
353 count = wordsFitDst;
354 if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
355 count = bx_pc_system.getNumCpuTicksLeftNextEvent();
357 // If after all the restrictions, there is anything left to do...
358 if (count) {
359 // Transfer data directly using host addresses
360 for (unsigned j=0; j<count; j++) {
361 WriteHostWordToLittleEndian(hostAddrDst, val);
362 hostAddrDst += pointerDelta;
365 return count;
368 return 0;
371 Bit32u BX_CPU_C::FastRepSTOSD(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit32u val, Bit32u count)
373 Bit32u dwordsFitDst;
374 signed int pointerDelta;
375 bx_address laddrDst;
376 Bit8u *hostAddrDst;
378 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
380 bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
381 if (!(dstSegPtr->cache.valid & SegAccessWOK))
382 return 0;
383 if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
384 return 0;
386 laddrDst = BX_CPU_THIS_PTR get_laddr(dstSeg, dstOff);
388 hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
389 // Check that native host access was not vetoed for that page
390 if (!hostAddrDst) return 0;
392 // See how many dwords can fit in the rest of this page.
393 if (BX_CPU_THIS_PTR get_DF()) {
394 // Counting downward.
395 // Note: 1st dword must not cross page boundary.
396 if ((laddrDst & 0xfff) > 0xffc) return 0;
397 dwordsFitDst = (4 + PAGE_OFFSET(laddrDst)) >> 2;
398 pointerDelta = (signed int) -4;
400 else {
401 // Counting upward.
402 dwordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 2;
403 pointerDelta = (signed int) 4;
406 // Restrict dword count to the number that will fit in either
407 // source or dest pages.
408 if (count > dwordsFitDst)
409 count = dwordsFitDst;
410 if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
411 count = bx_pc_system.getNumCpuTicksLeftNextEvent();
413 // If after all the restrictions, there is anything left to do...
414 if (count) {
415 // Transfer data directly using host addresses
416 for (unsigned j=0; j<count; j++) {
417 WriteHostDWordToLittleEndian(hostAddrDst, val);
418 hostAddrDst += pointerDelta;
421 return count;
424 return 0;
426 #endif
429 // REP MOVS methods
432 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSB_XbYb(bxInstruction_c *i)
434 #if BX_SUPPORT_X86_64
435 if (i->as64L())
436 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB64_XbYb);
437 else
438 #endif
439 if (i->as32L()) {
440 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB32_XbYb);
441 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
442 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
444 else {
445 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB16_XbYb);
449 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSW_XwYw(bxInstruction_c *i)
451 #if BX_SUPPORT_X86_64
452 if (i->as64L())
453 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW64_XwYw);
454 else
455 #endif
456 if (i->as32L()) {
457 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW32_XwYw);
458 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
459 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
461 else {
462 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW16_XwYw);
466 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSD_XdYd(bxInstruction_c *i)
468 #if BX_SUPPORT_X86_64
469 if (i->as64L())
470 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD64_XdYd);
471 else
472 #endif
473 if (i->as32L()) {
474 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD32_XdYd);
475 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
476 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
478 else {
479 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD16_XdYd);
483 #if BX_SUPPORT_X86_64
484 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSQ_XqYq(bxInstruction_c *i)
486 if (i->as64L()) {
487 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSQ64_XqYq);
489 else {
490 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSQ32_XqYq);
491 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
492 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
495 #endif
498 // MOVSB/MOVSW/MOVSD/MOVSQ methods
501 // 16 bit address size
502 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB16_XbYb(bxInstruction_c *i)
504 Bit8u temp8 = read_virtual_byte_32(i->seg(), SI);
505 write_virtual_byte_32(BX_SEG_REG_ES, DI, temp8);
507 if (BX_CPU_THIS_PTR get_DF()) {
508 /* decrement SI, DI */
509 SI--;
510 DI--;
512 else {
513 /* increment SI, DI */
514 SI++;
515 DI++;
519 // 32 bit address size
520 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB32_XbYb(bxInstruction_c *i)
522 Bit8u temp8;
524 Bit32u incr = 1;
526 #if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
527 /* If conditions are right, we can transfer IO to physical memory
528 * in a batch, rather than one instruction at a time */
529 if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
531 Bit32u byteCount = FastRepMOVSB(i, i->seg(), ESI, BX_SEG_REG_ES, EDI, ECX);
532 if (byteCount) {
533 // Decrement the ticks count by the number of iterations, minus
534 // one, since the main cpu loop will decrement one. Also,
535 // the count is predecremented before examined, so defintely
536 // don't roll it under zero.
537 BX_TICKN(byteCount-1);
539 // Decrement eCX. Note, the main loop will decrement 1 also, so
540 // decrement by one less than expected, like the case above.
541 RCX = ECX - (byteCount-1);
543 incr = byteCount;
545 else {
546 temp8 = read_virtual_byte(i->seg(), ESI);
547 write_virtual_byte(BX_SEG_REG_ES, EDI, temp8);
550 else
551 #endif
553 temp8 = read_virtual_byte(i->seg(), ESI);
554 write_virtual_byte(BX_SEG_REG_ES, EDI, temp8);
557 if (BX_CPU_THIS_PTR get_DF()) {
558 RSI = ESI - incr;
559 RDI = EDI - incr;
561 else {
562 RSI = ESI + incr;
563 RDI = EDI + incr;
567 #if BX_SUPPORT_X86_64
568 // 64 bit address size
569 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB64_XbYb(bxInstruction_c *i)
571 Bit8u temp8;
573 Bit64u rsi = RSI;
574 Bit64u rdi = RDI;
576 temp8 = read_virtual_byte_64(i->seg(), rsi);
577 write_virtual_byte_64(BX_SEG_REG_ES, rdi, temp8);
579 if (BX_CPU_THIS_PTR get_DF()) {
580 /* decrement RSI, RDI */
581 rsi--;
582 rdi--;
584 else {
585 /* increment RSI, RDI */
586 rsi++;
587 rdi++;
590 RSI = rsi;
591 RDI = rdi;
593 #endif
595 /* 16 bit opsize mode, 16 bit address size */
596 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW16_XwYw(bxInstruction_c *i)
598 Bit16u si = SI;
599 Bit16u di = DI;
601 Bit16u temp16 = read_virtual_word_32(i->seg(), si);
602 write_virtual_word_32(BX_SEG_REG_ES, di, temp16);
604 if (BX_CPU_THIS_PTR get_DF()) {
605 /* decrement SI, DI */
606 si -= 2;
607 di -= 2;
609 else {
610 /* increment SI, DI */
611 si += 2;
612 di += 2;
615 SI = si;
616 DI = di;
619 /* 16 bit opsize mode, 32 bit address size */
620 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW32_XwYw(bxInstruction_c *i)
622 Bit16u temp16;
624 Bit32u esi = ESI;
625 Bit32u edi = EDI;
627 temp16 = read_virtual_word(i->seg(), esi);
628 write_virtual_word(BX_SEG_REG_ES, edi, temp16);
630 if (BX_CPU_THIS_PTR get_DF()) {
631 esi -= 2;
632 edi -= 2;
634 else {
635 esi += 2;
636 edi += 2;
639 // zero extension of RSI/RDI
640 RSI = esi;
641 RDI = edi;
644 #if BX_SUPPORT_X86_64
645 /* 16 bit opsize mode, 64 bit address size */
646 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW64_XwYw(bxInstruction_c *i)
648 Bit16u temp16;
650 Bit64u rsi = RSI;
651 Bit64u rdi = RDI;
653 temp16 = read_virtual_word_64(i->seg(), rsi);
654 write_virtual_word_64(BX_SEG_REG_ES, rdi, temp16);
656 if (BX_CPU_THIS_PTR get_DF()) {
657 rsi -= 2;
658 rdi -= 2;
660 else {
661 rsi += 2;
662 rdi += 2;
665 RSI = rsi;
666 RDI = rdi;
668 #endif
670 /* 32 bit opsize mode, 16 bit address size */
671 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD16_XdYd(bxInstruction_c *i)
673 Bit32u temp32;
675 Bit16u si = SI;
676 Bit16u di = DI;
678 temp32 = read_virtual_dword_32(i->seg(), si);
679 write_virtual_dword_32(BX_SEG_REG_ES, di, temp32);
681 if (BX_CPU_THIS_PTR get_DF()) {
682 si -= 4;
683 di -= 4;
685 else {
686 si += 4;
687 di += 4;
690 SI = si;
691 DI = di;
694 /* 32 bit opsize mode, 32 bit address size */
695 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD32_XdYd(bxInstruction_c *i)
697 Bit32u temp32;
699 Bit32u incr = 4;
701 Bit32u esi = ESI;
702 Bit32u edi = EDI;
704 #if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
705 /* If conditions are right, we can transfer IO to physical memory
706 * in a batch, rather than one instruction at a time.
708 if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
710 Bit32u dwordCount = FastRepMOVSD(i, i->seg(), esi, BX_SEG_REG_ES, edi, ECX);
711 if (dwordCount) {
712 // Decrement the ticks count by the number of iterations, minus
713 // one, since the main cpu loop will decrement one. Also,
714 // the count is predecremented before examined, so defintely
715 // don't roll it under zero.
716 BX_TICKN(dwordCount-1);
718 // Decrement eCX. Note, the main loop will decrement 1 also, so
719 // decrement by one less than expected, like the case above.
720 RCX = ECX - (dwordCount-1);
722 incr = dwordCount << 2; // count * 4
724 else {
725 temp32 = read_virtual_dword(i->seg(), esi);
726 write_virtual_dword(BX_SEG_REG_ES, edi, temp32);
729 else
730 #endif
732 temp32 = read_virtual_dword(i->seg(), esi);
733 write_virtual_dword(BX_SEG_REG_ES, edi, temp32);
736 if (BX_CPU_THIS_PTR get_DF()) {
737 esi -= incr;
738 edi -= incr;
740 else {
741 esi += incr;
742 edi += incr;
745 // zero extension of RSI/RDI
746 RSI = esi;
747 RDI = edi;
750 #if BX_SUPPORT_X86_64
752 /* 32 bit opsize mode, 64 bit address size */
753 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD64_XdYd(bxInstruction_c *i)
755 Bit32u temp32;
757 Bit64u rsi = RSI;
758 Bit64u rdi = RDI;
760 temp32 = read_virtual_dword_64(i->seg(), rsi);
761 write_virtual_dword_64(BX_SEG_REG_ES, rdi, temp32);
763 if (BX_CPU_THIS_PTR get_DF()) {
764 rsi -= 4;
765 rdi -= 4;
767 else {
768 rsi += 4;
769 rdi += 4;
772 RSI = rsi;
773 RDI = rdi;
776 /* 64 bit opsize mode, 32 bit address size */
777 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSQ32_XqYq(bxInstruction_c *i)
779 Bit64u temp64;
781 Bit32u esi = ESI;
782 Bit32u edi = EDI;
784 temp64 = read_virtual_qword_64(i->seg(), esi);
785 write_virtual_qword_64(BX_SEG_REG_ES, edi, temp64);
787 if (BX_CPU_THIS_PTR get_DF()) {
788 esi -= 8;
789 edi -= 8;
791 else {
792 esi += 8;
793 edi += 8;
796 // zero extension of RSI/RDI
797 RSI = esi;
798 RDI = edi;
801 /* 64 bit opsize mode, 64 bit address size */
802 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSQ64_XqYq(bxInstruction_c *i)
804 Bit64u temp64;
806 Bit64u rsi = RSI;
807 Bit64u rdi = RDI;
809 temp64 = read_virtual_qword_64(i->seg(), rsi);
810 write_virtual_qword_64(BX_SEG_REG_ES, rdi, temp64);
812 if (BX_CPU_THIS_PTR get_DF()) {
813 rsi -= 8;
814 rdi -= 8;
816 else {
817 rsi += 8;
818 rdi += 8;
821 RSI = rsi;
822 RDI = rdi;
825 #endif
828 // REP CMPS methods
831 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSB_XbYb(bxInstruction_c *i)
833 #if BX_SUPPORT_X86_64
834 if (i->as64L()) {
835 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB64_XbYb);
837 else
838 #endif
839 if (i->as32L()) {
840 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB32_XbYb);
841 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
842 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
844 else {
845 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB16_XbYb);
849 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSW_XwYw(bxInstruction_c *i)
851 #if BX_SUPPORT_X86_64
852 if (i->as64L()) {
853 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW64_XwYw);
855 else
856 #endif
857 if (i->as32L()) {
858 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW32_XwYw);
859 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
860 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
862 else {
863 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW16_XwYw);
867 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSD_XdYd(bxInstruction_c *i)
869 #if BX_SUPPORT_X86_64
870 if (i->as64L()) {
871 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD64_XdYd);
873 else
874 #endif
875 if (i->as32L()) {
876 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD32_XdYd);
877 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
878 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
880 else {
881 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD16_XdYd);
885 #if BX_SUPPORT_X86_64
886 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSQ_XqYq(bxInstruction_c *i)
888 if (i->as64L()) {
889 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSQ64_XqYq);
891 else {
892 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSQ32_XqYq);
893 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
894 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
897 #endif
900 // CMPSB/CMPSW/CMPSD/CMPSQ methods
903 /* 16 bit address size */
904 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB16_XbYb(bxInstruction_c *i)
906 Bit8u op1_8, op2_8, diff_8;
908 Bit16u si = SI;
909 Bit16u di = DI;
911 op1_8 = read_virtual_byte_32(i->seg(), si);
912 op2_8 = read_virtual_byte_32(BX_SEG_REG_ES, di);
914 diff_8 = op1_8 - op2_8;
916 SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
918 if (BX_CPU_THIS_PTR get_DF()) {
919 si--;
920 di--;
922 else {
923 si++;
924 di++;
927 DI = di;
928 SI = si;
931 /* 32 bit address size */
932 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB32_XbYb(bxInstruction_c *i)
934 Bit8u op1_8, op2_8, diff_8;
936 Bit32u esi = ESI;
937 Bit32u edi = EDI;
939 op1_8 = read_virtual_byte(i->seg(), esi);
940 op2_8 = read_virtual_byte(BX_SEG_REG_ES, edi);
942 diff_8 = op1_8 - op2_8;
944 SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
946 if (BX_CPU_THIS_PTR get_DF()) {
947 esi--;
948 edi--;
950 else {
951 esi++;
952 edi++;
955 // zero extension of RSI/RDI
956 RDI = edi;
957 RSI = esi;
960 #if BX_SUPPORT_X86_64
961 /* 64 bit address size */
962 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB64_XbYb(bxInstruction_c *i)
964 Bit8u op1_8, op2_8, diff_8;
966 Bit64u rsi = RSI;
967 Bit64u rdi = RDI;
969 op1_8 = read_virtual_byte_64(i->seg(), rsi);
970 op2_8 = read_virtual_byte_64(BX_SEG_REG_ES, rdi);
972 diff_8 = op1_8 - op2_8;
974 SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
976 if (BX_CPU_THIS_PTR get_DF()) {
977 rsi--;
978 rdi--;
980 else {
981 rsi++;
982 rdi++;
985 RDI = rdi;
986 RSI = rsi;
988 #endif
990 /* 16 bit opsize mode, 16 bit address size */
991 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW16_XwYw(bxInstruction_c *i)
993 Bit16u op1_16, op2_16, diff_16;
995 Bit16u si = SI;
996 Bit16u di = DI;
998 op1_16 = read_virtual_word_32(i->seg(), si);
999 op2_16 = read_virtual_word_32(BX_SEG_REG_ES, di);
1001 diff_16 = op1_16 - op2_16;
1003 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1005 if (BX_CPU_THIS_PTR get_DF()) {
1006 si -= 2;
1007 di -= 2;
1009 else {
1010 si += 2;
1011 di += 2;
1014 DI = di;
1015 SI = si;
1018 /* 16 bit opsize mode, 32 bit address size */
1019 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW32_XwYw(bxInstruction_c *i)
1021 Bit16u op1_16, op2_16, diff_16;
1023 Bit32u esi = ESI;
1024 Bit32u edi = EDI;
1026 op1_16 = read_virtual_word(i->seg(), esi);
1027 op2_16 = read_virtual_word(BX_SEG_REG_ES, edi);
1029 diff_16 = op1_16 - op2_16;
1031 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1033 if (BX_CPU_THIS_PTR get_DF()) {
1034 esi -= 2;
1035 edi -= 2;
1037 else {
1038 esi += 2;
1039 edi += 2;
1042 // zero extension of RSI/RDI
1043 RDI = edi;
1044 RSI = esi;
1047 #if BX_SUPPORT_X86_64
1048 /* 16 bit opsize mode, 64 bit address size */
1049 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW64_XwYw(bxInstruction_c *i)
1051 Bit16u op1_16, op2_16, diff_16;
1053 Bit64u rsi = RSI;
1054 Bit64u rdi = RDI;
1056 op1_16 = read_virtual_word_64(i->seg(), rsi);
1057 op2_16 = read_virtual_word_64(BX_SEG_REG_ES, rdi);
1059 diff_16 = op1_16 - op2_16;
1061 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1063 if (BX_CPU_THIS_PTR get_DF()) {
1064 rsi -= 2;
1065 rdi -= 2;
1067 else {
1068 rsi += 2;
1069 rdi += 2;
1072 RDI = rdi;
1073 RSI = rsi;
1075 #endif
1077 /* 32 bit opsize mode, 16 bit address size */
1078 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD16_XdYd(bxInstruction_c *i)
1080 Bit32u op1_32, op2_32, diff_32;
1082 Bit16u si = SI;
1083 Bit16u di = DI;
1085 op1_32 = read_virtual_dword_32(i->seg(), si);
1086 op2_32 = read_virtual_dword_32(BX_SEG_REG_ES, di);
1088 diff_32 = op1_32 - op2_32;
1090 SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1092 if (BX_CPU_THIS_PTR get_DF()) {
1093 si -= 4;
1094 di -= 4;
1096 else {
1097 si += 4;
1098 di += 4;
1101 DI = di;
1102 SI = si;
1105 /* 32 bit opsize mode, 32 bit address size */
1106 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD32_XdYd(bxInstruction_c *i)
1108 Bit32u op1_32, op2_32, diff_32;
1110 Bit32u esi = ESI;
1111 Bit32u edi = EDI;
1113 op1_32 = read_virtual_dword(i->seg(), esi);
1114 op2_32 = read_virtual_dword(BX_SEG_REG_ES, edi);
1116 diff_32 = op1_32 - op2_32;
1118 SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1120 if (BX_CPU_THIS_PTR get_DF()) {
1121 esi -= 4;
1122 edi -= 4;
1124 else {
1125 esi += 4;
1126 edi += 4;
1129 // zero extension of RSI/RDI
1130 RDI = edi;
1131 RSI = esi;
1134 #if BX_SUPPORT_X86_64
1136 /* 32 bit opsize mode, 64 bit address size */
1137 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD64_XdYd(bxInstruction_c *i)
1139 Bit32u op1_32, op2_32, diff_32;
1141 Bit64u rsi = RSI;
1142 Bit64u rdi = RDI;
1144 op1_32 = read_virtual_dword_64(i->seg(), rsi);
1145 op2_32 = read_virtual_dword_64(BX_SEG_REG_ES, rdi);
1147 diff_32 = op1_32 - op2_32;
1149 SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1151 if (BX_CPU_THIS_PTR get_DF()) {
1152 rsi -= 4;
1153 rdi -= 4;
1155 else {
1156 rsi += 4;
1157 rdi += 4;
1160 RDI = rdi;
1161 RSI = rsi;
1164 /* 64 bit opsize mode, 32 bit address size */
1165 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSQ32_XqYq(bxInstruction_c *i)
1167 Bit64u op1_64, op2_64, diff_64;
1169 Bit32u esi = ESI;
1170 Bit32u edi = EDI;
1172 op1_64 = read_virtual_qword_64(i->seg(), esi);
1173 op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, edi);
1175 diff_64 = op1_64 - op2_64;
1177 SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
1179 if (BX_CPU_THIS_PTR get_DF()) {
1180 esi -= 8;
1181 edi -= 8;
1183 else {
1184 esi += 8;
1185 edi += 8;
1188 // zero extension of RSI/RDI
1189 RDI = edi;
1190 RSI = esi;
1193 /* 64 bit opsize mode, 64 bit address size */
1194 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSQ64_XqYq(bxInstruction_c *i)
1196 Bit64u op1_64, op2_64, diff_64;
1198 Bit64u rsi = RSI;
1199 Bit64u rdi = RDI;
1201 op1_64 = read_virtual_qword_64(i->seg(), rsi);
1202 op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, rdi);
1204 diff_64 = op1_64 - op2_64;
1206 SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
1208 if (BX_CPU_THIS_PTR get_DF()) {
1209 rsi -= 8;
1210 rdi -= 8;
1212 else {
1213 rsi += 8;
1214 rdi += 8;
1217 RDI = rdi;
1218 RSI = rsi;
1221 #endif
1224 // REP SCAS methods
1227 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASB_ALXb(bxInstruction_c *i)
1229 #if BX_SUPPORT_X86_64
1230 if (i->as64L()) {
1231 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB64_ALXb);
1233 else
1234 #endif
1235 if (i->as32L()) {
1236 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB32_ALXb);
1237 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1239 else {
1240 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB16_ALXb);
1244 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASW_AXXw(bxInstruction_c *i)
1246 #if BX_SUPPORT_X86_64
1247 if (i->as64L()) {
1248 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW64_AXXw);
1250 else
1251 #endif
1252 if (i->as32L()) {
1253 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW32_AXXw);
1254 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1256 else {
1257 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW16_AXXw);
1261 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASD_EAXXd(bxInstruction_c *i)
1263 #if BX_SUPPORT_X86_64
1264 if (i->as64L()) {
1265 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD64_EAXXd);
1267 else
1268 #endif
1269 if (i->as32L()) {
1270 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD32_EAXXd);
1271 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1273 else {
1274 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD16_EAXXd);
1278 #if BX_SUPPORT_X86_64
1279 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASQ_RAXXq(bxInstruction_c *i)
1281 if (i->as64L()) {
1282 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASQ64_RAXXq);
1284 else {
1285 BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASQ32_RAXXq);
1286 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1289 #endif
1292 // SCASB/SCASW/SCASD/SCASQ methods
1295 /* 16 bit address size */
1296 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB16_ALXb(bxInstruction_c *i)
1298 Bit8u op1_8 = AL, op2_8, diff_8;
1300 Bit16u di = DI;
1302 op2_8 = read_virtual_byte_32(BX_SEG_REG_ES, di);
1304 diff_8 = op1_8 - op2_8;
1306 SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
1308 if (BX_CPU_THIS_PTR get_DF()) {
1309 di--;
1311 else {
1312 di++;
1315 DI = di;
1318 /* 32 bit address size */
1319 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB32_ALXb(bxInstruction_c *i)
1321 Bit8u op1_8 = AL, op2_8, diff_8;
1323 Bit32u edi = EDI;
1325 op2_8 = read_virtual_byte(BX_SEG_REG_ES, edi);
1326 diff_8 = op1_8 - op2_8;
1328 SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
1330 if (BX_CPU_THIS_PTR get_DF()) {
1331 edi--;
1333 else {
1334 edi++;
1337 // zero extension of RDI
1338 RDI = edi;
1341 #if BX_SUPPORT_X86_64
1342 /* 64 bit address size */
1343 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB64_ALXb(bxInstruction_c *i)
1345 Bit8u op1_8 = AL, op2_8, diff_8;
1347 Bit64u rdi = RDI;
1349 op2_8 = read_virtual_byte_64(BX_SEG_REG_ES, rdi);
1351 diff_8 = op1_8 - op2_8;
1353 SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
1355 if (BX_CPU_THIS_PTR get_DF()) {
1356 rdi--;
1358 else {
1359 rdi++;
1362 RDI = rdi;
1364 #endif
1366 /* 16 bit opsize mode, 16 bit address size */
1367 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW16_AXXw(bxInstruction_c *i)
1369 Bit16u op1_16 = AX, op2_16, diff_16;
1371 Bit16u di = DI;
1373 op2_16 = read_virtual_word_32(BX_SEG_REG_ES, di);
1374 diff_16 = op1_16 - op2_16;
1376 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1378 if (BX_CPU_THIS_PTR get_DF()) {
1379 di -= 2;
1381 else {
1382 di += 2;
1385 DI = di;
1388 /* 16 bit opsize mode, 32 bit address size */
1389 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW32_AXXw(bxInstruction_c *i)
1391 Bit16u op1_16 = AX, op2_16, diff_16;
1393 Bit32u edi = EDI;
1395 op2_16 = read_virtual_word(BX_SEG_REG_ES, edi);
1396 diff_16 = op1_16 - op2_16;
1398 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1400 if (BX_CPU_THIS_PTR get_DF()) {
1401 edi -= 2;
1403 else {
1404 edi += 2;
1407 // zero extension of RDI
1408 RDI = edi;
1411 #if BX_SUPPORT_X86_64
1412 /* 16 bit opsize mode, 64 bit address size */
1413 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW64_AXXw(bxInstruction_c *i)
1415 Bit16u op1_16 = AX, op2_16, diff_16;
1417 Bit64u rdi = RDI;
1419 op2_16 = read_virtual_word_64(BX_SEG_REG_ES, rdi);
1421 diff_16 = op1_16 - op2_16;
1423 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1425 if (BX_CPU_THIS_PTR get_DF()) {
1426 rdi -= 2;
1428 else {
1429 rdi += 2;
1432 RDI = rdi;
1434 #endif
1436 /* 32 bit opsize mode, 16 bit address size */
1437 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD16_EAXXd(bxInstruction_c *i)
1439 Bit32u op1_32 = EAX, op2_32, diff_32;
1441 Bit16u di = DI;
1443 op2_32 = read_virtual_dword_32(BX_SEG_REG_ES, di);
1444 diff_32 = op1_32 - op2_32;
1446 SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1448 if (BX_CPU_THIS_PTR get_DF()) {
1449 di -= 4;
1451 else {
1452 di += 4;
1455 DI = di;
1458 /* 32 bit opsize mode, 32 bit address size */
1459 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD32_EAXXd(bxInstruction_c *i)
1461 Bit32u op1_32 = EAX, op2_32, diff_32;
1463 Bit32u edi = EDI;
1465 op2_32 = read_virtual_dword(BX_SEG_REG_ES, edi);
1466 diff_32 = op1_32 - op2_32;
1468 SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1470 if (BX_CPU_THIS_PTR get_DF()) {
1471 edi -= 4;
1473 else {
1474 edi += 4;
1477 // zero extension of RDI
1478 RDI = edi;
1481 #if BX_SUPPORT_X86_64
1483 /* 32 bit opsize mode, 64 bit address size */
1484 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD64_EAXXd(bxInstruction_c *i)
1486 Bit32u op1_32 = EAX, op2_32, diff_32;
1488 Bit64u rdi = RDI;
1490 op2_32 = read_virtual_dword_64(BX_SEG_REG_ES, rdi);
1492 diff_32 = op1_32 - op2_32;
1494 SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1496 if (BX_CPU_THIS_PTR get_DF()) {
1497 rdi -= 4;
1499 else {
1500 rdi += 4;
1503 RDI = rdi;
1506 /* 64 bit opsize mode, 32 bit address size */
1507 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASQ32_RAXXq(bxInstruction_c *i)
1509 Bit64u op1_64 = RAX, op2_64, diff_64;
1511 Bit32u edi = EDI;
1513 op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, edi);
1515 diff_64 = op1_64 - op2_64;
1517 SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
1519 if (BX_CPU_THIS_PTR get_DF()) {
1520 edi -= 8;
1522 else {
1523 edi += 8;
1526 // zero extension of RDI
1527 RDI = edi;
1530 /* 64 bit opsize mode, 64 bit address size */
1531 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASQ64_RAXXq(bxInstruction_c *i)
1533 Bit64u op1_64 = RAX, op2_64, diff_64;
1535 Bit64u rdi = RDI;
1537 op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, rdi);
1539 diff_64 = op1_64 - op2_64;
1541 SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
1543 if (BX_CPU_THIS_PTR get_DF()) {
1544 rdi -= 8;
1546 else {
1547 rdi += 8;
1550 RDI = rdi;
1553 #endif
1556 // REP STOS methods
1559 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSB_YbAL(bxInstruction_c *i)
1561 #if BX_SUPPORT_X86_64
1562 if (i->as64L())
1563 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB64_YbAL);
1564 else
1565 #endif
1566 if (i->as32L()) {
1567 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB32_YbAL);
1568 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1570 else {
1571 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB16_YbAL);
1575 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSW_YwAX(bxInstruction_c *i)
1577 #if BX_SUPPORT_X86_64
1578 if (i->as64L())
1579 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW64_YwAX);
1580 else
1581 #endif
1582 if (i->as32L()) {
1583 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW32_YwAX);
1584 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1586 else {
1587 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW16_YwAX);
1591 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSD_YdEAX(bxInstruction_c *i)
1593 #if BX_SUPPORT_X86_64
1594 if (i->as64L())
1595 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD64_YdEAX);
1596 else
1597 #endif
1598 if (i->as32L()) {
1599 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD32_YdEAX);
1600 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1602 else {
1603 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD16_YdEAX);
1607 #if BX_SUPPORT_X86_64
1608 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSQ_YqRAX(bxInstruction_c *i)
1610 if (i->as64L()) {
1611 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSQ64_YqRAX);
1613 else {
1614 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSQ32_YqRAX);
1615 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1618 #endif
1621 // STOSB/STOSW/STOSD/STOSQ methods
1624 // 16 bit address size
1625 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB16_YbAL(bxInstruction_c *i)
1627 Bit16u di = DI;
1629 write_virtual_byte_32(BX_SEG_REG_ES, di, AL);
1631 if (BX_CPU_THIS_PTR get_DF()) {
1632 di--;
1634 else {
1635 di++;
1638 DI = di;
1641 // 32 bit address size
1642 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB32_YbAL(bxInstruction_c *i)
1644 Bit32u incr = 1;
1645 Bit32u edi = EDI;
1647 #if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
1648 /* If conditions are right, we can transfer IO to physical memory
1649 * in a batch, rather than one instruction at a time.
1651 if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
1653 Bit32u byteCount = FastRepSTOSB(i, BX_SEG_REG_ES, edi, AL, ECX);
1654 if (byteCount) {
1655 // Decrement the ticks count by the number of iterations, minus
1656 // one, since the main cpu loop will decrement one. Also,
1657 // the count is predecremented before examined, so defintely
1658 // don't roll it under zero.
1659 BX_TICKN(byteCount-1);
1661 // Decrement eCX. Note, the main loop will decrement 1 also, so
1662 // decrement by one less than expected, like the case above.
1663 RCX = ECX - (byteCount-1);
1665 incr = byteCount;
1667 else {
1668 write_virtual_byte(BX_SEG_REG_ES, edi, AL);
1671 else
1672 #endif
1674 write_virtual_byte(BX_SEG_REG_ES, edi, AL);
1677 if (BX_CPU_THIS_PTR get_DF()) {
1678 edi -= incr;
1680 else {
1681 edi += incr;
1684 // zero extension of RDI
1685 RDI = edi;
1688 #if BX_SUPPORT_X86_64
1689 // 64 bit address size
1690 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB64_YbAL(bxInstruction_c *i)
1692 Bit64u rdi = RDI;
1694 write_virtual_byte_64(BX_SEG_REG_ES, rdi, AL);
1696 if (BX_CPU_THIS_PTR get_DF()) {
1697 rdi--;
1699 else {
1700 rdi++;
1703 RDI = rdi;
1705 #endif
1707 /* 16 bit opsize mode, 16 bit address size */
1708 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW16_YwAX(bxInstruction_c *i)
1710 Bit16u di = DI;
1712 write_virtual_word_32(BX_SEG_REG_ES, di, AX);
1714 if (BX_CPU_THIS_PTR get_DF()) {
1715 di -= 2;
1717 else {
1718 di += 2;
1721 DI = di;
1724 /* 16 bit opsize mode, 32 bit address size */
1725 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW32_YwAX(bxInstruction_c *i)
1727 Bit32u edi = EDI;
1729 write_virtual_word(BX_SEG_REG_ES, edi, AX);
1731 if (BX_CPU_THIS_PTR get_DF()) {
1732 edi -= 2;
1734 else {
1735 edi += 2;
1738 // zero extension of RDI
1739 RDI = edi;
1742 #if BX_SUPPORT_X86_64
1743 /* 16 bit opsize mode, 32 bit address size */
1744 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW64_YwAX(bxInstruction_c *i)
1746 Bit64u rdi = RDI;
1748 write_virtual_word_64(BX_SEG_REG_ES, rdi, AX);
1750 if (BX_CPU_THIS_PTR get_DF()) {
1751 rdi -= 2;
1753 else {
1754 rdi += 2;
1757 RDI = rdi;
1759 #endif
1761 /* 32 bit opsize mode, 16 bit address size */
1762 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD16_YdEAX(bxInstruction_c *i)
1764 Bit16u di = DI;
1766 write_virtual_dword_32(BX_SEG_REG_ES, di, EAX);
1768 if (BX_CPU_THIS_PTR get_DF()) {
1769 di -= 4;
1771 else {
1772 di += 4;
1775 DI = di;
1778 /* 32 bit opsize mode, 32 bit address size */
1779 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD32_YdEAX(bxInstruction_c *i)
1781 Bit32u edi = EDI;
1783 write_virtual_dword(BX_SEG_REG_ES, edi, EAX);
1785 if (BX_CPU_THIS_PTR get_DF()) {
1786 edi -= 4;
1788 else {
1789 edi += 4;
1792 // zero extension of RDI
1793 RDI = edi;
1796 #if BX_SUPPORT_X86_64
1798 /* 32 bit opsize mode, 32 bit address size */
1799 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD64_YdEAX(bxInstruction_c *i)
1801 Bit64u rdi = RDI;
1803 write_virtual_dword_64(BX_SEG_REG_ES, rdi, EAX);
1805 if (BX_CPU_THIS_PTR get_DF()) {
1806 rdi -= 4;
1808 else {
1809 rdi += 4;
1812 RDI = rdi;
1815 /* 64 bit opsize mode, 32 bit address size */
1816 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSQ32_YqRAX(bxInstruction_c *i)
1818 Bit32u edi = EDI;
1820 write_virtual_qword_64(BX_SEG_REG_ES, edi, RAX);
1822 if (BX_CPU_THIS_PTR get_DF()) {
1823 edi -= 8;
1825 else {
1826 edi += 8;
1829 // zero extension of RDI
1830 RDI = edi;
1833 /* 64 bit opsize mode, 64 bit address size */
1834 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSQ64_YqRAX(bxInstruction_c *i)
1836 Bit64u rdi = RDI;
1838 write_virtual_qword_64(BX_SEG_REG_ES, rdi, RAX);
1840 if (BX_CPU_THIS_PTR get_DF()) {
1841 rdi -= 8;
1843 else {
1844 rdi += 8;
1847 RDI = rdi;
1850 #endif
1853 // REP LODS methods
1856 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSB_ALXb(bxInstruction_c *i)
1858 #if BX_SUPPORT_X86_64
1859 if (i->as64L())
1860 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB64_ALXb);
1861 else
1862 #endif
1863 if (i->as32L()) {
1864 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB32_ALXb);
1865 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
1867 else {
1868 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB16_ALXb);
1872 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSW_AXXw(bxInstruction_c *i)
1874 #if BX_SUPPORT_X86_64
1875 if (i->as64L())
1876 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW64_AXXw);
1877 else
1878 #endif
1879 if (i->as32L()) {
1880 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW32_AXXw);
1881 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
1883 else {
1884 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW16_AXXw);
1888 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSD_EAXXd(bxInstruction_c *i)
1890 #if BX_SUPPORT_X86_64
1891 if (i->as64L())
1892 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD64_EAXXd);
1893 else
1894 #endif
1895 if (i->as32L()) {
1896 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD32_EAXXd);
1897 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
1899 else {
1900 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD16_EAXXd);
1904 #if BX_SUPPORT_X86_64
1905 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSQ_RAXXq(bxInstruction_c *i)
1907 if (i->as64L()) {
1908 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSQ64_RAXXq);
1910 else {
1911 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSQ32_RAXXq);
1912 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
1915 #endif
1918 // LODSB/LODSW/LODSD/LODSQ methods
1921 /* 16 bit address size */
1922 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB16_ALXb(bxInstruction_c *i)
1924 Bit16u si = SI;
1926 AL = read_virtual_byte_32(i->seg(), si);
1928 if (BX_CPU_THIS_PTR get_DF()) {
1929 si--;
1931 else {
1932 si++;
1935 SI = si;
1938 /* 32 bit address size */
1939 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB32_ALXb(bxInstruction_c *i)
1941 Bit32u esi = ESI;
1943 AL = read_virtual_byte(i->seg(), esi);
1945 if (BX_CPU_THIS_PTR get_DF()) {
1946 esi--;
1948 else {
1949 esi++;
1952 // zero extension of RSI
1953 RSI = esi;
1956 #if BX_SUPPORT_X86_64
1957 /* 64 bit address size */
1958 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB64_ALXb(bxInstruction_c *i)
1960 Bit64u rsi = RSI;
1962 AL = read_virtual_byte_64(i->seg(), rsi);
1964 if (BX_CPU_THIS_PTR get_DF()) {
1965 rsi--;
1967 else {
1968 rsi++;
1971 RSI = rsi;
1973 #endif
1975 /* 16 bit opsize mode, 16 bit address size */
1976 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW16_AXXw(bxInstruction_c *i)
1978 Bit16u si = SI;
1980 AX = read_virtual_word_32(i->seg(), si);
1982 if (BX_CPU_THIS_PTR get_DF()) {
1983 si -= 2;
1985 else {
1986 si += 2;
1989 SI = si;
1992 /* 16 bit opsize mode, 32 bit address size */
1993 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW32_AXXw(bxInstruction_c *i)
1995 Bit32u esi = ESI;
1997 AX = read_virtual_word(i->seg(), esi);
1999 if (BX_CPU_THIS_PTR get_DF()) {
2000 esi -= 2;
2002 else {
2003 esi += 2;
2006 // zero extension of RSI
2007 RSI = esi;
2010 #if BX_SUPPORT_X86_64
2011 /* 16 bit opsize mode, 64 bit address size */
2012 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW64_AXXw(bxInstruction_c *i)
2014 Bit64u rsi = RSI;
2016 AX = read_virtual_word_64(i->seg(), rsi);
2018 if (BX_CPU_THIS_PTR get_DF()) {
2019 rsi -= 2;
2021 else {
2022 rsi += 2;
2025 RSI = rsi;
2027 #endif
2029 /* 32 bit opsize mode, 16 bit address size */
2030 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD16_EAXXd(bxInstruction_c *i)
2032 Bit16u si = SI;
2034 RAX = read_virtual_dword_32(i->seg(), si);
2036 if (BX_CPU_THIS_PTR get_DF()) {
2037 si -= 4;
2039 else {
2040 si += 4;
2043 SI = si;
2046 /* 32 bit opsize mode, 32 bit address size */
2047 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD32_EAXXd(bxInstruction_c *i)
2049 Bit32u esi = ESI;
2051 RAX = read_virtual_dword(i->seg(), esi);
2053 if (BX_CPU_THIS_PTR get_DF()) {
2054 esi -= 4;
2056 else {
2057 esi += 4;
2060 // zero extension of RSI
2061 RSI = esi;
2064 #if BX_SUPPORT_X86_64
2066 /* 32 bit opsize mode, 64 bit address size */
2067 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD64_EAXXd(bxInstruction_c *i)
2069 Bit64u rsi = RSI;
2071 RAX = read_virtual_dword_64(i->seg(), rsi);
2073 if (BX_CPU_THIS_PTR get_DF()) {
2074 rsi -= 4;
2076 else {
2077 rsi += 4;
2080 RSI = rsi;
2083 /* 64 bit opsize mode, 32 bit address size */
2084 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSQ32_RAXXq(bxInstruction_c *i)
2086 Bit32u esi = ESI;
2088 RAX = read_virtual_qword_64(i->seg(), esi);
2090 if (BX_CPU_THIS_PTR get_DF()) {
2091 esi -= 8;
2093 else {
2094 esi += 8;
2097 // zero extension of RSI
2098 RSI = esi;
2101 /* 64 bit opsize mode, 64 bit address size */
2102 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSQ64_RAXXq(bxInstruction_c *i)
2104 Bit64u rsi = RSI;
2106 RAX = read_virtual_qword_64(i->seg(), rsi);
2108 if (BX_CPU_THIS_PTR get_DF()) {
2109 rsi -= 8;
2111 else {
2112 rsi += 8;
2115 RSI = rsi;
2118 #endif