Index: src/compiler/x87/instruction-selector-x87.cc |
diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/x87/instruction-selector-x87.cc |
similarity index 79% |
copy from src/compiler/ia32/instruction-selector-ia32.cc |
copy to src/compiler/x87/instruction-selector-x87.cc |
index e7ddc1ad18287b909eb05a3fbb8ced724459e865..76b339dbc986d92ba693f5d2ddb8f7486ac26f97 100644 |
--- a/src/compiler/ia32/instruction-selector-ia32.cc |
+++ b/src/compiler/x87/instruction-selector-x87.cc |
@@ -11,10 +11,10 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
-// Adds IA32-specific methods for generating operands. |
-class IA32OperandGenerator final : public OperandGenerator { |
+// Adds X87-specific methods for generating operands. |
+class X87OperandGenerator final : public OperandGenerator { |
public: |
- explicit IA32OperandGenerator(InstructionSelector* selector) |
+ explicit X87OperandGenerator(InstructionSelector* selector) |
: OperandGenerator(selector) {} |
InstructionOperand UseByteRegister(Node* node) { |
@@ -27,6 +27,10 @@ class IA32OperandGenerator final : public OperandGenerator { |
return DefineAsRegister(node); |
} |
+ InstructionOperand CreateImmediate(int imm) { |
+ return sequence()->AddImmediate(Constant(imm)); |
+ } |
+ |
bool CanBeImmediate(Node* node) { |
switch (node->opcode()) { |
case IrOpcode::kInt32Constant: |
@@ -125,50 +129,6 @@ class IA32OperandGenerator final : public OperandGenerator { |
}; |
-namespace { |
- |
-void VisitROFloat(InstructionSelector* selector, Node* node, |
- ArchOpcode opcode) { |
- IA32OperandGenerator g(selector); |
- selector->Emit(opcode, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
-} |
- |
- |
-void VisitRRFloat(InstructionSelector* selector, Node* node, |
- InstructionCode opcode) { |
- IA32OperandGenerator g(selector); |
- selector->Emit(opcode, g.DefineAsRegister(node), |
- g.UseRegister(node->InputAt(0))); |
-} |
- |
- |
-void VisitRROFloat(InstructionSelector* selector, Node* node, |
- ArchOpcode avx_opcode, ArchOpcode sse_opcode) { |
- IA32OperandGenerator g(selector); |
- InstructionOperand operand0 = g.UseRegister(node->InputAt(0)); |
- InstructionOperand operand1 = g.Use(node->InputAt(1)); |
- if (selector->IsSupported(AVX)) { |
- selector->Emit(avx_opcode, g.DefineAsRegister(node), operand0, operand1); |
- } else { |
- selector->Emit(sse_opcode, g.DefineSameAsFirst(node), operand0, operand1); |
- } |
-} |
- |
- |
-void VisitFloatUnop(InstructionSelector* selector, Node* node, Node* input, |
- ArchOpcode avx_opcode, ArchOpcode sse_opcode) { |
- IA32OperandGenerator g(selector); |
- if (selector->IsSupported(AVX)) { |
- selector->Emit(avx_opcode, g.DefineAsRegister(node), g.Use(input)); |
- } else { |
- selector->Emit(sse_opcode, g.DefineSameAsFirst(node), g.UseRegister(input)); |
- } |
-} |
- |
- |
-} // namespace |
- |
- |
void InstructionSelector::VisitLoad(Node* node) { |
MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
@@ -176,28 +136,28 @@ void InstructionSelector::VisitLoad(Node* node) { |
ArchOpcode opcode; |
switch (rep) { |
case kRepFloat32: |
- opcode = kIA32Movss; |
+ opcode = kX87Movss; |
break; |
case kRepFloat64: |
- opcode = kIA32Movsd; |
+ opcode = kX87Movsd; |
break; |
case kRepBit: // Fall through. |
case kRepWord8: |
- opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; |
+ opcode = typ == kTypeInt32 ? kX87Movsxbl : kX87Movzxbl; |
break; |
case kRepWord16: |
- opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; |
+ opcode = typ == kTypeInt32 ? kX87Movsxwl : kX87Movzxwl; |
break; |
case kRepTagged: // Fall through. |
case kRepWord32: |
- opcode = kIA32Movl; |
+ opcode = kX87Movl; |
break; |
default: |
UNREACHABLE(); |
return; |
} |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
InstructionOperand outputs[1]; |
outputs[0] = g.DefineAsRegister(node); |
InstructionOperand inputs[3]; |
@@ -210,7 +170,7 @@ void InstructionSelector::VisitLoad(Node* node) { |
void InstructionSelector::VisitStore(Node* node) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
Node* base = node->InputAt(0); |
Node* index = node->InputAt(1); |
Node* value = node->InputAt(2); |
@@ -223,12 +183,12 @@ void InstructionSelector::VisitStore(Node* node) { |
// and pass them here instead of using fixed regs |
if (g.CanBeImmediate(index)) { |
InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister()}; |
- Emit(kIA32StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx), |
+ Emit(kX87StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx), |
g.UseImmediate(index), g.UseFixed(value, ecx), arraysize(temps), |
temps); |
} else { |
InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister(edx)}; |
- Emit(kIA32StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx), |
+ Emit(kX87StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx), |
g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps), |
temps); |
} |
@@ -239,21 +199,21 @@ void InstructionSelector::VisitStore(Node* node) { |
ArchOpcode opcode; |
switch (rep) { |
case kRepFloat32: |
- opcode = kIA32Movss; |
+ opcode = kX87Movss; |
break; |
case kRepFloat64: |
- opcode = kIA32Movsd; |
+ opcode = kX87Movsd; |
break; |
case kRepBit: // Fall through. |
case kRepWord8: |
- opcode = kIA32Movb; |
+ opcode = kX87Movb; |
break; |
case kRepWord16: |
- opcode = kIA32Movw; |
+ opcode = kX87Movw; |
break; |
case kRepTagged: // Fall through. |
case kRepWord32: |
- opcode = kIA32Movl; |
+ opcode = kX87Movl; |
break; |
default: |
UNREACHABLE(); |
@@ -282,7 +242,7 @@ void InstructionSelector::VisitStore(Node* node) { |
void InstructionSelector::VisitCheckedLoad(Node* node) { |
MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
Node* const buffer = node->InputAt(0); |
Node* const offset = node->InputAt(1); |
Node* const length = node->InputAt(2); |
@@ -324,7 +284,7 @@ void InstructionSelector::VisitCheckedLoad(Node* node) { |
void InstructionSelector::VisitCheckedStore(Node* node) { |
MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
Node* const buffer = node->InputAt(0); |
Node* const offset = node->InputAt(1); |
Node* const length = node->InputAt(2); |
@@ -373,7 +333,7 @@ void InstructionSelector::VisitCheckedStore(Node* node) { |
// Shared routine for multiple binary operations. |
static void VisitBinop(InstructionSelector* selector, Node* node, |
InstructionCode opcode, FlagsContinuation* cont) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
Int32BinopMatcher m(node); |
Node* left = m.left().node(); |
Node* right = m.right().node(); |
@@ -413,7 +373,7 @@ static void VisitBinop(InstructionSelector* selector, Node* node, |
outputs[output_count++] = g.DefineSameAsFirst(node); |
if (cont->IsSet()) { |
- outputs[output_count++] = g.DefineAsByteRegister(cont->result()); |
+ outputs[output_count++] = g.DefineAsRegister(cont->result()); |
} |
DCHECK_NE(0u, input_count); |
@@ -435,22 +395,22 @@ static void VisitBinop(InstructionSelector* selector, Node* node, |
void InstructionSelector::VisitWord32And(Node* node) { |
- VisitBinop(this, node, kIA32And); |
+ VisitBinop(this, node, kX87And); |
} |
void InstructionSelector::VisitWord32Or(Node* node) { |
- VisitBinop(this, node, kIA32Or); |
+ VisitBinop(this, node, kX87Or); |
} |
void InstructionSelector::VisitWord32Xor(Node* node) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
Int32BinopMatcher m(node); |
if (m.right().Is(-1)) { |
- Emit(kIA32Not, g.DefineSameAsFirst(node), g.UseRegister(m.left().node())); |
+ Emit(kX87Not, g.DefineSameAsFirst(node), g.UseRegister(m.left().node())); |
} else { |
- VisitBinop(this, node, kIA32Xor); |
+ VisitBinop(this, node, kX87Xor); |
} |
} |
@@ -458,7 +418,7 @@ void InstructionSelector::VisitWord32Xor(Node* node) { |
// Shared routine for multiple shift operations. |
static inline void VisitShift(InstructionSelector* selector, Node* node, |
ArchOpcode opcode) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
Node* left = node->InputAt(0); |
Node* right = node->InputAt(1); |
@@ -476,7 +436,7 @@ namespace { |
void VisitMulHigh(InstructionSelector* selector, Node* node, |
ArchOpcode opcode) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
selector->Emit(opcode, g.DefineAsFixed(node, edx), |
g.UseFixed(node->InputAt(0), eax), |
g.UseUniqueRegister(node->InputAt(1))); |
@@ -484,7 +444,7 @@ void VisitMulHigh(InstructionSelector* selector, Node* node, |
void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
InstructionOperand temps[] = {g.TempRegister(edx)}; |
selector->Emit(opcode, g.DefineAsFixed(node, eax), |
g.UseFixed(node->InputAt(0), eax), |
@@ -493,7 +453,7 @@ void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
selector->Emit(opcode, g.DefineAsFixed(node, edx), |
g.UseFixed(node->InputAt(0), eax), |
g.UseUnique(node->InputAt(1))); |
@@ -501,7 +461,7 @@ void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
void EmitLea(InstructionSelector* selector, Node* result, Node* index, |
int scale, Node* base, Node* displacement) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
InstructionOperand inputs[4]; |
size_t input_count = 0; |
AddressingMode mode = g.GenerateMemoryOperandInputs( |
@@ -513,7 +473,7 @@ void EmitLea(InstructionSelector* selector, Node* result, Node* index, |
InstructionOperand outputs[1]; |
outputs[0] = g.DefineAsRegister(result); |
- InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea; |
+ InstructionCode opcode = AddressingModeField::encode(mode) | kX87Lea; |
selector->Emit(opcode, 1, outputs, input_count, inputs); |
} |
@@ -529,33 +489,33 @@ void InstructionSelector::VisitWord32Shl(Node* node) { |
EmitLea(this, node, index, m.scale(), base, NULL); |
return; |
} |
- VisitShift(this, node, kIA32Shl); |
+ VisitShift(this, node, kX87Shl); |
} |
void InstructionSelector::VisitWord32Shr(Node* node) { |
- VisitShift(this, node, kIA32Shr); |
+ VisitShift(this, node, kX87Shr); |
} |
void InstructionSelector::VisitWord32Sar(Node* node) { |
- VisitShift(this, node, kIA32Sar); |
+ VisitShift(this, node, kX87Sar); |
} |
void InstructionSelector::VisitWord32Ror(Node* node) { |
- VisitShift(this, node, kIA32Ror); |
+ VisitShift(this, node, kX87Ror); |
} |
void InstructionSelector::VisitWord32Clz(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kIA32Lzcnt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Lzcnt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitInt32Add(Node* node) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
// Try to match the Add to a lea pattern |
BaseWithIndexAndDisplacement32Matcher m(node); |
@@ -572,23 +532,23 @@ void InstructionSelector::VisitInt32Add(Node* node) { |
InstructionOperand outputs[1]; |
outputs[0] = g.DefineAsRegister(node); |
- InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea; |
+ InstructionCode opcode = AddressingModeField::encode(mode) | kX87Lea; |
Emit(opcode, 1, outputs, input_count, inputs); |
return; |
} |
// No lea pattern match, use add |
- VisitBinop(this, node, kIA32Add); |
+ VisitBinop(this, node, kX87Add); |
} |
void InstructionSelector::VisitInt32Sub(Node* node) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
Int32BinopMatcher m(node); |
if (m.left().Is(0)) { |
- Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); |
+ Emit(kX87Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); |
} else { |
- VisitBinop(this, node, kIA32Sub); |
+ VisitBinop(this, node, kX87Sub); |
} |
} |
@@ -601,212 +561,236 @@ void InstructionSelector::VisitInt32Mul(Node* node) { |
EmitLea(this, node, index, m.scale(), base, NULL); |
return; |
} |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
Node* left = node->InputAt(0); |
Node* right = node->InputAt(1); |
if (g.CanBeImmediate(right)) { |
- Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), |
+ Emit(kX87Imul, g.DefineAsRegister(node), g.Use(left), |
g.UseImmediate(right)); |
} else { |
if (g.CanBeBetterLeftOperand(right)) { |
std::swap(left, right); |
} |
- Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), |
+ Emit(kX87Imul, g.DefineSameAsFirst(node), g.UseRegister(left), |
g.Use(right)); |
} |
} |
void InstructionSelector::VisitInt32MulHigh(Node* node) { |
- VisitMulHigh(this, node, kIA32ImulHigh); |
+ VisitMulHigh(this, node, kX87ImulHigh); |
} |
void InstructionSelector::VisitUint32MulHigh(Node* node) { |
- VisitMulHigh(this, node, kIA32UmulHigh); |
+ VisitMulHigh(this, node, kX87UmulHigh); |
} |
void InstructionSelector::VisitInt32Div(Node* node) { |
- VisitDiv(this, node, kIA32Idiv); |
+ VisitDiv(this, node, kX87Idiv); |
} |
void InstructionSelector::VisitUint32Div(Node* node) { |
- VisitDiv(this, node, kIA32Udiv); |
+ VisitDiv(this, node, kX87Udiv); |
} |
void InstructionSelector::VisitInt32Mod(Node* node) { |
- VisitMod(this, node, kIA32Idiv); |
+ VisitMod(this, node, kX87Idiv); |
} |
void InstructionSelector::VisitUint32Mod(Node* node) { |
- VisitMod(this, node, kIA32Udiv); |
+ VisitMod(this, node, kX87Udiv); |
} |
void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kSSEFloat32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Float32ToFloat64, g.DefineAsFixed(node, stX_0), |
+ g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Int32ToFloat64, g.DefineAsFixed(node, stX_0), |
+ g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Uint32ToFloat64, g.DefineAsFixed(node, stX_0), |
+ g.UseRegister(node->InputAt(0))); |
} |
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Float64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Float64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kSSEFloat64ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Float64ToFloat32, g.DefineAsFixed(node, stX_0), |
+ g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitFloat32Add(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat32Add, kSSEFloat32Add); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float32Add, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Add(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat64Add, kSSEFloat64Add); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float64Add, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat32Sub(Node* node) { |
- IA32OperandGenerator g(this); |
- Float32BinopMatcher m(node); |
- if (m.left().IsMinusZero()) { |
- VisitFloatUnop(this, node, m.right().node(), kAVXFloat32Neg, |
- kSSEFloat32Neg); |
- return; |
- } |
- VisitRROFloat(this, node, kAVXFloat32Sub, kSSEFloat32Sub); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float32Sub, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Sub(Node* node) { |
- IA32OperandGenerator g(this); |
- Float64BinopMatcher m(node); |
- if (m.left().IsMinusZero()) { |
- if (m.right().IsFloat64RoundDown() && |
- CanCover(m.node(), m.right().node())) { |
- if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub && |
- CanCover(m.right().node(), m.right().InputAt(0))) { |
- Float64BinopMatcher mright0(m.right().InputAt(0)); |
- if (mright0.left().IsMinusZero()) { |
- Emit(kSSEFloat64Round | MiscField::encode(kRoundUp), |
- g.DefineAsRegister(node), g.UseRegister(mright0.right().node())); |
- return; |
- } |
- } |
- } |
- VisitFloatUnop(this, node, m.right().node(), kAVXFloat64Neg, |
- kSSEFloat64Neg); |
- return; |
- } |
- VisitRROFloat(this, node, kAVXFloat64Sub, kSSEFloat64Sub); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float64Sub, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat32Mul(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat32Mul, kSSEFloat32Mul); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float32Mul, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Mul(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat64Mul, kSSEFloat64Mul); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float64Mul, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat32Div(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat32Div, kSSEFloat32Div); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float32Div, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Div(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat64Div, kSSEFloat64Div); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float64Div, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Mod(Node* node) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
InstructionOperand temps[] = {g.TempRegister(eax)}; |
- Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), |
- g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1, |
- temps); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float64Mod, g.DefineAsFixed(node, stX_0), 1, temps)->MarkAsCall(); |
} |
void InstructionSelector::VisitFloat32Max(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat32Max, kSSEFloat32Max); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float32Max, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Max(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat64Max, kSSEFloat64Max); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float64Max, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat32Min(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat32Min, kSSEFloat32Min); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float32Min, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Min(Node* node) { |
- VisitRROFloat(this, node, kAVXFloat64Min, kSSEFloat64Min); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
+ Emit(kX87Float64Min, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat32Abs(Node* node) { |
- IA32OperandGenerator g(this); |
- VisitFloatUnop(this, node, node->InputAt(0), kAVXFloat32Abs, kSSEFloat32Abs); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87Float32Abs, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Abs(Node* node) { |
- IA32OperandGenerator g(this); |
- VisitFloatUnop(this, node, node->InputAt(0), kAVXFloat64Abs, kSSEFloat64Abs); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87Float64Abs, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat32Sqrt(Node* node) { |
- VisitROFloat(this, node, kSSEFloat32Sqrt); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87Float32Sqrt, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64Sqrt(Node* node) { |
- VisitROFloat(this, node, kSSEFloat64Sqrt); |
+ X87OperandGenerator g(this); |
+ Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ Emit(kX87Float64Sqrt, g.DefineAsFixed(node, stX_0), 0, NULL); |
} |
void InstructionSelector::VisitFloat64RoundDown(Node* node) { |
- VisitRRFloat(this, node, kSSEFloat64Round | MiscField::encode(kRoundDown)); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Float64Round | MiscField::encode(kRoundDown), |
+ g.UseFixed(node, stX_0), g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { |
- VisitRRFloat(this, node, kSSEFloat64Round | MiscField::encode(kRoundToZero)); |
+ X87OperandGenerator g(this); |
+ Emit(kX87Float64Round | MiscField::encode(kRoundToZero), |
+ g.UseFixed(node, stX_0), g.Use(node->InputAt(0))); |
} |
@@ -816,7 +800,7 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { |
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); |
FrameStateDescriptor* frame_state_descriptor = nullptr; |
@@ -837,7 +821,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { |
g.CanBeImmediate(node) |
? g.UseImmediate(node) |
: IsSupported(ATOM) ? g.UseRegister(node) : g.Use(node); |
- Emit(kIA32Push, g.NoOutput(), value); |
+ Emit(kX87Push, g.NoOutput(), value); |
} |
// Pass label of exception handler block. |
@@ -877,7 +861,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { |
void InstructionSelector::VisitTailCall(Node* node) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); |
DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
@@ -931,7 +915,7 @@ void InstructionSelector::VisitTailCall(Node* node) { |
g.CanBeImmediate(node) |
? g.UseImmediate(node) |
: IsSupported(ATOM) ? g.UseRegister(node) : g.Use(node); |
- Emit(kIA32Push, g.NoOutput(), value); |
+ Emit(kX87Push, g.NoOutput(), value); |
} |
// Select the appropriate opcode based on the call type. |
@@ -965,7 +949,7 @@ namespace { |
void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
InstructionOperand left, InstructionOperand right, |
FlagsContinuation* cont) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
if (cont->IsBranch()) { |
selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, |
g.Label(cont->true_block()), g.Label(cont->false_block())); |
@@ -981,7 +965,7 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
Node* left, Node* right, FlagsContinuation* cont, |
bool commutative) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
if (commutative && g.CanBeBetterLeftOperand(right)) { |
std::swap(left, right); |
} |
@@ -992,25 +976,41 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
// Shared routine for multiple float32 compare operations (inputs commuted). |
void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
FlagsContinuation* cont) { |
- Node* const left = node->InputAt(0); |
- Node* const right = node->InputAt(1); |
- VisitCompare(selector, kSSEFloat32Cmp, right, left, cont, false); |
+ X87OperandGenerator g(selector); |
+ selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
+ selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
+ if (cont->IsBranch()) { |
+ selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(), |
+ g.Label(cont->true_block()), g.Label(cont->false_block())); |
+ } else { |
+ DCHECK(cont->IsSet()); |
+ selector->Emit(cont->Encode(kX87Float32Cmp), |
+ g.DefineAsByteRegister(cont->result())); |
+ } |
} |
// Shared routine for multiple float64 compare operations (inputs commuted). |
void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
FlagsContinuation* cont) { |
- Node* const left = node->InputAt(0); |
- Node* const right = node->InputAt(1); |
- VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false); |
+ X87OperandGenerator g(selector); |
+ selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
+ selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
+ if (cont->IsBranch()) { |
+ selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), |
+ g.Label(cont->true_block()), g.Label(cont->false_block())); |
+ } else { |
+ DCHECK(cont->IsSet()); |
+ selector->Emit(cont->Encode(kX87Float64Cmp), |
+ g.DefineAsByteRegister(cont->result())); |
+ } |
} |
// Shared routine for multiple word compare operations. |
void VisitWordCompare(InstructionSelector* selector, Node* node, |
InstructionCode opcode, FlagsContinuation* cont) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
Node* const left = node->InputAt(0); |
Node* const right = node->InputAt(1); |
@@ -1029,7 +1029,7 @@ void VisitWordCompare(InstructionSelector* selector, Node* node, |
void VisitWordCompare(InstructionSelector* selector, Node* node, |
FlagsContinuation* cont) { |
- IA32OperandGenerator g(selector); |
+ X87OperandGenerator g(selector); |
Int32BinopMatcher m(node); |
if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
@@ -1038,7 +1038,7 @@ void VisitWordCompare(InstructionSelector* selector, Node* node, |
if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
// Compare(Load(js_stack_limit), LoadStackPointer) |
if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
- InstructionCode opcode = cont->Encode(kIA32StackCheck); |
+ InstructionCode opcode = cont->Encode(kX87StackCheck); |
if (cont->IsBranch()) { |
selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), |
g.Label(cont->false_block())); |
@@ -1049,7 +1049,7 @@ void VisitWordCompare(InstructionSelector* selector, Node* node, |
return; |
} |
} |
- VisitWordCompare(selector, node, kIA32Cmp, cont); |
+ VisitWordCompare(selector, node, kX87Cmp, cont); |
} |
@@ -1117,10 +1117,10 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
switch (node->opcode()) { |
case IrOpcode::kInt32AddWithOverflow: |
cont->OverwriteAndNegateIfEqual(kOverflow); |
- return VisitBinop(selector, node, kIA32Add, cont); |
+ return VisitBinop(selector, node, kX87Add, cont); |
case IrOpcode::kInt32SubWithOverflow: |
cont->OverwriteAndNegateIfEqual(kOverflow); |
- return VisitBinop(selector, node, kIA32Sub, cont); |
+ return VisitBinop(selector, node, kX87Sub, cont); |
default: |
break; |
} |
@@ -1130,7 +1130,7 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
case IrOpcode::kInt32Sub: |
return VisitWordCompare(selector, value, cont); |
case IrOpcode::kWord32And: |
- return VisitWordCompare(selector, value, kIA32Test, cont); |
+ return VisitWordCompare(selector, value, kX87Test, cont); |
default: |
break; |
} |
@@ -1138,8 +1138,8 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
} |
// Continuation could not be combined with a compare, emit compare against 0. |
- IA32OperandGenerator g(selector); |
- VisitCompare(selector, kIA32Cmp, g.Use(value), g.TempImmediate(0), cont); |
+ X87OperandGenerator g(selector); |
+ VisitCompare(selector, kX87Cmp, g.Use(value), g.TempImmediate(0), cont); |
} |
} // namespace |
@@ -1153,7 +1153,7 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
// Emit either ArchTableSwitch or ArchLookupSwitch. |
@@ -1168,7 +1168,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
InstructionOperand index_operand = value_operand; |
if (sw.min_value) { |
index_operand = g.TempRegister(); |
- Emit(kIA32Lea | AddressingModeField::encode(kMode_MRI), index_operand, |
+ Emit(kX87Lea | AddressingModeField::encode(kMode_MRI), index_operand, |
value_operand, g.TempImmediate(-sw.min_value)); |
} |
// Generate a table lookup. |
@@ -1217,20 +1217,20 @@ void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { |
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
FlagsContinuation cont(kOverflow, ovf); |
- return VisitBinop(this, node, kIA32Add, &cont); |
+ return VisitBinop(this, node, kX87Add, &cont); |
} |
FlagsContinuation cont; |
- VisitBinop(this, node, kIA32Add, &cont); |
+ VisitBinop(this, node, kX87Add, &cont); |
} |
void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
FlagsContinuation cont(kOverflow, ovf); |
- return VisitBinop(this, node, kIA32Sub, &cont); |
+ return VisitBinop(this, node, kX87Sub, &cont); |
} |
FlagsContinuation cont; |
- VisitBinop(this, node, kIA32Sub, &cont); |
+ VisitBinop(this, node, kX87Sub, &cont); |
} |
@@ -1271,39 +1271,34 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kSSEFloat64ExtractLowWord32, g.DefineAsRegister(node), |
+ X87OperandGenerator g(this); |
+ Emit(kX87Float64ExtractLowWord32, g.DefineAsRegister(node), |
g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) { |
- IA32OperandGenerator g(this); |
- Emit(kSSEFloat64ExtractHighWord32, g.DefineAsRegister(node), |
+ X87OperandGenerator g(this); |
+ Emit(kX87Float64ExtractHighWord32, g.DefineAsRegister(node), |
g.Use(node->InputAt(0))); |
} |
void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
Node* left = node->InputAt(0); |
Node* right = node->InputAt(1); |
- Float64Matcher mleft(left); |
- if (mleft.HasValue() && (bit_cast<uint64_t>(mleft.Value()) >> 32) == 0u) { |
- Emit(kSSEFloat64LoadLowWord32, g.DefineAsRegister(node), g.Use(right)); |
- return; |
- } |
- Emit(kSSEFloat64InsertLowWord32, g.DefineSameAsFirst(node), |
- g.UseRegister(left), g.Use(right)); |
+ Emit(kX87Float64InsertLowWord32, g.UseFixed(node, stX_0), g.UseRegister(left), |
+ g.UseRegister(right)); |
} |
void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) { |
- IA32OperandGenerator g(this); |
+ X87OperandGenerator g(this); |
Node* left = node->InputAt(0); |
Node* right = node->InputAt(1); |
- Emit(kSSEFloat64InsertHighWord32, g.DefineSameAsFirst(node), |
- g.UseRegister(left), g.Use(right)); |
+ Emit(kX87Float64InsertHighWord32, g.UseFixed(node, stX_0), |
+ g.UseRegister(left), g.UseRegister(right)); |
} |
@@ -1316,10 +1311,6 @@ InstructionSelector::SupportedMachineOperatorFlags() { |
MachineOperatorBuilder::kFloat64Max | |
MachineOperatorBuilder::kFloat64Min | |
MachineOperatorBuilder::kWord32ShiftIsSafe; |
- if (CpuFeatures::IsSupported(SSE4_1)) { |
- flags |= MachineOperatorBuilder::kFloat64RoundDown | |
- MachineOperatorBuilder::kFloat64RoundTruncate; |
- } |
return flags; |
} |