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