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