void InstructionCodeGeneratorMIPS::GenerateLongCompareAndBranch()

in compiler/optimizing/code_generator_mips.cc [2838:3049]


void InstructionCodeGeneratorMIPS::GenerateLongCompareAndBranch(IfCondition cond,
                                                                LocationSummary* locations,
                                                                MipsLabel* label) {
  Register lhs_high = locations->InAt(0).AsRegisterPairHigh<Register>();
  Register lhs_low = locations->InAt(0).AsRegisterPairLow<Register>();
  Location rhs_location = locations->InAt(1);
  Register rhs_high = ZERO;
  Register rhs_low = ZERO;
  int64_t imm = 0;
  uint32_t imm_high = 0;
  uint32_t imm_low = 0;
  bool use_imm = rhs_location.IsConstant();
  if (use_imm) {
    imm = rhs_location.GetConstant()->AsLongConstant()->GetValue();
    imm_high = High32Bits(imm);
    imm_low = Low32Bits(imm);
  } else {
    rhs_high = rhs_location.AsRegisterPairHigh<Register>();
    rhs_low = rhs_location.AsRegisterPairLow<Register>();
  }

  if (use_imm && imm == 0) {
    switch (cond) {
      case kCondEQ:
      case kCondBE:  // <= 0 if zero
        __ Or(TMP, lhs_high, lhs_low);
        __ Beqz(TMP, label);
        break;
      case kCondNE:
      case kCondA:  // > 0 if non-zero
        __ Or(TMP, lhs_high, lhs_low);
        __ Bnez(TMP, label);
        break;
      case kCondLT:
        __ Bltz(lhs_high, label);
        break;
      case kCondGE:
        __ Bgez(lhs_high, label);
        break;
      case kCondLE:
        __ Or(TMP, lhs_high, lhs_low);
        __ Sra(AT, lhs_high, 31);
        __ Bgeu(AT, TMP, label);
        break;
      case kCondGT:
        __ Or(TMP, lhs_high, lhs_low);
        __ Sra(AT, lhs_high, 31);
        __ Bltu(AT, TMP, label);
        break;
      case kCondB:  // always false
        break;
      case kCondAE:  // always true
        __ B(label);
        break;
    }
  } else if (use_imm) {
    // TODO: more efficient comparison with constants without loading them into TMP/AT.
    switch (cond) {
      case kCondEQ:
        __ LoadConst32(TMP, imm_high);
        __ Xor(TMP, TMP, lhs_high);
        __ LoadConst32(AT, imm_low);
        __ Xor(AT, AT, lhs_low);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondNE:
        __ LoadConst32(TMP, imm_high);
        __ Xor(TMP, TMP, lhs_high);
        __ LoadConst32(AT, imm_low);
        __ Xor(AT, AT, lhs_low);
        __ Or(TMP, TMP, AT);
        __ Bnez(TMP, label);
        break;
      case kCondLT:
        __ LoadConst32(TMP, imm_high);
        __ Blt(lhs_high, TMP, label);
        __ Slt(TMP, TMP, lhs_high);
        __ LoadConst32(AT, imm_low);
        __ Sltu(AT, lhs_low, AT);
        __ Blt(TMP, AT, label);
        break;
      case kCondGE:
        __ LoadConst32(TMP, imm_high);
        __ Blt(TMP, lhs_high, label);
        __ Slt(TMP, lhs_high, TMP);
        __ LoadConst32(AT, imm_low);
        __ Sltu(AT, lhs_low, AT);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondLE:
        __ LoadConst32(TMP, imm_high);
        __ Blt(lhs_high, TMP, label);
        __ Slt(TMP, TMP, lhs_high);
        __ LoadConst32(AT, imm_low);
        __ Sltu(AT, AT, lhs_low);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondGT:
        __ LoadConst32(TMP, imm_high);
        __ Blt(TMP, lhs_high, label);
        __ Slt(TMP, lhs_high, TMP);
        __ LoadConst32(AT, imm_low);
        __ Sltu(AT, AT, lhs_low);
        __ Blt(TMP, AT, label);
        break;
      case kCondB:
        __ LoadConst32(TMP, imm_high);
        __ Bltu(lhs_high, TMP, label);
        __ Sltu(TMP, TMP, lhs_high);
        __ LoadConst32(AT, imm_low);
        __ Sltu(AT, lhs_low, AT);
        __ Blt(TMP, AT, label);
        break;
      case kCondAE:
        __ LoadConst32(TMP, imm_high);
        __ Bltu(TMP, lhs_high, label);
        __ Sltu(TMP, lhs_high, TMP);
        __ LoadConst32(AT, imm_low);
        __ Sltu(AT, lhs_low, AT);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondBE:
        __ LoadConst32(TMP, imm_high);
        __ Bltu(lhs_high, TMP, label);
        __ Sltu(TMP, TMP, lhs_high);
        __ LoadConst32(AT, imm_low);
        __ Sltu(AT, AT, lhs_low);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondA:
        __ LoadConst32(TMP, imm_high);
        __ Bltu(TMP, lhs_high, label);
        __ Sltu(TMP, lhs_high, TMP);
        __ LoadConst32(AT, imm_low);
        __ Sltu(AT, AT, lhs_low);
        __ Blt(TMP, AT, label);
        break;
    }
  } else {
    switch (cond) {
      case kCondEQ:
        __ Xor(TMP, lhs_high, rhs_high);
        __ Xor(AT, lhs_low, rhs_low);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondNE:
        __ Xor(TMP, lhs_high, rhs_high);
        __ Xor(AT, lhs_low, rhs_low);
        __ Or(TMP, TMP, AT);
        __ Bnez(TMP, label);
        break;
      case kCondLT:
        __ Blt(lhs_high, rhs_high, label);
        __ Slt(TMP, rhs_high, lhs_high);
        __ Sltu(AT, lhs_low, rhs_low);
        __ Blt(TMP, AT, label);
        break;
      case kCondGE:
        __ Blt(rhs_high, lhs_high, label);
        __ Slt(TMP, lhs_high, rhs_high);
        __ Sltu(AT, lhs_low, rhs_low);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondLE:
        __ Blt(lhs_high, rhs_high, label);
        __ Slt(TMP, rhs_high, lhs_high);
        __ Sltu(AT, rhs_low, lhs_low);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondGT:
        __ Blt(rhs_high, lhs_high, label);
        __ Slt(TMP, lhs_high, rhs_high);
        __ Sltu(AT, rhs_low, lhs_low);
        __ Blt(TMP, AT, label);
        break;
      case kCondB:
        __ Bltu(lhs_high, rhs_high, label);
        __ Sltu(TMP, rhs_high, lhs_high);
        __ Sltu(AT, lhs_low, rhs_low);
        __ Blt(TMP, AT, label);
        break;
      case kCondAE:
        __ Bltu(rhs_high, lhs_high, label);
        __ Sltu(TMP, lhs_high, rhs_high);
        __ Sltu(AT, lhs_low, rhs_low);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondBE:
        __ Bltu(lhs_high, rhs_high, label);
        __ Sltu(TMP, rhs_high, lhs_high);
        __ Sltu(AT, rhs_low, lhs_low);
        __ Or(TMP, TMP, AT);
        __ Beqz(TMP, label);
        break;
      case kCondA:
        __ Bltu(rhs_high, lhs_high, label);
        __ Sltu(TMP, lhs_high, rhs_high);
        __ Sltu(AT, rhs_low, lhs_low);
        __ Blt(TMP, AT, label);
        break;
    }
  }
}