@@ -97,7 +97,6 @@ void test_advance_rip(void* obj, uint64_t len) {
9797em_status_t test_read_memory (void * obj, uint64_t ea, uint64_t * value,
9898 uint32_t size, uint32_t flags) {
9999 test_cpu_t * vcpu = reinterpret_cast <test_cpu_t *>(obj);
100- ea &= 0xFF ;
101100 if (ea + size >= 0x100 ) {
102101 return EM_ERROR;
103102 }
@@ -123,7 +122,6 @@ em_status_t test_read_memory(void* obj, uint64_t ea, uint64_t* value,
123122em_status_t test_write_memory (void * obj, uint64_t ea, uint64_t * value,
124123 uint32_t size, uint32_t flags) {
125124 test_cpu_t * vcpu = reinterpret_cast <test_cpu_t *>(obj);
126- ea &= 0xFF ;
127125 if (ea + size > 0x100 ) {
128126 return EM_ERROR;
129127 }
@@ -495,10 +493,10 @@ class EmulatorTest : public testing::Test {
495493 if (N == 64 && sizeof (void *) < 8 ) {
496494 return ;
497495 }
496+ // Only bit-test variants that implicitly use bit offset modulo width.
498497 test_insn_rN_rM<N>(insn_name, tests);
499498 test_insn_rN_iM<N,8 >(insn_name, tests);
500499 test_insn_mN_iM<N,8 >(insn_name, tests);
501- test_insn_mN_rM<N>(insn_name, tests);
502500 }
503501
504502 template <int N>
@@ -629,6 +627,24 @@ TEST_F(EmulatorTest, insn_bt) {
629627 { 0x80000000'00000000ULL , 0xFF , 0 ,
630628 0x80000000'00000000ULL , RFLAGS_CF },
631629 });
630+
631+ // Variant `bt mN,rN`: Modifies the EA based on the bit offset.
632+ test_cpu_t vcpu_original;
633+ test_cpu_t vcpu_expected;
634+ vcpu_original = {};
635+ vcpu_original.gpr [REG_RCX] = 0ULL ;
636+ (uint64_t &)vcpu_original.mem [0x00 ] = 0x00020000'00000000 ;
637+ (uint64_t &)vcpu_original.mem [0x08 ] = 0x00000000'00000000 ;
638+ (uint64_t &)vcpu_original.mem [0x10 ] = 0xFFFFFFFF'FFFFFFFE ;
639+
640+ vcpu_original.gpr [REG_RAX] = -15LL ;
641+ vcpu_expected = vcpu_original;
642+ vcpu_expected.flags |= RFLAGS_CF;
643+ run (" bt [ecx + 0x08], eax" , vcpu_original, vcpu_expected);
644+ vcpu_original.gpr [REG_RAX] = +64LL ;
645+ vcpu_expected = vcpu_original;
646+ vcpu_expected.flags &= ~RFLAGS_CF;
647+ run (" bt [rcx + 0x08], rax" , vcpu_original, vcpu_expected);
632648}
633649
634650TEST_F (EmulatorTest, insn_btc) {
@@ -650,6 +666,26 @@ TEST_F(EmulatorTest, insn_btc) {
650666 { 0x80000000'00000000ULL , 0xFF , 0 ,
651667 0x00000000'00000000ULL , RFLAGS_CF },
652668 });
669+
670+ // Variant `btc mN,rN`: Modifies the EA based on the bit offset.
671+ test_cpu_t vcpu_original;
672+ test_cpu_t vcpu_expected;
673+ vcpu_original = {};
674+ vcpu_original.gpr [REG_RCX] = 0ULL ;
675+ (uint64_t &)vcpu_original.mem [0x00 ] = 0x00020000'00000000 ;
676+ (uint64_t &)vcpu_original.mem [0x08 ] = 0x00000000'00000000 ;
677+ (uint64_t &)vcpu_original.mem [0x10 ] = 0xFFFFFFFF'FFFFFFFE ;
678+
679+ vcpu_original.gpr [REG_RAX] = -15LL ;
680+ vcpu_expected = vcpu_original;
681+ vcpu_expected.flags |= RFLAGS_CF;
682+ (uint64_t &)vcpu_expected.mem [0x00 ] = 0x00000000'00000000 ;
683+ run (" btc [ecx + 0x08], eax" , vcpu_original, vcpu_expected);
684+ vcpu_original.gpr [REG_RAX] = +64LL ;
685+ vcpu_expected = vcpu_original;
686+ vcpu_expected.flags &= ~RFLAGS_CF;
687+ (uint64_t &)vcpu_expected.mem [0x10 ] = 0xFFFFFFFF'FFFFFFFF ;
688+ run (" btc [rcx + 0x08], rax" , vcpu_original, vcpu_expected);
653689}
654690
655691TEST_F (EmulatorTest, insn_btr) {
@@ -671,6 +707,25 @@ TEST_F(EmulatorTest, insn_btr) {
671707 { 0x80000000'00000000ULL , 0xFF , 0 ,
672708 0x00000000'00000000ULL , RFLAGS_CF },
673709 });
710+
711+ // Variant `btr mN,rN`: Modifies the EA based on the bit offset.
712+ test_cpu_t vcpu_original;
713+ test_cpu_t vcpu_expected;
714+ vcpu_original = {};
715+ vcpu_original.gpr [REG_RCX] = 0ULL ;
716+ (uint64_t &)vcpu_original.mem [0x00 ] = 0x00020000'00000000 ;
717+ (uint64_t &)vcpu_original.mem [0x08 ] = 0x00000000'00000000 ;
718+ (uint64_t &)vcpu_original.mem [0x10 ] = 0xFFFFFFFF'FFFFFFFE ;
719+
720+ vcpu_original.gpr [REG_RAX] = -15LL ;
721+ vcpu_expected = vcpu_original;
722+ vcpu_expected.flags |= RFLAGS_CF;
723+ (uint64_t &)vcpu_expected.mem [0x00 ] = 0x00000000'00000000 ;
724+ run (" btr [ecx + 0x08], eax" , vcpu_original, vcpu_expected);
725+ vcpu_original.gpr [REG_RAX] = +64LL ;
726+ vcpu_expected = vcpu_original;
727+ vcpu_expected.flags &= ~RFLAGS_CF;
728+ run (" btr [rcx + 0x08], rax" , vcpu_original, vcpu_expected);
674729}
675730
676731TEST_F (EmulatorTest, insn_bts) {
@@ -692,6 +747,25 @@ TEST_F(EmulatorTest, insn_bts) {
692747 { 0x80000000'00000000ULL , 0xFF , 0 ,
693748 0x80000000'00000000ULL , RFLAGS_CF },
694749 });
750+
751+ // Variant `bts mN,rN`: Modifies the EA based on the bit offset.
752+ test_cpu_t vcpu_original;
753+ test_cpu_t vcpu_expected;
754+ vcpu_original = {};
755+ vcpu_original.gpr [REG_RCX] = 0ULL ;
756+ (uint64_t &)vcpu_original.mem [0x00 ] = 0x00020000'00000000 ;
757+ (uint64_t &)vcpu_original.mem [0x08 ] = 0x00000000'00000000 ;
758+ (uint64_t &)vcpu_original.mem [0x10 ] = 0xFFFFFFFF'FFFFFFFE ;
759+
760+ vcpu_original.gpr [REG_RAX] = -15LL ;
761+ vcpu_expected = vcpu_original;
762+ vcpu_expected.flags |= RFLAGS_CF;
763+ run (" bts [ecx + 0x08], eax" , vcpu_original, vcpu_expected);
764+ vcpu_original.gpr [REG_RAX] = +64LL ;
765+ vcpu_expected = vcpu_original;
766+ vcpu_expected.flags &= ~RFLAGS_CF;
767+ (uint64_t &)vcpu_expected.mem [0x10 ] = 0xFFFFFFFF'FFFFFFFF ;
768+ run (" bts [rcx + 0x08], rax" , vcpu_original, vcpu_expected);
695769}
696770
697771TEST_F (EmulatorTest, insn_movs) {
0 commit comments