| Index: src/x87/macro-assembler-x87.cc
|
| diff --git a/src/x87/macro-assembler-x87.cc b/src/x87/macro-assembler-x87.cc
|
| index 66f57033434a10779f30d45657e4ad8d084031a5..640f03d990b0efb0cb770a01e318999b38c0c503 100644
|
| --- a/src/x87/macro-assembler-x87.cc
|
| +++ b/src/x87/macro-assembler-x87.cc
|
| @@ -150,6 +150,7 @@ void MacroAssembler::RememberedSetHelper(
|
| Register object, // Only used for debug checks.
|
| Register addr,
|
| Register scratch,
|
| + SaveFPRegsMode save_fp,
|
| MacroAssembler::RememberedSetFinalAction and_then) {
|
| Label done;
|
| if (emit_debug_code()) {
|
| @@ -180,7 +181,7 @@ void MacroAssembler::RememberedSetHelper(
|
| DCHECK(and_then == kFallThroughAtEnd);
|
| j(equal, &done, Label::kNear);
|
| }
|
| - StoreBufferOverflowStub store_buffer_overflow(isolate(), kDontSaveFPRegs);
|
| + StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
|
| CallStub(&store_buffer_overflow);
|
| if (and_then == kReturnAtEnd) {
|
| ret(0);
|
| @@ -191,6 +192,31 @@ void MacroAssembler::RememberedSetHelper(
|
| }
|
|
|
|
|
| +void MacroAssembler::ClampTOSToUint8(Register result_reg) {
|
| + Label done, conv_failure;
|
| + sub(esp, Immediate(kPointerSize));
|
| + fnclex();
|
| + fist_s(Operand(esp, 0));
|
| + pop(result_reg);
|
| + X87CheckIA();
|
| + j(equal, &conv_failure, Label::kNear);
|
| + test(result_reg, Immediate(0xFFFFFF00));
|
| + j(zero, &done, Label::kNear);
|
| + setcc(sign, result_reg);
|
| + sub(result_reg, Immediate(1));
|
| + and_(result_reg, Immediate(255));
|
| + jmp(&done, Label::kNear);
|
| + bind(&conv_failure);
|
| + fnclex();
|
| + fldz();
|
| + fld(1);
|
| + FCmp();
|
| + setcc(below, result_reg); // 1 if negative, 0 if positive.
|
| + dec_b(result_reg); // 0 if negative, 255 if positive.
|
| + bind(&done);
|
| +}
|
| +
|
| +
|
| void MacroAssembler::ClampUint8(Register reg) {
|
| Label done;
|
| test(reg, Immediate(0xFFFFFF00));
|
| @@ -273,6 +299,7 @@ void MacroAssembler::RecordWriteArray(
|
| Register object,
|
| Register value,
|
| Register index,
|
| + SaveFPRegsMode save_fp,
|
| RememberedSetAction remembered_set_action,
|
| SmiCheck smi_check,
|
| PointersToHereCheck pointers_to_here_check_for_value) {
|
| @@ -294,8 +321,8 @@ void MacroAssembler::RecordWriteArray(
|
| lea(dst, Operand(object, index, times_half_pointer_size,
|
| FixedArray::kHeaderSize - kHeapObjectTag));
|
|
|
| - RecordWrite(object, dst, value, remembered_set_action, OMIT_SMI_CHECK,
|
| - pointers_to_here_check_for_value);
|
| + RecordWrite(object, dst, value, save_fp, remembered_set_action,
|
| + OMIT_SMI_CHECK, pointers_to_here_check_for_value);
|
|
|
| bind(&done);
|
|
|
| @@ -313,6 +340,7 @@ void MacroAssembler::RecordWriteField(
|
| int offset,
|
| Register value,
|
| Register dst,
|
| + SaveFPRegsMode save_fp,
|
| RememberedSetAction remembered_set_action,
|
| SmiCheck smi_check,
|
| PointersToHereCheck pointers_to_here_check_for_value) {
|
| @@ -338,8 +366,8 @@ void MacroAssembler::RecordWriteField(
|
| bind(&ok);
|
| }
|
|
|
| - RecordWrite(object, dst, value, remembered_set_action, OMIT_SMI_CHECK,
|
| - pointers_to_here_check_for_value);
|
| + RecordWrite(object, dst, value, save_fp, remembered_set_action,
|
| + OMIT_SMI_CHECK, pointers_to_here_check_for_value);
|
|
|
| bind(&done);
|
|
|
| @@ -356,7 +384,8 @@ void MacroAssembler::RecordWriteForMap(
|
| Register object,
|
| Handle<Map> map,
|
| Register scratch1,
|
| - Register scratch2) {
|
| + Register scratch2,
|
| + SaveFPRegsMode save_fp) {
|
| Label done;
|
|
|
| Register address = scratch1;
|
| @@ -393,7 +422,8 @@ void MacroAssembler::RecordWriteForMap(
|
| &done,
|
| Label::kNear);
|
|
|
| - RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET);
|
| + RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET,
|
| + save_fp);
|
| CallStub(&stub);
|
|
|
| bind(&done);
|
| @@ -416,6 +446,7 @@ void MacroAssembler::RecordWrite(
|
| Register object,
|
| Register address,
|
| Register value,
|
| + SaveFPRegsMode fp_mode,
|
| RememberedSetAction remembered_set_action,
|
| SmiCheck smi_check,
|
| PointersToHereCheck pointers_to_here_check_for_value) {
|
| @@ -461,8 +492,8 @@ void MacroAssembler::RecordWrite(
|
| &done,
|
| Label::kNear);
|
|
|
| - RecordWriteStub stub(isolate(), object, value, address,
|
| - remembered_set_action);
|
| + RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
|
| + fp_mode);
|
| CallStub(&stub);
|
|
|
| bind(&done);
|
| @@ -707,6 +738,53 @@ void MacroAssembler::FCmp() {
|
| }
|
|
|
|
|
| +void MacroAssembler::FXamMinusZero() {
|
| + fxam();
|
| + push(eax);
|
| + fnstsw_ax();
|
| + and_(eax, Immediate(0x4700));
|
| + // For minus zero, C3 == 1 && C1 == 1.
|
| + cmp(eax, Immediate(0x4200));
|
| + pop(eax);
|
| + fstp(0);
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::FXamSign() {
|
| + fxam();
|
| + push(eax);
|
| + fnstsw_ax();
|
| + // For negative value (including -0.0), C1 == 1.
|
| + and_(eax, Immediate(0x0200));
|
| + pop(eax);
|
| + fstp(0);
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::X87CheckIA() {
|
| + push(eax);
|
| + fnstsw_ax();
|
| + // For #IA, IE == 1 && SF == 0.
|
| + and_(eax, Immediate(0x0041));
|
| + cmp(eax, Immediate(0x0001));
|
| + pop(eax);
|
| +}
|
| +
|
| +
|
| +// rc=00B, round to nearest.
|
| +// rc=01B, round down.
|
| +// rc=10B, round up.
|
| +// rc=11B, round toward zero.
|
| +void MacroAssembler::X87SetRC(int rc) {
|
| + sub(esp, Immediate(kPointerSize));
|
| + fnstcw(MemOperand(esp, 0));
|
| + and_(MemOperand(esp, 0), Immediate(0xF3FF));
|
| + or_(MemOperand(esp, 0), Immediate(rc));
|
| + fldcw(MemOperand(esp, 0));
|
| + add(esp, Immediate(kPointerSize));
|
| +}
|
| +
|
| +
|
| void MacroAssembler::AssertNumber(Register object) {
|
| if (emit_debug_code()) {
|
| Label ok;
|
| @@ -844,8 +922,17 @@ void MacroAssembler::EnterExitFramePrologue() {
|
| }
|
|
|
|
|
| -void MacroAssembler::EnterExitFrameEpilogue(int argc) {
|
| - sub(esp, Immediate(argc * kPointerSize));
|
| +void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
|
| + // Optionally save FPU state.
|
| + if (save_doubles) {
|
| + // Store FPU state to m108byte.
|
| + int space = 108 + argc * kPointerSize;
|
| + sub(esp, Immediate(space));
|
| + const int offset = -2 * kPointerSize; // entry fp + code object.
|
| + fnsave(MemOperand(ebp, offset - 108));
|
| + } else {
|
| + sub(esp, Immediate(argc * kPointerSize));
|
| + }
|
|
|
| // Get the required frame alignment for the OS.
|
| const int kFrameAlignment = base::OS::ActivationFrameAlignment();
|
| @@ -859,7 +946,7 @@ void MacroAssembler::EnterExitFrameEpilogue(int argc) {
|
| }
|
|
|
|
|
| -void MacroAssembler::EnterExitFrame() {
|
| +void MacroAssembler::EnterExitFrame(bool save_doubles) {
|
| EnterExitFramePrologue();
|
|
|
| // Set up argc and argv in callee-saved registers.
|
| @@ -868,17 +955,23 @@ void MacroAssembler::EnterExitFrame() {
|
| lea(esi, Operand(ebp, eax, times_4, offset));
|
|
|
| // Reserve space for argc, argv and isolate.
|
| - EnterExitFrameEpilogue(3);
|
| + EnterExitFrameEpilogue(3, save_doubles);
|
| }
|
|
|
|
|
| void MacroAssembler::EnterApiExitFrame(int argc) {
|
| EnterExitFramePrologue();
|
| - EnterExitFrameEpilogue(argc);
|
| + EnterExitFrameEpilogue(argc, false);
|
| }
|
|
|
|
|
| -void MacroAssembler::LeaveExitFrame() {
|
| +void MacroAssembler::LeaveExitFrame(bool save_doubles) {
|
| + // Optionally restore FPU state.
|
| + if (save_doubles) {
|
| + const int offset = -2 * kPointerSize;
|
| + frstor(MemOperand(ebp, offset - 108));
|
| + }
|
| +
|
| // Get the return address from the stack and restore the frame pointer.
|
| mov(ecx, Operand(ebp, 1 * kPointerSize));
|
| mov(ebp, Operand(ebp, 0 * kPointerSize));
|
| @@ -1909,7 +2002,8 @@ void MacroAssembler::IndexFromHash(Register hash, Register index) {
|
|
|
|
|
| void MacroAssembler::CallRuntime(const Runtime::Function* f,
|
| - int num_arguments) {
|
| + int num_arguments,
|
| + SaveFPRegsMode save_doubles) {
|
| // If the expected number of arguments of the runtime function is
|
| // constant, we check that the actual number of arguments match the
|
| // expectation.
|
| @@ -1921,7 +2015,7 @@ void MacroAssembler::CallRuntime(const Runtime::Function* f,
|
| // smarter.
|
| Move(eax, Immediate(num_arguments));
|
| mov(ebx, Immediate(ExternalReference(f, isolate())));
|
| - CEntryStub ces(isolate(), 1);
|
| + CEntryStub ces(isolate(), 1, save_doubles);
|
| CallStub(&ces);
|
| }
|
|
|
|
|