87e1a8d4966d82a4ddff17af5f2522d22a0d7d57
[platform/upstream/v8.git] / src / ppc / lithium-codegen-ppc.cc
1 // 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/v8.h"
6
7 #include "src/base/bits.h"
8 #include "src/code-factory.h"
9 #include "src/code-stubs.h"
10 #include "src/cpu-profiler.h"
11 #include "src/hydrogen-osr.h"
12 #include "src/ic/ic.h"
13 #include "src/ic/stub-cache.h"
14 #include "src/ppc/lithium-codegen-ppc.h"
15 #include "src/ppc/lithium-gap-resolver-ppc.h"
16
17 namespace v8 {
18 namespace internal {
19
20
21 class SafepointGenerator final : public CallWrapper {
22  public:
23   SafepointGenerator(LCodeGen* codegen, LPointerMap* pointers,
24                      Safepoint::DeoptMode mode)
25       : codegen_(codegen), pointers_(pointers), deopt_mode_(mode) {}
26   virtual ~SafepointGenerator() {}
27
28   void BeforeCall(int call_size) const override {}
29
30   void AfterCall() const override {
31     codegen_->RecordSafepoint(pointers_, deopt_mode_);
32   }
33
34  private:
35   LCodeGen* codegen_;
36   LPointerMap* pointers_;
37   Safepoint::DeoptMode deopt_mode_;
38 };
39
40
41 #define __ masm()->
42
43 bool LCodeGen::GenerateCode() {
44   LPhase phase("Z_Code generation", chunk());
45   DCHECK(is_unused());
46   status_ = GENERATING;
47
48   // Open a frame scope to indicate that there is a frame on the stack.  The
49   // NONE indicates that the scope shouldn't actually generate code to set up
50   // the frame (that is done in GeneratePrologue).
51   FrameScope frame_scope(masm_, StackFrame::NONE);
52
53   bool rc = GeneratePrologue() && GenerateBody() && GenerateDeferredCode() &&
54             GenerateJumpTable() && GenerateSafepointTable();
55   if (FLAG_enable_embedded_constant_pool && !rc) {
56     masm()->AbortConstantPoolBuilding();
57   }
58   return rc;
59 }
60
61
62 void LCodeGen::FinishCode(Handle<Code> code) {
63   DCHECK(is_done());
64   code->set_stack_slots(GetStackSlotCount());
65   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
66   PopulateDeoptimizationData(code);
67 }
68
69
70 void LCodeGen::SaveCallerDoubles() {
71   DCHECK(info()->saves_caller_doubles());
72   DCHECK(NeedsEagerFrame());
73   Comment(";;; Save clobbered callee double registers");
74   int count = 0;
75   BitVector* doubles = chunk()->allocated_double_registers();
76   BitVector::Iterator save_iterator(doubles);
77   while (!save_iterator.Done()) {
78     __ stfd(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
79             MemOperand(sp, count * kDoubleSize));
80     save_iterator.Advance();
81     count++;
82   }
83 }
84
85
86 void LCodeGen::RestoreCallerDoubles() {
87   DCHECK(info()->saves_caller_doubles());
88   DCHECK(NeedsEagerFrame());
89   Comment(";;; Restore clobbered callee double registers");
90   BitVector* doubles = chunk()->allocated_double_registers();
91   BitVector::Iterator save_iterator(doubles);
92   int count = 0;
93   while (!save_iterator.Done()) {
94     __ lfd(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
95            MemOperand(sp, count * kDoubleSize));
96     save_iterator.Advance();
97     count++;
98   }
99 }
100
101
102 bool LCodeGen::GeneratePrologue() {
103   DCHECK(is_generating());
104
105   if (info()->IsOptimizing()) {
106     ProfileEntryHookStub::MaybeCallEntryHook(masm_);
107
108 #ifdef DEBUG
109     if (strlen(FLAG_stop_at) > 0 &&
110         info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
111       __ stop("stop_at");
112     }
113 #endif
114
115     // r4: Callee's JS function.
116     // cp: Callee's context.
117     // pp: Callee's constant pool pointer (if enabled)
118     // fp: Caller's frame pointer.
119     // lr: Caller's pc.
120     // ip: Our own function entry (required by the prologue)
121
122     // Sloppy mode functions and builtins need to replace the receiver with the
123     // global proxy when called as functions (without an explicit receiver
124     // object).
125     if (is_sloppy(info_->language_mode()) && info_->MayUseThis() &&
126         !info_->is_native() && info_->scope()->has_this_declaration()) {
127       Label ok;
128       int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
129       __ LoadP(r5, MemOperand(sp, receiver_offset));
130       __ CompareRoot(r5, Heap::kUndefinedValueRootIndex);
131       __ bne(&ok);
132
133       __ LoadP(r5, GlobalObjectOperand());
134       __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalProxyOffset));
135
136       __ StoreP(r5, MemOperand(sp, receiver_offset));
137
138       __ bind(&ok);
139     }
140   }
141
142   int prologue_offset = masm_->pc_offset();
143
144   if (prologue_offset) {
145     // Prologue logic requires it's starting address in ip and the
146     // corresponding offset from the function entry.
147     prologue_offset += Instruction::kInstrSize;
148     __ addi(ip, ip, Operand(prologue_offset));
149   }
150   info()->set_prologue_offset(prologue_offset);
151   if (NeedsEagerFrame()) {
152     if (info()->IsStub()) {
153       __ StubPrologue(prologue_offset);
154     } else {
155       __ Prologue(info()->IsCodePreAgingActive(), prologue_offset);
156     }
157     frame_is_built_ = true;
158     info_->AddNoFrameRange(0, masm_->pc_offset());
159   }
160
161   // Reserve space for the stack slots needed by the code.
162   int slots = GetStackSlotCount();
163   if (slots > 0) {
164     __ subi(sp, sp, Operand(slots * kPointerSize));
165     if (FLAG_debug_code) {
166       __ Push(r3, r4);
167       __ li(r0, Operand(slots));
168       __ mtctr(r0);
169       __ addi(r3, sp, Operand((slots + 2) * kPointerSize));
170       __ mov(r4, Operand(kSlotsZapValue));
171       Label loop;
172       __ bind(&loop);
173       __ StorePU(r4, MemOperand(r3, -kPointerSize));
174       __ bdnz(&loop);
175       __ Pop(r3, r4);
176     }
177   }
178
179   if (info()->saves_caller_doubles()) {
180     SaveCallerDoubles();
181   }
182
183   // Possibly allocate a local context.
184   int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
185   if (heap_slots > 0) {
186     Comment(";;; Allocate local context");
187     bool need_write_barrier = true;
188     // Argument to NewContext is the function, which is in r4.
189     DCHECK(!info()->scope()->is_script_scope());
190     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
191       FastNewContextStub stub(isolate(), heap_slots);
192       __ CallStub(&stub);
193       // Result of FastNewContextStub is always in new space.
194       need_write_barrier = false;
195     } else {
196       __ push(r4);
197       __ CallRuntime(Runtime::kNewFunctionContext, 1);
198     }
199     RecordSafepoint(Safepoint::kNoLazyDeopt);
200     // Context is returned in both r3 and cp.  It replaces the context
201     // passed to us.  It's saved in the stack and kept live in cp.
202     __ mr(cp, r3);
203     __ StoreP(r3, MemOperand(fp, StandardFrameConstants::kContextOffset));
204     // Copy any necessary parameters into the context.
205     int num_parameters = scope()->num_parameters();
206     int first_parameter = scope()->has_this_declaration() ? -1 : 0;
207     for (int i = first_parameter; i < num_parameters; i++) {
208       Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i);
209       if (var->IsContextSlot()) {
210         int parameter_offset = StandardFrameConstants::kCallerSPOffset +
211                                (num_parameters - 1 - i) * kPointerSize;
212         // Load parameter from stack.
213         __ LoadP(r3, MemOperand(fp, parameter_offset));
214         // Store it in the context.
215         MemOperand target = ContextOperand(cp, var->index());
216         __ StoreP(r3, target, r0);
217         // Update the write barrier. This clobbers r6 and r3.
218         if (need_write_barrier) {
219           __ RecordWriteContextSlot(cp, target.offset(), r3, r6,
220                                     GetLinkRegisterState(), kSaveFPRegs);
221         } else if (FLAG_debug_code) {
222           Label done;
223           __ JumpIfInNewSpace(cp, r3, &done);
224           __ Abort(kExpectedNewSpaceObject);
225           __ bind(&done);
226         }
227       }
228     }
229     Comment(";;; End allocate local context");
230   }
231
232   // Trace the call.
233   if (FLAG_trace && info()->IsOptimizing()) {
234     // We have not executed any compiled code yet, so cp still holds the
235     // incoming context.
236     __ CallRuntime(Runtime::kTraceEnter, 0);
237   }
238   return !is_aborted();
239 }
240
241
242 void LCodeGen::GenerateOsrPrologue() {
243   // Generate the OSR entry prologue at the first unknown OSR value, or if there
244   // are none, at the OSR entrypoint instruction.
245   if (osr_pc_offset_ >= 0) return;
246
247   osr_pc_offset_ = masm()->pc_offset();
248
249   // Adjust the frame size, subsuming the unoptimized frame into the
250   // optimized frame.
251   int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
252   DCHECK(slots >= 0);
253   __ subi(sp, sp, Operand(slots * kPointerSize));
254 }
255
256
257 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
258   if (instr->IsCall()) {
259     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
260   }
261   if (!instr->IsLazyBailout() && !instr->IsGap()) {
262     safepoints_.BumpLastLazySafepointIndex();
263   }
264 }
265
266
267 bool LCodeGen::GenerateDeferredCode() {
268   DCHECK(is_generating());
269   if (deferred_.length() > 0) {
270     for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
271       LDeferredCode* code = deferred_[i];
272
273       HValue* value =
274           instructions_->at(code->instruction_index())->hydrogen_value();
275       RecordAndWritePosition(
276           chunk()->graph()->SourcePositionToScriptPosition(value->position()));
277
278       Comment(
279           ";;; <@%d,#%d> "
280           "-------------------- Deferred %s --------------------",
281           code->instruction_index(), code->instr()->hydrogen_value()->id(),
282           code->instr()->Mnemonic());
283       __ bind(code->entry());
284       if (NeedsDeferredFrame()) {
285         Comment(";;; Build frame");
286         DCHECK(!frame_is_built_);
287         DCHECK(info()->IsStub());
288         frame_is_built_ = true;
289         __ LoadSmiLiteral(scratch0(), Smi::FromInt(StackFrame::STUB));
290         __ PushFixedFrame(scratch0());
291         __ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
292         Comment(";;; Deferred code");
293       }
294       code->Generate();
295       if (NeedsDeferredFrame()) {
296         Comment(";;; Destroy frame");
297         DCHECK(frame_is_built_);
298         __ PopFixedFrame(ip);
299         frame_is_built_ = false;
300       }
301       __ b(code->exit());
302     }
303   }
304
305   return !is_aborted();
306 }
307
308
309 bool LCodeGen::GenerateJumpTable() {
310   // Check that the jump table is accessible from everywhere in the function
311   // code, i.e. that offsets to the table can be encoded in the 24bit signed
312   // immediate of a branch instruction.
313   // To simplify we consider the code size from the first instruction to the
314   // end of the jump table. We also don't consider the pc load delta.
315   // Each entry in the jump table generates one instruction and inlines one
316   // 32bit data after it.
317   if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) +
318                 jump_table_.length() * 7)) {
319     Abort(kGeneratedCodeIsTooLarge);
320   }
321
322   if (jump_table_.length() > 0) {
323     Label needs_frame, call_deopt_entry;
324
325     Comment(";;; -------------------- Jump table --------------------");
326     Address base = jump_table_[0].address;
327
328     Register entry_offset = scratch0();
329
330     int length = jump_table_.length();
331     for (int i = 0; i < length; i++) {
332       Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i];
333       __ bind(&table_entry->label);
334
335       DCHECK_EQ(jump_table_[0].bailout_type, table_entry->bailout_type);
336       Address entry = table_entry->address;
337       DeoptComment(table_entry->deopt_info);
338
339       // Second-level deopt table entries are contiguous and small, so instead
340       // of loading the full, absolute address of each one, load an immediate
341       // offset which will be added to the base address later.
342       __ mov(entry_offset, Operand(entry - base));
343
344       if (table_entry->needs_frame) {
345         DCHECK(!info()->saves_caller_doubles());
346         Comment(";;; call deopt with frame");
347         __ PushFixedFrame();
348         __ b(&needs_frame, SetLK);
349       } else {
350         __ b(&call_deopt_entry, SetLK);
351       }
352       info()->LogDeoptCallPosition(masm()->pc_offset(),
353                                    table_entry->deopt_info.inlining_id);
354     }
355
356     if (needs_frame.is_linked()) {
357       __ bind(&needs_frame);
358       // This variant of deopt can only be used with stubs. Since we don't
359       // have a function pointer to install in the stack frame that we're
360       // building, install a special marker there instead.
361       DCHECK(info()->IsStub());
362       __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::STUB));
363       __ push(ip);
364       __ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
365     }
366
367     Comment(";;; call deopt");
368     __ bind(&call_deopt_entry);
369
370     if (info()->saves_caller_doubles()) {
371       DCHECK(info()->IsStub());
372       RestoreCallerDoubles();
373     }
374
375     // Add the base address to the offset previously loaded in entry_offset.
376     __ mov(ip, Operand(ExternalReference::ForDeoptEntry(base)));
377     __ add(ip, entry_offset, ip);
378     __ Jump(ip);
379   }
380
381   // The deoptimization jump table is the last part of the instruction
382   // sequence. Mark the generated code as done unless we bailed out.
383   if (!is_aborted()) status_ = DONE;
384   return !is_aborted();
385 }
386
387
388 bool LCodeGen::GenerateSafepointTable() {
389   DCHECK(is_done());
390   safepoints_.Emit(masm(), GetStackSlotCount());
391   return !is_aborted();
392 }
393
394
395 Register LCodeGen::ToRegister(int index) const {
396   return Register::FromAllocationIndex(index);
397 }
398
399
400 DoubleRegister LCodeGen::ToDoubleRegister(int index) const {
401   return DoubleRegister::FromAllocationIndex(index);
402 }
403
404
405 Register LCodeGen::ToRegister(LOperand* op) const {
406   DCHECK(op->IsRegister());
407   return ToRegister(op->index());
408 }
409
410
411 Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
412   if (op->IsRegister()) {
413     return ToRegister(op->index());
414   } else if (op->IsConstantOperand()) {
415     LConstantOperand* const_op = LConstantOperand::cast(op);
416     HConstant* constant = chunk_->LookupConstant(const_op);
417     Handle<Object> literal = constant->handle(isolate());
418     Representation r = chunk_->LookupLiteralRepresentation(const_op);
419     if (r.IsInteger32()) {
420       AllowDeferredHandleDereference get_number;
421       DCHECK(literal->IsNumber());
422       __ LoadIntLiteral(scratch, static_cast<int32_t>(literal->Number()));
423     } else if (r.IsDouble()) {
424       Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
425     } else {
426       DCHECK(r.IsSmiOrTagged());
427       __ Move(scratch, literal);
428     }
429     return scratch;
430   } else if (op->IsStackSlot()) {
431     __ LoadP(scratch, ToMemOperand(op));
432     return scratch;
433   }
434   UNREACHABLE();
435   return scratch;
436 }
437
438
439 void LCodeGen::EmitLoadIntegerConstant(LConstantOperand* const_op,
440                                        Register dst) {
441   DCHECK(IsInteger32(const_op));
442   HConstant* constant = chunk_->LookupConstant(const_op);
443   int32_t value = constant->Integer32Value();
444   if (IsSmi(const_op)) {
445     __ LoadSmiLiteral(dst, Smi::FromInt(value));
446   } else {
447     __ LoadIntLiteral(dst, value);
448   }
449 }
450
451
452 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
453   DCHECK(op->IsDoubleRegister());
454   return ToDoubleRegister(op->index());
455 }
456
457
458 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
459   HConstant* constant = chunk_->LookupConstant(op);
460   DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
461   return constant->handle(isolate());
462 }
463
464
465 bool LCodeGen::IsInteger32(LConstantOperand* op) const {
466   return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
467 }
468
469
470 bool LCodeGen::IsSmi(LConstantOperand* op) const {
471   return chunk_->LookupLiteralRepresentation(op).IsSmi();
472 }
473
474
475 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
476   return ToRepresentation(op, Representation::Integer32());
477 }
478
479
480 intptr_t LCodeGen::ToRepresentation(LConstantOperand* op,
481                                     const Representation& r) const {
482   HConstant* constant = chunk_->LookupConstant(op);
483   int32_t value = constant->Integer32Value();
484   if (r.IsInteger32()) return value;
485   DCHECK(r.IsSmiOrTagged());
486   return reinterpret_cast<intptr_t>(Smi::FromInt(value));
487 }
488
489
490 Smi* LCodeGen::ToSmi(LConstantOperand* op) const {
491   HConstant* constant = chunk_->LookupConstant(op);
492   return Smi::FromInt(constant->Integer32Value());
493 }
494
495
496 double LCodeGen::ToDouble(LConstantOperand* op) const {
497   HConstant* constant = chunk_->LookupConstant(op);
498   DCHECK(constant->HasDoubleValue());
499   return constant->DoubleValue();
500 }
501
502
503 Operand LCodeGen::ToOperand(LOperand* op) {
504   if (op->IsConstantOperand()) {
505     LConstantOperand* const_op = LConstantOperand::cast(op);
506     HConstant* constant = chunk()->LookupConstant(const_op);
507     Representation r = chunk_->LookupLiteralRepresentation(const_op);
508     if (r.IsSmi()) {
509       DCHECK(constant->HasSmiValue());
510       return Operand(Smi::FromInt(constant->Integer32Value()));
511     } else if (r.IsInteger32()) {
512       DCHECK(constant->HasInteger32Value());
513       return Operand(constant->Integer32Value());
514     } else if (r.IsDouble()) {
515       Abort(kToOperandUnsupportedDoubleImmediate);
516     }
517     DCHECK(r.IsTagged());
518     return Operand(constant->handle(isolate()));
519   } else if (op->IsRegister()) {
520     return Operand(ToRegister(op));
521   } else if (op->IsDoubleRegister()) {
522     Abort(kToOperandIsDoubleRegisterUnimplemented);
523     return Operand::Zero();
524   }
525   // Stack slots not implemented, use ToMemOperand instead.
526   UNREACHABLE();
527   return Operand::Zero();
528 }
529
530
531 static int ArgumentsOffsetWithoutFrame(int index) {
532   DCHECK(index < 0);
533   return -(index + 1) * kPointerSize;
534 }
535
536
537 MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
538   DCHECK(!op->IsRegister());
539   DCHECK(!op->IsDoubleRegister());
540   DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
541   if (NeedsEagerFrame()) {
542     return MemOperand(fp, StackSlotOffset(op->index()));
543   } else {
544     // Retrieve parameter without eager stack-frame relative to the
545     // stack-pointer.
546     return MemOperand(sp, ArgumentsOffsetWithoutFrame(op->index()));
547   }
548 }
549
550
551 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
552   DCHECK(op->IsDoubleStackSlot());
553   if (NeedsEagerFrame()) {
554     return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize);
555   } else {
556     // Retrieve parameter without eager stack-frame relative to the
557     // stack-pointer.
558     return MemOperand(sp,
559                       ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
560   }
561 }
562
563
564 void LCodeGen::WriteTranslation(LEnvironment* environment,
565                                 Translation* translation) {
566   if (environment == NULL) return;
567
568   // The translation includes one command per value in the environment.
569   int translation_size = environment->translation_size();
570
571   WriteTranslation(environment->outer(), translation);
572   WriteTranslationFrame(environment, translation);
573
574   int object_index = 0;
575   int dematerialized_index = 0;
576   for (int i = 0; i < translation_size; ++i) {
577     LOperand* value = environment->values()->at(i);
578     AddToTranslation(
579         environment, translation, value, environment->HasTaggedValueAt(i),
580         environment->HasUint32ValueAt(i), &object_index, &dematerialized_index);
581   }
582 }
583
584
585 void LCodeGen::AddToTranslation(LEnvironment* environment,
586                                 Translation* translation, LOperand* op,
587                                 bool is_tagged, bool is_uint32,
588                                 int* object_index_pointer,
589                                 int* dematerialized_index_pointer) {
590   if (op == LEnvironment::materialization_marker()) {
591     int object_index = (*object_index_pointer)++;
592     if (environment->ObjectIsDuplicateAt(object_index)) {
593       int dupe_of = environment->ObjectDuplicateOfAt(object_index);
594       translation->DuplicateObject(dupe_of);
595       return;
596     }
597     int object_length = environment->ObjectLengthAt(object_index);
598     if (environment->ObjectIsArgumentsAt(object_index)) {
599       translation->BeginArgumentsObject(object_length);
600     } else {
601       translation->BeginCapturedObject(object_length);
602     }
603     int dematerialized_index = *dematerialized_index_pointer;
604     int env_offset = environment->translation_size() + dematerialized_index;
605     *dematerialized_index_pointer += object_length;
606     for (int i = 0; i < object_length; ++i) {
607       LOperand* value = environment->values()->at(env_offset + i);
608       AddToTranslation(environment, translation, value,
609                        environment->HasTaggedValueAt(env_offset + i),
610                        environment->HasUint32ValueAt(env_offset + i),
611                        object_index_pointer, dematerialized_index_pointer);
612     }
613     return;
614   }
615
616   if (op->IsStackSlot()) {
617     if (is_tagged) {
618       translation->StoreStackSlot(op->index());
619     } else if (is_uint32) {
620       translation->StoreUint32StackSlot(op->index());
621     } else {
622       translation->StoreInt32StackSlot(op->index());
623     }
624   } else if (op->IsDoubleStackSlot()) {
625     translation->StoreDoubleStackSlot(op->index());
626   } else if (op->IsRegister()) {
627     Register reg = ToRegister(op);
628     if (is_tagged) {
629       translation->StoreRegister(reg);
630     } else if (is_uint32) {
631       translation->StoreUint32Register(reg);
632     } else {
633       translation->StoreInt32Register(reg);
634     }
635   } else if (op->IsDoubleRegister()) {
636     DoubleRegister reg = ToDoubleRegister(op);
637     translation->StoreDoubleRegister(reg);
638   } else if (op->IsConstantOperand()) {
639     HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
640     int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
641     translation->StoreLiteral(src_index);
642   } else {
643     UNREACHABLE();
644   }
645 }
646
647
648 void LCodeGen::CallCode(Handle<Code> code, RelocInfo::Mode mode,
649                         LInstruction* instr) {
650   CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
651 }
652
653
654 void LCodeGen::CallCodeGeneric(Handle<Code> code, RelocInfo::Mode mode,
655                                LInstruction* instr,
656                                SafepointMode safepoint_mode) {
657   DCHECK(instr != NULL);
658   __ Call(code, mode);
659   RecordSafepointWithLazyDeopt(instr, safepoint_mode);
660
661   // Signal that we don't inline smi code before these stubs in the
662   // optimizing code generator.
663   if (code->kind() == Code::BINARY_OP_IC || code->kind() == Code::COMPARE_IC) {
664     __ nop();
665   }
666 }
667
668
669 void LCodeGen::CallRuntime(const Runtime::Function* function, int num_arguments,
670                            LInstruction* instr, SaveFPRegsMode save_doubles) {
671   DCHECK(instr != NULL);
672
673   __ CallRuntime(function, num_arguments, save_doubles);
674
675   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
676 }
677
678
679 void LCodeGen::LoadContextFromDeferred(LOperand* context) {
680   if (context->IsRegister()) {
681     __ Move(cp, ToRegister(context));
682   } else if (context->IsStackSlot()) {
683     __ LoadP(cp, ToMemOperand(context));
684   } else if (context->IsConstantOperand()) {
685     HConstant* constant =
686         chunk_->LookupConstant(LConstantOperand::cast(context));
687     __ Move(cp, Handle<Object>::cast(constant->handle(isolate())));
688   } else {
689     UNREACHABLE();
690   }
691 }
692
693
694 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, int argc,
695                                        LInstruction* instr, LOperand* context) {
696   LoadContextFromDeferred(context);
697   __ CallRuntimeSaveDoubles(id);
698   RecordSafepointWithRegisters(instr->pointer_map(), argc,
699                                Safepoint::kNoLazyDeopt);
700 }
701
702
703 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
704                                                     Safepoint::DeoptMode mode) {
705   environment->set_has_been_used();
706   if (!environment->HasBeenRegistered()) {
707     // Physical stack frame layout:
708     // -x ............. -4  0 ..................................... y
709     // [incoming arguments] [spill slots] [pushed outgoing arguments]
710
711     // Layout of the environment:
712     // 0 ..................................................... size-1
713     // [parameters] [locals] [expression stack including arguments]
714
715     // Layout of the translation:
716     // 0 ........................................................ size - 1 + 4
717     // [expression stack including arguments] [locals] [4 words] [parameters]
718     // |>------------  translation_size ------------<|
719
720     int frame_count = 0;
721     int jsframe_count = 0;
722     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
723       ++frame_count;
724       if (e->frame_type() == JS_FUNCTION) {
725         ++jsframe_count;
726       }
727     }
728     Translation translation(&translations_, frame_count, jsframe_count, zone());
729     WriteTranslation(environment, &translation);
730     int deoptimization_index = deoptimizations_.length();
731     int pc_offset = masm()->pc_offset();
732     environment->Register(deoptimization_index, translation.index(),
733                           (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
734     deoptimizations_.Add(environment, zone());
735   }
736 }
737
738
739 void LCodeGen::DeoptimizeIf(Condition cond, LInstruction* instr,
740                             Deoptimizer::DeoptReason deopt_reason,
741                             Deoptimizer::BailoutType bailout_type,
742                             CRegister cr) {
743   LEnvironment* environment = instr->environment();
744   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
745   DCHECK(environment->HasBeenRegistered());
746   int id = environment->deoptimization_index();
747   DCHECK(info()->IsOptimizing() || info()->IsStub());
748   Address entry =
749       Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
750   if (entry == NULL) {
751     Abort(kBailoutWasNotPrepared);
752     return;
753   }
754
755   if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) {
756     CRegister alt_cr = cr6;
757     Register scratch = scratch0();
758     ExternalReference count = ExternalReference::stress_deopt_count(isolate());
759     Label no_deopt;
760     DCHECK(!alt_cr.is(cr));
761     __ Push(r4, scratch);
762     __ mov(scratch, Operand(count));
763     __ lwz(r4, MemOperand(scratch));
764     __ subi(r4, r4, Operand(1));
765     __ cmpi(r4, Operand::Zero(), alt_cr);
766     __ bne(&no_deopt, alt_cr);
767     __ li(r4, Operand(FLAG_deopt_every_n_times));
768     __ stw(r4, MemOperand(scratch));
769     __ Pop(r4, scratch);
770
771     __ Call(entry, RelocInfo::RUNTIME_ENTRY);
772     __ bind(&no_deopt);
773     __ stw(r4, MemOperand(scratch));
774     __ Pop(r4, scratch);
775   }
776
777   if (info()->ShouldTrapOnDeopt()) {
778     __ stop("trap_on_deopt", cond, kDefaultStopCode, cr);
779   }
780
781   Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
782
783   DCHECK(info()->IsStub() || frame_is_built_);
784   // Go through jump table if we need to handle condition, build frame, or
785   // restore caller doubles.
786   if (cond == al && frame_is_built_ && !info()->saves_caller_doubles()) {
787     DeoptComment(deopt_info);
788     __ Call(entry, RelocInfo::RUNTIME_ENTRY);
789     info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
790   } else {
791     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
792                                             !frame_is_built_);
793     // We often have several deopts to the same entry, reuse the last
794     // jump entry if this is the case.
795     if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
796         jump_table_.is_empty() ||
797         !table_entry.IsEquivalentTo(jump_table_.last())) {
798       jump_table_.Add(table_entry, zone());
799     }
800     __ b(cond, &jump_table_.last().label, cr);
801   }
802 }
803
804
805 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
806                             Deoptimizer::DeoptReason deopt_reason,
807                             CRegister cr) {
808   Deoptimizer::BailoutType bailout_type =
809       info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER;
810   DeoptimizeIf(condition, instr, deopt_reason, bailout_type, cr);
811 }
812
813
814 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
815   int length = deoptimizations_.length();
816   if (length == 0) return;
817   Handle<DeoptimizationInputData> data =
818       DeoptimizationInputData::New(isolate(), length, TENURED);
819
820   Handle<ByteArray> translations =
821       translations_.CreateByteArray(isolate()->factory());
822   data->SetTranslationByteArray(*translations);
823   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
824   data->SetOptimizationId(Smi::FromInt(info_->optimization_id()));
825   if (info_->IsOptimizing()) {
826     // Reference to shared function info does not change between phases.
827     AllowDeferredHandleDereference allow_handle_dereference;
828     data->SetSharedFunctionInfo(*info_->shared_info());
829   } else {
830     data->SetSharedFunctionInfo(Smi::FromInt(0));
831   }
832   data->SetWeakCellCache(Smi::FromInt(0));
833
834   Handle<FixedArray> literals =
835       factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
836   {
837     AllowDeferredHandleDereference copy_handles;
838     for (int i = 0; i < deoptimization_literals_.length(); i++) {
839       literals->set(i, *deoptimization_literals_[i]);
840     }
841     data->SetLiteralArray(*literals);
842   }
843
844   data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
845   data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
846
847   // Populate the deoptimization entries.
848   for (int i = 0; i < length; i++) {
849     LEnvironment* env = deoptimizations_[i];
850     data->SetAstId(i, env->ast_id());
851     data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
852     data->SetArgumentsStackHeight(i,
853                                   Smi::FromInt(env->arguments_stack_height()));
854     data->SetPc(i, Smi::FromInt(env->pc_offset()));
855   }
856   code->set_deoptimization_data(*data);
857 }
858
859
860 void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
861   DCHECK_EQ(0, deoptimization_literals_.length());
862   for (auto function : chunk()->inlined_functions()) {
863     DefineDeoptimizationLiteral(function);
864   }
865   inlined_function_count_ = deoptimization_literals_.length();
866 }
867
868
869 void LCodeGen::RecordSafepointWithLazyDeopt(LInstruction* instr,
870                                             SafepointMode safepoint_mode) {
871   if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
872     RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
873   } else {
874     DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
875     RecordSafepointWithRegisters(instr->pointer_map(), 0,
876                                  Safepoint::kLazyDeopt);
877   }
878 }
879
880
881 void LCodeGen::RecordSafepoint(LPointerMap* pointers, Safepoint::Kind kind,
882                                int arguments, Safepoint::DeoptMode deopt_mode) {
883   DCHECK(expected_safepoint_kind_ == kind);
884
885   const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
886   Safepoint safepoint =
887       safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode);
888   for (int i = 0; i < operands->length(); i++) {
889     LOperand* pointer = operands->at(i);
890     if (pointer->IsStackSlot()) {
891       safepoint.DefinePointerSlot(pointer->index(), zone());
892     } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
893       safepoint.DefinePointerRegister(ToRegister(pointer), zone());
894     }
895   }
896 }
897
898
899 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
900                                Safepoint::DeoptMode deopt_mode) {
901   RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
902 }
903
904
905 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
906   LPointerMap empty_pointers(zone());
907   RecordSafepoint(&empty_pointers, deopt_mode);
908 }
909
910
911 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
912                                             int arguments,
913                                             Safepoint::DeoptMode deopt_mode) {
914   RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
915 }
916
917
918 void LCodeGen::RecordAndWritePosition(int position) {
919   if (position == RelocInfo::kNoPosition) return;
920   masm()->positions_recorder()->RecordPosition(position);
921   masm()->positions_recorder()->WriteRecordedPositions();
922 }
923
924
925 static const char* LabelType(LLabel* label) {
926   if (label->is_loop_header()) return " (loop header)";
927   if (label->is_osr_entry()) return " (OSR entry)";
928   return "";
929 }
930
931
932 void LCodeGen::DoLabel(LLabel* label) {
933   Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------",
934           current_instruction_, label->hydrogen_value()->id(),
935           label->block_id(), LabelType(label));
936   __ bind(label->label());
937   current_block_ = label->block_id();
938   DoGap(label);
939 }
940
941
942 void LCodeGen::DoParallelMove(LParallelMove* move) { resolver_.Resolve(move); }
943
944
945 void LCodeGen::DoGap(LGap* gap) {
946   for (int i = LGap::FIRST_INNER_POSITION; i <= LGap::LAST_INNER_POSITION;
947        i++) {
948     LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
949     LParallelMove* move = gap->GetParallelMove(inner_pos);
950     if (move != NULL) DoParallelMove(move);
951   }
952 }
953
954
955 void LCodeGen::DoInstructionGap(LInstructionGap* instr) { DoGap(instr); }
956
957
958 void LCodeGen::DoParameter(LParameter* instr) {
959   // Nothing to do.
960 }
961
962
963 void LCodeGen::DoCallStub(LCallStub* instr) {
964   DCHECK(ToRegister(instr->context()).is(cp));
965   DCHECK(ToRegister(instr->result()).is(r3));
966   switch (instr->hydrogen()->major_key()) {
967     case CodeStub::RegExpExec: {
968       RegExpExecStub stub(isolate());
969       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
970       break;
971     }
972     case CodeStub::SubString: {
973       SubStringStub stub(isolate());
974       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
975       break;
976     }
977     case CodeStub::StringCompare: {
978       StringCompareStub stub(isolate());
979       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
980       break;
981     }
982     default:
983       UNREACHABLE();
984   }
985 }
986
987
988 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
989   GenerateOsrPrologue();
990 }
991
992
993 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
994   Register dividend = ToRegister(instr->dividend());
995   int32_t divisor = instr->divisor();
996   DCHECK(dividend.is(ToRegister(instr->result())));
997
998   // Theoretically, a variation of the branch-free code for integer division by
999   // a power of 2 (calculating the remainder via an additional multiplication
1000   // (which gets simplified to an 'and') and subtraction) should be faster, and
1001   // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
1002   // indicate that positive dividends are heavily favored, so the branching
1003   // version performs better.
1004   HMod* hmod = instr->hydrogen();
1005   int32_t shift = WhichPowerOf2Abs(divisor);
1006   Label dividend_is_not_negative, done;
1007   if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1008     __ cmpwi(dividend, Operand::Zero());
1009     __ bge(&dividend_is_not_negative);
1010     if (shift) {
1011       // Note that this is correct even for kMinInt operands.
1012       __ neg(dividend, dividend);
1013       __ ExtractBitRange(dividend, dividend, shift - 1, 0);
1014       __ neg(dividend, dividend, LeaveOE, SetRC);
1015       if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1016         DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, cr0);
1017       }
1018     } else if (!hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1019       __ li(dividend, Operand::Zero());
1020     } else {
1021       DeoptimizeIf(al, instr, Deoptimizer::kMinusZero);
1022     }
1023     __ b(&done);
1024   }
1025
1026   __ bind(&dividend_is_not_negative);
1027   if (shift) {
1028     __ ExtractBitRange(dividend, dividend, shift - 1, 0);
1029   } else {
1030     __ li(dividend, Operand::Zero());
1031   }
1032   __ bind(&done);
1033 }
1034
1035
1036 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1037   Register dividend = ToRegister(instr->dividend());
1038   int32_t divisor = instr->divisor();
1039   Register result = ToRegister(instr->result());
1040   DCHECK(!dividend.is(result));
1041
1042   if (divisor == 0) {
1043     DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
1044     return;
1045   }
1046
1047   __ TruncatingDiv(result, dividend, Abs(divisor));
1048   __ mov(ip, Operand(Abs(divisor)));
1049   __ mullw(result, result, ip);
1050   __ sub(result, dividend, result, LeaveOE, SetRC);
1051
1052   // Check for negative zero.
1053   HMod* hmod = instr->hydrogen();
1054   if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1055     Label remainder_not_zero;
1056     __ bne(&remainder_not_zero, cr0);
1057     __ cmpwi(dividend, Operand::Zero());
1058     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
1059     __ bind(&remainder_not_zero);
1060   }
1061 }
1062
1063
1064 void LCodeGen::DoModI(LModI* instr) {
1065   HMod* hmod = instr->hydrogen();
1066   Register left_reg = ToRegister(instr->left());
1067   Register right_reg = ToRegister(instr->right());
1068   Register result_reg = ToRegister(instr->result());
1069   Register scratch = scratch0();
1070   bool can_overflow = hmod->CheckFlag(HValue::kCanOverflow);
1071   Label done;
1072
1073   if (can_overflow) {
1074     __ li(r0, Operand::Zero());  // clear xer
1075     __ mtxer(r0);
1076   }
1077
1078   __ divw(scratch, left_reg, right_reg, SetOE, SetRC);
1079
1080   // Check for x % 0.
1081   if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1082     __ cmpwi(right_reg, Operand::Zero());
1083     DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
1084   }
1085
1086   // Check for kMinInt % -1, divw will return undefined, which is not what we
1087   // want. We have to deopt if we care about -0, because we can't return that.
1088   if (can_overflow) {
1089     if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1090       DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero, cr0);
1091     } else {
1092       if (CpuFeatures::IsSupported(ISELECT)) {
1093         __ isel(overflow, result_reg, r0, result_reg, cr0);
1094         __ boverflow(&done, cr0);
1095       } else {
1096         Label no_overflow_possible;
1097         __ bnooverflow(&no_overflow_possible, cr0);
1098         __ li(result_reg, Operand::Zero());
1099         __ b(&done);
1100         __ bind(&no_overflow_possible);
1101       }
1102     }
1103   }
1104
1105   __ mullw(scratch, right_reg, scratch);
1106   __ sub(result_reg, left_reg, scratch, LeaveOE, SetRC);
1107
1108   // If we care about -0, test if the dividend is <0 and the result is 0.
1109   if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1110     __ bne(&done, cr0);
1111     __ cmpwi(left_reg, Operand::Zero());
1112     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
1113   }
1114
1115   __ bind(&done);
1116 }
1117
1118
1119 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1120   Register dividend = ToRegister(instr->dividend());
1121   int32_t divisor = instr->divisor();
1122   Register result = ToRegister(instr->result());
1123   DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1124   DCHECK(!result.is(dividend));
1125
1126   // Check for (0 / -x) that will produce negative zero.
1127   HDiv* hdiv = instr->hydrogen();
1128   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1129     __ cmpwi(dividend, Operand::Zero());
1130     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
1131   }
1132   // Check for (kMinInt / -1).
1133   if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1134     __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
1135     __ cmpw(dividend, r0);
1136     DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
1137   }
1138
1139   int32_t shift = WhichPowerOf2Abs(divisor);
1140
1141   // Deoptimize if remainder will not be 0.
1142   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && shift) {
1143     __ TestBitRange(dividend, shift - 1, 0, r0);
1144     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, cr0);
1145   }
1146
1147   if (divisor == -1) {  // Nice shortcut, not needed for correctness.
1148     __ neg(result, dividend);
1149     return;
1150   }
1151   if (shift == 0) {
1152     __ mr(result, dividend);
1153   } else {
1154     if (shift == 1) {
1155       __ srwi(result, dividend, Operand(31));
1156     } else {
1157       __ srawi(result, dividend, 31);
1158       __ srwi(result, result, Operand(32 - shift));
1159     }
1160     __ add(result, dividend, result);
1161     __ srawi(result, result, shift);
1162   }
1163   if (divisor < 0) __ neg(result, result);
1164 }
1165
1166
1167 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1168   Register dividend = ToRegister(instr->dividend());
1169   int32_t divisor = instr->divisor();
1170   Register result = ToRegister(instr->result());
1171   DCHECK(!dividend.is(result));
1172
1173   if (divisor == 0) {
1174     DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
1175     return;
1176   }
1177
1178   // Check for (0 / -x) that will produce negative zero.
1179   HDiv* hdiv = instr->hydrogen();
1180   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1181     __ cmpwi(dividend, Operand::Zero());
1182     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
1183   }
1184
1185   __ TruncatingDiv(result, dividend, Abs(divisor));
1186   if (divisor < 0) __ neg(result, result);
1187
1188   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1189     Register scratch = scratch0();
1190     __ mov(ip, Operand(divisor));
1191     __ mullw(scratch, result, ip);
1192     __ cmpw(scratch, dividend);
1193     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision);
1194   }
1195 }
1196
1197
1198 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1199 void LCodeGen::DoDivI(LDivI* instr) {
1200   HBinaryOperation* hdiv = instr->hydrogen();
1201   const Register dividend = ToRegister(instr->dividend());
1202   const Register divisor = ToRegister(instr->divisor());
1203   Register result = ToRegister(instr->result());
1204   bool can_overflow = hdiv->CheckFlag(HValue::kCanOverflow);
1205
1206   DCHECK(!dividend.is(result));
1207   DCHECK(!divisor.is(result));
1208
1209   if (can_overflow) {
1210     __ li(r0, Operand::Zero());  // clear xer
1211     __ mtxer(r0);
1212   }
1213
1214   __ divw(result, dividend, divisor, SetOE, SetRC);
1215
1216   // Check for x / 0.
1217   if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1218     __ cmpwi(divisor, Operand::Zero());
1219     DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
1220   }
1221
1222   // Check for (0 / -x) that will produce negative zero.
1223   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1224     Label dividend_not_zero;
1225     __ cmpwi(dividend, Operand::Zero());
1226     __ bne(&dividend_not_zero);
1227     __ cmpwi(divisor, Operand::Zero());
1228     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
1229     __ bind(&dividend_not_zero);
1230   }
1231
1232   // Check for (kMinInt / -1).
1233   if (can_overflow) {
1234     if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1235       DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
1236     } else {
1237       // When truncating, we want kMinInt / -1 = kMinInt.
1238       if (CpuFeatures::IsSupported(ISELECT)) {
1239         __ isel(overflow, result, dividend, result, cr0);
1240       } else {
1241         Label no_overflow_possible;
1242         __ bnooverflow(&no_overflow_possible, cr0);
1243         __ mr(result, dividend);
1244         __ bind(&no_overflow_possible);
1245       }
1246     }
1247   }
1248
1249   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1250     // Deoptimize if remainder is not 0.
1251     Register scratch = scratch0();
1252     __ mullw(scratch, divisor, result);
1253     __ cmpw(dividend, scratch);
1254     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision);
1255   }
1256 }
1257
1258
1259 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1260   HBinaryOperation* hdiv = instr->hydrogen();
1261   Register dividend = ToRegister(instr->dividend());
1262   Register result = ToRegister(instr->result());
1263   int32_t divisor = instr->divisor();
1264   bool can_overflow = hdiv->CheckFlag(HValue::kLeftCanBeMinInt);
1265
1266   // If the divisor is positive, things are easy: There can be no deopts and we
1267   // can simply do an arithmetic right shift.
1268   int32_t shift = WhichPowerOf2Abs(divisor);
1269   if (divisor > 0) {
1270     if (shift || !result.is(dividend)) {
1271       __ srawi(result, dividend, shift);
1272     }
1273     return;
1274   }
1275
1276   // If the divisor is negative, we have to negate and handle edge cases.
1277   OEBit oe = LeaveOE;
1278 #if V8_TARGET_ARCH_PPC64
1279   if (divisor == -1 && can_overflow) {
1280     __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
1281     __ cmpw(dividend, r0);
1282     DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
1283   }
1284 #else
1285   if (can_overflow) {
1286     __ li(r0, Operand::Zero());  // clear xer
1287     __ mtxer(r0);
1288     oe = SetOE;
1289   }
1290 #endif
1291
1292   __ neg(result, dividend, oe, SetRC);
1293   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1294     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, cr0);
1295   }
1296
1297 // If the negation could not overflow, simply shifting is OK.
1298 #if !V8_TARGET_ARCH_PPC64
1299   if (!can_overflow) {
1300 #endif
1301     if (shift) {
1302       __ ShiftRightArithImm(result, result, shift);
1303     }
1304     return;
1305 #if !V8_TARGET_ARCH_PPC64
1306   }
1307
1308   // Dividing by -1 is basically negation, unless we overflow.
1309   if (divisor == -1) {
1310     DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
1311     return;
1312   }
1313
1314   Label overflow, done;
1315   __ boverflow(&overflow, cr0);
1316   __ srawi(result, result, shift);
1317   __ b(&done);
1318   __ bind(&overflow);
1319   __ mov(result, Operand(kMinInt / divisor));
1320   __ bind(&done);
1321 #endif
1322 }
1323
1324
1325 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1326   Register dividend = ToRegister(instr->dividend());
1327   int32_t divisor = instr->divisor();
1328   Register result = ToRegister(instr->result());
1329   DCHECK(!dividend.is(result));
1330
1331   if (divisor == 0) {
1332     DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
1333     return;
1334   }
1335
1336   // Check for (0 / -x) that will produce negative zero.
1337   HMathFloorOfDiv* hdiv = instr->hydrogen();
1338   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1339     __ cmpwi(dividend, Operand::Zero());
1340     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
1341   }
1342
1343   // Easy case: We need no dynamic check for the dividend and the flooring
1344   // division is the same as the truncating division.
1345   if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1346       (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1347     __ TruncatingDiv(result, dividend, Abs(divisor));
1348     if (divisor < 0) __ neg(result, result);
1349     return;
1350   }
1351
1352   // In the general case we may need to adjust before and after the truncating
1353   // division to get a flooring division.
1354   Register temp = ToRegister(instr->temp());
1355   DCHECK(!temp.is(dividend) && !temp.is(result));
1356   Label needs_adjustment, done;
1357   __ cmpwi(dividend, Operand::Zero());
1358   __ b(divisor > 0 ? lt : gt, &needs_adjustment);
1359   __ TruncatingDiv(result, dividend, Abs(divisor));
1360   if (divisor < 0) __ neg(result, result);
1361   __ b(&done);
1362   __ bind(&needs_adjustment);
1363   __ addi(temp, dividend, Operand(divisor > 0 ? 1 : -1));
1364   __ TruncatingDiv(result, temp, Abs(divisor));
1365   if (divisor < 0) __ neg(result, result);
1366   __ subi(result, result, Operand(1));
1367   __ bind(&done);
1368 }
1369
1370
1371 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
1372 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
1373   HBinaryOperation* hdiv = instr->hydrogen();
1374   const Register dividend = ToRegister(instr->dividend());
1375   const Register divisor = ToRegister(instr->divisor());
1376   Register result = ToRegister(instr->result());
1377   bool can_overflow = hdiv->CheckFlag(HValue::kCanOverflow);
1378
1379   DCHECK(!dividend.is(result));
1380   DCHECK(!divisor.is(result));
1381
1382   if (can_overflow) {
1383     __ li(r0, Operand::Zero());  // clear xer
1384     __ mtxer(r0);
1385   }
1386
1387   __ divw(result, dividend, divisor, SetOE, SetRC);
1388
1389   // Check for x / 0.
1390   if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1391     __ cmpwi(divisor, Operand::Zero());
1392     DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
1393   }
1394
1395   // Check for (0 / -x) that will produce negative zero.
1396   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1397     Label dividend_not_zero;
1398     __ cmpwi(dividend, Operand::Zero());
1399     __ bne(&dividend_not_zero);
1400     __ cmpwi(divisor, Operand::Zero());
1401     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
1402     __ bind(&dividend_not_zero);
1403   }
1404
1405   // Check for (kMinInt / -1).
1406   if (can_overflow) {
1407     if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1408       DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
1409     } else {
1410       // When truncating, we want kMinInt / -1 = kMinInt.
1411       if (CpuFeatures::IsSupported(ISELECT)) {
1412         __ isel(overflow, result, dividend, result, cr0);
1413       } else {
1414         Label no_overflow_possible;
1415         __ bnooverflow(&no_overflow_possible, cr0);
1416         __ mr(result, dividend);
1417         __ bind(&no_overflow_possible);
1418       }
1419     }
1420   }
1421
1422   Label done;
1423   Register scratch = scratch0();
1424 // If both operands have the same sign then we are done.
1425 #if V8_TARGET_ARCH_PPC64
1426   __ xor_(scratch, dividend, divisor);
1427   __ cmpwi(scratch, Operand::Zero());
1428   __ bge(&done);
1429 #else
1430   __ xor_(scratch, dividend, divisor, SetRC);
1431   __ bge(&done, cr0);
1432 #endif
1433
1434   // If there is no remainder then we are done.
1435   __ mullw(scratch, divisor, result);
1436   __ cmpw(dividend, scratch);
1437   __ beq(&done);
1438
1439   // We performed a truncating division. Correct the result.
1440   __ subi(result, result, Operand(1));
1441   __ bind(&done);
1442 }
1443
1444
1445 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
1446   DoubleRegister addend = ToDoubleRegister(instr->addend());
1447   DoubleRegister multiplier = ToDoubleRegister(instr->multiplier());
1448   DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1449   DoubleRegister result = ToDoubleRegister(instr->result());
1450
1451   __ fmadd(result, multiplier, multiplicand, addend);
1452 }
1453
1454
1455 void LCodeGen::DoMultiplySubD(LMultiplySubD* instr) {
1456   DoubleRegister minuend = ToDoubleRegister(instr->minuend());
1457   DoubleRegister multiplier = ToDoubleRegister(instr->multiplier());
1458   DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1459   DoubleRegister result = ToDoubleRegister(instr->result());
1460
1461   __ fmsub(result, multiplier, multiplicand, minuend);
1462 }
1463
1464
1465 void LCodeGen::DoMulI(LMulI* instr) {
1466   Register scratch = scratch0();
1467   Register result = ToRegister(instr->result());
1468   // Note that result may alias left.
1469   Register left = ToRegister(instr->left());
1470   LOperand* right_op = instr->right();
1471
1472   bool bailout_on_minus_zero =
1473       instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1474   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1475
1476   if (right_op->IsConstantOperand()) {
1477     int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
1478
1479     if (bailout_on_minus_zero && (constant < 0)) {
1480       // The case of a null constant will be handled separately.
1481       // If constant is negative and left is null, the result should be -0.
1482       __ cmpi(left, Operand::Zero());
1483       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
1484     }
1485
1486     switch (constant) {
1487       case -1:
1488         if (can_overflow) {
1489 #if V8_TARGET_ARCH_PPC64
1490           if (instr->hydrogen()->representation().IsSmi()) {
1491 #endif
1492             __ li(r0, Operand::Zero());  // clear xer
1493             __ mtxer(r0);
1494             __ neg(result, left, SetOE, SetRC);
1495             DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
1496 #if V8_TARGET_ARCH_PPC64
1497           } else {
1498             __ neg(result, left);
1499             __ TestIfInt32(result, r0);
1500             DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
1501           }
1502 #endif
1503         } else {
1504           __ neg(result, left);
1505         }
1506         break;
1507       case 0:
1508         if (bailout_on_minus_zero) {
1509 // If left is strictly negative and the constant is null, the
1510 // result is -0. Deoptimize if required, otherwise return 0.
1511 #if V8_TARGET_ARCH_PPC64
1512           if (instr->hydrogen()->representation().IsSmi()) {
1513 #endif
1514             __ cmpi(left, Operand::Zero());
1515 #if V8_TARGET_ARCH_PPC64
1516           } else {
1517             __ cmpwi(left, Operand::Zero());
1518           }
1519 #endif
1520           DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
1521         }
1522         __ li(result, Operand::Zero());
1523         break;
1524       case 1:
1525         __ Move(result, left);
1526         break;
1527       default:
1528         // Multiplying by powers of two and powers of two plus or minus
1529         // one can be done faster with shifted operands.
1530         // For other constants we emit standard code.
1531         int32_t mask = constant >> 31;
1532         uint32_t constant_abs = (constant + mask) ^ mask;
1533
1534         if (base::bits::IsPowerOfTwo32(constant_abs)) {
1535           int32_t shift = WhichPowerOf2(constant_abs);
1536           __ ShiftLeftImm(result, left, Operand(shift));
1537           // Correct the sign of the result if the constant is negative.
1538           if (constant < 0) __ neg(result, result);
1539         } else if (base::bits::IsPowerOfTwo32(constant_abs - 1)) {
1540           int32_t shift = WhichPowerOf2(constant_abs - 1);
1541           __ ShiftLeftImm(scratch, left, Operand(shift));
1542           __ add(result, scratch, left);
1543           // Correct the sign of the result if the constant is negative.
1544           if (constant < 0) __ neg(result, result);
1545         } else if (base::bits::IsPowerOfTwo32(constant_abs + 1)) {
1546           int32_t shift = WhichPowerOf2(constant_abs + 1);
1547           __ ShiftLeftImm(scratch, left, Operand(shift));
1548           __ sub(result, scratch, left);
1549           // Correct the sign of the result if the constant is negative.
1550           if (constant < 0) __ neg(result, result);
1551         } else {
1552           // Generate standard code.
1553           __ mov(ip, Operand(constant));
1554           __ Mul(result, left, ip);
1555         }
1556     }
1557
1558   } else {
1559     DCHECK(right_op->IsRegister());
1560     Register right = ToRegister(right_op);
1561
1562     if (can_overflow) {
1563 #if V8_TARGET_ARCH_PPC64
1564       // result = left * right.
1565       if (instr->hydrogen()->representation().IsSmi()) {
1566         __ SmiUntag(result, left);
1567         __ SmiUntag(scratch, right);
1568         __ Mul(result, result, scratch);
1569       } else {
1570         __ Mul(result, left, right);
1571       }
1572       __ TestIfInt32(result, r0);
1573       DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
1574       if (instr->hydrogen()->representation().IsSmi()) {
1575         __ SmiTag(result);
1576       }
1577 #else
1578       // scratch:result = left * right.
1579       if (instr->hydrogen()->representation().IsSmi()) {
1580         __ SmiUntag(result, left);
1581         __ mulhw(scratch, result, right);
1582         __ mullw(result, result, right);
1583       } else {
1584         __ mulhw(scratch, left, right);
1585         __ mullw(result, left, right);
1586       }
1587       __ TestIfInt32(scratch, result, r0);
1588       DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
1589 #endif
1590     } else {
1591       if (instr->hydrogen()->representation().IsSmi()) {
1592         __ SmiUntag(result, left);
1593         __ Mul(result, result, right);
1594       } else {
1595         __ Mul(result, left, right);
1596       }
1597     }
1598
1599     if (bailout_on_minus_zero) {
1600       Label done;
1601 #if V8_TARGET_ARCH_PPC64
1602       if (instr->hydrogen()->representation().IsSmi()) {
1603 #endif
1604         __ xor_(r0, left, right, SetRC);
1605         __ bge(&done, cr0);
1606 #if V8_TARGET_ARCH_PPC64
1607       } else {
1608         __ xor_(r0, left, right);
1609         __ cmpwi(r0, Operand::Zero());
1610         __ bge(&done);
1611       }
1612 #endif
1613       // Bail out if the result is minus zero.
1614       __ cmpi(result, Operand::Zero());
1615       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
1616       __ bind(&done);
1617     }
1618   }
1619 }
1620
1621
1622 void LCodeGen::DoBitI(LBitI* instr) {
1623   LOperand* left_op = instr->left();
1624   LOperand* right_op = instr->right();
1625   DCHECK(left_op->IsRegister());
1626   Register left = ToRegister(left_op);
1627   Register result = ToRegister(instr->result());
1628   Operand right(no_reg);
1629
1630   if (right_op->IsStackSlot()) {
1631     right = Operand(EmitLoadRegister(right_op, ip));
1632   } else {
1633     DCHECK(right_op->IsRegister() || right_op->IsConstantOperand());
1634     right = ToOperand(right_op);
1635
1636     if (right_op->IsConstantOperand() && is_uint16(right.immediate())) {
1637       switch (instr->op()) {
1638         case Token::BIT_AND:
1639           __ andi(result, left, right);
1640           break;
1641         case Token::BIT_OR:
1642           __ ori(result, left, right);
1643           break;
1644         case Token::BIT_XOR:
1645           __ xori(result, left, right);
1646           break;
1647         default:
1648           UNREACHABLE();
1649           break;
1650       }
1651       return;
1652     }
1653   }
1654
1655   switch (instr->op()) {
1656     case Token::BIT_AND:
1657       __ And(result, left, right);
1658       break;
1659     case Token::BIT_OR:
1660       __ Or(result, left, right);
1661       break;
1662     case Token::BIT_XOR:
1663       if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
1664         __ notx(result, left);
1665       } else {
1666         __ Xor(result, left, right);
1667       }
1668       break;
1669     default:
1670       UNREACHABLE();
1671       break;
1672   }
1673 }
1674
1675
1676 void LCodeGen::DoShiftI(LShiftI* instr) {
1677   // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so
1678   // result may alias either of them.
1679   LOperand* right_op = instr->right();
1680   Register left = ToRegister(instr->left());
1681   Register result = ToRegister(instr->result());
1682   Register scratch = scratch0();
1683   if (right_op->IsRegister()) {
1684     // Mask the right_op operand.
1685     __ andi(scratch, ToRegister(right_op), Operand(0x1F));
1686     switch (instr->op()) {
1687       case Token::ROR:
1688         // rotate_right(a, b) == rotate_left(a, 32 - b)
1689         __ subfic(scratch, scratch, Operand(32));
1690         __ rotlw(result, left, scratch);
1691         break;
1692       case Token::SAR:
1693         __ sraw(result, left, scratch);
1694         break;
1695       case Token::SHR:
1696         if (instr->can_deopt()) {
1697           __ srw(result, left, scratch, SetRC);
1698 #if V8_TARGET_ARCH_PPC64
1699           __ extsw(result, result, SetRC);
1700 #endif
1701           DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue, cr0);
1702         } else {
1703           __ srw(result, left, scratch);
1704         }
1705         break;
1706       case Token::SHL:
1707         __ slw(result, left, scratch);
1708 #if V8_TARGET_ARCH_PPC64
1709         __ extsw(result, result);
1710 #endif
1711         break;
1712       default:
1713         UNREACHABLE();
1714         break;
1715     }
1716   } else {
1717     // Mask the right_op operand.
1718     int value = ToInteger32(LConstantOperand::cast(right_op));
1719     uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1720     switch (instr->op()) {
1721       case Token::ROR:
1722         if (shift_count != 0) {
1723           __ rotrwi(result, left, shift_count);
1724         } else {
1725           __ Move(result, left);
1726         }
1727         break;
1728       case Token::SAR:
1729         if (shift_count != 0) {
1730           __ srawi(result, left, shift_count);
1731         } else {
1732           __ Move(result, left);
1733         }
1734         break;
1735       case Token::SHR:
1736         if (shift_count != 0) {
1737           __ srwi(result, left, Operand(shift_count));
1738         } else {
1739           if (instr->can_deopt()) {
1740             __ cmpwi(left, Operand::Zero());
1741             DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue);
1742           }
1743           __ Move(result, left);
1744         }
1745         break;
1746       case Token::SHL:
1747         if (shift_count != 0) {
1748 #if V8_TARGET_ARCH_PPC64
1749           if (instr->hydrogen_value()->representation().IsSmi()) {
1750             __ sldi(result, left, Operand(shift_count));
1751 #else
1752           if (instr->hydrogen_value()->representation().IsSmi() &&
1753               instr->can_deopt()) {
1754             if (shift_count != 1) {
1755               __ slwi(result, left, Operand(shift_count - 1));
1756               __ SmiTagCheckOverflow(result, result, scratch);
1757             } else {
1758               __ SmiTagCheckOverflow(result, left, scratch);
1759             }
1760             DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
1761 #endif
1762           } else {
1763             __ slwi(result, left, Operand(shift_count));
1764 #if V8_TARGET_ARCH_PPC64
1765             __ extsw(result, result);
1766 #endif
1767           }
1768         } else {
1769           __ Move(result, left);
1770         }
1771         break;
1772       default:
1773         UNREACHABLE();
1774         break;
1775     }
1776   }
1777 }
1778
1779
1780 void LCodeGen::DoSubI(LSubI* instr) {
1781   LOperand* right = instr->right();
1782   Register left = ToRegister(instr->left());
1783   Register result = ToRegister(instr->result());
1784   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1785 #if V8_TARGET_ARCH_PPC64
1786   const bool isInteger = !instr->hydrogen()->representation().IsSmi();
1787 #else
1788   const bool isInteger = false;
1789 #endif
1790   if (!can_overflow || isInteger) {
1791     if (right->IsConstantOperand()) {
1792       __ Add(result, left, -(ToOperand(right).immediate()), r0);
1793     } else {
1794       __ sub(result, left, EmitLoadRegister(right, ip));
1795     }
1796 #if V8_TARGET_ARCH_PPC64
1797     if (can_overflow) {
1798       __ TestIfInt32(result, r0);
1799       DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
1800     }
1801 #endif
1802   } else {
1803     if (right->IsConstantOperand()) {
1804       __ AddAndCheckForOverflow(result, left, -(ToOperand(right).immediate()),
1805                                 scratch0(), r0);
1806     } else {
1807       __ SubAndCheckForOverflow(result, left, EmitLoadRegister(right, ip),
1808                                 scratch0(), r0);
1809     }
1810     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
1811   }
1812 }
1813
1814
1815 void LCodeGen::DoRSubI(LRSubI* instr) {
1816   LOperand* left = instr->left();
1817   LOperand* right = instr->right();
1818   LOperand* result = instr->result();
1819
1820   DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow) &&
1821          right->IsConstantOperand());
1822
1823   Operand right_operand = ToOperand(right);
1824   if (is_int16(right_operand.immediate())) {
1825     __ subfic(ToRegister(result), ToRegister(left), right_operand);
1826   } else {
1827     __ mov(r0, right_operand);
1828     __ sub(ToRegister(result), r0, ToRegister(left));
1829   }
1830 }
1831
1832
1833 void LCodeGen::DoConstantI(LConstantI* instr) {
1834   __ mov(ToRegister(instr->result()), Operand(instr->value()));
1835 }
1836
1837
1838 void LCodeGen::DoConstantS(LConstantS* instr) {
1839   __ LoadSmiLiteral(ToRegister(instr->result()), instr->value());
1840 }
1841
1842
1843 void LCodeGen::DoConstantD(LConstantD* instr) {
1844   DCHECK(instr->result()->IsDoubleRegister());
1845   DoubleRegister result = ToDoubleRegister(instr->result());
1846 #if V8_HOST_ARCH_IA32
1847   // Need some crappy work-around for x87 sNaN -> qNaN breakage in simulator
1848   // builds.
1849   uint64_t bits = instr->bits();
1850   if ((bits & V8_UINT64_C(0x7FF8000000000000)) ==
1851       V8_UINT64_C(0x7FF0000000000000)) {
1852     uint32_t lo = static_cast<uint32_t>(bits);
1853     uint32_t hi = static_cast<uint32_t>(bits >> 32);
1854     __ mov(ip, Operand(lo));
1855     __ mov(scratch0(), Operand(hi));
1856     __ MovInt64ToDouble(result, scratch0(), ip);
1857     return;
1858   }
1859 #endif
1860   double v = instr->value();
1861   __ LoadDoubleLiteral(result, v, scratch0());
1862 }
1863
1864
1865 void LCodeGen::DoConstantE(LConstantE* instr) {
1866   __ mov(ToRegister(instr->result()), Operand(instr->value()));
1867 }
1868
1869
1870 void LCodeGen::DoConstantT(LConstantT* instr) {
1871   Handle<Object> object = instr->value(isolate());
1872   AllowDeferredHandleDereference smi_check;
1873   __ Move(ToRegister(instr->result()), object);
1874 }
1875
1876
1877 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) {
1878   Register result = ToRegister(instr->result());
1879   Register map = ToRegister(instr->value());
1880   __ EnumLength(result, map);
1881 }
1882
1883
1884 void LCodeGen::DoDateField(LDateField* instr) {
1885   Register object = ToRegister(instr->date());
1886   Register result = ToRegister(instr->result());
1887   Register scratch = ToRegister(instr->temp());
1888   Smi* index = instr->index();
1889   DCHECK(object.is(result));
1890   DCHECK(object.is(r3));
1891   DCHECK(!scratch.is(scratch0()));
1892   DCHECK(!scratch.is(object));
1893
1894   if (index->value() == 0) {
1895     __ LoadP(result, FieldMemOperand(object, JSDate::kValueOffset));
1896   } else {
1897     Label runtime, done;
1898     if (index->value() < JSDate::kFirstUncachedField) {
1899       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1900       __ mov(scratch, Operand(stamp));
1901       __ LoadP(scratch, MemOperand(scratch));
1902       __ LoadP(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
1903       __ cmp(scratch, scratch0());
1904       __ bne(&runtime);
1905       __ LoadP(result,
1906                FieldMemOperand(object, JSDate::kValueOffset +
1907                                            kPointerSize * index->value()));
1908       __ b(&done);
1909     }
1910     __ bind(&runtime);
1911     __ PrepareCallCFunction(2, scratch);
1912     __ LoadSmiLiteral(r4, index);
1913     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
1914     __ bind(&done);
1915   }
1916 }
1917
1918
1919 MemOperand LCodeGen::BuildSeqStringOperand(Register string, LOperand* index,
1920                                            String::Encoding encoding) {
1921   if (index->IsConstantOperand()) {
1922     int offset = ToInteger32(LConstantOperand::cast(index));
1923     if (encoding == String::TWO_BYTE_ENCODING) {
1924       offset *= kUC16Size;
1925     }
1926     STATIC_ASSERT(kCharSize == 1);
1927     return FieldMemOperand(string, SeqString::kHeaderSize + offset);
1928   }
1929   Register scratch = scratch0();
1930   DCHECK(!scratch.is(string));
1931   DCHECK(!scratch.is(ToRegister(index)));
1932   if (encoding == String::ONE_BYTE_ENCODING) {
1933     __ add(scratch, string, ToRegister(index));
1934   } else {
1935     STATIC_ASSERT(kUC16Size == 2);
1936     __ ShiftLeftImm(scratch, ToRegister(index), Operand(1));
1937     __ add(scratch, string, scratch);
1938   }
1939   return FieldMemOperand(scratch, SeqString::kHeaderSize);
1940 }
1941
1942
1943 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
1944   String::Encoding encoding = instr->hydrogen()->encoding();
1945   Register string = ToRegister(instr->string());
1946   Register result = ToRegister(instr->result());
1947
1948   if (FLAG_debug_code) {
1949     Register scratch = scratch0();
1950     __ LoadP(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
1951     __ lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1952
1953     __ andi(scratch, scratch,
1954             Operand(kStringRepresentationMask | kStringEncodingMask));
1955     static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1956     static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1957     __ cmpi(scratch,
1958             Operand(encoding == String::ONE_BYTE_ENCODING ? one_byte_seq_type
1959                                                           : two_byte_seq_type));
1960     __ Check(eq, kUnexpectedStringType);
1961   }
1962
1963   MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1964   if (encoding == String::ONE_BYTE_ENCODING) {
1965     __ lbz(result, operand);
1966   } else {
1967     __ lhz(result, operand);
1968   }
1969 }
1970
1971
1972 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
1973   String::Encoding encoding = instr->hydrogen()->encoding();
1974   Register string = ToRegister(instr->string());
1975   Register value = ToRegister(instr->value());
1976
1977   if (FLAG_debug_code) {
1978     Register index = ToRegister(instr->index());
1979     static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1980     static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1981     int encoding_mask =
1982         instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
1983             ? one_byte_seq_type
1984             : two_byte_seq_type;
1985     __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
1986   }
1987
1988   MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1989   if (encoding == String::ONE_BYTE_ENCODING) {
1990     __ stb(value, operand);
1991   } else {
1992     __ sth(value, operand);
1993   }
1994 }
1995
1996
1997 void LCodeGen::DoAddI(LAddI* instr) {
1998   LOperand* right = instr->right();
1999   Register left = ToRegister(instr->left());
2000   Register result = ToRegister(instr->result());
2001   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
2002 #if V8_TARGET_ARCH_PPC64
2003   const bool isInteger = !(instr->hydrogen()->representation().IsSmi() ||
2004                            instr->hydrogen()->representation().IsExternal());
2005 #else
2006   const bool isInteger = false;
2007 #endif
2008
2009   if (!can_overflow || isInteger) {
2010     if (right->IsConstantOperand()) {
2011       __ Add(result, left, ToOperand(right).immediate(), r0);
2012     } else {
2013       __ add(result, left, EmitLoadRegister(right, ip));
2014     }
2015 #if V8_TARGET_ARCH_PPC64
2016     if (can_overflow) {
2017       __ TestIfInt32(result, r0);
2018       DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
2019     }
2020 #endif
2021   } else {
2022     if (right->IsConstantOperand()) {
2023       __ AddAndCheckForOverflow(result, left, ToOperand(right).immediate(),
2024                                 scratch0(), r0);
2025     } else {
2026       __ AddAndCheckForOverflow(result, left, EmitLoadRegister(right, ip),
2027                                 scratch0(), r0);
2028     }
2029     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
2030   }
2031 }
2032
2033
2034 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
2035   LOperand* left = instr->left();
2036   LOperand* right = instr->right();
2037   HMathMinMax::Operation operation = instr->hydrogen()->operation();
2038   Condition cond = (operation == HMathMinMax::kMathMin) ? le : ge;
2039   if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
2040     Register left_reg = ToRegister(left);
2041     Register right_reg = EmitLoadRegister(right, ip);
2042     Register result_reg = ToRegister(instr->result());
2043     Label return_left, done;
2044 #if V8_TARGET_ARCH_PPC64
2045     if (instr->hydrogen_value()->representation().IsSmi()) {
2046 #endif
2047       __ cmp(left_reg, right_reg);
2048 #if V8_TARGET_ARCH_PPC64
2049     } else {
2050       __ cmpw(left_reg, right_reg);
2051     }
2052 #endif
2053     if (CpuFeatures::IsSupported(ISELECT)) {
2054       __ isel(cond, result_reg, left_reg, right_reg);
2055     } else {
2056       __ b(cond, &return_left);
2057       __ Move(result_reg, right_reg);
2058       __ b(&done);
2059       __ bind(&return_left);
2060       __ Move(result_reg, left_reg);
2061       __ bind(&done);
2062     }
2063   } else {
2064     DCHECK(instr->hydrogen()->representation().IsDouble());
2065     DoubleRegister left_reg = ToDoubleRegister(left);
2066     DoubleRegister right_reg = ToDoubleRegister(right);
2067     DoubleRegister result_reg = ToDoubleRegister(instr->result());
2068     Label check_nan_left, check_zero, return_left, return_right, done;
2069     __ fcmpu(left_reg, right_reg);
2070     __ bunordered(&check_nan_left);
2071     __ beq(&check_zero);
2072     __ b(cond, &return_left);
2073     __ b(&return_right);
2074
2075     __ bind(&check_zero);
2076     __ fcmpu(left_reg, kDoubleRegZero);
2077     __ bne(&return_left);  // left == right != 0.
2078
2079     // At this point, both left and right are either 0 or -0.
2080     // N.B. The following works because +0 + -0 == +0
2081     if (operation == HMathMinMax::kMathMin) {
2082       // For min we want logical-or of sign bit: -(-L + -R)
2083       __ fneg(left_reg, left_reg);
2084       __ fsub(result_reg, left_reg, right_reg);
2085       __ fneg(result_reg, result_reg);
2086     } else {
2087       // For max we want logical-and of sign bit: (L + R)
2088       __ fadd(result_reg, left_reg, right_reg);
2089     }
2090     __ b(&done);
2091
2092     __ bind(&check_nan_left);
2093     __ fcmpu(left_reg, left_reg);
2094     __ bunordered(&return_left);  // left == NaN.
2095
2096     __ bind(&return_right);
2097     if (!right_reg.is(result_reg)) {
2098       __ fmr(result_reg, right_reg);
2099     }
2100     __ b(&done);
2101
2102     __ bind(&return_left);
2103     if (!left_reg.is(result_reg)) {
2104       __ fmr(result_reg, left_reg);
2105     }
2106     __ bind(&done);
2107   }
2108 }
2109
2110
2111 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
2112   DoubleRegister left = ToDoubleRegister(instr->left());
2113   DoubleRegister right = ToDoubleRegister(instr->right());
2114   DoubleRegister result = ToDoubleRegister(instr->result());
2115   switch (instr->op()) {
2116     case Token::ADD:
2117       __ fadd(result, left, right);
2118       break;
2119     case Token::SUB:
2120       __ fsub(result, left, right);
2121       break;
2122     case Token::MUL:
2123       __ fmul(result, left, right);
2124       break;
2125     case Token::DIV:
2126       __ fdiv(result, left, right);
2127       break;
2128     case Token::MOD: {
2129       __ PrepareCallCFunction(0, 2, scratch0());
2130       __ MovToFloatParameters(left, right);
2131       __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()),
2132                        0, 2);
2133       // Move the result in the double result register.
2134       __ MovFromFloatResult(result);
2135       break;
2136     }
2137     default:
2138       UNREACHABLE();
2139       break;
2140   }
2141 }
2142
2143
2144 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
2145   DCHECK(ToRegister(instr->context()).is(cp));
2146   DCHECK(ToRegister(instr->left()).is(r4));
2147   DCHECK(ToRegister(instr->right()).is(r3));
2148   DCHECK(ToRegister(instr->result()).is(r3));
2149
2150   Handle<Code> code =
2151       CodeFactory::BinaryOpIC(isolate(), instr->op(), instr->strength()).code();
2152   CallCode(code, RelocInfo::CODE_TARGET, instr);
2153 }
2154
2155
2156 template <class InstrType>
2157 void LCodeGen::EmitBranch(InstrType instr, Condition cond, CRegister cr) {
2158   int left_block = instr->TrueDestination(chunk_);
2159   int right_block = instr->FalseDestination(chunk_);
2160
2161   int next_block = GetNextEmittedBlock();
2162
2163   if (right_block == left_block || cond == al) {
2164     EmitGoto(left_block);
2165   } else if (left_block == next_block) {
2166     __ b(NegateCondition(cond), chunk_->GetAssemblyLabel(right_block), cr);
2167   } else if (right_block == next_block) {
2168     __ b(cond, chunk_->GetAssemblyLabel(left_block), cr);
2169   } else {
2170     __ b(cond, chunk_->GetAssemblyLabel(left_block), cr);
2171     __ b(chunk_->GetAssemblyLabel(right_block));
2172   }
2173 }
2174
2175
2176 template <class InstrType>
2177 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cond, CRegister cr) {
2178   int false_block = instr->FalseDestination(chunk_);
2179   __ b(cond, chunk_->GetAssemblyLabel(false_block), cr);
2180 }
2181
2182
2183 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { __ stop("LBreak"); }
2184
2185
2186 void LCodeGen::DoBranch(LBranch* instr) {
2187   Representation r = instr->hydrogen()->value()->representation();
2188   DoubleRegister dbl_scratch = double_scratch0();
2189   const uint crZOrNaNBits = (1 << (31 - Assembler::encode_crbit(cr7, CR_EQ)) |
2190                              1 << (31 - Assembler::encode_crbit(cr7, CR_FU)));
2191
2192   if (r.IsInteger32()) {
2193     DCHECK(!info()->IsStub());
2194     Register reg = ToRegister(instr->value());
2195     __ cmpwi(reg, Operand::Zero());
2196     EmitBranch(instr, ne);
2197   } else if (r.IsSmi()) {
2198     DCHECK(!info()->IsStub());
2199     Register reg = ToRegister(instr->value());
2200     __ cmpi(reg, Operand::Zero());
2201     EmitBranch(instr, ne);
2202   } else if (r.IsDouble()) {
2203     DCHECK(!info()->IsStub());
2204     DoubleRegister reg = ToDoubleRegister(instr->value());
2205     // Test the double value. Zero and NaN are false.
2206     __ fcmpu(reg, kDoubleRegZero, cr7);
2207     __ mfcr(r0);
2208     __ andi(r0, r0, Operand(crZOrNaNBits));
2209     EmitBranch(instr, eq, cr0);
2210   } else {
2211     DCHECK(r.IsTagged());
2212     Register reg = ToRegister(instr->value());
2213     HType type = instr->hydrogen()->value()->type();
2214     if (type.IsBoolean()) {
2215       DCHECK(!info()->IsStub());
2216       __ CompareRoot(reg, Heap::kTrueValueRootIndex);
2217       EmitBranch(instr, eq);
2218     } else if (type.IsSmi()) {
2219       DCHECK(!info()->IsStub());
2220       __ cmpi(reg, Operand::Zero());
2221       EmitBranch(instr, ne);
2222     } else if (type.IsJSArray()) {
2223       DCHECK(!info()->IsStub());
2224       EmitBranch(instr, al);
2225     } else if (type.IsHeapNumber()) {
2226       DCHECK(!info()->IsStub());
2227       __ lfd(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2228       // Test the double value. Zero and NaN are false.
2229       __ fcmpu(dbl_scratch, kDoubleRegZero, cr7);
2230       __ mfcr(r0);
2231       __ andi(r0, r0, Operand(crZOrNaNBits));
2232       EmitBranch(instr, eq, cr0);
2233     } else if (type.IsString()) {
2234       DCHECK(!info()->IsStub());
2235       __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset));
2236       __ cmpi(ip, Operand::Zero());
2237       EmitBranch(instr, ne);
2238     } else {
2239       ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2240       // Avoid deopts in the case where we've never executed this path before.
2241       if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2242
2243       if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2244         // undefined -> false.
2245         __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
2246         __ beq(instr->FalseLabel(chunk_));
2247       }
2248       if (expected.Contains(ToBooleanStub::BOOLEAN)) {
2249         // Boolean -> its value.
2250         __ CompareRoot(reg, Heap::kTrueValueRootIndex);
2251         __ beq(instr->TrueLabel(chunk_));
2252         __ CompareRoot(reg, Heap::kFalseValueRootIndex);
2253         __ beq(instr->FalseLabel(chunk_));
2254       }
2255       if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
2256         // 'null' -> false.
2257         __ CompareRoot(reg, Heap::kNullValueRootIndex);
2258         __ beq(instr->FalseLabel(chunk_));
2259       }
2260
2261       if (expected.Contains(ToBooleanStub::SMI)) {
2262         // Smis: 0 -> false, all other -> true.
2263         __ cmpi(reg, Operand::Zero());
2264         __ beq(instr->FalseLabel(chunk_));
2265         __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2266       } else if (expected.NeedsMap()) {
2267         // If we need a map later and have a Smi -> deopt.
2268         __ TestIfSmi(reg, r0);
2269         DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
2270       }
2271
2272       const Register map = scratch0();
2273       if (expected.NeedsMap()) {
2274         __ LoadP(map, FieldMemOperand(reg, HeapObject::kMapOffset));
2275
2276         if (expected.CanBeUndetectable()) {
2277           // Undetectable -> false.
2278           __ lbz(ip, FieldMemOperand(map, Map::kBitFieldOffset));
2279           __ TestBit(ip, Map::kIsUndetectable, r0);
2280           __ bne(instr->FalseLabel(chunk_), cr0);
2281         }
2282       }
2283
2284       if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
2285         // spec object -> true.
2286         __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
2287         __ bge(instr->TrueLabel(chunk_));
2288       }
2289
2290       if (expected.Contains(ToBooleanStub::STRING)) {
2291         // String value -> false iff empty.
2292         Label not_string;
2293         __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
2294         __ bge(&not_string);
2295         __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset));
2296         __ cmpi(ip, Operand::Zero());
2297         __ bne(instr->TrueLabel(chunk_));
2298         __ b(instr->FalseLabel(chunk_));
2299         __ bind(&not_string);
2300       }
2301
2302       if (expected.Contains(ToBooleanStub::SYMBOL)) {
2303         // Symbol value -> true.
2304         __ CompareInstanceType(map, ip, SYMBOL_TYPE);
2305         __ beq(instr->TrueLabel(chunk_));
2306       }
2307
2308       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
2309         // SIMD value -> true.
2310         __ CompareInstanceType(map, ip, FLOAT32X4_TYPE);
2311         __ beq(instr->TrueLabel(chunk_));
2312       }
2313
2314       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2315         // heap number -> false iff +0, -0, or NaN.
2316         Label not_heap_number;
2317         __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
2318         __ bne(&not_heap_number);
2319         __ lfd(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2320         // Test the double value. Zero and NaN are false.
2321         __ fcmpu(dbl_scratch, kDoubleRegZero, cr7);
2322         __ mfcr(r0);
2323         __ andi(r0, r0, Operand(crZOrNaNBits));
2324         __ bne(instr->FalseLabel(chunk_), cr0);
2325         __ b(instr->TrueLabel(chunk_));
2326         __ bind(&not_heap_number);
2327       }
2328
2329       if (!expected.IsGeneric()) {
2330         // We've seen something for the first time -> deopt.
2331         // This can only happen if we are not generic already.
2332         DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject);
2333       }
2334     }
2335   }
2336 }
2337
2338
2339 void LCodeGen::EmitGoto(int block) {
2340   if (!IsNextEmittedBlock(block)) {
2341     __ b(chunk_->GetAssemblyLabel(LookupDestination(block)));
2342   }
2343 }
2344
2345
2346 void LCodeGen::DoGoto(LGoto* instr) { EmitGoto(instr->block_id()); }
2347
2348
2349 Condition LCodeGen::TokenToCondition(Token::Value op) {
2350   Condition cond = kNoCondition;
2351   switch (op) {
2352     case Token::EQ:
2353     case Token::EQ_STRICT:
2354       cond = eq;
2355       break;
2356     case Token::NE:
2357     case Token::NE_STRICT:
2358       cond = ne;
2359       break;
2360     case Token::LT:
2361       cond = lt;
2362       break;
2363     case Token::GT:
2364       cond = gt;
2365       break;
2366     case Token::LTE:
2367       cond = le;
2368       break;
2369     case Token::GTE:
2370       cond = ge;
2371       break;
2372     case Token::IN:
2373     case Token::INSTANCEOF:
2374     default:
2375       UNREACHABLE();
2376   }
2377   return cond;
2378 }
2379
2380
2381 void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
2382   LOperand* left = instr->left();
2383   LOperand* right = instr->right();
2384   bool is_unsigned =
2385       instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
2386       instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
2387   Condition cond = TokenToCondition(instr->op());
2388
2389   if (left->IsConstantOperand() && right->IsConstantOperand()) {
2390     // We can statically evaluate the comparison.
2391     double left_val = ToDouble(LConstantOperand::cast(left));
2392     double right_val = ToDouble(LConstantOperand::cast(right));
2393     int next_block = EvalComparison(instr->op(), left_val, right_val)
2394                          ? instr->TrueDestination(chunk_)
2395                          : instr->FalseDestination(chunk_);
2396     EmitGoto(next_block);
2397   } else {
2398     if (instr->is_double()) {
2399       // Compare left and right operands as doubles and load the
2400       // resulting flags into the normal status register.
2401       __ fcmpu(ToDoubleRegister(left), ToDoubleRegister(right));
2402       // If a NaN is involved, i.e. the result is unordered,
2403       // jump to false block label.
2404       __ bunordered(instr->FalseLabel(chunk_));
2405     } else {
2406       if (right->IsConstantOperand()) {
2407         int32_t value = ToInteger32(LConstantOperand::cast(right));
2408         if (instr->hydrogen_value()->representation().IsSmi()) {
2409           if (is_unsigned) {
2410             __ CmplSmiLiteral(ToRegister(left), Smi::FromInt(value), r0);
2411           } else {
2412             __ CmpSmiLiteral(ToRegister(left), Smi::FromInt(value), r0);
2413           }
2414         } else {
2415           if (is_unsigned) {
2416             __ Cmplwi(ToRegister(left), Operand(value), r0);
2417           } else {
2418             __ Cmpwi(ToRegister(left), Operand(value), r0);
2419           }
2420         }
2421       } else if (left->IsConstantOperand()) {
2422         int32_t value = ToInteger32(LConstantOperand::cast(left));
2423         if (instr->hydrogen_value()->representation().IsSmi()) {
2424           if (is_unsigned) {
2425             __ CmplSmiLiteral(ToRegister(right), Smi::FromInt(value), r0);
2426           } else {
2427             __ CmpSmiLiteral(ToRegister(right), Smi::FromInt(value), r0);
2428           }
2429         } else {
2430           if (is_unsigned) {
2431             __ Cmplwi(ToRegister(right), Operand(value), r0);
2432           } else {
2433             __ Cmpwi(ToRegister(right), Operand(value), r0);
2434           }
2435         }
2436         // We commuted the operands, so commute the condition.
2437         cond = CommuteCondition(cond);
2438       } else if (instr->hydrogen_value()->representation().IsSmi()) {
2439         if (is_unsigned) {
2440           __ cmpl(ToRegister(left), ToRegister(right));
2441         } else {
2442           __ cmp(ToRegister(left), ToRegister(right));
2443         }
2444       } else {
2445         if (is_unsigned) {
2446           __ cmplw(ToRegister(left), ToRegister(right));
2447         } else {
2448           __ cmpw(ToRegister(left), ToRegister(right));
2449         }
2450       }
2451     }
2452     EmitBranch(instr, cond);
2453   }
2454 }
2455
2456
2457 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2458   Register left = ToRegister(instr->left());
2459   Register right = ToRegister(instr->right());
2460
2461   __ cmp(left, right);
2462   EmitBranch(instr, eq);
2463 }
2464
2465
2466 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2467   if (instr->hydrogen()->representation().IsTagged()) {
2468     Register input_reg = ToRegister(instr->object());
2469     __ mov(ip, Operand(factory()->the_hole_value()));
2470     __ cmp(input_reg, ip);
2471     EmitBranch(instr, eq);
2472     return;
2473   }
2474
2475   DoubleRegister input_reg = ToDoubleRegister(instr->object());
2476   __ fcmpu(input_reg, input_reg);
2477   EmitFalseBranch(instr, ordered);
2478
2479   Register scratch = scratch0();
2480   __ MovDoubleHighToInt(scratch, input_reg);
2481   __ Cmpi(scratch, Operand(kHoleNanUpper32), r0);
2482   EmitBranch(instr, eq);
2483 }
2484
2485
2486 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2487   Representation rep = instr->hydrogen()->value()->representation();
2488   DCHECK(!rep.IsInteger32());
2489   Register scratch = ToRegister(instr->temp());
2490
2491   if (rep.IsDouble()) {
2492     DoubleRegister value = ToDoubleRegister(instr->value());
2493     __ fcmpu(value, kDoubleRegZero);
2494     EmitFalseBranch(instr, ne);
2495 #if V8_TARGET_ARCH_PPC64
2496     __ MovDoubleToInt64(scratch, value);
2497 #else
2498     __ MovDoubleHighToInt(scratch, value);
2499 #endif
2500     __ cmpi(scratch, Operand::Zero());
2501     EmitBranch(instr, lt);
2502   } else {
2503     Register value = ToRegister(instr->value());
2504     __ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex,
2505                 instr->FalseLabel(chunk()), DO_SMI_CHECK);
2506 #if V8_TARGET_ARCH_PPC64
2507     __ LoadP(scratch, FieldMemOperand(value, HeapNumber::kValueOffset));
2508     __ li(ip, Operand(1));
2509     __ rotrdi(ip, ip, 1);  // ip = 0x80000000_00000000
2510     __ cmp(scratch, ip);
2511 #else
2512     __ lwz(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset));
2513     __ lwz(ip, FieldMemOperand(value, HeapNumber::kMantissaOffset));
2514     Label skip;
2515     __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
2516     __ cmp(scratch, r0);
2517     __ bne(&skip);
2518     __ cmpi(ip, Operand::Zero());
2519     __ bind(&skip);
2520 #endif
2521     EmitBranch(instr, eq);
2522   }
2523 }
2524
2525
2526 Condition LCodeGen::EmitIsObject(Register input, Register temp1,
2527                                  Label* is_not_object, Label* is_object) {
2528   Register temp2 = scratch0();
2529   __ JumpIfSmi(input, is_not_object);
2530
2531   __ LoadRoot(temp2, Heap::kNullValueRootIndex);
2532   __ cmp(input, temp2);
2533   __ beq(is_object);
2534
2535   // Load map.
2536   __ LoadP(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
2537   // Undetectable objects behave like undefined.
2538   __ lbz(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
2539   __ TestBit(temp2, Map::kIsUndetectable, r0);
2540   __ bne(is_not_object, cr0);
2541
2542   // Load instance type and check that it is in object type range.
2543   __ lbz(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
2544   __ cmpi(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2545   __ blt(is_not_object);
2546   __ cmpi(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2547   return le;
2548 }
2549
2550
2551 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
2552   Register reg = ToRegister(instr->value());
2553   Register temp1 = ToRegister(instr->temp());
2554
2555   Condition true_cond = EmitIsObject(reg, temp1, instr->FalseLabel(chunk_),
2556                                      instr->TrueLabel(chunk_));
2557
2558   EmitBranch(instr, true_cond);
2559 }
2560
2561
2562 Condition LCodeGen::EmitIsString(Register input, Register temp1,
2563                                  Label* is_not_string,
2564                                  SmiCheck check_needed = INLINE_SMI_CHECK) {
2565   if (check_needed == INLINE_SMI_CHECK) {
2566     __ JumpIfSmi(input, is_not_string);
2567   }
2568   __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE);
2569
2570   return lt;
2571 }
2572
2573
2574 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2575   Register reg = ToRegister(instr->value());
2576   Register temp1 = ToRegister(instr->temp());
2577
2578   SmiCheck check_needed = instr->hydrogen()->value()->type().IsHeapObject()
2579                               ? OMIT_SMI_CHECK
2580                               : INLINE_SMI_CHECK;
2581   Condition true_cond =
2582       EmitIsString(reg, temp1, instr->FalseLabel(chunk_), check_needed);
2583
2584   EmitBranch(instr, true_cond);
2585 }
2586
2587
2588 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2589   Register input_reg = EmitLoadRegister(instr->value(), ip);
2590   __ TestIfSmi(input_reg, r0);
2591   EmitBranch(instr, eq, cr0);
2592 }
2593
2594
2595 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2596   Register input = ToRegister(instr->value());
2597   Register temp = ToRegister(instr->temp());
2598
2599   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2600     __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2601   }
2602   __ LoadP(temp, FieldMemOperand(input, HeapObject::kMapOffset));
2603   __ lbz(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
2604   __ TestBit(temp, Map::kIsUndetectable, r0);
2605   EmitBranch(instr, ne, cr0);
2606 }
2607
2608
2609 static Condition ComputeCompareCondition(Token::Value op) {
2610   switch (op) {
2611     case Token::EQ_STRICT:
2612     case Token::EQ:
2613       return eq;
2614     case Token::LT:
2615       return lt;
2616     case Token::GT:
2617       return gt;
2618     case Token::LTE:
2619       return le;
2620     case Token::GTE:
2621       return ge;
2622     default:
2623       UNREACHABLE();
2624       return kNoCondition;
2625   }
2626 }
2627
2628
2629 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2630   DCHECK(ToRegister(instr->context()).is(cp));
2631   Token::Value op = instr->op();
2632
2633   Handle<Code> ic =
2634       CodeFactory::CompareIC(isolate(), op, Strength::WEAK).code();
2635   CallCode(ic, RelocInfo::CODE_TARGET, instr);
2636   // This instruction also signals no smi code inlined
2637   __ cmpi(r3, Operand::Zero());
2638
2639   Condition condition = ComputeCompareCondition(op);
2640
2641   EmitBranch(instr, condition);
2642 }
2643
2644
2645 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2646   InstanceType from = instr->from();
2647   InstanceType to = instr->to();
2648   if (from == FIRST_TYPE) return to;
2649   DCHECK(from == to || to == LAST_TYPE);
2650   return from;
2651 }
2652
2653
2654 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2655   InstanceType from = instr->from();
2656   InstanceType to = instr->to();
2657   if (from == to) return eq;
2658   if (to == LAST_TYPE) return ge;
2659   if (from == FIRST_TYPE) return le;
2660   UNREACHABLE();
2661   return eq;
2662 }
2663
2664
2665 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2666   Register scratch = scratch0();
2667   Register input = ToRegister(instr->value());
2668
2669   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2670     __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2671   }
2672
2673   __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
2674   EmitBranch(instr, BranchCondition(instr->hydrogen()));
2675 }
2676
2677
2678 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
2679   Register input = ToRegister(instr->value());
2680   Register result = ToRegister(instr->result());
2681
2682   __ AssertString(input);
2683
2684   __ lwz(result, FieldMemOperand(input, String::kHashFieldOffset));
2685   __ IndexFromHash(result, result);
2686 }
2687
2688
2689 void LCodeGen::DoHasCachedArrayIndexAndBranch(
2690     LHasCachedArrayIndexAndBranch* instr) {
2691   Register input = ToRegister(instr->value());
2692   Register scratch = scratch0();
2693
2694   __ lwz(scratch, FieldMemOperand(input, String::kHashFieldOffset));
2695   __ mov(r0, Operand(String::kContainsCachedArrayIndexMask));
2696   __ and_(r0, scratch, r0, SetRC);
2697   EmitBranch(instr, eq, cr0);
2698 }
2699
2700
2701 // Branches to a label or falls through with the answer in flags.  Trashes
2702 // the temp registers, but not the input.
2703 void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false,
2704                                Handle<String> class_name, Register input,
2705                                Register temp, Register temp2) {
2706   DCHECK(!input.is(temp));
2707   DCHECK(!input.is(temp2));
2708   DCHECK(!temp.is(temp2));
2709
2710   __ JumpIfSmi(input, is_false);
2711
2712   if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
2713     // Assuming the following assertions, we can use the same compares to test
2714     // for both being a function type and being in the object type range.
2715     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2716     STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2717                   FIRST_SPEC_OBJECT_TYPE + 1);
2718     STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2719                   LAST_SPEC_OBJECT_TYPE - 1);
2720     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
2721     __ CompareObjectType(input, temp, temp2, FIRST_SPEC_OBJECT_TYPE);
2722     __ blt(is_false);
2723     __ beq(is_true);
2724     __ cmpi(temp2, Operand(LAST_SPEC_OBJECT_TYPE));
2725     __ beq(is_true);
2726   } else {
2727     // Faster code path to avoid two compares: subtract lower bound from the
2728     // actual type and do a signed compare with the width of the type range.
2729     __ LoadP(temp, FieldMemOperand(input, HeapObject::kMapOffset));
2730     __ lbz(temp2, FieldMemOperand(temp, Map::kInstanceTypeOffset));
2731     __ subi(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2732     __ cmpi(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
2733                            FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2734     __ bgt(is_false);
2735   }
2736
2737   // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
2738   // Check if the constructor in the map is a function.
2739   Register instance_type = ip;
2740   __ GetMapConstructor(temp, temp, temp2, instance_type);
2741
2742   // Objects with a non-function constructor have class 'Object'.
2743   __ cmpi(instance_type, Operand(JS_FUNCTION_TYPE));
2744   if (class_name->IsOneByteEqualTo(STATIC_CHAR_VECTOR("Object"))) {
2745     __ bne(is_true);
2746   } else {
2747     __ bne(is_false);
2748   }
2749
2750   // temp now contains the constructor function. Grab the
2751   // instance class name from there.
2752   __ LoadP(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
2753   __ LoadP(temp,
2754            FieldMemOperand(temp, SharedFunctionInfo::kInstanceClassNameOffset));
2755   // The class name we are testing against is internalized since it's a literal.
2756   // The name in the constructor is internalized because of the way the context
2757   // is booted.  This routine isn't expected to work for random API-created
2758   // classes and it doesn't have to because you can't access it with natives
2759   // syntax.  Since both sides are internalized it is sufficient to use an
2760   // identity comparison.
2761   __ Cmpi(temp, Operand(class_name), r0);
2762   // End with the answer in flags.
2763 }
2764
2765
2766 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2767   Register input = ToRegister(instr->value());
2768   Register temp = scratch0();
2769   Register temp2 = ToRegister(instr->temp());
2770   Handle<String> class_name = instr->hydrogen()->class_name();
2771
2772   EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2773                   class_name, input, temp, temp2);
2774
2775   EmitBranch(instr, eq);
2776 }
2777
2778
2779 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2780   Register reg = ToRegister(instr->value());
2781   Register temp = ToRegister(instr->temp());
2782
2783   __ LoadP(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
2784   __ Cmpi(temp, Operand(instr->map()), r0);
2785   EmitBranch(instr, eq);
2786 }
2787
2788
2789 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2790   DCHECK(ToRegister(instr->context()).is(cp));
2791   DCHECK(ToRegister(instr->left()).is(r3));   // Object is in r3.
2792   DCHECK(ToRegister(instr->right()).is(r4));  // Function is in r4.
2793
2794   InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters);
2795   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2796
2797   if (CpuFeatures::IsSupported(ISELECT)) {
2798     __ mov(r4, Operand(factory()->true_value()));
2799     __ mov(r5, Operand(factory()->false_value()));
2800     __ cmpi(r3, Operand::Zero());
2801     __ isel(eq, r3, r4, r5);
2802   } else {
2803     Label equal, done;
2804     __ cmpi(r3, Operand::Zero());
2805     __ beq(&equal);
2806     __ mov(r3, Operand(factory()->false_value()));
2807     __ b(&done);
2808
2809     __ bind(&equal);
2810     __ mov(r3, Operand(factory()->true_value()));
2811     __ bind(&done);
2812   }
2813 }
2814
2815
2816 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2817   class DeferredInstanceOfKnownGlobal final : public LDeferredCode {
2818    public:
2819     DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2820                                   LInstanceOfKnownGlobal* instr)
2821         : LDeferredCode(codegen), instr_(instr) {}
2822     void Generate() override {
2823       codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_,
2824                                                  &load_bool_);
2825     }
2826     LInstruction* instr() override { return instr_; }
2827     Label* map_check() { return &map_check_; }
2828     Label* load_bool() { return &load_bool_; }
2829
2830    private:
2831     LInstanceOfKnownGlobal* instr_;
2832     Label map_check_;
2833     Label load_bool_;
2834   };
2835
2836   DeferredInstanceOfKnownGlobal* deferred;
2837   deferred = new (zone()) DeferredInstanceOfKnownGlobal(this, instr);
2838
2839   Label done, false_result;
2840   Register object = ToRegister(instr->value());
2841   Register temp = ToRegister(instr->temp());
2842   Register result = ToRegister(instr->result());
2843
2844   // A Smi is not instance of anything.
2845   __ JumpIfSmi(object, &false_result);
2846
2847   // This is the inlined call site instanceof cache. The two occurences of the
2848   // hole value will be patched to the last map/result pair generated by the
2849   // instanceof stub.
2850   Label cache_miss;
2851   Register map = temp;
2852   __ LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
2853   {
2854     // Block trampoline emission to ensure the positions of instructions are
2855     // as expected by the patcher. See InstanceofStub::Generate().
2856     Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
2857     __ bind(deferred->map_check());  // Label for calculating code patching.
2858     // We use Factory::the_hole_value() on purpose instead of loading from the
2859     // root array to force relocation to be able to later patch with
2860     // the cached map.
2861     Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value());
2862     __ mov(ip, Operand(cell));
2863     __ LoadP(ip, FieldMemOperand(ip, Cell::kValueOffset));
2864     __ cmp(map, ip);
2865     __ bc_short(ne, &cache_miss);
2866     __ bind(deferred->load_bool());  // Label for calculating code patching.
2867     // We use Factory::the_hole_value() on purpose instead of loading from the
2868     // root array to force relocation to be able to later patch
2869     // with true or false.
2870     __ mov(result, Operand(factory()->the_hole_value()));
2871   }
2872   __ b(&done);
2873
2874   // The inlined call site cache did not match. Check null and string before
2875   // calling the deferred code.
2876   __ bind(&cache_miss);
2877   // Null is not instance of anything.
2878   __ LoadRoot(ip, Heap::kNullValueRootIndex);
2879   __ cmp(object, ip);
2880   __ beq(&false_result);
2881
2882   // String values is not instance of anything.
2883   Condition is_string = masm_->IsObjectStringType(object, temp);
2884   __ b(is_string, &false_result, cr0);
2885
2886   // Go to the deferred code.
2887   __ b(deferred->entry());
2888
2889   __ bind(&false_result);
2890   __ LoadRoot(result, Heap::kFalseValueRootIndex);
2891
2892   // Here result has either true or false. Deferred code also produces true or
2893   // false object.
2894   __ bind(deferred->exit());
2895   __ bind(&done);
2896 }
2897
2898
2899 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
2900                                                Label* map_check,
2901                                                Label* bool_load) {
2902   InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
2903   flags = static_cast<InstanceofStub::Flags>(flags |
2904                                              InstanceofStub::kArgsInRegisters);
2905   flags = static_cast<InstanceofStub::Flags>(
2906       flags | InstanceofStub::kCallSiteInlineCheck);
2907   flags = static_cast<InstanceofStub::Flags>(
2908       flags | InstanceofStub::kReturnTrueFalseObject);
2909   InstanceofStub stub(isolate(), flags);
2910
2911   PushSafepointRegistersScope scope(this);
2912   LoadContextFromDeferred(instr->context());
2913
2914   __ Move(InstanceofStub::right(), instr->function());
2915   {
2916     Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
2917     Handle<Code> code = stub.GetCode();
2918     // Include instructions below in delta: bitwise_mov32 + li + call
2919     int additional_delta = 3 * Instruction::kInstrSize + masm_->CallSize(code);
2920     // The labels must be already bound since the code has predictabel size up
2921     // to the call instruction.
2922     DCHECK(map_check->is_bound());
2923     DCHECK(bool_load->is_bound());
2924     int map_check_delta =
2925         masm_->InstructionsGeneratedSince(map_check) * Instruction::kInstrSize;
2926     int bool_load_delta =
2927         masm_->InstructionsGeneratedSince(bool_load) * Instruction::kInstrSize;
2928     // r8 is the delta from our callee's lr to the location of the map check.
2929     __ bitwise_mov32(r8, map_check_delta + additional_delta);
2930     // r9 is the delta from map check to bool load.
2931     __ li(r9, Operand(map_check_delta - bool_load_delta));
2932     CallCodeGeneric(code, RelocInfo::CODE_TARGET, instr,
2933                     RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
2934     DCHECK_EQ((map_check_delta + additional_delta) / Instruction::kInstrSize,
2935               masm_->InstructionsGeneratedSince(map_check));
2936   }
2937   LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
2938   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
2939   // Put the result value (r3) into the result register slot and
2940   // restore all registers.
2941   __ StoreToSafepointRegisterSlot(r3, ToRegister(instr->result()));
2942 }
2943
2944
2945 void LCodeGen::DoCmpT(LCmpT* instr) {
2946   DCHECK(ToRegister(instr->context()).is(cp));
2947   Token::Value op = instr->op();
2948
2949   Handle<Code> ic =
2950       CodeFactory::CompareIC(isolate(), op, instr->strength()).code();
2951   CallCode(ic, RelocInfo::CODE_TARGET, instr);
2952   // This instruction also signals no smi code inlined
2953   __ cmpi(r3, Operand::Zero());
2954
2955   Condition condition = ComputeCompareCondition(op);
2956   if (CpuFeatures::IsSupported(ISELECT)) {
2957     __ LoadRoot(r4, Heap::kTrueValueRootIndex);
2958     __ LoadRoot(r5, Heap::kFalseValueRootIndex);
2959     __ isel(condition, ToRegister(instr->result()), r4, r5);
2960   } else {
2961     Label true_value, done;
2962
2963     __ b(condition, &true_value);
2964
2965     __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
2966     __ b(&done);
2967
2968     __ bind(&true_value);
2969     __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
2970
2971     __ bind(&done);
2972   }
2973 }
2974
2975
2976 void LCodeGen::DoReturn(LReturn* instr) {
2977   if (FLAG_trace && info()->IsOptimizing()) {
2978     // Push the return value on the stack as the parameter.
2979     // Runtime::TraceExit returns its parameter in r3.  We're leaving the code
2980     // managed by the register allocator and tearing down the frame, it's
2981     // safe to write to the context register.
2982     __ push(r3);
2983     __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2984     __ CallRuntime(Runtime::kTraceExit, 1);
2985   }
2986   if (info()->saves_caller_doubles()) {
2987     RestoreCallerDoubles();
2988   }
2989   int no_frame_start = -1;
2990   if (instr->has_constant_parameter_count()) {
2991     int parameter_count = ToInteger32(instr->constant_parameter_count());
2992     int32_t sp_delta = (parameter_count + 1) * kPointerSize;
2993     if (NeedsEagerFrame()) {
2994       no_frame_start = masm_->LeaveFrame(StackFrame::JAVA_SCRIPT, sp_delta);
2995     } else if (sp_delta != 0) {
2996       __ addi(sp, sp, Operand(sp_delta));
2997     }
2998   } else {
2999     DCHECK(info()->IsStub());  // Functions would need to drop one more value.
3000     Register reg = ToRegister(instr->parameter_count());
3001     // The argument count parameter is a smi
3002     if (NeedsEagerFrame()) {
3003       no_frame_start = masm_->LeaveFrame(StackFrame::JAVA_SCRIPT);
3004     }
3005     __ SmiToPtrArrayOffset(r0, reg);
3006     __ add(sp, sp, r0);
3007   }
3008
3009   __ blr();
3010
3011   if (no_frame_start != -1) {
3012     info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
3013   }
3014 }
3015
3016
3017 template <class T>
3018 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
3019   Register vector_register = ToRegister(instr->temp_vector());
3020   Register slot_register = LoadDescriptor::SlotRegister();
3021   DCHECK(vector_register.is(LoadWithVectorDescriptor::VectorRegister()));
3022   DCHECK(slot_register.is(r3));
3023
3024   AllowDeferredHandleDereference vector_structure_check;
3025   Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
3026   __ Move(vector_register, vector);
3027   // No need to allocate this register.
3028   FeedbackVectorICSlot slot = instr->hydrogen()->slot();
3029   int index = vector->GetIndex(slot);
3030   __ LoadSmiLiteral(slot_register, Smi::FromInt(index));
3031 }
3032
3033
3034 template <class T>
3035 void LCodeGen::EmitVectorStoreICRegisters(T* instr) {
3036   Register vector_register = ToRegister(instr->temp_vector());
3037   Register slot_register = ToRegister(instr->temp_slot());
3038
3039   AllowDeferredHandleDereference vector_structure_check;
3040   Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
3041   __ Move(vector_register, vector);
3042   FeedbackVectorICSlot slot = instr->hydrogen()->slot();
3043   int index = vector->GetIndex(slot);
3044   __ LoadSmiLiteral(slot_register, Smi::FromInt(index));
3045 }
3046
3047
3048 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
3049   DCHECK(ToRegister(instr->context()).is(cp));
3050   DCHECK(ToRegister(instr->global_object())
3051              .is(LoadDescriptor::ReceiverRegister()));
3052   DCHECK(ToRegister(instr->result()).is(r3));
3053
3054   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
3055   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
3056   Handle<Code> ic =
3057       CodeFactory::LoadICInOptimizedCode(isolate(), instr->typeof_mode(),
3058                                          SLOPPY, PREMONOMORPHIC).code();
3059   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3060 }
3061
3062
3063 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3064   Register context = ToRegister(instr->context());
3065   Register result = ToRegister(instr->result());
3066   __ LoadP(result, ContextOperand(context, instr->slot_index()));
3067   if (instr->hydrogen()->RequiresHoleCheck()) {
3068     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3069     if (instr->hydrogen()->DeoptimizesOnHole()) {
3070       __ cmp(result, ip);
3071       DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3072     } else {
3073       if (CpuFeatures::IsSupported(ISELECT)) {
3074         Register scratch = scratch0();
3075         __ mov(scratch, Operand(factory()->undefined_value()));
3076         __ cmp(result, ip);
3077         __ isel(eq, result, scratch, result);
3078       } else {
3079         Label skip;
3080         __ cmp(result, ip);
3081         __ bne(&skip);
3082         __ mov(result, Operand(factory()->undefined_value()));
3083         __ bind(&skip);
3084       }
3085     }
3086   }
3087 }
3088
3089
3090 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3091   Register context = ToRegister(instr->context());
3092   Register value = ToRegister(instr->value());
3093   Register scratch = scratch0();
3094   MemOperand target = ContextOperand(context, instr->slot_index());
3095
3096   Label skip_assignment;
3097
3098   if (instr->hydrogen()->RequiresHoleCheck()) {
3099     __ LoadP(scratch, target);
3100     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3101     __ cmp(scratch, ip);
3102     if (instr->hydrogen()->DeoptimizesOnHole()) {
3103       DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3104     } else {
3105       __ bne(&skip_assignment);
3106     }
3107   }
3108
3109   __ StoreP(value, target, r0);
3110   if (instr->hydrogen()->NeedsWriteBarrier()) {
3111     SmiCheck check_needed = instr->hydrogen()->value()->type().IsHeapObject()
3112                                 ? OMIT_SMI_CHECK
3113                                 : INLINE_SMI_CHECK;
3114     __ RecordWriteContextSlot(context, target.offset(), value, scratch,
3115                               GetLinkRegisterState(), kSaveFPRegs,
3116                               EMIT_REMEMBERED_SET, check_needed);
3117   }
3118
3119   __ bind(&skip_assignment);
3120 }
3121
3122
3123 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
3124   HObjectAccess access = instr->hydrogen()->access();
3125   int offset = access.offset();
3126   Register object = ToRegister(instr->object());
3127
3128   if (access.IsExternalMemory()) {
3129     Register result = ToRegister(instr->result());
3130     MemOperand operand = MemOperand(object, offset);
3131     __ LoadRepresentation(result, operand, access.representation(), r0);
3132     return;
3133   }
3134
3135   if (instr->hydrogen()->representation().IsDouble()) {
3136     DCHECK(access.IsInobject());
3137     DoubleRegister result = ToDoubleRegister(instr->result());
3138     __ lfd(result, FieldMemOperand(object, offset));
3139     return;
3140   }
3141
3142   Register result = ToRegister(instr->result());
3143   if (!access.IsInobject()) {
3144     __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
3145     object = result;
3146   }
3147
3148   Representation representation = access.representation();
3149
3150 #if V8_TARGET_ARCH_PPC64
3151   // 64-bit Smi optimization
3152   if (representation.IsSmi() &&
3153       instr->hydrogen()->representation().IsInteger32()) {
3154     // Read int value directly from upper half of the smi.
3155     offset = SmiWordOffset(offset);
3156     representation = Representation::Integer32();
3157   }
3158 #endif
3159
3160   __ LoadRepresentation(result, FieldMemOperand(object, offset), representation,
3161                         r0);
3162 }
3163
3164
3165 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
3166   DCHECK(ToRegister(instr->context()).is(cp));
3167   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3168   DCHECK(ToRegister(instr->result()).is(r3));
3169
3170   // Name is always in r5.
3171   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
3172   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
3173   Handle<Code> ic =
3174       CodeFactory::LoadICInOptimizedCode(
3175           isolate(), NOT_INSIDE_TYPEOF, instr->hydrogen()->language_mode(),
3176           instr->hydrogen()->initialization_state()).code();
3177   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3178 }
3179
3180
3181 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
3182   Register scratch = scratch0();
3183   Register function = ToRegister(instr->function());
3184   Register result = ToRegister(instr->result());
3185
3186   // Get the prototype or initial map from the function.
3187   __ LoadP(result,
3188            FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3189
3190   // Check that the function has a prototype or an initial map.
3191   __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3192   __ cmp(result, ip);
3193   DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3194
3195   // If the function does not have an initial map, we're done.
3196   if (CpuFeatures::IsSupported(ISELECT)) {
3197     // Get the prototype from the initial map (optimistic).
3198     __ LoadP(ip, FieldMemOperand(result, Map::kPrototypeOffset));
3199     __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
3200     __ isel(eq, result, ip, result);
3201   } else {
3202     Label done;
3203     __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
3204     __ bne(&done);
3205
3206     // Get the prototype from the initial map.
3207     __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset));
3208
3209     // All done.
3210     __ bind(&done);
3211   }
3212 }
3213
3214
3215 void LCodeGen::DoLoadRoot(LLoadRoot* instr) {
3216   Register result = ToRegister(instr->result());
3217   __ LoadRoot(result, instr->index());
3218 }
3219
3220
3221 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
3222   Register arguments = ToRegister(instr->arguments());
3223   Register result = ToRegister(instr->result());
3224   // There are two words between the frame pointer and the last argument.
3225   // Subtracting from length accounts for one of them add one more.
3226   if (instr->length()->IsConstantOperand()) {
3227     int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
3228     if (instr->index()->IsConstantOperand()) {
3229       int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3230       int index = (const_length - const_index) + 1;
3231       __ LoadP(result, MemOperand(arguments, index * kPointerSize), r0);
3232     } else {
3233       Register index = ToRegister(instr->index());
3234       __ subfic(result, index, Operand(const_length + 1));
3235       __ ShiftLeftImm(result, result, Operand(kPointerSizeLog2));
3236       __ LoadPX(result, MemOperand(arguments, result));
3237     }
3238   } else if (instr->index()->IsConstantOperand()) {
3239     Register length = ToRegister(instr->length());
3240     int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3241     int loc = const_index - 1;
3242     if (loc != 0) {
3243       __ subi(result, length, Operand(loc));
3244       __ ShiftLeftImm(result, result, Operand(kPointerSizeLog2));
3245       __ LoadPX(result, MemOperand(arguments, result));
3246     } else {
3247       __ ShiftLeftImm(result, length, Operand(kPointerSizeLog2));
3248       __ LoadPX(result, MemOperand(arguments, result));
3249     }
3250   } else {
3251     Register length = ToRegister(instr->length());
3252     Register index = ToRegister(instr->index());
3253     __ sub(result, length, index);
3254     __ addi(result, result, Operand(1));
3255     __ ShiftLeftImm(result, result, Operand(kPointerSizeLog2));
3256     __ LoadPX(result, MemOperand(arguments, result));
3257   }
3258 }
3259
3260
3261 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
3262   Register external_pointer = ToRegister(instr->elements());
3263   Register key = no_reg;
3264   ElementsKind elements_kind = instr->elements_kind();
3265   bool key_is_constant = instr->key()->IsConstantOperand();
3266   int constant_key = 0;
3267   if (key_is_constant) {
3268     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
3269     if (constant_key & 0xF0000000) {
3270       Abort(kArrayIndexConstantValueTooBig);
3271     }
3272   } else {
3273     key = ToRegister(instr->key());
3274   }
3275   int element_size_shift = ElementsKindToShiftSize(elements_kind);
3276   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
3277   int base_offset = instr->base_offset();
3278
3279   if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
3280       elements_kind == FLOAT32_ELEMENTS ||
3281       elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
3282       elements_kind == FLOAT64_ELEMENTS) {
3283     DoubleRegister result = ToDoubleRegister(instr->result());
3284     if (key_is_constant) {
3285       __ Add(scratch0(), external_pointer, constant_key << element_size_shift,
3286              r0);
3287     } else {
3288       __ IndexToArrayOffset(r0, key, element_size_shift, key_is_smi);
3289       __ add(scratch0(), external_pointer, r0);
3290     }
3291     if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
3292         elements_kind == FLOAT32_ELEMENTS) {
3293       __ lfs(result, MemOperand(scratch0(), base_offset));
3294     } else {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
3295       __ lfd(result, MemOperand(scratch0(), base_offset));
3296     }
3297   } else {
3298     Register result = ToRegister(instr->result());
3299     MemOperand mem_operand =
3300         PrepareKeyedOperand(key, external_pointer, key_is_constant, key_is_smi,
3301                             constant_key, element_size_shift, base_offset);
3302     switch (elements_kind) {
3303       case EXTERNAL_INT8_ELEMENTS:
3304       case INT8_ELEMENTS:
3305         if (key_is_constant) {
3306           __ LoadByte(result, mem_operand, r0);
3307         } else {
3308           __ lbzx(result, mem_operand);
3309         }
3310         __ extsb(result, result);
3311         break;
3312       case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
3313       case EXTERNAL_UINT8_ELEMENTS:
3314       case UINT8_ELEMENTS:
3315       case UINT8_CLAMPED_ELEMENTS:
3316         if (key_is_constant) {
3317           __ LoadByte(result, mem_operand, r0);
3318         } else {
3319           __ lbzx(result, mem_operand);
3320         }
3321         break;
3322       case EXTERNAL_INT16_ELEMENTS:
3323       case INT16_ELEMENTS:
3324         if (key_is_constant) {
3325           __ LoadHalfWordArith(result, mem_operand, r0);
3326         } else {
3327           __ lhax(result, mem_operand);
3328         }
3329         break;
3330       case EXTERNAL_UINT16_ELEMENTS:
3331       case UINT16_ELEMENTS:
3332         if (key_is_constant) {
3333           __ LoadHalfWord(result, mem_operand, r0);
3334         } else {
3335           __ lhzx(result, mem_operand);
3336         }
3337         break;
3338       case EXTERNAL_INT32_ELEMENTS:
3339       case INT32_ELEMENTS:
3340         if (key_is_constant) {
3341           __ LoadWordArith(result, mem_operand, r0);
3342         } else {
3343           __ lwax(result, mem_operand);
3344         }
3345         break;
3346       case EXTERNAL_UINT32_ELEMENTS:
3347       case UINT32_ELEMENTS:
3348         if (key_is_constant) {
3349           __ LoadWord(result, mem_operand, r0);
3350         } else {
3351           __ lwzx(result, mem_operand);
3352         }
3353         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3354           __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
3355           __ cmplw(result, r0);
3356           DeoptimizeIf(ge, instr, Deoptimizer::kNegativeValue);
3357         }
3358         break;
3359       case FLOAT32_ELEMENTS:
3360       case FLOAT64_ELEMENTS:
3361       case EXTERNAL_FLOAT32_ELEMENTS:
3362       case EXTERNAL_FLOAT64_ELEMENTS:
3363       case FAST_HOLEY_DOUBLE_ELEMENTS:
3364       case FAST_HOLEY_ELEMENTS:
3365       case FAST_HOLEY_SMI_ELEMENTS:
3366       case FAST_DOUBLE_ELEMENTS:
3367       case FAST_ELEMENTS:
3368       case FAST_SMI_ELEMENTS:
3369       case DICTIONARY_ELEMENTS:
3370       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
3371       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
3372         UNREACHABLE();
3373         break;
3374     }
3375   }
3376 }
3377
3378
3379 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3380   Register elements = ToRegister(instr->elements());
3381   bool key_is_constant = instr->key()->IsConstantOperand();
3382   Register key = no_reg;
3383   DoubleRegister result = ToDoubleRegister(instr->result());
3384   Register scratch = scratch0();
3385
3386   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
3387   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
3388   int constant_key = 0;
3389   if (key_is_constant) {
3390     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
3391     if (constant_key & 0xF0000000) {
3392       Abort(kArrayIndexConstantValueTooBig);
3393     }
3394   } else {
3395     key = ToRegister(instr->key());
3396   }
3397
3398   int base_offset = instr->base_offset() + constant_key * kDoubleSize;
3399   if (!key_is_constant) {
3400     __ IndexToArrayOffset(r0, key, element_size_shift, key_is_smi);
3401     __ add(scratch, elements, r0);
3402     elements = scratch;
3403   }
3404   if (!is_int16(base_offset)) {
3405     __ Add(scratch, elements, base_offset, r0);
3406     base_offset = 0;
3407     elements = scratch;
3408   }
3409   __ lfd(result, MemOperand(elements, base_offset));
3410
3411   if (instr->hydrogen()->RequiresHoleCheck()) {
3412     if (is_int16(base_offset + Register::kExponentOffset)) {
3413       __ lwz(scratch,
3414              MemOperand(elements, base_offset + Register::kExponentOffset));
3415     } else {
3416       __ addi(scratch, elements, Operand(base_offset));
3417       __ lwz(scratch, MemOperand(scratch, Register::kExponentOffset));
3418     }
3419     __ Cmpi(scratch, Operand(kHoleNanUpper32), r0);
3420     DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3421   }
3422 }
3423
3424
3425 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3426   HLoadKeyed* hinstr = instr->hydrogen();
3427   Register elements = ToRegister(instr->elements());
3428   Register result = ToRegister(instr->result());
3429   Register scratch = scratch0();
3430   Register store_base = scratch;
3431   int offset = instr->base_offset();
3432
3433   if (instr->key()->IsConstantOperand()) {
3434     LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
3435     offset += ToInteger32(const_operand) * kPointerSize;
3436     store_base = elements;
3437   } else {
3438     Register key = ToRegister(instr->key());
3439     // Even though the HLoadKeyed instruction forces the input
3440     // representation for the key to be an integer, the input gets replaced
3441     // during bound check elimination with the index argument to the bounds
3442     // check, which can be tagged, so that case must be handled here, too.
3443     if (hinstr->key()->representation().IsSmi()) {
3444       __ SmiToPtrArrayOffset(r0, key);
3445     } else {
3446       __ ShiftLeftImm(r0, key, Operand(kPointerSizeLog2));
3447     }
3448     __ add(scratch, elements, r0);
3449   }
3450
3451   bool requires_hole_check = hinstr->RequiresHoleCheck();
3452   Representation representation = hinstr->representation();
3453
3454 #if V8_TARGET_ARCH_PPC64
3455   // 64-bit Smi optimization
3456   if (representation.IsInteger32() &&
3457       hinstr->elements_kind() == FAST_SMI_ELEMENTS) {
3458     DCHECK(!requires_hole_check);
3459     // Read int value directly from upper half of the smi.
3460     offset = SmiWordOffset(offset);
3461   }
3462 #endif
3463
3464   __ LoadRepresentation(result, MemOperand(store_base, offset), representation,
3465                         r0);
3466
3467   // Check for the hole value.
3468   if (requires_hole_check) {
3469     if (IsFastSmiElementsKind(hinstr->elements_kind())) {
3470       __ TestIfSmi(result, r0);
3471       DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
3472     } else {
3473       __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3474       __ cmp(result, scratch);
3475       DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3476     }
3477   } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) {
3478     DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS);
3479     Label done;
3480     __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3481     __ cmp(result, scratch);
3482     __ bne(&done);
3483     if (info()->IsStub()) {
3484       // A stub can safely convert the hole to undefined only if the array
3485       // protector cell contains (Smi) Isolate::kArrayProtectorValid. Otherwise
3486       // it needs to bail out.
3487       __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
3488       __ LoadP(result, FieldMemOperand(result, Cell::kValueOffset));
3489       __ CmpSmiLiteral(result, Smi::FromInt(Isolate::kArrayProtectorValid), r0);
3490       DeoptimizeIf(ne, instr, Deoptimizer::kHole);
3491     }
3492     __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3493     __ bind(&done);
3494   }
3495 }
3496
3497
3498 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3499   if (instr->is_typed_elements()) {
3500     DoLoadKeyedExternalArray(instr);
3501   } else if (instr->hydrogen()->representation().IsDouble()) {
3502     DoLoadKeyedFixedDoubleArray(instr);
3503   } else {
3504     DoLoadKeyedFixedArray(instr);
3505   }
3506 }
3507
3508
3509 MemOperand LCodeGen::PrepareKeyedOperand(Register key, Register base,
3510                                          bool key_is_constant, bool key_is_smi,
3511                                          int constant_key,
3512                                          int element_size_shift,
3513                                          int base_offset) {
3514   Register scratch = scratch0();
3515
3516   if (key_is_constant) {
3517     return MemOperand(base, (constant_key << element_size_shift) + base_offset);
3518   }
3519
3520   bool needs_shift =
3521       (element_size_shift != (key_is_smi ? kSmiTagSize + kSmiShiftSize : 0));
3522
3523   if (!(base_offset || needs_shift)) {
3524     return MemOperand(base, key);
3525   }
3526
3527   if (needs_shift) {
3528     __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi);
3529     key = scratch;
3530   }
3531
3532   if (base_offset) {
3533     __ Add(scratch, key, base_offset, r0);
3534   }
3535
3536   return MemOperand(base, scratch);
3537 }
3538
3539
3540 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
3541   DCHECK(ToRegister(instr->context()).is(cp));
3542   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3543   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
3544
3545   if (instr->hydrogen()->HasVectorAndSlot()) {
3546     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
3547   }
3548
3549   Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
3550                         isolate(), instr->hydrogen()->language_mode(),
3551                         instr->hydrogen()->initialization_state()).code();
3552   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3553 }
3554
3555
3556 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
3557   Register scratch = scratch0();
3558   Register result = ToRegister(instr->result());
3559
3560   if (instr->hydrogen()->from_inlined()) {
3561     __ subi(result, sp, Operand(2 * kPointerSize));
3562   } else {
3563     // Check if the calling frame is an arguments adaptor frame.
3564     __ LoadP(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3565     __ LoadP(result,
3566              MemOperand(scratch, StandardFrameConstants::kContextOffset));
3567     __ CmpSmiLiteral(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
3568
3569     // Result is the frame pointer for the frame if not adapted and for the real
3570     // frame below the adaptor frame if adapted.
3571     if (CpuFeatures::IsSupported(ISELECT)) {
3572       __ isel(eq, result, scratch, fp);
3573     } else {
3574       Label done, adapted;
3575       __ beq(&adapted);
3576       __ mr(result, fp);
3577       __ b(&done);
3578
3579       __ bind(&adapted);
3580       __ mr(result, scratch);
3581       __ bind(&done);
3582     }
3583   }
3584 }
3585
3586
3587 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
3588   Register elem = ToRegister(instr->elements());
3589   Register result = ToRegister(instr->result());
3590
3591   Label done;
3592
3593   // If no arguments adaptor frame the number of arguments is fixed.
3594   __ cmp(fp, elem);
3595   __ mov(result, Operand(scope()->num_parameters()));
3596   __ beq(&done);
3597
3598   // Arguments adaptor frame present. Get argument length from there.
3599   __ LoadP(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3600   __ LoadP(result,
3601            MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
3602   __ SmiUntag(result);
3603
3604   // Argument length is in result register.
3605   __ bind(&done);
3606 }
3607
3608
3609 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3610   Register receiver = ToRegister(instr->receiver());
3611   Register function = ToRegister(instr->function());
3612   Register result = ToRegister(instr->result());
3613   Register scratch = scratch0();
3614
3615   // If the receiver is null or undefined, we have to pass the global
3616   // object as a receiver to normal functions. Values have to be
3617   // passed unchanged to builtins and strict-mode functions.
3618   Label global_object, result_in_receiver;
3619
3620   if (!instr->hydrogen()->known_function()) {
3621     // Do not transform the receiver to object for strict mode
3622     // functions.
3623     __ LoadP(scratch,
3624              FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
3625     __ lwz(scratch,
3626            FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
3627     __ TestBit(scratch,
3628 #if V8_TARGET_ARCH_PPC64
3629                SharedFunctionInfo::kStrictModeFunction,
3630 #else
3631                SharedFunctionInfo::kStrictModeFunction + kSmiTagSize,
3632 #endif
3633                r0);
3634     __ bne(&result_in_receiver, cr0);
3635
3636     // Do not transform the receiver to object for builtins.
3637     __ TestBit(scratch,
3638 #if V8_TARGET_ARCH_PPC64
3639                SharedFunctionInfo::kNative,
3640 #else
3641                SharedFunctionInfo::kNative + kSmiTagSize,
3642 #endif
3643                r0);
3644     __ bne(&result_in_receiver, cr0);
3645   }
3646
3647   // Normal function. Replace undefined or null with global receiver.
3648   __ LoadRoot(scratch, Heap::kNullValueRootIndex);
3649   __ cmp(receiver, scratch);
3650   __ beq(&global_object);
3651   __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
3652   __ cmp(receiver, scratch);
3653   __ beq(&global_object);
3654
3655   // Deoptimize if the receiver is not a JS object.
3656   __ TestIfSmi(receiver, r0);
3657   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
3658   __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
3659   DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject);
3660
3661   __ b(&result_in_receiver);
3662   __ bind(&global_object);
3663   __ LoadP(result, FieldMemOperand(function, JSFunction::kContextOffset));
3664   __ LoadP(result, ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
3665   __ LoadP(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset));
3666   if (result.is(receiver)) {
3667     __ bind(&result_in_receiver);
3668   } else {
3669     Label result_ok;
3670     __ b(&result_ok);
3671     __ bind(&result_in_receiver);
3672     __ mr(result, receiver);
3673     __ bind(&result_ok);
3674   }
3675 }
3676
3677
3678 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3679   Register receiver = ToRegister(instr->receiver());
3680   Register function = ToRegister(instr->function());
3681   Register length = ToRegister(instr->length());
3682   Register elements = ToRegister(instr->elements());
3683   Register scratch = scratch0();
3684   DCHECK(receiver.is(r3));  // Used for parameter count.
3685   DCHECK(function.is(r4));  // Required by InvokeFunction.
3686   DCHECK(ToRegister(instr->result()).is(r3));
3687
3688   // Copy the arguments to this function possibly from the
3689   // adaptor frame below it.
3690   const uint32_t kArgumentsLimit = 1 * KB;
3691   __ cmpli(length, Operand(kArgumentsLimit));
3692   DeoptimizeIf(gt, instr, Deoptimizer::kTooManyArguments);
3693
3694   // Push the receiver and use the register to keep the original
3695   // number of arguments.
3696   __ push(receiver);
3697   __ mr(receiver, length);
3698   // The arguments are at a one pointer size offset from elements.
3699   __ addi(elements, elements, Operand(1 * kPointerSize));
3700
3701   // Loop through the arguments pushing them onto the execution
3702   // stack.
3703   Label invoke, loop;
3704   // length is a small non-negative integer, due to the test above.
3705   __ cmpi(length, Operand::Zero());
3706   __ beq(&invoke);
3707   __ mtctr(length);
3708   __ bind(&loop);
3709   __ ShiftLeftImm(r0, length, Operand(kPointerSizeLog2));
3710   __ LoadPX(scratch, MemOperand(elements, r0));
3711   __ push(scratch);
3712   __ addi(length, length, Operand(-1));
3713   __ bdnz(&loop);
3714
3715   __ bind(&invoke);
3716   DCHECK(instr->HasPointerMap());
3717   LPointerMap* pointers = instr->pointer_map();
3718   SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
3719   // The number of arguments is stored in receiver which is r3, as expected
3720   // by InvokeFunction.
3721   ParameterCount actual(receiver);
3722   __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
3723 }
3724
3725
3726 void LCodeGen::DoPushArgument(LPushArgument* instr) {
3727   LOperand* argument = instr->value();
3728   if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
3729     Abort(kDoPushArgumentNotImplementedForDoubleType);
3730   } else {
3731     Register argument_reg = EmitLoadRegister(argument, ip);
3732     __ push(argument_reg);
3733   }
3734 }
3735
3736
3737 void LCodeGen::DoDrop(LDrop* instr) { __ Drop(instr->count()); }
3738
3739
3740 void LCodeGen::DoThisFunction(LThisFunction* instr) {
3741   Register result = ToRegister(instr->result());
3742   __ LoadP(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
3743 }
3744
3745
3746 void LCodeGen::DoContext(LContext* instr) {
3747   // If there is a non-return use, the context must be moved to a register.
3748   Register result = ToRegister(instr->result());
3749   if (info()->IsOptimizing()) {
3750     __ LoadP(result, MemOperand(fp, StandardFrameConstants::kContextOffset));
3751   } else {
3752     // If there is no frame, the context must be in cp.
3753     DCHECK(result.is(cp));
3754   }
3755 }
3756
3757
3758 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3759   DCHECK(ToRegister(instr->context()).is(cp));
3760   __ push(cp);  // The context is the first argument.
3761   __ Move(scratch0(), instr->hydrogen()->pairs());
3762   __ push(scratch0());
3763   __ LoadSmiLiteral(scratch0(), Smi::FromInt(instr->hydrogen()->flags()));
3764   __ push(scratch0());
3765   CallRuntime(Runtime::kDeclareGlobals, 3, instr);
3766 }
3767
3768
3769 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3770                                  int formal_parameter_count, int arity,
3771                                  LInstruction* instr) {
3772   bool dont_adapt_arguments =
3773       formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3774   bool can_invoke_directly =
3775       dont_adapt_arguments || formal_parameter_count == arity;
3776
3777   Register function_reg = r4;
3778
3779   LPointerMap* pointers = instr->pointer_map();
3780
3781   if (can_invoke_directly) {
3782     // Change context.
3783     __ LoadP(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset));
3784
3785     // Set r3 to arguments count if adaption is not needed. Assumes that r3
3786     // is available to write to at this point.
3787     if (dont_adapt_arguments) {
3788       __ mov(r3, Operand(arity));
3789     }
3790
3791     bool is_self_call = function.is_identical_to(info()->closure());
3792
3793     // Invoke function.
3794     if (is_self_call) {
3795       __ CallSelf();
3796     } else {
3797       __ LoadP(ip, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
3798       __ CallJSEntry(ip);
3799     }
3800
3801     // Set up deoptimization.
3802     RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3803   } else {
3804     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3805     ParameterCount count(arity);
3806     ParameterCount expected(formal_parameter_count);
3807     __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator);
3808   }
3809 }
3810
3811
3812 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3813   DCHECK(instr->context() != NULL);
3814   DCHECK(ToRegister(instr->context()).is(cp));
3815   Register input = ToRegister(instr->value());
3816   Register result = ToRegister(instr->result());
3817   Register scratch = scratch0();
3818
3819   // Deoptimize if not a heap number.
3820   __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
3821   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3822   __ cmp(scratch, ip);
3823   DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
3824
3825   Label done;
3826   Register exponent = scratch0();
3827   scratch = no_reg;
3828   __ lwz(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3829   // Check the sign of the argument. If the argument is positive, just
3830   // return it.
3831   __ cmpwi(exponent, Operand::Zero());
3832   // Move the input to the result if necessary.
3833   __ Move(result, input);
3834   __ bge(&done);
3835
3836   // Input is negative. Reverse its sign.
3837   // Preserve the value of all registers.
3838   {
3839     PushSafepointRegistersScope scope(this);
3840
3841     // Registers were saved at the safepoint, so we can use
3842     // many scratch registers.
3843     Register tmp1 = input.is(r4) ? r3 : r4;
3844     Register tmp2 = input.is(r5) ? r3 : r5;
3845     Register tmp3 = input.is(r6) ? r3 : r6;
3846     Register tmp4 = input.is(r7) ? r3 : r7;
3847
3848     // exponent: floating point exponent value.
3849
3850     Label allocated, slow;
3851     __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
3852     __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
3853     __ b(&allocated);
3854
3855     // Slow case: Call the runtime system to do the number allocation.
3856     __ bind(&slow);
3857
3858     CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr,
3859                             instr->context());
3860     // Set the pointer to the new heap number in tmp.
3861     if (!tmp1.is(r3)) __ mr(tmp1, r3);
3862     // Restore input_reg after call to runtime.
3863     __ LoadFromSafepointRegisterSlot(input, input);
3864     __ lwz(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3865
3866     __ bind(&allocated);
3867     // exponent: floating point exponent value.
3868     // tmp1: allocated heap number.
3869     STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
3870     __ clrlwi(exponent, exponent, Operand(1));  // clear sign bit
3871     __ stw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
3872     __ lwz(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
3873     __ stw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
3874
3875     __ StoreToSafepointRegisterSlot(tmp1, result);
3876   }
3877
3878   __ bind(&done);
3879 }
3880
3881
3882 void LCodeGen::EmitMathAbs(LMathAbs* instr) {
3883   Register input = ToRegister(instr->value());
3884   Register result = ToRegister(instr->result());
3885   Label done;
3886   __ cmpi(input, Operand::Zero());
3887   __ Move(result, input);
3888   __ bge(&done);
3889   __ li(r0, Operand::Zero());  // clear xer
3890   __ mtxer(r0);
3891   __ neg(result, result, SetOE, SetRC);
3892   // Deoptimize on overflow.
3893   DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
3894   __ bind(&done);
3895 }
3896
3897
3898 #if V8_TARGET_ARCH_PPC64
3899 void LCodeGen::EmitInteger32MathAbs(LMathAbs* instr) {
3900   Register input = ToRegister(instr->value());
3901   Register result = ToRegister(instr->result());
3902   Label done;
3903   __ cmpwi(input, Operand::Zero());
3904   __ Move(result, input);
3905   __ bge(&done);
3906
3907   // Deoptimize on overflow.
3908   __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
3909   __ cmpw(input, r0);
3910   DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
3911
3912   __ neg(result, result);
3913   __ bind(&done);
3914 }
3915 #endif
3916
3917
3918 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3919   // Class for deferred case.
3920   class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode {
3921    public:
3922     DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3923         : LDeferredCode(codegen), instr_(instr) {}
3924     void Generate() override {
3925       codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3926     }
3927     LInstruction* instr() override { return instr_; }
3928
3929    private:
3930     LMathAbs* instr_;
3931   };
3932
3933   Representation r = instr->hydrogen()->value()->representation();
3934   if (r.IsDouble()) {
3935     DoubleRegister input = ToDoubleRegister(instr->value());
3936     DoubleRegister result = ToDoubleRegister(instr->result());
3937     __ fabs(result, input);
3938 #if V8_TARGET_ARCH_PPC64
3939   } else if (r.IsInteger32()) {
3940     EmitInteger32MathAbs(instr);
3941   } else if (r.IsSmi()) {
3942 #else
3943   } else if (r.IsSmiOrInteger32()) {
3944 #endif
3945     EmitMathAbs(instr);
3946   } else {
3947     // Representation is tagged.
3948     DeferredMathAbsTaggedHeapNumber* deferred =
3949         new (zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
3950     Register input = ToRegister(instr->value());
3951     // Smi check.
3952     __ JumpIfNotSmi(input, deferred->entry());
3953     // If smi, handle it directly.
3954     EmitMathAbs(instr);
3955     __ bind(deferred->exit());
3956   }
3957 }
3958
3959
3960 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3961   DoubleRegister input = ToDoubleRegister(instr->value());
3962   Register result = ToRegister(instr->result());
3963   Register input_high = scratch0();
3964   Register scratch = ip;
3965   Label done, exact;
3966
3967   __ TryInt32Floor(result, input, input_high, scratch, double_scratch0(), &done,
3968                    &exact);
3969   DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN);
3970
3971   __ bind(&exact);
3972   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3973     // Test for -0.
3974     __ cmpi(result, Operand::Zero());
3975     __ bne(&done);
3976     __ cmpwi(input_high, Operand::Zero());
3977     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
3978   }
3979   __ bind(&done);
3980 }
3981
3982
3983 void LCodeGen::DoMathRound(LMathRound* instr) {
3984   DoubleRegister input = ToDoubleRegister(instr->value());
3985   Register result = ToRegister(instr->result());
3986   DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
3987   DoubleRegister input_plus_dot_five = double_scratch1;
3988   Register scratch1 = scratch0();
3989   Register scratch2 = ip;
3990   DoubleRegister dot_five = double_scratch0();
3991   Label convert, done;
3992
3993   __ LoadDoubleLiteral(dot_five, 0.5, r0);
3994   __ fabs(double_scratch1, input);
3995   __ fcmpu(double_scratch1, dot_five);
3996   DeoptimizeIf(unordered, instr, Deoptimizer::kLostPrecisionOrNaN);
3997   // If input is in [-0.5, -0], the result is -0.
3998   // If input is in [+0, +0.5[, the result is +0.
3999   // If the input is +0.5, the result is 1.
4000   __ bgt(&convert);  // Out of [-0.5, +0.5].
4001   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
4002 #if V8_TARGET_ARCH_PPC64
4003     __ MovDoubleToInt64(scratch1, input);
4004 #else
4005     __ MovDoubleHighToInt(scratch1, input);
4006 #endif
4007     __ cmpi(scratch1, Operand::Zero());
4008     // [-0.5, -0].
4009     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
4010   }
4011   __ fcmpu(input, dot_five);
4012   if (CpuFeatures::IsSupported(ISELECT)) {
4013     __ li(result, Operand(1));
4014     __ isel(lt, result, r0, result);
4015     __ b(&done);
4016   } else {
4017     Label return_zero;
4018     __ bne(&return_zero);
4019     __ li(result, Operand(1));  // +0.5.
4020     __ b(&done);
4021     // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on
4022     // flag kBailoutOnMinusZero.
4023     __ bind(&return_zero);
4024     __ li(result, Operand::Zero());
4025     __ b(&done);
4026   }
4027
4028   __ bind(&convert);
4029   __ fadd(input_plus_dot_five, input, dot_five);
4030   // Reuse dot_five (double_scratch0) as we no longer need this value.
4031   __ TryInt32Floor(result, input_plus_dot_five, scratch1, scratch2,
4032                    double_scratch0(), &done, &done);
4033   DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN);
4034   __ bind(&done);
4035 }
4036
4037
4038 void LCodeGen::DoMathFround(LMathFround* instr) {
4039   DoubleRegister input_reg = ToDoubleRegister(instr->value());
4040   DoubleRegister output_reg = ToDoubleRegister(instr->result());
4041   __ frsp(output_reg, input_reg);
4042 }
4043
4044
4045 void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
4046   DoubleRegister input = ToDoubleRegister(instr->value());
4047   DoubleRegister result = ToDoubleRegister(instr->result());
4048   __ fsqrt(result, input);
4049 }
4050
4051
4052 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
4053   DoubleRegister input = ToDoubleRegister(instr->value());
4054   DoubleRegister result = ToDoubleRegister(instr->result());
4055   DoubleRegister temp = double_scratch0();
4056
4057   // Note that according to ECMA-262 15.8.2.13:
4058   // Math.pow(-Infinity, 0.5) == Infinity
4059   // Math.sqrt(-Infinity) == NaN
4060   Label skip, done;
4061
4062   __ LoadDoubleLiteral(temp, -V8_INFINITY, scratch0());
4063   __ fcmpu(input, temp);
4064   __ bne(&skip);
4065   __ fneg(result, temp);
4066   __ b(&done);
4067
4068   // Add +0 to convert -0 to +0.
4069   __ bind(&skip);
4070   __ fadd(result, input, kDoubleRegZero);
4071   __ fsqrt(result, result);
4072   __ bind(&done);
4073 }
4074
4075
4076 void LCodeGen::DoPower(LPower* instr) {
4077   Representation exponent_type = instr->hydrogen()->right()->representation();
4078 // Having marked this as a call, we can use any registers.
4079 // Just make sure that the input/output registers are the expected ones.
4080   Register tagged_exponent = MathPowTaggedDescriptor::exponent();
4081   DCHECK(!instr->right()->IsDoubleRegister() ||
4082          ToDoubleRegister(instr->right()).is(d2));
4083   DCHECK(!instr->right()->IsRegister() ||
4084          ToRegister(instr->right()).is(tagged_exponent));
4085   DCHECK(ToDoubleRegister(instr->left()).is(d1));
4086   DCHECK(ToDoubleRegister(instr->result()).is(d3));
4087
4088   if (exponent_type.IsSmi()) {
4089     MathPowStub stub(isolate(), MathPowStub::TAGGED);
4090     __ CallStub(&stub);
4091   } else if (exponent_type.IsTagged()) {
4092     Label no_deopt;
4093     __ JumpIfSmi(tagged_exponent, &no_deopt);
4094     DCHECK(!r10.is(tagged_exponent));
4095     __ LoadP(r10, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
4096     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
4097     __ cmp(r10, ip);
4098     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
4099     __ bind(&no_deopt);
4100     MathPowStub stub(isolate(), MathPowStub::TAGGED);
4101     __ CallStub(&stub);
4102   } else if (exponent_type.IsInteger32()) {
4103     MathPowStub stub(isolate(), MathPowStub::INTEGER);
4104     __ CallStub(&stub);
4105   } else {
4106     DCHECK(exponent_type.IsDouble());
4107     MathPowStub stub(isolate(), MathPowStub::DOUBLE);
4108     __ CallStub(&stub);
4109   }
4110 }
4111
4112
4113 void LCodeGen::DoMathExp(LMathExp* instr) {
4114   DoubleRegister input = ToDoubleRegister(instr->value());
4115   DoubleRegister result = ToDoubleRegister(instr->result());
4116   DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
4117   DoubleRegister double_scratch2 = double_scratch0();
4118   Register temp1 = ToRegister(instr->temp1());
4119   Register temp2 = ToRegister(instr->temp2());
4120
4121   MathExpGenerator::EmitMathExp(masm(), input, result, double_scratch1,
4122                                 double_scratch2, temp1, temp2, scratch0());
4123 }
4124
4125
4126 void LCodeGen::DoMathLog(LMathLog* instr) {
4127   __ PrepareCallCFunction(0, 1, scratch0());
4128   __ MovToFloatParameter(ToDoubleRegister(instr->value()));
4129   __ CallCFunction(ExternalReference::math_log_double_function(isolate()), 0,
4130                    1);
4131   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
4132 }
4133
4134
4135 void LCodeGen::DoMathClz32(LMathClz32* instr) {
4136   Register input = ToRegister(instr->value());
4137   Register result = ToRegister(instr->result());
4138   __ cntlzw_(result, input);
4139 }
4140
4141
4142 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
4143   DCHECK(ToRegister(instr->context()).is(cp));
4144   DCHECK(ToRegister(instr->function()).is(r4));
4145   DCHECK(instr->HasPointerMap());
4146
4147   Handle<JSFunction> known_function = instr->hydrogen()->known_function();
4148   if (known_function.is_null()) {
4149     LPointerMap* pointers = instr->pointer_map();
4150     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
4151     ParameterCount count(instr->arity());
4152     __ InvokeFunction(r4, count, CALL_FUNCTION, generator);
4153   } else {
4154     CallKnownFunction(known_function,
4155                       instr->hydrogen()->formal_parameter_count(),
4156                       instr->arity(), instr);
4157   }
4158 }
4159
4160
4161 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
4162   DCHECK(ToRegister(instr->result()).is(r3));
4163
4164   if (instr->hydrogen()->IsTailCall()) {
4165     if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL);
4166
4167     if (instr->target()->IsConstantOperand()) {
4168       LConstantOperand* target = LConstantOperand::cast(instr->target());
4169       Handle<Code> code = Handle<Code>::cast(ToHandle(target));
4170       __ Jump(code, RelocInfo::CODE_TARGET);
4171     } else {
4172       DCHECK(instr->target()->IsRegister());
4173       Register target = ToRegister(instr->target());
4174       __ addi(ip, target, Operand(Code::kHeaderSize - kHeapObjectTag));
4175       __ JumpToJSEntry(ip);
4176     }
4177   } else {
4178     LPointerMap* pointers = instr->pointer_map();
4179     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
4180
4181     if (instr->target()->IsConstantOperand()) {
4182       LConstantOperand* target = LConstantOperand::cast(instr->target());
4183       Handle<Code> code = Handle<Code>::cast(ToHandle(target));
4184       generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
4185       __ Call(code, RelocInfo::CODE_TARGET);
4186     } else {
4187       DCHECK(instr->target()->IsRegister());
4188       Register target = ToRegister(instr->target());
4189       generator.BeforeCall(__ CallSize(target));
4190       __ addi(ip, target, Operand(Code::kHeaderSize - kHeapObjectTag));
4191       __ CallJSEntry(ip);
4192     }
4193     generator.AfterCall();
4194   }
4195 }
4196
4197
4198 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
4199   DCHECK(ToRegister(instr->function()).is(r4));
4200   DCHECK(ToRegister(instr->result()).is(r3));
4201
4202   if (instr->hydrogen()->pass_argument_count()) {
4203     __ mov(r3, Operand(instr->arity()));
4204   }
4205
4206   // Change context.
4207   __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
4208
4209   bool is_self_call = false;
4210   if (instr->hydrogen()->function()->IsConstant()) {
4211     HConstant* fun_const = HConstant::cast(instr->hydrogen()->function());
4212     Handle<JSFunction> jsfun =
4213         Handle<JSFunction>::cast(fun_const->handle(isolate()));
4214     is_self_call = jsfun.is_identical_to(info()->closure());
4215   }
4216
4217   if (is_self_call) {
4218     __ CallSelf();
4219   } else {
4220     __ LoadP(ip, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
4221     __ CallJSEntry(ip);
4222   }
4223
4224   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
4225 }
4226
4227
4228 void LCodeGen::DoCallFunction(LCallFunction* instr) {
4229   DCHECK(ToRegister(instr->context()).is(cp));
4230   DCHECK(ToRegister(instr->function()).is(r4));
4231   DCHECK(ToRegister(instr->result()).is(r3));
4232
4233   int arity = instr->arity();
4234   CallFunctionFlags flags = instr->hydrogen()->function_flags();
4235   if (instr->hydrogen()->HasVectorAndSlot()) {
4236     Register slot_register = ToRegister(instr->temp_slot());
4237     Register vector_register = ToRegister(instr->temp_vector());
4238     DCHECK(slot_register.is(r6));
4239     DCHECK(vector_register.is(r5));
4240
4241     AllowDeferredHandleDereference vector_structure_check;
4242     Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
4243     int index = vector->GetIndex(instr->hydrogen()->slot());
4244
4245     __ Move(vector_register, vector);
4246     __ LoadSmiLiteral(slot_register, Smi::FromInt(index));
4247
4248     CallICState::CallType call_type =
4249         (flags & CALL_AS_METHOD) ? CallICState::METHOD : CallICState::FUNCTION;
4250
4251     Handle<Code> ic =
4252         CodeFactory::CallICInOptimizedCode(isolate(), arity, call_type).code();
4253     CallCode(ic, RelocInfo::CODE_TARGET, instr);
4254   } else {
4255     CallFunctionStub stub(isolate(), arity, flags);
4256     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4257   }
4258 }
4259
4260
4261 void LCodeGen::DoCallNew(LCallNew* instr) {
4262   DCHECK(ToRegister(instr->context()).is(cp));
4263   DCHECK(ToRegister(instr->constructor()).is(r4));
4264   DCHECK(ToRegister(instr->result()).is(r3));
4265
4266   __ mov(r3, Operand(instr->arity()));
4267   // No cell in r5 for construct type feedback in optimized code
4268   __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
4269   CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
4270   CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4271 }
4272
4273
4274 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4275   DCHECK(ToRegister(instr->context()).is(cp));
4276   DCHECK(ToRegister(instr->constructor()).is(r4));
4277   DCHECK(ToRegister(instr->result()).is(r3));
4278
4279   __ mov(r3, Operand(instr->arity()));
4280   if (instr->arity() == 1) {
4281     // We only need the allocation site for the case we have a length argument.
4282     // The case may bail out to the runtime, which will determine the correct
4283     // elements kind with the site.
4284     __ Move(r5, instr->hydrogen()->site());
4285   } else {
4286     __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
4287   }
4288   ElementsKind kind = instr->hydrogen()->elements_kind();
4289   AllocationSiteOverrideMode override_mode =
4290       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
4291           ? DISABLE_ALLOCATION_SITES
4292           : DONT_OVERRIDE;
4293
4294   if (instr->arity() == 0) {
4295     ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
4296     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4297   } else if (instr->arity() == 1) {
4298     Label done;
4299     if (IsFastPackedElementsKind(kind)) {
4300       Label packed_case;
4301       // We might need a change here
4302       // look at the first argument
4303       __ LoadP(r8, MemOperand(sp, 0));
4304       __ cmpi(r8, Operand::Zero());
4305       __ beq(&packed_case);
4306
4307       ElementsKind holey_kind = GetHoleyElementsKind(kind);
4308       ArraySingleArgumentConstructorStub stub(isolate(), holey_kind,
4309                                               override_mode);
4310       CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4311       __ b(&done);
4312       __ bind(&packed_case);
4313     }
4314
4315     ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
4316     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4317     __ bind(&done);
4318   } else {
4319     ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
4320     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4321   }
4322 }
4323
4324
4325 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
4326   CallRuntime(instr->function(), instr->arity(), instr);
4327 }
4328
4329
4330 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
4331   Register function = ToRegister(instr->function());
4332   Register code_object = ToRegister(instr->code_object());
4333   __ addi(code_object, code_object,
4334           Operand(Code::kHeaderSize - kHeapObjectTag));
4335   __ StoreP(code_object,
4336             FieldMemOperand(function, JSFunction::kCodeEntryOffset), r0);
4337 }
4338
4339
4340 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
4341   Register result = ToRegister(instr->result());
4342   Register base = ToRegister(instr->base_object());
4343   if (instr->offset()->IsConstantOperand()) {
4344     LConstantOperand* offset = LConstantOperand::cast(instr->offset());
4345     __ Add(result, base, ToInteger32(offset), r0);
4346   } else {
4347     Register offset = ToRegister(instr->offset());
4348     __ add(result, base, offset);
4349   }
4350 }
4351
4352
4353 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
4354   HStoreNamedField* hinstr = instr->hydrogen();
4355   Representation representation = instr->representation();
4356
4357   Register object = ToRegister(instr->object());
4358   Register scratch = scratch0();
4359   HObjectAccess access = hinstr->access();
4360   int offset = access.offset();
4361
4362   if (access.IsExternalMemory()) {
4363     Register value = ToRegister(instr->value());
4364     MemOperand operand = MemOperand(object, offset);
4365     __ StoreRepresentation(value, operand, representation, r0);
4366     return;
4367   }
4368
4369   __ AssertNotSmi(object);
4370
4371 #if V8_TARGET_ARCH_PPC64
4372   DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() ||
4373          IsInteger32(LConstantOperand::cast(instr->value())));
4374 #else
4375   DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() ||
4376          IsSmi(LConstantOperand::cast(instr->value())));
4377 #endif
4378   if (!FLAG_unbox_double_fields && representation.IsDouble()) {
4379     DCHECK(access.IsInobject());
4380     DCHECK(!hinstr->has_transition());
4381     DCHECK(!hinstr->NeedsWriteBarrier());
4382     DoubleRegister value = ToDoubleRegister(instr->value());
4383     __ stfd(value, FieldMemOperand(object, offset));
4384     return;
4385   }
4386
4387   if (hinstr->has_transition()) {
4388     Handle<Map> transition = hinstr->transition_map();
4389     AddDeprecationDependency(transition);
4390     __ mov(scratch, Operand(transition));
4391     __ StoreP(scratch, FieldMemOperand(object, HeapObject::kMapOffset), r0);
4392     if (hinstr->NeedsWriteBarrierForMap()) {
4393       Register temp = ToRegister(instr->temp());
4394       // Update the write barrier for the map field.
4395       __ RecordWriteForMap(object, scratch, temp, GetLinkRegisterState(),
4396                            kSaveFPRegs);
4397     }
4398   }
4399
4400   // Do the store.
4401   Register record_dest = object;
4402   Register record_value = no_reg;
4403   Register record_scratch = scratch;
4404 #if V8_TARGET_ARCH_PPC64
4405   if (FLAG_unbox_double_fields && representation.IsDouble()) {
4406     DCHECK(access.IsInobject());
4407     DoubleRegister value = ToDoubleRegister(instr->value());
4408     __ stfd(value, FieldMemOperand(object, offset));
4409     if (hinstr->NeedsWriteBarrier()) {
4410       record_value = ToRegister(instr->value());
4411     }
4412   } else {
4413     if (representation.IsSmi() &&
4414         hinstr->value()->representation().IsInteger32()) {
4415       DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
4416       // 64-bit Smi optimization
4417       // Store int value directly to upper half of the smi.
4418       offset = SmiWordOffset(offset);
4419       representation = Representation::Integer32();
4420     }
4421 #endif
4422     if (access.IsInobject()) {
4423       Register value = ToRegister(instr->value());
4424       MemOperand operand = FieldMemOperand(object, offset);
4425       __ StoreRepresentation(value, operand, representation, r0);
4426       record_value = value;
4427     } else {
4428       Register value = ToRegister(instr->value());
4429       __ LoadP(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
4430       MemOperand operand = FieldMemOperand(scratch, offset);
4431       __ StoreRepresentation(value, operand, representation, r0);
4432       record_dest = scratch;
4433       record_value = value;
4434       record_scratch = object;
4435     }
4436 #if V8_TARGET_ARCH_PPC64
4437   }
4438 #endif
4439
4440   if (hinstr->NeedsWriteBarrier()) {
4441     __ RecordWriteField(record_dest, offset, record_value, record_scratch,
4442                         GetLinkRegisterState(), kSaveFPRegs,
4443                         EMIT_REMEMBERED_SET, hinstr->SmiCheckForWriteBarrier(),
4444                         hinstr->PointersToHereCheckForValue());
4445   }
4446 }
4447
4448
4449 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4450   DCHECK(ToRegister(instr->context()).is(cp));
4451   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4452   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4453
4454   if (instr->hydrogen()->HasVectorAndSlot()) {
4455     EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
4456   }
4457
4458   __ mov(StoreDescriptor::NameRegister(), Operand(instr->name()));
4459   Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
4460                         isolate(), instr->language_mode(),
4461                         instr->hydrogen()->initialization_state()).code();
4462   CallCode(ic, RelocInfo::CODE_TARGET, instr);
4463 }
4464
4465
4466 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
4467   Representation representation = instr->hydrogen()->length()->representation();
4468   DCHECK(representation.Equals(instr->hydrogen()->index()->representation()));
4469   DCHECK(representation.IsSmiOrInteger32());
4470
4471   Condition cc = instr->hydrogen()->allow_equality() ? lt : le;
4472   if (instr->length()->IsConstantOperand()) {
4473     int32_t length = ToInteger32(LConstantOperand::cast(instr->length()));
4474     Register index = ToRegister(instr->index());
4475     if (representation.IsSmi()) {
4476       __ Cmpli(index, Operand(Smi::FromInt(length)), r0);
4477     } else {
4478       __ Cmplwi(index, Operand(length), r0);
4479     }
4480     cc = CommuteCondition(cc);
4481   } else if (instr->index()->IsConstantOperand()) {
4482     int32_t index = ToInteger32(LConstantOperand::cast(instr->index()));
4483     Register length = ToRegister(instr->length());
4484     if (representation.IsSmi()) {
4485       __ Cmpli(length, Operand(Smi::FromInt(index)), r0);
4486     } else {
4487       __ Cmplwi(length, Operand(index), r0);
4488     }
4489   } else {
4490     Register index = ToRegister(instr->index());
4491     Register length = ToRegister(instr->length());
4492     if (representation.IsSmi()) {
4493       __ cmpl(length, index);
4494     } else {
4495       __ cmplw(length, index);
4496     }
4497   }
4498   if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4499     Label done;
4500     __ b(NegateCondition(cc), &done);
4501     __ stop("eliminated bounds check failed");
4502     __ bind(&done);
4503   } else {
4504     DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds);
4505   }
4506 }
4507
4508
4509 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4510   Register external_pointer = ToRegister(instr->elements());
4511   Register key = no_reg;
4512   ElementsKind elements_kind = instr->elements_kind();
4513   bool key_is_constant = instr->key()->IsConstantOperand();
4514   int constant_key = 0;
4515   if (key_is_constant) {
4516     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
4517     if (constant_key & 0xF0000000) {
4518       Abort(kArrayIndexConstantValueTooBig);
4519     }
4520   } else {
4521     key = ToRegister(instr->key());
4522   }
4523   int element_size_shift = ElementsKindToShiftSize(elements_kind);
4524   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
4525   int base_offset = instr->base_offset();
4526
4527   if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
4528       elements_kind == FLOAT32_ELEMENTS ||
4529       elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
4530       elements_kind == FLOAT64_ELEMENTS) {
4531     Register address = scratch0();
4532     DoubleRegister value(ToDoubleRegister(instr->value()));
4533     if (key_is_constant) {
4534       if (constant_key != 0) {
4535         __ Add(address, external_pointer, constant_key << element_size_shift,
4536                r0);
4537       } else {
4538         address = external_pointer;
4539       }
4540     } else {
4541       __ IndexToArrayOffset(r0, key, element_size_shift, key_is_smi);
4542       __ add(address, external_pointer, r0);
4543     }
4544     if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
4545         elements_kind == FLOAT32_ELEMENTS) {
4546       __ frsp(double_scratch0(), value);
4547       __ stfs(double_scratch0(), MemOperand(address, base_offset));
4548     } else {  // Storing doubles, not floats.
4549       __ stfd(value, MemOperand(address, base_offset));
4550     }
4551   } else {
4552     Register value(ToRegister(instr->value()));
4553     MemOperand mem_operand =
4554         PrepareKeyedOperand(key, external_pointer, key_is_constant, key_is_smi,
4555                             constant_key, element_size_shift, base_offset);
4556     switch (elements_kind) {
4557       case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
4558       case EXTERNAL_INT8_ELEMENTS:
4559       case EXTERNAL_UINT8_ELEMENTS:
4560       case UINT8_ELEMENTS:
4561       case UINT8_CLAMPED_ELEMENTS:
4562       case INT8_ELEMENTS:
4563         if (key_is_constant) {
4564           __ StoreByte(value, mem_operand, r0);
4565         } else {
4566           __ stbx(value, mem_operand);
4567         }
4568         break;
4569       case EXTERNAL_INT16_ELEMENTS:
4570       case EXTERNAL_UINT16_ELEMENTS:
4571       case INT16_ELEMENTS:
4572       case UINT16_ELEMENTS:
4573         if (key_is_constant) {
4574           __ StoreHalfWord(value, mem_operand, r0);
4575         } else {
4576           __ sthx(value, mem_operand);
4577         }
4578         break;
4579       case EXTERNAL_INT32_ELEMENTS:
4580       case EXTERNAL_UINT32_ELEMENTS:
4581       case INT32_ELEMENTS:
4582       case UINT32_ELEMENTS:
4583         if (key_is_constant) {
4584           __ StoreWord(value, mem_operand, r0);
4585         } else {
4586           __ stwx(value, mem_operand);
4587         }
4588         break;
4589       case FLOAT32_ELEMENTS:
4590       case FLOAT64_ELEMENTS:
4591       case EXTERNAL_FLOAT32_ELEMENTS:
4592       case EXTERNAL_FLOAT64_ELEMENTS:
4593       case FAST_DOUBLE_ELEMENTS:
4594       case FAST_ELEMENTS:
4595       case FAST_SMI_ELEMENTS:
4596       case FAST_HOLEY_DOUBLE_ELEMENTS:
4597       case FAST_HOLEY_ELEMENTS:
4598       case FAST_HOLEY_SMI_ELEMENTS:
4599       case DICTIONARY_ELEMENTS:
4600       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
4601       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
4602         UNREACHABLE();
4603         break;
4604     }
4605   }
4606 }
4607
4608
4609 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4610   DoubleRegister value = ToDoubleRegister(instr->value());
4611   Register elements = ToRegister(instr->elements());
4612   Register key = no_reg;
4613   Register scratch = scratch0();
4614   DoubleRegister double_scratch = double_scratch0();
4615   bool key_is_constant = instr->key()->IsConstantOperand();
4616   int constant_key = 0;
4617
4618   // Calculate the effective address of the slot in the array to store the
4619   // double value.
4620   if (key_is_constant) {
4621     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
4622     if (constant_key & 0xF0000000) {
4623       Abort(kArrayIndexConstantValueTooBig);
4624     }
4625   } else {
4626     key = ToRegister(instr->key());
4627   }
4628   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
4629   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
4630   int base_offset = instr->base_offset() + constant_key * kDoubleSize;
4631   if (!key_is_constant) {
4632     __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi);
4633     __ add(scratch, elements, scratch);
4634     elements = scratch;
4635   }
4636   if (!is_int16(base_offset)) {
4637     __ Add(scratch, elements, base_offset, r0);
4638     base_offset = 0;
4639     elements = scratch;
4640   }
4641
4642   if (instr->NeedsCanonicalization()) {
4643     // Turn potential sNaN value into qNaN.
4644     __ CanonicalizeNaN(double_scratch, value);
4645     __ stfd(double_scratch, MemOperand(elements, base_offset));
4646   } else {
4647     __ stfd(value, MemOperand(elements, base_offset));
4648   }
4649 }
4650
4651
4652 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4653   HStoreKeyed* hinstr = instr->hydrogen();
4654   Register value = ToRegister(instr->value());
4655   Register elements = ToRegister(instr->elements());
4656   Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
4657   Register scratch = scratch0();
4658   Register store_base = scratch;
4659   int offset = instr->base_offset();
4660
4661   // Do the store.
4662   if (instr->key()->IsConstantOperand()) {
4663     DCHECK(!hinstr->NeedsWriteBarrier());
4664     LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
4665     offset += ToInteger32(const_operand) * kPointerSize;
4666     store_base = elements;
4667   } else {
4668     // Even though the HLoadKeyed instruction forces the input
4669     // representation for the key to be an integer, the input gets replaced
4670     // during bound check elimination with the index argument to the bounds
4671     // check, which can be tagged, so that case must be handled here, too.
4672     if (hinstr->key()->representation().IsSmi()) {
4673       __ SmiToPtrArrayOffset(scratch, key);
4674     } else {
4675       __ ShiftLeftImm(scratch, key, Operand(kPointerSizeLog2));
4676     }
4677     __ add(scratch, elements, scratch);
4678   }
4679
4680   Representation representation = hinstr->value()->representation();
4681
4682 #if V8_TARGET_ARCH_PPC64
4683   // 64-bit Smi optimization
4684   if (representation.IsInteger32()) {
4685     DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
4686     DCHECK(hinstr->elements_kind() == FAST_SMI_ELEMENTS);
4687     // Store int value directly to upper half of the smi.
4688     offset = SmiWordOffset(offset);
4689   }
4690 #endif
4691
4692   __ StoreRepresentation(value, MemOperand(store_base, offset), representation,
4693                          r0);
4694
4695   if (hinstr->NeedsWriteBarrier()) {
4696     SmiCheck check_needed = hinstr->value()->type().IsHeapObject()
4697                                 ? OMIT_SMI_CHECK
4698                                 : INLINE_SMI_CHECK;
4699     // Compute address of modified element and store it into key register.
4700     __ Add(key, store_base, offset, r0);
4701     __ RecordWrite(elements, key, value, GetLinkRegisterState(), kSaveFPRegs,
4702                    EMIT_REMEMBERED_SET, check_needed,
4703                    hinstr->PointersToHereCheckForValue());
4704   }
4705 }
4706
4707
4708 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4709   // By cases: external, fast double
4710   if (instr->is_typed_elements()) {
4711     DoStoreKeyedExternalArray(instr);
4712   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
4713     DoStoreKeyedFixedDoubleArray(instr);
4714   } else {
4715     DoStoreKeyedFixedArray(instr);
4716   }
4717 }
4718
4719
4720 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4721   DCHECK(ToRegister(instr->context()).is(cp));
4722   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4723   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
4724   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4725
4726   if (instr->hydrogen()->HasVectorAndSlot()) {
4727     EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
4728   }
4729
4730   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
4731                         isolate(), instr->language_mode(),
4732                         instr->hydrogen()->initialization_state()).code();
4733   CallCode(ic, RelocInfo::CODE_TARGET, instr);
4734 }
4735
4736
4737 void LCodeGen::DoMaybeGrowElements(LMaybeGrowElements* instr) {
4738   class DeferredMaybeGrowElements final : public LDeferredCode {
4739    public:
4740     DeferredMaybeGrowElements(LCodeGen* codegen, LMaybeGrowElements* instr)
4741         : LDeferredCode(codegen), instr_(instr) {}
4742     void Generate() override { codegen()->DoDeferredMaybeGrowElements(instr_); }
4743     LInstruction* instr() override { return instr_; }
4744
4745    private:
4746     LMaybeGrowElements* instr_;
4747   };
4748
4749   Register result = r3;
4750   DeferredMaybeGrowElements* deferred =
4751       new (zone()) DeferredMaybeGrowElements(this, instr);
4752   LOperand* key = instr->key();
4753   LOperand* current_capacity = instr->current_capacity();
4754
4755   DCHECK(instr->hydrogen()->key()->representation().IsInteger32());
4756   DCHECK(instr->hydrogen()->current_capacity()->representation().IsInteger32());
4757   DCHECK(key->IsConstantOperand() || key->IsRegister());
4758   DCHECK(current_capacity->IsConstantOperand() ||
4759          current_capacity->IsRegister());
4760
4761   if (key->IsConstantOperand() && current_capacity->IsConstantOperand()) {
4762     int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
4763     int32_t constant_capacity =
4764         ToInteger32(LConstantOperand::cast(current_capacity));
4765     if (constant_key >= constant_capacity) {
4766       // Deferred case.
4767       __ b(deferred->entry());
4768     }
4769   } else if (key->IsConstantOperand()) {
4770     int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
4771     __ Cmpwi(ToRegister(current_capacity), Operand(constant_key), r0);
4772     __ ble(deferred->entry());
4773   } else if (current_capacity->IsConstantOperand()) {
4774     int32_t constant_capacity =
4775         ToInteger32(LConstantOperand::cast(current_capacity));
4776     __ Cmpwi(ToRegister(key), Operand(constant_capacity), r0);
4777     __ bge(deferred->entry());
4778   } else {
4779     __ cmpw(ToRegister(key), ToRegister(current_capacity));
4780     __ bge(deferred->entry());
4781   }
4782
4783   if (instr->elements()->IsRegister()) {
4784     __ Move(result, ToRegister(instr->elements()));
4785   } else {
4786     __ LoadP(result, ToMemOperand(instr->elements()));
4787   }
4788
4789   __ bind(deferred->exit());
4790 }
4791
4792
4793 void LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) {
4794   // TODO(3095996): Get rid of this. For now, we need to make the
4795   // result register contain a valid pointer because it is already
4796   // contained in the register pointer map.
4797   Register result = r3;
4798   __ li(result, Operand::Zero());
4799
4800   // We have to call a stub.
4801   {
4802     PushSafepointRegistersScope scope(this);
4803     if (instr->object()->IsRegister()) {
4804       __ Move(result, ToRegister(instr->object()));
4805     } else {
4806       __ LoadP(result, ToMemOperand(instr->object()));
4807     }
4808
4809     LOperand* key = instr->key();
4810     if (key->IsConstantOperand()) {
4811       __ LoadSmiLiteral(r6, ToSmi(LConstantOperand::cast(key)));
4812     } else {
4813       __ SmiTag(r6, ToRegister(key));
4814     }
4815
4816     GrowArrayElementsStub stub(isolate(), instr->hydrogen()->is_js_array(),
4817                                instr->hydrogen()->kind());
4818     __ CallStub(&stub);
4819     RecordSafepointWithLazyDeopt(
4820         instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4821     __ StoreToSafepointRegisterSlot(result, result);
4822   }
4823
4824   // Deopt on smi, which means the elements array changed to dictionary mode.
4825   __ TestIfSmi(result, r0);
4826   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
4827 }
4828
4829
4830 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4831   Register object_reg = ToRegister(instr->object());
4832   Register scratch = scratch0();
4833
4834   Handle<Map> from_map = instr->original_map();
4835   Handle<Map> to_map = instr->transitioned_map();
4836   ElementsKind from_kind = instr->from_kind();
4837   ElementsKind to_kind = instr->to_kind();
4838
4839   Label not_applicable;
4840   __ LoadP(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
4841   __ Cmpi(scratch, Operand(from_map), r0);
4842   __ bne(&not_applicable);
4843
4844   if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
4845     Register new_map_reg = ToRegister(instr->new_map_temp());
4846     __ mov(new_map_reg, Operand(to_map));
4847     __ StoreP(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset),
4848               r0);
4849     // Write barrier.
4850     __ RecordWriteForMap(object_reg, new_map_reg, scratch,
4851                          GetLinkRegisterState(), kDontSaveFPRegs);
4852   } else {
4853     DCHECK(ToRegister(instr->context()).is(cp));
4854     DCHECK(object_reg.is(r3));
4855     PushSafepointRegistersScope scope(this);
4856     __ Move(r4, to_map);
4857     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
4858     TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
4859     __ CallStub(&stub);
4860     RecordSafepointWithRegisters(instr->pointer_map(), 0,
4861                                  Safepoint::kLazyDeopt);
4862   }
4863   __ bind(&not_applicable);
4864 }
4865
4866
4867 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4868   Register object = ToRegister(instr->object());
4869   Register temp = ToRegister(instr->temp());
4870   Label no_memento_found;
4871   __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4872   DeoptimizeIf(eq, instr, Deoptimizer::kMementoFound);
4873   __ bind(&no_memento_found);
4874 }
4875
4876
4877 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4878   DCHECK(ToRegister(instr->context()).is(cp));
4879   DCHECK(ToRegister(instr->left()).is(r4));
4880   DCHECK(ToRegister(instr->right()).is(r3));
4881   StringAddStub stub(isolate(), instr->hydrogen()->flags(),
4882                      instr->hydrogen()->pretenure_flag());
4883   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4884 }
4885
4886
4887 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4888   class DeferredStringCharCodeAt final : public LDeferredCode {
4889    public:
4890     DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
4891         : LDeferredCode(codegen), instr_(instr) {}
4892     void Generate() override { codegen()->DoDeferredStringCharCodeAt(instr_); }
4893     LInstruction* instr() override { return instr_; }
4894
4895    private:
4896     LStringCharCodeAt* instr_;
4897   };
4898
4899   DeferredStringCharCodeAt* deferred =
4900       new (zone()) DeferredStringCharCodeAt(this, instr);
4901
4902   StringCharLoadGenerator::Generate(
4903       masm(), ToRegister(instr->string()), ToRegister(instr->index()),
4904       ToRegister(instr->result()), deferred->entry());
4905   __ bind(deferred->exit());
4906 }
4907
4908
4909 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
4910   Register string = ToRegister(instr->string());
4911   Register result = ToRegister(instr->result());
4912   Register scratch = scratch0();
4913
4914   // TODO(3095996): Get rid of this. For now, we need to make the
4915   // result register contain a valid pointer because it is already
4916   // contained in the register pointer map.
4917   __ li(result, Operand::Zero());
4918
4919   PushSafepointRegistersScope scope(this);
4920   __ push(string);
4921   // Push the index as a smi. This is safe because of the checks in
4922   // DoStringCharCodeAt above.
4923   if (instr->index()->IsConstantOperand()) {
4924     int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
4925     __ LoadSmiLiteral(scratch, Smi::FromInt(const_index));
4926     __ push(scratch);
4927   } else {
4928     Register index = ToRegister(instr->index());
4929     __ SmiTag(index);
4930     __ push(index);
4931   }
4932   CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2, instr,
4933                           instr->context());
4934   __ AssertSmi(r3);
4935   __ SmiUntag(r3);
4936   __ StoreToSafepointRegisterSlot(r3, result);
4937 }
4938
4939
4940 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4941   class DeferredStringCharFromCode final : public LDeferredCode {
4942    public:
4943     DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
4944         : LDeferredCode(codegen), instr_(instr) {}
4945     void Generate() override {
4946       codegen()->DoDeferredStringCharFromCode(instr_);
4947     }
4948     LInstruction* instr() override { return instr_; }
4949
4950    private:
4951     LStringCharFromCode* instr_;
4952   };
4953
4954   DeferredStringCharFromCode* deferred =
4955       new (zone()) DeferredStringCharFromCode(this, instr);
4956
4957   DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
4958   Register char_code = ToRegister(instr->char_code());
4959   Register result = ToRegister(instr->result());
4960   DCHECK(!char_code.is(result));
4961
4962   __ cmpli(char_code, Operand(String::kMaxOneByteCharCode));
4963   __ bgt(deferred->entry());
4964   __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
4965   __ ShiftLeftImm(r0, char_code, Operand(kPointerSizeLog2));
4966   __ add(result, result, r0);
4967   __ LoadP(result, FieldMemOperand(result, FixedArray::kHeaderSize));
4968   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
4969   __ cmp(result, ip);
4970   __ beq(deferred->entry());
4971   __ bind(deferred->exit());
4972 }
4973
4974
4975 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4976   Register char_code = ToRegister(instr->char_code());
4977   Register result = ToRegister(instr->result());
4978
4979   // TODO(3095996): Get rid of this. For now, we need to make the
4980   // result register contain a valid pointer because it is already
4981   // contained in the register pointer map.
4982   __ li(result, Operand::Zero());
4983
4984   PushSafepointRegistersScope scope(this);
4985   __ SmiTag(char_code);
4986   __ push(char_code);
4987   CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
4988   __ StoreToSafepointRegisterSlot(r3, result);
4989 }
4990
4991
4992 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4993   LOperand* input = instr->value();
4994   DCHECK(input->IsRegister() || input->IsStackSlot());
4995   LOperand* output = instr->result();
4996   DCHECK(output->IsDoubleRegister());
4997   if (input->IsStackSlot()) {
4998     Register scratch = scratch0();
4999     __ LoadP(scratch, ToMemOperand(input));
5000     __ ConvertIntToDouble(scratch, ToDoubleRegister(output));
5001   } else {
5002     __ ConvertIntToDouble(ToRegister(input), ToDoubleRegister(output));
5003   }
5004 }
5005
5006
5007 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
5008   LOperand* input = instr->value();
5009   LOperand* output = instr->result();
5010   __ ConvertUnsignedIntToDouble(ToRegister(input), ToDoubleRegister(output));
5011 }
5012
5013
5014 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
5015   class DeferredNumberTagI final : public LDeferredCode {
5016    public:
5017     DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
5018         : LDeferredCode(codegen), instr_(instr) {}
5019     void Generate() override {
5020       codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(),
5021                                        instr_->temp2(), SIGNED_INT32);
5022     }
5023     LInstruction* instr() override { return instr_; }
5024
5025    private:
5026     LNumberTagI* instr_;
5027   };
5028
5029   Register src = ToRegister(instr->value());
5030   Register dst = ToRegister(instr->result());
5031
5032   DeferredNumberTagI* deferred = new (zone()) DeferredNumberTagI(this, instr);
5033 #if V8_TARGET_ARCH_PPC64
5034   __ SmiTag(dst, src);
5035 #else
5036   __ SmiTagCheckOverflow(dst, src, r0);
5037   __ BranchOnOverflow(deferred->entry());
5038 #endif
5039   __ bind(deferred->exit());
5040 }
5041
5042
5043 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
5044   class DeferredNumberTagU final : public LDeferredCode {
5045    public:
5046     DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
5047         : LDeferredCode(codegen), instr_(instr) {}
5048     void Generate() override {
5049       codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(),
5050                                        instr_->temp2(), UNSIGNED_INT32);
5051     }
5052     LInstruction* instr() override { return instr_; }
5053
5054    private:
5055     LNumberTagU* instr_;
5056   };
5057
5058   Register input = ToRegister(instr->value());
5059   Register result = ToRegister(instr->result());
5060
5061   DeferredNumberTagU* deferred = new (zone()) DeferredNumberTagU(this, instr);
5062   __ Cmpli(input, Operand(Smi::kMaxValue), r0);
5063   __ bgt(deferred->entry());
5064   __ SmiTag(result, input);
5065   __ bind(deferred->exit());
5066 }
5067
5068
5069 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, LOperand* value,
5070                                      LOperand* temp1, LOperand* temp2,
5071                                      IntegerSignedness signedness) {
5072   Label done, slow;
5073   Register src = ToRegister(value);
5074   Register dst = ToRegister(instr->result());
5075   Register tmp1 = scratch0();
5076   Register tmp2 = ToRegister(temp1);
5077   Register tmp3 = ToRegister(temp2);
5078   DoubleRegister dbl_scratch = double_scratch0();
5079
5080   if (signedness == SIGNED_INT32) {
5081     // There was overflow, so bits 30 and 31 of the original integer
5082     // disagree. Try to allocate a heap number in new space and store
5083     // the value in there. If that fails, call the runtime system.
5084     if (dst.is(src)) {
5085       __ SmiUntag(src, dst);
5086       __ xoris(src, src, Operand(HeapNumber::kSignMask >> 16));
5087     }
5088     __ ConvertIntToDouble(src, dbl_scratch);
5089   } else {
5090     __ ConvertUnsignedIntToDouble(src, dbl_scratch);
5091   }
5092
5093   if (FLAG_inline_new) {
5094     __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
5095     __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow);
5096     __ b(&done);
5097   }
5098
5099   // Slow case: Call the runtime system to do the number allocation.
5100   __ bind(&slow);
5101   {
5102     // TODO(3095996): Put a valid pointer value in the stack slot where the
5103     // result register is stored, as this register is in the pointer map, but
5104     // contains an integer value.
5105     __ li(dst, Operand::Zero());
5106
5107     // Preserve the value of all registers.
5108     PushSafepointRegistersScope scope(this);
5109
5110     // NumberTagI and NumberTagD use the context from the frame, rather than
5111     // the environment's HContext or HInlinedContext value.
5112     // They only call Runtime::kAllocateHeapNumber.
5113     // The corresponding HChange instructions are added in a phase that does
5114     // not have easy access to the local context.
5115     __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
5116     __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
5117     RecordSafepointWithRegisters(instr->pointer_map(), 0,
5118                                  Safepoint::kNoLazyDeopt);
5119     __ StoreToSafepointRegisterSlot(r3, dst);
5120   }
5121
5122   // Done. Put the value in dbl_scratch into the value of the allocated heap
5123   // number.
5124   __ bind(&done);
5125   __ stfd(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
5126 }
5127
5128
5129 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
5130   class DeferredNumberTagD final : public LDeferredCode {
5131    public:
5132     DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
5133         : LDeferredCode(codegen), instr_(instr) {}
5134     void Generate() override { codegen()->DoDeferredNumberTagD(instr_); }
5135     LInstruction* instr() override { return instr_; }
5136
5137    private:
5138     LNumberTagD* instr_;
5139   };
5140
5141   DoubleRegister input_reg = ToDoubleRegister(instr->value());
5142   Register scratch = scratch0();
5143   Register reg = ToRegister(instr->result());
5144   Register temp1 = ToRegister(instr->temp());
5145   Register temp2 = ToRegister(instr->temp2());
5146
5147   DeferredNumberTagD* deferred = new (zone()) DeferredNumberTagD(this, instr);
5148   if (FLAG_inline_new) {
5149     __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
5150     __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
5151   } else {
5152     __ b(deferred->entry());
5153   }
5154   __ bind(deferred->exit());
5155   __ stfd(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset));
5156 }
5157
5158
5159 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
5160   // TODO(3095996): Get rid of this. For now, we need to make the
5161   // result register contain a valid pointer because it is already
5162   // contained in the register pointer map.
5163   Register reg = ToRegister(instr->result());
5164   __ li(reg, Operand::Zero());
5165
5166   PushSafepointRegistersScope scope(this);
5167   // NumberTagI and NumberTagD use the context from the frame, rather than
5168   // the environment's HContext or HInlinedContext value.
5169   // They only call Runtime::kAllocateHeapNumber.
5170   // The corresponding HChange instructions are added in a phase that does
5171   // not have easy access to the local context.
5172   __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
5173   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
5174   RecordSafepointWithRegisters(instr->pointer_map(), 0,
5175                                Safepoint::kNoLazyDeopt);
5176   __ StoreToSafepointRegisterSlot(r3, reg);
5177 }
5178
5179
5180 void LCodeGen::DoSmiTag(LSmiTag* instr) {
5181   HChange* hchange = instr->hydrogen();
5182   Register input = ToRegister(instr->value());
5183   Register output = ToRegister(instr->result());
5184   if (hchange->CheckFlag(HValue::kCanOverflow) &&
5185       hchange->value()->CheckFlag(HValue::kUint32)) {
5186     __ TestUnsignedSmiCandidate(input, r0);
5187     DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, cr0);
5188   }
5189 #if !V8_TARGET_ARCH_PPC64
5190   if (hchange->CheckFlag(HValue::kCanOverflow) &&
5191       !hchange->value()->CheckFlag(HValue::kUint32)) {
5192     __ SmiTagCheckOverflow(output, input, r0);
5193     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
5194   } else {
5195 #endif
5196     __ SmiTag(output, input);
5197 #if !V8_TARGET_ARCH_PPC64
5198   }
5199 #endif
5200 }
5201
5202
5203 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
5204   Register scratch = scratch0();
5205   Register input = ToRegister(instr->value());
5206   Register result = ToRegister(instr->result());
5207   if (instr->needs_check()) {
5208     // If the input is a HeapObject, value of scratch won't be zero.
5209     __ andi(scratch, input, Operand(kHeapObjectTag));
5210     __ SmiUntag(result, input);
5211     DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
5212   } else {
5213     __ SmiUntag(result, input);
5214   }
5215 }
5216
5217
5218 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
5219                                 DoubleRegister result_reg,
5220                                 NumberUntagDMode mode) {
5221   bool can_convert_undefined_to_nan =
5222       instr->hydrogen()->can_convert_undefined_to_nan();
5223   bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
5224
5225   Register scratch = scratch0();
5226   DCHECK(!result_reg.is(double_scratch0()));
5227
5228   Label convert, load_smi, done;
5229
5230   if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5231     // Smi check.
5232     __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
5233
5234     // Heap number map check.
5235     __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5236     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
5237     __ cmp(scratch, ip);
5238     if (can_convert_undefined_to_nan) {
5239       __ bne(&convert);
5240     } else {
5241       DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
5242     }
5243     // load heap number
5244     __ lfd(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5245     if (deoptimize_on_minus_zero) {
5246 #if V8_TARGET_ARCH_PPC64
5247       __ MovDoubleToInt64(scratch, result_reg);
5248       // rotate left by one for simple compare.
5249       __ rldicl(scratch, scratch, 1, 0);
5250       __ cmpi(scratch, Operand(1));
5251 #else
5252       __ MovDoubleToInt64(scratch, ip, result_reg);
5253       __ cmpi(ip, Operand::Zero());
5254       __ bne(&done);
5255       __ Cmpi(scratch, Operand(HeapNumber::kSignMask), r0);
5256 #endif
5257       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
5258     }
5259     __ b(&done);
5260     if (can_convert_undefined_to_nan) {
5261       __ bind(&convert);
5262       // Convert undefined (and hole) to NaN.
5263       __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5264       __ cmp(input_reg, ip);
5265       DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined);
5266       __ LoadRoot(scratch, Heap::kNanValueRootIndex);
5267       __ lfd(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
5268       __ b(&done);
5269     }
5270   } else {
5271     __ SmiUntag(scratch, input_reg);
5272     DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
5273   }
5274   // Smi to double register conversion
5275   __ bind(&load_smi);
5276   // scratch: untagged value of input_reg
5277   __ ConvertIntToDouble(scratch, result_reg);
5278   __ bind(&done);
5279 }
5280
5281
5282 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
5283   Register input_reg = ToRegister(instr->value());
5284   Register scratch1 = scratch0();
5285   Register scratch2 = ToRegister(instr->temp());
5286   DoubleRegister double_scratch = double_scratch0();
5287   DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2());
5288
5289   DCHECK(!scratch1.is(input_reg) && !scratch1.is(scratch2));
5290   DCHECK(!scratch2.is(input_reg) && !scratch2.is(scratch1));
5291
5292   Label done;
5293
5294   // Heap number map check.
5295   __ LoadP(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5296   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
5297   __ cmp(scratch1, ip);
5298
5299   if (instr->truncating()) {
5300     // Performs a truncating conversion of a floating point number as used by
5301     // the JS bitwise operations.
5302     Label no_heap_number, check_bools, check_false;
5303     __ bne(&no_heap_number);
5304     __ mr(scratch2, input_reg);
5305     __ TruncateHeapNumberToI(input_reg, scratch2);
5306     __ b(&done);
5307
5308     // Check for Oddballs. Undefined/False is converted to zero and True to one
5309     // for truncating conversions.
5310     __ bind(&no_heap_number);
5311     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5312     __ cmp(input_reg, ip);
5313     __ bne(&check_bools);
5314     __ li(input_reg, Operand::Zero());
5315     __ b(&done);
5316
5317     __ bind(&check_bools);
5318     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
5319     __ cmp(input_reg, ip);
5320     __ bne(&check_false);
5321     __ li(input_reg, Operand(1));
5322     __ b(&done);
5323
5324     __ bind(&check_false);
5325     __ LoadRoot(ip, Heap::kFalseValueRootIndex);
5326     __ cmp(input_reg, ip);
5327     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean);
5328     __ li(input_reg, Operand::Zero());
5329   } else {
5330     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
5331
5332     __ lfd(double_scratch2,
5333            FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5334     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5335       // preserve heap number pointer in scratch2 for minus zero check below
5336       __ mr(scratch2, input_reg);
5337     }
5338     __ TryDoubleToInt32Exact(input_reg, double_scratch2, scratch1,
5339                              double_scratch);
5340     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
5341
5342     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5343       __ cmpi(input_reg, Operand::Zero());
5344       __ bne(&done);
5345       __ lwz(scratch1,
5346              FieldMemOperand(scratch2, HeapNumber::kValueOffset +
5347                                            Register::kExponentOffset));
5348       __ cmpwi(scratch1, Operand::Zero());
5349       DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
5350     }
5351   }
5352   __ bind(&done);
5353 }
5354
5355
5356 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5357   class DeferredTaggedToI final : public LDeferredCode {
5358    public:
5359     DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
5360         : LDeferredCode(codegen), instr_(instr) {}
5361     void Generate() override { codegen()->DoDeferredTaggedToI(instr_); }
5362     LInstruction* instr() override { return instr_; }
5363
5364    private:
5365     LTaggedToI* instr_;
5366   };
5367
5368   LOperand* input = instr->value();
5369   DCHECK(input->IsRegister());
5370   DCHECK(input->Equals(instr->result()));
5371
5372   Register input_reg = ToRegister(input);
5373
5374   if (instr->hydrogen()->value()->representation().IsSmi()) {
5375     __ SmiUntag(input_reg);
5376   } else {
5377     DeferredTaggedToI* deferred = new (zone()) DeferredTaggedToI(this, instr);
5378
5379     // Branch to deferred code if the input is a HeapObject.
5380     __ JumpIfNotSmi(input_reg, deferred->entry());
5381
5382     __ SmiUntag(input_reg);
5383     __ bind(deferred->exit());
5384   }
5385 }
5386
5387
5388 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
5389   LOperand* input = instr->value();
5390   DCHECK(input->IsRegister());
5391   LOperand* result = instr->result();
5392   DCHECK(result->IsDoubleRegister());
5393
5394   Register input_reg = ToRegister(input);
5395   DoubleRegister result_reg = ToDoubleRegister(result);
5396
5397   HValue* value = instr->hydrogen()->value();
5398   NumberUntagDMode mode = value->representation().IsSmi()
5399                               ? NUMBER_CANDIDATE_IS_SMI
5400                               : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5401
5402   EmitNumberUntagD(instr, input_reg, result_reg, mode);
5403 }
5404
5405
5406 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5407   Register result_reg = ToRegister(instr->result());
5408   Register scratch1 = scratch0();
5409   DoubleRegister double_input = ToDoubleRegister(instr->value());
5410   DoubleRegister double_scratch = double_scratch0();
5411
5412   if (instr->truncating()) {
5413     __ TruncateDoubleToI(result_reg, double_input);
5414   } else {
5415     __ TryDoubleToInt32Exact(result_reg, double_input, scratch1,
5416                              double_scratch);
5417     // Deoptimize if the input wasn't a int32 (inside a double).
5418     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
5419     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5420       Label done;
5421       __ cmpi(result_reg, Operand::Zero());
5422       __ bne(&done);
5423 #if V8_TARGET_ARCH_PPC64
5424       __ MovDoubleToInt64(scratch1, double_input);
5425 #else
5426       __ MovDoubleHighToInt(scratch1, double_input);
5427 #endif
5428       __ cmpi(scratch1, Operand::Zero());
5429       DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
5430       __ bind(&done);
5431     }
5432   }
5433 }
5434
5435
5436 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5437   Register result_reg = ToRegister(instr->result());
5438   Register scratch1 = scratch0();
5439   DoubleRegister double_input = ToDoubleRegister(instr->value());
5440   DoubleRegister double_scratch = double_scratch0();
5441
5442   if (instr->truncating()) {
5443     __ TruncateDoubleToI(result_reg, double_input);
5444   } else {
5445     __ TryDoubleToInt32Exact(result_reg, double_input, scratch1,
5446                              double_scratch);
5447     // Deoptimize if the input wasn't a int32 (inside a double).
5448     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
5449     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5450       Label done;
5451       __ cmpi(result_reg, Operand::Zero());
5452       __ bne(&done);
5453 #if V8_TARGET_ARCH_PPC64
5454       __ MovDoubleToInt64(scratch1, double_input);
5455 #else
5456       __ MovDoubleHighToInt(scratch1, double_input);
5457 #endif
5458       __ cmpi(scratch1, Operand::Zero());
5459       DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
5460       __ bind(&done);
5461     }
5462   }
5463 #if V8_TARGET_ARCH_PPC64
5464   __ SmiTag(result_reg);
5465 #else
5466   __ SmiTagCheckOverflow(result_reg, r0);
5467   DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
5468 #endif
5469 }
5470
5471
5472 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5473   LOperand* input = instr->value();
5474   __ TestIfSmi(ToRegister(input), r0);
5475   DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
5476 }
5477
5478
5479 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5480   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5481     LOperand* input = instr->value();
5482     __ TestIfSmi(ToRegister(input), r0);
5483     DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
5484   }
5485 }
5486
5487
5488 void LCodeGen::DoCheckArrayBufferNotNeutered(
5489     LCheckArrayBufferNotNeutered* instr) {
5490   Register view = ToRegister(instr->view());
5491   Register scratch = scratch0();
5492
5493   __ LoadP(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
5494   __ lwz(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
5495   __ andi(r0, scratch, Operand(1 << JSArrayBuffer::WasNeutered::kShift));
5496   DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds, cr0);
5497 }
5498
5499
5500 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5501   Register input = ToRegister(instr->value());
5502   Register scratch = scratch0();
5503
5504   __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5505   __ lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5506
5507   if (instr->hydrogen()->is_interval_check()) {
5508     InstanceType first;
5509     InstanceType last;
5510     instr->hydrogen()->GetCheckInterval(&first, &last);
5511
5512     __ cmpli(scratch, Operand(first));
5513
5514     // If there is only one type in the interval check for equality.
5515     if (first == last) {
5516       DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
5517     } else {
5518       DeoptimizeIf(lt, instr, Deoptimizer::kWrongInstanceType);
5519       // Omit check for the last type.
5520       if (last != LAST_TYPE) {
5521         __ cmpli(scratch, Operand(last));
5522         DeoptimizeIf(gt, instr, Deoptimizer::kWrongInstanceType);
5523       }
5524     }
5525   } else {
5526     uint8_t mask;
5527     uint8_t tag;
5528     instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5529
5530     if (base::bits::IsPowerOfTwo32(mask)) {
5531       DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5532       __ andi(r0, scratch, Operand(mask));
5533       DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType,
5534                    cr0);
5535     } else {
5536       __ andi(scratch, scratch, Operand(mask));
5537       __ cmpi(scratch, Operand(tag));
5538       DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
5539     }
5540   }
5541 }
5542
5543
5544 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5545   Register reg = ToRegister(instr->value());
5546   Handle<HeapObject> object = instr->hydrogen()->object().handle();
5547   AllowDeferredHandleDereference smi_check;
5548   if (isolate()->heap()->InNewSpace(*object)) {
5549     Register reg = ToRegister(instr->value());
5550     Handle<Cell> cell = isolate()->factory()->NewCell(object);
5551     __ mov(ip, Operand(cell));
5552     __ LoadP(ip, FieldMemOperand(ip, Cell::kValueOffset));
5553     __ cmp(reg, ip);
5554   } else {
5555     __ Cmpi(reg, Operand(object), r0);
5556   }
5557   DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch);
5558 }
5559
5560
5561 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5562   Register temp = ToRegister(instr->temp());
5563   {
5564     PushSafepointRegistersScope scope(this);
5565     __ push(object);
5566     __ li(cp, Operand::Zero());
5567     __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5568     RecordSafepointWithRegisters(instr->pointer_map(), 1,
5569                                  Safepoint::kNoLazyDeopt);
5570     __ StoreToSafepointRegisterSlot(r3, temp);
5571   }
5572   __ TestIfSmi(temp, r0);
5573   DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, cr0);
5574 }
5575
5576
5577 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5578   class DeferredCheckMaps final : public LDeferredCode {
5579    public:
5580     DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5581         : LDeferredCode(codegen), instr_(instr), object_(object) {
5582       SetExit(check_maps());
5583     }
5584     void Generate() override {
5585       codegen()->DoDeferredInstanceMigration(instr_, object_);
5586     }
5587     Label* check_maps() { return &check_maps_; }
5588     LInstruction* instr() override { return instr_; }
5589
5590    private:
5591     LCheckMaps* instr_;
5592     Label check_maps_;
5593     Register object_;
5594   };
5595
5596   if (instr->hydrogen()->IsStabilityCheck()) {
5597     const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5598     for (int i = 0; i < maps->size(); ++i) {
5599       AddStabilityDependency(maps->at(i).handle());
5600     }
5601     return;
5602   }
5603
5604   Register object = ToRegister(instr->value());
5605   Register map_reg = ToRegister(instr->temp());
5606
5607   __ LoadP(map_reg, FieldMemOperand(object, HeapObject::kMapOffset));
5608
5609   DeferredCheckMaps* deferred = NULL;
5610   if (instr->hydrogen()->HasMigrationTarget()) {
5611     deferred = new (zone()) DeferredCheckMaps(this, instr, object);
5612     __ bind(deferred->check_maps());
5613   }
5614
5615   const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5616   Label success;
5617   for (int i = 0; i < maps->size() - 1; i++) {
5618     Handle<Map> map = maps->at(i).handle();
5619     __ CompareMap(map_reg, map, &success);
5620     __ beq(&success);
5621   }
5622
5623   Handle<Map> map = maps->at(maps->size() - 1).handle();
5624   __ CompareMap(map_reg, map, &success);
5625   if (instr->hydrogen()->HasMigrationTarget()) {
5626     __ bne(deferred->entry());
5627   } else {
5628     DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
5629   }
5630
5631   __ bind(&success);
5632 }
5633
5634
5635 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5636   DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
5637   Register result_reg = ToRegister(instr->result());
5638   __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0());
5639 }
5640
5641
5642 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5643   Register unclamped_reg = ToRegister(instr->unclamped());
5644   Register result_reg = ToRegister(instr->result());
5645   __ ClampUint8(result_reg, unclamped_reg);
5646 }
5647
5648
5649 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
5650   Register scratch = scratch0();
5651   Register input_reg = ToRegister(instr->unclamped());
5652   Register result_reg = ToRegister(instr->result());
5653   DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
5654   Label is_smi, done, heap_number;
5655
5656   // Both smi and heap number cases are handled.
5657   __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi);
5658
5659   // Check for heap number
5660   __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5661   __ Cmpi(scratch, Operand(factory()->heap_number_map()), r0);
5662   __ beq(&heap_number);
5663
5664   // Check for undefined. Undefined is converted to zero for clamping
5665   // conversions.
5666   __ Cmpi(input_reg, Operand(factory()->undefined_value()), r0);
5667   DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined);
5668   __ li(result_reg, Operand::Zero());
5669   __ b(&done);
5670
5671   // Heap number
5672   __ bind(&heap_number);
5673   __ lfd(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5674   __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0());
5675   __ b(&done);
5676
5677   // smi
5678   __ bind(&is_smi);
5679   __ ClampUint8(result_reg, result_reg);
5680
5681   __ bind(&done);
5682 }
5683
5684
5685 void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5686   DoubleRegister value_reg = ToDoubleRegister(instr->value());
5687   Register result_reg = ToRegister(instr->result());
5688
5689   if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5690     __ MovDoubleHighToInt(result_reg, value_reg);
5691   } else {
5692     __ MovDoubleLowToInt(result_reg, value_reg);
5693   }
5694 }
5695
5696
5697 void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5698   Register hi_reg = ToRegister(instr->hi());
5699   Register lo_reg = ToRegister(instr->lo());
5700   DoubleRegister result_reg = ToDoubleRegister(instr->result());
5701 #if V8_TARGET_ARCH_PPC64
5702   __ MovInt64ComponentsToDouble(result_reg, hi_reg, lo_reg, r0);
5703 #else
5704   __ MovInt64ToDouble(result_reg, hi_reg, lo_reg);
5705 #endif
5706 }
5707
5708
5709 void LCodeGen::DoAllocate(LAllocate* instr) {
5710   class DeferredAllocate final : public LDeferredCode {
5711    public:
5712     DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5713         : LDeferredCode(codegen), instr_(instr) {}
5714     void Generate() override { codegen()->DoDeferredAllocate(instr_); }
5715     LInstruction* instr() override { return instr_; }
5716
5717    private:
5718     LAllocate* instr_;
5719   };
5720
5721   DeferredAllocate* deferred = new (zone()) DeferredAllocate(this, instr);
5722
5723   Register result = ToRegister(instr->result());
5724   Register scratch = ToRegister(instr->temp1());
5725   Register scratch2 = ToRegister(instr->temp2());
5726
5727   // Allocate memory for the object.
5728   AllocationFlags flags = TAG_OBJECT;
5729   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5730     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5731   }
5732   if (instr->hydrogen()->IsOldSpaceAllocation()) {
5733     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5734     flags = static_cast<AllocationFlags>(flags | PRETENURE);
5735   }
5736
5737   if (instr->size()->IsConstantOperand()) {
5738     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5739     if (size <= Page::kMaxRegularHeapObjectSize) {
5740       __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
5741     } else {
5742       __ b(deferred->entry());
5743     }
5744   } else {
5745     Register size = ToRegister(instr->size());
5746     __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
5747   }
5748
5749   __ bind(deferred->exit());
5750
5751   if (instr->hydrogen()->MustPrefillWithFiller()) {
5752     if (instr->size()->IsConstantOperand()) {
5753       int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5754       __ LoadIntLiteral(scratch, size - kHeapObjectTag);
5755     } else {
5756       __ subi(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag));
5757     }
5758     __ mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
5759     Label loop;
5760     __ bind(&loop);
5761     __ subi(scratch, scratch, Operand(kPointerSize));
5762     __ StorePX(scratch2, MemOperand(result, scratch));
5763     __ cmpi(scratch, Operand::Zero());
5764     __ bge(&loop);
5765   }
5766 }
5767
5768
5769 void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
5770   Register result = ToRegister(instr->result());
5771
5772   // TODO(3095996): Get rid of this. For now, we need to make the
5773   // result register contain a valid pointer because it is already
5774   // contained in the register pointer map.
5775   __ LoadSmiLiteral(result, Smi::FromInt(0));
5776
5777   PushSafepointRegistersScope scope(this);
5778   if (instr->size()->IsRegister()) {
5779     Register size = ToRegister(instr->size());
5780     DCHECK(!size.is(result));
5781     __ SmiTag(size);
5782     __ push(size);
5783   } else {
5784     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5785 #if !V8_TARGET_ARCH_PPC64
5786     if (size >= 0 && size <= Smi::kMaxValue) {
5787 #endif
5788       __ Push(Smi::FromInt(size));
5789 #if !V8_TARGET_ARCH_PPC64
5790     } else {
5791       // We should never get here at runtime => abort
5792       __ stop("invalid allocation size");
5793       return;
5794     }
5795 #endif
5796   }
5797
5798   int flags = AllocateDoubleAlignFlag::encode(
5799       instr->hydrogen()->MustAllocateDoubleAligned());
5800   if (instr->hydrogen()->IsOldSpaceAllocation()) {
5801     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5802     flags = AllocateTargetSpace::update(flags, OLD_SPACE);
5803   } else {
5804     flags = AllocateTargetSpace::update(flags, NEW_SPACE);
5805   }
5806   __ Push(Smi::FromInt(flags));
5807
5808   CallRuntimeFromDeferred(Runtime::kAllocateInTargetSpace, 2, instr,
5809                           instr->context());
5810   __ StoreToSafepointRegisterSlot(r3, result);
5811 }
5812
5813
5814 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
5815   DCHECK(ToRegister(instr->value()).is(r3));
5816   __ push(r3);
5817   CallRuntime(Runtime::kToFastProperties, 1, instr);
5818 }
5819
5820
5821 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
5822   DCHECK(ToRegister(instr->context()).is(cp));
5823   Label materialized;
5824   // Registers will be used as follows:
5825   // r10 = literals array.
5826   // r4 = regexp literal.
5827   // r3 = regexp literal clone.
5828   // r5 and r7-r9 are used as temporaries.
5829   int literal_offset =
5830       FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
5831   __ Move(r10, instr->hydrogen()->literals());
5832   __ LoadP(r4, FieldMemOperand(r10, literal_offset));
5833   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5834   __ cmp(r4, ip);
5835   __ bne(&materialized);
5836
5837   // Create regexp literal using runtime function
5838   // Result will be in r3.
5839   __ LoadSmiLiteral(r9, Smi::FromInt(instr->hydrogen()->literal_index()));
5840   __ mov(r8, Operand(instr->hydrogen()->pattern()));
5841   __ mov(r7, Operand(instr->hydrogen()->flags()));
5842   __ Push(r10, r9, r8, r7);
5843   CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
5844   __ mr(r4, r3);
5845
5846   __ bind(&materialized);
5847   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
5848   Label allocated, runtime_allocate;
5849
5850   __ Allocate(size, r3, r5, r6, &runtime_allocate, TAG_OBJECT);
5851   __ b(&allocated);
5852
5853   __ bind(&runtime_allocate);
5854   __ LoadSmiLiteral(r3, Smi::FromInt(size));
5855   __ Push(r4, r3);
5856   CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5857   __ pop(r4);
5858
5859   __ bind(&allocated);
5860   // Copy the content into the newly allocated memory.
5861   __ CopyFields(r3, r4, r5.bit(), size / kPointerSize);
5862 }
5863
5864
5865 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
5866   DCHECK(ToRegister(instr->context()).is(cp));
5867   // Use the fast case closure allocation code that allocates in new
5868   // space for nested functions that don't need literals cloning.
5869   bool pretenure = instr->hydrogen()->pretenure();
5870   if (!pretenure && instr->hydrogen()->has_no_literals()) {
5871     FastNewClosureStub stub(isolate(), instr->hydrogen()->language_mode(),
5872                             instr->hydrogen()->kind());
5873     __ mov(r5, Operand(instr->hydrogen()->shared_info()));
5874     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5875   } else {
5876     __ mov(r5, Operand(instr->hydrogen()->shared_info()));
5877     __ mov(r4, Operand(pretenure ? factory()->true_value()
5878                                  : factory()->false_value()));
5879     __ Push(cp, r5, r4);
5880     CallRuntime(Runtime::kNewClosure, 3, instr);
5881   }
5882 }
5883
5884
5885 void LCodeGen::DoTypeof(LTypeof* instr) {
5886   DCHECK(ToRegister(instr->value()).is(r6));
5887   DCHECK(ToRegister(instr->result()).is(r3));
5888   Label end, do_call;
5889   Register value_register = ToRegister(instr->value());
5890   __ JumpIfNotSmi(value_register, &do_call);
5891   __ mov(r3, Operand(isolate()->factory()->number_string()));
5892   __ b(&end);
5893   __ bind(&do_call);
5894   TypeofStub stub(isolate());
5895   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5896   __ bind(&end);
5897 }
5898
5899
5900 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5901   Register input = ToRegister(instr->value());
5902
5903   Condition final_branch_condition =
5904       EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), input,
5905                    instr->type_literal());
5906   if (final_branch_condition != kNoCondition) {
5907     EmitBranch(instr, final_branch_condition);
5908   }
5909 }
5910
5911
5912 Condition LCodeGen::EmitTypeofIs(Label* true_label, Label* false_label,
5913                                  Register input, Handle<String> type_name) {
5914   Condition final_branch_condition = kNoCondition;
5915   Register scratch = scratch0();
5916   Factory* factory = isolate()->factory();
5917   if (String::Equals(type_name, factory->number_string())) {
5918     __ JumpIfSmi(input, true_label);
5919     __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5920     __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
5921     final_branch_condition = eq;
5922
5923   } else if (String::Equals(type_name, factory->string_string())) {
5924     __ JumpIfSmi(input, false_label);
5925     __ CompareObjectType(input, scratch, no_reg, FIRST_NONSTRING_TYPE);
5926     __ bge(false_label);
5927     __ lbz(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
5928     __ ExtractBit(r0, scratch, Map::kIsUndetectable);
5929     __ cmpi(r0, Operand::Zero());
5930     final_branch_condition = eq;
5931
5932   } else if (String::Equals(type_name, factory->symbol_string())) {
5933     __ JumpIfSmi(input, false_label);
5934     __ CompareObjectType(input, scratch, no_reg, SYMBOL_TYPE);
5935     final_branch_condition = eq;
5936
5937   } else if (String::Equals(type_name, factory->boolean_string())) {
5938     __ CompareRoot(input, Heap::kTrueValueRootIndex);
5939     __ beq(true_label);
5940     __ CompareRoot(input, Heap::kFalseValueRootIndex);
5941     final_branch_condition = eq;
5942
5943   } else if (String::Equals(type_name, factory->undefined_string())) {
5944     __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
5945     __ beq(true_label);
5946     __ JumpIfSmi(input, false_label);
5947     // Check for undetectable objects => true.
5948     __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5949     __ lbz(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
5950     __ ExtractBit(r0, scratch, Map::kIsUndetectable);
5951     __ cmpi(r0, Operand::Zero());
5952     final_branch_condition = ne;
5953
5954   } else if (String::Equals(type_name, factory->function_string())) {
5955     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
5956     Register type_reg = scratch;
5957     __ JumpIfSmi(input, false_label);
5958     __ CompareObjectType(input, scratch, type_reg, JS_FUNCTION_TYPE);
5959     __ beq(true_label);
5960     __ cmpi(type_reg, Operand(JS_FUNCTION_PROXY_TYPE));
5961     final_branch_condition = eq;
5962
5963   } else if (String::Equals(type_name, factory->object_string())) {
5964     Register map = scratch;
5965     __ JumpIfSmi(input, false_label);
5966     __ CompareRoot(input, Heap::kNullValueRootIndex);
5967     __ beq(true_label);
5968     __ CheckObjectTypeRange(input, map, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE,
5969                             LAST_NONCALLABLE_SPEC_OBJECT_TYPE, false_label);
5970     // Check for undetectable objects => false.
5971     __ lbz(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
5972     __ ExtractBit(r0, scratch, Map::kIsUndetectable);
5973     __ cmpi(r0, Operand::Zero());
5974     final_branch_condition = eq;
5975
5976   } else if (String::Equals(type_name, factory->float32x4_string())) {
5977     __ JumpIfSmi(input, false_label);
5978     __ CompareObjectType(input, scratch, no_reg, FLOAT32X4_TYPE);
5979     final_branch_condition = eq;
5980
5981   } else {
5982     __ b(false_label);
5983   }
5984
5985   return final_branch_condition;
5986 }
5987
5988
5989 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5990   Register temp1 = ToRegister(instr->temp());
5991
5992   EmitIsConstructCall(temp1, scratch0());
5993   EmitBranch(instr, eq);
5994 }
5995
5996
5997 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
5998   DCHECK(!temp1.is(temp2));
5999   // Get the frame pointer for the calling frame.
6000   __ LoadP(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
6001
6002   // Skip the arguments adaptor frame if it exists.
6003   Label check_frame_marker;
6004   __ LoadP(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
6005   __ CmpSmiLiteral(temp2, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
6006   __ bne(&check_frame_marker);
6007   __ LoadP(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
6008
6009   // Check the marker in the calling frame.
6010   __ bind(&check_frame_marker);
6011   __ LoadP(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
6012   __ CmpSmiLiteral(temp1, Smi::FromInt(StackFrame::CONSTRUCT), r0);
6013 }
6014
6015
6016 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
6017   if (!info()->IsStub()) {
6018     // Ensure that we have enough space after the previous lazy-bailout
6019     // instruction for patching the code here.
6020     int current_pc = masm()->pc_offset();
6021     if (current_pc < last_lazy_deopt_pc_ + space_needed) {
6022       int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
6023       DCHECK_EQ(0, padding_size % Assembler::kInstrSize);
6024       while (padding_size > 0) {
6025         __ nop();
6026         padding_size -= Assembler::kInstrSize;
6027       }
6028     }
6029   }
6030   last_lazy_deopt_pc_ = masm()->pc_offset();
6031 }
6032
6033
6034 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
6035   last_lazy_deopt_pc_ = masm()->pc_offset();
6036   DCHECK(instr->HasEnvironment());
6037   LEnvironment* env = instr->environment();
6038   RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6039   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6040 }
6041
6042
6043 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
6044   Deoptimizer::BailoutType type = instr->hydrogen()->type();
6045   // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
6046   // needed return address), even though the implementation of LAZY and EAGER is
6047   // now identical. When LAZY is eventually completely folded into EAGER, remove
6048   // the special case below.
6049   if (info()->IsStub() && type == Deoptimizer::EAGER) {
6050     type = Deoptimizer::LAZY;
6051   }
6052
6053   DeoptimizeIf(al, instr, instr->hydrogen()->reason(), type);
6054 }
6055
6056
6057 void LCodeGen::DoDummy(LDummy* instr) {
6058   // Nothing to see here, move on!
6059 }
6060
6061
6062 void LCodeGen::DoDummyUse(LDummyUse* instr) {
6063   // Nothing to see here, move on!
6064 }
6065
6066
6067 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
6068   PushSafepointRegistersScope scope(this);
6069   LoadContextFromDeferred(instr->context());
6070   __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
6071   RecordSafepointWithLazyDeopt(
6072       instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
6073   DCHECK(instr->HasEnvironment());
6074   LEnvironment* env = instr->environment();
6075   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6076 }
6077
6078
6079 void LCodeGen::DoStackCheck(LStackCheck* instr) {
6080   class DeferredStackCheck final : public LDeferredCode {
6081    public:
6082     DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
6083         : LDeferredCode(codegen), instr_(instr) {}
6084     void Generate() override { codegen()->DoDeferredStackCheck(instr_); }
6085     LInstruction* instr() override { return instr_; }
6086
6087    private:
6088     LStackCheck* instr_;
6089   };
6090
6091   DCHECK(instr->HasEnvironment());
6092   LEnvironment* env = instr->environment();
6093   // There is no LLazyBailout instruction for stack-checks. We have to
6094   // prepare for lazy deoptimization explicitly here.
6095   if (instr->hydrogen()->is_function_entry()) {
6096     // Perform stack overflow check.
6097     Label done;
6098     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
6099     __ cmpl(sp, ip);
6100     __ bge(&done);
6101     DCHECK(instr->context()->IsRegister());
6102     DCHECK(ToRegister(instr->context()).is(cp));
6103     CallCode(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET,
6104              instr);
6105     __ bind(&done);
6106   } else {
6107     DCHECK(instr->hydrogen()->is_backwards_branch());
6108     // Perform stack overflow check if this goto needs it before jumping.
6109     DeferredStackCheck* deferred_stack_check =
6110         new (zone()) DeferredStackCheck(this, instr);
6111     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
6112     __ cmpl(sp, ip);
6113     __ blt(deferred_stack_check->entry());
6114     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
6115     __ bind(instr->done_label());
6116     deferred_stack_check->SetExit(instr->done_label());
6117     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6118     // Don't record a deoptimization index for the safepoint here.
6119     // This will be done explicitly when emitting call and the safepoint in
6120     // the deferred code.
6121   }
6122 }
6123
6124
6125 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
6126   // This is a pseudo-instruction that ensures that the environment here is
6127   // properly registered for deoptimization and records the assembler's PC
6128   // offset.
6129   LEnvironment* environment = instr->environment();
6130
6131   // If the environment were already registered, we would have no way of
6132   // backpatching it with the spill slot operands.
6133   DCHECK(!environment->HasBeenRegistered());
6134   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6135
6136   GenerateOsrPrologue();
6137 }
6138
6139
6140 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
6141   __ TestIfSmi(r3, r0);
6142   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
6143
6144   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
6145   __ CompareObjectType(r3, r4, r4, LAST_JS_PROXY_TYPE);
6146   DeoptimizeIf(le, instr, Deoptimizer::kWrongInstanceType);
6147
6148   Label use_cache, call_runtime;
6149   Register null_value = r8;
6150   __ LoadRoot(null_value, Heap::kNullValueRootIndex);
6151   __ CheckEnumCache(null_value, &call_runtime);
6152
6153   __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
6154   __ b(&use_cache);
6155
6156   // Get the set of properties to enumerate.
6157   __ bind(&call_runtime);
6158   __ push(r3);
6159   CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
6160
6161   __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
6162   __ LoadRoot(ip, Heap::kMetaMapRootIndex);
6163   __ cmp(r4, ip);
6164   DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
6165   __ bind(&use_cache);
6166 }
6167
6168
6169 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6170   Register map = ToRegister(instr->map());
6171   Register result = ToRegister(instr->result());
6172   Label load_cache, done;
6173   __ EnumLength(result, map);
6174   __ CmpSmiLiteral(result, Smi::FromInt(0), r0);
6175   __ bne(&load_cache);
6176   __ mov(result, Operand(isolate()->factory()->empty_fixed_array()));
6177   __ b(&done);
6178
6179   __ bind(&load_cache);
6180   __ LoadInstanceDescriptors(map, result);
6181   __ LoadP(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
6182   __ LoadP(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
6183   __ cmpi(result, Operand::Zero());
6184   DeoptimizeIf(eq, instr, Deoptimizer::kNoCache);
6185
6186   __ bind(&done);
6187 }
6188
6189
6190 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6191   Register object = ToRegister(instr->value());
6192   Register map = ToRegister(instr->map());
6193   __ LoadP(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
6194   __ cmp(map, scratch0());
6195   DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
6196 }
6197
6198
6199 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
6200                                            Register result, Register object,
6201                                            Register index) {
6202   PushSafepointRegistersScope scope(this);
6203   __ Push(object, index);
6204   __ li(cp, Operand::Zero());
6205   __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
6206   RecordSafepointWithRegisters(instr->pointer_map(), 2,
6207                                Safepoint::kNoLazyDeopt);
6208   __ StoreToSafepointRegisterSlot(r3, result);
6209 }
6210
6211
6212 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6213   class DeferredLoadMutableDouble final : public LDeferredCode {
6214    public:
6215     DeferredLoadMutableDouble(LCodeGen* codegen, LLoadFieldByIndex* instr,
6216                               Register result, Register object, Register index)
6217         : LDeferredCode(codegen),
6218           instr_(instr),
6219           result_(result),
6220           object_(object),
6221           index_(index) {}
6222     void Generate() override {
6223       codegen()->DoDeferredLoadMutableDouble(instr_, result_, object_, index_);
6224     }
6225     LInstruction* instr() override { return instr_; }
6226
6227    private:
6228     LLoadFieldByIndex* instr_;
6229     Register result_;
6230     Register object_;
6231     Register index_;
6232   };
6233
6234   Register object = ToRegister(instr->object());
6235   Register index = ToRegister(instr->index());
6236   Register result = ToRegister(instr->result());
6237   Register scratch = scratch0();
6238
6239   DeferredLoadMutableDouble* deferred;
6240   deferred = new (zone())
6241       DeferredLoadMutableDouble(this, instr, result, object, index);
6242
6243   Label out_of_object, done;
6244
6245   __ TestBitMask(index, reinterpret_cast<uintptr_t>(Smi::FromInt(1)), r0);
6246   __ bne(deferred->entry(), cr0);
6247   __ ShiftRightArithImm(index, index, 1);
6248
6249   __ cmpi(index, Operand::Zero());
6250   __ blt(&out_of_object);
6251
6252   __ SmiToPtrArrayOffset(r0, index);
6253   __ add(scratch, object, r0);
6254   __ LoadP(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
6255
6256   __ b(&done);
6257
6258   __ bind(&out_of_object);
6259   __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
6260   // Index is equal to negated out of object property index plus 1.
6261   __ SmiToPtrArrayOffset(r0, index);
6262   __ sub(scratch, result, r0);
6263   __ LoadP(result,
6264            FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize));
6265   __ bind(deferred->exit());
6266   __ bind(&done);
6267 }
6268
6269
6270 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
6271   Register context = ToRegister(instr->context());
6272   __ StoreP(context, MemOperand(fp, StandardFrameConstants::kContextOffset));
6273 }
6274
6275
6276 void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) {
6277   Handle<ScopeInfo> scope_info = instr->scope_info();
6278   __ Push(scope_info);
6279   __ push(ToRegister(instr->function()));
6280   CallRuntime(Runtime::kPushBlockContext, 2, instr);
6281   RecordSafepoint(Safepoint::kNoLazyDeopt);
6282 }
6283
6284
6285 #undef __
6286 }  // namespace internal
6287 }  // namespace v8