[vm, x64] Add missing addressing mode for testb.

To be used by the incremental write barrier.

Bug: https://github.com/dart-lang/sdk/issues/34002
Change-Id: I1f5214b5abe348fbb4eaa399819b01e515b085fb
Reviewed-on: https://dart-review.googlesource.com/71060
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Aart Bik <ajcbik@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index bee1638..9708f45 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -464,6 +464,13 @@
   EmitUint8(imm.value() & 0xFF);
 }
 
+void Assembler::testb(const Address& address, Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandREX(reg, address, REX_NONE);
+  EmitUint8(0x84);
+  EmitOperand(reg & 7, address);
+}
+
 void Assembler::testq(Register reg, const Immediate& imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   if (imm.is_uint8()) {
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 5b86aca..df24912 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -523,6 +523,7 @@
 
   void testl(Register reg, const Immediate& imm) { testq(reg, imm); }
   void testb(const Address& address, const Immediate& imm);
+  void testb(const Address& address, Register reg);
 
   void testq(Register reg, const Immediate& imm);
   void TestImmediate(Register dst, const Immediate& imm);
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index e478f97..12f73d7 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -637,6 +637,38 @@
       "ret\n");
 }
 
+ASSEMBLER_TEST_GENERATE(Testb3, assembler) {
+  Label zero;
+  __ pushq(CallingConventions::kArg1Reg);
+  __ movq(RBX, Immediate(0x10));
+  __ testb(Address(RSP, 0), RBX);
+  __ j(ZERO, &zero);
+  __ movq(RAX, Immediate(1));
+  __ popq(RCX);
+  __ ret();
+  __ Bind(&zero);
+  __ movq(RAX, Immediate(0));
+  __ popq(RCX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Testb3, test) {
+  typedef int (*TestbCode)(int);
+  EXPECT_EQ(1, reinterpret_cast<TestbCode>(test->entry())(0x11));
+  EXPECT_EQ(0, reinterpret_cast<TestbCode>(test->entry())(0x101));
+  EXPECT_DISASSEMBLY_NOT_WINDOWS(
+      "push rdi\n"
+      "movl rbx,0x10\n"
+      "testb rbx,[rsp]\n"
+      "jz 0x................\n"
+      "movl rax,1\n"
+      "pop rcx\n"
+      "ret\n"
+      "movl rax,0\n"
+      "pop rcx\n"
+      "ret\n");
+}
+
 ASSEMBLER_TEST_GENERATE(Increment, assembler) {
   __ movq(RAX, Immediate(0));
   __ pushq(RAX);