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