1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/adapters.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/instruction-selector-impl.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-matchers.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/node-properties.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Adds Arm-specific methods for generating InstructionOperands.
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass ArmOperandGenerator : public OperandGenerator {
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit ArmOperandGenerator(InstructionSelector* selector)
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : OperandGenerator(selector) {}
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool CanBeImmediate(int32_t value) const {
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return Assembler::ImmediateFitsAddrMode1Instruction(value);
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool CanBeImmediate(uint32_t value) const {
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return CanBeImmediate(bit_cast<int32_t>(value));
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool CanBeImmediate(Node* node, InstructionCode opcode) {
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Int32Matcher m(node);
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!m.HasValue()) return false;
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t value = m.Value();
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (ArchOpcodeField::decode(opcode)) {
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmAnd:
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmMov:
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmMvn:
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmBic:
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return CanBeImmediate(value) || CanBeImmediate(~value);
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmAdd:
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmSub:
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmCmp:
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmCmn:
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return CanBeImmediate(value) || CanBeImmediate(-value);
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmTst:
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmTeq:
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmOrr:
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmEor:
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmRsb:
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return CanBeImmediate(value);
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case kArmVldrF32:
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case kArmVstrF32:
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case kArmVldrF64:
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case kArmVstrF64:
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return value >= -1020 && value <= 1020 && (value % 4) == 0;
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmLdrb:
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmLdrsb:
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmStrb:
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmLdr:
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmStr:
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return value >= -4095 && value <= 4095;
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmLdrh:
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmLdrsh:
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kArmStrh:
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return value >= -255 && value <= 255;
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace {
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ArmOperandGenerator g(selector);
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  selector->Emit(opcode, g.DefineAsRegister(node),
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(node->InputAt(0)));
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(selector);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  selector->Emit(opcode, g.DefineAsRegister(node),
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 g.UseRegister(node->InputAt(0)),
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 g.UseRegister(node->InputAt(1)));
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <IrOpcode::Value kOpcode, int kImmMin, int kImmMax,
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          AddressingMode kImmMode, AddressingMode kRegMode>
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool TryMatchShift(InstructionSelector* selector,
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   InstructionCode* opcode_return, Node* node,
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   InstructionOperand* value_return,
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   InstructionOperand* shift_return) {
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(selector);
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (node->opcode() == kOpcode) {
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Int32BinopMatcher m(node);
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    *value_return = g.UseRegister(m.left().node());
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (m.right().IsInRange(kImmMin, kImmMax)) {
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      *opcode_return |= AddressingModeField::encode(kImmMode);
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      *shift_return = g.UseImmediate(m.right().node());
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      *opcode_return |= AddressingModeField::encode(kRegMode);
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      *shift_return = g.UseRegister(m.right().node());
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return true;
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return false;
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <IrOpcode::Value kOpcode, int kImmMin, int kImmMax,
11913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          AddressingMode kImmMode>
12013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool TryMatchShiftImmediate(InstructionSelector* selector,
12113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            InstructionCode* opcode_return, Node* node,
12213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            InstructionOperand* value_return,
12313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                            InstructionOperand* shift_return) {
12413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ArmOperandGenerator g(selector);
12513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (node->opcode() == kOpcode) {
12613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Int32BinopMatcher m(node);
12713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (m.right().IsInRange(kImmMin, kImmMax)) {
12813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      *opcode_return |= AddressingModeField::encode(kImmMode);
12913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      *value_return = g.UseRegister(m.left().node());
13013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      *shift_return = g.UseImmediate(m.right().node());
13113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return true;
13213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
13313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
13413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return false;
13513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool TryMatchROR(InstructionSelector* selector, InstructionCode* opcode_return,
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Node* node, InstructionOperand* value_return,
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 InstructionOperand* shift_return) {
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return TryMatchShift<IrOpcode::kWord32Ror, 1, 31, kMode_Operand2_R_ROR_I,
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       kMode_Operand2_R_ROR_R>(selector, opcode_return, node,
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                               value_return, shift_return);
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool TryMatchASR(InstructionSelector* selector, InstructionCode* opcode_return,
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Node* node, InstructionOperand* value_return,
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 InstructionOperand* shift_return) {
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return TryMatchShift<IrOpcode::kWord32Sar, 1, 32, kMode_Operand2_R_ASR_I,
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       kMode_Operand2_R_ASR_R>(selector, opcode_return, node,
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                               value_return, shift_return);
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool TryMatchLSL(InstructionSelector* selector, InstructionCode* opcode_return,
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Node* node, InstructionOperand* value_return,
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 InstructionOperand* shift_return) {
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return TryMatchShift<IrOpcode::kWord32Shl, 0, 31, kMode_Operand2_R_LSL_I,
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       kMode_Operand2_R_LSL_R>(selector, opcode_return, node,
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                               value_return, shift_return);
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
16313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool TryMatchLSLImmediate(InstructionSelector* selector,
16413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                          InstructionCode* opcode_return, Node* node,
16513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                          InstructionOperand* value_return,
16613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                          InstructionOperand* shift_return) {
16713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return TryMatchShiftImmediate<IrOpcode::kWord32Shl, 0, 31,
16813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                kMode_Operand2_R_LSL_I>(
16913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      selector, opcode_return, node, value_return, shift_return);
17013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool TryMatchLSR(InstructionSelector* selector, InstructionCode* opcode_return,
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Node* node, InstructionOperand* value_return,
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 InstructionOperand* shift_return) {
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return TryMatchShift<IrOpcode::kWord32Shr, 1, 32, kMode_Operand2_R_LSR_I,
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       kMode_Operand2_R_LSR_R>(selector, opcode_return, node,
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                               value_return, shift_return);
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool TryMatchShift(InstructionSelector* selector,
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   InstructionCode* opcode_return, Node* node,
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   InstructionOperand* value_return,
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   InstructionOperand* shift_return) {
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TryMatchASR(selector, opcode_return, node, value_return, shift_return) ||
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TryMatchLSL(selector, opcode_return, node, value_return, shift_return) ||
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TryMatchLSR(selector, opcode_return, node, value_return, shift_return) ||
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TryMatchROR(selector, opcode_return, node, value_return, shift_return));
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool TryMatchImmediateOrShift(InstructionSelector* selector,
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              InstructionCode* opcode_return, Node* node,
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              size_t* input_count_return,
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              InstructionOperand* inputs) {
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(selector);
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (g.CanBeImmediate(node, *opcode_return)) {
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *opcode_return |= AddressingModeField::encode(kMode_Operand2_I);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[0] = g.UseImmediate(node);
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *input_count_return = 1;
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) {
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *input_count_return = 2;
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid VisitBinop(InstructionSelector* selector, Node* node,
213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                InstructionCode opcode, InstructionCode reverse_opcode,
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                FlagsContinuation* cont) {
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(selector);
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Int32BinopMatcher m(node);
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand inputs[5];
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t input_count = 0;
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand outputs[2];
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t output_count = 0;
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (m.left().node() == m.right().node()) {
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If both inputs refer to the same operand, enforce allocating a register
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // for both of them to ensure that we don't end up generating code like
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // this:
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    //
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    //   mov r0, r1, asr #16
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    //   adds r0, r0, r1, asr #16
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    //   bvs label
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InstructionOperand const input = g.UseRegister(m.left().node());
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    opcode |= AddressingModeField::encode(kMode_Operand2_R);
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    inputs[input_count++] = input;
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    inputs[input_count++] = input;
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                      &input_count, &inputs[1])) {
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[0] = g.UseRegister(m.left().node());
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    input_count++;
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (TryMatchImmediateOrShift(selector, &reverse_opcode,
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      m.left().node(), &input_count,
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      &inputs[1])) {
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[0] = g.UseRegister(m.right().node());
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    opcode = reverse_opcode;
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    input_count++;
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    opcode |= AddressingModeField::encode(kMode_Operand2_R);
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.UseRegister(m.left().node());
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.UseRegister(m.right().node());
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cont->IsBranch()) {
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.Label(cont->true_block());
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.Label(cont->false_block());
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
255f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  outputs[output_count++] = g.DefineAsRegister(node);
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cont->IsSet()) {
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outputs[output_count++] = g.DefineAsRegister(cont->result());
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_NE(0u, input_count);
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_NE(0u, output_count);
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(arraysize(inputs), input_count);
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(arraysize(outputs), output_count);
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NE(kMode_None, AddressingModeField::decode(opcode));
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  opcode = cont->Encode(opcode);
2673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (cont->IsDeoptimize()) {
2683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             cont->reason(), cont->frame_state());
2703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
2713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    selector->Emit(opcode, output_count, outputs, input_count, inputs);
2723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid VisitBinop(InstructionSelector* selector, Node* node,
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                InstructionCode opcode, InstructionCode reverse_opcode) {
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagsContinuation cont;
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitBinop(selector, node, opcode, reverse_opcode, &cont);
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid EmitDiv(InstructionSelector* selector, ArchOpcode div_opcode,
284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode,
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             InstructionOperand result_operand, InstructionOperand left_operand,
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             InstructionOperand right_operand) {
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(selector);
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (selector->IsSupported(SUDIV)) {
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    selector->Emit(div_opcode, result_operand, left_operand, right_operand);
290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand left_double_operand = g.TempDoubleRegister();
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand right_double_operand = g.TempDoubleRegister();
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand result_double_operand = g.TempDoubleRegister();
295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  selector->Emit(f64i32_opcode, left_double_operand, left_operand);
296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  selector->Emit(f64i32_opcode, right_double_operand, right_operand);
297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  selector->Emit(kArmVdivF64, result_double_operand, left_double_operand,
298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 right_double_operand);
299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  selector->Emit(i32f64_opcode, result_operand, result_double_operand);
300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode div_opcode,
304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode) {
305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(selector);
306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Int32BinopMatcher m(node);
307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode,
308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          g.DefineAsRegister(node), g.UseRegister(m.left().node()),
309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          g.UseRegister(m.right().node()));
310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VisitMod(InstructionSelector* selector, Node* node, ArchOpcode div_opcode,
314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode) {
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(selector);
316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Int32BinopMatcher m(node);
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand div_operand = g.TempRegister();
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand result_operand = g.DefineAsRegister(node);
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand left_operand = g.UseRegister(m.left().node());
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand right_operand = g.UseRegister(m.right().node());
321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode, div_operand,
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          left_operand, right_operand);
32313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (selector->IsSupported(ARMv7)) {
324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    selector->Emit(kArmMls, result_operand, div_operand, right_operand,
325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   left_operand);
326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InstructionOperand mul_operand = g.TempRegister();
328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    selector->Emit(kArmMul, mul_operand, div_operand, right_operand);
32913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    selector->Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R),
33013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                   result_operand, left_operand, mul_operand);
331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid EmitLoad(InstructionSelector* selector, InstructionCode opcode,
335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              InstructionOperand* output, Node* base, Node* index) {
336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ArmOperandGenerator g(selector);
337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand inputs[3];
338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t input_count = 2;
339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  inputs[0] = g.UseRegister(base);
341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (g.CanBeImmediate(index, opcode)) {
342f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    inputs[1] = g.UseImmediate(index);
343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    opcode |= AddressingModeField::encode(kMode_Offset_RI);
344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if ((opcode == kArmLdr) &&
345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch             TryMatchLSLImmediate(selector, &opcode, index, &inputs[1],
346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  &inputs[2])) {
347f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    input_count = 3;
348f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    inputs[1] = g.UseRegister(index);
350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    opcode |= AddressingModeField::encode(kMode_Offset_RR);
351f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
352f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  selector->Emit(opcode, 1, output, input_count, inputs);
353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid EmitStore(InstructionSelector* selector, InstructionCode opcode,
356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               size_t input_count, InstructionOperand* inputs,
357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Node* index) {
358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ArmOperandGenerator g(selector);
359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (g.CanBeImmediate(index, opcode)) {
361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    inputs[input_count++] = g.UseImmediate(index);
362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    opcode |= AddressingModeField::encode(kMode_Offset_RI);
363f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if ((opcode == kArmStr) &&
364f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch             TryMatchLSLImmediate(selector, &opcode, index, &inputs[2],
365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  &inputs[3])) {
366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    input_count = 4;
367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    inputs[input_count++] = g.UseRegister(index);
369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    opcode |= AddressingModeField::encode(kMode_Offset_RR);
370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  selector->Emit(opcode, 0, nullptr, input_count, inputs);
372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace
375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitLoad(Node* node) {
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* base = node->InputAt(0);
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* index = node->InputAt(1);
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
38313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InstructionCode opcode = kArchNop;
384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (load_rep.representation()) {
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kFloat32:
386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kArmVldrF32;
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kFloat64:
389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kArmVldrF64;
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kBit:  // Fall through.
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord8:
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      opcode = load_rep.IsUnsigned() ? kArmLdrb : kArmLdrsb;
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord16:
396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      opcode = load_rep.IsUnsigned() ? kArmLdrh : kArmLdrsh;
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kTaggedSigned:   // Fall through.
399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kTaggedPointer:  // Fall through.
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kTagged:  // Fall through.
401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord32:
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      opcode = kArmLdr;
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kWord64:   // Fall through.
405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kSimd128:  // Fall through.
406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kNone:
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
411f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand output = g.DefineAsRegister(node);
412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EmitLoad(this, opcode, &output, base, index);
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
415f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid InstructionSelector::VisitProtectedLoad(Node* node) {
416f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // TODO(eholk)
417f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  UNIMPLEMENTED();
418f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitStore(Node* node) {
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* base = node->InputAt(0);
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* index = node->InputAt(1);
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* value = node->InputAt(2);
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StoreRepresentation store_rep = StoreRepresentationOf(node->op());
427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind();
428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MachineRepresentation rep = store_rep.representation();
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (write_barrier_kind != kNoWriteBarrier) {
431f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(CanBeTaggedPointer(rep));
432109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AddressingMode addressing_mode;
433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InstructionOperand inputs[3];
434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t input_count = 0;
435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    inputs[input_count++] = g.UseUniqueRegister(base);
436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // OutOfLineRecordWrite uses the index in an 'add' instruction as well as
437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // for the store itself, so we must check compatibility with both.
438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (g.CanBeImmediate(index, kArmAdd) && g.CanBeImmediate(index, kArmStr)) {
439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      inputs[input_count++] = g.UseImmediate(index);
440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      addressing_mode = kMode_Offset_RI;
441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else {
442109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      inputs[input_count++] = g.UseUniqueRegister(index);
443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      addressing_mode = kMode_Offset_RR;
444109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
4453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    inputs[input_count++] = g.UseUniqueRegister(value);
446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny;
447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (write_barrier_kind) {
448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kNoWriteBarrier:
449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNREACHABLE();
450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kMapWriteBarrier:
452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        record_write_mode = RecordWriteMode::kValueIsMap;
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kPointerWriteBarrier:
455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        record_write_mode = RecordWriteMode::kValueIsPointer;
456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kFullWriteBarrier:
458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        record_write_mode = RecordWriteMode::kValueIsAny;
459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t const temp_count = arraysize(temps);
463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InstructionCode code = kArchStoreWithWriteBarrier;
464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    code |= AddressingModeField::encode(addressing_mode);
465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    code |= MiscField::encode(static_cast<int>(record_write_mode));
466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
46813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    InstructionCode opcode = kArchNop;
469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (rep) {
470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case MachineRepresentation::kFloat32:
471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        opcode = kArmVstrF32;
472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case MachineRepresentation::kFloat64:
474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        opcode = kArmVstrF64;
475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case MachineRepresentation::kBit:  // Fall through.
477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case MachineRepresentation::kWord8:
478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        opcode = kArmStrb;
479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case MachineRepresentation::kWord16:
481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        opcode = kArmStrh;
482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case MachineRepresentation::kTaggedSigned:   // Fall through.
484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case MachineRepresentation::kTaggedPointer:  // Fall through.
485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case MachineRepresentation::kTagged:  // Fall through.
486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case MachineRepresentation::kWord32:
487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        opcode = kArmStr;
488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
489109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case MachineRepresentation::kWord64:   // Fall through.
490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case MachineRepresentation::kSimd128:  // Fall through.
491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case MachineRepresentation::kNone:
492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNREACHABLE();
493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return;
494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
496f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    InstructionOperand inputs[4];
497f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    size_t input_count = 0;
498f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    inputs[input_count++] = g.UseRegister(value);
499f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    inputs[input_count++] = g.UseRegister(base);
500f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    EmitStore(this, opcode, input_count, inputs, index);
501f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
502f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
50313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid InstructionSelector::VisitUnalignedLoad(Node* node) {
505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  UnalignedLoadRepresentation load_rep =
506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UnalignedLoadRepresentationOf(node->op());
507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ArmOperandGenerator g(this);
508f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* base = node->InputAt(0);
509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* index = node->InputAt(1);
510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionCode opcode = kArmLdr;
512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Only floating point loads need to be specially handled; integer loads
513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // support unaligned access. We support unaligned FP loads by loading to
514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // integer registers first, then moving to the destination FP register.
515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (load_rep.representation()) {
516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kFloat32: {
517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      InstructionOperand temp = g.TempRegister();
518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      EmitLoad(this, opcode, &temp, base, index);
519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp);
520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return;
521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kFloat64: {
523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // TODO(arm): use vld1.8 for this when NEON is available.
524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Compute the address of the least-significant half of the FP value.
525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // We assume that the base node is unlikely to be an encodable immediate
526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // or the result of a shift operation, so only consider the addressing
527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // mode that should be used for the index node.
528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      InstructionCode add_opcode = kArmAdd;
529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      InstructionOperand inputs[3];
530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[0] = g.UseRegister(base);
531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      size_t input_count;
533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count,
534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                   &inputs[1])) {
535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // input_count has been set by TryMatchImmediateOrShift(), so increment
536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // it to account for the base register in inputs[0].
537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        input_count++;
538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      } else {
539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        add_opcode |= AddressingModeField::encode(kMode_Operand2_R);
540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        inputs[1] = g.UseRegister(index);
541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        input_count = 2;  // Base register and index.
542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      InstructionOperand addr = g.TempRegister();
545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Emit(add_opcode, 1, &addr, input_count, inputs);
546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Load both halves and move to an FP register.
548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      InstructionOperand fp_lo = g.TempRegister();
549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      InstructionOperand fp_hi = g.TempRegister();
55013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      opcode |= AddressingModeField::encode(kMode_Offset_RI);
551f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Emit(opcode, fp_lo, addr, g.TempImmediate(0));
552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Emit(opcode, fp_hi, addr, g.TempImmediate(4));
553f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi);
554f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return;
555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    default:
557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // All other cases should support unaligned accesses.
558f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
559f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return;
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid InstructionSelector::VisitUnalignedStore(Node* node) {
564f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ArmOperandGenerator g(this);
565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* base = node->InputAt(0);
566f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* index = node->InputAt(1);
567f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(2);
568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand inputs[4];
570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t input_count = 0;
571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  UnalignedStoreRepresentation store_rep =
573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UnalignedStoreRepresentationOf(node->op());
574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Only floating point stores need to be specially handled; integer stores
576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // support unaligned access. We support unaligned FP stores by moving the
577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // value to integer registers first, then storing to the destination address.
578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (store_rep) {
579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kFloat32: {
580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[input_count++] = g.TempRegister();
581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value));
582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[input_count++] = g.UseRegister(base);
583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      EmitStore(this, kArmStr, input_count, inputs, index);
584f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return;
585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kFloat64: {
587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // TODO(arm): use vst1.8 for this when NEON is available.
588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Store a 64-bit floating point value using two 32-bit integer stores.
589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Computing the store address here would require three live temporary
590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after
591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // storing the least-significant half of the value.
592f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // First, move the 64-bit FP value into two temporary integer registers.
594f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()};
595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[input_count++] = g.UseRegister(value);
596f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count,
597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch           inputs);
598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Store the least-significant half.
600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[0] = fp[0];  // Low 32-bits of FP value.
601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[input_count++] = g.UseRegister(base);  // First store base address.
602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      EmitStore(this, kArmStr, input_count, inputs, index);
603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Store the most-significant half.
605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      InstructionOperand base4 = g.TempRegister();
606f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4,
607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch           g.UseRegister(base), g.TempImmediate(4));  // Compute base + 4.
608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[0] = fp[1];  // High 32-bits of FP value.
609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[1] = base4;  // Second store base + 4 address.
610f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      EmitStore(this, kArmStr, input_count, inputs, index);
611f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return;
612f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    default:
614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // All other cases should support unaligned accesses.
615f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
616f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return;
617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitCheckedLoad(Node* node) {
621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op());
622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ArmOperandGenerator g(this);
623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const buffer = node->InputAt(0);
624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const offset = node->InputAt(1);
625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const length = node->InputAt(2);
626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArchOpcode opcode = kArchNop;
627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (load_rep.representation()) {
628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord8:
629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8;
630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord16:
632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      opcode = load_rep.IsSigned() ? kCheckedLoadInt16 : kCheckedLoadUint16;
633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord32:
635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kCheckedLoadWord32;
636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kFloat32:
638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kCheckedLoadFloat32;
639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kFloat64:
641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kCheckedLoadFloat64;
642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
643109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kBit:      // Fall through.
644f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kTaggedSigned:   // Fall through.
645f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kTaggedPointer:  // Fall through.
646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kTagged:   // Fall through.
647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kWord64:   // Fall through.
648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kSimd128:  // Fall through.
649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kNone:
650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      UNREACHABLE();
651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return;
652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand offset_operand = g.UseRegister(offset);
654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp)
655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ? g.UseImmediate(length)
656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          : g.UseRegister(length);
657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       g.DefineAsRegister(node), offset_operand, length_operand,
659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       g.UseRegister(buffer), offset_operand);
660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitCheckedStore(Node* node) {
664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MachineRepresentation rep = CheckedStoreRepresentationOf(node->op());
665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ArmOperandGenerator g(this);
666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const buffer = node->InputAt(0);
667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const offset = node->InputAt(1);
668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const length = node->InputAt(2);
669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Node* const value = node->InputAt(3);
670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArchOpcode opcode = kArchNop;
671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  switch (rep) {
672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord8:
673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kCheckedStoreWord8;
674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord16:
676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kCheckedStoreWord16;
677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kWord32:
679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kCheckedStoreWord32;
680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kFloat32:
682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kCheckedStoreFloat32;
683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kFloat64:
685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      opcode = kCheckedStoreFloat64;
686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
687109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kBit:      // Fall through.
688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kTaggedSigned:   // Fall through.
689f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case MachineRepresentation::kTaggedPointer:  // Fall through.
690109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kTagged:   // Fall through.
691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kWord64:   // Fall through.
692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case MachineRepresentation::kSimd128:  // Fall through.
693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case MachineRepresentation::kNone:
694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      UNREACHABLE();
695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return;
696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand offset_operand = g.UseRegister(offset);
698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp)
699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ? g.UseImmediate(length)
700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          : g.UseRegister(length);
701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), g.NoOutput(),
702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       offset_operand, length_operand, g.UseRegister(value),
703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       g.UseRegister(buffer), offset_operand);
704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace {
708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid EmitBic(InstructionSelector* selector, Node* node, Node* left,
710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             Node* right) {
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(selector);
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionCode opcode = kArmBic;
713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand value_operand;
714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand shift_operand;
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) {
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   value_operand, shift_operand);
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 g.DefineAsRegister(node), g.UseRegister(left),
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 g.UseRegister(right));
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid EmitUbfx(InstructionSelector* selector, Node* node, Node* left,
727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              uint32_t lsb, uint32_t width) {
728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(1u, width);
729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(width, 32u - lsb);
730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ArmOperandGenerator g(selector);
731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  selector->Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(left),
732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.TempImmediate(lsb), g.TempImmediate(width));
733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace
736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32And(Node* node) {
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Int32BinopMatcher m(node);
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) {
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Int32BinopMatcher mleft(m.left().node());
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (mleft.right().Is(-1)) {
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBic(this, node, m.right().node(), mleft.left().node());
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) {
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Int32BinopMatcher mright(m.right().node());
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (mright.right().Is(-1)) {
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBic(this, node, m.left().node(), mright.left().node());
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (m.right().HasValue()) {
756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    uint32_t const value = m.right().Value();
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t width = base::bits::CountPopulation32(value);
758109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    uint32_t leading_zeros = base::bits::CountLeadingZeros32(value);
759109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
760109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Try to merge SHR operations on the left hand input into this AND.
761109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (m.left().IsWord32Shr()) {
762109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Int32BinopMatcher mshr(m.left().node());
763109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      if (mshr.right().HasValue()) {
764109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        uint32_t const shift = mshr.right().Value();
765109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
766109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        if (((shift == 8) || (shift == 16) || (shift == 24)) &&
767109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            ((value == 0xff) || (value == 0xffff))) {
768109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          // Merge SHR into AND by emitting a UXTB or UXTH instruction with a
769109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          // bytewise rotation.
770109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          Emit((value == 0xff) ? kArmUxtb : kArmUxth,
771109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch               g.DefineAsRegister(m.node()), g.UseRegister(mshr.left().node()),
772109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch               g.TempImmediate(mshr.right().Value()));
773109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          return;
774109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        } else if (IsSupported(ARMv7) && (width != 0) &&
775109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                   ((leading_zeros + width) == 32)) {
776109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          // Merge Shr into And by emitting a UBFX instruction.
777109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value));
778109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          if ((1 <= shift) && (shift <= 31)) {
779109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            // UBFX cannot extract bits past the register size, however since
780109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            // shifting the original value would have introduced some zeros we
781109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            // can still use UBFX with a smaller mask and the remaining bits
782109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            // will be zeros.
783109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            EmitUbfx(this, node, mshr.left().node(), shift,
784109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                     std::min(width, 32 - shift));
785109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            return;
786109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          }
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
789109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (value == 0xffff) {
790109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      // Emit UXTH for this AND. We don't bother testing for UXTB, as it's no
791109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      // better than AND 0xff for this operation.
792109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Emit(kArmUxth, g.DefineAsRegister(m.node()),
793109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch           g.UseRegister(m.left().node()), g.TempImmediate(0));
794109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return;
795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (g.CanBeImmediate(~value)) {
797109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      // Emit BIC for this AND by inverting the immediate value first.
798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I),
799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           g.DefineAsRegister(node), g.UseRegister(m.left().node()),
800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           g.TempImmediate(~value));
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
803109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!g.CanBeImmediate(value) && IsSupported(ARMv7)) {
804109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      // If value has 9 to 23 contiguous set bits, and has the lsb set, we can
805109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      // replace this AND with UBFX. Other contiguous bit patterns have already
806109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      // been handled by BIC or will be handled by AND.
807109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      if ((width != 0) && ((leading_zeros + width) == 32) &&
808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          (9 <= leading_zeros) && (leading_zeros <= 23)) {
809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value));
810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        EmitUbfx(this, node, m.left().node(), 0, width);
811109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return;
812109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
813109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      width = 32 - width;
815109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      leading_zeros = base::bits::CountLeadingZeros32(~value);
816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      uint32_t lsb = base::bits::CountTrailingZeros32(~value);
817109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      if ((leading_zeros + width + lsb) == 32) {
818109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        // This AND can be replaced with BFC.
819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.TempImmediate(lsb), g.TempImmediate(width));
821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return;
822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitBinop(this, node, kArmAnd, kArmAnd);
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Or(Node* node) {
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitBinop(this, node, kArmOrr, kArmOrr);
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Xor(Node* node) {
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Int32BinopMatcher m(node);
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (m.right().Is(-1)) {
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InstructionCode opcode = kArmMvn;
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InstructionOperand value_operand;
840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InstructionOperand shift_operand;
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (TryMatchShift(this, &opcode, m.left().node(), &value_operand,
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      &shift_operand)) {
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand);
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         g.DefineAsRegister(node), g.UseRegister(m.left().node()));
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitBinop(this, node, kArmEor, kArmEor);
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace {
855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename TryMatchShift>
857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VisitShift(InstructionSelector* selector, Node* node,
858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                TryMatchShift try_match_shift, FlagsContinuation* cont) {
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(selector);
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionCode opcode = kArmMov;
861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand inputs[4];
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t input_count = 2;
863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand outputs[2];
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t output_count = 0;
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1]));
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cont->IsBranch()) {
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.Label(cont->true_block());
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.Label(cont->false_block());
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  outputs[output_count++] = g.DefineAsRegister(node);
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cont->IsSet()) {
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outputs[output_count++] = g.DefineAsRegister(cont->result());
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_NE(0u, input_count);
879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_NE(0u, output_count);
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(arraysize(inputs), input_count);
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(arraysize(outputs), output_count);
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NE(kMode_None, AddressingModeField::decode(opcode));
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  opcode = cont->Encode(opcode);
8853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (cont->IsDeoptimize()) {
8863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
887f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             cont->reason(), cont->frame_state());
8883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
8893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    selector->Emit(opcode, output_count, outputs, input_count, inputs);
8903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename TryMatchShift>
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VisitShift(InstructionSelector* selector, Node* node,
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              TryMatchShift try_match_shift) {
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagsContinuation cont;
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitShift(selector, node, try_match_shift, &cont);
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace
902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Shl(Node* node) {
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitShift(this, node, TryMatchLSL);
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Shr(Node* node) {
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Int32BinopMatcher m(node);
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsSupported(ARMv7) && m.left().IsWord32And() &&
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      m.right().IsInRange(0, 31)) {
914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t lsb = m.right().Value();
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Int32BinopMatcher mleft(m.left().node());
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (mleft.right().HasValue()) {
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      uint32_t value = (mleft.right().Value() >> lsb) << lsb;
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      uint32_t width = base::bits::CountPopulation32(value);
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      uint32_t msb = base::bits::CountLeadingZeros32(value);
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (msb + width + lsb == 32) {
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value));
922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return EmitUbfx(this, node, mleft.left().node(), lsb, width);
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitShift(this, node, TryMatchLSR);
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Sar(Node* node) {
931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ArmOperandGenerator g(this);
932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Int32BinopMatcher m(node);
933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) {
934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Int32BinopMatcher mleft(m.left().node());
935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (m.right().HasValue() && mleft.right().HasValue()) {
936109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      uint32_t sar = m.right().Value();
937109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      uint32_t shl = mleft.right().Value();
938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      if ((sar == shl) && (sar == 16)) {
939109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        Emit(kArmSxth, g.DefineAsRegister(node),
940109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch             g.UseRegister(mleft.left().node()), g.TempImmediate(0));
941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return;
942109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      } else if ((sar == shl) && (sar == 24)) {
943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        Emit(kArmSxtb, g.DefineAsRegister(node),
944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch             g.UseRegister(mleft.left().node()), g.TempImmediate(0));
945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return;
946109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      } else if (IsSupported(ARMv7) && (sar >= shl)) {
947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        Emit(kArmSbfx, g.DefineAsRegister(node),
948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch             g.UseRegister(mleft.left().node()), g.TempImmediate(sar - shl),
949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch             g.TempImmediate(32 - sar));
950109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return;
951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitShift(this, node, TryMatchASR);
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid InstructionSelector::VisitInt32PairAdd(Node* node) {
9583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  ArmOperandGenerator g(this);
9593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
960c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* projection1 = NodeProperties::FindProjection(node, 1);
961c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (projection1) {
962c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // We use UseUniqueRegister here to avoid register sharing with the output
963c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // registers.
964c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    InstructionOperand inputs[] = {
965c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
966c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};
967c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
968c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    InstructionOperand outputs[] = {
969c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.DefineAsRegister(node),
970c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
971c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
972c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Emit(kArmAddPair, 2, outputs, 4, inputs);
973c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
974c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // The high word of the result is not used, so we emit the standard 32 bit
975c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // instruction.
976c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_R),
977c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch         g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
978c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch         g.UseRegister(node->InputAt(2)));
979c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
9803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
9813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
9823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid InstructionSelector::VisitInt32PairSub(Node* node) {
9833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  ArmOperandGenerator g(this);
9843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
985c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* projection1 = NodeProperties::FindProjection(node, 1);
986c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (projection1) {
987c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // We use UseUniqueRegister here to avoid register sharing with the output
988c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // register.
989c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    InstructionOperand inputs[] = {
990c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
991c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};
9923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
993c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    InstructionOperand outputs[] = {
994c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.DefineAsRegister(node),
995c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
9963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
997c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Emit(kArmSubPair, 2, outputs, 4, inputs);
998c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
999c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // The high word of the result is not used, so we emit the standard 32 bit
1000c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // instruction.
1001c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R),
1002c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch         g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
1003c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch         g.UseRegister(node->InputAt(2)));
1004c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
10053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
10063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
10073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid InstructionSelector::VisitInt32PairMul(Node* node) {
10083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  ArmOperandGenerator g(this);
1009c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* projection1 = NodeProperties::FindProjection(node, 1);
1010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (projection1) {
1011c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
1012c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   g.UseUniqueRegister(node->InputAt(1)),
1013c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   g.UseUniqueRegister(node->InputAt(2)),
1014c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   g.UseUniqueRegister(node->InputAt(3))};
1015c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1016c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    InstructionOperand outputs[] = {
1017c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.DefineAsRegister(node),
1018c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
1019c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1020c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Emit(kArmMulPair, 2, outputs, 4, inputs);
10213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
1022c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // The high word of the result is not used, so we emit the standard 32 bit
1023c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // instruction.
1024c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Emit(kArmMul | AddressingModeField::encode(kMode_Operand2_R),
1025c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch         g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
1026c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch         g.UseRegister(node->InputAt(2)));
10273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
10283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
10293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace {
1031c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Shared routine for multiple shift operations.
1032c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid VisitWord32PairShift(InstructionSelector* selector, InstructionCode opcode,
1033c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                          Node* node) {
1034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ArmOperandGenerator g(selector);
1035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // We use g.UseUniqueRegister here to guarantee that there is
1036c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // no register aliasing of input registers with output registers.
10373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Int32Matcher m(node->InputAt(2));
10383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InstructionOperand shift_operand;
10393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (m.HasValue()) {
10403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shift_operand = g.UseImmediate(m.node());
10413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
10423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    shift_operand = g.UseUniqueRegister(m.node());
10433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
10443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1045c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
10463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 g.UseUniqueRegister(node->InputAt(1)),
10473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 shift_operand};
10483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1049c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* projection1 = NodeProperties::FindProjection(node, 1);
10503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1051c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  InstructionOperand outputs[2];
1052c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  InstructionOperand temps[1];
1053c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int32_t output_count = 0;
1054c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int32_t temp_count = 0;
10553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1056c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  outputs[output_count++] = g.DefineAsRegister(node);
1057c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (projection1) {
1058c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    outputs[output_count++] = g.DefineAsRegister(projection1);
10593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
1060c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    temps[temp_count++] = g.TempRegister();
10613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
10623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1063c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  selector->Emit(opcode, output_count, outputs, 3, inputs, temp_count, temps);
1064c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1065c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}  // namespace
1066c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid InstructionSelector::VisitWord32PairShl(Node* node) {
1067c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  VisitWord32PairShift(this, kArmLslPair, node);
1068c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
10693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1070c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid InstructionSelector::VisitWord32PairShr(Node* node) {
1071c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  VisitWord32PairShift(this, kArmLsrPair, node);
1072c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
10733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1074c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid InstructionSelector::VisitWord32PairSar(Node* node) {
1075c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  VisitWord32PairShift(this, kArmAsrPair, node);
10763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Ror(Node* node) {
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitShift(this, node, TryMatchROR);
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitWord32Clz(Node* node) {
1084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmClz, node);
1085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1091109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InstructionSelector::VisitWord32ReverseBits(Node* node) {
1092109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(IsSupported(ARMv7));
1093109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  VisitRR(this, kArmRbit, node);
1094109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1095109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); }
1097f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }
1099109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Add(Node* node) {
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Int32BinopMatcher m(node);
1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (CanCover(node, m.left().node())) {
1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (m.left().opcode()) {
1108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kInt32Mul: {
1109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Int32BinopMatcher mleft(m.left().node());
1110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Emit(kArmMla, g.DefineAsRegister(node),
1111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(mleft.left().node()),
1112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(mleft.right().node()),
1113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(m.right().node()));
1114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return;
1115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kInt32MulHigh: {
1117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Int32BinopMatcher mleft(m.left().node());
1118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Emit(kArmSmmla, g.DefineAsRegister(node),
1119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(mleft.left().node()),
1120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(mleft.right().node()),
1121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(m.right().node()));
1122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return;
1123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32And: {
1125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Int32BinopMatcher mleft(m.left().node());
1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (mleft.right().Is(0xff)) {
1127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Emit(kArmUxtab, g.DefineAsRegister(node),
1128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               g.UseRegister(m.right().node()),
1129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               g.UseRegister(mleft.left().node()), g.TempImmediate(0));
1130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          return;
1131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else if (mleft.right().Is(0xffff)) {
1132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Emit(kArmUxtah, g.DefineAsRegister(node),
1133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               g.UseRegister(m.right().node()),
1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               g.UseRegister(mleft.left().node()), g.TempImmediate(0));
1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          return;
1136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
1137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32Sar: {
1139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Int32BinopMatcher mleft(m.left().node());
1140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (CanCover(mleft.node(), mleft.left().node()) &&
1141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            mleft.left().IsWord32Shl()) {
1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Int32BinopMatcher mleftleft(mleft.left().node());
1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          if (mleft.right().Is(24) && mleftleft.right().Is(24)) {
1144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            Emit(kArmSxtab, g.DefineAsRegister(node),
1145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(m.right().node()),
1146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(mleftleft.left().node()), g.TempImmediate(0));
1147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            return;
1148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (mleft.right().Is(16) && mleftleft.right().Is(16)) {
1149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            Emit(kArmSxtah, g.DefineAsRegister(node),
1150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(m.right().node()),
1151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(mleftleft.left().node()), g.TempImmediate(0));
1152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            return;
1153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          }
1154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
1157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (CanCover(node, m.right().node())) {
1161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (m.right().opcode()) {
1162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kInt32Mul: {
1163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Int32BinopMatcher mright(m.right().node());
1164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Emit(kArmMla, g.DefineAsRegister(node),
1165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(mright.left().node()),
1166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(mright.right().node()),
1167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(m.left().node()));
1168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return;
1169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kInt32MulHigh: {
1171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Int32BinopMatcher mright(m.right().node());
1172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Emit(kArmSmmla, g.DefineAsRegister(node),
1173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(mright.left().node()),
1174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(mright.right().node()),
1175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             g.UseRegister(m.left().node()));
1176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return;
1177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32And: {
1179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Int32BinopMatcher mright(m.right().node());
1180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (mright.right().Is(0xff)) {
1181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Emit(kArmUxtab, g.DefineAsRegister(node),
1182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               g.UseRegister(m.left().node()),
1183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               g.UseRegister(mright.left().node()), g.TempImmediate(0));
1184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          return;
1185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else if (mright.right().Is(0xffff)) {
1186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Emit(kArmUxtah, g.DefineAsRegister(node),
1187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               g.UseRegister(m.left().node()),
1188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               g.UseRegister(mright.left().node()), g.TempImmediate(0));
1189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          return;
1190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
1191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32Sar: {
1193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Int32BinopMatcher mright(m.right().node());
1194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (CanCover(mright.node(), mright.left().node()) &&
1195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            mright.left().IsWord32Shl()) {
1196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Int32BinopMatcher mrightleft(mright.left().node());
1197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          if (mright.right().Is(24) && mrightleft.right().Is(24)) {
1198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            Emit(kArmSxtab, g.DefineAsRegister(node),
1199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(m.left().node()),
1200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(mrightleft.left().node()), g.TempImmediate(0));
1201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            return;
1202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (mright.right().Is(16) && mrightleft.right().Is(16)) {
1203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            Emit(kArmSxtah, g.DefineAsRegister(node),
1204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(m.left().node()),
1205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 g.UseRegister(mrightleft.left().node()), g.TempImmediate(0));
1206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            return;
1207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          }
1208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
1209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
1211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitBinop(this, node, kArmAdd, kArmAdd);
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Sub(Node* node) {
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Int32BinopMatcher m(node);
122113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (IsSupported(ARMv7) && m.right().IsInt32Mul() &&
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CanCover(node, m.right().node())) {
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Int32BinopMatcher mright(m.right().node());
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()),
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         g.UseRegister(mright.right().node()), g.UseRegister(m.left().node()));
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitBinop(this, node, kArmSub, kArmRsb);
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace {
1232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid EmitInt32MulWithOverflow(InstructionSelector* selector, Node* node,
1234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                              FlagsContinuation* cont) {
1235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ArmOperandGenerator g(selector);
1236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Int32BinopMatcher m(node);
1237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand result_operand = g.DefineAsRegister(node);
1238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand temp_operand = g.TempRegister();
1239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand outputs[] = {result_operand, temp_operand};
1240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand inputs[] = {g.UseRegister(m.left().node()),
1241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                 g.UseRegister(m.right().node())};
1242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  selector->Emit(kArmSmull, 2, outputs, 2, inputs);
1243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // result operand needs shift operator.
1245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand shift_31 = g.UseImmediate(31);
1246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionCode opcode = cont->Encode(kArmCmp) |
1247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           AddressingModeField::encode(kMode_Operand2_R_ASR_I);
1248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (cont->IsBranch()) {
1249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    selector->Emit(opcode, g.NoOutput(), temp_operand, result_operand, shift_31,
1250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   g.Label(cont->true_block()), g.Label(cont->false_block()));
1251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (cont->IsDeoptimize()) {
1252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    InstructionOperand in[] = {temp_operand, result_operand, shift_31};
1253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    selector->EmitDeoptimize(opcode, 0, nullptr, 3, in, cont->reason(),
1254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             cont->frame_state());
1255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
1256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(cont->IsSet());
1257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    selector->Emit(opcode, g.DefineAsRegister(cont->result()), temp_operand,
1258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   result_operand, shift_31);
1259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Mul(Node* node) {
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Int32BinopMatcher m(node);
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (m.right().HasValue() && m.right().Value() > 0) {
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t value = m.right().Value();
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (base::bits::IsPowerOfTwo32(value - 1)) {
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           g.DefineAsRegister(node), g.UseRegister(m.left().node()),
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           g.UseRegister(m.left().node()),
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           g.TempImmediate(WhichPowerOf2(value - 1)));
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (value < kMaxInt && base::bits::IsPowerOfTwo32(value + 1)) {
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Emit(kArmRsb | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           g.DefineAsRegister(node), g.UseRegister(m.left().node()),
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           g.UseRegister(m.left().node()),
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           g.TempImmediate(WhichPowerOf2(value + 1)));
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRRR(this, kArmMul, node);
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitInt32MulHigh(Node* node) {
1289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRRR(this, kArmSmmul, node);
1290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitUint32MulHigh(Node* node) {
1294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ArmOperandGenerator g(this);
1295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand outputs[] = {g.TempRegister(), g.DefineAsRegister(node)};
1296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0)),
1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 g.UseRegister(node->InputAt(1))};
1298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Emit(kArmUmull, arraysize(outputs), outputs, arraysize(inputs), inputs);
1299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Div(Node* node) {
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitDiv(this, node, kArmSdiv, kArmVcvtF64S32, kArmVcvtS32F64);
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitUint32Div(Node* node) {
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitDiv(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64);
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Mod(Node* node) {
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitMod(this, node, kArmSdiv, kArmVcvtF64S32, kArmVcvtS32F64);
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitUint32Mod(Node* node) {
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitMod(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64);
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) {
1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVcvtF64F32, node);
1324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1327109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
1328109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  VisitRR(this, kArmVcvtF32S32, node);
1329109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1331109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1332109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
1333109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  VisitRR(this, kArmVcvtF32U32, node);
1334109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1335109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
1338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVcvtF64S32, node);
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
1343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVcvtF64U32, node);
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
1348109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  VisitRR(this, kArmVcvtS32F32, node);
1349109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1350109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1351109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InstructionSelector::VisitTruncateFloat32ToUint32(Node* node) {
1353109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  VisitRR(this, kArmVcvtU32F32, node);
1354109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1355109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1356109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
1358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVcvtS32F64, node);
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
1363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVcvtU32F64, node);
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid InstructionSelector::VisitTruncateFloat64ToUint32(Node* node) {
13673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  VisitRR(this, kArmVcvtU32F64, node);
13683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
1370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVcvtF32F64, node);
1371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
1374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  VisitRR(this, kArchTruncateDoubleToI, node);
1375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
1378bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  VisitRR(this, kArmVcvtS32F64, node);
1379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
138213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  VisitRR(this, kArmVmovU32F32, node);
1383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
138613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  VisitRR(this, kArmVmovF32U32, node);
1387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32Add(Node* node) {
1390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(this);
1391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Float32BinopMatcher m(node);
1392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (m.left().IsFloat32Mul() && CanCover(node, m.left().node())) {
1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Float32BinopMatcher mleft(m.left().node());
1394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Emit(kArmVmlaF32, g.DefineSameAsFirst(node),
1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()),
1396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         g.UseRegister(mleft.right().node()));
1397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
1398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (m.right().IsFloat32Mul() && CanCover(node, m.right().node())) {
1400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Float32BinopMatcher mright(m.right().node());
1401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Emit(kArmVmlaF32, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
1402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         g.UseRegister(mright.left().node()),
1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         g.UseRegister(mright.right().node()));
1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRRR(this, kArmVaddF32, node);
1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Add(Node* node) {
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
1412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Float64BinopMatcher m(node);
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (m.left().IsFloat64Mul() && CanCover(node, m.left().node())) {
1414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Float64BinopMatcher mleft(m.left().node());
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Emit(kArmVmlaF64, g.DefineSameAsFirst(node),
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()),
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         g.UseRegister(mleft.right().node()));
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
1421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Float64BinopMatcher mright(m.right().node());
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Emit(kArmVmlaF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         g.UseRegister(mright.left().node()),
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         g.UseRegister(mright.right().node()));
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRRR(this, kArmVaddF64, node);
1428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32Sub(Node* node) {
1431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(this);
1432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Float32BinopMatcher m(node);
1433f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (m.right().IsFloat32Mul() && CanCover(node, m.right().node())) {
1434f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Float32BinopMatcher mright(m.right().node());
1435f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Emit(kArmVmlsF32, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
1436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         g.UseRegister(mright.left().node()),
1437f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         g.UseRegister(mright.right().node()));
1438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
1439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  VisitRRR(this, kArmVsubF32, node);
1441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Sub(Node* node) {
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
1445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Float64BinopMatcher m(node);
1446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
1447f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Float64BinopMatcher mright(m.right().node());
1448f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Emit(kArmVmlsF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
1449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         g.UseRegister(mright.left().node()),
1450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         g.UseRegister(mright.right().node()));
1451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return;
1452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  VisitRRR(this, kArmVsubF64, node);
1454bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32Mul(Node* node) {
1457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRRR(this, kArmVmulF32, node);
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Mul(Node* node) {
1462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRRR(this, kArmVmulF64, node);
1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32Div(Node* node) {
1467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRRR(this, kArmVdivF32, node);
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Div(Node* node) {
1472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRRR(this, kArmVdivF64, node);
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Mod(Node* node) {
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(this);
1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Emit(kArmVmodF64, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0),
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       g.UseFixed(node->InputAt(1), d1))->MarkAsCall();
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InstructionSelector::VisitFloat32Max(Node* node) {
1483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  VisitRRR(this, kArmFloat32Max, node);
1484bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1486bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InstructionSelector::VisitFloat64Max(Node* node) {
1487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  VisitRRR(this, kArmFloat64Max, node);
1488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
149013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
149113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  VisitRR(this, kArmFloat64SilenceNaN, node);
149213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
149313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InstructionSelector::VisitFloat32Min(Node* node) {
1495bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  VisitRRR(this, kArmFloat32Min, node);
1496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1498bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InstructionSelector::VisitFloat64Min(Node* node) {
1499bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  VisitRRR(this, kArmFloat64Min, node);
1500bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32Abs(Node* node) {
1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVabsF32, node);
1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat64Abs(Node* node) {
1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVabsF64, node);
1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32Sqrt(Node* node) {
1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVsqrtF32, node);
1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Sqrt(Node* node) {
1517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVsqrtF64, node);
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32RoundDown(Node* node) {
1522f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintmF32, node);
1524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat64RoundDown(Node* node) {
1528f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintmF64, node);
1530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32RoundUp(Node* node) {
1534f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintpF32, node);
1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat64RoundUp(Node* node) {
1540f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintpF64, node);
1542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32RoundTruncate(Node* node) {
1546f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintzF32, node);
1548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
1552f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintzF64, node);
1554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
1558f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintaF64, node);
1560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
1564f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintnF32, node);
1566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
1570f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(CpuFeatures::IsSupported(ARMv8));
1571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVrintnF64, node);
1572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
157413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid InstructionSelector::VisitFloat32Neg(Node* node) {
157513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  VisitRR(this, kArmVnegF32, node);
157613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
157713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
157813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid InstructionSelector::VisitFloat64Neg(Node* node) {
157913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  VisitRR(this, kArmVnegF64, node);
158013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
158113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
158213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
158313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                   InstructionCode opcode) {
158413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ArmOperandGenerator g(this);
158513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0),
158613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       g.UseFixed(node->InputAt(1), d1))
158713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ->MarkAsCall();
158813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
158913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
159013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
159113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                  InstructionCode opcode) {
159213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ArmOperandGenerator g(this);
159313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0))
159413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ->MarkAsCall();
159513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::EmitPrepareArguments(
1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
1599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* node) {
1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(this);
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Prepare for C function call.
1603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (descriptor->IsCFunctionCall()) {
1604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Emit(kArchPrepareCallCFunction |
1605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch             MiscField::encode(static_cast<int>(descriptor->ParameterCount())),
1606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         0, nullptr, 0, nullptr);
1607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Poke any stack arguments.
1609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (size_t n = 0; n < arguments->size(); ++n) {
1610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PushParameter input = (*arguments)[n];
1611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (input.node()) {
1612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        int slot = static_cast<int>(n);
1613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Emit(kArmPoke | MiscField::encode(slot), g.NoOutput(),
1614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             g.UseRegister(input.node()));
1615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Push any stack arguments.
1619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (PushParameter input : base::Reversed(*arguments)) {
1620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Skip any alignment holes in pushed nodes.
1621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (input.node() == nullptr) continue;
1622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Emit(kArmPush, g.NoOutput(), g.UseRegister(input.node()));
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool InstructionSelector::IsTailCallAddressImmediate() { return false; }
1629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
16303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochint InstructionSelector::GetTempsCountForTailCallFromJSFunction() { return 3; }
1631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace {
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Shared routine for multiple compare operations.
1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VisitCompare(InstructionSelector* selector, InstructionCode opcode,
1636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  InstructionOperand left, InstructionOperand right,
1637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  FlagsContinuation* cont) {
1638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(selector);
1639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  opcode = cont->Encode(opcode);
1640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (cont->IsBranch()) {
1641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    selector->Emit(opcode, g.NoOutput(), left, right,
1642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   g.Label(cont->true_block()), g.Label(cont->false_block()));
16433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else if (cont->IsDeoptimize()) {
1644f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->reason(),
16453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             cont->frame_state());
1646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(cont->IsSet());
1648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right);
1649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Shared routine for multiple float32 compare operations.
1654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VisitFloat32Compare(InstructionSelector* selector, Node* node,
1655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         FlagsContinuation* cont) {
1656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(selector);
1657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Float32BinopMatcher m(node);
1658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (m.right().Is(0.0f)) {
1659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitCompare(selector, kArmVcmpF32, g.UseRegister(m.left().node()),
1660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 g.UseImmediate(m.right().node()), cont);
1661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (m.left().Is(0.0f)) {
1662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cont->Commute();
1663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitCompare(selector, kArmVcmpF32, g.UseRegister(m.right().node()),
1664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 g.UseImmediate(m.left().node()), cont);
1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitCompare(selector, kArmVcmpF32, g.UseRegister(m.left().node()),
1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 g.UseRegister(m.right().node()), cont);
1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Shared routine for multiple float64 compare operations.
1673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid VisitFloat64Compare(InstructionSelector* selector, Node* node,
1674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         FlagsContinuation* cont) {
1675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ArmOperandGenerator g(selector);
1676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Float64BinopMatcher m(node);
1677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (m.right().Is(0.0)) {
1678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.left().node()),
1679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 g.UseImmediate(m.right().node()), cont);
1680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (m.left().Is(0.0)) {
1681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cont->Commute();
1682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.right().node()),
1683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 g.UseImmediate(m.left().node()), cont);
1684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
1685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.left().node()),
1686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 g.UseRegister(m.right().node()), cont);
1687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1690f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Check whether we can convert:
1691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ((a <op> b) cmp 0), b.<cond>
1692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// to:
1693f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// (a <ops> b), b.<cond'>
1694f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// where <ops> is the flag setting version of <op>.
1695f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// We only generate conditions <cond'> that are a combination of the N
1696f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// and Z flags. This avoids the need to make this function dependent on
1697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// the flag-setting operation.
1698f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CanUseFlagSettingBinop(FlagsCondition cond) {
1699f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (cond) {
1700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kEqual:
1701f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kNotEqual:
1702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kSignedLessThan:
1703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kSignedGreaterThanOrEqual:
1704f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kUnsignedLessThanOrEqual:  // x <= 0 -> x == 0
1705f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kUnsignedGreaterThan:      // x > 0 -> x != 0
1706f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return true;
1707f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    default:
1708f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return false;
1709f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1710f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1711f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1712f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Map <cond> to <cond'> so that the following transformation is possible:
1713f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ((a <op> b) cmp 0), b.<cond>
1714f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// to:
1715f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// (a <ops> b), b.<cond'>
1716f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// where <ops> is the flag setting version of <op>.
1717f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochFlagsCondition MapForFlagSettingBinop(FlagsCondition cond) {
1718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(CanUseFlagSettingBinop(cond));
1719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (cond) {
1720f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kEqual:
1721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kNotEqual:
1722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return cond;
1723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kSignedLessThan:
1724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return kNegative;
1725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kSignedGreaterThanOrEqual:
1726f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return kPositiveOrZero;
1727f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kUnsignedLessThanOrEqual:  // x <= 0 -> x == 0
1728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return kEqual;
1729f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case kUnsignedGreaterThan:  // x > 0 -> x != 0
1730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return kNotEqual;
1731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    default:
1732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
1733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return cond;
1734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Check if we can perform the transformation:
1738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ((a <op> b) cmp 0), b.<cond>
1739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// to:
1740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// (a <ops> b), b.<cond'>
1741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// where <ops> is the flag setting version of <op>, and if so,
1742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// updates {node}, {opcode} and {cont} accordingly.
1743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MaybeReplaceCmpZeroWithFlagSettingBinop(InstructionSelector* selector,
1744f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             Node** node, Node* binop,
1745f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             InstructionCode* opcode,
1746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             FlagsCondition cond,
1747f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             FlagsContinuation* cont) {
1748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionCode binop_opcode;
1749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionCode no_output_opcode;
1750f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (binop->opcode()) {
1751f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kInt32Add:
1752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      binop_opcode = kArmAdd;
1753f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      no_output_opcode = kArmCmn;
1754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
1755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kWord32And:
1756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      binop_opcode = kArmAnd;
1757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      no_output_opcode = kArmTst;
1758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
1759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kWord32Or:
1760f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      binop_opcode = kArmOrr;
1761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      no_output_opcode = kArmOrr;
1762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
1763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kWord32Xor:
1764f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      binop_opcode = kArmEor;
1765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      no_output_opcode = kArmTeq;
1766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
1767f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    default:
1768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNREACHABLE();
1769f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return;
1770f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1771f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (selector->CanCover(*node, binop)) {
1772f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // The comparison is the only user of {node}.
1773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    cont->Overwrite(MapForFlagSettingBinop(cond));
1774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    *opcode = no_output_opcode;
1775f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    *node = binop;
1776f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (selector->IsOnlyUserOfNodeInSameBlock(*node, binop)) {
1777f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // We can also handle the case where the {node} and the comparison are in
1778f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // the same basic block, and the comparison is the only user of {node} in
1779f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // this basic block ({node} has users in other basic blocks).
1780f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    cont->Overwrite(MapForFlagSettingBinop(cond));
1781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    *opcode = binop_opcode;
1782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    *node = binop;
1783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Shared routine for multiple word compare operations.
1787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid VisitWordCompare(InstructionSelector* selector, Node* node,
1788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                      InstructionCode opcode, FlagsContinuation* cont) {
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArmOperandGenerator g(selector);
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Int32BinopMatcher m(node);
1791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand inputs[5];
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t input_count = 0;
1793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionOperand outputs[2];
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t output_count = 0;
1795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool has_result = (opcode != kArmCmp) && (opcode != kArmCmn) &&
1796f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    (opcode != kArmTst) && (opcode != kArmTeq);
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               &input_count, &inputs[1])) {
1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[0] = g.UseRegister(m.left().node());
1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    input_count++;
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      &input_count, &inputs[1])) {
1804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[0] = g.UseRegister(m.right().node());
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    input_count++;
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    opcode |= AddressingModeField::encode(kMode_Operand2_R);
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.UseRegister(m.left().node());
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.UseRegister(m.right().node());
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1813f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (has_result) {
1814f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (cont->IsDeoptimize()) {
1815f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // If we can deoptimize as a result of the binop, we need to make sure
1816f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // that the deopt inputs are not overwritten by the binop result. One way
1817f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // to achieve that is to declare the output register as same-as-first.
1818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      outputs[output_count++] = g.DefineSameAsFirst(node);
1819f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
1820f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      outputs[output_count++] = g.DefineAsRegister(node);
1821f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1823f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cont->IsBranch()) {
1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.Label(cont->true_block());
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inputs[input_count++] = g.Label(cont->false_block());
18273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else if (cont->IsSet()) {
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outputs[output_count++] = g.DefineAsRegister(cont->result());
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_NE(0u, input_count);
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(arraysize(inputs), input_count);
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(arraysize(outputs), output_count);
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  opcode = cont->Encode(opcode);
18363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (cont->IsDeoptimize()) {
18373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
1838f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             cont->reason(), cont->frame_state());
18393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
18403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    selector->Emit(opcode, output_count, outputs, input_count, inputs);
18413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid VisitWordCompare(InstructionSelector* selector, Node* node,
1846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                      FlagsContinuation* cont) {
1847f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  InstructionCode opcode = kArmCmp;
1848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Int32BinopMatcher m(node);
1849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1850f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  FlagsCondition cond = cont->condition();
1851f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (m.right().Is(0) && (m.left().IsInt32Add() || m.left().IsWord32Or() ||
1852f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                          m.left().IsWord32And() || m.left().IsWord32Xor())) {
1853f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Emit flag setting instructions for comparisons against zero.
1854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (CanUseFlagSettingBinop(cond)) {
1855f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* binop = m.left().node();
1856f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode,
1857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                              cond, cont);
1858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1859f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (m.left().Is(0) &&
1860f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch             (m.right().IsInt32Add() || m.right().IsWord32Or() ||
1861f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              m.right().IsWord32And() || m.right().IsWord32Xor())) {
1862f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Same as above, but we need to commute the condition before we
1863f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // continue with the rest of the checks.
1864f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    cond = CommuteFlagsCondition(cond);
1865f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (CanUseFlagSettingBinop(cond)) {
1866f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* binop = m.right().node();
1867f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode,
1868f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                              cond, cont);
1869f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1870f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1871f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1872f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  VisitWordCompare(selector, node, opcode, cont);
1873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1876958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Shared routine for word comparisons against zero.
1877958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid VisitWordCompareZero(InstructionSelector* selector, Node* user,
1878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                          Node* value, FlagsContinuation* cont) {
1879c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Try to combine with comparisons against 0 by simply inverting the branch.
1880c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  while (value->opcode() == IrOpcode::kWord32Equal &&
1881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch         selector->CanCover(user, value)) {
1882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Int32BinopMatcher m(value);
1883c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (!m.right().Is(0)) break;
1884c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1885c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    user = value;
1886c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    value = m.left().node();
1887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    cont->Negate();
1888c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1889c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1890c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (selector->CanCover(user, value)) {
1891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (value->opcode()) {
1892c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      case IrOpcode::kWord32Equal:
1893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        cont->OverwriteAndNegateIfEqual(kEqual);
1894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, cont);
1895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kInt32LessThan:
1896958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        cont->OverwriteAndNegateIfEqual(kSignedLessThan);
1897958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, cont);
1898958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kInt32LessThanOrEqual:
1899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, cont);
1901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kUint32LessThan:
1902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
1903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, cont);
1904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kUint32LessThanOrEqual:
1905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, cont);
1907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kFloat32Equal:
1908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cont->OverwriteAndNegateIfEqual(kEqual);
1909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return VisitFloat32Compare(selector, value, cont);
1910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kFloat32LessThan:
1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cont->OverwriteAndNegateIfEqual(kFloatLessThan);
1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return VisitFloat32Compare(selector, value, cont);
1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kFloat32LessThanOrEqual:
1914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cont->OverwriteAndNegateIfEqual(kFloatLessThanOrEqual);
1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return VisitFloat32Compare(selector, value, cont);
1916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kFloat64Equal:
1917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cont->OverwriteAndNegateIfEqual(kEqual);
1918958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitFloat64Compare(selector, value, cont);
1919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kFloat64LessThan:
1920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cont->OverwriteAndNegateIfEqual(kFloatLessThan);
1921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitFloat64Compare(selector, value, cont);
1922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kFloat64LessThanOrEqual:
1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cont->OverwriteAndNegateIfEqual(kFloatLessThanOrEqual);
1924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitFloat64Compare(selector, value, cont);
1925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kProjection:
1926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Check if this is the overflow output projection of an
1927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // <Operation>WithOverflow node.
1928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (ProjectionIndexOf(value->op()) == 1u) {
1929958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          // We cannot combine the <Operation>WithOverflow with this branch
1930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          // unless the 0th projection (the use of the actual value of the
1931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // <Operation> is either nullptr, which means there's no use of the
1932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          // actual value, or was already defined, which means it is scheduled
1933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          // *AFTER* this branch).
1934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Node* const node = value->InputAt(0);
1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Node* const result = NodeProperties::FindProjection(node, 0);
1936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          if (!result || selector->IsDefined(result)) {
1937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            switch (node->opcode()) {
1938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              case IrOpcode::kInt32AddWithOverflow:
1939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                cont->OverwriteAndNegateIfEqual(kOverflow);
1940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                return VisitBinop(selector, node, kArmAdd, kArmAdd, cont);
1941958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              case IrOpcode::kInt32SubWithOverflow:
1942958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                cont->OverwriteAndNegateIfEqual(kOverflow);
1943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                return VisitBinop(selector, node, kArmSub, kArmRsb, cont);
1944f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              case IrOpcode::kInt32MulWithOverflow:
1945f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                // ARM doesn't set the overflow flag for multiplication, so we
1946f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                // need to test on kNotEqual. Here is the code sequence used:
1947f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                //   smull resultlow, resulthigh, left, right
1948f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                //   cmp resulthigh, Operand(resultlow, ASR, 31)
1949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                cont->OverwriteAndNegateIfEqual(kNotEqual);
1950f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                return EmitInt32MulWithOverflow(selector, node, cont);
1951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              default:
1952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                break;
1953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
1954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          }
1955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
1956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kInt32Add:
1958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, kArmCmn, cont);
1959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kInt32Sub:
1960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, kArmCmp, cont);
1961958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32And:
1962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, kArmTst, cont);
1963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32Or:
1964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitBinop(selector, value, kArmOrr, kArmOrr, cont);
1965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32Xor:
1966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitWordCompare(selector, value, kArmTeq, cont);
1967958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32Sar:
1968958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitShift(selector, value, TryMatchASR, cont);
1969958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32Shl:
1970958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitShift(selector, value, TryMatchLSL, cont);
1971958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32Shr:
1972958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitShift(selector, value, TryMatchLSR, cont);
1973958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case IrOpcode::kWord32Ror:
1974958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return VisitShift(selector, value, TryMatchROR, cont);
1975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
1976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1977958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (user->opcode() == IrOpcode::kWord32Equal) {
1981f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return VisitWordCompare(selector, user, cont);
1982f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1983f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Continuation could not be combined with a compare, emit compare against 0.
1985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ArmOperandGenerator g(selector);
1986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  InstructionCode const opcode =
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand const value_operand = g.UseRegister(value);
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cont->IsBranch()) {
1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    selector->Emit(opcode, g.NoOutput(), value_operand, value_operand,
1991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   g.Label(cont->true_block()), g.Label(cont->false_block()));
19923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else if (cont->IsDeoptimize()) {
19933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    selector->EmitDeoptimize(opcode, g.NoOutput(), value_operand, value_operand,
1994f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             cont->reason(), cont->frame_state());
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
19963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(cont->IsSet());
1997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand,
1998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   value_operand);
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace
2003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
2005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                      BasicBlock* fbranch) {
2006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FlagsContinuation cont(kNotEqual, tbranch, fbranch);
2007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid InstructionSelector::VisitDeoptimizeIf(Node* node) {
2011f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
2012f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      kNotEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1));
20133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  VisitWordCompareZero(this, node, node->InputAt(0), &cont);
20143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
20153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid InstructionSelector::VisitDeoptimizeUnless(Node* node) {
2017f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
2018f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      kEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1));
20193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  VisitWordCompareZero(this, node, node->InputAt(0), &cont);
20203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
2023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(this);
2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Emit either ArchTableSwitch or ArchLookupSwitch.
2027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t table_space_cost = 4 + sw.value_range;
2028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t table_time_cost = 3;
2029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t lookup_space_cost = 3 + 2 * sw.case_count;
2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t lookup_time_cost = sw.case_count;
2031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (sw.case_count > 0 &&
2032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      table_space_cost + 3 * table_time_cost <=
2033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          lookup_space_cost + 3 * lookup_time_cost &&
2034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      sw.min_value > std::numeric_limits<int32_t>::min()) {
2035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InstructionOperand index_operand = value_operand;
2036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (sw.min_value) {
2037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      index_operand = g.TempRegister();
2038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_I),
2039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           index_operand, value_operand, g.TempImmediate(sw.min_value));
2040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Generate a table lookup.
2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return EmitTableSwitch(sw, index_operand);
2043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Generate a sequence of conditional jumps.
2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return EmitLookupSwitch(sw, value_operand);
2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitWord32Equal(Node* const node) {
20513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
2052958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Int32BinopMatcher m(node);
2053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (m.right().Is(0)) {
2054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
2055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2056958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitWordCompare(this, node, &cont);
2057958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2058958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2059958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2060958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitInt32LessThan(Node* node) {
20613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
2062958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitWordCompare(this, node, &cont);
2063958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2064958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
20673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont =
20683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
2069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitWordCompare(this, node, &cont);
2070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitUint32LessThan(Node* node) {
20743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
2075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitWordCompare(this, node, &cont);
2076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
20803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont =
20813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
2082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitWordCompare(this, node, &cont);
2083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
20883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
2089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return VisitBinop(this, node, kArmAdd, kArmAdd, &cont);
2090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FlagsContinuation cont;
2092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitBinop(this, node, kArmAdd, kArmAdd, &cont);
2093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
20973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
2098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return VisitBinop(this, node, kArmSub, kArmRsb, &cont);
2099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FlagsContinuation cont;
2101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitBinop(this, node, kArmSub, kArmRsb, &cont);
2102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
2105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
2106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // ARM doesn't set the overflow flag for multiplication, so we need to test
2107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // on kNotEqual. Here is the code sequence used:
2108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    //   smull resultlow, resulthigh, left, right
2109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    //   cmp resulthigh, Operand(resultlow, ASR, 31)
2110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
2111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return EmitInt32MulWithOverflow(this, node, &cont);
2112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  FlagsContinuation cont;
2114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EmitInt32MulWithOverflow(this, node, &cont);
2115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32Equal(Node* node) {
21183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
2119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitFloat32Compare(this, node, &cont);
2120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32LessThan(Node* node) {
21243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont = FlagsContinuation::ForSet(kFloatLessThan, node);
2125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitFloat32Compare(this, node, &cont);
2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) {
21303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont =
21313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      FlagsContinuation::ForSet(kFloatLessThanOrEqual, node);
2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitFloat32Compare(this, node, &cont);
2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitFloat64Equal(Node* node) {
21373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
2138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitFloat64Compare(this, node, &cont);
2139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitFloat64LessThan(Node* node) {
21433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont = FlagsContinuation::ForSet(kFloatLessThan, node);
2144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitFloat64Compare(this, node, &cont);
2145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
21493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FlagsContinuation cont =
21503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      FlagsContinuation::ForSet(kFloatLessThanOrEqual, node);
2151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  VisitFloat64Compare(this, node, &cont);
2152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) {
2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVmovLowU32F64, node);
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) {
2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  VisitRR(this, kArmVmovHighU32F64, node);
2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat64InsertLowWord32(Node* node) {
2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(this);
2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* left = node->InputAt(0);
2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* right = node->InputAt(1);
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (left->opcode() == IrOpcode::kFloat64InsertHighWord32 &&
2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CanCover(node, left)) {
2171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    left = left->InputAt(1);
2172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), g.UseRegister(right),
2173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         g.UseRegister(left));
2174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Emit(kArmVmovLowF64U32, g.DefineSameAsFirst(node), g.UseRegister(left),
2177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       g.UseRegister(right));
2178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstructionSelector::VisitFloat64InsertHighWord32(Node* node) {
2182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ArmOperandGenerator g(this);
2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* left = node->InputAt(0);
2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* right = node->InputAt(1);
2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (left->opcode() == IrOpcode::kFloat64InsertLowWord32 &&
2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CanCover(node, left)) {
2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    left = left->InputAt(1);
2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), g.UseRegister(left),
2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         g.UseRegister(right));
2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Emit(kArmVmovHighF64U32, g.DefineSameAsFirst(node), g.UseRegister(left),
2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       g.UseRegister(right));
2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InstructionSelector::VisitAtomicLoad(Node* node) {
2197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
2198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ArmOperandGenerator g(this);
2199bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* base = node->InputAt(0);
2200bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* index = node->InputAt(1);
2201bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ArchOpcode opcode = kArchNop;
2202bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  switch (load_rep.representation()) {
2203bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case MachineRepresentation::kWord8:
2204bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
2205bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
2206bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case MachineRepresentation::kWord16:
2207bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
2208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
2209bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case MachineRepresentation::kWord32:
2210bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      opcode = kAtomicLoadWord32;
2211bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
2212bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    default:
2213bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      UNREACHABLE();
2214bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return;
2215bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
2216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
2217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch       g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
2218bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
2219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
2220bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InstructionSelector::VisitAtomicStore(Node* node) {
2221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
2222bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ArmOperandGenerator g(this);
2223bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* base = node->InputAt(0);
2224bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* index = node->InputAt(1);
2225bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(2);
2226bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ArchOpcode opcode = kArchNop;
2227bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  switch (rep) {
2228bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case MachineRepresentation::kWord8:
2229bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      opcode = kAtomicStoreWord8;
2230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
2231bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case MachineRepresentation::kWord16:
2232bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      opcode = kAtomicStoreWord16;
2233bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
2234bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case MachineRepresentation::kWord32:
2235bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      opcode = kAtomicStoreWord32;
2236bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
2237bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    default:
2238bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      UNREACHABLE();
2239bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return;
2240bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
2241bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
2242bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  AddressingMode addressing_mode = kMode_Offset_RR;
2243bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  InstructionOperand inputs[4];
2244bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  size_t input_count = 0;
2245bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inputs[input_count++] = g.UseUniqueRegister(base);
2246bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inputs[input_count++] = g.UseUniqueRegister(index);
2247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inputs[input_count++] = g.UseUniqueRegister(value);
2248bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
2249bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Emit(code, 0, nullptr, input_count, inputs);
2250bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
2251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// static
2253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierMachineOperatorBuilder::Flags
2254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierInstructionSelector::SupportedMachineOperatorFlags() {
225513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  MachineOperatorBuilder::Flags flags;
225613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (CpuFeatures::IsSupported(SUDIV)) {
225713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // The sdiv and udiv instructions correctly return 0 if the divisor is 0,
225813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // but the fall-back implementation does not.
225913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    flags |= MachineOperatorBuilder::kInt32DivIsSafe |
226013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch             MachineOperatorBuilder::kUint32DivIsSafe;
226113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
2262109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
2263109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    flags |= MachineOperatorBuilder::kWord32ReverseBits;
2264109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (CpuFeatures::IsSupported(ARMv8)) {
2266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    flags |= MachineOperatorBuilder::kFloat32RoundDown |
2267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             MachineOperatorBuilder::kFloat64RoundDown |
2268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             MachineOperatorBuilder::kFloat32RoundUp |
2269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             MachineOperatorBuilder::kFloat64RoundUp |
2270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             MachineOperatorBuilder::kFloat32RoundTruncate |
2271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             MachineOperatorBuilder::kFloat64RoundTruncate |
2272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             MachineOperatorBuilder::kFloat64RoundTiesAway |
2273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             MachineOperatorBuilder::kFloat32RoundTiesEven |
2274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch             MachineOperatorBuilder::kFloat64RoundTiesEven;
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return flags;
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
227913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// static
228013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochMachineOperatorBuilder::AlignmentRequirements
228113e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochInstructionSelector::AlignmentRequirements() {
2282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Vector<MachineType> req_aligned = Vector<MachineType>::New(2);
2283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  req_aligned[0] = MachineType::Float32();
2284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  req_aligned[1] = MachineType::Float64();
228513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return MachineOperatorBuilder::AlignmentRequirements::
2286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      SomeUnalignedAccessUnsupported(req_aligned, req_aligned);
228713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
228813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace compiler
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace internal
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8
2292