Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Unified Diff: src/x64/codegen-x64.cc

Issue 300004: X64 Win64: Reimplement fmod so that it works. (Closed)
Patch Set: And it lints. Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/x64/codegen-x64.cc
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index d72257e96f007c32de8378436b2b35344d2cfdd8..8e4a8ca7bd83f4ccb88227bfc4302d15c215ba31 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -219,12 +219,19 @@ class FloatingPointHelper : public AllStatic {
// Input values must be either smi or heap number objects (fp values).
// Requirements:
// Register version: operands in registers lhs and rhs.
+ // Version without scratch memory pushes and pops the stack to get a
+ // memory cell, the version with scratch memory uses 8 bytes (64 bits)
+ // at that location.
// Stack version: operands on TOS+1 and TOS+2.
// Returns operands as floating point numbers on fp stack.
static void LoadFloatOperands(MacroAssembler* masm);
static void LoadFloatOperands(MacroAssembler* masm,
Register lhs,
Register rhs);
+ static void LoadFloatOperands(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
+ const Operand& scratch_memory);
// Code pattern for loading a floating point value and converting it
// to a 32 bit integer. Input value must be either a smi or a heap number
@@ -4004,6 +4011,112 @@ void CodeGenerator::GenerateFastMathOp(MathOp op, ZoneList<Expression*>* args) {
}
William Hesse 2009/10/20 14:50:51 Could this function be documented more, explaining
+void CodeGenerator::GenerateNumberMod(ZoneList<Expression*>* args) {
+ ASSERT_EQ(2, args->length());
+#ifdef _WIN64
+ Load(args->at(0));
+ Load(args->at(1));
+ // Allocate rax for using fnstsw_ax.
+ Result tmp = allocator_->Allocate(rax);
+ // Allocate callee save register, for storing value while calling runtime.
+ Result callee_save_result = allocator_->Allocate(r15);
+ Result divisor_result = frame_->Pop();
+ Result dividend_result = frame_->Pop();
+ divisor_result.ToRegister();
+ dividend_result.ToRegister();
+ {
+ // Code uses the physical stack, so it must be in sync.
+ VirtualFrame::SpilledScope scope;
+ Register dividend = dividend_result.reg();
+ Register divisor = divisor_result.reg();
+ Register callee_save = callee_save_result.reg();
+
+ Label done;
+ // Make room on stack for temporary value.
+ __ subq(rsp, Immediate(kPointerSize));
+
+ // Load operands onto FPU stack.
+ // Divisor must go first on stack, so order of operands is really rhs, lhs.
+ FloatingPointHelper::LoadFloatOperands(masm_,
+ divisor,
+ dividend,
+ Operand(rsp, 0));
+
+ // Compute the remainder.
+ {
+ Label partial_remainder_loop;
+ __ bind(&partial_remainder_loop);
+ __ fprem();
+ __ fwait();
+ __ fnstsw_ax();
+ __ testl(rax, Immediate(kCondition2));
+ __ j(not_zero, &partial_remainder_loop);
+ }
+
+ // Result is in ST(0), garbage in ST(1), and original value
+ // of dividend in ST(2). Return ST(0) unless a division by zero or
+ // invalid operation exception has been raised. Status word is in rax.
+
+ Label valid_result;
+ Label allocate_result;
+ // Test for InvalidOperation or division by zero.
+ // In those cases, discard the result and use NaN instead.
+ __ testb(rax, Immediate(kInvalidOperandException | kZeroDivideException));
+ __ j(zero, &valid_result);
+
+ __ fstp(0); // Pop (garbage) result
+ __ addq(rsp, Immediate(kPointerSize)); // Free stack cell.
+ int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000);
+ // Move NaN to (callee save) register for later storing into new HeapNumber.
+ __ movq(callee_save, kNaNValue, RelocInfo::NONE);
+ __ jmp(&allocate_result);
+
+ // Allocate new space for a HeapNumber (is branched back to if direct heap
+ // allocation fails in the following code).
+ Label gc_req;
+ Label heap_number_allocated;
+ __ bind(&gc_req);
+ // Garbage collection required before allocating a heap number.
+ // Call runtime to do the allocation, and handle the allocation failure.
+ __ CallRuntime(Runtime::kAllocateHeapNumber, 0);
+ __ jmp(&heap_number_allocated);
+
+ __ bind(&valid_result);
+
+ // Result in ST(0), garbage in ST(1) and ST(2).
+ // Pop result and free stack cell.
+ __ fstp_d(Operand(rsp, 0));
+ __ pop(callee_save);
+
+ __ bind(&allocate_result);
+ // Free FPU stack and clear pending FPU exceptions (e.g., Denormal).
+ __ fstp(0);
+ Label no_exceptions_set;
+ __ testb(rax, Immediate(kAnyExceptionMask));
+ __ j(zero, &no_exceptions_set);
+ __ fnclex();
+ __ bind(&no_exceptions_set);
+
+ FloatingPointHelper::AllocateHeapNumber(masm_, &gc_req, dividend, rax);
+ __ bind(&heap_number_allocated); // Return point for gc_req branch.
+ __ movq(FieldOperand(rax, HeapNumber::kValueOffset), callee_save);
+
+ __ bind(&done);
+ }
+ frame_->Push(&tmp);
+
+#else
+ // Simply call the runtime function. Arguments must be numbers.
+ ASSERT(args->length() == 2);
+ Load(args->at(0));
+ Load(args->at(1));
+
+ Result answer = frame_->CallRuntime(Runtime::kNumberMod, 2);
+ frame_->Push(&answer);
+#endif
+}
+
+
void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
JumpTarget leave, null, function, non_function_constructor;
@@ -7324,17 +7437,41 @@ void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
__ jmp(&done);
__ bind(&load_smi_lhs);
- __ SmiToInteger64(kScratchRegister, lhs);
- __ push(kScratchRegister);
- __ fild_d(Operand(rsp, 0));
- __ pop(kScratchRegister);
+ __ push(lhs);
+ __ FLoadSmi(Operand(rsp, 0));
+ __ addq(rsp, Immediate(kPointerSize));
__ jmp(&done_load_lhs);
__ bind(&load_smi_rhs);
- __ SmiToInteger64(kScratchRegister, rhs);
- __ push(kScratchRegister);
- __ fild_d(Operand(rsp, 0));
- __ pop(kScratchRegister);
+ __ push(rhs);
+ __ FLoadSmi(Operand(rsp, 0));
+ __ addq(rsp, Immediate(kPointerSize));
+
+ __ bind(&done);
+}
+
+
+void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
+ const Operand& scratch_memory) {
+ Label load_smi_lhs, load_smi_rhs, done_load_lhs, done;
+ __ JumpIfSmi(lhs, &load_smi_lhs);
+ __ fld_d(FieldOperand(lhs, HeapNumber::kValueOffset));
+ __ bind(&done_load_lhs);
+
+ __ JumpIfSmi(rhs, &load_smi_rhs);
+ __ fld_d(FieldOperand(rhs, HeapNumber::kValueOffset));
+ __ jmp(&done);
+
+ __ bind(&load_smi_lhs);
+ __ movq(scratch_memory, lhs);
+ __ FLoadSmi(scratch_memory);
+ __ jmp(&done_load_lhs);
+
+ __ bind(&load_smi_rhs);
+ __ movq(scratch_memory, rhs);
+ __ FLoadSmi(scratch_memory);
__ bind(&done);
}

Powered by Google App Engine
This is Rietveld 408576698