Don Cowan, a nationally-known North Carolina trial lawyer who reached the highest levels of his profession representing Fortune 500 companies and criminal defendants charged with capital crimes, died on Monday in Raleigh. The cause was complications from a severe stroke he suffered eight years earlier. He was 75.
Don's legal career spanned 43 years, from the jungles of Vietnam, where he served in the U.S. Army Office of Staff Judge Advocate General (JAG) Corps, to state and federal courtrooms across the United States. He was a highly sought-after lawyer, not only for his expertise across diverse areas of litigation, but also for his ability to master complex concepts of antitrust, intellectual property, and criminal law, and explain them to juries as if they were simple, straightforward, and intuitive ideas. In addition to his trial work, Don was an Adjunct Professor of Trial Practice at Duke University School of Law, and regularly taught seminars on trial practice and evidence to trial judges and lawyers. He served multiple terms on the Wake Forest University Board of Trustees and as president of the Wake Forest Law Alumni Association.
With a client list which read like a Who's Who of North Carolina business, politics, and education, Don was known for his limitless work capacity. He was also perhaps the only lawyer or judge in the state to read every decision handed down by the North Carolina Supreme Court and Court of Appeals during his career. For his law practice, no case was too complex or too challenging for Don to take on. His former law partner, Doug Ey, theorized it this way: "Don long ago saw the scariest thing he will ever see: After jumping out of helicopters at night over the Mekong Delta with the 82nd Airborne, there is no judge, jury, or case that will ever intimidate him."
Winning prestigious civil cases may have been what built Don's legal career and reputation, but it was his work on criminal cases where he paid it back. In 1987, a Superior Court judge asked Don to represent a Martin County man accused of first-degree murder. For the next 19 years, Don spent thousands of hours knocking on doors, interviewing long-forgotten witnesses, and handling the capital murder trial and appeals. Don's final legal challenge to his client's death sentence revealed flaws in the state's lethal injection drug cocktail which led to unusually painful and cruel deaths, and was the subject of a New York Times article on death penalty challenges across the country. At the conclusion of nearly two decades of complex legal work on the case, all without taking a fee, Don told a reporter, "There are a lot of lawyers who have done this more than I have. Nothing I did was unusual."
He might not have viewed himself that way, but his colleagues did. Throughout his career, Don became known as a standard for respect and collegiality. Whether they were on the same or different sides of a case, trial lawyers used Don's example as the right way to practice law in an often-contentious profession among adversaries with the livelihoods of their businesses, or themselves, at stake. Don passed his fundamentals of professionalism on to a generation of lawyers who followed him.
Suzanne Reynolds, who worked with Don early in her career, and later served as Dean of the Wake Forest University School of Law, was one of those lawyers. "One of the greatest blessings of my professional life has been having Don Cowan as a mentor," Reynolds said. "Don's heart, however, surpasses his analytical prowess. He always saved time to champion issues that favored people whom the law had forgotten or excluded. I am a better lawyer and person because of Don Cowan."
Don was known for never asking one of his associates to do something he wasn't willing to do himself. He once walked into a young lawyer's office with two files under his arm. "Pick one," he said. When the lawyer did, Don told him, "We're walking to the courthouse to pick two juries. You take that one, and I'll take this one." When the trials were over, the young lawyer asked Don why he didn't keep the better case for himself. "I don't give away losers," he said.
Don was a Fellow, Regent, and Secretary of the American College of Trial Lawyers, and a former member of the American Bar Association House of Delegates. He was a past president of the North Carolina Bar Association, and Legal Services of North Carolina (now Legal Aid of North Carolina). During the course of his career, Don was consistently recognized as one of the top trial lawyers in the state, as well as the nation. In 2009, the North Carolina Bar Association selected Don as the second recipient of the Advocate's Award, which was created to recognize lawyers with the highest degree of legal skill, ethical standards, and service to the legal community. Five years later, Don received the John J. Parker award, the highest honor given by the North Carolina Bar Association.
James Donald Cowan, Jr., was born in Raleigh on Nov. 14, 1943. Don's father worked for the North Carolina Department of Labor. His mother, as Don described her, provided the perfect nurturing balance to his father's discipline. Don attended Broughton High School, where he met his future wife, Sarah Langston. He graduated from Wake Forest University in 1965, and received his law degree from Wake Forest University School of Law in 1968, where he was Editor-in-Chief of the Law Review.
Don began his legal career in the U.S. Army JAG Corps, serving as a Captain in the 1st Infantry Division (the "Big Red One") in Lai Khe, Republic of South Vietnam, and the 1st Armored Division in Nuremberg, Germany. A military and legal colleague noted that Don's military service and the honors he received, but never discussed, "speak directly to the quiet strength and courage of this man."
After returning to North Carolina, Don began practicing civil litigation in 1973 with what was then Smith, Moore, Smith, Schell & Hunter. He remained with the Smith, Moore Law Firm for more than three decades until 2008, when he joined the Law Firm of Ellis & Winters, where he practiced until he suffered a disabling stroke on May 28, 2011, just two weeks after he made what would be his final argument before the United States Court of Appeals for the Fourth Circuit.
Perhaps the only things that slowed Don down during his career were his family and his love of music. He was a constant (and vocal) presence on the sidelines at his children's soccer games through high school, first as a coach and then as an encouraging father. At an early age, he introduced them to the music of Eric Clapton, The Rolling Stones, Fleetwood Mac, and perhaps his favorite band, The Eagles, whose country-tinged philosophical anthem "Take It Easy" became part of the soundtrack of their early lives. Don's children in turn gave him the Police, Van Halen, and Guns 'n Roses, much to the surprise of young lawyers in his firm who may have ridden with Don to depositions at any point in the late 1980's or '90's, hoping to discuss the finer points of their research on the economic loss rule, or the completed and accepted doctrine, only to be serenaded by W. Axl Rose welcoming them to the jungle.
Don's career continued at a breakneck pace until Dec. 5, 2006, and the birth of his first grandchild. The trials, appeals, and seminars didn't stop, but their pace slowed, and were scheduled around trips to Potomac, Maryland, and New York City to visit his three grandchildren. They saw "Poppy", as he was known to them, as the loving, silly grandfather who always made them laugh, and never tired of singing the Lion King's "Hakuna Matata" at the top of his lungs, again and again. But in those moments, Don's family saw yet another side of the man they had known their whole lives. Perhaps it was there all along, but now they could see Don's spirit in the lyrics he sang with his grandchildren: "It means no worries for the rest of your days."
Throughout his journey from the halls of Broughton High School to Wake Forest University, Germany, and back to North Carolina, Don's wife and life-partner, Sarah, was his constant companion, as well as his source of energy and inspiration. She was a sounding board and voice of reason throughout his legal career, and devoted caretaker when Don could no longer care for himself. She made his life richer and more complete than any one man could ever dream. For Don, she was the "girl my lord in a flatbed Ford slowing down to take a look at me."
Don is survived by his wife, Sarah Langston Cowan, his children and their spouses, Coleman Cowan (Angela Abernethy Cowan) and Duren Cowan Banks (Brett Banks), his three grandchildren, Caitlin James Banks, John Mason Banks, and Julian Hayes Cowan, and his sister, Rebecca Edwards.
Visitation will be held Friday, April 12th from 6 to 8 p.m. at 3617 Alamance Dr. in Raleigh.
A memorial service will be held the following day, Saturday, April 13th at 11 a.m. at Christ Church, 120 E. Edenton St. in Raleigh.
The family suggests memorials to Legal Aid of North Carolina, P.O. Box. 28741, Raleigh, NC 27611.
"Sarah, Mary Nan and I send our condolences. We have lost a..."
"Don was a great man and a heck of a trial lawyer. It was a..."


text:
namespace v8 {
namespace internal {
namespace compiler {

// Adds X87-specific methods for generating operands.
class X87OperandGenerator final : public OperandGenerator {
 public:
  explicit X87OperandGenerator(InstructionSelector* selector)
      : OperandGenerator(selector) {}

  InstructionOperand UseByteRegister(Node* node) {
    // TODO(titzer): encode byte register use constraints.
    return UseFixed(node, edx);
  }

  InstructionOperand DefineAsByteRegister(Node* node) {
    // TODO(titzer): encode byte register def constraints.
    return DefineAsRegister(node);
  }

  bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input,
                          int effect_level) {
    if (input->opcode() != IrOpcode::kLoad ||
        !selector()->CanCover(node, input)) {
      return false;
    }
    if (effect_level != selector()->GetEffectLevel(input)) {
      return false;
    }
    MachineRepresentation rep =
        LoadRepresentationOf(input->op()).representation();
    switch (opcode) {
      case kX87Cmp:
      case kX87Test:
        return rep == MachineRepresentation::kWord32 ||
               rep == MachineRepresentation::kTagged;
      case kX87Cmp16:
      case kX87Test16:
        return rep == MachineRepresentation::kWord16;
      case kX87Cmp8:
      case kX87Test8:
        return rep == MachineRepresentation::kWord8;
      default:
        break;
    }
    return false;
  }

  InstructionOperand CreateImmediate(int imm) {
    return sequence()->AddImmediate(Constant(imm));
  }

  bool CanBeImmediate(Node* node) {
    switch (node->opcode()) {
      case IrOpcode::kInt32Constant:
      case IrOpcode::kNumberConstant:
      case IrOpcode::kExternalConstant:
      case IrOpcode::kRelocatableInt32Constant:
      case IrOpcode::kRelocatableInt64Constant:
        return true;
      case IrOpcode::kHeapConstant: {
// TODO(bmeurer): We must not dereference handles concurrently. If we
// really have to this here, then we need to find a way to put this
// information on the HeapConstant node already.
#if 0
        // Constants in new space cannot be used as immediates in V8 because
        // the GC does not scan code objects when collecting the new generation.
        Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
        Isolate* isolate = value->GetIsolate();
        return !isolate->heap()->InNewSpace(*value);
#endif
      }
      default:
        return false;
    }
  }

  AddressingMode GenerateMemoryOperandInputs(Node* index, int scale, Node* base,
                                             Node* displacement_node,
                                             DisplacementMode displacement_mode,
                                             InstructionOperand inputs[],
                                             size_t* input_count) {
    AddressingMode mode = kMode_MRI;
    int32_t displacement = (displacement_node == nullptr)
                               ? 0
                               : OpParameter<int32_t>(displacement_node);
    if (displacement_mode == kNegativeDisplacement) {
      displacement = -displacement;
    }
    if (base != nullptr) {
      if (base->opcode() == IrOpcode::kInt32Constant) {
        displacement += OpParameter<int32_t>(base);
        base = nullptr;
      }
    }
    if (base != nullptr) {
      inputs[(*input_count)++] = UseRegister(base);
      if (index != nullptr) {
        DCHECK(scale >= 0 && scale <= 3);
        inputs[(*input_count)++] = UseRegister(index);
        if (displacement != 0) {
          inputs[(*input_count)++] = TempImmediate(displacement);
          static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I,
                                                       kMode_MR4I, kMode_MR8I};
          mode = kMRnI_modes[scale];
        } else {
          static const AddressingMode kMRn_modes[] = {kMode_MR1, kMode_MR2,
                                                      kMode_MR4, kMode_MR8};
          mode = kMRn_modes[scale];
        }
      } else {
        if (displacement == 0) {
          mode = kMode_MR;
        } else {
          inputs[(*input_count)++] = TempImmediate(displacement);
          mode = kMode_MRI;
        }
      }
    } else {
      DCHECK(scale >= 0 && scale <= 3);
      if (index != nullptr) {
        inputs[(*input_count)++] = UseRegister(index);
        if (displacement != 0) {
          inputs[(*input_count)++] = TempImmediate(displacement);
          static const AddressingMode kMnI_modes[] = {kMode_MRI, kMode_M2I,
                                                      kMode_M4I, kMode_M8I};
          mode = kMnI_modes[scale];
        } else {
          static const AddressingMode kMn_modes[] = {kMode_MR, kMode_M2,
                                                     kMode_M4, kMode_M8};
          mode = kMn_modes[scale];
        }
      } else {
        inputs[(*input_count)++] = TempImmediate(displacement);
        return kMode_MI;
      }
    }
    return mode;
  }

  AddressingMode GetEffectiveAddressMemoryOperand(Node* node,
                                                  InstructionOperand inputs[],
                                                  size_t* input_count) {
    BaseWithIndexAndDisplacement32Matcher m(node, AddressOption::kAllowAll);
    DCHECK(m.matches());
    if ((m.displacement() == nullptr || CanBeImmediate(m.displacement()))) {
      return GenerateMemoryOperandInputs(
          m.index(), m.scale(), m.base(), m.displacement(),
          m.displacement_mode(), inputs, input_count);
    } else {
      inputs[(*input_count)++] = UseRegister(node->InputAt(0));
      inputs[(*input_count)++] = UseRegister(node->InputAt(1));
      return kMode_MR1;
    }
  }

  bool CanBeBetterLeftOperand(Node* node) const {
    return !selector()->IsLive(node);
  }
};

void InstructionSelector::VisitLoad(Node* node) {
  LoadRepresentation load_rep = LoadRepresentationOf(node->op());

  ArchOpcode opcode = kArchNop;
  switch (load_rep.representation()) {
    case MachineRepresentation::kFloat32:
      opcode = kX87Movss;
      break;
    case MachineRepresentation::kFloat64:
      opcode = kX87Movsd;
      break;
    case MachineRepresentation::kBit:  // Fall through.
    case MachineRepresentation::kWord8:
      opcode = load_rep.IsSigned() ? kX87Movsxbl : kX87Movzxbl;
      break;
    case MachineRepresentation::kWord16:
      opcode = load_rep.IsSigned() ? kX87Movsxwl : kX87Movzxwl;
      break;
    case MachineRepresentation::kTaggedSigned:   // Fall through.
    case MachineRepresentation::kTaggedPointer:  // Fall through.
    case MachineRepresentation::kTagged:         // Fall through.
    case MachineRepresentation::kWord32:
      opcode = kX87Movl;
      break;
    case MachineRepresentation::kWord64:   // Fall through.
    case MachineRepresentation::kSimd128:  // Fall through.
    case MachineRepresentation::kNone:
      UNREACHABLE();
      return;
  }

  X87OperandGenerator g(this);
  InstructionOperand outputs[1];
  outputs[0] = g.DefineAsRegister(node);
  InstructionOperand inputs[3];
  size_t input_count = 0;
  AddressingMode mode =
      g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
  InstructionCode code = opcode | AddressingModeField::encode(mode);
  Emit(code, 1, outputs, input_count, inputs);
}

void InstructionSelector::VisitProtectedLoad(Node* node) {
  // TODO(eholk)
  UNIMPLEMENTED();
}

void InstructionSelector::VisitStore(Node* node) {
  X87OperandGenerator g(this);
  Node* base = node->InputAt(0);
  Node* index = node->InputAt(1);
  Node* value = node->InputAt(2);

  StoreRepresentation store_rep = StoreRepresentationOf(node->op());
  WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind();
  MachineRepresentation rep = store_rep.representation();

  if (write_barrier_kind != kNoWriteBarrier) {
    DCHECK(CanBeTaggedPointer(rep));
    AddressingMode addressing_mode;
    InstructionOperand inputs[3];
    size_t input_count = 0;
    inputs[input_count++] = g.UseUniqueRegister(base);
    if (g.CanBeImmediate(index)) {
      inputs[input_count++] = g.UseImmediate(index);
      addressing_mode = kMode_MRI;
    } else {
      inputs[input_count++] = g.UseUniqueRegister(index);
      addressing_mode = kMode_MR1;
    }
    inputs[input_count++] = g.UseUniqueRegister(value);
    RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny;
    switch (write_barrier_kind) {
      case kNoWriteBarrier:
        UNREACHABLE();
        break;
      case kMapWriteBarrier:
        record_write_mode = RecordWriteMode::kValueIsMap;
        break;
      case kPointerWriteBarrier:
        record_write_mode = RecordWriteMode::kValueIsPointer;
        break;
      case kFullWriteBarrier:
        record_write_mode = RecordWriteMode::kValueIsAny;
        break;
    }
    InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
    size_t const temp_count = arraysize(temps);
    InstructionCode code = kArchStoreWithWriteBarrier;
    code |= AddressingModeField::encode(addressing_mode);
    code |= MiscField::encode(static_cast<int>(record_write_mode));
    Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
  } else {
    ArchOpcode opcode = kArchNop;
    switch (rep) {
      case MachineRepresentation::kFloat32:
        opcode = kX87Movss;
        break;
      case MachineRepresentation::kFloat64:
        opcode = kX87Movsd;
        break;
      case MachineRepresentation::kBit:  // Fall through.
      case MachineRepresentation::kWord8:
        opcode = kX87Movb;
        break;
      case MachineRepresentation::kWord16:
        opcode = kX87Movw;
        break;
      case MachineRepresentation::kTaggedSigned:   // Fall through.
      case MachineRepresentation::kTaggedPointer:  // Fall through.
      case MachineRepresentation::kTagged:         // Fall through.
      case MachineRepresentation::kWord32:
        opcode = kX87Movl;
        break;
      case MachineRepresentation::kWord64:   // Fall through.
      case MachineRepresentation::kSimd128:  // Fall through.
      case MachineRepresentation::kNone:
        UNREACHABLE();
        return;
    }

    InstructionOperand val;
    if (g.CanBeImmediate(value)) {
      val = g.UseImmediate(value);
    } else if (rep == MachineRepresentation::kWord8 ||
               rep == MachineRepresentation::kBit) {
      val = g.UseByteRegister(value);
    } else {
      val = g.UseRegister(value);
    }

    InstructionOperand inputs[4];
    size_t input_count = 0;
    AddressingMode addressing_mode =
        g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
    InstructionCode code =
        opcode | AddressingModeField::encode(addressing_mode);
    inputs[input_count++] = val;
    Emit(code, 0, static_cast<InstructionOperand*>(nullptr), input_count,
         inputs);
  }
}

void InstructionSelector::VisitProtectedStore(Node* node) {
  // TODO(eholk)
  UNIMPLEMENTED();
}

// Architecture supports unaligned access, therefore VisitLoad is used instead
void InstructionSelector::VisitUnalignedLoad(Node* node) { UNREACHABLE(); }

// Architecture supports unaligned access, therefore VisitStore is used instead
void InstructionSelector::VisitUnalignedStore(Node* node) { UNREACHABLE(); }

void InstructionSelector::VisitCheckedLoad(Node* node) {
  CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op());
  X87OperandGenerator g(this);
  Node* const buffer = node->InputAt(0);
  Node* const offset = node->InputAt(1);
  Node* const length = node->InputAt(2);
  ArchOpcode opcode = kArchNop;
  switch (load_rep.representation()) {
    case MachineRepresentation::kWord8:
      opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8;
      break;
    case MachineRepresentation::kWord16:
      opcode = load_rep.IsSigned() ? kCheckedLoadInt16 : kCheckedLoadUint16;
      break;
    case MachineRepresentation::kWord32:
      opcode = kCheckedLoadWord32;
      break;
    case MachineRepresentation::kFloat32:
      opcode = kCheckedLoadFloat32;
      break;
    case MachineRepresentation::kFloat64:
      opcode = kCheckedLoadFloat64;
      break;
    case MachineRepresentation::kBit:            // Fall through.
    case MachineRepresentation::kTaggedSigned:   // Fall through.
    case MachineRepresentation::kTaggedPointer:  // Fall through.
    case MachineRepresentation::kTagged:         // Fall through.
    case MachineRepresentation::kWord64:         // Fall through.
    case MachineRepresentation::kSimd128:        // Fall through.
    case MachineRepresentation::kNone:
      UNREACHABLE();
      return;
  }
  InstructionOperand offset_operand = g.UseRegister(offset);
  InstructionOperand length_operand =
      g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
  if (g.CanBeImmediate(buffer)) {
    Emit(opcode | AddressingModeField::encode(kMode_MRI),
         g.DefineAsRegister(node), offset_operand, length_operand,
         offset_operand, g.UseImmediate(buffer));
  } else {
    Emit(opcode | AddressingModeField::encode(kMode_MR1),
         g.DefineAsRegister(node), offset_operand, length_operand,
         g.UseRegister(buffer), offset_operand);
  }
}

void InstructionSelector::VisitCheckedStore(Node* node) {
  MachineRepresentation rep = CheckedStoreRepresentationOf(node->op());
  X87OperandGenerator g(this);
  Node* const buffer = node->InputAt(0);
  Node* const offset = node->InputAt(1);
  Node* const length = node->InputAt(2);
  Node* const value = node->InputAt(3);
  ArchOpcode opcode = kArchNop;
  switch (rep) {
    case MachineRepresentation::kWord8:
      opcode = kCheckedStoreWord8;
      break;
    case MachineRepresentation::kWord16:
      opcode = kCheckedStoreWord16;
      break;
    case MachineRepresentation::kWord32:
      opcode = kCheckedStoreWord32;
      break;
    case MachineRepresentation::kFloat32:
      opcode = kCheckedStoreFloat32;
      break;
    case MachineRepresentation::kFloat64:
      opcode = kCheckedStoreFloat64;
      break;
    case MachineRepresentation::kBit:            // Fall through.
    case MachineRepresentation::kTaggedSigned:   // Fall through.
    case MachineRepresentation::kTaggedPointer:  // Fall through.
    case MachineRepresentation::kTagged:         // Fall through.
    case MachineRepresentation::kWord64:         // Fall through.
    case MachineRepresentation::kSimd128:        // Fall through.
    case MachineRepresentation::kNone:
      UNREACHABLE();
      return;
  }
  InstructionOperand value_operand =
      g.CanBeImmediate(value) ? g.UseImmediate(value)
                              : ((rep == MachineRepresentation::kWord8 ||
                                  rep == MachineRepresentation::kBit)
                                     ? g.UseByteRegister(value)
                                     : g.UseRegister(value));
  InstructionOperand offset_operand = g.UseRegister(offset);
  InstructionOperand length_operand =
      g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
  if (g.CanBeImmediate(buffer)) {
    Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
         offset_operand, length_operand, value_operand, offset_operand,
         g.UseImmediate(buffer));
  } else {
    Emit(opcode | AddressingModeField::encode(kMode_MR1), g.NoOutput(),
         offset_operand, length_operand, value_operand, g.UseRegister(buffer),
         offset_operand);
  }
}

namespace {

// Shared routine for multiple binary operations.
void VisitBinop(InstructionSelector* selector, Node* node,
                InstructionCode opcode, FlagsContinuation* cont) {
  X87OperandGenerator g(selector);
  Int32BinopMatcher m(node);
  Node* left = m.left().node();
  Node* right = m.right().node();
  InstructionOperand inputs[4];
  size_t input_count = 0;
  InstructionOperand outputs[2];
  size_t output_count = 0;

  // TODO(turbofan): match complex addressing modes.
  if (left == right) {
    // If both inputs refer to the same operand, enforce allocating a register
    // for both of them to ensure that we don't end up generating code like
    // this:
    //
    //   mov eax, [ebp-0x10]
    //   add eax, [ebp-0x10]
    //   jo label
    InstructionOperand const input = g.UseRegister(left);
    inputs[input_count++] = input;
    inputs[input_count++] = input;
  } else if (g.CanBeImmediate(right)) {
    inputs[input_count++] = g.UseRegister(left);
    inputs[input_count++] = g.UseImmediate(right);
  } else {
    if (node->op()->HasProperty(Operator::kCommutative) &&
        g.CanBeBetterLeftOperand(right)) {
      std::swap(left, right);
    }
    inputs[input_count++] = g.UseRegister(left);
    inputs[input_count++] = g.Use(right);
  }

  if (cont->IsBranch()) {
    inputs[input_count++] = g.Label(cont->true_block());
    inputs[input_count++] = g.Label(cont->false_block());
  }

  outputs[output_count++] = g.DefineSameAsFirst(node);
  if (cont->IsSet()) {
    outputs[output_count++] = g.DefineAsRegister(cont->result());
  }

  DCHECK_NE(0u, input_count);
  DCHECK_NE(0u, output_count);
  DCHECK_GE(arraysize(inputs), input_count);
  DCHECK_GE(arraysize(outputs), output_count);

  opcode = cont->Encode(opcode);
  if (cont->IsDeoptimize()) {
    selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
                             cont->reason(), cont->frame_state());
  } else {
    selector->Emit(opcode, output_count, outputs, input_count, inputs);
  }
}

// Shared routine for multiple binary operations.
void VisitBinop(InstructionSelector* selector, Node* node,
                InstructionCode opcode) {
  FlagsContinuation cont;
  VisitBinop(selector, node, opcode, &cont);
}

}  // namespace

void InstructionSelector::VisitWord32And(Node* node) {
  VisitBinop(this, node, kX87And);
}

void InstructionSelector::VisitWord32Or(Node* node) {
  VisitBinop(this, node, kX87Or);
}

void InstructionSelector::VisitWord32Xor(Node* node) {
  X87OperandGenerator g(this);
  Int32BinopMatcher m(node);
  if (m.right().Is(-1)) {
    Emit(kX87Not, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()));
  } else {
    VisitBinop(this, node, kX87Xor);
  }
}

// Shared routine for multiple shift operations.
static inline void VisitShift(InstructionSelector* selector, Node* node,
                              ArchOpcode opcode) {
  X87OperandGenerator g(selector);
  Node* left = node->InputAt(0);
  Node* right = node->InputAt(1);

  if (g.CanBeImmediate(right)) {
    selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
                   g.UseImmediate(right));
  } else {
    selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
                   g.UseFixed(right, ecx));
  }
}

namespace {

void VisitMulHigh(InstructionSelector* selector, Node* node,
                  ArchOpcode opcode) {
  X87OperandGenerator g(selector);
  InstructionOperand temps[] = {g.TempRegister(eax)};
  selector->Emit(
      opcode, g.DefineAsFixed(node, edx), g.UseFixed(node->InputAt(0), eax),
      g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps);
}

void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
  X87OperandGenerator g(selector);
  InstructionOperand temps[] = {g.TempRegister(edx)};
  selector->Emit(opcode, g.DefineAsFixed(node, eax),
                 g.UseFixed(node->InputAt(0), eax),
                 g.UseUnique(node->InputAt(1)), arraysize(temps), temps);
}

void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
  X87OperandGenerator g(selector);
  InstructionOperand temps[] = {g.TempRegister(eax)};
  selector->Emit(opcode, g.DefineAsFixed(node, edx),
                 g.UseFixed(node->InputAt(0), eax),
                 g.UseUnique(node->InputAt(1)), arraysize(temps), temps);
}

void EmitLea(InstructionSelector* selector, Node* result, Node* index,
             int scale, Node* base, Node* displacement,
             DisplacementMode displacement_mode) {
  X87OperandGenerator g(selector);
  InstructionOperand inputs[4];
  size_t input_count = 0;
  AddressingMode mode =
      g.GenerateMemoryOperandInputs(index, scale, base, displacement,
                                    displacement_mode, inputs, &input_count);

  DCHECK_NE(0u, input_count);
  DCHECK_GE(arraysize(inputs), input_count);

  InstructionOperand outputs[1];
  outputs[0] = g.DefineAsRegister(result);

  InstructionCode opcode = AddressingModeField::encode(mode) | kX87Lea;

  selector->Emit(opcode, 1, outputs, input_count, inputs);
}

}  // namespace

void InstructionSelector::VisitWord32Shl(Node* node) {
  Int32ScaleMatcher m(node, true);
  if (m.matches()) {
    Node* index = node->InputAt(0);
    Node* base = m.power_of_two_plus_one() ? index : nullptr;
    EmitLea(this, node, index, m.scale(), base, nullptr, kPositiveDisplacement);
    return;
  }
  VisitShift(this, node, kX87Shl);
}

void InstructionSelector::VisitWord32Shr(Node* node) {
  VisitShift(this, node, kX87Shr);
}

void InstructionSelector::VisitWord32Sar(Node* node) {
  VisitShift(this, node, kX87Sar);
}

void InstructionSelector::VisitInt32PairAdd(Node* node) {
  X87OperandGenerator g(this);

  Node* projection1 = NodeProperties::FindProjection(node, 1);
  if (projection1) {
    // We use UseUniqueRegister here to avoid register sharing with the temp
    // register.
    InstructionOperand inputs[] = {
        g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
        g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};

    InstructionOperand outputs[] = {g.DefineSameAsFirst(node),
                                    g.DefineAsRegister(projection1)};

    InstructionOperand temps[] = {g.TempRegister()};

    Emit(kX87AddPair, 2, outputs, 4, inputs, 1, temps);
  } else {
    // The high word of the result is not used, so we emit the standard 32 bit
    // instruction.
    Emit(kX87Add, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
         g.Use(node->InputAt(2)));
  }
}

void InstructionSelector::VisitInt32PairSub(Node* node) {
  X87OperandGenerator g(this);

  Node* projection1 = NodeProperties::FindProjection(node, 1);
  if (projection1) {
    // We use UseUniqueRegister here to avoid register sharing with the temp
    // register.
    InstructionOperand inputs[] = {
        g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
        g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};

    InstructionOperand outputs[] = {g.DefineSameAsFirst(node),
                                    g.DefineAsRegister(projection1)};

    InstructionOperand temps[] = {g.TempRegister()};

    Emit(kX87SubPair, 2, outputs, 4, inputs, 1, temps);
  } else {
    // The high word of the result is not used, so we emit the standard 32 bit
    // instruction.
    Emit(kX87Sub, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
         g.Use(node->InputAt(2)));
  }
}

void InstructionSelector::VisitInt32PairMul(Node* node) {
  X87OperandGenerator g(this);

  Node* projection1 = NodeProperties::FindProjection(node, 1);
  if (projection1) {
    // InputAt(3) explicitly shares ecx with OutputRegister(1) to save one
    // register and one mov instruction.
    InstructionOperand inputs[] = {g.UseUnique(node->InputAt(0)),
                                   g.UseUnique(node->InputAt(1)),
                                   g.UseUniqueRegister(node->InputAt(2)),
                                   g.UseFixed(node->InputAt(3), ecx)};

    InstructionOperand outputs[] = {
        g.DefineAsFixed(node, eax),
        g.DefineAsFixed(NodeProperties::FindProjection(node, 1), ecx)};

    InstructionOperand temps[] = {g.TempRegister(edx)};

    Emit(kX87MulPair, 2, outputs, 4, inputs, 1, temps);
  } else {
    // The high word of the result is not used, so we emit the standard 32 bit
    // instruction.
    Emit(kX87Imul, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
         g.Use(node->InputAt(2)));
  }
}

void VisitWord32PairShift(InstructionSelector* selector, InstructionCode opcode,
                          Node* node) {
  X87OperandGenerator g(selector);

  Node* shift = node->InputAt(2);
  InstructionOperand shift_operand;
  if (g.CanBeImmediate(shift)) {
    shift_operand = g.UseImmediate(shift);
  } else {
    shift_operand = g.UseFixed(shift, ecx);
  }
  InstructionOperand inputs[] = {g.UseFixed(node->InputAt(0), eax),
                                 g.UseFixed(node->InputAt(1), edx),
                                 shift_operand};

  InstructionOperand outputs[2];
  InstructionOperand temps[1];
  int32_t output_count = 0;
  int32_t temp_count = 0;
  outputs[output_count++] = g.DefineAsFixed(node, eax);
  Node* projection1 = NodeProperties::FindProjection(node, 1);
  if (projection1) {
    outputs[output_count++] = g.DefineAsFixed(projection1, edx);
  } else {
    temps[temp_count++] = g.TempRegister(edx);
  }

  selector->Emit(opcode, output_count, outputs, 3, inputs, temp_count, temps);
}

void InstructionSelector::VisitWord32PairShl(Node* node) {
  VisitWord32PairShift(this, kX87ShlPair, node);
}

void InstructionSelector::VisitWord32PairShr(Node* node) {
  VisitWord32PairShift(this, kX87ShrPair, node);
}

void InstructionSelector::VisitWord32PairSar(Node* node) {
  VisitWord32PairShift(this, kX87SarPair, node);
}

void InstructionSelector::VisitWord32Ror(Node* node) {
  VisitShift(this, node, kX87Ror);
}

void InstructionSelector::VisitWord32Clz(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Lzcnt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }

void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); }

void InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); }

void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }

void InstructionSelector::VisitWord32Popcnt(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Popcnt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitInt32Add(Node* node) {
  X87OperandGenerator g(this);

  // Try to match the Add to a lea pattern
  BaseWithIndexAndDisplacement32Matcher m(node);
  if (m.matches() &&
      (m.displacement() == nullptr || g.CanBeImmediate(m.displacement()))) {
    InstructionOperand inputs[4];
    size_t input_count = 0;
    AddressingMode mode = g.GenerateMemoryOperandInputs(
        m.index(), m.scale(), m.base(), m.displacement(), m.displacement_mode(),
        inputs, &input_count);

    DCHECK_NE(0u, input_count);
    DCHECK_GE(arraysize(inputs), input_count);

    InstructionOperand outputs[1];
    outputs[0] = g.DefineAsRegister(node);

    InstructionCode opcode = AddressingModeField::encode(mode) | kX87Lea;
    Emit(opcode, 1, outputs, input_count, inputs);
    return;
  }

  // No lea pattern match, use add
  VisitBinop(this, node, kX87Add);
}

void InstructionSelector::VisitInt32Sub(Node* node) {
  X87OperandGenerator g(this);
  Int32BinopMatcher m(node);
  if (m.left().Is(0)) {
    Emit(kX87Neg, g.DefineSameAsFirst(node), g.Use(m.right().node()));
  } else {
    VisitBinop(this, node, kX87Sub);
  }
}

void InstructionSelector::VisitInt32Mul(Node* node) {
  Int32ScaleMatcher m(node, true);
  if (m.matches()) {
    Node* index = node->InputAt(0);
    Node* base = m.power_of_two_plus_one() ? index : nullptr;
    EmitLea(this, node, index, m.scale(), base, nullptr, kPositiveDisplacement);
    return;
  }
  X87OperandGenerator g(this);
  Node* left = node->InputAt(0);
  Node* right = node->InputAt(1);
  if (g.CanBeImmediate(right)) {
    Emit(kX87Imul, g.DefineAsRegister(node), g.Use(left),
         g.UseImmediate(right));
  } else {
    if (g.CanBeBetterLeftOperand(right)) {
      std::swap(left, right);
    }
    Emit(kX87Imul, g.DefineSameAsFirst(node), g.UseRegister(left),
         g.Use(right));
  }
}

void InstructionSelector::VisitInt32MulHigh(Node* node) {
  VisitMulHigh(this, node, kX87ImulHigh);
}

void InstructionSelector::VisitUint32MulHigh(Node* node) {
  VisitMulHigh(this, node, kX87UmulHigh);
}

void InstructionSelector::VisitInt32Div(Node* node) {
  VisitDiv(this, node, kX87Idiv);
}

void InstructionSelector::VisitUint32Div(Node* node) {
  VisitDiv(this, node, kX87Udiv);
}

void InstructionSelector::VisitInt32Mod(Node* node) {
  VisitMod(this, node, kX87Idiv);
}

void InstructionSelector::VisitUint32Mod(Node* node) {
  VisitMod(this, node, kX87Udiv);
}

void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float32ToFloat64, g.DefineAsFixed(node, stX_0),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Int32ToFloat32, g.DefineAsFixed(node, stX_0),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Uint32ToFloat32, g.DefineAsFixed(node, stX_0),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Int32ToFloat64, g.DefineAsFixed(node, stX_0),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Uint32ToFloat64, g.DefineAsFixed(node, stX_0),
       g.UseRegister(node->InputAt(0)));
}

void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float32ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitTruncateFloat32ToUint32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float32ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitTruncateFloat64ToUint32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64ToFloat32, g.DefineAsFixed(node, stX_0),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87BitcastFI, g.DefineAsRegister(node), 0, nullptr);
}

void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87BitcastIF, g.DefineAsFixed(node, stX_0), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat32Add(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat64Add(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat32Sub(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat64Sub(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat32Mul(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat64Mul(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat32Div(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat64Div(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat64Mod(Node* node) {
  X87OperandGenerator g(this);
  InstructionOperand temps[] = {g.TempRegister(eax)};
  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) {
  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, nullptr);
}

void InstructionSelector::VisitFloat64Max(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat32Min(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat64Min(Node* node) {
  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, nullptr);
}

void InstructionSelector::VisitFloat32Abs(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87Float32Abs, g.DefineAsFixed(node, stX_0), 0, nullptr);
}

void InstructionSelector::VisitFloat64Abs(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87Float64Abs, g.DefineAsFixed(node, stX_0), 0, nullptr);
}

void InstructionSelector::VisitFloat32Sqrt(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87Float32Sqrt, g.DefineAsFixed(node, stX_0), 0, nullptr);
}

void InstructionSelector::VisitFloat64Sqrt(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87Float64Sqrt, g.DefineAsFixed(node, stX_0), 0, nullptr);
}

void InstructionSelector::VisitFloat32RoundDown(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float32Round | MiscField::encode(kRoundDown),
       g.UseFixed(node, stX_0), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat64RoundDown(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64Round | MiscField::encode(kRoundDown),
       g.UseFixed(node, stX_0), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat32RoundUp(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float32Round | MiscField::encode(kRoundUp), g.UseFixed(node, stX_0),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat64RoundUp(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64Round | MiscField::encode(kRoundUp), g.UseFixed(node, stX_0),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat32RoundTruncate(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float32Round | MiscField::encode(kRoundToZero),
       g.UseFixed(node, stX_0), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64Round | MiscField::encode(kRoundToZero),
       g.UseFixed(node, stX_0), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
  UNREACHABLE();
}

void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float32Round | MiscField::encode(kRoundToNearest),
       g.UseFixed(node, stX_0), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64Round | MiscField::encode(kRoundToNearest),
       g.UseFixed(node, stX_0), g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat32Neg(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87Float32Neg, g.DefineAsFixed(node, stX_0), 0, nullptr);
}

void InstructionSelector::VisitFloat64Neg(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87Float64Neg, g.DefineAsFixed(node, stX_0), 0, nullptr);
}

void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
                                                   InstructionCode opcode) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1)));
  Emit(opcode, g.DefineAsFixed(node, stX_0), 0, nullptr)->MarkAsCall();
}

void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
                                                  InstructionCode opcode) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(opcode, g.DefineAsFixed(node, stX_0), 0, nullptr)->MarkAsCall();
}

void InstructionSelector::EmitPrepareArguments(
    ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
    Node* node) {
  X87OperandGenerator g(this);

  // Prepare for C function call.
  if (descriptor->IsCFunctionCall()) {
    InstructionOperand temps[] = {g.TempRegister()};
    size_t const temp_count = arraysize(temps);
    Emit(kArchPrepareCallCFunction |
             MiscField::encode(static_cast<int>(descriptor->ParameterCount())),
         0, nullptr, 0, nullptr, temp_count, temps);

    // Poke any stack arguments.
    for (size_t n = 0; n < arguments->size(); ++n) {
      PushParameter input = (*arguments)[n];
      if (input.node()) {
        int const slot = static_cast<int>(n);
        InstructionOperand value = g.CanBeImmediate(input.node())
                                       ? g.UseImmediate(input.node())
                                       : g.UseRegister(input.node());
        Emit(kX87Poke | MiscField::encode(slot), g.NoOutput(), value);
      }
    }
  } else {
    // Push any stack arguments.
    for (PushParameter input : base::Reversed(*arguments)) {
      // TODO(titzer): handle pushing double parameters.
      if (input.node() == nullptr) continue;
      InstructionOperand value =
          g.CanBeImmediate(input.node())
              ? g.UseImmediate(input.node())
              : IsSupported(ATOM) ||
                        sequence()->IsFP(GetVirtualRegister(input.node()))
                    ? g.UseRegister(input.node())
                    : g.Use(input.node());
      Emit(kX87Push, g.NoOutput(), value);
    }
  }
}

bool InstructionSelector::IsTailCallAddressImmediate() { return true; }

int InstructionSelector::GetTempsCountForTailCallFromJSFunction() { return 0; }

namespace {

void VisitCompareWithMemoryOperand(InstructionSelector* selector,
                                   InstructionCode opcode, Node* left,
                                   InstructionOperand right,
                                   FlagsContinuation* cont) {
  DCHECK(left->opcode() == IrOpcode::kLoad);
  X87OperandGenerator g(selector);
  size_t input_count = 0;
  InstructionOperand inputs[6];
  AddressingMode addressing_mode =
      g.GetEffectiveAddressMemoryOperand(left, inputs, &input_count);
  opcode |= AddressingModeField::encode(addressing_mode);
  opcode = cont->Encode(opcode);
  inputs[input_count++] = right;

  if (cont->IsBranch()) {
    inputs[input_count++] = g.Label(cont->true_block());
    inputs[input_count++] = g.Label(cont->false_block());
    selector->Emit(opcode, 0, nullptr, input_count, inputs);
  } else if (cont->IsDeoptimize()) {
    selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs,
                             cont->reason(), cont->frame_state());
  } else {
    DCHECK(cont->IsSet());
    InstructionOperand output = g.DefineAsRegister(cont->result());
    selector->Emit(opcode, 1, &output, input_count, inputs);
  }
}

// Shared routine for multiple compare operations.
void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
                  InstructionOperand left, InstructionOperand right,
                  FlagsContinuation* cont) {
  X87OperandGenerator g(selector);
  opcode = cont->Encode(opcode);
  if (cont->IsBranch()) {
    selector->Emit(opcode, g.NoOutput(), left, right,
                   g.Label(cont->true_block()), g.Label(cont->false_block()));
  } else if (cont->IsDeoptimize()) {
    selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->reason(),
                             cont->frame_state());
  } else {
    DCHECK(cont->IsSet());
    selector->Emit(opcode, g.DefineAsByteRegister(cont->result()), left, right);
  }
}

// Shared routine for multiple compare operations.
void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
                  Node* left, Node* right, FlagsContinuation* cont,
                  bool commutative) {
  X87OperandGenerator g(selector);
  if (commutative && g.CanBeBetterLeftOperand(right)) {
    std::swap(left, right);
  }
  VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
}

// Tries to match the size of the given opcode to that of the operands, if
// possible.
InstructionCode TryNarrowOpcodeSize(InstructionCode opcode, Node* left,
                                    Node* right, FlagsContinuation* cont) {
  // Currently, if one of the two operands is not a Load, we don't know what its
  // machine representation is, so we bail out.
  // TODO(epertoso): we can probably get some size information out of immediates
  // and phi nodes.
  if (left->opcode() != IrOpcode::kLoad || right->opcode() != IrOpcode::kLoad) {
    return opcode;
  }
  // If the load representations don't match, both operands will be
  // zero/sign-extended to 32bit.
  MachineType left_type = LoadRepresentationOf(left->op());
  MachineType right_type = LoadRepresentationOf(right->op());
  if (left_type == right_type) {
    switch (left_type.representation()) {
      case MachineRepresentation::kBit:
      case MachineRepresentation::kWord8: {
        if (opcode == kX87Test) return kX87Test8;
        if (opcode == kX87Cmp) {
          if (left_type.semantic() == MachineSemantic::kUint32) {
            cont->OverwriteUnsignedIfSigned();
          } else {
            CHECK_EQ(MachineSemantic::kInt32, left_type.semantic());
          }
          return kX87Cmp8;
        }
        break;
      }
      case MachineRepresentation::kWord16:
        if (opcode == kX87Test) return kX87Test16;
        if (opcode == kX87Cmp) {
          if (left_type.semantic() == MachineSemantic::kUint32) {
            cont->OverwriteUnsignedIfSigned();
          } else {
            CHECK_EQ(MachineSemantic::kInt32, left_type.semantic());
          }
          return kX87Cmp16;
        }
        break;
      default:
        break;
    }
  }
  return opcode;
}

// Shared routine for multiple float32 compare operations (inputs commuted).
void VisitFloat32Compare(InstructionSelector* selector, Node* node,
                         FlagsContinuation* cont) {
  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 if (cont->IsDeoptimize()) {
    selector->EmitDeoptimize(cont->Encode(kX87Float32Cmp), g.NoOutput(),
                             g.Use(node->InputAt(0)), g.Use(node->InputAt(1)),
                             cont->reason(), cont->frame_state());
  } 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) {
  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 if (cont->IsDeoptimize()) {
    selector->EmitDeoptimize(cont->Encode(kX87Float64Cmp), g.NoOutput(),
                             g.Use(node->InputAt(0)), g.Use(node->InputAt(1)),
                             cont->reason(), cont->frame_state());
  } 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) {
  X87OperandGenerator g(selector);
  Node* left = node->InputAt(0);
  Node* right = node->InputAt(1);

  InstructionCode narrowed_opcode =
      TryNarrowOpcodeSize(opcode, left, right, cont);

  int effect_level = selector->GetEffectLevel(node);
  if (cont->IsBranch()) {
    effect_level = selector->GetEffectLevel(
        cont->true_block()->PredecessorAt(0)->control_input());
  }

  // If one of the two inputs is an immediate, make sure it's on the right, or
  // if one of the two inputs is a memory operand, make sure it's on the left.
  if ((!g.CanBeImmediate(right) && g.CanBeImmediate(left)) ||
      (g.CanBeMemoryOperand(narrowed_opcode, node, right, effect_level) &&
       !g.CanBeMemoryOperand(narrowed_opcode, node, left, effect_level))) {
    if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
    std::swap(left, right);
  }

  // Match immediates on right side of comparison.
  if (g.CanBeImmediate(right)) {
    if (g.CanBeMemoryOperand(opcode, node, left, effect_level)) {
      // TODO(epertoso): we should use `narrowed_opcode' here once we match
      // immediates too.
      return VisitCompareWithMemoryOperand(selector, opcode, left,
                                           g.UseImmediate(right), cont);
    }
    return VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right),
                        cont);
  }

  // Match memory operands on left side of comparison.
  if (g.CanBeMemoryOperand(narrowed_opcode, node, left, effect_level)) {
    bool needs_byte_register =
        narrowed_opcode == kX87Test8 || narrowed_opcode == kX87Cmp8;
    return VisitCompareWithMemoryOperand(
        selector, narrowed_opcode, left,
        needs_byte_register ? g.UseByteRegister(right) : g.UseRegister(right),
        cont);
  }

  if (g.CanBeBetterLeftOperand(right)) {
    if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
    std::swap(left, right);
  }

  return VisitCompare(selector, opcode, left, right, cont,
                      node->op()->HasProperty(Operator::kCommutative));
}

void VisitWordCompare(InstructionSelector* selector, Node* node,
                      FlagsContinuation* cont) {
  X87OperandGenerator g(selector);
  Int32BinopMatcher m(node);
  if (m.left().IsLoad() && m.right().IsLoadStackPointer()) {
    LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node());
    ExternalReference js_stack_limit =
        ExternalReference::address_of_stack_limit(selector->isolate());
    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(kX87StackCheck);
      if (cont->IsBranch()) {
        selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()),
                       g.Label(cont->false_block()));
      } else if (cont->IsDeoptimize()) {
        selector->EmitDeoptimize(opcode, 0, nullptr, 0, nullptr, cont->reason(),
                                 cont->frame_state());
      } else {
        DCHECK(cont->IsSet());
        selector->Emit(opcode, g.DefineAsRegister(cont->result()));
      }
      return;
    }
  }
  VisitWordCompare(selector, node, kX87Cmp, cont);
}

// Shared routine for word comparison with zero.
void VisitWordCompareZero(InstructionSelector* selector, Node* user,
                          Node* value, FlagsContinuation* cont) {
  // Try to combine with comparisons against 0 by simply inverting the branch.
  while (value->opcode() == IrOpcode::kWord32Equal &&
         selector->CanCover(user, value)) {
    Int32BinopMatcher m(value);
    if (!m.right().Is(0)) break;

    user = value;
    value = m.left().node();
    cont->Negate();
  }

  if (selector->CanCover(user, value)) {
    switch (value->opcode()) {
      case IrOpcode::kWord32Equal:
        cont->OverwriteAndNegateIfEqual(kEqual);
        return VisitWordCompare(selector, value, cont);
      case IrOpcode::kInt32LessThan:
        cont->OverwriteAndNegateIfEqual(kSignedLessThan);
        return VisitWordCompare(selector, value, cont);
      case IrOpcode::kInt32LessThanOrEqual:
        cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
        return VisitWordCompare(selector, value, cont);
      case IrOpcode::kUint32LessThan:
        cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
        return VisitWordCompare(selector, value, cont);
      case IrOpcode::kUint32LessThanOrEqual:
        cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
        return VisitWordCompare(selector, value, cont);
      case IrOpcode::kFloat32Equal:
        cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
        return VisitFloat32Compare(selector, value, cont);
      case IrOpcode::kFloat32LessThan:
        cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
        return VisitFloat32Compare(selector, value, cont);
      case IrOpcode::kFloat32LessThanOrEqual:
        cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
        return VisitFloat32Compare(selector, value, cont);
      case IrOpcode::kFloat64Equal:
        cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
        return VisitFloat64Compare(selector, value, cont);
      case IrOpcode::kFloat64LessThan:
        cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
        return VisitFloat64Compare(selector, value, cont);
      case IrOpcode::kFloat64LessThanOrEqual:
        cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
        return VisitFloat64Compare(selector, value, cont);
      case IrOpcode::kProjection:
        // Check if this is the overflow output projection of an
        // <Operation>WithOverflow node.
        if (ProjectionIndexOf(value->op()) == 1u) {
          // We cannot combine the <Operation>WithOverflow with this branch
          // unless the 0th projection (the use of the actual value of the
          // <Operation> is either nullptr, which means there's no use of the
          // actual value, or was already defined, which means it is scheduled
          // *AFTER* this branch).
          Node* const node = value->InputAt(0);
          Node* const result = NodeProperties::FindProjection(node, 0);
          if (result == nullptr || selector->IsDefined(result)) {
            switch (node->opcode()) {
              case IrOpcode::kInt32AddWithOverflow:
                cont->OverwriteAndNegateIfEqual(kOverflow);
                return VisitBinop(selector, node, kX87Add, cont);
              case IrOpcode::kInt32SubWithOverflow:
                cont->OverwriteAndNegateIfEqual(kOverflow);
                return VisitBinop(selector, node, kX87Sub, cont);
              case IrOpcode::kInt32MulWithOverflow:
                cont->OverwriteAndNegateIfEqual(kOverflow);
                return VisitBinop(selector, node, kX87Imul, cont);
              default:
                break;
            }
          }
        }
        break;
      case IrOpcode::kInt32Sub:
        return VisitWordCompare(selector, value, cont);
      case IrOpcode::kWord32And:
        return VisitWordCompare(selector, value, kX87Test, cont);
      default:
        break;
    }
  }

  // Continuation could not be combined with a compare, emit compare against 0.
  X87OperandGenerator g(selector);
  VisitCompare(selector, kX87Cmp, g.Use(value), g.TempImmediate(0), cont);
}

}  // namespace

void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
                                      BasicBlock* fbranch) {
  FlagsContinuation cont(kNotEqual, tbranch, fbranch);
  VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
}

void InstructionSelector::VisitDeoptimizeIf(Node* node) {
  FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
      kNotEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1));
  VisitWordCompareZero(this, node, node->InputAt(0), &cont);
}

void InstructionSelector::VisitDeoptimizeUnless(Node* node) {
  FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
      kEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1));
  VisitWordCompareZero(this, node, node->InputAt(0), &cont);
}

void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
  X87OperandGenerator g(this);
  InstructionOperand value_operand = g.UseRegister(node->InputAt(0));

  // Emit either ArchTableSwitch or ArchLookupSwitch.
  size_t table_space_cost = 4 + sw.value_range;
  size_t table_time_cost = 3;
  size_t lookup_space_cost = 3 + 2 * sw.case_count;
  size_t lookup_time_cost = sw.case_count;
  if (sw.case_count > 4 &&
      table_space_cost + 3 * table_time_cost <=
          lookup_space_cost + 3 * lookup_time_cost &&
      sw.min_value > std::numeric_limits<int32_t>::min()) {
    InstructionOperand index_operand = value_operand;
    if (sw.min_value) {
      index_operand = g.TempRegister();
      Emit(kX87Lea | AddressingModeField::encode(kMode_MRI), index_operand,
           value_operand, g.TempImmediate(-sw.min_value));
    }
    // Generate a table lookup.
    return EmitTableSwitch(sw, index_operand);
  }

  // Generate a sequence of conditional jumps.
  return EmitLookupSwitch(sw, value_operand);
}

void InstructionSelector::VisitWord32Equal(Node* const node) {
  FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
  Int32BinopMatcher m(node);
  if (m.right().Is(0)) {
    return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
  }
  VisitWordCompare(this, node, &cont);
}

void InstructionSelector::VisitInt32LessThan(Node* node) {
  FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
  VisitWordCompare(this, node, &cont);
}

void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
  FlagsContinuation cont =
      FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
  VisitWordCompare(this, node, &cont);
}

void InstructionSelector::VisitUint32LessThan(Node* node) {
  FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
  VisitWordCompare(this, node, &cont);
}

void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
  FlagsContinuation cont =
      FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
  VisitWordCompare(this, node, &cont);
}

void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
  if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
    FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
    return VisitBinop(this, node, kX87Add, &cont);
  }
  FlagsContinuation cont;
  VisitBinop(this, node, kX87Add, &cont);
}

void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
  if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
    FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
    return VisitBinop(this, node, kX87Sub, &cont);
  }
  FlagsContinuation cont;
  VisitBinop(this, node, kX87Sub, &cont);
}

void InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
  if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
    FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
    return VisitBinop(this, node, kX87Imul, &cont);
  }
  FlagsContinuation cont;
  VisitBinop(this, node, kX87Imul, &cont);
}

void InstructionSelector::VisitFloat32Equal(Node* node) {
  FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node);
  VisitFloat32Compare(this, node, &cont);
}

void InstructionSelector::VisitFloat32LessThan(Node* node) {
  FlagsContinuation cont =
      FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
  VisitFloat32Compare(this, node, &cont);
}

void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) {
  FlagsContinuation cont =
      FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
  VisitFloat32Compare(this, node, &cont);
}

void InstructionSelector::VisitFloat64Equal(Node* node) {
  FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node);
  VisitFloat64Compare(this, node, &cont);
}

void InstructionSelector::VisitFloat64LessThan(Node* node) {
  FlagsContinuation cont =
      FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
  VisitFloat64Compare(this, node, &cont);
}

void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
  FlagsContinuation cont =
      FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
  VisitFloat64Compare(this, node, &cont);
}

void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64ExtractLowWord32, g.DefineAsRegister(node),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87Float64ExtractHighWord32, g.DefineAsRegister(node),
       g.Use(node->InputAt(0)));
}

void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) {
  X87OperandGenerator g(this);
  Node* left = node->InputAt(0);
  Node* right = node->InputAt(1);
  Emit(kX87Float64InsertLowWord32, g.UseFixed(node, stX_0), g.UseRegister(left),
       g.UseRegister(right));
}

void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) {
  X87OperandGenerator g(this);
  Node* left = node->InputAt(0);
  Node* right = node->InputAt(1);
  Emit(kX87Float64InsertHighWord32, g.UseFixed(node, stX_0),
       g.UseRegister(left), g.UseRegister(right));
}

void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
  X87OperandGenerator g(this);
  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
  Emit(kX87Float64SilenceNaN, g.DefineAsFixed(node, stX_0), 0, nullptr);
}

void InstructionSelector::VisitAtomicLoad(Node* node) {
  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
  DCHECK(load_rep.representation() == MachineRepresentation::kWord8 ||
         load_rep.representation() == MachineRepresentation::kWord16 ||
         load_rep.representation() == MachineRepresentation::kWord32);
  USE(load_rep);
  VisitLoad(node);
}

void InstructionSelector::VisitAtomicStore(Node* node) {
  X87OperandGenerator g(this);
  Node* base = node->InputAt(0);
  Node* index = node->InputAt(1);
  Node* value = node->InputAt(2);

  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
  ArchOpcode opcode = kArchNop;
  switch (rep) {
    case MachineRepresentation::kWord8:
      opcode = kX87Xchgb;
      break;
    case MachineRepresentation::kWord16:
      opcode = kX87Xchgw;
      break;
    case MachineRepresentation::kWord32:
      opcode = kX87Xchgl;
      break;
    default:
      UNREACHABLE();
      break;
  }
  AddressingMode addressing_mode;
  InstructionOperand inputs[4];
  size_t input_count = 0;
  inputs[input_count++] = g.UseUniqueRegister(base);
  if (g.CanBeImmediate(index)) {
    inputs[input_count++] = g.UseImmediate(index);
    addressing_mode = kMode_MRI;
  } else {
    inputs[input_count++] = g.UseUniqueRegister(index);
    addressing_mode = kMode_MR1;
  }
  inputs[input_count++] = g.UseUniqueRegister(value);
  InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
  Emit(code, 0, nullptr, input_count, inputs);
}

// static
MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
  MachineOperatorBuilder::Flags flags =
      MachineOperatorBuilder::kWord32ShiftIsSafe;
  if (CpuFeatures::IsSupported(POPCNT)) {
    flags |= MachineOperatorBuilder::kWord32Popcnt;
  }

  flags |= MachineOperatorBuilder::kFloat32RoundDown |
           MachineOperatorBuilder::kFloat64RoundDown |
           MachineOperatorBuilder::kFloat32RoundUp |
           MachineOperatorBuilder::kFloat64RoundUp |
           MachineOperatorBuilder::kFloat32RoundTruncate |
           MachineOperatorBuilder::kFloat64RoundTruncate |
           MachineOperatorBuilder::kFloat32RoundTiesEven |
           MachineOperatorBuilder::kFloat64RoundTiesEven;
  return flags;
}

// static
MachineOperatorBuilder::AlignmentRequirements
InstructionSelector::AlignmentRequirements() {
  return MachineOperatorBuilder::AlignmentRequirements::
      FullUnalignedAccessSupport();
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8

redpajama_set_name: RedPajamaGithub


Being bilingual opens up a world of opportunities in your life. Learning to speak another language different from your native language not only allows you to express yourself in another language, but it also allows us to learn about other cultures and people.
Education wise, many high schools and university programs have world language requirements to enter or finish a degree from their program but if at all possible it is best to start language learning from a young age.
In the United States, there is a growing Latino or Spanish speaking population which means increased opportunities for bilinguals within the United States and abroad. There are many elementary schools that offer programming in Spanish; be it: bilingual, dual language or Spanish immersion classrooms.
Bilingual education (if given the opportunity) is a great thing to enroll your child in starting in preschool or Kindergarten. Students learn to read, write, do math and science in a second language. They learn how to communicate with friends, teachers and other adults in the community in ways that they would not be able to if they attended a traditional monolingual (English) elementary school.
Language learning for young children is also easier. Don't wait to encourage learning a language until middle school or high school as it is much easier to learn and become fluent in a second or third language before that age of 10. Little kids are not afraid of making mistakes and pick up on language patterns quickly whereas older students and adults often struggle to learn because they want to be "perfect" or are afraid to make mistakes.
Can anyone be bilingual? It takes hard work and dedication but as long as you (or your family) is committed to bilingual education it is possible. Remember that language learning is a process. You did NOT learn to speak your first language in a day or two so you cannot expect yourself (or your child) to be "fluent" in a second language in a few short days or weeks.
Being bilingual opens up new opportunities; especially career-wise. Many bilingual can access higher-paying jobs since they have the ability to express themselves in two languages. Many can serve as translators, mediators, teachers, doctors, diplomats or in specialized markets or positions because of their language skills. Being bilingual often sets job candidates apart when companies hire new employees.
Being bilingual shapes your mind differently. Bilingual people are often better problem solvers and can approach tasks, people and communication in multifaceted manners because they understand that there are different perspectives and ways to do things.
Having to learn, think and express yourself in more than one language (English and Spanish) allows you to learn, breathe and experience the culture of the language you are learning and you can see various perspective or points of view and be more empathetic with people from different countries, cultures or perspectives.
Bilingual education creates the opportunity to not only learn academics in a second language or learn to communicate with people but also allows you to learn certain expressions that correspond only to certain languages and not only that we can learn from their customs and ways of doing things or living.
The advantages of bilingual education are countless, be it for academics, hobbies, careers or professional growth. Being bilingual makes learning an adventure and creates well rounded and world-minded adults.


text:
Navy confiscates four trucks used for illegal bunkering in Lagos
Ripples Nigeria
The Western Naval Command on Friday confiscated four trucks used for illegal bunkering at Idimu area of Lagos State.
The Flag Officer Commanding (FOC), Western Naval Command, Rear Adm. Jason Gbassa, disclosed this to journalists during a visit to the site of the illegal operation.
Gbassa, who said no arrest was made during the operation, said the trucks would be forfeited to the Federal Government.
He said: "The culprits abandoned their trucks and appliances when they saw our men approaching.
"The striking thing is that people have the effrontery to carry out such illegal activities against the mandate of Operation Awatse in a built-up area where people reside.
"We have the trucks with us and some of them are loaded.
READ ALSO: Nigerian Navy arrests four stowaways in Lagos
"We are going to move them back to base and follow-up with further investigations and handing over to the appropriate agencies.
"We will follow up on this case and ensure we conclude effectively to make sure that the trucks are forfeited to the Federal Government."
The navy commander noted that four people who were involved in a similar incident some weeks ago had been convicted.
"We will continue to pursue the perpetrators in order to know the people behind these illegal acts," he added.
Support Ripples Nigeria, hold up solutions journalism
Balanced, fearless journalism driven by data comes at huge financial costs.
As a media platform, we hold leadership accountable and will not trade the right to press freedom and free speech for a piece of cake.
If you like what we do, and are ready to uphold solutions journalism, kindly donate to the Ripples Nigeria cause.
Your support would help to ensure that citizens and institutions continue to have free access to credible and reliable information for societal development.
INSECURITY: UNIJOS suspends academic activities for second time in three months
Unknown gunmen kill LASU student activist who criticized school management
Investigations3 weeks ago
In this features, KELECHUKWU IRUOMA goes into the rural communities of Bayelsa State, south-south Nigeria to uncover the plight of...
Investigations1 month ago
For a number of years communities in Ilorin South LGA of Kwara State have had to live with the menace...
Investigations2 months ago
By Arinze Chijioke In the early days of Sandra Izuckukwu's marriage in 2019, her husband, Sunday Izuchukwu, did everything she...
This investigation is on the unresolved killing of three Nigerian journalists while on assignments between 2019 and 2020. For six...
This investigation is on the unresolved killing of three Nigerian journalists while on assignments between 2019-2020. For six months, Nigerian...

redpajama_set_name: RedPajamaCommonCrawl


Want to trace your ancestors?
Come visit the Family History Room at HJ Daley Library at Campbelltown.
There you will find Australian Births/Deaths/Marriages , Assisted Immigration Records, Unassisted Immigration Records, Cemetery and Burial records and more. These records can be found in our books, microfilm and microfiche collections.
These databases can be used at any of our branch libraries. Please note: library staff can help with catalogue searches, finding books and other resources, and will show you how to use the various machines (microfilm readers, for instance), but cannot do the research for you.
If you're just beginning or are stuck with your research, you can get help. Volunteers from Campbelltown and District Family History Society are at the library between 10am and 12noon Monday to Saturday to assist you. Please note this service operates February through November only. Bookings can be made at the library or by phoning 4645 4557.


text:
If America has a communist President then perhaps Britain could have a socialist Prime Minister?
I'm morbidly fascinated by the political culture of the American right and someday hope to do work on it, though I'm not sure what form that might take. In the 10 years or so I've been keenly following American politics, it's got progressively weirder and shows no signs of abating. In fact it reached a new level of inanity. Consider the results of this poll:
Almost one in four Republicans suspect that Barack Obama is the Antichrist. That's one of the most astounding findings from a notably stunning new online poll from Harris Interactive. Majorities of Republicans also believe that Obama is a socialist (67 percent), that he wants to take away Americans' guns (61 percent), is a Muslim (57 percent), has done "many" things that are not constitutional (55 percent), and wants to turn the country over to a one world government (51 percent).
In fairness to the GOP the poll indicates that the country generally seems to have become a bit unhinged. Overall, 40 percent of Americans think Obama's a socialist, 32 percent think he's a Muslim, and one in four think that "he is a domestic enemy that the U.S. Constitution speaks of.
http://www.usnews.com/opinion/blogs/robert-schlesinger/2010/03/24/party-of-nuts-poll-shows-gop-thinks-obama-is-muslim-socialist
Even on the most charitable interpretations Republicans are, at least, complicit in the growth of these bizarre views:
Rep. Joe Walsh (R-Ill.) held another lively town hall meeting this weekend, playing host to a constituent who accused President Barack Obama of "sedition" because he had allegedly lied to voters about his true political allegiances to "socialism, communism and Nazism."
In a discussion about health care reform, a woman told Walsh that she believed the United States was losing its freedom because of elected officials who were falsifying their ideologies to get elected.
"It is sedition. I mean, they did it underground. If they are honest brokers and they believe in what they're saying and where they want this country to go, like Obama, then you're right. He should have said it before he was elected, and said 'I'm a socialist, I believe in socialism, in communism, Nazism,' whatever, and say 'this is where I want to lead the country' — not do it underhandedly," she said.
http://www.huffingtonpost.com/2012/05/21/joe-walsh-town-hall-obama_n_1532768.html
And many (including myself) would argue that they're wilfully fuelling them for their own short term gain. It's the intensification of a longer standing strategy and it risks becoming almost indescribably self-destructive, as the Republican party is now driven by true believers who have been motivated to join the party largely because of their acceptance of this nonsense. But could something similar happen here? I would have thought not and yet the last few weeks would seem to suggest that an attempt is being made. After all, it's seemed clear to me for some time that the current government have been reading from the Republican playbook for the last few years (e.g. ideologically motivated deficit hawking has been a driver of party politics for longer there than it has here) and there are demonstrable links between UK right-wing think tanks (in which the Cameroons are deeply entwined) and their American equivalents. Owen Jones offers a great analysis of this in yesterday's Independent:
That in mind, I wonder what Ralph Miliband would have made of his son's transformation from a "laughable blank sheet of paper" to "frothing-at-the-mouth Communist who is going to nationalise your mother quicker than you can say 'Friedrich Engels had a cracking beard'". Ed Miliband's suggested crackdown on land-banking (once endorsed by Boris "Commie" Johnson) and a temporary freeze on energy prices (backed by arch-Leninist Tom Burke, the former Tory special adviser on energy) have provoked comparisons with undesirable elements ranging from Robert Mugabe to the Bolsheviks. After he stood on a soapbox in Brighton and indulged a bystander asking when he would "bring back socialism", the British right have behaved as though Labour are planning to finish what Lenin was doing before he was so rudely interrupted.
In part, it is the sinister red-baiting of Ed Miliband through his dead father, culminating with the Daily Mail accusing the Labour leader of planning to drive "a hammer and sickle through the heart of the nation so many of us love". Pass the spliff, Mr Dacre. "Like a good Marxist," writes The Daily Telegraph's Charles Moore, "he detects the cowardice latent in capitalists," accusing Miliband of being "part of an ideology" which is "ultimately pauperising and totalitarian." Jeremy Hunt odiously endorsed the Mail's lunacy, arguing that "Ralph Miliband was no friend of the free market and I have never heard Ed Miliband say he supports it." George Osborne, meanwhile, accuses Ed Miliband of making "essentially the same argument Karl Marx made in Das Kapital."
This is what is really going on. The right are so drunk on three decades of free-market triumphalism, so used to the left being smashed and battered, that they believe even the mildest deviation from the neo-liberal script is unacceptable. They thought all of these battles had been won, that they were rid of all their turbulent priests, and now they are incandescent at the alleged resurgence of defeated enemies. Don't you know you're supposed to be dead? It's not even the most moderate form of social democracy that the right are trying to drive from political life. Anyone who does not advocate yet more aggressive doses of neo-liberalism – more privatisation, more cuts to the taxes of the wealthy, more attacks on workers' rights – is liable to come under suspicion, too.
The British right's strategy is pretty clear. They want to do to "socialist" what the US right have done to "liberal": turn it into an unequivocally toxic word that no-one in public life would want to associate with, and use it as a means to smear political opponents deemed to deviate from Britain's suffocating neo-liberal consensus. Bemusing, to say the least, given Labour first officially declared itself a "democratic socialist party" under Tony Blair in 1995 as a sop to the left in the party's new revised Clause IV. He even wrote a Fabian Society pamphlet entitled Socialism. Yes, granted it meant nothing more to him than motherhood and apple pie, and he had more leeway than Miliband because it was rather more difficult to pin him down as a heartfelt lefty, but the point is even New Labour could happily bandy "socialism" about.
http://www.independent.co.uk/voices/comment/ed-miliband-isnt-offering-socialism–but-the-tories-are-still-terrified-8862388.html
I struggle to fathom the depth of the demonstrable stupidity I'm presented with when encountering someone who believes Ed Miliband is a socialist. Which leads me to assume that they don't really mean it. Or by 'socialist' they mean someone mildly to the left of New Labour orthodoxy. When I encounter Obama being called a Islamic Commie Nazi (etc) I can find it kind of funny (less so with a potential US default imminent) because of the distance. But it worries me a lot that this toxic political culture could be willingly inculcated in the UK. I'm pretty certain some are making the attempt but I doubt it could take root. I'm less sure of this then I used to be though.
BSA Annual Conference 2014: Changing Society - Call for papers
Blogging as Public Sociology


I post to attract new members, but this is how you treat non-english speaking posters.
You are a disgrace who don't even follow your own rules.
Shame on you for being a racist and narrow minded bigot, and shame on others for not speaking out against this.
Although the administrators and moderators of Thai Dreaming will attempt to keep all objectionable messages off this site, it is impossible for us to review all messages. All messages express the views of the author, and neither the owners of Thai Dreaming, nor vBulletin Solutions, Inc. (developers of vBulletin) will be held responsible for the content of any message.
WTTB Vixi, where are you from ?..................why were you banned before ?
For posting in my language about Thailand.
If you post in a forum where people speak and write only English, and can not read your script, then that is not being racist. It is only sensible. My only question is why would you join a forum where people speak only English and then complain about it?
I don't join Thai forums and call them racist because they don't speak English. If you got banned then it is because you did not adapt. I don't go into a restaurant in a Thai village somewhere and complain because they don't speak English.
Internet forums are where you can learn from others if you are willing to contribute and adapt. Not all forums are suitable for everyone. New members should look, read and try to understand whether or not a forum is suitable for them. Obviously, from your first post you do not understand this concept.
what is your language Khun Vixiband?....your post may well have been interpreted as spam/bot poster..
But its not against the rules of the forum.
Banning someone for talk in own language is racist, I don't see how its not.
I post in my own language to meet with others to talk about Thailand who may not speak english.
English isn't the world language.
In the rules or no where on the site does it say post must be in english.
Okay, that is up to you, but on this forum everyone writes in English. There might be a few members who can speak and write Thai, but they do not do so on this forum. That does not make the forum racist. Otherwise, everyone, everywhere in the world could be called "racist" for not being able to speak and write all languages.
Like Bacwaan said..."your first post typed in Thai script may well have been interpreted as spam or a bot poster.. " We get a lot of that and it has to eliminated quickly or the site is over run with spam ads.
But again I'll ask, why post in Thai script if you can post in English on this site? If nobody can read it then nobody will respond and you will be just talking to yourself in a vacuum.
Thanks, Rob. Only just saw these.
Yes , it is a nice view of the land and flowers Vixi.
Why not take the challenge and make a Russian language section Boss?
I nominate Vixiband as the Mod for all the entries in Russian.
If Vixi has the time I would appreciate any efforts to translate to English.


My Grandma and I were talking on the phone the other day. A story about my Grandpa as a kid reminded me of an episode from "Leave it to Beaver" so I thought I'd tell her about it.
Me: "That story reminds me of "Leave it to Beaver"."
Grandma: "That cute kid with the hair?"
Me: "Uh, I guess so..."
Grandma: "What's his first name?"
Grandma: "No, that's not it..."
Me: "... His brother's name is Wally ..."
Grandma: "No, that's not it either..."
Me: "Oh... ... Wait -- do you mean Justin Bieber?!?!"
Grandma: "Yeah, that's it -- Justin Bieber!"
Clearly the generation gap works in reverse too.
Jodi, Call me old fashioned too, but I'm with you -- I thought for sure my Grandma would be too!
Stacia, I know! Now how will we be able to identify him without his signature 'do?!?!


text:
3D Printing Is Altering Global Manufacturing
Technology and automation has brought manufacturing a long way. One of the latest innovations, 3D printing, could make a significant mark of global proportions. Will your firm be at the forefront of this technology or be left in the dust?
Take Action to Control Workers' Comp AFTER an Accident
No matter how careful your company is, accidents and injuries can still happen. When they do, responding properly is an important factor in keeping your Workers' Compensation insurance costs under control. Here are six steps to take in the event an injury occurs:
Keeping Patients Hospitalized One More Day Has Multiple Benefits
It turns out that keeping patients in the hospital for just one day longer can saves lives, lower costs and reduce readmissions. That's the conclusion of one study from the Columbia University Business School entitled "Should Hospitals Keep Their Patients Longer?"
Ten Ways to Expand Your Not-for-Profit's Email List
Email messages have become a sweet spot for many not-for-profit organizations.
Tax Implications of Taking 529 College Savings Plan Withdrawals
Tax-favored Section 529 college savings plans — also known as qualified tuition programs — have been around long enough that many people are now withdrawing money to pay for school. Qualified withdrawals are always federal-income-tax-free and usually state-income-tax-free, too. However, the full story isn't quite so simple. Here are the key details.
Bring Home a Tax Credit for Adoption
When you adopt a child, you could bring home more than a bundle of joy. You may also be in line for a valuable tax credit.
Should You Consider an Employer Roth 401(k) Account?
Nowadays, many employer retirement plans give employees the option of contributing to designated Roth accounts (DRAs). According to a 2020 survey, 75% of employer plans now offer DRAs, which are also known as Roth 401(k) accounts.
Ten Best Practices for Managing Overtime
Scheduling hourly employees to work more than 40 hours a week can help overcome seasonal peaks in production or bridge a temporary labor shortage. But excessive overtime should be the exception, rather than the norm, in a healthy, productive manufacturing business.
Internal fraud drains approximately $4 trillion annually from global businesses, according to an estimate by the Association of Certified Fraud Examiners (ACFE).
Facing a HIPAA Audit: What to Know
Early in the history of the Health Insurance Portability and Accountability Act (HIPAA), violations typically involved receiving a warning letter from the Department of Health and Human Services (HHS). It was basically toothless and carried no penalties. In 2009, Congress passed the Health Information Technology for Economic and Clinical Health Act (HITECH), which supplied the government with a range of tools to support enforcement. In short, HIPAA grew fangs.


Read on for a little bit about how we started and some of the things we've done. Future releases or versions of the Business In Japan Webportal are also in the works, so stay tuned here and in the BIJ Group on LinkedIn or Facebook!
Business In Japan began as a LinkedIn group, one of the early ones (group number 54,168) and was started by Rob Pereyda at a time when online marketers – he was not one – on LinkedIn were rushing to create Email Collection honey pots – that is to say, build groups that would become as large as possible as quickly as possible, so they could harvest the emails from them. At the time LinkedIn allowed group owners to download the emails of their group members, similar to what is still the case for your individual first level connections on LinkedIn (as at Aug., 2016). These were called things like "Connect with me", "TopLinked" or "LinkedIn Open Networkers (LIONs)".
Other booming groups were often started, understandably, by recruiters.
At any one time there are between 1.5M and 2.1M LinkedIn groups apparently. I just now created then deleted a group to see how many groups have ever been created and it was 7,065,306.
Rob was in the Anime and other Japanese content licensing business, was nonthreatening and authentic. The group grew steadily with those in or interested in doing Business in Japan, and I was one of the early members. Around the 1,000 member mark Rob found it was getting harder and harder to keep out the broadcasted link sharing, advertising, blog and self promotion and so one day 'deputized' about a dozen people as Moderators to help. I'm not sure how many in the beginning actually did any moderating at all but I did, increasingly seeing an opportunity to help grow a valuable place to come to learn and ask questions about Japan in a Business or Professional setting.
In October of 2009, Rob thought it was about time to have a first meet up for BIJ, and as he was working in a start up using the Shin Marunouchi Building's Mitsubishi owned business incubation office 'Egg-Japan', he had a bit of influence to get permission to use the outdoor area next to a restaurant on the 7F of Shin Marunouchi building's main restaurant floor. Shin Maru Building is pretty much on top of Tokyo Station. We expected around 50 people – over 200 showed up. Next event we planned for 250+ and reserved the spots outside two restaurants – and over 700 BIJ members and friends attended.
So in April 2010 with help from my network and reach, we planned for 1,000 people – Business In Japan Night, organizing with building management and every Restaurant on the 7F of Shin Maru Building to make available at least a 500 yen drink and 500 yen food choice, and be prepared for many people. RSVP's on the now defunct LinkedIn Events system topped 1,200 people as we got a bit worried. But April was cold… it rained most of the afternoon and evening, too cold to be on the balcony. Nevertheless, it was packed… but we don't think we cracked the 1,000. Perhaps 900 or so.
Rob was to leave his employer Crunchyroll soon after and we lost access to Shin Marunouchi building, but I think in terms of such PAYG (Pay as you go) Business Networking events, those events stand as the largest and most enjoyable events in Tokyo in the last 8 years.
We went on to do other events at other venues, even doing a couple of 350+ paid events, and now we have recently begun regular Monthly Events – you can see many of our Past Events since LinkedIn's Event system shut down, and sign up to be notified of any new ones here on the awesome Doorkeeper platform: businessinjapan.doorkeeper and I have often posted them at my personal Website http://goodpeople.jp/ under the Blog. We have a BIJ Facebook Page (but don't use the Event system at this point) and often post to our LinkedIn Company Page also.
Business In Japan group on LinkedIn and now here on BusinessInJapan.com is a whole lot more than Events. Stick around, poke around, find and engage with things and people of interest.
As always, feel free let me know if I might help you.