1 /////////////////////////////////////////////////////////////////////////
2 // $Id: bit.cc,v 1.31 2007/01/26 22:12:05 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
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
31 #define LOG_THIS BX_CPU_THIS_PTR
36 void BX_CPU_C::SETO_Eb(bxInstruction_c
*i
)
45 /* now write result back to destination */
47 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
50 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
54 void BX_CPU_C::SETNO_Eb(bxInstruction_c
*i
)
63 /* now write result back to destination */
65 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
68 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
72 void BX_CPU_C::SETB_Eb(bxInstruction_c
*i
)
81 /* now write result back to destination */
83 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
86 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
90 void BX_CPU_C::SETNB_Eb(bxInstruction_c
*i
)
99 /* now write result back to destination */
101 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
104 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
108 void BX_CPU_C::SETZ_Eb(bxInstruction_c
*i
)
117 /* now write result back to destination */
119 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
122 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
126 void BX_CPU_C::SETNZ_Eb(bxInstruction_c
*i
)
135 /* now write result back to destination */
137 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
140 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
144 void BX_CPU_C::SETBE_Eb(bxInstruction_c
*i
)
148 if (get_CF() || get_ZF())
153 /* now write result back to destination */
155 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
158 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
162 void BX_CPU_C::SETNBE_Eb(bxInstruction_c
*i
)
166 if ((get_CF()==0) && (get_ZF()==0))
171 /* now write result back to destination */
173 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
176 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
180 void BX_CPU_C::SETS_Eb(bxInstruction_c
*i
)
189 /* now write result back to destination */
191 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
194 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
198 void BX_CPU_C::SETNS_Eb(bxInstruction_c
*i
)
207 /* now write result back to destination */
209 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
212 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
216 void BX_CPU_C::SETP_Eb(bxInstruction_c
*i
)
225 /* now write result back to destination */
227 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
230 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
234 void BX_CPU_C::SETNP_Eb(bxInstruction_c
*i
)
243 /* now write result back to destination */
245 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
248 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
252 void BX_CPU_C::SETL_Eb(bxInstruction_c
*i
)
256 if (getB_SF() != getB_OF())
261 /* now write result back to destination */
263 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
266 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
270 void BX_CPU_C::SETNL_Eb(bxInstruction_c
*i
)
274 if (getB_SF() == getB_OF())
279 /* now write result back to destination */
281 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
284 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
288 void BX_CPU_C::SETLE_Eb(bxInstruction_c
*i
)
292 if (get_ZF() || (getB_SF()!=getB_OF()))
297 /* now write result back to destination */
299 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
302 write_virtual_byte(i
->seg(), RMAddr(i
), &result_8
);
306 void BX_CPU_C::SETNLE_Eb(bxInstruction_c
*i
)
310 if ((get_ZF()==0) && (getB_SF()==getB_OF()))
315 /* now write result back to destination */
317 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
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 */
330 op2_16
= BX_READ_16BIT_REG(i
->rm());
333 /* pointer, segment address pair */
334 read_virtual_word(i
->seg(), RMAddr(i
), &op2_16
);
338 assert_ZF(); /* op1_16 undefined */
343 while ( (op2_16
& 0x01) == 0 ) {
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 */
361 op2_32
= BX_READ_32BIT_REG(i
->rm());
364 /* pointer, segment address pair */
365 read_virtual_dword(i
->seg(), RMAddr(i
), &op2_32
);
369 assert_ZF(); /* op1_32 undefined */
374 while ( (op2_32
& 0x01) == 0 ) {
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 */
393 op2_64
= BX_READ_64BIT_REG(i
->rm());
396 /* pointer, segment address pair */
397 read_virtual_qword(i
->seg(), RMAddr(i
), &op2_64
);
401 assert_ZF(); /* op1_64 undefined */
406 while ( (op2_64
& 0x01) == 0 ) {
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 */
424 op2_16
= BX_READ_16BIT_REG(i
->rm());
427 /* pointer, segment address pair */
428 read_virtual_word(i
->seg(), RMAddr(i
), &op2_16
);
432 assert_ZF(); /* op1_16 undefined */
437 while ( (op2_16
& 0x8000) == 0 ) {
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 */
455 op2_32
= BX_READ_32BIT_REG(i
->rm());
458 /* pointer, segment address pair */
459 read_virtual_dword(i
->seg(), RMAddr(i
), &op2_32
);
463 assert_ZF(); /* op1_32 undefined */
468 while ( (op2_32
& 0x80000000) == 0 ) {
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 */
487 op2_64
= BX_READ_64BIT_REG(i
->rm());
490 /* pointer, segment address pair */
491 read_virtual_qword(i
->seg(), RMAddr(i
), &op2_64
);
495 assert_ZF(); /* op1_64 undefined */
500 while ( (op2_64
& BX_CONST64(0x8000000000000000)) == 0 ) {
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
);
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;
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
);
531 BX_INFO(("BSWAP_ERX: required CPU >= 4, use --enable-cpu-level=4 option"));
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;
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
)
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 */
566 op1_16
= BX_READ_16BIT_REG(i
->rm());
568 set_CF((op1_16
>> op2_16
) & 0x01);
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
)
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 */
592 op1_32
= BX_READ_32BIT_REG(i
->rm());
594 set_CF((op1_32
>> op2_32
) & 0x01);
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
)
612 Bit64u op1_64
, op2_64
;
613 Bit64s displacement64
;
616 op2_64
= BX_READ_64BIT_REG(i
->nnn());
618 /* op1_64 is a register or memory reference */
620 op1_64
= BX_READ_64BIT_REG(i
->rm());
622 set_CF((op1_64
>> op2_64
) & 0x01);
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);
637 void BX_CPU_C::BTS_EwGw(bxInstruction_c
*i
)
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 */
647 op1_16
= BX_READ_16BIT_REG(i
->rm());
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
);
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
);
672 void BX_CPU_C::BTS_EdGd(bxInstruction_c
*i
)
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 */
682 op1_32
= BX_READ_32BIT_REG(i
->rm());
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
);
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
);
707 #if BX_SUPPORT_X86_64
708 void BX_CPU_C::BTS_EqGq(bxInstruction_c
*i
)
711 Bit64u op1_64
, op2_64
, index
;
712 Bit64s displacement64
;
715 op2_64
= BX_READ_64BIT_REG(i
->nnn());
717 /* op1_64 is a register or memory reference */
719 op1_64
= BX_READ_64BIT_REG(i
->rm());
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
);
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
);
745 void BX_CPU_C::BTR_EwGw(bxInstruction_c
*i
)
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 */
755 op1_16
= BX_READ_16BIT_REG(i
->rm());
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
);
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
);
781 void BX_CPU_C::BTR_EdGd(bxInstruction_c
*i
)
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 */
791 op1_32
= BX_READ_32BIT_REG(i
->rm());
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
);
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
);
817 #if BX_SUPPORT_X86_64
818 void BX_CPU_C::BTR_EqGq(bxInstruction_c
*i
)
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 */
828 op1_64
= BX_READ_64BIT_REG(i
->rm());
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
);
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
);
855 void BX_CPU_C::BTC_EwGw(bxInstruction_c
*i
)
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 */
866 op1_16
= BX_READ_16BIT_REG(i
->rm());
867 op1_addr
= 0; // keep compiler happy
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 */
879 /* now write diff back to destination */
881 BX_WRITE_16BIT_REG(i
->rm(), op1_16
);
884 write_RMW_virtual_word(op1_16
);
890 void BX_CPU_C::BTC_EdGd(bxInstruction_c
*i
)
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 */
901 op1_32
= BX_READ_32BIT_REG(i
->rm());
902 op1_addr
= 0; // keep compiler happy
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 */
914 /* now write diff back to destination */
916 BX_WRITE_32BIT_REGZ(i
->rm(), op1_32
);
919 write_RMW_virtual_dword(op1_32
);
923 #if BX_SUPPORT_X86_64
924 void BX_CPU_C::BTC_EqGq(bxInstruction_c
*i
)
927 Bit64u op1_64
, op2_64
;
928 Bit64s displacement64
;
931 op2_64
= BX_READ_64BIT_REG(i
->nnn());
932 index
= op2_64
& 0x3f;
934 /* op1_64 is a register or memory reference */
936 op1_64
= BX_READ_64BIT_REG(i
->rm());
937 op1_addr
= 0; // keep compiler happy
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 */
949 /* now write diff back to destination */
951 BX_WRITE_64BIT_REG(i
->rm(), op1_64
);
954 write_RMW_virtual_qword(op1_64
);
959 void BX_CPU_C::BT_EwIb(bxInstruction_c
*i
)
963 Bit8u op2_8
= i
->Ib() & 0xf;
965 /* op1_16 is a register or memory reference */
967 op1_16
= BX_READ_16BIT_REG(i
->rm());
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
)
981 Bit8u op2_8
= i
->Ib() & 0x1f;
983 /* op1_32 is a register or memory reference */
985 op1_32
= BX_READ_32BIT_REG(i
->rm());
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
)
1000 Bit8u op2_8
= i
->Ib() & 0x3f;
1002 /* op1_64 is a register or memory reference */
1004 op1_64
= BX_READ_64BIT_REG(i
->rm());
1007 /* pointer, segment address pair */
1008 read_virtual_qword(i
->seg(), RMAddr(i
), &op1_64
);
1011 set_CF((op1_64
>> op2_8
) & 0x01);
1015 void BX_CPU_C::BTS_EwIb(bxInstruction_c
*i
)
1019 Bit8u op2_8
= i
->Ib() & 0xf;
1021 /* op1_16 is a register or memory reference */
1023 op1_16
= BX_READ_16BIT_REG(i
->rm());
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 */
1035 BX_WRITE_16BIT_REG(i
->rm(), op1_16
);
1038 write_RMW_virtual_word(op1_16
);
1044 void BX_CPU_C::BTS_EdIb(bxInstruction_c
*i
)
1048 Bit8u op2_8
= i
->Ib() & 0x1f;
1050 /* op1_32 is a register or memory reference */
1052 op1_32
= BX_READ_32BIT_REG(i
->rm());
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 */
1064 BX_WRITE_32BIT_REGZ(i
->rm(), op1_32
);
1067 write_RMW_virtual_dword(op1_32
);
1073 #if BX_SUPPORT_X86_64
1074 void BX_CPU_C::BTS_EqIb(bxInstruction_c
*i
)
1078 Bit8u op2_8
= i
->Ib() & 0x3f;
1080 /* op1_64 is a register or memory reference */
1082 op1_64
= BX_READ_64BIT_REG(i
->rm());
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 */
1094 BX_WRITE_64BIT_REG(i
->rm(), op1_64
);
1097 write_RMW_virtual_qword(op1_64
);
1104 void BX_CPU_C::BTC_EwIb(bxInstruction_c
*i
)
1108 Bit8u op2_8
= i
->Ib() & 0xf;
1110 /* op1_16 is a register or memory reference */
1112 op1_16
= BX_READ_16BIT_REG(i
->rm());
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 */
1123 /* now write diff back to destination */
1125 BX_WRITE_16BIT_REG(i
->rm(), op1_16
);
1128 write_RMW_virtual_word(op1_16
);
1132 void BX_CPU_C::BTC_EdIb(bxInstruction_c
*i
)
1136 Bit8u op2_8
= i
->Ib() & 0x1f;
1138 /* op1_32 is a register or memory reference */
1140 op1_32
= BX_READ_32BIT_REG(i
->rm());
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 */
1151 /* now write diff back to destination */
1153 BX_WRITE_32BIT_REGZ(i
->rm(), op1_32
);
1156 write_RMW_virtual_dword(op1_32
);
1160 #if BX_SUPPORT_X86_64
1161 void BX_CPU_C::BTC_EqIb(bxInstruction_c
*i
)
1165 Bit8u op2_8
= i
->Ib() & 0x3f;
1167 /* op1_64 is a register or memory reference */
1169 op1_64
= BX_READ_64BIT_REG(i
->rm());
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 */
1180 /* now write diff back to destination */
1182 BX_WRITE_64BIT_REG(i
->rm(), op1_64
);
1185 write_RMW_virtual_qword(op1_64
);
1190 void BX_CPU_C::BTR_EwIb(bxInstruction_c
*i
)
1194 Bit8u op2_8
= i
->Ib() & 0xf;
1196 /* op1_16 is a register or memory reference */
1198 op1_16
= BX_READ_16BIT_REG(i
->rm());
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 */
1210 BX_WRITE_16BIT_REG(i
->rm(), op1_16
);
1213 write_RMW_virtual_word(op1_16
);
1219 void BX_CPU_C::BTR_EdIb(bxInstruction_c
*i
)
1223 Bit8u op2_8
= i
->Ib() & 0x1f;
1225 /* op1_32 is a register or memory reference */
1227 op1_32
= BX_READ_32BIT_REG(i
->rm());
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 */
1239 BX_WRITE_32BIT_REGZ(i
->rm(), op1_32
);
1242 write_RMW_virtual_dword(op1_32
);
1248 #if BX_SUPPORT_X86_64
1249 void BX_CPU_C::BTR_EqIb(bxInstruction_c
*i
)
1253 Bit8u op2_8
= i
->Ib() & 0x3f;
1255 /* op1_64 is a register or memory reference */
1257 op1_64
= BX_READ_64BIT_REG(i
->rm());
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 */
1269 BX_WRITE_64BIT_REG(i
->rm(), op1_64
);
1272 write_RMW_virtual_qword(op1_64
);
1279 #endif /* BX_CPU_LEVEL >= 3 */