blob: e1cf2a66d3fb215d9638312fb8c066da4d35c3d2 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/code-generator.h"
6
7#include "src/arm/macro-assembler-arm.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/ast/scopes.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/compiler/code-generator-impl.h"
10#include "src/compiler/gap-resolver.h"
11#include "src/compiler/node-matchers.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/compiler/osr.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013
14namespace v8 {
15namespace internal {
16namespace compiler {
17
18#define __ masm()->
19
20
21#define kScratchReg r9
22
23
24// Adds Arm-specific methods to convert InstructionOperands.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025class ArmOperandConverter final : public InstructionOperandConverter {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026 public:
27 ArmOperandConverter(CodeGenerator* gen, Instruction* instr)
28 : InstructionOperandConverter(gen, instr) {}
29
30 SBit OutputSBit() const {
31 switch (instr_->flags_mode()) {
32 case kFlags_branch:
Ben Murdochda12d292016-06-02 14:46:10 +010033 case kFlags_deoptimize:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034 case kFlags_set:
35 return SetCC;
36 case kFlags_none:
37 return LeaveCC;
38 }
39 UNREACHABLE();
40 return LeaveCC;
41 }
42
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043 Operand InputImmediate(size_t index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 Constant constant = ToConstant(instr_->InputAt(index));
45 switch (constant.type()) {
46 case Constant::kInt32:
47 return Operand(constant.ToInt32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040048 case Constant::kFloat32:
49 return Operand(
50 isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 case Constant::kFloat64:
52 return Operand(
53 isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
54 case Constant::kInt64:
55 case Constant::kExternalReference:
56 case Constant::kHeapObject:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040057 case Constant::kRpoNumber:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 break;
59 }
60 UNREACHABLE();
61 return Operand::Zero();
62 }
63
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 Operand InputOperand2(size_t first_index) {
65 const size_t index = first_index;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066 switch (AddressingModeField::decode(instr_->opcode())) {
67 case kMode_None:
68 case kMode_Offset_RI:
69 case kMode_Offset_RR:
70 break;
71 case kMode_Operand2_I:
72 return InputImmediate(index + 0);
73 case kMode_Operand2_R:
74 return Operand(InputRegister(index + 0));
75 case kMode_Operand2_R_ASR_I:
76 return Operand(InputRegister(index + 0), ASR, InputInt5(index + 1));
77 case kMode_Operand2_R_ASR_R:
78 return Operand(InputRegister(index + 0), ASR, InputRegister(index + 1));
79 case kMode_Operand2_R_LSL_I:
80 return Operand(InputRegister(index + 0), LSL, InputInt5(index + 1));
81 case kMode_Operand2_R_LSL_R:
82 return Operand(InputRegister(index + 0), LSL, InputRegister(index + 1));
83 case kMode_Operand2_R_LSR_I:
84 return Operand(InputRegister(index + 0), LSR, InputInt5(index + 1));
85 case kMode_Operand2_R_LSR_R:
86 return Operand(InputRegister(index + 0), LSR, InputRegister(index + 1));
87 case kMode_Operand2_R_ROR_I:
88 return Operand(InputRegister(index + 0), ROR, InputInt5(index + 1));
89 case kMode_Operand2_R_ROR_R:
90 return Operand(InputRegister(index + 0), ROR, InputRegister(index + 1));
91 }
92 UNREACHABLE();
93 return Operand::Zero();
94 }
95
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096 MemOperand InputOffset(size_t* first_index) {
97 const size_t index = *first_index;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 switch (AddressingModeField::decode(instr_->opcode())) {
99 case kMode_None:
100 case kMode_Operand2_I:
101 case kMode_Operand2_R:
102 case kMode_Operand2_R_ASR_I:
103 case kMode_Operand2_R_ASR_R:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 case kMode_Operand2_R_LSL_R:
105 case kMode_Operand2_R_LSR_I:
106 case kMode_Operand2_R_LSR_R:
107 case kMode_Operand2_R_ROR_I:
108 case kMode_Operand2_R_ROR_R:
109 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100110 case kMode_Operand2_R_LSL_I:
111 *first_index += 3;
112 return MemOperand(InputRegister(index + 0), InputRegister(index + 1),
113 LSL, InputInt32(index + 2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 case kMode_Offset_RI:
115 *first_index += 2;
116 return MemOperand(InputRegister(index + 0), InputInt32(index + 1));
117 case kMode_Offset_RR:
118 *first_index += 2;
119 return MemOperand(InputRegister(index + 0), InputRegister(index + 1));
120 }
121 UNREACHABLE();
122 return MemOperand(r0);
123 }
124
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 MemOperand InputOffset(size_t first_index = 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126 return InputOffset(&first_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 }
128
129 MemOperand ToMemOperand(InstructionOperand* op) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 DCHECK_NOT_NULL(op);
Ben Murdochc5610432016-08-08 18:44:38 +0100131 DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
Ben Murdochda12d292016-06-02 14:46:10 +0100132 return SlotToMemOperand(AllocatedOperand::cast(op)->index());
133 }
134
135 MemOperand SlotToMemOperand(int slot) const {
136 FrameOffset offset = frame_access_state()->GetFrameOffset(slot);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
138 }
139};
140
141
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400142namespace {
143
Ben Murdoch61f157c2016-09-16 13:49:30 +0100144class OutOfLineLoadFloat final : public OutOfLineCode {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400145 public:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100146 OutOfLineLoadFloat(CodeGenerator* gen, SwVfpRegister result)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400147 : OutOfLineCode(gen), result_(result) {}
148
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149 void Generate() final {
Ben Murdochda12d292016-06-02 14:46:10 +0100150 // Compute sqrtf(-1.0f), which results in a quiet single-precision NaN.
151 __ vmov(result_, -1.0f);
152 __ vsqrt(result_, result_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400153 }
154
155 private:
156 SwVfpRegister const result_;
157};
158
Ben Murdoch61f157c2016-09-16 13:49:30 +0100159class OutOfLineLoadDouble final : public OutOfLineCode {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400160 public:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100161 OutOfLineLoadDouble(CodeGenerator* gen, DwVfpRegister result)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400162 : OutOfLineCode(gen), result_(result) {}
163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 void Generate() final {
Ben Murdochda12d292016-06-02 14:46:10 +0100165 // Compute sqrt(-1.0), which results in a quiet double-precision NaN.
166 __ vmov(result_, -1.0);
167 __ vsqrt(result_, result_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168 }
169
170 private:
171 DwVfpRegister const result_;
172};
173
174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175class OutOfLineLoadInteger final : public OutOfLineCode {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400176 public:
177 OutOfLineLoadInteger(CodeGenerator* gen, Register result)
178 : OutOfLineCode(gen), result_(result) {}
179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 void Generate() final { __ mov(result_, Operand::Zero()); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400181
182 private:
183 Register const result_;
184};
185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186
187class OutOfLineRecordWrite final : public OutOfLineCode {
188 public:
189 OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register index,
190 Register value, Register scratch0, Register scratch1,
191 RecordWriteMode mode)
192 : OutOfLineCode(gen),
193 object_(object),
194 index_(index),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100195 index_immediate_(0),
196 value_(value),
197 scratch0_(scratch0),
198 scratch1_(scratch1),
Ben Murdochc5610432016-08-08 18:44:38 +0100199 mode_(mode),
200 must_save_lr_(!gen->frame_access_state()->has_frame()) {}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100201
202 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t index,
203 Register value, Register scratch0, Register scratch1,
204 RecordWriteMode mode)
205 : OutOfLineCode(gen),
206 object_(object),
207 index_(no_reg),
208 index_immediate_(index),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 value_(value),
210 scratch0_(scratch0),
211 scratch1_(scratch1),
Ben Murdochda12d292016-06-02 14:46:10 +0100212 mode_(mode),
213 must_save_lr_(!gen->frame_access_state()->has_frame()) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214
215 void Generate() final {
216 if (mode_ > RecordWriteMode::kValueIsPointer) {
217 __ JumpIfSmi(value_, exit());
218 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100219 __ CheckPageFlag(value_, scratch0_,
220 MemoryChunk::kPointersToHereAreInterestingMask, eq,
221 exit());
222 RememberedSetAction const remembered_set_action =
223 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
224 : OMIT_REMEMBERED_SET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 SaveFPRegsMode const save_fp_mode =
226 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
Ben Murdochda12d292016-06-02 14:46:10 +0100227 if (must_save_lr_) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100228 // We need to save and restore lr if the frame was elided.
229 __ Push(lr);
230 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100232 remembered_set_action, save_fp_mode);
233 if (index_.is(no_reg)) {
234 __ add(scratch1_, object_, Operand(index_immediate_));
235 } else {
236 DCHECK_EQ(0, index_immediate_);
237 __ add(scratch1_, object_, Operand(index_));
238 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 __ CallStub(&stub);
Ben Murdochda12d292016-06-02 14:46:10 +0100240 if (must_save_lr_) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100241 __ Pop(lr);
242 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 }
244
245 private:
246 Register const object_;
247 Register const index_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100248 int32_t const index_immediate_; // Valid if index_.is(no_reg).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 Register const value_;
250 Register const scratch0_;
251 Register const scratch1_;
252 RecordWriteMode const mode_;
Ben Murdochda12d292016-06-02 14:46:10 +0100253 bool must_save_lr_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254};
255
256
257Condition FlagsConditionToCondition(FlagsCondition condition) {
258 switch (condition) {
259 case kEqual:
260 return eq;
261 case kNotEqual:
262 return ne;
263 case kSignedLessThan:
264 return lt;
265 case kSignedGreaterThanOrEqual:
266 return ge;
267 case kSignedLessThanOrEqual:
268 return le;
269 case kSignedGreaterThan:
270 return gt;
271 case kUnsignedLessThan:
272 return lo;
273 case kUnsignedGreaterThanOrEqual:
274 return hs;
275 case kUnsignedLessThanOrEqual:
276 return ls;
277 case kUnsignedGreaterThan:
278 return hi;
279 case kFloatLessThanOrUnordered:
280 return lt;
281 case kFloatGreaterThanOrEqual:
282 return ge;
283 case kFloatLessThanOrEqual:
284 return ls;
285 case kFloatGreaterThanOrUnordered:
286 return hi;
287 case kFloatLessThan:
288 return lo;
289 case kFloatGreaterThanOrEqualOrUnordered:
290 return hs;
291 case kFloatLessThanOrEqualOrUnordered:
292 return le;
293 case kFloatGreaterThan:
294 return gt;
295 case kOverflow:
296 return vs;
297 case kNotOverflow:
298 return vc;
299 default:
300 break;
301 }
302 UNREACHABLE();
303 return kNoCondition;
304}
305
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400306} // namespace
307
Ben Murdoch61f157c2016-09-16 13:49:30 +0100308#define ASSEMBLE_CHECKED_LOAD_FP(Type) \
309 do { \
310 auto result = i.Output##Type##Register(); \
311 auto offset = i.InputRegister(0); \
312 if (instr->InputAt(1)->IsRegister()) { \
313 __ cmp(offset, i.InputRegister(1)); \
314 } else { \
315 __ cmp(offset, i.InputImmediate(1)); \
316 } \
317 auto ool = new (zone()) OutOfLineLoad##Type(this, result); \
318 __ b(hs, ool->entry()); \
319 __ vldr(result, i.InputOffset(2)); \
320 __ bind(ool->exit()); \
321 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400322 } while (0)
323
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400324#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \
325 do { \
326 auto result = i.OutputRegister(); \
327 auto offset = i.InputRegister(0); \
328 if (instr->InputAt(1)->IsRegister()) { \
329 __ cmp(offset, i.InputRegister(1)); \
330 } else { \
331 __ cmp(offset, i.InputImmediate(1)); \
332 } \
333 auto ool = new (zone()) OutOfLineLoadInteger(this, result); \
334 __ b(hs, ool->entry()); \
335 __ asm_instr(result, i.InputOffset(2)); \
336 __ bind(ool->exit()); \
337 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
338 } while (0)
339
Ben Murdoch61f157c2016-09-16 13:49:30 +0100340#define ASSEMBLE_CHECKED_STORE_FP(Type) \
341 do { \
342 auto offset = i.InputRegister(0); \
343 if (instr->InputAt(1)->IsRegister()) { \
344 __ cmp(offset, i.InputRegister(1)); \
345 } else { \
346 __ cmp(offset, i.InputImmediate(1)); \
347 } \
348 auto value = i.Input##Type##Register(2); \
349 __ vstr(value, i.InputOffset(3), lo); \
350 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400351 } while (0)
352
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400353#define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \
354 do { \
355 auto offset = i.InputRegister(0); \
356 if (instr->InputAt(1)->IsRegister()) { \
357 __ cmp(offset, i.InputRegister(1)); \
358 } else { \
359 __ cmp(offset, i.InputImmediate(1)); \
360 } \
361 auto value = i.InputRegister(2); \
362 __ asm_instr(value, i.InputOffset(3), lo); \
363 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
364 } while (0)
365
Ben Murdochc5610432016-08-08 18:44:38 +0100366#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \
367 do { \
368 __ asm_instr(i.OutputRegister(), \
369 MemOperand(i.InputRegister(0), i.InputRegister(1))); \
370 __ dmb(ISH); \
371 } while (0)
372
373#define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr) \
374 do { \
375 __ dmb(ISH); \
376 __ asm_instr(i.InputRegister(2), \
377 MemOperand(i.InputRegister(0), i.InputRegister(1))); \
378 __ dmb(ISH); \
379 } while (0)
380
Ben Murdoch61f157c2016-09-16 13:49:30 +0100381#define ASSEMBLE_IEEE754_BINOP(name) \
382 do { \
383 /* TODO(bmeurer): We should really get rid of this special instruction, */ \
384 /* and generate a CallAddress instruction instead. */ \
385 FrameScope scope(masm(), StackFrame::MANUAL); \
386 __ PrepareCallCFunction(0, 2, kScratchReg); \
387 __ MovToFloatParameters(i.InputDoubleRegister(0), \
388 i.InputDoubleRegister(1)); \
389 __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
390 0, 2); \
391 /* Move the result in the double result register. */ \
392 __ MovFromFloatResult(i.OutputDoubleRegister()); \
393 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
394 } while (0)
395
396#define ASSEMBLE_IEEE754_UNOP(name) \
397 do { \
398 /* TODO(bmeurer): We should really get rid of this special instruction, */ \
399 /* and generate a CallAddress instruction instead. */ \
400 FrameScope scope(masm(), StackFrame::MANUAL); \
401 __ PrepareCallCFunction(0, 1, kScratchReg); \
402 __ MovToFloatParameter(i.InputDoubleRegister(0)); \
403 __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
404 0, 1); \
405 /* Move the result in the double result register. */ \
406 __ MovFromFloatResult(i.OutputDoubleRegister()); \
407 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
408 } while (0)
409
Ben Murdochda12d292016-06-02 14:46:10 +0100410void CodeGenerator::AssembleDeconstructFrame() {
411 __ LeaveFrame(StackFrame::MANUAL);
412}
413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000414void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
415 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
416 if (sp_slot_delta > 0) {
417 __ add(sp, sp, Operand(sp_slot_delta * kPointerSize));
418 }
419 frame_access_state()->SetFrameAccessToDefault();
420}
421
422
423void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
424 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
425 if (sp_slot_delta < 0) {
426 __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize));
427 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
428 }
Ben Murdochda12d292016-06-02 14:46:10 +0100429 if (frame_access_state()->has_frame()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 if (FLAG_enable_embedded_constant_pool) {
431 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
432 }
433 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
434 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
435 }
436 frame_access_state()->SetFrameAccessToSP();
437}
438
Ben Murdochda12d292016-06-02 14:46:10 +0100439void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
440 Register scratch1,
441 Register scratch2,
442 Register scratch3) {
443 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
444 Label done;
445
446 // Check if current frame is an arguments adaptor frame.
447 __ ldr(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset));
448 __ cmp(scratch1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
449 __ b(ne, &done);
450
451 // Load arguments count from current arguments adaptor frame (note, it
452 // does not include receiver).
453 Register caller_args_count_reg = scratch1;
454 __ ldr(caller_args_count_reg,
455 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
456 __ SmiUntag(caller_args_count_reg);
457
458 ParameterCount callee_args_count(args_reg);
459 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
460 scratch3);
461 __ bind(&done);
462}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000463
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464// Assembles an instruction after register allocation, producing machine code.
Ben Murdochc5610432016-08-08 18:44:38 +0100465CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
466 Instruction* instr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467 ArmOperandConverter i(this, instr);
468
Ben Murdochda12d292016-06-02 14:46:10 +0100469 __ MaybeCheckConstPool();
470 InstructionCode opcode = instr->opcode();
471 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
472 switch (arch_opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000473 case kArchCallCodeObject: {
474 EnsureSpaceForLazyDeopt();
475 if (instr->InputAt(0)->IsImmediate()) {
476 __ Call(Handle<Code>::cast(i.InputHeapObject(0)),
477 RelocInfo::CODE_TARGET);
478 } else {
479 __ add(ip, i.InputRegister(0),
480 Operand(Code::kHeaderSize - kHeapObjectTag));
481 __ Call(ip);
482 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483 RecordCallPosition(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000484 DCHECK_EQ(LeaveCC, i.OutputSBit());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485 frame_access_state()->ClearSPDelta();
486 break;
487 }
Ben Murdochda12d292016-06-02 14:46:10 +0100488 case kArchTailCallCodeObjectFromJSFunction:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489 case kArchTailCallCodeObject: {
490 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
491 AssembleDeconstructActivationRecord(stack_param_delta);
Ben Murdochda12d292016-06-02 14:46:10 +0100492 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
493 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
494 i.TempRegister(0), i.TempRegister(1),
495 i.TempRegister(2));
496 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 if (instr->InputAt(0)->IsImmediate()) {
498 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)),
499 RelocInfo::CODE_TARGET);
500 } else {
501 __ add(ip, i.InputRegister(0),
502 Operand(Code::kHeaderSize - kHeapObjectTag));
503 __ Jump(ip);
504 }
505 DCHECK_EQ(LeaveCC, i.OutputSBit());
506 frame_access_state()->ClearSPDelta();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507 break;
508 }
Ben Murdochc5610432016-08-08 18:44:38 +0100509 case kArchTailCallAddress: {
510 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
511 AssembleDeconstructActivationRecord(stack_param_delta);
512 CHECK(!instr->InputAt(0)->IsImmediate());
513 __ Jump(i.InputRegister(0));
514 frame_access_state()->ClearSPDelta();
515 break;
516 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000517 case kArchCallJSFunction: {
518 EnsureSpaceForLazyDeopt();
519 Register func = i.InputRegister(0);
520 if (FLAG_debug_code) {
521 // Check the function's context matches the context argument.
522 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
523 __ cmp(cp, kScratchReg);
524 __ Assert(eq, kWrongFunctionContext);
525 }
526 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
527 __ Call(ip);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528 RecordCallPosition(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 DCHECK_EQ(LeaveCC, i.OutputSBit());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000530 frame_access_state()->ClearSPDelta();
531 break;
532 }
Ben Murdochda12d292016-06-02 14:46:10 +0100533 case kArchTailCallJSFunctionFromJSFunction:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000534 case kArchTailCallJSFunction: {
535 Register func = i.InputRegister(0);
536 if (FLAG_debug_code) {
537 // Check the function's context matches the context argument.
538 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
539 __ cmp(cp, kScratchReg);
540 __ Assert(eq, kWrongFunctionContext);
541 }
542 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
543 AssembleDeconstructActivationRecord(stack_param_delta);
Ben Murdochda12d292016-06-02 14:46:10 +0100544 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) {
545 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
546 i.TempRegister(0), i.TempRegister(1),
547 i.TempRegister(2));
548 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
550 __ Jump(ip);
551 DCHECK_EQ(LeaveCC, i.OutputSBit());
552 frame_access_state()->ClearSPDelta();
553 break;
554 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 case kArchPrepareCallCFunction: {
556 int const num_parameters = MiscField::decode(instr->opcode());
557 __ PrepareCallCFunction(num_parameters, kScratchReg);
558 // Frame alignment requires using FP-relative frame addressing.
559 frame_access_state()->SetFrameAccessToFP();
560 break;
561 }
562 case kArchPrepareTailCall:
563 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1));
564 break;
565 case kArchCallCFunction: {
566 int const num_parameters = MiscField::decode(instr->opcode());
567 if (instr->InputAt(0)->IsImmediate()) {
568 ExternalReference ref = i.InputExternalReference(0);
569 __ CallCFunction(ref, num_parameters);
570 } else {
571 Register func = i.InputRegister(0);
572 __ CallCFunction(func, num_parameters);
573 }
574 frame_access_state()->SetFrameAccessToDefault();
575 frame_access_state()->ClearSPDelta();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576 break;
577 }
578 case kArchJmp:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400579 AssembleArchJump(i.InputRpo(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580 DCHECK_EQ(LeaveCC, i.OutputSBit());
581 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 case kArchLookupSwitch:
583 AssembleArchLookupSwitch(instr);
584 DCHECK_EQ(LeaveCC, i.OutputSBit());
585 break;
586 case kArchTableSwitch:
587 AssembleArchTableSwitch(instr);
588 DCHECK_EQ(LeaveCC, i.OutputSBit());
589 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100590 case kArchDebugBreak:
591 __ stop("kArchDebugBreak");
592 break;
593 case kArchComment: {
594 Address comment_string = i.InputExternalReference(0).address();
595 __ RecordComment(reinterpret_cast<const char*>(comment_string));
596 break;
597 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598 case kArchNop:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000599 case kArchThrowTerminator:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 // don't emit code for nops.
601 DCHECK_EQ(LeaveCC, i.OutputSBit());
602 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 case kArchDeoptimize: {
604 int deopt_state_id =
605 BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
606 Deoptimizer::BailoutType bailout_type =
607 Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
Ben Murdochc5610432016-08-08 18:44:38 +0100608 CodeGenResult result =
609 AssembleDeoptimizerCall(deopt_state_id, bailout_type);
610 if (result != kSuccess) return result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611 break;
612 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613 case kArchRet:
614 AssembleReturn();
615 DCHECK_EQ(LeaveCC, i.OutputSBit());
616 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400617 case kArchStackPointer:
618 __ mov(i.OutputRegister(), sp);
619 DCHECK_EQ(LeaveCC, i.OutputSBit());
620 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 case kArchFramePointer:
622 __ mov(i.OutputRegister(), fp);
623 DCHECK_EQ(LeaveCC, i.OutputSBit());
624 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100625 case kArchParentFramePointer:
Ben Murdochda12d292016-06-02 14:46:10 +0100626 if (frame_access_state()->has_frame()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100627 __ ldr(i.OutputRegister(), MemOperand(fp, 0));
628 } else {
629 __ mov(i.OutputRegister(), fp);
630 }
631 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632 case kArchTruncateDoubleToI:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100633 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 DCHECK_EQ(LeaveCC, i.OutputSBit());
635 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636 case kArchStoreWithWriteBarrier: {
637 RecordWriteMode mode =
638 static_cast<RecordWriteMode>(MiscField::decode(instr->opcode()));
639 Register object = i.InputRegister(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640 Register value = i.InputRegister(2);
641 Register scratch0 = i.TempRegister(0);
642 Register scratch1 = i.TempRegister(1);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100643 OutOfLineRecordWrite* ool;
644
645 AddressingMode addressing_mode =
646 AddressingModeField::decode(instr->opcode());
647 if (addressing_mode == kMode_Offset_RI) {
648 int32_t index = i.InputInt32(1);
649 ool = new (zone()) OutOfLineRecordWrite(this, object, index, value,
650 scratch0, scratch1, mode);
651 __ str(value, MemOperand(object, index));
652 } else {
653 DCHECK_EQ(kMode_Offset_RR, addressing_mode);
654 Register index(i.InputRegister(1));
655 ool = new (zone()) OutOfLineRecordWrite(this, object, index, value,
656 scratch0, scratch1, mode);
657 __ str(value, MemOperand(object, index));
658 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000659 __ CheckPageFlag(object, scratch0,
660 MemoryChunk::kPointersFromHereAreInterestingMask, ne,
661 ool->entry());
662 __ bind(ool->exit());
663 break;
664 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100665 case kArchStackSlot: {
666 FrameOffset offset =
667 frame_access_state()->GetFrameOffset(i.InputInt32(0));
668 Register base;
669 if (offset.from_stack_pointer()) {
670 base = sp;
671 } else {
672 base = fp;
673 }
674 __ add(i.OutputRegister(0), base, Operand(offset.offset()));
675 break;
676 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100677 case kIeee754Float64Atan:
678 ASSEMBLE_IEEE754_UNOP(atan);
679 break;
680 case kIeee754Float64Atan2:
681 ASSEMBLE_IEEE754_BINOP(atan2);
682 break;
683 case kIeee754Float64Cbrt:
684 ASSEMBLE_IEEE754_UNOP(cbrt);
685 break;
686 case kIeee754Float64Cos:
687 ASSEMBLE_IEEE754_UNOP(cos);
688 break;
689 case kIeee754Float64Exp:
690 ASSEMBLE_IEEE754_UNOP(exp);
691 break;
692 case kIeee754Float64Expm1:
693 ASSEMBLE_IEEE754_UNOP(expm1);
694 break;
695 case kIeee754Float64Atanh:
696 ASSEMBLE_IEEE754_UNOP(atanh);
697 break;
698 case kIeee754Float64Log:
699 ASSEMBLE_IEEE754_UNOP(log);
700 break;
701 case kIeee754Float64Log1p:
702 ASSEMBLE_IEEE754_UNOP(log1p);
703 break;
704 case kIeee754Float64Log2:
705 ASSEMBLE_IEEE754_UNOP(log2);
706 break;
707 case kIeee754Float64Log10:
708 ASSEMBLE_IEEE754_UNOP(log10);
709 break;
710 case kIeee754Float64Sin:
711 ASSEMBLE_IEEE754_UNOP(sin);
712 break;
713 case kIeee754Float64Tan:
714 ASSEMBLE_IEEE754_UNOP(tan);
715 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 case kArmAdd:
717 __ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
718 i.OutputSBit());
719 break;
720 case kArmAnd:
721 __ and_(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
722 i.OutputSBit());
723 break;
724 case kArmBic:
725 __ bic(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
726 i.OutputSBit());
727 break;
728 case kArmMul:
729 __ mul(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
730 i.OutputSBit());
731 break;
732 case kArmMla:
733 __ mla(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
734 i.InputRegister(2), i.OutputSBit());
735 break;
736 case kArmMls: {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100737 CpuFeatureScope scope(masm(), ARMv7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000738 __ mls(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
739 i.InputRegister(2));
740 DCHECK_EQ(LeaveCC, i.OutputSBit());
741 break;
742 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400743 case kArmSmmul:
744 __ smmul(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
745 DCHECK_EQ(LeaveCC, i.OutputSBit());
746 break;
747 case kArmSmmla:
748 __ smmla(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
749 i.InputRegister(2));
750 DCHECK_EQ(LeaveCC, i.OutputSBit());
751 break;
752 case kArmUmull:
753 __ umull(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
754 i.InputRegister(1), i.OutputSBit());
755 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 case kArmSdiv: {
757 CpuFeatureScope scope(masm(), SUDIV);
758 __ sdiv(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
759 DCHECK_EQ(LeaveCC, i.OutputSBit());
760 break;
761 }
762 case kArmUdiv: {
763 CpuFeatureScope scope(masm(), SUDIV);
764 __ udiv(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
765 DCHECK_EQ(LeaveCC, i.OutputSBit());
766 break;
767 }
768 case kArmMov:
769 __ Move(i.OutputRegister(), i.InputOperand2(0), i.OutputSBit());
770 break;
771 case kArmMvn:
772 __ mvn(i.OutputRegister(), i.InputOperand2(0), i.OutputSBit());
773 break;
774 case kArmOrr:
775 __ orr(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
776 i.OutputSBit());
777 break;
778 case kArmEor:
779 __ eor(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
780 i.OutputSBit());
781 break;
782 case kArmSub:
783 __ sub(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
784 i.OutputSBit());
785 break;
786 case kArmRsb:
787 __ rsb(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
788 i.OutputSBit());
789 break;
790 case kArmBfc: {
791 CpuFeatureScope scope(masm(), ARMv7);
792 __ bfc(i.OutputRegister(), i.InputInt8(1), i.InputInt8(2));
793 DCHECK_EQ(LeaveCC, i.OutputSBit());
794 break;
795 }
796 case kArmUbfx: {
797 CpuFeatureScope scope(masm(), ARMv7);
798 __ ubfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
799 i.InputInt8(2));
800 DCHECK_EQ(LeaveCC, i.OutputSBit());
801 break;
802 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100803 case kArmSbfx: {
804 CpuFeatureScope scope(masm(), ARMv7);
805 __ sbfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
806 i.InputInt8(2));
807 DCHECK_EQ(LeaveCC, i.OutputSBit());
808 break;
809 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400810 case kArmSxtb:
811 __ sxtb(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1));
812 DCHECK_EQ(LeaveCC, i.OutputSBit());
813 break;
814 case kArmSxth:
815 __ sxth(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1));
816 DCHECK_EQ(LeaveCC, i.OutputSBit());
817 break;
818 case kArmSxtab:
819 __ sxtab(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
820 i.InputInt32(2));
821 DCHECK_EQ(LeaveCC, i.OutputSBit());
822 break;
823 case kArmSxtah:
824 __ sxtah(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
825 i.InputInt32(2));
826 DCHECK_EQ(LeaveCC, i.OutputSBit());
827 break;
828 case kArmUxtb:
829 __ uxtb(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1));
830 DCHECK_EQ(LeaveCC, i.OutputSBit());
831 break;
832 case kArmUxth:
833 __ uxth(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1));
834 DCHECK_EQ(LeaveCC, i.OutputSBit());
835 break;
836 case kArmUxtab:
837 __ uxtab(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
838 i.InputInt32(2));
839 DCHECK_EQ(LeaveCC, i.OutputSBit());
840 break;
841 case kArmUxtah:
842 __ uxtah(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
843 i.InputInt32(2));
844 DCHECK_EQ(LeaveCC, i.OutputSBit());
845 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100846 case kArmRbit: {
847 CpuFeatureScope scope(masm(), ARMv7);
848 __ rbit(i.OutputRegister(), i.InputRegister(0));
849 DCHECK_EQ(LeaveCC, i.OutputSBit());
850 break;
851 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 case kArmClz:
853 __ clz(i.OutputRegister(), i.InputRegister(0));
854 DCHECK_EQ(LeaveCC, i.OutputSBit());
855 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856 case kArmCmp:
857 __ cmp(i.InputRegister(0), i.InputOperand2(1));
858 DCHECK_EQ(SetCC, i.OutputSBit());
859 break;
860 case kArmCmn:
861 __ cmn(i.InputRegister(0), i.InputOperand2(1));
862 DCHECK_EQ(SetCC, i.OutputSBit());
863 break;
864 case kArmTst:
865 __ tst(i.InputRegister(0), i.InputOperand2(1));
866 DCHECK_EQ(SetCC, i.OutputSBit());
867 break;
868 case kArmTeq:
869 __ teq(i.InputRegister(0), i.InputOperand2(1));
870 DCHECK_EQ(SetCC, i.OutputSBit());
871 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100872 case kArmAddPair:
873 // i.InputRegister(0) ... left low word.
874 // i.InputRegister(1) ... left high word.
875 // i.InputRegister(2) ... right low word.
876 // i.InputRegister(3) ... right high word.
877 __ add(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2),
878 SBit::SetCC);
879 __ adc(i.OutputRegister(1), i.InputRegister(1),
880 Operand(i.InputRegister(3)));
881 DCHECK_EQ(LeaveCC, i.OutputSBit());
882 break;
883 case kArmSubPair:
884 // i.InputRegister(0) ... left low word.
885 // i.InputRegister(1) ... left high word.
886 // i.InputRegister(2) ... right low word.
887 // i.InputRegister(3) ... right high word.
888 __ sub(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2),
889 SBit::SetCC);
890 __ sbc(i.OutputRegister(1), i.InputRegister(1),
891 Operand(i.InputRegister(3)));
892 DCHECK_EQ(LeaveCC, i.OutputSBit());
893 break;
894 case kArmMulPair:
895 // i.InputRegister(0) ... left low word.
896 // i.InputRegister(1) ... left high word.
897 // i.InputRegister(2) ... right low word.
898 // i.InputRegister(3) ... right high word.
899 __ umull(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
900 i.InputRegister(2));
901 __ mla(i.OutputRegister(1), i.InputRegister(0), i.InputRegister(3),
902 i.OutputRegister(1));
903 __ mla(i.OutputRegister(1), i.InputRegister(2), i.InputRegister(1),
904 i.OutputRegister(1));
905 break;
906 case kArmLslPair:
907 if (instr->InputAt(2)->IsImmediate()) {
908 __ LslPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
909 i.InputRegister(1), i.InputInt32(2));
910 } else {
911 __ LslPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
912 i.InputRegister(1), kScratchReg, i.InputRegister(2));
913 }
914 break;
915 case kArmLsrPair:
916 if (instr->InputAt(2)->IsImmediate()) {
917 __ LsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
918 i.InputRegister(1), i.InputInt32(2));
919 } else {
920 __ LsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
921 i.InputRegister(1), kScratchReg, i.InputRegister(2));
922 }
923 break;
924 case kArmAsrPair:
925 if (instr->InputAt(2)->IsImmediate()) {
926 __ AsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
927 i.InputRegister(1), i.InputInt32(2));
928 } else {
929 __ AsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
930 i.InputRegister(1), kScratchReg, i.InputRegister(2));
931 }
932 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000933 case kArmVcmpF32:
Ben Murdochc5610432016-08-08 18:44:38 +0100934 if (instr->InputAt(1)->IsFPRegister()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100935 __ VFPCompareAndSetFlags(i.InputFloatRegister(0),
936 i.InputFloatRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 } else {
938 DCHECK(instr->InputAt(1)->IsImmediate());
939 // 0.0 is the only immediate supported by vcmp instructions.
940 DCHECK(i.InputFloat32(1) == 0.0f);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100941 __ VFPCompareAndSetFlags(i.InputFloatRegister(0), i.InputFloat32(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 }
943 DCHECK_EQ(SetCC, i.OutputSBit());
944 break;
945 case kArmVaddF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100946 __ vadd(i.OutputFloatRegister(), i.InputFloatRegister(0),
947 i.InputFloatRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948 DCHECK_EQ(LeaveCC, i.OutputSBit());
949 break;
950 case kArmVsubF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100951 __ vsub(i.OutputFloatRegister(), i.InputFloatRegister(0),
952 i.InputFloatRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000953 DCHECK_EQ(LeaveCC, i.OutputSBit());
954 break;
955 case kArmVmulF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100956 __ vmul(i.OutputFloatRegister(), i.InputFloatRegister(0),
957 i.InputFloatRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000958 DCHECK_EQ(LeaveCC, i.OutputSBit());
959 break;
960 case kArmVmlaF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100961 __ vmla(i.OutputFloatRegister(), i.InputFloatRegister(1),
962 i.InputFloatRegister(2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000963 DCHECK_EQ(LeaveCC, i.OutputSBit());
964 break;
965 case kArmVmlsF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100966 __ vmls(i.OutputFloatRegister(), i.InputFloatRegister(1),
967 i.InputFloatRegister(2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 DCHECK_EQ(LeaveCC, i.OutputSBit());
969 break;
970 case kArmVdivF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100971 __ vdiv(i.OutputFloatRegister(), i.InputFloatRegister(0),
972 i.InputFloatRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 DCHECK_EQ(LeaveCC, i.OutputSBit());
974 break;
975 case kArmVsqrtF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100976 __ vsqrt(i.OutputFloatRegister(), i.InputFloatRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 break;
978 case kArmVabsF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100979 __ vabs(i.OutputFloatRegister(), i.InputFloatRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 break;
981 case kArmVnegF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100982 __ vneg(i.OutputFloatRegister(), i.InputFloatRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000983 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000984 case kArmVcmpF64:
Ben Murdochc5610432016-08-08 18:44:38 +0100985 if (instr->InputAt(1)->IsFPRegister()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100986 __ VFPCompareAndSetFlags(i.InputDoubleRegister(0),
987 i.InputDoubleRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988 } else {
989 DCHECK(instr->InputAt(1)->IsImmediate());
990 // 0.0 is the only immediate supported by vcmp instructions.
991 DCHECK(i.InputDouble(1) == 0.0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100992 __ VFPCompareAndSetFlags(i.InputDoubleRegister(0), i.InputDouble(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000994 DCHECK_EQ(SetCC, i.OutputSBit());
995 break;
996 case kArmVaddF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100997 __ vadd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
998 i.InputDoubleRegister(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000999 DCHECK_EQ(LeaveCC, i.OutputSBit());
1000 break;
1001 case kArmVsubF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001002 __ vsub(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
1003 i.InputDoubleRegister(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 DCHECK_EQ(LeaveCC, i.OutputSBit());
1005 break;
1006 case kArmVmulF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001007 __ vmul(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
1008 i.InputDoubleRegister(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001009 DCHECK_EQ(LeaveCC, i.OutputSBit());
1010 break;
1011 case kArmVmlaF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001012 __ vmla(i.OutputDoubleRegister(), i.InputDoubleRegister(1),
1013 i.InputDoubleRegister(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 DCHECK_EQ(LeaveCC, i.OutputSBit());
1015 break;
1016 case kArmVmlsF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001017 __ vmls(i.OutputDoubleRegister(), i.InputDoubleRegister(1),
1018 i.InputDoubleRegister(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001019 DCHECK_EQ(LeaveCC, i.OutputSBit());
1020 break;
1021 case kArmVdivF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001022 __ vdiv(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
1023 i.InputDoubleRegister(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001024 DCHECK_EQ(LeaveCC, i.OutputSBit());
1025 break;
1026 case kArmVmodF64: {
1027 // TODO(bmeurer): We should really get rid of this special instruction,
1028 // and generate a CallAddress instruction instead.
1029 FrameScope scope(masm(), StackFrame::MANUAL);
1030 __ PrepareCallCFunction(0, 2, kScratchReg);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001031 __ MovToFloatParameters(i.InputDoubleRegister(0),
1032 i.InputDoubleRegister(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()),
1034 0, 2);
1035 // Move the result in the double result register.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001036 __ MovFromFloatResult(i.OutputDoubleRegister());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037 DCHECK_EQ(LeaveCC, i.OutputSBit());
1038 break;
1039 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001040 case kArmVsqrtF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001041 __ vsqrt(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 case kArmVabsF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001044 __ vabs(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001045 break;
1046 case kArmVnegF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001047 __ vneg(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001048 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 case kArmVrintmF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001050 __ vrintm(i.OutputFloatRegister(), i.InputFloatRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001051 break;
1052 case kArmVrintmF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001053 __ vrintm(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001054 break;
1055 case kArmVrintpF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001056 __ vrintp(i.OutputFloatRegister(), i.InputFloatRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001057 break;
1058 case kArmVrintpF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001059 __ vrintp(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001060 break;
1061 case kArmVrintzF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001062 __ vrintz(i.OutputFloatRegister(), i.InputFloatRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001063 break;
1064 case kArmVrintzF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001065 __ vrintz(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001066 break;
1067 case kArmVrintaF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001068 __ vrinta(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001069 break;
1070 case kArmVrintnF32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001071 __ vrintn(i.OutputFloatRegister(), i.InputFloatRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 break;
1073 case kArmVrintnF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001074 __ vrintn(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001076 case kArmVcvtF32F64: {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001077 __ vcvt_f32_f64(i.OutputFloatRegister(), i.InputDoubleRegister(0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001078 DCHECK_EQ(LeaveCC, i.OutputSBit());
1079 break;
1080 }
1081 case kArmVcvtF64F32: {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001082 __ vcvt_f64_f32(i.OutputDoubleRegister(), i.InputFloatRegister(0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001083 DCHECK_EQ(LeaveCC, i.OutputSBit());
1084 break;
1085 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001086 case kArmVcvtF32S32: {
1087 SwVfpRegister scratch = kScratchDoubleReg.low();
1088 __ vmov(scratch, i.InputRegister(0));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001089 __ vcvt_f32_s32(i.OutputFloatRegister(), scratch);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001090 DCHECK_EQ(LeaveCC, i.OutputSBit());
1091 break;
1092 }
1093 case kArmVcvtF32U32: {
1094 SwVfpRegister scratch = kScratchDoubleReg.low();
1095 __ vmov(scratch, i.InputRegister(0));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001096 __ vcvt_f32_u32(i.OutputFloatRegister(), scratch);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001097 DCHECK_EQ(LeaveCC, i.OutputSBit());
1098 break;
1099 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001100 case kArmVcvtF64S32: {
1101 SwVfpRegister scratch = kScratchDoubleReg.low();
1102 __ vmov(scratch, i.InputRegister(0));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001103 __ vcvt_f64_s32(i.OutputDoubleRegister(), scratch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 DCHECK_EQ(LeaveCC, i.OutputSBit());
1105 break;
1106 }
1107 case kArmVcvtF64U32: {
1108 SwVfpRegister scratch = kScratchDoubleReg.low();
1109 __ vmov(scratch, i.InputRegister(0));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001110 __ vcvt_f64_u32(i.OutputDoubleRegister(), scratch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001111 DCHECK_EQ(LeaveCC, i.OutputSBit());
1112 break;
1113 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001114 case kArmVcvtS32F32: {
1115 SwVfpRegister scratch = kScratchDoubleReg.low();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001116 __ vcvt_s32_f32(scratch, i.InputFloatRegister(0));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001117 __ vmov(i.OutputRegister(), scratch);
1118 DCHECK_EQ(LeaveCC, i.OutputSBit());
1119 break;
1120 }
1121 case kArmVcvtU32F32: {
1122 SwVfpRegister scratch = kScratchDoubleReg.low();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001123 __ vcvt_u32_f32(scratch, i.InputFloatRegister(0));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001124 __ vmov(i.OutputRegister(), scratch);
1125 DCHECK_EQ(LeaveCC, i.OutputSBit());
1126 break;
1127 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128 case kArmVcvtS32F64: {
1129 SwVfpRegister scratch = kScratchDoubleReg.low();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001130 __ vcvt_s32_f64(scratch, i.InputDoubleRegister(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 __ vmov(i.OutputRegister(), scratch);
1132 DCHECK_EQ(LeaveCC, i.OutputSBit());
1133 break;
1134 }
1135 case kArmVcvtU32F64: {
1136 SwVfpRegister scratch = kScratchDoubleReg.low();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001137 __ vcvt_u32_f64(scratch, i.InputDoubleRegister(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001138 __ vmov(i.OutputRegister(), scratch);
1139 DCHECK_EQ(LeaveCC, i.OutputSBit());
1140 break;
1141 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001142 case kArmVmovU32F32:
1143 __ vmov(i.OutputRegister(), i.InputFloatRegister(0));
1144 DCHECK_EQ(LeaveCC, i.OutputSBit());
1145 break;
1146 case kArmVmovF32U32:
1147 __ vmov(i.OutputFloatRegister(), i.InputRegister(0));
1148 DCHECK_EQ(LeaveCC, i.OutputSBit());
1149 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 case kArmVmovLowU32F64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001151 __ VmovLow(i.OutputRegister(), i.InputDoubleRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001152 DCHECK_EQ(LeaveCC, i.OutputSBit());
1153 break;
1154 case kArmVmovLowF64U32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001155 __ VmovLow(i.OutputDoubleRegister(), i.InputRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001156 DCHECK_EQ(LeaveCC, i.OutputSBit());
1157 break;
1158 case kArmVmovHighU32F64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001159 __ VmovHigh(i.OutputRegister(), i.InputDoubleRegister(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 DCHECK_EQ(LeaveCC, i.OutputSBit());
1161 break;
1162 case kArmVmovHighF64U32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001163 __ VmovHigh(i.OutputDoubleRegister(), i.InputRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 DCHECK_EQ(LeaveCC, i.OutputSBit());
1165 break;
1166 case kArmVmovF64U32U32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001167 __ vmov(i.OutputDoubleRegister(), i.InputRegister(0), i.InputRegister(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001168 DCHECK_EQ(LeaveCC, i.OutputSBit());
1169 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001170 case kArmLdrb:
1171 __ ldrb(i.OutputRegister(), i.InputOffset());
1172 DCHECK_EQ(LeaveCC, i.OutputSBit());
1173 break;
1174 case kArmLdrsb:
1175 __ ldrsb(i.OutputRegister(), i.InputOffset());
1176 DCHECK_EQ(LeaveCC, i.OutputSBit());
1177 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001178 case kArmStrb:
1179 __ strb(i.InputRegister(0), i.InputOffset(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 DCHECK_EQ(LeaveCC, i.OutputSBit());
1181 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001182 case kArmLdrh:
1183 __ ldrh(i.OutputRegister(), i.InputOffset());
1184 break;
1185 case kArmLdrsh:
1186 __ ldrsh(i.OutputRegister(), i.InputOffset());
1187 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001188 case kArmStrh:
1189 __ strh(i.InputRegister(0), i.InputOffset(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001190 DCHECK_EQ(LeaveCC, i.OutputSBit());
1191 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 case kArmLdr:
1193 __ ldr(i.OutputRegister(), i.InputOffset());
1194 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001195 case kArmStr:
1196 __ str(i.InputRegister(0), i.InputOffset(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001197 DCHECK_EQ(LeaveCC, i.OutputSBit());
1198 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001199 case kArmVldrF32: {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001200 __ vldr(i.OutputFloatRegister(), i.InputOffset());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001201 DCHECK_EQ(LeaveCC, i.OutputSBit());
1202 break;
1203 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001204 case kArmVstrF32:
1205 __ vstr(i.InputFloatRegister(0), i.InputOffset(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206 DCHECK_EQ(LeaveCC, i.OutputSBit());
1207 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001208 case kArmVldrF64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001209 __ vldr(i.OutputDoubleRegister(), i.InputOffset());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 DCHECK_EQ(LeaveCC, i.OutputSBit());
1211 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001212 case kArmVstrF64:
1213 __ vstr(i.InputDoubleRegister(0), i.InputOffset(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 DCHECK_EQ(LeaveCC, i.OutputSBit());
1215 break;
Ben Murdochc5610432016-08-08 18:44:38 +01001216 case kArmFloat32Max: {
1217 CpuFeatureScope scope(masm(), ARMv8);
1218 // (b < a) ? a : b
Ben Murdoch61f157c2016-09-16 13:49:30 +01001219 SwVfpRegister a = i.InputFloatRegister(0);
1220 SwVfpRegister b = i.InputFloatRegister(1);
1221 SwVfpRegister result = i.OutputFloatRegister();
Ben Murdochc5610432016-08-08 18:44:38 +01001222 __ VFPCompareAndSetFlags(a, b);
1223 __ vsel(gt, result, a, b);
1224 break;
1225 }
1226 case kArmFloat32Min: {
1227 CpuFeatureScope scope(masm(), ARMv8);
1228 // (a < b) ? a : b
Ben Murdoch61f157c2016-09-16 13:49:30 +01001229 SwVfpRegister a = i.InputFloatRegister(0);
1230 SwVfpRegister b = i.InputFloatRegister(1);
1231 SwVfpRegister result = i.OutputFloatRegister();
Ben Murdochc5610432016-08-08 18:44:38 +01001232 __ VFPCompareAndSetFlags(b, a);
1233 __ vsel(gt, result, a, b);
1234 break;
1235 }
1236 case kArmFloat64Max: {
1237 CpuFeatureScope scope(masm(), ARMv8);
1238 // (b < a) ? a : b
Ben Murdoch61f157c2016-09-16 13:49:30 +01001239 DwVfpRegister a = i.InputDoubleRegister(0);
1240 DwVfpRegister b = i.InputDoubleRegister(1);
1241 DwVfpRegister result = i.OutputDoubleRegister();
Ben Murdochc5610432016-08-08 18:44:38 +01001242 __ VFPCompareAndSetFlags(a, b);
1243 __ vsel(gt, result, a, b);
1244 break;
1245 }
1246 case kArmFloat64Min: {
1247 CpuFeatureScope scope(masm(), ARMv8);
1248 // (a < b) ? a : b
Ben Murdoch61f157c2016-09-16 13:49:30 +01001249 DwVfpRegister a = i.InputDoubleRegister(0);
1250 DwVfpRegister b = i.InputDoubleRegister(1);
1251 DwVfpRegister result = i.OutputDoubleRegister();
Ben Murdochc5610432016-08-08 18:44:38 +01001252 __ VFPCompareAndSetFlags(b, a);
1253 __ vsel(gt, result, a, b);
1254 break;
1255 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001256 case kArmFloat64SilenceNaN: {
1257 DwVfpRegister value = i.InputDoubleRegister(0);
1258 DwVfpRegister result = i.OutputDoubleRegister();
1259 __ VFPCanonicalizeNaN(result, value);
1260 break;
1261 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001262 case kArmPush:
Ben Murdochc5610432016-08-08 18:44:38 +01001263 if (instr->InputAt(0)->IsFPRegister()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001264 LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
1265 if (op->representation() == MachineRepresentation::kFloat64) {
1266 __ vpush(i.InputDoubleRegister(0));
1267 frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1268 } else {
1269 DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
1270 __ vpush(i.InputFloatRegister(0));
1271 frame_access_state()->IncreaseSPDelta(1);
1272 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001273 } else {
1274 __ push(i.InputRegister(0));
1275 frame_access_state()->IncreaseSPDelta(1);
1276 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277 DCHECK_EQ(LeaveCC, i.OutputSBit());
1278 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001279 case kArmPoke: {
1280 int const slot = MiscField::decode(instr->opcode());
1281 __ str(i.InputRegister(0), MemOperand(sp, slot * kPointerSize));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 DCHECK_EQ(LeaveCC, i.OutputSBit());
1283 break;
1284 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001285 case kCheckedLoadInt8:
1286 ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsb);
1287 break;
1288 case kCheckedLoadUint8:
1289 ASSEMBLE_CHECKED_LOAD_INTEGER(ldrb);
1290 break;
1291 case kCheckedLoadInt16:
1292 ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsh);
1293 break;
1294 case kCheckedLoadUint16:
1295 ASSEMBLE_CHECKED_LOAD_INTEGER(ldrh);
1296 break;
1297 case kCheckedLoadWord32:
1298 ASSEMBLE_CHECKED_LOAD_INTEGER(ldr);
1299 break;
1300 case kCheckedLoadFloat32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001301 ASSEMBLE_CHECKED_LOAD_FP(Float);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001302 break;
1303 case kCheckedLoadFloat64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001304 ASSEMBLE_CHECKED_LOAD_FP(Double);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001305 break;
1306 case kCheckedStoreWord8:
1307 ASSEMBLE_CHECKED_STORE_INTEGER(strb);
1308 break;
1309 case kCheckedStoreWord16:
1310 ASSEMBLE_CHECKED_STORE_INTEGER(strh);
1311 break;
1312 case kCheckedStoreWord32:
1313 ASSEMBLE_CHECKED_STORE_INTEGER(str);
1314 break;
1315 case kCheckedStoreFloat32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001316 ASSEMBLE_CHECKED_STORE_FP(Float);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001317 break;
1318 case kCheckedStoreFloat64:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001319 ASSEMBLE_CHECKED_STORE_FP(Double);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001320 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 case kCheckedLoadWord64:
1322 case kCheckedStoreWord64:
1323 UNREACHABLE(); // currently unsupported checked int64 load/store.
1324 break;
Ben Murdochc5610432016-08-08 18:44:38 +01001325
1326 case kAtomicLoadInt8:
1327 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrsb);
1328 break;
1329 case kAtomicLoadUint8:
1330 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrb);
1331 break;
1332 case kAtomicLoadInt16:
1333 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrsh);
1334 break;
1335 case kAtomicLoadUint16:
1336 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrh);
1337 break;
1338 case kAtomicLoadWord32:
1339 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldr);
1340 break;
1341
1342 case kAtomicStoreWord8:
1343 ASSEMBLE_ATOMIC_STORE_INTEGER(strb);
1344 break;
1345 case kAtomicStoreWord16:
1346 ASSEMBLE_ATOMIC_STORE_INTEGER(strh);
1347 break;
1348 case kAtomicStoreWord32:
1349 ASSEMBLE_ATOMIC_STORE_INTEGER(str);
1350 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001351 }
Ben Murdochc5610432016-08-08 18:44:38 +01001352 return kSuccess;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001353} // NOLINT(readability/fn_size)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001354
1355
1356// Assembles branches after an instruction.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001357void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001358 ArmOperandConverter i(this, instr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001359 Label* tlabel = branch->true_label;
1360 Label* flabel = branch->false_label;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001361 Condition cc = FlagsConditionToCondition(branch->condition);
1362 __ b(cc, tlabel);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001363 if (!branch->fallthru) __ b(flabel); // no fallthru to flabel.
1364}
1365
1366
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001367void CodeGenerator::AssembleArchJump(RpoNumber target) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001368 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001369}
1370
1371
1372// Assembles boolean materializations after an instruction.
1373void CodeGenerator::AssembleArchBoolean(Instruction* instr,
1374 FlagsCondition condition) {
1375 ArmOperandConverter i(this, instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001376
1377 // Materialize a full 32-bit 1 or 0 value. The result register is always the
1378 // last output of the instruction.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001379 DCHECK_NE(0u, instr->OutputCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001380 Register reg = i.OutputRegister(instr->OutputCount() - 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001381 Condition cc = FlagsConditionToCondition(condition);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001382 __ mov(reg, Operand(0));
1383 __ mov(reg, Operand(1), LeaveCC, cc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384}
1385
1386
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001387void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
1388 ArmOperandConverter i(this, instr);
1389 Register input = i.InputRegister(0);
1390 for (size_t index = 2; index < instr->InputCount(); index += 2) {
1391 __ cmp(input, Operand(i.InputInt32(index + 0)));
1392 __ b(eq, GetLabel(i.InputRpo(index + 1)));
1393 }
1394 AssembleArchJump(i.InputRpo(1));
1395}
1396
1397
1398void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
1399 ArmOperandConverter i(this, instr);
1400 Register input = i.InputRegister(0);
1401 size_t const case_count = instr->InputCount() - 2;
1402 // Ensure to emit the constant pool first if necessary.
1403 __ CheckConstPool(true, true);
1404 __ cmp(input, Operand(case_count));
1405 __ BlockConstPoolFor(case_count + 2);
1406 __ add(pc, pc, Operand(input, LSL, 2), LeaveCC, lo);
1407 __ b(GetLabel(i.InputRpo(1)));
1408 for (size_t index = 0; index < case_count; ++index) {
1409 __ b(GetLabel(i.InputRpo(index + 2)));
1410 }
1411}
1412
Ben Murdochc5610432016-08-08 18:44:38 +01001413CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414 int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001415 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 isolate(), deoptimization_id, bailout_type);
Ben Murdochda12d292016-06-02 14:46:10 +01001417 // TODO(turbofan): We should be able to generate better code by sharing the
1418 // actual final call site and just bl'ing to it here, similar to what we do
1419 // in the lithium backend.
Ben Murdochc5610432016-08-08 18:44:38 +01001420 if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001421 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
Ben Murdochda12d292016-06-02 14:46:10 +01001422 __ CheckConstPool(false, false);
Ben Murdochc5610432016-08-08 18:44:38 +01001423 return kSuccess;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001424}
1425
Ben Murdochc5610432016-08-08 18:44:38 +01001426void CodeGenerator::FinishFrame(Frame* frame) {
1427 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001428
Ben Murdochc5610432016-08-08 18:44:38 +01001429 const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
1430 if (saves_fp != 0) {
1431 frame->AlignSavedCalleeRegisterSlots();
1432 }
1433
1434 if (saves_fp != 0) {
1435 // Save callee-saved FP registers.
1436 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
1437 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
1438 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
1439 DCHECK_EQ((last - first + 1), base::bits::CountPopulation32(saves_fp));
1440 frame->AllocateSavedCalleeRegisterSlots((last - first + 1) *
1441 (kDoubleSize / kPointerSize));
1442 }
1443 const RegList saves = FLAG_enable_embedded_constant_pool
1444 ? (descriptor->CalleeSavedRegisters() & ~pp.bit())
1445 : descriptor->CalleeSavedRegisters();
1446 if (saves != 0) {
1447 // Save callee-saved registers.
1448 frame->AllocateSavedCalleeRegisterSlots(
1449 base::bits::CountPopulation32(saves));
1450 }
1451}
1452
1453void CodeGenerator::AssembleConstructFrame() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001454 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
Ben Murdochda12d292016-06-02 14:46:10 +01001455 if (frame_access_state()->has_frame()) {
1456 if (descriptor->IsCFunctionCall()) {
1457 if (FLAG_enable_embedded_constant_pool) {
1458 __ Push(lr, fp, pp);
1459 // Adjust FP to point to saved FP.
1460 __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
1461 } else {
1462 __ Push(lr, fp);
1463 __ mov(fp, sp);
1464 }
1465 } else if (descriptor->IsJSFunctionCall()) {
1466 __ Prologue(this->info()->GeneratePreagedPrologue());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001467 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001468 __ StubPrologue(info()->GetOutputStackFrameType());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001470 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001471
Ben Murdochc5610432016-08-08 18:44:38 +01001472 int shrink_slots = frame()->GetSpillSlotCount();
1473
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001474 if (info()->is_osr()) {
1475 // TurboFan OSR-compiled functions cannot be entered directly.
1476 __ Abort(kShouldNotDirectlyEnterOsrFunction);
1477
1478 // Unoptimized code jumps directly to this entrypoint while the unoptimized
1479 // frame is still on the stack. Optimized code uses OSR values directly from
1480 // the unoptimized frame. Thus, all that needs to be done is to allocate the
1481 // remaining stack slots.
1482 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
1483 osr_pc_offset_ = __ pc_offset();
Ben Murdochc5610432016-08-08 18:44:38 +01001484 shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001485 }
1486
1487 const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
Ben Murdochc5610432016-08-08 18:44:38 +01001488 if (shrink_slots > 0) {
1489 __ sub(sp, sp, Operand(shrink_slots * kPointerSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490 }
1491
1492 if (saves_fp != 0) {
1493 // Save callee-saved FP registers.
1494 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
1495 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
1496 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
1497 DCHECK_EQ((last - first + 1), base::bits::CountPopulation32(saves_fp));
1498 __ vstm(db_w, sp, DwVfpRegister::from_code(first),
1499 DwVfpRegister::from_code(last));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001500 }
1501 const RegList saves = FLAG_enable_embedded_constant_pool
1502 ? (descriptor->CalleeSavedRegisters() & ~pp.bit())
1503 : descriptor->CalleeSavedRegisters();
1504 if (saves != 0) {
1505 // Save callee-saved registers.
1506 __ stm(db_w, sp, saves);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001507 }
1508}
1509
1510
1511void CodeGenerator::AssembleReturn() {
1512 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001513 int pop_count = static_cast<int>(descriptor->StackParameterCount());
1514
1515 // Restore registers.
1516 const RegList saves = FLAG_enable_embedded_constant_pool
1517 ? (descriptor->CalleeSavedRegisters() & ~pp.bit())
1518 : descriptor->CalleeSavedRegisters();
1519 if (saves != 0) {
1520 __ ldm(ia_w, sp, saves);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001521 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001522
1523 // Restore FP registers.
1524 const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
1525 if (saves_fp != 0) {
1526 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
1527 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
1528 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
1529 __ vldm(ia_w, sp, DwVfpRegister::from_code(first),
1530 DwVfpRegister::from_code(last));
1531 }
1532
1533 if (descriptor->IsCFunctionCall()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001534 AssembleDeconstructFrame();
1535 } else if (frame_access_state()->has_frame()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001536 // Canonicalize JSFunction return sites for now.
1537 if (return_label_.is_bound()) {
1538 __ b(&return_label_);
1539 return;
1540 } else {
1541 __ bind(&return_label_);
Ben Murdochda12d292016-06-02 14:46:10 +01001542 AssembleDeconstructFrame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001543 }
1544 }
1545 __ Ret(pop_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001546}
1547
1548
1549void CodeGenerator::AssembleMove(InstructionOperand* source,
1550 InstructionOperand* destination) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 ArmOperandConverter g(this, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001552 // Dispatch on the source and destination operand kinds. Not all
1553 // combinations are possible.
1554 if (source->IsRegister()) {
1555 DCHECK(destination->IsRegister() || destination->IsStackSlot());
1556 Register src = g.ToRegister(source);
1557 if (destination->IsRegister()) {
1558 __ mov(g.ToRegister(destination), src);
1559 } else {
1560 __ str(src, g.ToMemOperand(destination));
1561 }
1562 } else if (source->IsStackSlot()) {
1563 DCHECK(destination->IsRegister() || destination->IsStackSlot());
1564 MemOperand src = g.ToMemOperand(source);
1565 if (destination->IsRegister()) {
1566 __ ldr(g.ToRegister(destination), src);
1567 } else {
1568 Register temp = kScratchReg;
1569 __ ldr(temp, src);
1570 __ str(temp, g.ToMemOperand(destination));
1571 }
1572 } else if (source->IsConstant()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001573 Constant src = g.ToConstant(source);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001574 if (destination->IsRegister() || destination->IsStackSlot()) {
1575 Register dst =
1576 destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001577 switch (src.type()) {
1578 case Constant::kInt32:
Ben Murdochc5610432016-08-08 18:44:38 +01001579 if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
Ben Murdoch61f157c2016-09-16 13:49:30 +01001580 src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
Ben Murdochc5610432016-08-08 18:44:38 +01001581 src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
1582 __ mov(dst, Operand(src.ToInt32(), src.rmode()));
1583 } else {
1584 __ mov(dst, Operand(src.ToInt32()));
1585 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001586 break;
1587 case Constant::kInt64:
1588 UNREACHABLE();
1589 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001590 case Constant::kFloat32:
1591 __ Move(dst,
1592 isolate()->factory()->NewNumber(src.ToFloat32(), TENURED));
1593 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001594 case Constant::kFloat64:
1595 __ Move(dst,
1596 isolate()->factory()->NewNumber(src.ToFloat64(), TENURED));
1597 break;
1598 case Constant::kExternalReference:
1599 __ mov(dst, Operand(src.ToExternalReference()));
1600 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001601 case Constant::kHeapObject: {
1602 Handle<HeapObject> src_object = src.ToHeapObject();
1603 Heap::RootListIndex index;
Ben Murdochda12d292016-06-02 14:46:10 +01001604 int slot;
1605 if (IsMaterializableFromFrame(src_object, &slot)) {
1606 __ ldr(dst, g.SlotToMemOperand(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001607 } else if (IsMaterializableFromRoot(src_object, &index)) {
1608 __ LoadRoot(dst, index);
1609 } else {
1610 __ Move(dst, src_object);
1611 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001612 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001614 case Constant::kRpoNumber:
1615 UNREACHABLE(); // TODO(dcarney): loading RPO constants on arm.
1616 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617 }
1618 if (destination->IsStackSlot()) __ str(dst, g.ToMemOperand(destination));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001619 } else if (src.type() == Constant::kFloat32) {
Ben Murdochc5610432016-08-08 18:44:38 +01001620 if (destination->IsFPStackSlot()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001621 MemOperand dst = g.ToMemOperand(destination);
1622 __ mov(ip, Operand(bit_cast<int32_t>(src.ToFloat32())));
1623 __ str(ip, dst);
1624 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001625 SwVfpRegister dst = g.ToFloatRegister(destination);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001626 __ vmov(dst, src.ToFloat32());
1627 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001628 } else {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001629 DCHECK_EQ(Constant::kFloat64, src.type());
Ben Murdochc5610432016-08-08 18:44:38 +01001630 DwVfpRegister dst = destination->IsFPRegister()
Ben Murdoch61f157c2016-09-16 13:49:30 +01001631 ? g.ToDoubleRegister(destination)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001632 : kScratchDoubleReg;
1633 __ vmov(dst, src.ToFloat64(), kScratchReg);
Ben Murdochc5610432016-08-08 18:44:38 +01001634 if (destination->IsFPStackSlot()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001635 __ vstr(dst, g.ToMemOperand(destination));
1636 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001637 }
Ben Murdochc5610432016-08-08 18:44:38 +01001638 } else if (source->IsFPRegister()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001639 MachineRepresentation rep = LocationOperand::cast(source)->representation();
1640 if (rep == MachineRepresentation::kFloat64) {
1641 DwVfpRegister src = g.ToDoubleRegister(source);
1642 if (destination->IsFPRegister()) {
1643 DwVfpRegister dst = g.ToDoubleRegister(destination);
1644 __ Move(dst, src);
1645 } else {
1646 DCHECK(destination->IsFPStackSlot());
1647 __ vstr(src, g.ToMemOperand(destination));
1648 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001649 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001650 DCHECK_EQ(MachineRepresentation::kFloat32, rep);
1651 SwVfpRegister src = g.ToFloatRegister(source);
1652 if (destination->IsFPRegister()) {
1653 SwVfpRegister dst = g.ToFloatRegister(destination);
1654 __ Move(dst, src);
1655 } else {
1656 DCHECK(destination->IsFPStackSlot());
1657 __ vstr(src, g.ToMemOperand(destination));
1658 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001659 }
Ben Murdochc5610432016-08-08 18:44:38 +01001660 } else if (source->IsFPStackSlot()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001661 MemOperand src = g.ToMemOperand(source);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001662 MachineRepresentation rep =
1663 LocationOperand::cast(destination)->representation();
Ben Murdochc5610432016-08-08 18:44:38 +01001664 if (destination->IsFPRegister()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001665 if (rep == MachineRepresentation::kFloat64) {
1666 __ vldr(g.ToDoubleRegister(destination), src);
1667 } else {
1668 DCHECK_EQ(MachineRepresentation::kFloat32, rep);
1669 __ vldr(g.ToFloatRegister(destination), src);
1670 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001671 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001672 DCHECK(destination->IsFPStackSlot());
1673 if (rep == MachineRepresentation::kFloat64) {
1674 DwVfpRegister temp = kScratchDoubleReg;
1675 __ vldr(temp, src);
1676 __ vstr(temp, g.ToMemOperand(destination));
1677 } else {
1678 DCHECK_EQ(MachineRepresentation::kFloat32, rep);
1679 SwVfpRegister temp = kScratchDoubleReg.low();
1680 __ vldr(temp, src);
1681 __ vstr(temp, g.ToMemOperand(destination));
1682 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001683 }
1684 } else {
1685 UNREACHABLE();
1686 }
1687}
1688
1689
1690void CodeGenerator::AssembleSwap(InstructionOperand* source,
1691 InstructionOperand* destination) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001692 ArmOperandConverter g(this, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001693 // Dispatch on the source and destination operand kinds. Not all
1694 // combinations are possible.
1695 if (source->IsRegister()) {
1696 // Register-register.
1697 Register temp = kScratchReg;
1698 Register src = g.ToRegister(source);
1699 if (destination->IsRegister()) {
1700 Register dst = g.ToRegister(destination);
1701 __ Move(temp, src);
1702 __ Move(src, dst);
1703 __ Move(dst, temp);
1704 } else {
1705 DCHECK(destination->IsStackSlot());
1706 MemOperand dst = g.ToMemOperand(destination);
1707 __ mov(temp, src);
1708 __ ldr(src, dst);
1709 __ str(temp, dst);
1710 }
1711 } else if (source->IsStackSlot()) {
1712 DCHECK(destination->IsStackSlot());
1713 Register temp_0 = kScratchReg;
1714 SwVfpRegister temp_1 = kScratchDoubleReg.low();
1715 MemOperand src = g.ToMemOperand(source);
1716 MemOperand dst = g.ToMemOperand(destination);
1717 __ ldr(temp_0, src);
1718 __ vldr(temp_1, dst);
1719 __ str(temp_0, dst);
1720 __ vstr(temp_1, src);
Ben Murdochc5610432016-08-08 18:44:38 +01001721 } else if (source->IsFPRegister()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001722 MachineRepresentation rep = LocationOperand::cast(source)->representation();
1723 LowDwVfpRegister temp = kScratchDoubleReg;
1724 if (rep == MachineRepresentation::kFloat64) {
1725 DwVfpRegister src = g.ToDoubleRegister(source);
1726 if (destination->IsFPRegister()) {
1727 DwVfpRegister dst = g.ToDoubleRegister(destination);
1728 __ Move(temp, src);
1729 __ Move(src, dst);
1730 __ Move(dst, temp);
1731 } else {
1732 DCHECK(destination->IsFPStackSlot());
1733 MemOperand dst = g.ToMemOperand(destination);
1734 __ Move(temp, src);
1735 __ vldr(src, dst);
1736 __ vstr(temp, dst);
1737 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001738 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001739 DCHECK_EQ(MachineRepresentation::kFloat32, rep);
1740 SwVfpRegister src = g.ToFloatRegister(source);
1741 if (destination->IsFPRegister()) {
1742 SwVfpRegister dst = g.ToFloatRegister(destination);
1743 __ Move(temp.low(), src);
1744 __ Move(src, dst);
1745 __ Move(dst, temp.low());
1746 } else {
1747 DCHECK(destination->IsFPStackSlot());
1748 MemOperand dst = g.ToMemOperand(destination);
1749 __ Move(temp.low(), src);
1750 __ vldr(src, dst);
1751 __ vstr(temp.low(), dst);
1752 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001753 }
Ben Murdochc5610432016-08-08 18:44:38 +01001754 } else if (source->IsFPStackSlot()) {
1755 DCHECK(destination->IsFPStackSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756 Register temp_0 = kScratchReg;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001757 LowDwVfpRegister temp_1 = kScratchDoubleReg;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001758 MemOperand src0 = g.ToMemOperand(source);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001759 MemOperand dst0 = g.ToMemOperand(destination);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001760 MachineRepresentation rep = LocationOperand::cast(source)->representation();
1761 if (rep == MachineRepresentation::kFloat64) {
1762 MemOperand src1(src0.rn(), src0.offset() + kPointerSize);
1763 MemOperand dst1(dst0.rn(), dst0.offset() + kPointerSize);
1764 __ vldr(temp_1, dst0); // Save destination in temp_1.
1765 __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination.
1766 __ str(temp_0, dst0);
1767 __ ldr(temp_0, src1);
1768 __ str(temp_0, dst1);
1769 __ vstr(temp_1, src0);
1770 } else {
1771 DCHECK_EQ(MachineRepresentation::kFloat32, rep);
1772 __ vldr(temp_1.low(), dst0); // Save destination in temp_1.
1773 __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination.
1774 __ str(temp_0, dst0);
1775 __ vstr(temp_1.low(), src0);
1776 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001777 } else {
1778 // No other combinations are possible.
1779 UNREACHABLE();
1780 }
1781}
1782
1783
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001784void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
1785 // On 32-bit ARM we emit the jump tables inline.
1786 UNREACHABLE();
1787}
1788
1789
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001790void CodeGenerator::EnsureSpaceForLazyDeopt() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001791 if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
1792 return;
1793 }
1794
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795 int space_needed = Deoptimizer::patch_size();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001796 // Ensure that we have enough space after the previous lazy-bailout
1797 // instruction for patching the code here.
1798 int current_pc = masm()->pc_offset();
1799 if (current_pc < last_lazy_deopt_pc_ + space_needed) {
1800 // Block literal pool emission for duration of padding.
1801 v8::internal::Assembler::BlockConstPoolScope block_const_pool(masm());
1802 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
1803 DCHECK_EQ(0, padding_size % v8::internal::Assembler::kInstrSize);
1804 while (padding_size > 0) {
1805 __ nop();
1806 padding_size -= v8::internal::Assembler::kInstrSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001807 }
1808 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001809}
1810
1811#undef __
1812
1813} // namespace compiler
1814} // namespace internal
1815} // namespace v8