in libredex/DexInstruction.cpp [220:313]
uint16_t DexInstruction::src(int i) const {
auto format = dex_opcode::format(opcode());
switch (format) {
case FMT_f11x_s:
case FMT_f21t:
case FMT_f21c_s:
case FMT_f31t:
redex_assert(i == 0);
return (m_opcode >> 8) & 0xff;
case FMT_f12x:
case FMT_f22s:
case FMT_f22c_d:
redex_assert(i == 0);
return (m_opcode >> 12) & 0xf;
case FMT_f12x_2:
redex_assert(i < 2);
if (i == 0) return (m_opcode >> 8) & 0xf;
return (m_opcode >> 12) & 0xf;
case FMT_f22x:
case FMT_f3rc:
case FMT_f4rcc:
redex_assert(i == 0);
return m_arg[0];
case FMT_f23x_d:
redex_assert(i < 2);
if (i == 0) return m_arg[0] & 0xff;
return (m_arg[0] >> 8) & 0xff;
case FMT_f23x_s:
redex_assert(i < 3);
if (i == 0) return (m_opcode >> 8) & 0xff;
if (i == 1) return m_arg[0] & 0xff;
return (m_arg[0] >> 8) & 0xff;
case FMT_f22b:
redex_assert(i == 0);
return m_arg[0] & 0xff;
case FMT_f22t:
case FMT_f22c_s:
redex_assert(i < 2);
if (i == 0) return (m_opcode >> 8) & 0xf;
return (m_opcode >> 12) & 0xf; // i == 1
case FMT_f32x:
redex_assert(i == 0);
return m_arg[1];
case FMT_f35c:
case FMT_f45cc:
redex_assert(i < 5);
switch (i) {
case 0:
return m_arg[0] & 0xf;
case 1:
return (m_arg[0] >> 4) & 0xf;
case 2:
return (m_arg[0] >> 8) & 0xf;
case 3:
return (m_arg[0] >> 12) & 0xf;
case 4:
return (m_opcode >> 8) & 0xf;
}
case FMT_f41c_s:
redex_assert(i == 0);
return m_arg[0];
case FMT_f52c_d:
redex_assert(i == 0);
return m_arg[1];
case FMT_f52c_s:
redex_assert(i <= 1);
return m_arg[i];
case FMT_f5rc:
redex_assert(i == 0);
return m_arg[1];
case FMT_f57c:
redex_assert(i <= 6);
switch (i) {
case 0:
return (m_arg[0] >> 4) & 0xf;
case 1:
return (m_arg[0] >> 8) & 0xf;
case 2:
return (m_arg[0] >> 12) & 0xf;
case 3:
return m_arg[1] & 0xf;
case 4:
return (m_arg[1] >> 4) & 0xf;
case 5:
return (m_arg[1] >> 8) & 0xf;
case 6:
return (m_arg[1] >> 12) & 0xf;
}
not_reached();
default:
// All other formats do not define source registers.
not_reached_log("Unhandled opcode: %s", SHOW(this));
}
}