Commit c4550bc6 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

ARM: Add instructions VFPCompareAndSetFlags and VFPCompareAndLoadFlags to macro assembler

Also removed the SBit from the vcmp instruction as it is not part of the instruction.
Review URL: http://codereview.chromium.org/6117003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6268 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ecc00e78
......@@ -2337,7 +2337,6 @@ void Assembler::vdiv(const DwVfpRegister dst,
void Assembler::vcmp(const DwVfpRegister src1,
const DwVfpRegister src2,
const SBit s,
const Condition cond) {
// vcmp(Dd, Dm) double precision floating point comparison.
// We set bit E, as we want any NaN to set the cumulative exception flag
......@@ -2353,7 +2352,6 @@ void Assembler::vcmp(const DwVfpRegister src1,
void Assembler::vcmp(const DwVfpRegister src1,
const double src2,
const SBit s,
const Condition cond) {
// vcmp(Dd, Dm) double precision floating point comparison.
// Instruction details available in ARM DDI 0406A, A8-570.
......
......@@ -1147,11 +1147,9 @@ class Assembler : public Malloced {
const Condition cond = al);
void vcmp(const DwVfpRegister src1,
const DwVfpRegister src2,
const SBit s = LeaveCC,
const Condition cond = al);
void vcmp(const DwVfpRegister src1,
const double src2,
const SBit s = LeaveCC,
const Condition cond = al);
void vmrs(const Register dst,
const Condition cond = al);
......
......@@ -866,8 +866,7 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
__ vldr(d0, scratch2, HeapNumber::kValueOffset);
__ sub(probe, probe, Operand(kHeapObjectTag));
__ vldr(d1, probe, HeapNumber::kValueOffset);
__ vcmp(d0, d1);
__ vmrs(pc);
__ VFPCompareAndSetFlags(d0, d1);
__ b(ne, not_found); // The cache did not contain this value.
__ b(&load_result_from_cache);
} else {
......@@ -975,8 +974,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
CpuFeatures::Scope scope(VFP3);
Label no_nan;
// ARMv7 VFP3 instructions to implement double precision comparison.
__ vcmp(d7, d6);
__ vmrs(pc); // Move vector status bits to normal status bits.
__ VFPCompareAndSetFlags(d7, d6);
Label nan;
__ b(vs, &nan);
__ mov(r0, Operand(EQUAL), LeaveCC, eq);
......@@ -1096,8 +1094,7 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
__ sub(ip, tos_, Operand(kHeapObjectTag));
__ vldr(d1, ip, HeapNumber::kValueOffset);
__ vcmp(d1, 0.0);
__ vmrs(pc);
__ VFPCompareAndSetFlags(d1, 0.0);
// "tos_" is a register, and contains a non zero value by default.
// Hence we only need to overwrite "tos_" with zero to return false for
// FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
......@@ -4915,8 +4912,7 @@ void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
__ vldr(d1, r2, HeapNumber::kValueOffset);
// Compare operands
__ vcmp(d0, d1);
__ vmrs(pc); // Move vector status bits to normal status bits.
__ VFPCompareAndSetFlags(d0, d1);
// Don't base result on status bits when a NaN is involved.
__ b(vs, &unordered);
......
......@@ -4667,8 +4667,7 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
__ mov(scratch2, Operand(0x7FF00000));
__ mov(scratch1, Operand(0, RelocInfo::NONE));
__ vmov(d1, scratch1, scratch2); // Load infinity into d1.
__ vcmp(d0, d1);
__ vmrs(pc);
__ VFPCompareAndSetFlags(d0, d1);
runtime.Branch(eq); // d0 reached infinity.
__ vdiv(d0, d2, d0);
__ b(&allocate_return);
......
......@@ -1080,13 +1080,8 @@ void LCodeGen::DoBranch(LBranch* instr) {
DoubleRegister reg = ToDoubleRegister(instr->input());
Register scratch = scratch0();
// Test for the double value. Zero and NaN are false.
// Clear the Invalid cumulative exception flags.
__ ClearFPSCRBits(kVFPInvalidExceptionBit, scratch);
__ vcmp(reg, 0.0);
// Retrieve the exception and status flags and
// check for zero or an invalid exception.
__ vmrs(scratch);
// Test the double value. Zero and NaN are false.
__ VFPCompareAndLoadFlags(reg, 0.0, scratch);
__ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPInvalidExceptionBit));
EmitBranch(true_block, false_block, ne);
} else {
......@@ -1114,7 +1109,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
__ tst(reg, Operand(kSmiTagMask));
__ b(eq, true_label);
// Test for double values. Zero and NaN are false.
// Test double values. Zero and NaN are false.
Label call_stub;
DoubleRegister dbl_scratch = d0;
Register scratch = scratch0();
......@@ -1124,12 +1119,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
__ b(ne, &call_stub);
__ sub(ip, reg, Operand(kHeapObjectTag));
__ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
// Clear the Invalid cumulative exception flags.
__ ClearFPSCRBits(kVFPInvalidExceptionBit, scratch);
__ vcmp(dbl_scratch, 0.0);
// Retrieve the exception and status flags and
// check for zero or an invalid exception.
__ vmrs(scratch);
__ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch);
__ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPInvalidExceptionBit));
__ b(ne, false_label);
__ b(true_label);
......@@ -2206,7 +2196,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ bind(&heap_number);
__ sub(ip, input_reg, Operand(kHeapObjectTag));
__ vldr(dbl_tmp, ip, HeapNumber::kValueOffset);
__ vcmp(dbl_tmp, 0.0); // Sets overflow bit if NaN.
__ vcmp(dbl_tmp, 0.0); // Sets overflow bit in FPSCR flags if NaN.
__ vcvt_s32_f64(flt_scratch, dbl_tmp);
__ vmov(input_reg, flt_scratch); // 32-bit result of conversion.
__ vmrs(pc); // Move vector status bits to normal status bits.
......@@ -2227,8 +2217,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
// back to check; note that using non-overlapping s and d regs would be
// slightly faster.
__ vcvt_f64_s32(dbl_scratch, flt_scratch);
__ vcmp(dbl_scratch, dbl_tmp);
__ vmrs(pc); // Move vector status bits to normal status bits.
__ VFPCompareAndSetFlags(dbl_scratch, dbl_tmp);
DeoptimizeIf(ne, instr->environment()); // Not equal or unordered.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ tst(input_reg, Operand(input_reg));
......
......@@ -519,10 +519,54 @@ void MacroAssembler::Strd(Register src1, Register src2,
}
void MacroAssembler::ClearFPSCRBits(uint32_t bits_to_clear, Register scratch) {
vmrs(scratch);
bic(scratch, scratch, Operand(bits_to_clear));
vmsr(scratch);
void MacroAssembler::ClearFPSCRBits(const uint32_t bits_to_clear,
const Register scratch,
const Condition cond) {
vmrs(scratch, cond);
bic(scratch, scratch, Operand(bits_to_clear), LeaveCC, cond);
vmsr(scratch, cond);
}
void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
const DwVfpRegister src2,
const Condition cond) {
// Compare and move FPSCR flags to the normal condition flags.
vcmp(src1, src2, cond);
vmrs(pc, cond);
}
void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
const double src2,
const Condition cond) {
// Compare and move FPSCR flags to the normal condition flags.
vcmp(src1, src2, cond);
vmrs(pc, cond);
}
void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
const DwVfpRegister src2,
const Register fpscr_flags,
const Condition cond) {
// Clear the Invalid cumulative exception flags (use fpscr_flags as scratch).
ClearFPSCRBits(kVFPInvalidExceptionBit, fpscr_flags);
// Compare and load FPSCR.
vcmp(src1, src2, cond);
vmrs(fpscr_flags);
}
void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
const double src2,
const Register fpscr_flags,
const Condition cond) {
// Clear the Invalid cumulative exception flags (use fpscr_flags as scratch).
ClearFPSCRBits(kVFPInvalidExceptionBit, fpscr_flags);
// Compare and load FPSCR.
vcmp(src1, src2, cond);
vmrs(fpscr_flags);
}
......
......@@ -247,8 +247,29 @@ class MacroAssembler: public Assembler {
const MemOperand& dst,
Condition cond = al);
// Clear FPSCR bits.
void ClearFPSCRBits(uint32_t bits_to_clear, Register scratch);
// Clear specified FPSCR bits.
void ClearFPSCRBits(const uint32_t bits_to_clear,
const Register scratch,
const Condition cond = al);
// Compare double values and move the result to the normal condition flags.
void VFPCompareAndSetFlags(const DwVfpRegister src1,
const DwVfpRegister src2,
const Condition cond = al);
void VFPCompareAndSetFlags(const DwVfpRegister src1,
const double src2,
const Condition cond = al);
// Compare double values and then load the fpscr flags to a register.
void VFPCompareAndLoadFlags(const DwVfpRegister src1,
const DwVfpRegister src2,
const Register fpscr_flags,
const Condition cond = al);
void VFPCompareAndLoadFlags(const DwVfpRegister src1,
const double src2,
const Register fpscr_flags,
const Condition cond = al);
// ---------------------------------------------------------------------------
// Activation frames
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment