Make dex instruction size a lookup.
Add ostream operators for dex instruction enums.
Move simple methods to header file.
Change-Id: I9644bfb975896a491ee73ef9a8ef13c062c5fcbd
diff --git a/src/dex_instruction.cc b/src/dex_instruction.cc
index 80a7d9d..0de7523 100644
--- a/src/dex_instruction.cc
+++ b/src/dex_instruction.cc
@@ -53,6 +53,20 @@
#undef INSTRUCTION_VERIFY_FLAGS
};
+int const Instruction::kInstructionSizeInCodeUnits[] = {
+#define INSTRUCTION_SIZE(opcode, c, p, format, r, i, a, v) \
+ (( opcode == NOP ) ? -1 : \
+ ((format >= k10x) && (format <= k10t)) ? 1 : \
+ ((format >= k20t) && (format <= k22c)) ? 2 : \
+ ((format >= k32x) && (format <= k3rc)) ? 3 : \
+ ( format == k51l ) ? 5 : -1 \
+ ),
+#include "dex_instruction_list.h"
+ DEX_INSTRUCTION_LIST(INSTRUCTION_SIZE)
+#undef DEX_INSTRUCTION_LIST
+#undef INSTRUCTION_SIZE
+};
+
/*
* Handy macros for helping decode instructions.
*/
@@ -70,9 +84,9 @@
void Instruction::Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const {
const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
uint16_t insn = *insns;
- int opcode = insn & 0xFF;
+ Code opcode = static_cast<Code>(insn & 0xFF);
- switch (FormatOf(Opcode())) {
+ switch (FormatOf(opcode)) {
case k10x: // op
/* nothing to do; copy the AA bits out for the verifier */
vA = INST_AA(insn);
@@ -201,69 +215,33 @@
vB_wide = FETCH_u4(1) | ((uint64_t) FETCH_u4(3) << 32);
break;
default:
- LOG(ERROR) << "Can't decode unexpected format " << static_cast<int>(FormatOf(Opcode())) << " (op=" << opcode << ")";
+ LOG(ERROR) << "Can't decode unexpected format " << FormatOf(opcode) << " (op=" << opcode << ")";
return;
}
}
-size_t Instruction::SizeInCodeUnits() const {
+size_t Instruction::SizeInCodeUnitsComplexOpcode() const {
const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
- if (*insns == Instruction::kPackedSwitchSignature) {
- return (4 + insns[1] * 2);
- } else if (*insns == Instruction::kSparseSwitchSignature) {
- return (2 + insns[1] * 4);
- } else if (*insns == kArrayDataSignature) {
- uint16_t element_size = insns[1];
- uint32_t length = insns[2] | (((uint32_t)insns[3]) << 16);
- // The plus 1 is to round up for odd size and width.
- return (4 + (element_size * length + 1) / 2);
- } else {
- switch (FormatOf(Opcode())) {
- case k10x:
- case k12x:
- case k11n:
- case k11x:
- case k10t:
- return 1;
- case k20t:
- case k22x:
- case k21t:
- case k21s:
- case k21h:
- case k21c:
- case k23x:
- case k22b:
- case k22t:
- case k22s:
- case k22c:
- return 2;
- case k32x:
- case k30t:
- case k31t:
- case k31i:
- case k31c:
- case k35c:
- case k3rc:
- return 3;
- case k51l:
- return 5;
- default:
- LOG(FATAL) << "Unreachable";
+ // Handle special NOP encoded variable length sequences.
+ switch (*insns) {
+ case kPackedSwitchSignature:
+ return (4 + insns[1] * 2);
+ case kSparseSwitchSignature:
+ return (2 + insns[1] * 4);
+ case kArrayDataSignature: {
+ uint16_t element_size = insns[1];
+ uint32_t length = insns[2] | (((uint32_t)insns[3]) << 16);
+ // The plus 1 is to round up for odd size and width.
+ return (4 + (element_size * length + 1) / 2);
}
+ default:
+ if ((*insns & 0xFF) == 0) {
+ return 1; // NOP.
+ } else {
+ LOG(FATAL) << "Unreachable: " << DumpString(NULL);
+ return 0;
+ }
}
- return 0;
-}
-
-Instruction::Code Instruction::Opcode() const {
- const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
- int opcode = *insns & 0xFF;
- return static_cast<Code>(opcode);
-}
-
-const Instruction* Instruction::Next() const {
- size_t current_size_in_bytes = SizeInCodeUnits() * sizeof(uint16_t);
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
- return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
}
std::string Instruction::DumpHex(size_t code_units) const {
@@ -449,9 +427,8 @@
return os.str();
}
-DecodedInstruction::DecodedInstruction(const Instruction* inst) {
- inst->Decode(vA, vB, vB_wide, vC, arg);
- opcode = inst->Opcode();
+std::ostream& operator<<(std::ostream& os, const Instruction::Code& code) {
+ return os << Instruction::Name(code);
}
} // namespace art