17d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved.
27d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
37d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// found in the LICENSE file.
47d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org#include "src/base/bits.h"
67d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/instruction-selector-impl.h"
77d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/node-matchers.h"
87d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
97d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace v8 {
107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace internal {
117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace compiler {
127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Adds Arm-specific methods for generating InstructionOperands.
14ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass ArmOperandGenerator FINAL : public OperandGenerator {
157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit ArmOperandGenerator(InstructionSelector* selector)
177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : OperandGenerator(selector) {}
187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* UseOperand(Node* node, InstructionCode opcode) {
207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (CanBeImmediate(node, opcode)) {
217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return UseImmediate(node);
227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return UseRegister(node);
247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool CanBeImmediate(Node* node, InstructionCode opcode) {
27e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    Int32Matcher m(node);
28e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    if (!m.HasValue()) return false;
29e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    int32_t value = m.Value();
307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (ArchOpcodeField::decode(opcode)) {
317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmAnd:
327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmMov:
337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmMvn:
347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmBic:
357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return ImmediateFitsAddrMode1Instruction(value) ||
367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org               ImmediateFitsAddrMode1Instruction(~value);
377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmAdd:
397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmSub:
407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmCmp:
417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmCmn:
427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return ImmediateFitsAddrMode1Instruction(value) ||
437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org               ImmediateFitsAddrMode1Instruction(-value);
447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmTst:
467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmTeq:
477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmOrr:
487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmEor:
497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmRsb:
507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return ImmediateFitsAddrMode1Instruction(value);
517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
52fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      case kArmVldr32:
53fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      case kArmVstr32:
546474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmVldr64:
556474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmVstr64:
567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return value >= -1020 && value <= 1020 && (value % 4) == 0;
577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
586474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmLdrb:
596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmLdrsb:
606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmStrb:
616474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmLdr:
626474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmStr:
637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmStoreWriteBarrier:
647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return value >= -4095 && value <= 4095;
657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
666474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmLdrh:
676474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmLdrsh:
686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      case kArmStrh:
697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return value >= -255 && value <= 255;
707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
717b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      case kArchCallCodeObject:
727b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      case kArchCallJSFunction:
737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArchJmp:
747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArchNop:
757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArchRet:
767dae5b9f8500ada1f217a27db8a1f5c62becd404machenbach@chromium.org      case kArchTruncateDoubleToI:
777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmMul:
787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmMla:
797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmMls:
807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmSdiv:
817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmUdiv:
827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmBfc:
837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmUbfx:
847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVcmpF64:
857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVaddF64:
867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVsubF64:
877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVmulF64:
887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVmlaF64:
897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVmlsF64:
907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVdivF64:
917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVmodF64:
927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVnegF64:
93b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      case kArmVsqrtF64:
947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVcvtF64S32:
957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVcvtF64U32:
967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVcvtS32F64:
977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kArmVcvtU32F64:
987b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      case kArmPush:
997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return false;
1007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    UNREACHABLE();
1027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return false;
1037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
1067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool ImmediateFitsAddrMode1Instruction(int32_t imm) const {
1077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return Assembler::ImmediateFitsAddrMode1Instruction(imm);
1087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
1107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode,
1137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                            Node* node) {
1147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
115fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  selector->Emit(opcode, g.DefineAsRegister(node),
116fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org                 g.UseRegister(node->InputAt(0)),
117fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org                 g.UseRegister(node->InputAt(1)));
1187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic bool TryMatchROR(InstructionSelector* selector,
1227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                        InstructionCode* opcode_return, Node* node,
1237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                        InstructionOperand** value_return,
1247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                        InstructionOperand** shift_return) {
1257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
1265e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  if (node->opcode() != IrOpcode::kWord32Ror) return false;
1277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
1285e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  *value_return = g.UseRegister(m.left().node());
1295e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  if (m.right().IsInRange(1, 31)) {
1307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_I);
1315e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    *shift_return = g.UseImmediate(m.right().node());
1325e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  } else {
1337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_R);
1345e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    *shift_return = g.UseRegister(m.right().node());
1357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1365e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  return true;
1377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline bool TryMatchASR(InstructionSelector* selector,
1417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionCode* opcode_return, Node* node,
1427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionOperand** value_return,
1437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionOperand** shift_return) {
1447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
1457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (node->opcode() != IrOpcode::kWord32Sar) return false;
1467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
1477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  *value_return = g.UseRegister(m.left().node());
1487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().IsInRange(1, 32)) {
1497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_I);
1507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *shift_return = g.UseImmediate(m.right().node());
1517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
1527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_R);
1537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *shift_return = g.UseRegister(m.right().node());
1547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return true;
1567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline bool TryMatchLSL(InstructionSelector* selector,
1607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionCode* opcode_return, Node* node,
1617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionOperand** value_return,
1627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionOperand** shift_return) {
1637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
1647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (node->opcode() != IrOpcode::kWord32Shl) return false;
1657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
1667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  *value_return = g.UseRegister(m.left().node());
1677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().IsInRange(0, 31)) {
1687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
1697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *shift_return = g.UseImmediate(m.right().node());
1707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
1717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_R);
1727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *shift_return = g.UseRegister(m.right().node());
1737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return true;
1757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline bool TryMatchLSR(InstructionSelector* selector,
1797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionCode* opcode_return, Node* node,
1807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionOperand** value_return,
1817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               InstructionOperand** shift_return) {
1827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
1837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (node->opcode() != IrOpcode::kWord32Shr) return false;
1847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
1857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  *value_return = g.UseRegister(m.left().node());
1867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().IsInRange(1, 32)) {
1877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_I);
1887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *shift_return = g.UseImmediate(m.right().node());
1897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
1907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_R);
1917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *shift_return = g.UseRegister(m.right().node());
1927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return true;
1947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
197aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgstatic inline bool TryMatchShift(InstructionSelector* selector,
198aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                                 InstructionCode* opcode_return, Node* node,
199aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                                 InstructionOperand** value_return,
200aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                                 InstructionOperand** shift_return) {
201aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  return (
202aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      TryMatchASR(selector, opcode_return, node, value_return, shift_return) ||
203aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      TryMatchLSL(selector, opcode_return, node, value_return, shift_return) ||
204aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      TryMatchLSR(selector, opcode_return, node, value_return, shift_return) ||
205aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      TryMatchROR(selector, opcode_return, node, value_return, shift_return));
206aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org}
207aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
208aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
2097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline bool TryMatchImmediateOrShift(InstructionSelector* selector,
2107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                            InstructionCode* opcode_return,
2117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                            Node* node,
2127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                            size_t* input_count_return,
2137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                            InstructionOperand** inputs) {
2147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
2157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (g.CanBeImmediate(node, *opcode_return)) {
2167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *opcode_return |= AddressingModeField::encode(kMode_Operand2_I);
2177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    inputs[0] = g.UseImmediate(node);
2187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *input_count_return = 1;
2197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return true;
2207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
221aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) {
2227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    *input_count_return = 2;
2237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return true;
2247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return false;
2267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic void VisitBinop(InstructionSelector* selector, Node* node,
230e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                       InstructionCode opcode, InstructionCode reverse_opcode,
231e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                       FlagsContinuation* cont) {
232aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  ArmOperandGenerator g(selector);
233aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  Int32BinopMatcher m(node);
234e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  InstructionOperand* inputs[5];
235aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  size_t input_count = 0;
236aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  InstructionOperand* outputs[2];
237aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  size_t output_count = 0;
238aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
239aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
240aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                               &input_count, &inputs[1])) {
241aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    inputs[0] = g.UseRegister(m.left().node());
242aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    input_count++;
243aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  } else if (TryMatchImmediateOrShift(selector, &reverse_opcode,
244aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                                      m.left().node(), &input_count,
245aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                                      &inputs[1])) {
246aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    inputs[0] = g.UseRegister(m.right().node());
247aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    opcode = reverse_opcode;
248aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    input_count++;
249aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  } else {
250aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    opcode |= AddressingModeField::encode(kMode_Operand2_R);
251aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    inputs[input_count++] = g.UseRegister(m.left().node());
252aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    inputs[input_count++] = g.UseRegister(m.right().node());
253aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  }
254aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
255e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  if (cont->IsBranch()) {
256e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    inputs[input_count++] = g.Label(cont->true_block());
257e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    inputs[input_count++] = g.Label(cont->false_block());
258aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  }
259e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
260e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  outputs[output_count++] = g.DefineAsRegister(node);
261e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  if (cont->IsSet()) {
262e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    outputs[output_count++] = g.DefineAsRegister(cont->result());
263aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  }
264aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
265e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(0, input_count);
266e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(0, output_count);
267fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK_GE(arraysize(inputs), input_count);
268fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK_GE(arraysize(outputs), output_count);
269e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(kMode_None, AddressingModeField::decode(opcode));
270aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
271e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
272e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                                      outputs, input_count, inputs);
273e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  if (cont->IsBranch()) instr->MarkAsControl();
274e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org}
275e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
276e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
277e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.orgstatic void VisitBinop(InstructionSelector* selector, Node* node,
278e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                       InstructionCode opcode, InstructionCode reverse_opcode) {
279e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  FlagsContinuation cont;
280e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  VisitBinop(selector, node, opcode, reverse_opcode, &cont);
2817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitLoad(Node* node) {
2856313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
2866313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
2877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
2887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* base = node->InputAt(0);
2897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* index = node->InputAt(1);
2907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArchOpcode opcode;
2927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (rep) {
293fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    case kRepFloat32:
294fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      opcode = kArmVldr32;
295fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      break;
2965e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepFloat64:
2976474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kArmVldr64;
2987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2995e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepBit:  // Fall through.
3005e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord8:
3016474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = typ == kTypeUint32 ? kArmLdrb : kArmLdrsb;
3027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3035e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord16:
3046474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = typ == kTypeUint32 ? kArmLdrh : kArmLdrsh;
3057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3065e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepTagged:  // Fall through.
3075e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord32:
3086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kArmLdr;
3097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
3117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      UNREACHABLE();
3127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
3137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (g.CanBeImmediate(index, opcode)) {
316fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_Offset_RI),
317fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
3187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
319fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
320fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
3217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitStore(Node* node) {
3267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
3277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* base = node->InputAt(0);
3287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* index = node->InputAt(1);
3297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* value = node->InputAt(2);
3307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
3326313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  MachineType rep = RepresentationOf(store_rep.machine_type());
3336313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
3345e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    DCHECK(rep == kRepTagged);
3357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(dcarney): refactor RecordWrite function to take temp registers
3367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    //                and pass them here instead of using fixed regs
3377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(dcarney): handle immediate indices.
3387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    InstructionOperand* temps[] = {g.TempRegister(r5), g.TempRegister(r6)};
3397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kArmStoreWriteBarrier, NULL, g.UseFixed(base, r4),
340fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.UseFixed(index, r5), g.UseFixed(value, r6), arraysize(temps),
3417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         temps);
3427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
3437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3446313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
3457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArchOpcode opcode;
3477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (rep) {
348fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    case kRepFloat32:
349fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      opcode = kArmVstr32;
350fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      break;
3515e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepFloat64:
3526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kArmVstr64;
3537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3545e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepBit:  // Fall through.
3555e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord8:
3566474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kArmStrb;
3577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3585e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord16:
3596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kArmStrh;
3607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3615e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepTagged:  // Fall through.
3625e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord32:
3636474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kArmStr;
3647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
3667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      UNREACHABLE();
3677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
3687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (g.CanBeImmediate(index, opcode)) {
3717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL,
372fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
3737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
3747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL,
375fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.UseRegister(base), g.UseRegister(index), g.UseRegister(value));
3767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline void EmitBic(InstructionSelector* selector, Node* node,
3817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                           Node* left, Node* right) {
3827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
3837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionCode opcode = kArmBic;
384aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  InstructionOperand* value_operand;
385aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  InstructionOperand* shift_operand;
386aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) {
387aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
388aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                   value_operand, shift_operand);
389aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    return;
3907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
391aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
392aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                 g.DefineAsRegister(node), g.UseRegister(left),
393aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                 g.UseRegister(right));
3947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32And(Node* node) {
3987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
3997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
4007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) {
4017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mleft(m.left().node());
4027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (mleft.right().Is(-1)) {
4037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      EmitBic(this, node, m.right().node(), mleft.left().node());
4047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
4057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
4067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) {
4087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mright(m.right().node());
4097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (mright.right().Is(-1)) {
4107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      EmitBic(this, node, m.left().node(), mright.left().node());
4117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
4127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
4137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4143e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  if (IsSupported(ARMv7) && m.right().HasValue()) {
4157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    uint32_t value = m.right().Value();
4166474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    uint32_t width = base::bits::CountPopulation32(value);
417e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org    uint32_t msb = base::bits::CountLeadingZeros32(value);
4187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (width != 0 && msb + width == 32) {
419e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org      DCHECK_EQ(0, base::bits::CountTrailingZeros32(value));
4207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (m.left().IsWord32Shr()) {
4217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        Int32BinopMatcher mleft(m.left().node());
4227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        if (mleft.right().IsInRange(0, 31)) {
4237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          Emit(kArmUbfx, g.DefineAsRegister(node),
4247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org               g.UseRegister(mleft.left().node()),
4257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org               g.UseImmediate(mleft.right().node()), g.TempImmediate(width));
4267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          return;
4277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        }
4287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
4297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
4307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.TempImmediate(0), g.TempImmediate(width));
4317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
4327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
4337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Try to interpret this AND as BFC.
4347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    width = 32 - width;
435e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org    msb = base::bits::CountLeadingZeros32(~value);
436e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org    uint32_t lsb = base::bits::CountTrailingZeros32(~value);
4377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (msb + width + lsb == 32) {
4387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
4397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.TempImmediate(lsb), g.TempImmediate(width));
4407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
4417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
4427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitBinop(this, node, kArmAnd, kArmAnd);
4447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Or(Node* node) {
4487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitBinop(this, node, kArmOrr, kArmOrr);
4497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Xor(Node* node) {
4537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
4547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
4557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().Is(-1)) {
456aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    InstructionCode opcode = kArmMvn;
457aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    InstructionOperand* value_operand;
458aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    InstructionOperand* shift_operand;
459aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    if (TryMatchShift(this, &opcode, m.left().node(), &value_operand,
460aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org                      &shift_operand)) {
461aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand);
462aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      return;
463aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    }
464aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
465aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org         g.DefineAsRegister(node), g.UseRegister(m.left().node()));
466aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    return;
4677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
468aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  VisitBinop(this, node, kArmEor, kArmEor);
4697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgtemplate <typename TryMatchShift>
4737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline void VisitShift(InstructionSelector* selector, Node* node,
4745e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                              TryMatchShift try_match_shift,
4755e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                              FlagsContinuation* cont) {
4767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
4777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionCode opcode = kArmMov;
4785e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  InstructionOperand* inputs[4];
4795e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  size_t input_count = 2;
4805e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  InstructionOperand* outputs[2];
4815e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  size_t output_count = 0;
4825e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
4835e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1]));
4845e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
4855e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  if (cont->IsBranch()) {
4865e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    inputs[input_count++] = g.Label(cont->true_block());
4875e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    inputs[input_count++] = g.Label(cont->false_block());
4885e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  }
4895e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
4905e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  outputs[output_count++] = g.DefineAsRegister(node);
4915e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  if (cont->IsSet()) {
4925e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    outputs[output_count++] = g.DefineAsRegister(cont->result());
4935e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  }
4945e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
4955e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK_NE(0, input_count);
4965e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK_NE(0, output_count);
497fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK_GE(arraysize(inputs), input_count);
498fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK_GE(arraysize(outputs), output_count);
4995e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK_NE(kMode_None, AddressingModeField::decode(opcode));
5005e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
5015e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
5025e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                                      outputs, input_count, inputs);
5035e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  if (cont->IsBranch()) instr->MarkAsControl();
5045e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org}
5055e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
5065e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
5075e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgtemplate <typename TryMatchShift>
5085e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgstatic inline void VisitShift(InstructionSelector* selector, Node* node,
5095e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                              TryMatchShift try_match_shift) {
5105e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  FlagsContinuation cont;
5115e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  VisitShift(selector, node, try_match_shift, &cont);
5127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Shl(Node* node) {
5167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitShift(this, node, TryMatchLSL);
5177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Shr(Node* node) {
5217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
5227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
5233e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  if (IsSupported(ARMv7) && m.left().IsWord32And() &&
5247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      m.right().IsInRange(0, 31)) {
5257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    int32_t lsb = m.right().Value();
5267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mleft(m.left().node());
5277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (mleft.right().HasValue()) {
5287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      uint32_t value = (mleft.right().Value() >> lsb) << lsb;
5296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      uint32_t width = base::bits::CountPopulation32(value);
530e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org      uint32_t msb = base::bits::CountLeadingZeros32(value);
5317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (msb + width + lsb == 32) {
532e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org        DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value));
5337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        Emit(kArmUbfx, g.DefineAsRegister(node),
5347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org             g.UseRegister(mleft.left().node()), g.TempImmediate(lsb),
5357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org             g.TempImmediate(width));
5367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return;
5377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
5387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
5397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitShift(this, node, TryMatchLSR);
5417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Sar(Node* node) {
5457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitShift(this, node, TryMatchASR);
5467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5495e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgvoid InstructionSelector::VisitWord32Ror(Node* node) {
5505e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  VisitShift(this, node, TryMatchROR);
5515e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org}
5525e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
5535e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
5547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Add(Node* node) {
5557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
5567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
5577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.left().IsInt32Mul() && CanCover(node, m.left().node())) {
5587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mleft(m.left().node());
5597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mleft.left().node()),
5607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node()));
5617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
5627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) {
5647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mright(m.right().node());
5657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mright.left().node()),
5667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(mright.right().node()), g.UseRegister(m.left().node()));
5677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
5687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitBinop(this, node, kArmAdd, kArmAdd);
5707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Sub(Node* node) {
5747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
5757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
5763e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  if (IsSupported(MLS) && m.right().IsInt32Mul() &&
5777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      CanCover(node, m.right().node())) {
5787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mright(m.right().node());
5797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()),
5807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(mright.right().node()), g.UseRegister(m.left().node()));
5817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
5827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitBinop(this, node, kArmSub, kArmRsb);
5847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Mul(Node* node) {
5887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
5897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
5907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().HasValue() && m.right().Value() > 0) {
5917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    int32_t value = m.right().Value();
59221d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    if (base::bits::IsPowerOfTwo32(value - 1)) {
5937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
5947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.DefineAsRegister(node), g.UseRegister(m.left().node()),
5957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.UseRegister(m.left().node()),
5967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.TempImmediate(WhichPowerOf2(value - 1)));
5977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
5987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
59921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    if (value < kMaxInt && base::bits::IsPowerOfTwo32(value + 1)) {
6007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Emit(kArmRsb | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
6017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.DefineAsRegister(node), g.UseRegister(m.left().node()),
6027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.UseRegister(m.left().node()),
6037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.TempImmediate(WhichPowerOf2(value + 1)));
6047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
6057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
6067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kArmMul, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
6087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org       g.UseRegister(m.right().node()));
6097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic void EmitDiv(InstructionSelector* selector, ArchOpcode div_opcode,
6137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                    ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode,
6147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                    InstructionOperand* result_operand,
6157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                    InstructionOperand* left_operand,
6167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                    InstructionOperand* right_operand) {
6177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
6183e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  if (selector->IsSupported(SUDIV)) {
6197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    selector->Emit(div_opcode, result_operand, left_operand, right_operand);
6207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
6217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* left_double_operand = g.TempDoubleRegister();
6237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* right_double_operand = g.TempDoubleRegister();
6247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* result_double_operand = g.TempDoubleRegister();
6257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  selector->Emit(f64i32_opcode, left_double_operand, left_operand);
6267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  selector->Emit(f64i32_opcode, right_double_operand, right_operand);
6277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  selector->Emit(kArmVdivF64, result_double_operand, left_double_operand,
6287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                 right_double_operand);
6297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  selector->Emit(i32f64_opcode, result_operand, result_double_operand);
6307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic void VisitDiv(InstructionSelector* selector, Node* node,
6347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                     ArchOpcode div_opcode, ArchOpcode f64i32_opcode,
6357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                     ArchOpcode i32f64_opcode) {
6367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
6377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
6387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode,
6397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          g.DefineAsRegister(node), g.UseRegister(m.left().node()),
6407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          g.UseRegister(m.right().node()));
6417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Div(Node* node) {
6457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitDiv(this, node, kArmSdiv, kArmVcvtF64S32, kArmVcvtS32F64);
6467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32UDiv(Node* node) {
6507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitDiv(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64);
6517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic void VisitMod(InstructionSelector* selector, Node* node,
6557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                     ArchOpcode div_opcode, ArchOpcode f64i32_opcode,
6567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                     ArchOpcode i32f64_opcode) {
6577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
6587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
6597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* div_operand = g.TempRegister();
6607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* result_operand = g.DefineAsRegister(node);
6617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* left_operand = g.UseRegister(m.left().node());
6627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* right_operand = g.UseRegister(m.right().node());
6637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode, div_operand,
6647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          left_operand, right_operand);
6653e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  if (selector->IsSupported(MLS)) {
6667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    selector->Emit(kArmMls, result_operand, div_operand, right_operand,
6677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   left_operand);
6687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
6697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* mul_operand = g.TempRegister();
6717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  selector->Emit(kArmMul, mul_operand, div_operand, right_operand);
6727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  selector->Emit(kArmSub, result_operand, left_operand, mul_operand);
6737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Mod(Node* node) {
6777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitMod(this, node, kArmSdiv, kArmVcvtF64S32, kArmVcvtS32F64);
6787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32UMod(Node* node) {
6827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitMod(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64);
6837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
686aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgvoid InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
6877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
688fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  Emit(kArmVcvtF64S32, g.DefineAsRegister(node),
6897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org       g.UseRegister(node->InputAt(0)));
6907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
693aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgvoid InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
6947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
695fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  Emit(kArmVcvtF64U32, g.DefineAsRegister(node),
6967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org       g.UseRegister(node->InputAt(0)));
6977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
700aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgvoid InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
7017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
7027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kArmVcvtS32F64, g.DefineAsRegister(node),
703fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       g.UseRegister(node->InputAt(0)));
7047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
707aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgvoid InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
7087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
7097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kArmVcvtU32F64, g.DefineAsRegister(node),
710fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       g.UseRegister(node->InputAt(0)));
7117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Add(Node* node) {
7157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
7167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
7177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.left().IsFloat64Mul() && CanCover(node, m.left().node())) {
7187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mleft(m.left().node());
7197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kArmVmlaF64, g.DefineSameAsFirst(node),
7207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()),
7217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(mleft.right().node()));
7227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
7237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
7247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
7257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mright(m.right().node());
7267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kArmVmlaF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
7277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(mright.left().node()),
7287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(mright.right().node()));
7297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
7307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
7317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitRRRFloat64(this, kArmVaddF64, node);
7327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Sub(Node* node) {
7367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
7377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
7387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
7397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher mright(m.right().node());
7407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kArmVmlsF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
7417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(mright.left().node()),
7427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(mright.right().node()));
7437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
7447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
7457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitRRRFloat64(this, kArmVsubF64, node);
7467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Mul(Node* node) {
7507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
7517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Float64BinopMatcher m(node);
7527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().Is(-1.0)) {
753fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    Emit(kArmVnegF64, g.DefineAsRegister(node), g.UseRegister(m.left().node()));
7547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
7557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    VisitRRRFloat64(this, kArmVmulF64, node);
7567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
7577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Div(Node* node) {
7617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitRRRFloat64(this, kArmVdivF64, node);
7627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Mod(Node* node) {
7667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
767fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  Emit(kArmVmodF64, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0),
768fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       g.UseFixed(node->InputAt(1), d1))->MarkAsCall();
7697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
772b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Sqrt(Node* node) {
773b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  ArmOperandGenerator g(this);
774b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  Emit(kArmVsqrtF64, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
775b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org}
776b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org
777b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org
7787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitCall(Node* call, BasicBlock* continuation,
7797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                    BasicBlock* deoptimization) {
7807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
7817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call);
782a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
783a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  FrameStateDescriptor* frame_state_descriptor = NULL;
784a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  if (descriptor->NeedsFrameState()) {
785a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    frame_state_descriptor =
786a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org        GetFrameStateDescriptor(call->InputAt(descriptor->InputCount()));
787a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
788a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
789a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
7907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Compute InstructionOperands for inputs and outputs.
7927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): on ARM64 it's probably better to use the code object in a
7937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // register if there are multiple uses of it. Improve constant pool and the
7947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // heuristics in the register allocator for where to emit constants.
795ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  InitializeCallBuffer(call, &buffer, true, false);
7967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(dcarney): might be possible to use claim/poke instead
7987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Push any stack arguments.
799a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  for (NodeVectorRIter input = buffer.pushed_nodes.rbegin();
800a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org       input != buffer.pushed_nodes.rend(); input++) {
801a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    Emit(kArmPush, NULL, g.UseRegister(*input));
8027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Select the appropriate opcode based on the call type.
8057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionCode opcode;
8067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (descriptor->kind()) {
8077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case CallDescriptor::kCallCodeObject: {
8087b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      opcode = kArchCallCodeObject;
8097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
8107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
8117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case CallDescriptor::kCallJSFunction:
8127b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      opcode = kArchCallJSFunction;
8137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
8147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
8157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      UNREACHABLE();
8167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
8177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
818d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org  opcode |= MiscField::encode(descriptor->flags());
8197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Emit the call instruction.
8217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Instruction* call_instr =
822a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
823a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org           buffer.instruction_args.size(), &buffer.instruction_args.front());
8247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  call_instr->MarkAsCall();
8267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (deoptimization != NULL) {
827e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(continuation != NULL);
8287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    call_instr->MarkAsControl();
8297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
8317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
833e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.orgvoid InstructionSelector::VisitInt32AddWithOverflow(Node* node,
834e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                                                    FlagsContinuation* cont) {
835e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  VisitBinop(this, node, kArmAdd, kArmAdd, cont);
836e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org}
837e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
838e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
839e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.orgvoid InstructionSelector::VisitInt32SubWithOverflow(Node* node,
840e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                                                    FlagsContinuation* cont) {
841e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  VisitBinop(this, node, kArmSub, kArmRsb, cont);
842e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org}
843e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
844e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
8457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Shared routine for multiple compare operations.
8467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic void VisitWordCompare(InstructionSelector* selector, Node* node,
8477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                             InstructionCode opcode, FlagsContinuation* cont,
848e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                             bool commutative) {
8497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(selector);
8507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
8517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* inputs[5];
8527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  size_t input_count = 0;
8537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* outputs[1];
8547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  size_t output_count = 0;
8557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
8577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               &input_count, &inputs[1])) {
8587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    inputs[0] = g.UseRegister(m.left().node());
8597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    input_count++;
8607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
8617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                      &input_count, &inputs[1])) {
8627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (!commutative) cont->Commute();
8637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    inputs[0] = g.UseRegister(m.right().node());
8647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    input_count++;
8657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
8667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    opcode |= AddressingModeField::encode(kMode_Operand2_R);
8677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    inputs[input_count++] = g.UseRegister(m.left().node());
8687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    inputs[input_count++] = g.UseRegister(m.right().node());
8697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (cont->IsBranch()) {
8727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    inputs[input_count++] = g.Label(cont->true_block());
8737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    inputs[input_count++] = g.Label(cont->false_block());
8747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
875e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(cont->IsSet());
8767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    outputs[output_count++] = g.DefineAsRegister(cont->result());
8777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
879e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(0, input_count);
880fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK_GE(arraysize(inputs), input_count);
881fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK_GE(arraysize(outputs), output_count);
8827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
8847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                      outputs, input_count, inputs);
8857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (cont->IsBranch()) instr->MarkAsControl();
8867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
8877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) {
8907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (node->opcode()) {
8917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kInt32Add:
892e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      return VisitWordCompare(this, node, kArmCmn, cont, true);
8937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kInt32Sub:
894e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      return VisitWordCompare(this, node, kArmCmp, cont, false);
8957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kWord32And:
896e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      return VisitWordCompare(this, node, kArmTst, cont, true);
8977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kWord32Or:
898e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      return VisitBinop(this, node, kArmOrr, kArmOrr, cont);
8997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kWord32Xor:
900e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      return VisitWordCompare(this, node, kArmTeq, cont, true);
9015e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case IrOpcode::kWord32Sar:
9025e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      return VisitShift(this, node, TryMatchASR, cont);
9035e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case IrOpcode::kWord32Shl:
9045e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      return VisitShift(this, node, TryMatchLSL, cont);
9055e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case IrOpcode::kWord32Shr:
9065e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      return VisitShift(this, node, TryMatchLSR, cont);
9075e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case IrOpcode::kWord32Ror:
9085e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      return VisitShift(this, node, TryMatchROR, cont);
9097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
9107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
9117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
9127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
9147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionCode opcode =
9157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
9167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (cont->IsBranch()) {
9177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(opcode, NULL, g.UseRegister(node), g.UseRegister(node),
9187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.Label(cont->true_block()),
9197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.Label(cont->false_block()))->MarkAsControl();
9207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
9217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(opcode, g.DefineAsRegister(cont->result()), g.UseRegister(node),
9227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(node));
9237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
9247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
9257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Compare(Node* node,
9287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                             FlagsContinuation* cont) {
929e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  VisitWordCompare(this, node, kArmCmp, cont, false);
9307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
9317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Compare(Node* node,
9347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                              FlagsContinuation* cont) {
9357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArmOperandGenerator g(this);
9367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Float64BinopMatcher m(node);
9377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (cont->IsBranch()) {
938fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    Emit(cont->Encode(kArmVcmpF64), NULL, g.UseRegister(m.left().node()),
939fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.UseRegister(m.right().node()), g.Label(cont->true_block()),
9407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.Label(cont->false_block()))->MarkAsControl();
9417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
942e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(cont->IsSet());
9437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()),
944fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.UseRegister(m.left().node()), g.UseRegister(m.right().node()));
9457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
9467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
9477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace compiler
9497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace internal
9507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace v8
951