- compare disk size with the size calculated from geometry to avoid image
[bochs-mirror.git] / cpu / bit.cc
blobab4fce95332725b33c946d213f343bceaa6f28a9
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: bit.cc,v 1.31 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
28 #define NEED_CPU_REG_SHORTCUTS 1
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
34 #if BX_CPU_LEVEL >= 3
36 void BX_CPU_C::SETO_Eb(bxInstruction_c *i)
38 Bit8u result_8;
40 if (get_OF())
41 result_8 = 1;
42 else
43 result_8 = 0;
45 /* now write result back to destination */
46 if (i->modC0()) {
47 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
49 else {
50 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
54 void BX_CPU_C::SETNO_Eb(bxInstruction_c *i)
56 Bit8u result_8;
58 if (get_OF()==0)
59 result_8 = 1;
60 else
61 result_8 = 0;
63 /* now write result back to destination */
64 if (i->modC0()) {
65 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
67 else {
68 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
72 void BX_CPU_C::SETB_Eb(bxInstruction_c *i)
74 Bit8u result_8;
76 if (get_CF())
77 result_8 = 1;
78 else
79 result_8 = 0;
81 /* now write result back to destination */
82 if (i->modC0()) {
83 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
85 else {
86 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
90 void BX_CPU_C::SETNB_Eb(bxInstruction_c *i)
92 Bit8u result_8;
94 if (get_CF()==0)
95 result_8 = 1;
96 else
97 result_8 = 0;
99 /* now write result back to destination */
100 if (i->modC0()) {
101 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
103 else {
104 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
108 void BX_CPU_C::SETZ_Eb(bxInstruction_c *i)
110 Bit8u result_8;
112 if (get_ZF())
113 result_8 = 1;
114 else
115 result_8 = 0;
117 /* now write result back to destination */
118 if (i->modC0()) {
119 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
121 else {
122 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
126 void BX_CPU_C::SETNZ_Eb(bxInstruction_c *i)
128 Bit8u result_8;
130 if (get_ZF()==0)
131 result_8 = 1;
132 else
133 result_8 = 0;
135 /* now write result back to destination */
136 if (i->modC0()) {
137 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
139 else {
140 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
144 void BX_CPU_C::SETBE_Eb(bxInstruction_c *i)
146 Bit8u result_8;
148 if (get_CF() || get_ZF())
149 result_8 = 1;
150 else
151 result_8 = 0;
153 /* now write result back to destination */
154 if (i->modC0()) {
155 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
157 else {
158 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
162 void BX_CPU_C::SETNBE_Eb(bxInstruction_c *i)
164 Bit8u result_8;
166 if ((get_CF()==0) && (get_ZF()==0))
167 result_8 = 1;
168 else
169 result_8 = 0;
171 /* now write result back to destination */
172 if (i->modC0()) {
173 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
175 else {
176 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
180 void BX_CPU_C::SETS_Eb(bxInstruction_c *i)
182 Bit8u result_8;
184 if (get_SF())
185 result_8 = 1;
186 else
187 result_8 = 0;
189 /* now write result back to destination */
190 if (i->modC0()) {
191 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
193 else {
194 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
198 void BX_CPU_C::SETNS_Eb(bxInstruction_c *i)
200 Bit8u result_8;
202 if (get_SF()==0)
203 result_8 = 1;
204 else
205 result_8 = 0;
207 /* now write result back to destination */
208 if (i->modC0()) {
209 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
211 else {
212 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
216 void BX_CPU_C::SETP_Eb(bxInstruction_c *i)
218 Bit8u result_8;
220 if (get_PF())
221 result_8 = 1;
222 else
223 result_8 = 0;
225 /* now write result back to destination */
226 if (i->modC0()) {
227 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
229 else {
230 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
234 void BX_CPU_C::SETNP_Eb(bxInstruction_c *i)
236 Bit8u result_8;
238 if (get_PF() == 0)
239 result_8 = 1;
240 else
241 result_8 = 0;
243 /* now write result back to destination */
244 if (i->modC0()) {
245 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
247 else {
248 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
252 void BX_CPU_C::SETL_Eb(bxInstruction_c *i)
254 Bit8u result_8;
256 if (getB_SF() != getB_OF())
257 result_8 = 1;
258 else
259 result_8 = 0;
261 /* now write result back to destination */
262 if (i->modC0()) {
263 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
265 else {
266 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
270 void BX_CPU_C::SETNL_Eb(bxInstruction_c *i)
272 Bit8u result_8;
274 if (getB_SF() == getB_OF())
275 result_8 = 1;
276 else
277 result_8 = 0;
279 /* now write result back to destination */
280 if (i->modC0()) {
281 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
283 else {
284 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
288 void BX_CPU_C::SETLE_Eb(bxInstruction_c *i)
290 Bit8u result_8;
292 if (get_ZF() || (getB_SF()!=getB_OF()))
293 result_8 = 1;
294 else
295 result_8 = 0;
297 /* now write result back to destination */
298 if (i->modC0()) {
299 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
301 else {
302 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
306 void BX_CPU_C::SETNLE_Eb(bxInstruction_c *i)
308 Bit8u result_8;
310 if ((get_ZF()==0) && (getB_SF()==getB_OF()))
311 result_8 = 1;
312 else
313 result_8 = 0;
315 /* now write result back to destination */
316 if (i->modC0()) {
317 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
319 else {
320 write_virtual_byte(i->seg(), RMAddr(i), &result_8);
324 void BX_CPU_C::BSF_GwEw(bxInstruction_c *i)
326 Bit16u op1_16, op2_16;
328 /* op2_16 is a register or memory reference */
329 if (i->modC0()) {
330 op2_16 = BX_READ_16BIT_REG(i->rm());
332 else {
333 /* pointer, segment address pair */
334 read_virtual_word(i->seg(), RMAddr(i), &op2_16);
337 if (op2_16 == 0) {
338 assert_ZF(); /* op1_16 undefined */
339 return;
342 op1_16 = 0;
343 while ( (op2_16 & 0x01) == 0 ) {
344 op1_16++;
345 op2_16 >>= 1;
348 SET_FLAGS_OSZAPC_RESULT_16(op1_16, BX_INSTR_BITSCAN16);
350 /* now write result back to destination */
351 BX_WRITE_16BIT_REG(i->nnn(), op1_16);
354 void BX_CPU_C::BSF_GdEd(bxInstruction_c *i)
356 /* for 32 bit operand size mode */
357 Bit32u op1_32, op2_32;
359 /* op2_32 is a register or memory reference */
360 if (i->modC0()) {
361 op2_32 = BX_READ_32BIT_REG(i->rm());
363 else {
364 /* pointer, segment address pair */
365 read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
368 if (op2_32 == 0) {
369 assert_ZF(); /* op1_32 undefined */
370 return;
373 op1_32 = 0;
374 while ( (op2_32 & 0x01) == 0 ) {
375 op1_32++;
376 op2_32 >>= 1;
379 SET_FLAGS_OSZAPC_RESULT_32(op1_32, BX_INSTR_BITSCAN32);
381 /* now write result back to destination */
382 BX_WRITE_32BIT_REGZ(i->nnn(), op1_32);
385 #if BX_SUPPORT_X86_64
386 void BX_CPU_C::BSF_GqEq(bxInstruction_c *i)
388 /* for 64 bit operand size mode */
389 Bit64u op1_64, op2_64;
391 /* op2_64 is a register or memory reference */
392 if (i->modC0()) {
393 op2_64 = BX_READ_64BIT_REG(i->rm());
395 else {
396 /* pointer, segment address pair */
397 read_virtual_qword(i->seg(), RMAddr(i), &op2_64);
400 if (op2_64 == 0) {
401 assert_ZF(); /* op1_64 undefined */
402 return;
405 op1_64 = 0;
406 while ( (op2_64 & 0x01) == 0 ) {
407 op1_64++;
408 op2_64 >>= 1;
411 SET_FLAGS_OSZAPC_RESULT_64(op1_64, BX_INSTR_BITSCAN64);
413 /* now write result back to destination */
414 BX_WRITE_64BIT_REG(i->nnn(), op1_64);
416 #endif // #if BX_SUPPORT_X86_64
418 void BX_CPU_C::BSR_GwEw(bxInstruction_c *i)
420 Bit16u op1_16, op2_16;
422 /* op2_16 is a register or memory reference */
423 if (i->modC0()) {
424 op2_16 = BX_READ_16BIT_REG(i->rm());
426 else {
427 /* pointer, segment address pair */
428 read_virtual_word(i->seg(), RMAddr(i), &op2_16);
431 if (op2_16 == 0) {
432 assert_ZF(); /* op1_16 undefined */
433 return;
436 op1_16 = 15;
437 while ( (op2_16 & 0x8000) == 0 ) {
438 op1_16--;
439 op2_16 <<= 1;
442 SET_FLAGS_OSZAPC_RESULT_16(op1_16, BX_INSTR_BITSCAN16);
444 /* now write result back to destination */
445 BX_WRITE_16BIT_REG(i->nnn(), op1_16);
448 void BX_CPU_C::BSR_GdEd(bxInstruction_c *i)
450 /* for 32 bit operand size mode */
451 Bit32u op1_32, op2_32;
453 /* op2_32 is a register or memory reference */
454 if (i->modC0()) {
455 op2_32 = BX_READ_32BIT_REG(i->rm());
457 else {
458 /* pointer, segment address pair */
459 read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
462 if (op2_32 == 0) {
463 assert_ZF(); /* op1_32 undefined */
464 return;
467 op1_32 = 31;
468 while ( (op2_32 & 0x80000000) == 0 ) {
469 op1_32--;
470 op2_32 <<= 1;
473 SET_FLAGS_OSZAPC_RESULT_32(op1_32, BX_INSTR_BITSCAN32);
475 /* now write result back to destination */
476 BX_WRITE_32BIT_REGZ(i->nnn(), op1_32);
479 #if BX_SUPPORT_X86_64
480 void BX_CPU_C::BSR_GqEq(bxInstruction_c *i)
482 /* for 64 bit operand size mode */
483 Bit64u op1_64, op2_64;
485 /* op2_64 is a register or memory reference */
486 if (i->modC0()) {
487 op2_64 = BX_READ_64BIT_REG(i->rm());
489 else {
490 /* pointer, segment address pair */
491 read_virtual_qword(i->seg(), RMAddr(i), &op2_64);
494 if (op2_64 == 0) {
495 assert_ZF(); /* op1_64 undefined */
496 return;
499 op1_64 = 63;
500 while ( (op2_64 & BX_CONST64(0x8000000000000000)) == 0 ) {
501 op1_64--;
502 op2_64 <<= 1;
505 SET_FLAGS_OSZAPC_RESULT_64(op1_64, BX_INSTR_BITSCAN64);
507 /* now write result back to destination */
508 BX_WRITE_64BIT_REG(i->nnn(), op1_64);
510 #endif
512 void BX_CPU_C::BSWAP_ERX(bxInstruction_c *i)
514 #if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
515 Bit32u val32, b0, b1, b2, b3;
517 if (i->os32L() == 0) {
518 BX_ERROR(("BSWAP with 16-bit opsize: undefined behavior !"));
521 val32 = BX_READ_32BIT_REG(i->opcodeReg());
522 b0 = val32 & 0xff; val32 >>= 8;
523 b1 = val32 & 0xff; val32 >>= 8;
524 b2 = val32 & 0xff; val32 >>= 8;
525 b3 = val32;
526 val32 = (b0<<24) | (b1<<16) | (b2<<8) | b3; // zero extended
528 // in 64-bit mode, hi-order 32 bits are not modified
529 BX_WRITE_32BIT_REGZ(i->opcodeReg(), val32);
530 #else
531 BX_INFO(("BSWAP_ERX: required CPU >= 4, use --enable-cpu-level=4 option"));
532 UndefinedOpcode(i);
533 #endif
536 #if BX_SUPPORT_X86_64
537 void BX_CPU_C::BSWAP_RRX(bxInstruction_c *i)
539 Bit64u val64, b0, b1, b2, b3, b4, b5, b6, b7;
541 val64 = BX_READ_64BIT_REG(i->opcodeReg());
542 b0 = val64 & 0xff; val64 >>= 8;
543 b1 = val64 & 0xff; val64 >>= 8;
544 b2 = val64 & 0xff; val64 >>= 8;
545 b3 = val64 & 0xff; val64 >>= 8;
546 b4 = val64 & 0xff; val64 >>= 8;
547 b5 = val64 & 0xff; val64 >>= 8;
548 b6 = val64 & 0xff; val64 >>= 8;
549 b7 = val64;
550 val64 = (b0<<56) | (b1<<48) | (b2<<40) | (b3<<32) | (b4<<24) | (b4<<16) | (b4<<8) | b7;
552 BX_WRITE_64BIT_REG(i->opcodeReg(), val64);
554 #endif // #if BX_SUPPORT_X86_64
556 void BX_CPU_C::BT_EwGw(bxInstruction_c *i)
558 bx_address op1_addr;
559 Bit16u op1_16, op2_16, index;
560 Bit32s displacement32;
562 op2_16 = BX_READ_16BIT_REG(i->nnn());
564 /* op1_16 is a register or memory reference */
565 if (i->modC0()) {
566 op1_16 = BX_READ_16BIT_REG(i->rm());
567 op2_16 &= 0x0f;
568 set_CF((op1_16 >> op2_16) & 0x01);
569 return;
572 index = op2_16 & 0x0f;
573 displacement32 = ((Bit16s) (op2_16&0xfff0)) / 16;
574 op1_addr = RMAddr(i) + 2 * displacement32;
576 /* pointer, segment address pair */
577 read_virtual_word(i->seg(), op1_addr, &op1_16);
579 set_CF((op1_16 >> index) & 0x01);
582 void BX_CPU_C::BT_EdGd(bxInstruction_c *i)
584 bx_address op1_addr;
585 Bit32u op1_32, op2_32, index;
586 Bit32s displacement32;
588 op2_32 = BX_READ_32BIT_REG(i->nnn());
590 /* op1_32 is a register or memory reference */
591 if (i->modC0()) {
592 op1_32 = BX_READ_32BIT_REG(i->rm());
593 op2_32 &= 0x1f;
594 set_CF((op1_32 >> op2_32) & 0x01);
595 return;
598 index = op2_32 & 0x1f;
599 displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32;
600 op1_addr = RMAddr(i) + 4 * displacement32;
602 /* pointer, segment address pair */
603 read_virtual_dword(i->seg(), op1_addr, &op1_32);
605 set_CF((op1_32 >> index) & 0x01);
608 #if BX_SUPPORT_X86_64
609 void BX_CPU_C::BT_EqGq(bxInstruction_c *i)
611 bx_address op1_addr;
612 Bit64u op1_64, op2_64;
613 Bit64s displacement64;
614 Bit64u index;
616 op2_64 = BX_READ_64BIT_REG(i->nnn());
618 /* op1_64 is a register or memory reference */
619 if (i->modC0()) {
620 op1_64 = BX_READ_64BIT_REG(i->rm());
621 op2_64 &= 0x3f;
622 set_CF((op1_64 >> op2_64) & 0x01);
623 return;
626 index = op2_64 & 0x3f;
627 displacement64 = ((Bit64s) (op2_64 & BX_CONST64(0xffffffffffffffc0))) / 64;
628 op1_addr = RMAddr(i) + 8 * displacement64;
630 /* pointer, segment address pair */
631 read_virtual_qword(i->seg(), op1_addr, &op1_64);
633 set_CF((op1_64 >> index) & 0x01);
635 #endif
637 void BX_CPU_C::BTS_EwGw(bxInstruction_c *i)
639 bx_address op1_addr;
640 Bit16u op1_16, op2_16, bit_i, index;
641 Bit32s displacement32;
643 op2_16 = BX_READ_16BIT_REG(i->nnn());
645 /* op1_16 is a register or memory reference */
646 if (i->modC0()) {
647 op1_16 = BX_READ_16BIT_REG(i->rm());
648 op2_16 &= 0x0f;
649 set_CF((op1_16 >> op2_16) & 0x01);
650 op1_16 |= (((Bit16u) 1) << op2_16);
652 /* now write diff back to destination */
653 BX_WRITE_16BIT_REG(i->rm(), op1_16);
654 return;
657 index = op2_16 & 0x0f;
658 displacement32 = ((Bit16s) (op2_16 & 0xfff0)) / 16;
659 op1_addr = RMAddr(i) + 2 * displacement32;
661 /* pointer, segment address pair */
662 read_RMW_virtual_word(i->seg(), op1_addr, &op1_16);
664 bit_i = (op1_16 >> index) & 0x01;
665 op1_16 |= (((Bit16u) 1) << index);
667 write_RMW_virtual_word(op1_16);
669 set_CF(bit_i);
672 void BX_CPU_C::BTS_EdGd(bxInstruction_c *i)
674 bx_address op1_addr;
675 Bit32u op1_32, op2_32, bit_i, index;
676 Bit32s displacement32;
678 op2_32 = BX_READ_32BIT_REG(i->nnn());
680 /* op1_32 is a register or memory reference */
681 if (i->modC0()) {
682 op1_32 = BX_READ_32BIT_REG(i->rm());
683 op2_32 &= 0x1f;
684 set_CF((op1_32 >> op2_32) & 0x01);
685 op1_32 |= (((Bit32u) 1) << op2_32);
687 /* now write diff back to destination */
688 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
689 return;
692 index = op2_32 & 0x1f;
693 displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32;
694 op1_addr = RMAddr(i) + 4 * displacement32;
696 /* pointer, segment address pair */
697 read_RMW_virtual_dword(i->seg(), op1_addr, &op1_32);
699 bit_i = (op1_32 >> index) & 0x01;
700 op1_32 |= (((Bit32u) 1) << index);
702 write_RMW_virtual_dword(op1_32);
704 set_CF(bit_i);
707 #if BX_SUPPORT_X86_64
708 void BX_CPU_C::BTS_EqGq(bxInstruction_c *i)
710 bx_address op1_addr;
711 Bit64u op1_64, op2_64, index;
712 Bit64s displacement64;
713 Bit64u bit_i;
715 op2_64 = BX_READ_64BIT_REG(i->nnn());
717 /* op1_64 is a register or memory reference */
718 if (i->modC0()) {
719 op1_64 = BX_READ_64BIT_REG(i->rm());
720 op2_64 &= 0x3f;
721 set_CF((op1_64 >> op2_64) & 0x01);
722 op1_64 |= (((Bit64u) 1) << op2_64);
724 /* now write diff back to destination */
725 BX_WRITE_64BIT_REG(i->rm(), op1_64);
726 return;
729 index = op2_64 & 0x3f;
730 displacement64 = ((Bit64s) (op2_64 & BX_CONST64(0xffffffffffffffc0))) / 64;
731 op1_addr = RMAddr(i) + 8 * displacement64;
733 /* pointer, segment address pair */
734 read_RMW_virtual_qword(i->seg(), op1_addr, &op1_64);
736 bit_i = (op1_64 >> index) & 0x01;
737 op1_64 |= (((Bit64u) 1) << index);
739 write_RMW_virtual_qword(op1_64);
741 set_CF(bit_i);
743 #endif
745 void BX_CPU_C::BTR_EwGw(bxInstruction_c *i)
747 bx_address op1_addr;
748 Bit16u op1_16, op2_16, index;
749 Bit32s displacement32;
751 op2_16 = BX_READ_16BIT_REG(i->nnn());
753 /* op1_16 is a register or memory reference */
754 if (i->modC0()) {
755 op1_16 = BX_READ_16BIT_REG(i->rm());
756 op2_16 &= 0x0f;
757 set_CF((op1_16 >> op2_16) & 0x01);
758 op1_16 &= ~(((Bit16u) 1) << op2_16);
760 /* now write diff back to destination */
761 BX_WRITE_16BIT_REG(i->rm(), op1_16);
762 return;
765 index = op2_16 & 0x0f;
766 displacement32 = ((Bit16s) (op2_16&0xfff0)) / 16;
767 op1_addr = RMAddr(i) + 2 * displacement32;
769 /* pointer, segment address pair */
770 read_RMW_virtual_word(i->seg(), op1_addr, &op1_16);
772 bx_bool temp_cf = (op1_16 >> index) & 0x01;
773 op1_16 &= ~(((Bit16u) 1) << index);
775 /* now write back to destination */
776 write_RMW_virtual_word(op1_16);
778 set_CF(temp_cf);
781 void BX_CPU_C::BTR_EdGd(bxInstruction_c *i)
783 bx_address op1_addr;
784 Bit32u op1_32, op2_32, index;
785 Bit32s displacement32;
787 op2_32 = BX_READ_32BIT_REG(i->nnn());
789 /* op1_32 is a register or memory reference */
790 if (i->modC0()) {
791 op1_32 = BX_READ_32BIT_REG(i->rm());
792 op2_32 &= 0x1f;
793 set_CF((op1_32 >> op2_32) & 0x01);
794 op1_32 &= ~(((Bit32u) 1) << op2_32);
796 /* now write diff back to destination */
797 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
798 return;
801 index = op2_32 & 0x1f;
802 displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32;
803 op1_addr = RMAddr(i) + 4 * displacement32;
805 /* pointer, segment address pair */
806 read_RMW_virtual_dword(i->seg(), op1_addr, &op1_32);
808 bx_bool temp_cf = (op1_32 >> index) & 0x01;
809 op1_32 &= ~(((Bit32u) 1) << index);
811 /* now write back to destination */
812 write_RMW_virtual_dword(op1_32);
814 set_CF(temp_cf);
817 #if BX_SUPPORT_X86_64
818 void BX_CPU_C::BTR_EqGq(bxInstruction_c *i)
820 bx_address op1_addr;
821 Bit64u op1_64, op2_64, index;
822 Bit64s displacement64;
824 op2_64 = BX_READ_64BIT_REG(i->nnn());
826 /* op1_64 is a register or memory reference */
827 if (i->modC0()) {
828 op1_64 = BX_READ_64BIT_REG(i->rm());
829 op2_64 &= 0x3f;
830 set_CF((op1_64 >> op2_64) & 0x01);
831 op1_64 &= ~(((Bit64u) 1) << op2_64);
833 /* now write diff back to destination */
834 BX_WRITE_64BIT_REG(i->rm(), op1_64);
835 return;
838 index = op2_64 & 0x3f;
839 displacement64 = ((Bit64s) (op2_64 & BX_CONST64(0xffffffffffffffc0))) / 64;
840 op1_addr = RMAddr(i) + 8 * displacement64;
842 /* pointer, segment address pair */
843 read_RMW_virtual_qword(i->seg(), op1_addr, &op1_64);
845 bx_bool temp_cf = (op1_64 >> index) & 0x01;
846 op1_64 &= ~(((Bit64u) 1) << index);
848 /* now write back to destination */
849 write_RMW_virtual_qword(op1_64);
851 set_CF(temp_cf);
853 #endif
855 void BX_CPU_C::BTC_EwGw(bxInstruction_c *i)
857 bx_address op1_addr;
858 Bit16u op1_16, op2_16, index_16;
859 Bit16s displacement16;
861 op2_16 = BX_READ_16BIT_REG(i->nnn());
862 index_16 = op2_16 & 0x0f;
864 /* op1_16 is a register or memory reference */
865 if (i->modC0()) {
866 op1_16 = BX_READ_16BIT_REG(i->rm());
867 op1_addr = 0; // keep compiler happy
869 else {
870 displacement16 = ((Bit16s) (op2_16 & 0xfff0)) / 16;
871 op1_addr = RMAddr(i) + 2 * displacement16;
872 read_RMW_virtual_word(i->seg(), op1_addr, &op1_16);
875 bx_bool temp_CF = (op1_16 >> index_16) & 0x01;
876 op1_16 ^= (((Bit16u) 1) << index_16); /* toggle bit */
877 set_CF(temp_CF);
879 /* now write diff back to destination */
880 if (i->modC0()) {
881 BX_WRITE_16BIT_REG(i->rm(), op1_16);
883 else {
884 write_RMW_virtual_word(op1_16);
887 set_CF(temp_CF);
890 void BX_CPU_C::BTC_EdGd(bxInstruction_c *i)
892 bx_address op1_addr;
893 Bit32u op1_32, op2_32, index_32;
894 Bit32s displacement32;
896 op2_32 = BX_READ_32BIT_REG(i->nnn());
897 index_32 = op2_32 & 0x1f;
899 /* op1_32 is a register or memory reference */
900 if (i->modC0()) {
901 op1_32 = BX_READ_32BIT_REG(i->rm());
902 op1_addr = 0; // keep compiler happy
904 else {
905 displacement32 = ((Bit32s) (op2_32 & 0xffffffe0)) / 32;
906 op1_addr = RMAddr(i) + 4 * displacement32;
907 read_RMW_virtual_dword(i->seg(), op1_addr, &op1_32);
910 bx_bool temp_CF = (op1_32 >> index_32) & 0x01;
911 op1_32 ^= (((Bit32u) 1) << index_32); /* toggle bit */
912 set_CF(temp_CF);
914 /* now write diff back to destination */
915 if (i->modC0()) {
916 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
918 else {
919 write_RMW_virtual_dword(op1_32);
923 #if BX_SUPPORT_X86_64
924 void BX_CPU_C::BTC_EqGq(bxInstruction_c *i)
926 bx_address op1_addr;
927 Bit64u op1_64, op2_64;
928 Bit64s displacement64;
929 Bit64u index;
931 op2_64 = BX_READ_64BIT_REG(i->nnn());
932 index = op2_64 & 0x3f;
934 /* op1_64 is a register or memory reference */
935 if (i->modC0()) {
936 op1_64 = BX_READ_64BIT_REG(i->rm());
937 op1_addr = 0; // keep compiler happy
939 else {
940 displacement64 = ((Bit64s) (op2_64 & BX_CONST64(0xffffffffffffffc0))) / 64;
941 op1_addr = RMAddr(i) + 8 * displacement64;
942 read_RMW_virtual_qword(i->seg(), op1_addr, &op1_64);
945 bx_bool temp_CF = (op1_64 >> index) & 0x01;
946 op1_64 ^= (((Bit64u) 1) << index); /* toggle bit */
947 set_CF(temp_CF);
949 /* now write diff back to destination */
950 if (i->modC0()) {
951 BX_WRITE_64BIT_REG(i->rm(), op1_64);
953 else {
954 write_RMW_virtual_qword(op1_64);
957 #endif
959 void BX_CPU_C::BT_EwIb(bxInstruction_c *i)
961 Bit16u op1_16;
963 Bit8u op2_8 = i->Ib() & 0xf;
965 /* op1_16 is a register or memory reference */
966 if (i->modC0()) {
967 op1_16 = BX_READ_16BIT_REG(i->rm());
969 else {
970 /* pointer, segment address pair */
971 read_virtual_word(i->seg(), RMAddr(i), &op1_16);
974 set_CF((op1_16 >> op2_8) & 0x01);
977 void BX_CPU_C::BT_EdIb(bxInstruction_c *i)
979 Bit32u op1_32;
981 Bit8u op2_8 = i->Ib() & 0x1f;
983 /* op1_32 is a register or memory reference */
984 if (i->modC0()) {
985 op1_32 = BX_READ_32BIT_REG(i->rm());
987 else {
988 /* pointer, segment address pair */
989 read_virtual_dword(i->seg(), RMAddr(i), &op1_32);
992 set_CF((op1_32 >> op2_8) & 0x01);
995 #if BX_SUPPORT_X86_64
996 void BX_CPU_C::BT_EqIb(bxInstruction_c *i)
998 Bit64u op1_64;
1000 Bit8u op2_8 = i->Ib() & 0x3f;
1002 /* op1_64 is a register or memory reference */
1003 if (i->modC0()) {
1004 op1_64 = BX_READ_64BIT_REG(i->rm());
1006 else {
1007 /* pointer, segment address pair */
1008 read_virtual_qword(i->seg(), RMAddr(i), &op1_64);
1011 set_CF((op1_64 >> op2_8) & 0x01);
1013 #endif
1015 void BX_CPU_C::BTS_EwIb(bxInstruction_c *i)
1017 Bit16u op1_16;
1019 Bit8u op2_8 = i->Ib() & 0xf;
1021 /* op1_16 is a register or memory reference */
1022 if (i->modC0()) {
1023 op1_16 = BX_READ_16BIT_REG(i->rm());
1025 else {
1026 /* pointer, segment address pair */
1027 read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
1030 bx_bool temp_CF = (op1_16 >> op2_8) & 0x01;
1031 op1_16 |= (((Bit16u) 1) << op2_8);
1033 /* now write diff back to destination */
1034 if (i->modC0()) {
1035 BX_WRITE_16BIT_REG(i->rm(), op1_16);
1037 else {
1038 write_RMW_virtual_word(op1_16);
1041 set_CF(temp_CF);
1044 void BX_CPU_C::BTS_EdIb(bxInstruction_c *i)
1046 Bit32u op1_32;
1048 Bit8u op2_8 = i->Ib() & 0x1f;
1050 /* op1_32 is a register or memory reference */
1051 if (i->modC0()) {
1052 op1_32 = BX_READ_32BIT_REG(i->rm());
1054 else {
1055 /* pointer, segment address pair */
1056 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
1059 bx_bool temp_CF = (op1_32 >> op2_8) & 0x01;
1060 op1_32 |= (((Bit32u) 1) << op2_8);
1062 /* now write diff back to destination */
1063 if (i->modC0()) {
1064 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
1066 else {
1067 write_RMW_virtual_dword(op1_32);
1070 set_CF(temp_CF);
1073 #if BX_SUPPORT_X86_64
1074 void BX_CPU_C::BTS_EqIb(bxInstruction_c *i)
1076 Bit64u op1_64;
1078 Bit8u op2_8 = i->Ib() & 0x3f;
1080 /* op1_64 is a register or memory reference */
1081 if (i->modC0()) {
1082 op1_64 = BX_READ_64BIT_REG(i->rm());
1084 else {
1085 /* pointer, segment address pair */
1086 read_RMW_virtual_qword(i->seg(), RMAddr(i), &op1_64);
1089 bx_bool temp_CF = (op1_64 >> op2_8) & 0x01;
1090 op1_64 |= (((Bit64u) 1) << op2_8);
1092 /* now write diff back to destination */
1093 if (i->modC0()) {
1094 BX_WRITE_64BIT_REG(i->rm(), op1_64);
1096 else {
1097 write_RMW_virtual_qword(op1_64);
1100 set_CF(temp_CF);
1102 #endif
1104 void BX_CPU_C::BTC_EwIb(bxInstruction_c *i)
1106 Bit16u op1_16;
1108 Bit8u op2_8 = i->Ib() & 0xf;
1110 /* op1_16 is a register or memory reference */
1111 if (i->modC0()) {
1112 op1_16 = BX_READ_16BIT_REG(i->rm());
1114 else {
1115 /* pointer, segment address pair */
1116 read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
1119 bx_bool temp_CF = (op1_16 >> op2_8) & 0x01;
1120 op1_16 ^= (((Bit16u) 1) << op2_8); /* toggle bit */
1121 set_CF(temp_CF);
1123 /* now write diff back to destination */
1124 if (i->modC0()) {
1125 BX_WRITE_16BIT_REG(i->rm(), op1_16);
1127 else {
1128 write_RMW_virtual_word(op1_16);
1132 void BX_CPU_C::BTC_EdIb(bxInstruction_c *i)
1134 Bit32u op1_32;
1136 Bit8u op2_8 = i->Ib() & 0x1f;
1138 /* op1_32 is a register or memory reference */
1139 if (i->modC0()) {
1140 op1_32 = BX_READ_32BIT_REG(i->rm());
1142 else {
1143 /* pointer, segment address pair */
1144 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
1147 bx_bool temp_CF = (op1_32 >> op2_8) & 0x01;
1148 op1_32 ^= (((Bit32u) 1) << op2_8); /* toggle bit */
1149 set_CF(temp_CF);
1151 /* now write diff back to destination */
1152 if (i->modC0()) {
1153 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
1155 else {
1156 write_RMW_virtual_dword(op1_32);
1160 #if BX_SUPPORT_X86_64
1161 void BX_CPU_C::BTC_EqIb(bxInstruction_c *i)
1163 Bit64u op1_64;
1165 Bit8u op2_8 = i->Ib() & 0x3f;
1167 /* op1_64 is a register or memory reference */
1168 if (i->modC0()) {
1169 op1_64 = BX_READ_64BIT_REG(i->rm());
1171 else {
1172 /* pointer, segment address pair */
1173 read_RMW_virtual_qword(i->seg(), RMAddr(i), &op1_64);
1176 bx_bool temp_CF = (op1_64 >> op2_8) & 0x01;
1177 op1_64 ^= (((Bit64u) 1) << op2_8); /* toggle bit */
1178 set_CF(temp_CF);
1180 /* now write diff back to destination */
1181 if (i->modC0()) {
1182 BX_WRITE_64BIT_REG(i->rm(), op1_64);
1184 else {
1185 write_RMW_virtual_qword(op1_64);
1188 #endif
1190 void BX_CPU_C::BTR_EwIb(bxInstruction_c *i)
1192 Bit16u op1_16;
1194 Bit8u op2_8 = i->Ib() & 0xf;
1196 /* op1_16 is a register or memory reference */
1197 if (i->modC0()) {
1198 op1_16 = BX_READ_16BIT_REG(i->rm());
1200 else {
1201 /* pointer, segment address pair */
1202 read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
1205 bx_bool temp_CF = (op1_16 >> op2_8) & 0x01;
1206 op1_16 &= ~(((Bit16u) 1) << op2_8);
1208 /* now write diff back to destination */
1209 if (i->modC0()) {
1210 BX_WRITE_16BIT_REG(i->rm(), op1_16);
1212 else {
1213 write_RMW_virtual_word(op1_16);
1216 set_CF(temp_CF);
1219 void BX_CPU_C::BTR_EdIb(bxInstruction_c *i)
1221 Bit32u op1_32;
1223 Bit8u op2_8 = i->Ib() & 0x1f;
1225 /* op1_32 is a register or memory reference */
1226 if (i->modC0()) {
1227 op1_32 = BX_READ_32BIT_REG(i->rm());
1229 else {
1230 /* pointer, segment address pair */
1231 read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
1234 bx_bool temp_CF = (op1_32 >> op2_8) & 0x01;
1235 op1_32 &= ~(((Bit32u) 1) << op2_8);
1237 /* now write diff back to destination */
1238 if (i->modC0()) {
1239 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
1241 else {
1242 write_RMW_virtual_dword(op1_32);
1245 set_CF(temp_CF);
1248 #if BX_SUPPORT_X86_64
1249 void BX_CPU_C::BTR_EqIb(bxInstruction_c *i)
1251 Bit64u op1_64;
1253 Bit8u op2_8 = i->Ib() & 0x3f;
1255 /* op1_64 is a register or memory reference */
1256 if (i->modC0()) {
1257 op1_64 = BX_READ_64BIT_REG(i->rm());
1259 else {
1260 /* pointer, segment address pair */
1261 read_RMW_virtual_qword(i->seg(), RMAddr(i), &op1_64);
1264 bx_bool temp_CF = (op1_64 >> op2_8) & 0x01;
1265 op1_64 &= ~(((Bit64u) 1) << op2_8);
1267 /* now write diff back to destination */
1268 if (i->modC0()) {
1269 BX_WRITE_64BIT_REG(i->rm(), op1_64);
1271 else {
1272 write_RMW_virtual_qword(op1_64);
1275 set_CF(temp_CF);
1277 #endif
1279 #endif /* BX_CPU_LEVEL >= 3 */