in tools/oatmeal/dex.cpp [33:282]
void make_instruction(const uint16_t** insns_ptr,
const QuickData* quick_data,
const std::string* dex,
size_t& file_ptr,
WritableBuffer& out_buffer) {
auto& insns = *insns_ptr;
auto fopcode = static_cast<DexOpcode>(*insns++);
DexOpcode opcode = static_cast<DexOpcode>(fopcode & 0xff);
// clang-format off
#ifdef DEBUG_LOG
printf("Processing FOPCODE::OPCODE: %04x :: %02x :: %s\n",
fopcode,
opcode,
print(opcode).c_str());
#endif
switch (opcode) {
case DOPCODE_NOP: {
#ifdef DEBUG_LOG
printf("Processing FOPCODE: %s\n", print(fopcode).c_str());
#endif
if (fopcode == FOPCODE_PACKED_SWITCH) {
size_t count = (*insns--) * 2 + 4;
for (size_t i = 0; i < count; i++) {
WRITE16_TO_BUFFER(out_buffer, insns, file_ptr)
insns++;
}
return;
} else if (fopcode == FOPCODE_SPARSE_SWITCH) {
size_t count = (*insns--) * 4 + 2;
for (size_t i = 0; i < count; i++) {
WRITE16_TO_BUFFER(out_buffer, insns, file_ptr)
insns++;
}
return;
} else if (fopcode == FOPCODE_FILLED_ARRAY) {
uint16_t ewidth = *insns++;
uint32_t size = *((uint32_t*)insns);
size_t count = (ewidth * size + 1) / 2 + 4;
insns -= 2;
for (size_t i = 0; i < count; i++) {
WRITE16_TO_BUFFER(out_buffer, insns, file_ptr)
insns++;
}
return;
}
}
/* fall through for NOP */
SWITCH_FORMAT_10 {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x :: %s\n", opcode, print(opcode).c_str());
#endif
break;
}
SWITCH_FORMAT_20 {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
uint16_t arg = *insns++;
WRITE16_TO_BUFFER(out_buffer, arg, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x %02x :: %s\n",
opcode,
arg,
print(opcode).c_str());
#endif
break;
}
SWITCH_FORMAT_30 {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
uint16_t arg_low = *insns++;
WRITE16_TO_BUFFER(out_buffer, arg_low, file_ptr)
uint16_t arg_high = *insns++;
WRITE16_TO_BUFFER(out_buffer, arg_high, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x %02x%02x :: %s\n",
opcode,
arg_low,
arg_high,
print(opcode).c_str());
#endif
break;
}
SWITCH_FORMAT_50 {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
uint16_t arg_0 = *insns++;
WRITE16_TO_BUFFER(out_buffer, arg_0, file_ptr)
uint16_t arg_1 = *insns++;
WRITE16_TO_BUFFER(out_buffer, arg_1, file_ptr)
uint16_t arg_2 = *insns++;
WRITE16_TO_BUFFER(out_buffer, arg_2, file_ptr)
uint16_t arg_3 = *insns++;
WRITE16_TO_BUFFER(out_buffer, arg_3, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x %02x%02x%02x%02x :: %s\n",
opcode,
arg_0,
arg_1,
arg_2,
arg_3,
print(opcode).c_str());
#endif
break;
// return new DexInstruction(insns - 5, 4);
}
SWITCH_FORMAT_REGULAR_FIELD_REF {
uint16_t fidx = *insns++;
uint16_t quick_fopcode = fopcode;
uint16_t quick_arg = fidx;
uint16_t quick_data_off = quick_data->get_field_offset(*dex, fidx);
if (quick_data_off > 0) {
quick_fopcode = (fopcode & 0xff00) | (quicken(opcode) & 0x00ff);
quick_arg = quick_data_off;
#ifdef DEBUG_LOG
printf("QUICKEN: [%s] %s :: %02x->%02x :: %02x->%02x\n",
(*dex).c_str(),
print(opcode).c_str(),
fopcode,
quick_fopcode,
fidx,
quick_arg);
#endif
} else {
#ifdef DEBUG_LOG
printf("No quick mapping for: [%s]:%u\n", (*dex).c_str(), fidx);
#endif
}
WRITE16_TO_BUFFER(out_buffer, quick_fopcode, file_ptr)
WRITE16_TO_BUFFER(out_buffer, quick_arg, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x %02x :: %s\n",
quick_fopcode,
quick_arg,
print(opcode).c_str());
#endif
break;
}
SWITCH_FORMAT_REGULAR_METHOD_REF {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
uint16_t midx = *insns++;
uint16_t arg = *insns++;
WRITE16_TO_BUFFER(out_buffer, midx, file_ptr)
WRITE16_TO_BUFFER(out_buffer, arg, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x %02x %02x :: %s\n",
fopcode,
midx,
arg,
print(opcode).c_str());
#endif
break;
}
SWITCH_FORMAT_CONST_STRING {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
uint16_t sidx = *insns++;
WRITE16_TO_BUFFER(out_buffer, sidx, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x %02x :: %s\n",
fopcode,
sidx,
print(opcode).c_str());
#endif
break;
}
SWITCH_FORMAT_CONST_STRING_JUMBO {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
uint16_t sidx_partial_low = *insns++;
uint16_t sidx_partial_high = *insns++;
WRITE16_TO_BUFFER(out_buffer, sidx_partial_low, file_ptr)
WRITE16_TO_BUFFER(out_buffer, sidx_partial_high, file_ptr)
#ifdef DEBUG_LOG
uint32_t sidx = sidx_partial_high << 16 | sidx_partial_low;
printf("Writing OPCODE: %02x %04x :: %s\n",
fopcode,
sidx,
print(opcode).c_str());
#endif
break;
}
SWITCH_FORMAT_TYPE_REF {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
uint16_t tidx = *insns++;
WRITE16_TO_BUFFER(out_buffer, tidx, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x %02x :: %s\n",
fopcode,
tidx,
print(opcode).c_str());
#endif
break;
}
SWITCH_FORMAT_FILL_ARRAY {
WRITE16_TO_BUFFER(out_buffer, fopcode, file_ptr)
uint16_t tidx = *insns++;
uint16_t arg = *insns++;
WRITE16_TO_BUFFER(out_buffer, tidx, file_ptr)
WRITE16_TO_BUFFER(out_buffer, arg, file_ptr)
#ifdef DEBUG_LOG
printf("Writing OPCODE: %02x %02x :: %s\n",
fopcode,
tidx,
print(opcode).c_str());
#endif
break;
}
default:
fprintf(stderr, "Unknown opcode %02x\n", opcode);
// return nullptr;
}
// clang-format on
}