Instruction: Add new formats 45cc and 4rcc.
These are new 4 byte formats with the following properties.
- The first three (16 bit) words of these instructions have the same
format as 35c and 3rc respectively.
- The fourth 16 bit word encodes an additional constant index reference.
This change includes placeholder opcodes for invoke-polymorphic and
invoke-polymorphic/range which will be the first dex instructions that
use this new format. In addition to a method_idx that gives the invoked
method, these instructions also provide a proto_idx which gives the
(static) type signature of the call site.
The only reason these are included in this change is because we need
an instruction with a given format to write a unit_test using the Instruction
API.
bug: 30550796
test: make test-art-host
Change-Id: I02612ddee47169757175a8079d82f811f6545945
diff --git a/runtime/dex_instruction_test.cc b/runtime/dex_instruction_test.cc
index 671ac0e..00c8e07 100644
--- a/runtime/dex_instruction_test.cc
+++ b/runtime/dex_instruction_test.cc
@@ -28,4 +28,96 @@
EXPECT_EQ(Instruction::kVerifyNone, Instruction::VerifyFlagsOf(nop));
}
+static void Build45cc(uint8_t num_args, uint16_t method_idx, uint16_t proto_idx,
+ uint16_t arg_regs, uint16_t* out) {
+ // A = num argument registers
+ // B = method_idx
+ // C - G = argument registers
+ // H = proto_idx
+ //
+ // op = 0xFA
+ //
+ // format:
+ // AG op BBBB FEDC HHHH
+ out[0] = 0;
+ out[0] |= (num_args << 12);
+ out[0] |= 0x00FA;
+
+ out[1] = method_idx;
+ out[2] = arg_regs;
+ out[3] = proto_idx;
+}
+
+static void Build4rcc(uint16_t num_args, uint16_t method_idx, uint16_t proto_idx,
+ uint16_t arg_regs_start, uint16_t* out) {
+ // A = num argument registers
+ // B = method_idx
+ // C = first argument register
+ // H = proto_idx
+ //
+ // op = 0xFB
+ //
+ // format:
+ // AA op BBBB CCCC HHHH
+ out[0] = 0;
+ out[0] |= (num_args << 8);
+ out[0] |= 0x00FB;
+
+ out[1] = method_idx;
+ out[2] = arg_regs_start;
+ out[3] = proto_idx;
+}
+
+TEST(Instruction, PropertiesOf45cc) {
+ uint16_t instruction[4];
+ Build45cc(4u /* num_vregs */, 16u /* method_idx */, 32u /* proto_idx */,
+ 0xcafe /* arg_regs */, instruction);
+
+ const Instruction* ins = Instruction::At(instruction);
+ ASSERT_EQ(4u, ins->SizeInCodeUnits());
+
+ ASSERT_TRUE(ins->HasVRegA());
+ ASSERT_EQ(4, ins->VRegA());
+ ASSERT_EQ(4u, ins->VRegA_45cc());
+ ASSERT_EQ(4u, ins->VRegA_45cc(instruction[0]));
+
+ ASSERT_TRUE(ins->HasVRegB());
+ ASSERT_EQ(16, ins->VRegB());
+ ASSERT_EQ(16u, ins->VRegB_45cc());
+
+ ASSERT_TRUE(ins->HasVRegC());
+ ASSERT_EQ(0xe, ins->VRegC());
+ ASSERT_EQ(0xe, ins->VRegC_45cc());
+
+ ASSERT_TRUE(ins->HasVRegH());
+ ASSERT_EQ(32, ins->VRegH());
+ ASSERT_EQ(32, ins->VRegH_45cc());
+}
+
+TEST(Instruction, PropertiesOf4rcc) {
+ uint16_t instruction[4];
+ Build4rcc(4u /* num_vregs */, 16u /* method_idx */, 32u /* proto_idx */,
+ 0xcafe /* arg_regs */, instruction);
+
+ const Instruction* ins = Instruction::At(instruction);
+ ASSERT_EQ(4u, ins->SizeInCodeUnits());
+
+ ASSERT_TRUE(ins->HasVRegA());
+ ASSERT_EQ(4, ins->VRegA());
+ ASSERT_EQ(4u, ins->VRegA_4rcc());
+ ASSERT_EQ(4u, ins->VRegA_4rcc(instruction[0]));
+
+ ASSERT_TRUE(ins->HasVRegB());
+ ASSERT_EQ(16, ins->VRegB());
+ ASSERT_EQ(16u, ins->VRegB_4rcc());
+
+ ASSERT_TRUE(ins->HasVRegC());
+ ASSERT_EQ(0xcafe, ins->VRegC());
+ ASSERT_EQ(0xcafe, ins->VRegC_4rcc());
+
+ ASSERT_TRUE(ins->HasVRegH());
+ ASSERT_EQ(32, ins->VRegH());
+ ASSERT_EQ(32, ins->VRegH_4rcc());
+}
+
} // namespace art