uint16_t DexInstruction::src()

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));
  }
}