- tftp_send_optack() was not 64-bit clean (patch from SF bug #1787500)
[bochs-mirror.git] / cpu / arith32.cc
blob59284f59a3d058c6a4258423ce6066380839dfa8
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: arith32.cc,v 1.50 2007/01/26 22:12:05 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
29 #define NEED_CPU_REG_SHORTCUTS 1
30 #include "bochs.h"
31 #include "cpu.h"
32 #define LOG_THIS BX_CPU_THIS_PTR
35 #if BX_SUPPORT_X86_64==0
36 // Make life easier for merging cpu64 and cpu code.
37 #define RAX EAX
38 #define RDX EDX
39 #endif
42 void BX_CPU_C::INC_ERX(bxInstruction_c *i)
44 unsigned opcodeReg = i->opcodeReg();
46 #if defined(BX_HostAsm_Inc32)
47 Bit32u flags32;
48 asmInc32(BX_CPU_THIS_PTR gen_reg[opcodeReg].dword.erx, flags32);
49 setEFlagsOSZAP(flags32);
50 #else
51 Bit32u erx = ++ BX_CPU_THIS_PTR gen_reg[opcodeReg].dword.erx;
52 SET_FLAGS_OSZAP_RESULT_32(erx, BX_INSTR_INC32);
53 #endif
55 BX_CLEAR_64BIT_HIGH(opcodeReg);
58 void BX_CPU_C::DEC_ERX(bxInstruction_c *i)
60 unsigned opcodeReg = i->opcodeReg();
62 #if defined(BX_HostAsm_Dec32)
63 Bit32u flags32;
64 asmDec32(BX_CPU_THIS_PTR gen_reg[opcodeReg].dword.erx, flags32);
65 setEFlagsOSZAP(flags32);
66 #else
67 Bit32u erx = -- BX_CPU_THIS_PTR gen_reg[opcodeReg].dword.erx;
68 SET_FLAGS_OSZAP_RESULT_32(erx, BX_INSTR_DEC32);
69 #endif
71 BX_CLEAR_64BIT_HIGH(opcodeReg);
74 void BX_CPU_C::ADD_EdGd(bxInstruction_c *i)
76 Bit32u op2_32, op1_32, sum_32;
78 op2_32 = BX_READ_32BIT_REG(i->nnn());
80 if (i->modC0()) {
81 op1_32 = BX_READ_32BIT_REG(i->rm());
82 sum_32 = op1_32 + op2_32;
83 BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
85 else {
86 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
87 sum_32 = op1_32 + op2_32;
88 write_RMW_virtual_dword(sum_32);
91 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
94 void BX_CPU_C::ADD_GdEEd(bxInstruction_c *i)
96 Bit32u op1_32, op2_32, sum_32;
97 unsigned nnn = i->nnn();
99 op1_32 = BX_READ_32BIT_REG(nnn);
101 read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
103 #if defined(BX_HostAsm_Add32)
104 Bit32u flags32;
105 asmAdd32(sum_32, op1_32, op2_32, flags32);
106 setEFlagsOSZAPC(flags32);
107 #else
108 sum_32 = op1_32 + op2_32;
109 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
110 #endif
112 BX_WRITE_32BIT_REGZ(nnn, sum_32);
115 void BX_CPU_C::ADD_GdEGd(bxInstruction_c *i)
117 Bit32u op1_32, op2_32, sum_32;
118 unsigned nnn = i->nnn();
120 op1_32 = BX_READ_32BIT_REG(nnn);
121 op2_32 = BX_READ_32BIT_REG(i->rm());
123 #if defined(BX_HostAsm_Add32)
124 Bit32u flags32;
125 asmAdd32(sum_32, op1_32, op2_32, flags32);
126 setEFlagsOSZAPC(flags32);
127 #else
128 sum_32 = op1_32 + op2_32;
129 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
130 #endif
132 BX_WRITE_32BIT_REGZ(nnn, sum_32);
135 void BX_CPU_C::ADD_EAXId(bxInstruction_c *i)
137 Bit32u op1_32, op2_32, sum_32;
139 op1_32 = EAX;
140 op2_32 = i->Id();
141 sum_32 = op1_32 + op2_32;
143 RAX = sum_32;
145 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
148 void BX_CPU_C::ADC_EdGd(bxInstruction_c *i)
150 bx_bool temp_CF = getB_CF();
152 Bit32u op2_32, op1_32, sum_32;
154 op2_32 = BX_READ_32BIT_REG(i->nnn());
156 if (i->modC0()) {
157 op1_32 = BX_READ_32BIT_REG(i->rm());
158 sum_32 = op1_32 + op2_32 + temp_CF;
159 BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
161 else {
162 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
163 sum_32 = op1_32 + op2_32 + temp_CF;
164 write_RMW_virtual_dword(sum_32);
167 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD_ADC32(temp_CF));
170 void BX_CPU_C::ADC_GdEd(bxInstruction_c *i)
172 bx_bool temp_CF = getB_CF();
174 Bit32u op1_32, op2_32, sum_32;
176 op1_32 = BX_READ_32BIT_REG(i->nnn());
178 if (i->modC0()) {
179 op2_32 = BX_READ_32BIT_REG(i->rm());
181 else {
182 read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
185 sum_32 = op1_32 + op2_32 + temp_CF;
187 BX_WRITE_32BIT_REGZ(i->nnn(), sum_32);
189 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD_ADC32(temp_CF));
192 void BX_CPU_C::ADC_EAXId(bxInstruction_c *i)
194 bx_bool temp_CF = getB_CF();
196 Bit32u op1_32, op2_32, sum_32;
198 op1_32 = EAX;
199 op2_32 = i->Id();
200 sum_32 = op1_32 + op2_32 + temp_CF;
202 RAX = sum_32;
204 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD_ADC32(temp_CF));
207 void BX_CPU_C::SBB_EdGd(bxInstruction_c *i)
209 bx_bool temp_CF = getB_CF();
211 Bit32u op2_32, op1_32, diff_32;
213 op2_32 = BX_READ_32BIT_REG(i->nnn());
215 if (i->modC0()) {
216 op1_32 = BX_READ_32BIT_REG(i->rm());
217 diff_32 = op1_32 - (op2_32 + temp_CF);
218 BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
220 else {
221 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
222 diff_32 = op1_32 - (op2_32 + temp_CF);
223 write_RMW_virtual_dword(diff_32);
226 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB_SBB32(temp_CF));
229 void BX_CPU_C::SBB_GdEd(bxInstruction_c *i)
231 bx_bool temp_CF = getB_CF();
233 Bit32u op1_32, op2_32, diff_32;
235 op1_32 = BX_READ_32BIT_REG(i->nnn());
237 if (i->modC0()) {
238 op2_32 = BX_READ_32BIT_REG(i->rm());
240 else {
241 read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
244 diff_32 = op1_32 - (op2_32 + temp_CF);
246 BX_WRITE_32BIT_REGZ(i->nnn(), diff_32);
248 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB_SBB32(temp_CF));
251 void BX_CPU_C::SBB_EAXId(bxInstruction_c *i)
253 bx_bool temp_CF = getB_CF();
255 Bit32u op1_32, op2_32, diff_32;
257 op1_32 = EAX;
258 op2_32 = i->Id();
259 diff_32 = op1_32 - (op2_32 + temp_CF);
261 RAX = diff_32;
263 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB_SBB32(temp_CF));
266 void BX_CPU_C::SBB_EdId(bxInstruction_c *i)
268 bx_bool temp_CF = getB_CF();
270 Bit32u op2_32, op1_32, diff_32;
272 op2_32 = i->Id();
274 if (i->modC0()) {
275 op1_32 = BX_READ_32BIT_REG(i->rm());
276 diff_32 = op1_32 - (op2_32 + temp_CF);
277 BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
279 else {
280 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
281 diff_32 = op1_32 - (op2_32 + temp_CF);
282 write_RMW_virtual_dword(diff_32);
285 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB_SBB32(temp_CF));
288 void BX_CPU_C::SUB_EdGd(bxInstruction_c *i)
290 Bit32u op2_32, op1_32, diff_32;
292 op2_32 = BX_READ_32BIT_REG(i->nnn());
294 if (i->modC0()) {
295 op1_32 = BX_READ_32BIT_REG(i->rm());
296 diff_32 = op1_32 - op2_32;
297 BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
299 else {
300 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
301 diff_32 = op1_32 - op2_32;
302 write_RMW_virtual_dword(diff_32);
305 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
308 void BX_CPU_C::SUB_GdEd(bxInstruction_c *i)
310 Bit32u op1_32, op2_32, diff_32;
311 unsigned nnn = i->nnn();
313 op1_32 = BX_READ_32BIT_REG(nnn);
315 if (i->modC0()) {
316 op2_32 = BX_READ_32BIT_REG(i->rm());
318 else {
319 read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
322 #if defined(BX_HostAsm_Sub32)
323 Bit32u flags32;
324 asmSub32(diff_32, op1_32, op2_32, flags32);
325 setEFlagsOSZAPC(flags32);
326 #else
327 diff_32 = op1_32 - op2_32;
328 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
329 #endif
331 BX_WRITE_32BIT_REGZ(nnn, diff_32);
334 void BX_CPU_C::SUB_EAXId(bxInstruction_c *i)
336 Bit32u op1_32, op2_32, diff_32;
338 op1_32 = EAX;
339 op2_32 = i->Id();
340 diff_32 = op1_32 - op2_32;
342 RAX = diff_32;
344 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
347 void BX_CPU_C::CMP_EdGd(bxInstruction_c *i)
349 Bit32u op2_32, op1_32;
351 op2_32 = BX_READ_32BIT_REG(i->nnn());
353 if (i->modC0()) {
354 op1_32 = BX_READ_32BIT_REG(i->rm());
356 else {
357 read_virtual_dword(i->seg(), RMAddr(i), &op1_32);
360 #if defined(BX_HostAsm_Cmp32)
361 Bit32u flags32;
362 asmCmp32(op1_32, op2_32, flags32);
363 setEFlagsOSZAPC(flags32);
364 #else
365 Bit32u diff_32 = op1_32 - op2_32;
366 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_COMPARE32);
367 #endif
370 void BX_CPU_C::CMP_GdEd(bxInstruction_c *i)
372 Bit32u op1_32, op2_32;
374 op1_32 = BX_READ_32BIT_REG(i->nnn());
376 if (i->modC0()) {
377 op2_32 = BX_READ_32BIT_REG(i->rm());
379 else {
380 read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
383 #if defined(BX_HostAsm_Cmp32)
384 Bit32u flags32;
385 asmCmp32(op1_32, op2_32, flags32);
386 setEFlagsOSZAPC(flags32);
387 #else
388 Bit32u diff_32 = op1_32 - op2_32;
389 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_COMPARE32);
390 #endif
393 void BX_CPU_C::CMP_EAXId(bxInstruction_c *i)
395 Bit32u op1_32, op2_32;
397 op1_32 = EAX;
398 op2_32 = i->Id();
400 #if defined(BX_HostAsm_Cmp32)
401 Bit32u flags32;
402 asmCmp32(op1_32, op2_32, flags32);
403 setEFlagsOSZAPC(flags32);
404 #else
405 Bit32u diff_32 = op1_32 - op2_32;
406 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_COMPARE32);
407 #endif
410 void BX_CPU_C::CWDE(bxInstruction_c *i)
412 /* CWDE: no flags are effected */
413 Bit32u tmp = (Bit16s) AX;
414 RAX = tmp;
417 void BX_CPU_C::CDQ(bxInstruction_c *i)
419 /* CDQ: no flags are affected */
420 if (EAX & 0x80000000) {
421 RDX = 0xFFFFFFFF;
423 else {
424 RDX = 0x00000000;
428 // Some info on the opcodes at {0F,A6} and {0F,A7}
429 // On 386 steps A0-B0:
430 // {OF,A6} = XBTS
431 // {OF,A7} = IBTS
432 // On 486 steps A0-B0:
433 // {OF,A6} = CMPXCHG 8
434 // {OF,A7} = CMPXCHG 16|32
436 // On 486 >= B steps, and further processors, the
437 // CMPXCHG instructions were moved to opcodes:
438 // {OF,B0} = CMPXCHG 8
439 // {OF,B1} = CMPXCHG 16|32
441 void BX_CPU_C::CMPXCHG_XBTS(bxInstruction_c *i)
443 BX_INFO(("CMPXCHG_XBTS: Generate #UD exception"));
444 UndefinedOpcode(i);
447 void BX_CPU_C::CMPXCHG_IBTS(bxInstruction_c *i)
449 BX_INFO(("CMPXCHG_IBTS: Generate #UD exception"));
450 UndefinedOpcode(i);
453 void BX_CPU_C::XADD_EdGd(bxInstruction_c *i)
455 #if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
457 Bit32u op2_32, op1_32, sum_32;
459 /* XADD dst(r/m), src(r)
460 * temp <-- src + dst | sum = op2 + op1
461 * src <-- dst | op2 = op1
462 * dst <-- tmp | op1 = sum
465 op2_32 = BX_READ_32BIT_REG(i->nnn());
467 if (i->modC0()) {
468 op1_32 = BX_READ_32BIT_REG(i->rm());
469 sum_32 = op1_32 + op2_32;
470 // and write destination into source
471 // Note: if both op1 & op2 are registers, the last one written
472 // should be the sum, as op1 & op2 may be the same register.
473 // For example: XADD AL, AL
474 BX_WRITE_32BIT_REGZ(i->nnn(), op1_32);
475 BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
477 else {
478 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
479 sum_32 = op1_32 + op2_32;
480 write_RMW_virtual_dword(sum_32);
481 /* and write destination into source */
482 BX_WRITE_32BIT_REGZ(i->nnn(), op1_32);
485 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
486 #else
487 BX_INFO (("XADD_EdGd not supported for cpulevel <= 3"));
488 UndefinedOpcode(i);
489 #endif
492 void BX_CPU_C::ADD_EEdId(bxInstruction_c *i)
494 Bit32u op2_32, op1_32, sum_32;
496 op2_32 = i->Id();
498 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
500 #if defined(BX_HostAsm_Add32)
501 Bit32u flags32;
502 asmAdd32(sum_32, op1_32, op2_32, flags32);
503 setEFlagsOSZAPC(flags32);
504 #else
505 sum_32 = op1_32 + op2_32;
506 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
507 #endif
509 write_RMW_virtual_dword(sum_32);
512 void BX_CPU_C::ADD_EGdId(bxInstruction_c *i)
514 Bit32u op2_32, op1_32, sum_32;
516 op2_32 = i->Id();
517 op1_32 = BX_READ_32BIT_REG(i->rm());
519 #if defined(BX_HostAsm_Add32)
520 Bit32u flags32;
521 asmAdd32(sum_32, op1_32, op2_32, flags32);
522 setEFlagsOSZAPC(flags32);
523 #else
524 sum_32 = op1_32 + op2_32;
525 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
526 #endif
528 BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
531 void BX_CPU_C::ADC_EdId(bxInstruction_c *i)
533 bx_bool temp_CF = getB_CF();
535 Bit32u op2_32, op1_32, sum_32;
537 op2_32 = i->Id();
539 if (i->modC0()) {
540 op1_32 = BX_READ_32BIT_REG(i->rm());
541 sum_32 = op1_32 + op2_32 + temp_CF;
542 BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
544 else {
545 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
546 sum_32 = op1_32 + op2_32 + temp_CF;
547 write_RMW_virtual_dword(sum_32);
550 SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD_ADC32(temp_CF));
553 void BX_CPU_C::SUB_EdId(bxInstruction_c *i)
555 Bit32u op2_32, op1_32, diff_32;
557 op2_32 = i->Id();
559 if (i->modC0()) {
560 op1_32 = BX_READ_32BIT_REG(i->rm());
561 diff_32 = op1_32 - op2_32;
562 BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
564 else {
565 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
566 diff_32 = op1_32 - op2_32;
567 write_RMW_virtual_dword(diff_32);
570 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
573 void BX_CPU_C::CMP_EdId(bxInstruction_c *i)
575 Bit32u op2_32, op1_32;
577 op2_32 = i->Id();
579 if (i->modC0()) {
580 op1_32 = BX_READ_32BIT_REG(i->rm());
582 else {
583 read_virtual_dword(i->seg(), RMAddr(i), &op1_32);
586 #if defined(BX_HostAsm_Cmp32)
587 Bit32u flags32;
588 asmCmp32(op1_32, op2_32, flags32);
589 setEFlagsOSZAPC(flags32);
590 #else
591 Bit32u diff_32;
592 diff_32 = op1_32 - op2_32;
593 SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_COMPARE32);
594 #endif
597 void BX_CPU_C::NEG_Ed(bxInstruction_c *i)
599 Bit32u op1_32, diff_32;
601 if (i->modC0()) {
602 op1_32 = BX_READ_32BIT_REG(i->rm());
603 diff_32 = -op1_32;
604 BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
606 else {
607 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
608 diff_32 = -op1_32;
609 write_RMW_virtual_dword(diff_32);
612 SET_FLAGS_OSZAPC_RESULT_32(diff_32, BX_INSTR_NEG32);
615 void BX_CPU_C::INC_Ed(bxInstruction_c *i)
617 Bit32u op1_32;
619 if (i->modC0()) {
620 op1_32 = BX_READ_32BIT_REG(i->rm());
621 op1_32++;
622 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
624 else {
625 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
626 op1_32++;
627 write_RMW_virtual_dword(op1_32);
630 SET_FLAGS_OSZAP_RESULT_32(op1_32, BX_INSTR_INC32);
633 void BX_CPU_C::DEC_Ed(bxInstruction_c *i)
635 Bit32u op1_32;
637 if (i->modC0()) {
638 op1_32 = BX_READ_32BIT_REG(i->rm());
639 op1_32--;
640 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
642 else {
643 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
644 op1_32--;
645 write_RMW_virtual_dword(op1_32);
648 SET_FLAGS_OSZAP_RESULT_32(op1_32, BX_INSTR_DEC32);
651 void BX_CPU_C::CMPXCHG_EdGd(bxInstruction_c *i)
653 #if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
654 Bit32u op2_32, op1_32, diff_32;
656 if (i->modC0()) {
657 op1_32 = BX_READ_32BIT_REG(i->rm());
659 else {
660 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
663 diff_32 = EAX - op1_32;
665 SET_FLAGS_OSZAPC_32(EAX, op1_32, diff_32, BX_INSTR_COMPARE32);
667 if (diff_32 == 0) { // if accumulator == dest
668 // dest <-- src
669 op2_32 = BX_READ_32BIT_REG(i->nnn());
671 if (i->modC0()) {
672 BX_WRITE_32BIT_REGZ(i->rm(), op2_32);
674 else {
675 write_RMW_virtual_dword(op2_32);
678 else {
679 // accumulator <-- dest
680 RAX = op1_32;
682 #else
683 BX_INFO(("CMPXCHG_EdGd: not supported for cpulevel <= 3"));
684 UndefinedOpcode(i);
685 #endif
688 void BX_CPU_C::CMPXCHG8B(bxInstruction_c *i)
690 #if (BX_CPU_LEVEL >= 5) || (BX_CPU_LEVEL_HACKED >= 5)
691 Bit32u op1_64_lo, op1_64_hi, diff;
693 if (i->modC0()) {
694 BX_INFO(("CMPXCHG8B: dest is not memory location (#UD)"));
695 UndefinedOpcode(i);
698 read_virtual_dword(i->seg(), RMAddr(i), &op1_64_lo);
699 read_RMW_virtual_dword(i->seg(), RMAddr(i) + 4, &op1_64_hi);
701 diff = EAX - op1_64_lo;
702 diff |= EDX - op1_64_hi;
704 if (diff == 0) { // if accumulator == dest
705 // ZF = 1
706 set_ZF(1);
707 // dest <-- src
708 write_RMW_virtual_dword(ECX);
709 write_virtual_dword(i->seg(), RMAddr(i), &EBX);
711 else {
712 // ZF = 0
713 set_ZF(0);
714 // accumulator <-- dest
715 RAX = op1_64_lo;
716 RDX = op1_64_hi;
719 #else
720 BX_INFO(("CMPXCHG8B: not supported for cpulevel <= 4"));
721 UndefinedOpcode(i);
722 #endif