Revert of Expose SIMD.Float32x4 type to Javascript. (patchset #14 id:450001 of https...
[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::HEAP_NUMBER)) {
2309         // heap number -> false iff +0, -0, or NaN.
2310         Label not_heap_number;
2311         __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
2312         __ bne(&not_heap_number);
2313         __ lfd(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2314         // Test the double value. Zero and NaN are false.
2315         __ fcmpu(dbl_scratch, kDoubleRegZero, cr7);
2316         __ mfcr(r0);
2317         __ andi(r0, r0, Operand(crZOrNaNBits));
2318         __ bne(instr->FalseLabel(chunk_), cr0);
2319         __ b(instr->TrueLabel(chunk_));
2320         __ bind(&not_heap_number);
2321       }
2322
2323       if (!expected.IsGeneric()) {
2324         // We've seen something for the first time -> deopt.
2325         // This can only happen if we are not generic already.
2326         DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject);
2327       }
2328     }
2329   }
2330 }
2331
2332
2333 void LCodeGen::EmitGoto(int block) {
2334   if (!IsNextEmittedBlock(block)) {
2335     __ b(chunk_->GetAssemblyLabel(LookupDestination(block)));
2336   }
2337 }
2338
2339
2340 void LCodeGen::DoGoto(LGoto* instr) { EmitGoto(instr->block_id()); }
2341
2342
2343 Condition LCodeGen::TokenToCondition(Token::Value op) {
2344   Condition cond = kNoCondition;
2345   switch (op) {
2346     case Token::EQ:
2347     case Token::EQ_STRICT:
2348       cond = eq;
2349       break;
2350     case Token::NE:
2351     case Token::NE_STRICT:
2352       cond = ne;
2353       break;
2354     case Token::LT:
2355       cond = lt;
2356       break;
2357     case Token::GT:
2358       cond = gt;
2359       break;
2360     case Token::LTE:
2361       cond = le;
2362       break;
2363     case Token::GTE:
2364       cond = ge;
2365       break;
2366     case Token::IN:
2367     case Token::INSTANCEOF:
2368     default:
2369       UNREACHABLE();
2370   }
2371   return cond;
2372 }
2373
2374
2375 void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
2376   LOperand* left = instr->left();
2377   LOperand* right = instr->right();
2378   bool is_unsigned =
2379       instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
2380       instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
2381   Condition cond = TokenToCondition(instr->op());
2382
2383   if (left->IsConstantOperand() && right->IsConstantOperand()) {
2384     // We can statically evaluate the comparison.
2385     double left_val = ToDouble(LConstantOperand::cast(left));
2386     double right_val = ToDouble(LConstantOperand::cast(right));
2387     int next_block = EvalComparison(instr->op(), left_val, right_val)
2388                          ? instr->TrueDestination(chunk_)
2389                          : instr->FalseDestination(chunk_);
2390     EmitGoto(next_block);
2391   } else {
2392     if (instr->is_double()) {
2393       // Compare left and right operands as doubles and load the
2394       // resulting flags into the normal status register.
2395       __ fcmpu(ToDoubleRegister(left), ToDoubleRegister(right));
2396       // If a NaN is involved, i.e. the result is unordered,
2397       // jump to false block label.
2398       __ bunordered(instr->FalseLabel(chunk_));
2399     } else {
2400       if (right->IsConstantOperand()) {
2401         int32_t value = ToInteger32(LConstantOperand::cast(right));
2402         if (instr->hydrogen_value()->representation().IsSmi()) {
2403           if (is_unsigned) {
2404             __ CmplSmiLiteral(ToRegister(left), Smi::FromInt(value), r0);
2405           } else {
2406             __ CmpSmiLiteral(ToRegister(left), Smi::FromInt(value), r0);
2407           }
2408         } else {
2409           if (is_unsigned) {
2410             __ Cmplwi(ToRegister(left), Operand(value), r0);
2411           } else {
2412             __ Cmpwi(ToRegister(left), Operand(value), r0);
2413           }
2414         }
2415       } else if (left->IsConstantOperand()) {
2416         int32_t value = ToInteger32(LConstantOperand::cast(left));
2417         if (instr->hydrogen_value()->representation().IsSmi()) {
2418           if (is_unsigned) {
2419             __ CmplSmiLiteral(ToRegister(right), Smi::FromInt(value), r0);
2420           } else {
2421             __ CmpSmiLiteral(ToRegister(right), Smi::FromInt(value), r0);
2422           }
2423         } else {
2424           if (is_unsigned) {
2425             __ Cmplwi(ToRegister(right), Operand(value), r0);
2426           } else {
2427             __ Cmpwi(ToRegister(right), Operand(value), r0);
2428           }
2429         }
2430         // We commuted the operands, so commute the condition.
2431         cond = CommuteCondition(cond);
2432       } else if (instr->hydrogen_value()->representation().IsSmi()) {
2433         if (is_unsigned) {
2434           __ cmpl(ToRegister(left), ToRegister(right));
2435         } else {
2436           __ cmp(ToRegister(left), ToRegister(right));
2437         }
2438       } else {
2439         if (is_unsigned) {
2440           __ cmplw(ToRegister(left), ToRegister(right));
2441         } else {
2442           __ cmpw(ToRegister(left), ToRegister(right));
2443         }
2444       }
2445     }
2446     EmitBranch(instr, cond);
2447   }
2448 }
2449
2450
2451 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2452   Register left = ToRegister(instr->left());
2453   Register right = ToRegister(instr->right());
2454
2455   __ cmp(left, right);
2456   EmitBranch(instr, eq);
2457 }
2458
2459
2460 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2461   if (instr->hydrogen()->representation().IsTagged()) {
2462     Register input_reg = ToRegister(instr->object());
2463     __ mov(ip, Operand(factory()->the_hole_value()));
2464     __ cmp(input_reg, ip);
2465     EmitBranch(instr, eq);
2466     return;
2467   }
2468
2469   DoubleRegister input_reg = ToDoubleRegister(instr->object());
2470   __ fcmpu(input_reg, input_reg);
2471   EmitFalseBranch(instr, ordered);
2472
2473   Register scratch = scratch0();
2474   __ MovDoubleHighToInt(scratch, input_reg);
2475   __ Cmpi(scratch, Operand(kHoleNanUpper32), r0);
2476   EmitBranch(instr, eq);
2477 }
2478
2479
2480 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2481   Representation rep = instr->hydrogen()->value()->representation();
2482   DCHECK(!rep.IsInteger32());
2483   Register scratch = ToRegister(instr->temp());
2484
2485   if (rep.IsDouble()) {
2486     DoubleRegister value = ToDoubleRegister(instr->value());
2487     __ fcmpu(value, kDoubleRegZero);
2488     EmitFalseBranch(instr, ne);
2489 #if V8_TARGET_ARCH_PPC64
2490     __ MovDoubleToInt64(scratch, value);
2491 #else
2492     __ MovDoubleHighToInt(scratch, value);
2493 #endif
2494     __ cmpi(scratch, Operand::Zero());
2495     EmitBranch(instr, lt);
2496   } else {
2497     Register value = ToRegister(instr->value());
2498     __ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex,
2499                 instr->FalseLabel(chunk()), DO_SMI_CHECK);
2500 #if V8_TARGET_ARCH_PPC64
2501     __ LoadP(scratch, FieldMemOperand(value, HeapNumber::kValueOffset));
2502     __ li(ip, Operand(1));
2503     __ rotrdi(ip, ip, 1);  // ip = 0x80000000_00000000
2504     __ cmp(scratch, ip);
2505 #else
2506     __ lwz(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset));
2507     __ lwz(ip, FieldMemOperand(value, HeapNumber::kMantissaOffset));
2508     Label skip;
2509     __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
2510     __ cmp(scratch, r0);
2511     __ bne(&skip);
2512     __ cmpi(ip, Operand::Zero());
2513     __ bind(&skip);
2514 #endif
2515     EmitBranch(instr, eq);
2516   }
2517 }
2518
2519
2520 Condition LCodeGen::EmitIsObject(Register input, Register temp1,
2521                                  Label* is_not_object, Label* is_object) {
2522   Register temp2 = scratch0();
2523   __ JumpIfSmi(input, is_not_object);
2524
2525   __ LoadRoot(temp2, Heap::kNullValueRootIndex);
2526   __ cmp(input, temp2);
2527   __ beq(is_object);
2528
2529   // Load map.
2530   __ LoadP(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
2531   // Undetectable objects behave like undefined.
2532   __ lbz(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
2533   __ TestBit(temp2, Map::kIsUndetectable, r0);
2534   __ bne(is_not_object, cr0);
2535
2536   // Load instance type and check that it is in object type range.
2537   __ lbz(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
2538   __ cmpi(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2539   __ blt(is_not_object);
2540   __ cmpi(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2541   return le;
2542 }
2543
2544
2545 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
2546   Register reg = ToRegister(instr->value());
2547   Register temp1 = ToRegister(instr->temp());
2548
2549   Condition true_cond = EmitIsObject(reg, temp1, instr->FalseLabel(chunk_),
2550                                      instr->TrueLabel(chunk_));
2551
2552   EmitBranch(instr, true_cond);
2553 }
2554
2555
2556 Condition LCodeGen::EmitIsString(Register input, Register temp1,
2557                                  Label* is_not_string,
2558                                  SmiCheck check_needed = INLINE_SMI_CHECK) {
2559   if (check_needed == INLINE_SMI_CHECK) {
2560     __ JumpIfSmi(input, is_not_string);
2561   }
2562   __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE);
2563
2564   return lt;
2565 }
2566
2567
2568 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2569   Register reg = ToRegister(instr->value());
2570   Register temp1 = ToRegister(instr->temp());
2571
2572   SmiCheck check_needed = instr->hydrogen()->value()->type().IsHeapObject()
2573                               ? OMIT_SMI_CHECK
2574                               : INLINE_SMI_CHECK;
2575   Condition true_cond =
2576       EmitIsString(reg, temp1, instr->FalseLabel(chunk_), check_needed);
2577
2578   EmitBranch(instr, true_cond);
2579 }
2580
2581
2582 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2583   Register input_reg = EmitLoadRegister(instr->value(), ip);
2584   __ TestIfSmi(input_reg, r0);
2585   EmitBranch(instr, eq, cr0);
2586 }
2587
2588
2589 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2590   Register input = ToRegister(instr->value());
2591   Register temp = ToRegister(instr->temp());
2592
2593   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2594     __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2595   }
2596   __ LoadP(temp, FieldMemOperand(input, HeapObject::kMapOffset));
2597   __ lbz(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
2598   __ TestBit(temp, Map::kIsUndetectable, r0);
2599   EmitBranch(instr, ne, cr0);
2600 }
2601
2602
2603 static Condition ComputeCompareCondition(Token::Value op) {
2604   switch (op) {
2605     case Token::EQ_STRICT:
2606     case Token::EQ:
2607       return eq;
2608     case Token::LT:
2609       return lt;
2610     case Token::GT:
2611       return gt;
2612     case Token::LTE:
2613       return le;
2614     case Token::GTE:
2615       return ge;
2616     default:
2617       UNREACHABLE();
2618       return kNoCondition;
2619   }
2620 }
2621
2622
2623 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2624   DCHECK(ToRegister(instr->context()).is(cp));
2625   Token::Value op = instr->op();
2626
2627   Handle<Code> ic =
2628       CodeFactory::CompareIC(isolate(), op, Strength::WEAK).code();
2629   CallCode(ic, RelocInfo::CODE_TARGET, instr);
2630   // This instruction also signals no smi code inlined
2631   __ cmpi(r3, Operand::Zero());
2632
2633   Condition condition = ComputeCompareCondition(op);
2634
2635   EmitBranch(instr, condition);
2636 }
2637
2638
2639 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2640   InstanceType from = instr->from();
2641   InstanceType to = instr->to();
2642   if (from == FIRST_TYPE) return to;
2643   DCHECK(from == to || to == LAST_TYPE);
2644   return from;
2645 }
2646
2647
2648 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2649   InstanceType from = instr->from();
2650   InstanceType to = instr->to();
2651   if (from == to) return eq;
2652   if (to == LAST_TYPE) return ge;
2653   if (from == FIRST_TYPE) return le;
2654   UNREACHABLE();
2655   return eq;
2656 }
2657
2658
2659 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2660   Register scratch = scratch0();
2661   Register input = ToRegister(instr->value());
2662
2663   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2664     __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2665   }
2666
2667   __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
2668   EmitBranch(instr, BranchCondition(instr->hydrogen()));
2669 }
2670
2671
2672 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
2673   Register input = ToRegister(instr->value());
2674   Register result = ToRegister(instr->result());
2675
2676   __ AssertString(input);
2677
2678   __ lwz(result, FieldMemOperand(input, String::kHashFieldOffset));
2679   __ IndexFromHash(result, result);
2680 }
2681
2682
2683 void LCodeGen::DoHasCachedArrayIndexAndBranch(
2684     LHasCachedArrayIndexAndBranch* instr) {
2685   Register input = ToRegister(instr->value());
2686   Register scratch = scratch0();
2687
2688   __ lwz(scratch, FieldMemOperand(input, String::kHashFieldOffset));
2689   __ mov(r0, Operand(String::kContainsCachedArrayIndexMask));
2690   __ and_(r0, scratch, r0, SetRC);
2691   EmitBranch(instr, eq, cr0);
2692 }
2693
2694
2695 // Branches to a label or falls through with the answer in flags.  Trashes
2696 // the temp registers, but not the input.
2697 void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false,
2698                                Handle<String> class_name, Register input,
2699                                Register temp, Register temp2) {
2700   DCHECK(!input.is(temp));
2701   DCHECK(!input.is(temp2));
2702   DCHECK(!temp.is(temp2));
2703
2704   __ JumpIfSmi(input, is_false);
2705
2706   if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
2707     // Assuming the following assertions, we can use the same compares to test
2708     // for both being a function type and being in the object type range.
2709     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2710     STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2711                   FIRST_SPEC_OBJECT_TYPE + 1);
2712     STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2713                   LAST_SPEC_OBJECT_TYPE - 1);
2714     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
2715     __ CompareObjectType(input, temp, temp2, FIRST_SPEC_OBJECT_TYPE);
2716     __ blt(is_false);
2717     __ beq(is_true);
2718     __ cmpi(temp2, Operand(LAST_SPEC_OBJECT_TYPE));
2719     __ beq(is_true);
2720   } else {
2721     // Faster code path to avoid two compares: subtract lower bound from the
2722     // actual type and do a signed compare with the width of the type range.
2723     __ LoadP(temp, FieldMemOperand(input, HeapObject::kMapOffset));
2724     __ lbz(temp2, FieldMemOperand(temp, Map::kInstanceTypeOffset));
2725     __ subi(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2726     __ cmpi(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
2727                            FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2728     __ bgt(is_false);
2729   }
2730
2731   // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
2732   // Check if the constructor in the map is a function.
2733   Register instance_type = ip;
2734   __ GetMapConstructor(temp, temp, temp2, instance_type);
2735
2736   // Objects with a non-function constructor have class 'Object'.
2737   __ cmpi(instance_type, Operand(JS_FUNCTION_TYPE));
2738   if (class_name->IsOneByteEqualTo(STATIC_CHAR_VECTOR("Object"))) {
2739     __ bne(is_true);
2740   } else {
2741     __ bne(is_false);
2742   }
2743
2744   // temp now contains the constructor function. Grab the
2745   // instance class name from there.
2746   __ LoadP(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
2747   __ LoadP(temp,
2748            FieldMemOperand(temp, SharedFunctionInfo::kInstanceClassNameOffset));
2749   // The class name we are testing against is internalized since it's a literal.
2750   // The name in the constructor is internalized because of the way the context
2751   // is booted.  This routine isn't expected to work for random API-created
2752   // classes and it doesn't have to because you can't access it with natives
2753   // syntax.  Since both sides are internalized it is sufficient to use an
2754   // identity comparison.
2755   __ Cmpi(temp, Operand(class_name), r0);
2756   // End with the answer in flags.
2757 }
2758
2759
2760 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2761   Register input = ToRegister(instr->value());
2762   Register temp = scratch0();
2763   Register temp2 = ToRegister(instr->temp());
2764   Handle<String> class_name = instr->hydrogen()->class_name();
2765
2766   EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2767                   class_name, input, temp, temp2);
2768
2769   EmitBranch(instr, eq);
2770 }
2771
2772
2773 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2774   Register reg = ToRegister(instr->value());
2775   Register temp = ToRegister(instr->temp());
2776
2777   __ LoadP(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
2778   __ Cmpi(temp, Operand(instr->map()), r0);
2779   EmitBranch(instr, eq);
2780 }
2781
2782
2783 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2784   DCHECK(ToRegister(instr->context()).is(cp));
2785   DCHECK(ToRegister(instr->left()).is(r3));   // Object is in r3.
2786   DCHECK(ToRegister(instr->right()).is(r4));  // Function is in r4.
2787
2788   InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters);
2789   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2790
2791   if (CpuFeatures::IsSupported(ISELECT)) {
2792     __ mov(r4, Operand(factory()->true_value()));
2793     __ mov(r5, Operand(factory()->false_value()));
2794     __ cmpi(r3, Operand::Zero());
2795     __ isel(eq, r3, r4, r5);
2796   } else {
2797     Label equal, done;
2798     __ cmpi(r3, Operand::Zero());
2799     __ beq(&equal);
2800     __ mov(r3, Operand(factory()->false_value()));
2801     __ b(&done);
2802
2803     __ bind(&equal);
2804     __ mov(r3, Operand(factory()->true_value()));
2805     __ bind(&done);
2806   }
2807 }
2808
2809
2810 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2811   class DeferredInstanceOfKnownGlobal final : public LDeferredCode {
2812    public:
2813     DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2814                                   LInstanceOfKnownGlobal* instr)
2815         : LDeferredCode(codegen), instr_(instr) {}
2816     void Generate() override {
2817       codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_,
2818                                                  &load_bool_);
2819     }
2820     LInstruction* instr() override { return instr_; }
2821     Label* map_check() { return &map_check_; }
2822     Label* load_bool() { return &load_bool_; }
2823
2824    private:
2825     LInstanceOfKnownGlobal* instr_;
2826     Label map_check_;
2827     Label load_bool_;
2828   };
2829
2830   DeferredInstanceOfKnownGlobal* deferred;
2831   deferred = new (zone()) DeferredInstanceOfKnownGlobal(this, instr);
2832
2833   Label done, false_result;
2834   Register object = ToRegister(instr->value());
2835   Register temp = ToRegister(instr->temp());
2836   Register result = ToRegister(instr->result());
2837
2838   // A Smi is not instance of anything.
2839   __ JumpIfSmi(object, &false_result);
2840
2841   // This is the inlined call site instanceof cache. The two occurences of the
2842   // hole value will be patched to the last map/result pair generated by the
2843   // instanceof stub.
2844   Label cache_miss;
2845   Register map = temp;
2846   __ LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
2847   {
2848     // Block trampoline emission to ensure the positions of instructions are
2849     // as expected by the patcher. See InstanceofStub::Generate().
2850     Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
2851     __ bind(deferred->map_check());  // Label for calculating code patching.
2852     // We use Factory::the_hole_value() on purpose instead of loading from the
2853     // root array to force relocation to be able to later patch with
2854     // the cached map.
2855     Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value());
2856     __ mov(ip, Operand(cell));
2857     __ LoadP(ip, FieldMemOperand(ip, Cell::kValueOffset));
2858     __ cmp(map, ip);
2859     __ bc_short(ne, &cache_miss);
2860     __ bind(deferred->load_bool());  // Label for calculating code patching.
2861     // We use Factory::the_hole_value() on purpose instead of loading from the
2862     // root array to force relocation to be able to later patch
2863     // with true or false.
2864     __ mov(result, Operand(factory()->the_hole_value()));
2865   }
2866   __ b(&done);
2867
2868   // The inlined call site cache did not match. Check null and string before
2869   // calling the deferred code.
2870   __ bind(&cache_miss);
2871   // Null is not instance of anything.
2872   __ LoadRoot(ip, Heap::kNullValueRootIndex);
2873   __ cmp(object, ip);
2874   __ beq(&false_result);
2875
2876   // String values is not instance of anything.
2877   Condition is_string = masm_->IsObjectStringType(object, temp);
2878   __ b(is_string, &false_result, cr0);
2879
2880   // Go to the deferred code.
2881   __ b(deferred->entry());
2882
2883   __ bind(&false_result);
2884   __ LoadRoot(result, Heap::kFalseValueRootIndex);
2885
2886   // Here result has either true or false. Deferred code also produces true or
2887   // false object.
2888   __ bind(deferred->exit());
2889   __ bind(&done);
2890 }
2891
2892
2893 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
2894                                                Label* map_check,
2895                                                Label* bool_load) {
2896   InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
2897   flags = static_cast<InstanceofStub::Flags>(flags |
2898                                              InstanceofStub::kArgsInRegisters);
2899   flags = static_cast<InstanceofStub::Flags>(
2900       flags | InstanceofStub::kCallSiteInlineCheck);
2901   flags = static_cast<InstanceofStub::Flags>(
2902       flags | InstanceofStub::kReturnTrueFalseObject);
2903   InstanceofStub stub(isolate(), flags);
2904
2905   PushSafepointRegistersScope scope(this);
2906   LoadContextFromDeferred(instr->context());
2907
2908   __ Move(InstanceofStub::right(), instr->function());
2909   {
2910     Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
2911     Handle<Code> code = stub.GetCode();
2912     // Include instructions below in delta: bitwise_mov32 + li + call
2913     int additional_delta = 3 * Instruction::kInstrSize + masm_->CallSize(code);
2914     // The labels must be already bound since the code has predictabel size up
2915     // to the call instruction.
2916     DCHECK(map_check->is_bound());
2917     DCHECK(bool_load->is_bound());
2918     int map_check_delta =
2919         masm_->InstructionsGeneratedSince(map_check) * Instruction::kInstrSize;
2920     int bool_load_delta =
2921         masm_->InstructionsGeneratedSince(bool_load) * Instruction::kInstrSize;
2922     // r8 is the delta from our callee's lr to the location of the map check.
2923     __ bitwise_mov32(r8, map_check_delta + additional_delta);
2924     // r9 is the delta from map check to bool load.
2925     __ li(r9, Operand(map_check_delta - bool_load_delta));
2926     CallCodeGeneric(code, RelocInfo::CODE_TARGET, instr,
2927                     RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
2928     DCHECK_EQ((map_check_delta + additional_delta) / Instruction::kInstrSize,
2929               masm_->InstructionsGeneratedSince(map_check));
2930   }
2931   LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
2932   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
2933   // Put the result value (r3) into the result register slot and
2934   // restore all registers.
2935   __ StoreToSafepointRegisterSlot(r3, ToRegister(instr->result()));
2936 }
2937
2938
2939 void LCodeGen::DoCmpT(LCmpT* instr) {
2940   DCHECK(ToRegister(instr->context()).is(cp));
2941   Token::Value op = instr->op();
2942
2943   Handle<Code> ic =
2944       CodeFactory::CompareIC(isolate(), op, instr->strength()).code();
2945   CallCode(ic, RelocInfo::CODE_TARGET, instr);
2946   // This instruction also signals no smi code inlined
2947   __ cmpi(r3, Operand::Zero());
2948
2949   Condition condition = ComputeCompareCondition(op);
2950   if (CpuFeatures::IsSupported(ISELECT)) {
2951     __ LoadRoot(r4, Heap::kTrueValueRootIndex);
2952     __ LoadRoot(r5, Heap::kFalseValueRootIndex);
2953     __ isel(condition, ToRegister(instr->result()), r4, r5);
2954   } else {
2955     Label true_value, done;
2956
2957     __ b(condition, &true_value);
2958
2959     __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
2960     __ b(&done);
2961
2962     __ bind(&true_value);
2963     __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
2964
2965     __ bind(&done);
2966   }
2967 }
2968
2969
2970 void LCodeGen::DoReturn(LReturn* instr) {
2971   if (FLAG_trace && info()->IsOptimizing()) {
2972     // Push the return value on the stack as the parameter.
2973     // Runtime::TraceExit returns its parameter in r3.  We're leaving the code
2974     // managed by the register allocator and tearing down the frame, it's
2975     // safe to write to the context register.
2976     __ push(r3);
2977     __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2978     __ CallRuntime(Runtime::kTraceExit, 1);
2979   }
2980   if (info()->saves_caller_doubles()) {
2981     RestoreCallerDoubles();
2982   }
2983   int no_frame_start = -1;
2984   if (instr->has_constant_parameter_count()) {
2985     int parameter_count = ToInteger32(instr->constant_parameter_count());
2986     int32_t sp_delta = (parameter_count + 1) * kPointerSize;
2987     if (NeedsEagerFrame()) {
2988       no_frame_start = masm_->LeaveFrame(StackFrame::JAVA_SCRIPT, sp_delta);
2989     } else if (sp_delta != 0) {
2990       __ addi(sp, sp, Operand(sp_delta));
2991     }
2992   } else {
2993     DCHECK(info()->IsStub());  // Functions would need to drop one more value.
2994     Register reg = ToRegister(instr->parameter_count());
2995     // The argument count parameter is a smi
2996     if (NeedsEagerFrame()) {
2997       no_frame_start = masm_->LeaveFrame(StackFrame::JAVA_SCRIPT);
2998     }
2999     __ SmiToPtrArrayOffset(r0, reg);
3000     __ add(sp, sp, r0);
3001   }
3002
3003   __ blr();
3004
3005   if (no_frame_start != -1) {
3006     info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
3007   }
3008 }
3009
3010
3011 template <class T>
3012 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
3013   Register vector_register = ToRegister(instr->temp_vector());
3014   Register slot_register = LoadDescriptor::SlotRegister();
3015   DCHECK(vector_register.is(LoadWithVectorDescriptor::VectorRegister()));
3016   DCHECK(slot_register.is(r3));
3017
3018   AllowDeferredHandleDereference vector_structure_check;
3019   Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
3020   __ Move(vector_register, vector);
3021   // No need to allocate this register.
3022   FeedbackVectorICSlot slot = instr->hydrogen()->slot();
3023   int index = vector->GetIndex(slot);
3024   __ LoadSmiLiteral(slot_register, Smi::FromInt(index));
3025 }
3026
3027
3028 template <class T>
3029 void LCodeGen::EmitVectorStoreICRegisters(T* instr) {
3030   Register vector_register = ToRegister(instr->temp_vector());
3031   Register slot_register = ToRegister(instr->temp_slot());
3032
3033   AllowDeferredHandleDereference vector_structure_check;
3034   Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
3035   __ Move(vector_register, vector);
3036   FeedbackVectorICSlot slot = instr->hydrogen()->slot();
3037   int index = vector->GetIndex(slot);
3038   __ LoadSmiLiteral(slot_register, Smi::FromInt(index));
3039 }
3040
3041
3042 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
3043   DCHECK(ToRegister(instr->context()).is(cp));
3044   DCHECK(ToRegister(instr->global_object())
3045              .is(LoadDescriptor::ReceiverRegister()));
3046   DCHECK(ToRegister(instr->result()).is(r3));
3047
3048   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
3049   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
3050   Handle<Code> ic =
3051       CodeFactory::LoadICInOptimizedCode(isolate(), instr->typeof_mode(),
3052                                          SLOPPY, PREMONOMORPHIC).code();
3053   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3054 }
3055
3056
3057 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3058   Register context = ToRegister(instr->context());
3059   Register result = ToRegister(instr->result());
3060   __ LoadP(result, ContextOperand(context, instr->slot_index()));
3061   if (instr->hydrogen()->RequiresHoleCheck()) {
3062     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3063     if (instr->hydrogen()->DeoptimizesOnHole()) {
3064       __ cmp(result, ip);
3065       DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3066     } else {
3067       if (CpuFeatures::IsSupported(ISELECT)) {
3068         Register scratch = scratch0();
3069         __ mov(scratch, Operand(factory()->undefined_value()));
3070         __ cmp(result, ip);
3071         __ isel(eq, result, scratch, result);
3072       } else {
3073         Label skip;
3074         __ cmp(result, ip);
3075         __ bne(&skip);
3076         __ mov(result, Operand(factory()->undefined_value()));
3077         __ bind(&skip);
3078       }
3079     }
3080   }
3081 }
3082
3083
3084 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3085   Register context = ToRegister(instr->context());
3086   Register value = ToRegister(instr->value());
3087   Register scratch = scratch0();
3088   MemOperand target = ContextOperand(context, instr->slot_index());
3089
3090   Label skip_assignment;
3091
3092   if (instr->hydrogen()->RequiresHoleCheck()) {
3093     __ LoadP(scratch, target);
3094     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3095     __ cmp(scratch, ip);
3096     if (instr->hydrogen()->DeoptimizesOnHole()) {
3097       DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3098     } else {
3099       __ bne(&skip_assignment);
3100     }
3101   }
3102
3103   __ StoreP(value, target, r0);
3104   if (instr->hydrogen()->NeedsWriteBarrier()) {
3105     SmiCheck check_needed = instr->hydrogen()->value()->type().IsHeapObject()
3106                                 ? OMIT_SMI_CHECK
3107                                 : INLINE_SMI_CHECK;
3108     __ RecordWriteContextSlot(context, target.offset(), value, scratch,
3109                               GetLinkRegisterState(), kSaveFPRegs,
3110                               EMIT_REMEMBERED_SET, check_needed);
3111   }
3112
3113   __ bind(&skip_assignment);
3114 }
3115
3116
3117 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
3118   HObjectAccess access = instr->hydrogen()->access();
3119   int offset = access.offset();
3120   Register object = ToRegister(instr->object());
3121
3122   if (access.IsExternalMemory()) {
3123     Register result = ToRegister(instr->result());
3124     MemOperand operand = MemOperand(object, offset);
3125     __ LoadRepresentation(result, operand, access.representation(), r0);
3126     return;
3127   }
3128
3129   if (instr->hydrogen()->representation().IsDouble()) {
3130     DCHECK(access.IsInobject());
3131     DoubleRegister result = ToDoubleRegister(instr->result());
3132     __ lfd(result, FieldMemOperand(object, offset));
3133     return;
3134   }
3135
3136   Register result = ToRegister(instr->result());
3137   if (!access.IsInobject()) {
3138     __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
3139     object = result;
3140   }
3141
3142   Representation representation = access.representation();
3143
3144 #if V8_TARGET_ARCH_PPC64
3145   // 64-bit Smi optimization
3146   if (representation.IsSmi() &&
3147       instr->hydrogen()->representation().IsInteger32()) {
3148     // Read int value directly from upper half of the smi.
3149     offset = SmiWordOffset(offset);
3150     representation = Representation::Integer32();
3151   }
3152 #endif
3153
3154   __ LoadRepresentation(result, FieldMemOperand(object, offset), representation,
3155                         r0);
3156 }
3157
3158
3159 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
3160   DCHECK(ToRegister(instr->context()).is(cp));
3161   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3162   DCHECK(ToRegister(instr->result()).is(r3));
3163
3164   // Name is always in r5.
3165   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
3166   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
3167   Handle<Code> ic =
3168       CodeFactory::LoadICInOptimizedCode(
3169           isolate(), NOT_INSIDE_TYPEOF, instr->hydrogen()->language_mode(),
3170           instr->hydrogen()->initialization_state()).code();
3171   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3172 }
3173
3174
3175 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
3176   Register scratch = scratch0();
3177   Register function = ToRegister(instr->function());
3178   Register result = ToRegister(instr->result());
3179
3180   // Get the prototype or initial map from the function.
3181   __ LoadP(result,
3182            FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3183
3184   // Check that the function has a prototype or an initial map.
3185   __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3186   __ cmp(result, ip);
3187   DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3188
3189   // If the function does not have an initial map, we're done.
3190   if (CpuFeatures::IsSupported(ISELECT)) {
3191     // Get the prototype from the initial map (optimistic).
3192     __ LoadP(ip, FieldMemOperand(result, Map::kPrototypeOffset));
3193     __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
3194     __ isel(eq, result, ip, result);
3195   } else {
3196     Label done;
3197     __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
3198     __ bne(&done);
3199
3200     // Get the prototype from the initial map.
3201     __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset));
3202
3203     // All done.
3204     __ bind(&done);
3205   }
3206 }
3207
3208
3209 void LCodeGen::DoLoadRoot(LLoadRoot* instr) {
3210   Register result = ToRegister(instr->result());
3211   __ LoadRoot(result, instr->index());
3212 }
3213
3214
3215 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
3216   Register arguments = ToRegister(instr->arguments());
3217   Register result = ToRegister(instr->result());
3218   // There are two words between the frame pointer and the last argument.
3219   // Subtracting from length accounts for one of them add one more.
3220   if (instr->length()->IsConstantOperand()) {
3221     int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
3222     if (instr->index()->IsConstantOperand()) {
3223       int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3224       int index = (const_length - const_index) + 1;
3225       __ LoadP(result, MemOperand(arguments, index * kPointerSize), r0);
3226     } else {
3227       Register index = ToRegister(instr->index());
3228       __ subfic(result, index, Operand(const_length + 1));
3229       __ ShiftLeftImm(result, result, Operand(kPointerSizeLog2));
3230       __ LoadPX(result, MemOperand(arguments, result));
3231     }
3232   } else if (instr->index()->IsConstantOperand()) {
3233     Register length = ToRegister(instr->length());
3234     int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3235     int loc = const_index - 1;
3236     if (loc != 0) {
3237       __ subi(result, length, Operand(loc));
3238       __ ShiftLeftImm(result, result, Operand(kPointerSizeLog2));
3239       __ LoadPX(result, MemOperand(arguments, result));
3240     } else {
3241       __ ShiftLeftImm(result, length, Operand(kPointerSizeLog2));
3242       __ LoadPX(result, MemOperand(arguments, result));
3243     }
3244   } else {
3245     Register length = ToRegister(instr->length());
3246     Register index = ToRegister(instr->index());
3247     __ sub(result, length, index);
3248     __ addi(result, result, Operand(1));
3249     __ ShiftLeftImm(result, result, Operand(kPointerSizeLog2));
3250     __ LoadPX(result, MemOperand(arguments, result));
3251   }
3252 }
3253
3254
3255 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
3256   Register external_pointer = ToRegister(instr->elements());
3257   Register key = no_reg;
3258   ElementsKind elements_kind = instr->elements_kind();
3259   bool key_is_constant = instr->key()->IsConstantOperand();
3260   int constant_key = 0;
3261   if (key_is_constant) {
3262     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
3263     if (constant_key & 0xF0000000) {
3264       Abort(kArrayIndexConstantValueTooBig);
3265     }
3266   } else {
3267     key = ToRegister(instr->key());
3268   }
3269   int element_size_shift = ElementsKindToShiftSize(elements_kind);
3270   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
3271   int base_offset = instr->base_offset();
3272
3273   if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
3274       elements_kind == FLOAT32_ELEMENTS ||
3275       elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
3276       elements_kind == FLOAT64_ELEMENTS) {
3277     DoubleRegister result = ToDoubleRegister(instr->result());
3278     if (key_is_constant) {
3279       __ Add(scratch0(), external_pointer, constant_key << element_size_shift,
3280              r0);
3281     } else {
3282       __ IndexToArrayOffset(r0, key, element_size_shift, key_is_smi);
3283       __ add(scratch0(), external_pointer, r0);
3284     }
3285     if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
3286         elements_kind == FLOAT32_ELEMENTS) {
3287       __ lfs(result, MemOperand(scratch0(), base_offset));
3288     } else {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
3289       __ lfd(result, MemOperand(scratch0(), base_offset));
3290     }
3291   } else {
3292     Register result = ToRegister(instr->result());
3293     MemOperand mem_operand =
3294         PrepareKeyedOperand(key, external_pointer, key_is_constant, key_is_smi,
3295                             constant_key, element_size_shift, base_offset);
3296     switch (elements_kind) {
3297       case EXTERNAL_INT8_ELEMENTS:
3298       case INT8_ELEMENTS:
3299         if (key_is_constant) {
3300           __ LoadByte(result, mem_operand, r0);
3301         } else {
3302           __ lbzx(result, mem_operand);
3303         }
3304         __ extsb(result, result);
3305         break;
3306       case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
3307       case EXTERNAL_UINT8_ELEMENTS:
3308       case UINT8_ELEMENTS:
3309       case UINT8_CLAMPED_ELEMENTS:
3310         if (key_is_constant) {
3311           __ LoadByte(result, mem_operand, r0);
3312         } else {
3313           __ lbzx(result, mem_operand);
3314         }
3315         break;
3316       case EXTERNAL_INT16_ELEMENTS:
3317       case INT16_ELEMENTS:
3318         if (key_is_constant) {
3319           __ LoadHalfWordArith(result, mem_operand, r0);
3320         } else {
3321           __ lhax(result, mem_operand);
3322         }
3323         break;
3324       case EXTERNAL_UINT16_ELEMENTS:
3325       case UINT16_ELEMENTS:
3326         if (key_is_constant) {
3327           __ LoadHalfWord(result, mem_operand, r0);
3328         } else {
3329           __ lhzx(result, mem_operand);
3330         }
3331         break;
3332       case EXTERNAL_INT32_ELEMENTS:
3333       case INT32_ELEMENTS:
3334         if (key_is_constant) {
3335           __ LoadWordArith(result, mem_operand, r0);
3336         } else {
3337           __ lwax(result, mem_operand);
3338         }
3339         break;
3340       case EXTERNAL_UINT32_ELEMENTS:
3341       case UINT32_ELEMENTS:
3342         if (key_is_constant) {
3343           __ LoadWord(result, mem_operand, r0);
3344         } else {
3345           __ lwzx(result, mem_operand);
3346         }
3347         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3348           __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
3349           __ cmplw(result, r0);
3350           DeoptimizeIf(ge, instr, Deoptimizer::kNegativeValue);
3351         }
3352         break;
3353       case FLOAT32_ELEMENTS:
3354       case FLOAT64_ELEMENTS:
3355       case EXTERNAL_FLOAT32_ELEMENTS:
3356       case EXTERNAL_FLOAT64_ELEMENTS:
3357       case FAST_HOLEY_DOUBLE_ELEMENTS:
3358       case FAST_HOLEY_ELEMENTS:
3359       case FAST_HOLEY_SMI_ELEMENTS:
3360       case FAST_DOUBLE_ELEMENTS:
3361       case FAST_ELEMENTS:
3362       case FAST_SMI_ELEMENTS:
3363       case DICTIONARY_ELEMENTS:
3364       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
3365       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
3366         UNREACHABLE();
3367         break;
3368     }
3369   }
3370 }
3371
3372
3373 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3374   Register elements = ToRegister(instr->elements());
3375   bool key_is_constant = instr->key()->IsConstantOperand();
3376   Register key = no_reg;
3377   DoubleRegister result = ToDoubleRegister(instr->result());
3378   Register scratch = scratch0();
3379
3380   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
3381   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
3382   int constant_key = 0;
3383   if (key_is_constant) {
3384     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
3385     if (constant_key & 0xF0000000) {
3386       Abort(kArrayIndexConstantValueTooBig);
3387     }
3388   } else {
3389     key = ToRegister(instr->key());
3390   }
3391
3392   int base_offset = instr->base_offset() + constant_key * kDoubleSize;
3393   if (!key_is_constant) {
3394     __ IndexToArrayOffset(r0, key, element_size_shift, key_is_smi);
3395     __ add(scratch, elements, r0);
3396     elements = scratch;
3397   }
3398   if (!is_int16(base_offset)) {
3399     __ Add(scratch, elements, base_offset, r0);
3400     base_offset = 0;
3401     elements = scratch;
3402   }
3403   __ lfd(result, MemOperand(elements, base_offset));
3404
3405   if (instr->hydrogen()->RequiresHoleCheck()) {
3406     if (is_int16(base_offset + Register::kExponentOffset)) {
3407       __ lwz(scratch,
3408              MemOperand(elements, base_offset + Register::kExponentOffset));
3409     } else {
3410       __ addi(scratch, elements, Operand(base_offset));
3411       __ lwz(scratch, MemOperand(scratch, Register::kExponentOffset));
3412     }
3413     __ Cmpi(scratch, Operand(kHoleNanUpper32), r0);
3414     DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3415   }
3416 }
3417
3418
3419 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3420   HLoadKeyed* hinstr = instr->hydrogen();
3421   Register elements = ToRegister(instr->elements());
3422   Register result = ToRegister(instr->result());
3423   Register scratch = scratch0();
3424   Register store_base = scratch;
3425   int offset = instr->base_offset();
3426
3427   if (instr->key()->IsConstantOperand()) {
3428     LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
3429     offset += ToInteger32(const_operand) * kPointerSize;
3430     store_base = elements;
3431   } else {
3432     Register key = ToRegister(instr->key());
3433     // Even though the HLoadKeyed instruction forces the input
3434     // representation for the key to be an integer, the input gets replaced
3435     // during bound check elimination with the index argument to the bounds
3436     // check, which can be tagged, so that case must be handled here, too.
3437     if (hinstr->key()->representation().IsSmi()) {
3438       __ SmiToPtrArrayOffset(r0, key);
3439     } else {
3440       __ ShiftLeftImm(r0, key, Operand(kPointerSizeLog2));
3441     }
3442     __ add(scratch, elements, r0);
3443   }
3444
3445   bool requires_hole_check = hinstr->RequiresHoleCheck();
3446   Representation representation = hinstr->representation();
3447
3448 #if V8_TARGET_ARCH_PPC64
3449   // 64-bit Smi optimization
3450   if (representation.IsInteger32() &&
3451       hinstr->elements_kind() == FAST_SMI_ELEMENTS) {
3452     DCHECK(!requires_hole_check);
3453     // Read int value directly from upper half of the smi.
3454     offset = SmiWordOffset(offset);
3455   }
3456 #endif
3457
3458   __ LoadRepresentation(result, MemOperand(store_base, offset), representation,
3459                         r0);
3460
3461   // Check for the hole value.
3462   if (requires_hole_check) {
3463     if (IsFastSmiElementsKind(hinstr->elements_kind())) {
3464       __ TestIfSmi(result, r0);
3465       DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
3466     } else {
3467       __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3468       __ cmp(result, scratch);
3469       DeoptimizeIf(eq, instr, Deoptimizer::kHole);
3470     }
3471   } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) {
3472     DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS);
3473     Label done;
3474     __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3475     __ cmp(result, scratch);
3476     __ bne(&done);
3477     if (info()->IsStub()) {
3478       // A stub can safely convert the hole to undefined only if the array
3479       // protector cell contains (Smi) Isolate::kArrayProtectorValid. Otherwise
3480       // it needs to bail out.
3481       __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
3482       __ LoadP(result, FieldMemOperand(result, Cell::kValueOffset));
3483       __ CmpSmiLiteral(result, Smi::FromInt(Isolate::kArrayProtectorValid), r0);
3484       DeoptimizeIf(ne, instr, Deoptimizer::kHole);
3485     }
3486     __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3487     __ bind(&done);
3488   }
3489 }
3490
3491
3492 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3493   if (instr->is_typed_elements()) {
3494     DoLoadKeyedExternalArray(instr);
3495   } else if (instr->hydrogen()->representation().IsDouble()) {
3496     DoLoadKeyedFixedDoubleArray(instr);
3497   } else {
3498     DoLoadKeyedFixedArray(instr);
3499   }
3500 }
3501
3502
3503 MemOperand LCodeGen::PrepareKeyedOperand(Register key, Register base,
3504                                          bool key_is_constant, bool key_is_smi,
3505                                          int constant_key,
3506                                          int element_size_shift,
3507                                          int base_offset) {
3508   Register scratch = scratch0();
3509
3510   if (key_is_constant) {
3511     return MemOperand(base, (constant_key << element_size_shift) + base_offset);
3512   }
3513
3514   bool needs_shift =
3515       (element_size_shift != (key_is_smi ? kSmiTagSize + kSmiShiftSize : 0));
3516
3517   if (!(base_offset || needs_shift)) {
3518     return MemOperand(base, key);
3519   }
3520
3521   if (needs_shift) {
3522     __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi);
3523     key = scratch;
3524   }
3525
3526   if (base_offset) {
3527     __ Add(scratch, key, base_offset, r0);
3528   }
3529
3530   return MemOperand(base, scratch);
3531 }
3532
3533
3534 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
3535   DCHECK(ToRegister(instr->context()).is(cp));
3536   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3537   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
3538
3539   if (instr->hydrogen()->HasVectorAndSlot()) {
3540     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
3541   }
3542
3543   Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
3544                         isolate(), instr->hydrogen()->language_mode(),
3545                         instr->hydrogen()->initialization_state()).code();
3546   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3547 }
3548
3549
3550 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
3551   Register scratch = scratch0();
3552   Register result = ToRegister(instr->result());
3553
3554   if (instr->hydrogen()->from_inlined()) {
3555     __ subi(result, sp, Operand(2 * kPointerSize));
3556   } else {
3557     // Check if the calling frame is an arguments adaptor frame.
3558     __ LoadP(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3559     __ LoadP(result,
3560              MemOperand(scratch, StandardFrameConstants::kContextOffset));
3561     __ CmpSmiLiteral(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
3562
3563     // Result is the frame pointer for the frame if not adapted and for the real
3564     // frame below the adaptor frame if adapted.
3565     if (CpuFeatures::IsSupported(ISELECT)) {
3566       __ isel(eq, result, scratch, fp);
3567     } else {
3568       Label done, adapted;
3569       __ beq(&adapted);
3570       __ mr(result, fp);
3571       __ b(&done);
3572
3573       __ bind(&adapted);
3574       __ mr(result, scratch);
3575       __ bind(&done);
3576     }
3577   }
3578 }
3579
3580
3581 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
3582   Register elem = ToRegister(instr->elements());
3583   Register result = ToRegister(instr->result());
3584
3585   Label done;
3586
3587   // If no arguments adaptor frame the number of arguments is fixed.
3588   __ cmp(fp, elem);
3589   __ mov(result, Operand(scope()->num_parameters()));
3590   __ beq(&done);
3591
3592   // Arguments adaptor frame present. Get argument length from there.
3593   __ LoadP(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3594   __ LoadP(result,
3595            MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
3596   __ SmiUntag(result);
3597
3598   // Argument length is in result register.
3599   __ bind(&done);
3600 }
3601
3602
3603 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3604   Register receiver = ToRegister(instr->receiver());
3605   Register function = ToRegister(instr->function());
3606   Register result = ToRegister(instr->result());
3607   Register scratch = scratch0();
3608
3609   // If the receiver is null or undefined, we have to pass the global
3610   // object as a receiver to normal functions. Values have to be
3611   // passed unchanged to builtins and strict-mode functions.
3612   Label global_object, result_in_receiver;
3613
3614   if (!instr->hydrogen()->known_function()) {
3615     // Do not transform the receiver to object for strict mode
3616     // functions.
3617     __ LoadP(scratch,
3618              FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
3619     __ lwz(scratch,
3620            FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
3621     __ TestBit(scratch,
3622 #if V8_TARGET_ARCH_PPC64
3623                SharedFunctionInfo::kStrictModeFunction,
3624 #else
3625                SharedFunctionInfo::kStrictModeFunction + kSmiTagSize,
3626 #endif
3627                r0);
3628     __ bne(&result_in_receiver, cr0);
3629
3630     // Do not transform the receiver to object for builtins.
3631     __ TestBit(scratch,
3632 #if V8_TARGET_ARCH_PPC64
3633                SharedFunctionInfo::kNative,
3634 #else
3635                SharedFunctionInfo::kNative + kSmiTagSize,
3636 #endif
3637                r0);
3638     __ bne(&result_in_receiver, cr0);
3639   }
3640
3641   // Normal function. Replace undefined or null with global receiver.
3642   __ LoadRoot(scratch, Heap::kNullValueRootIndex);
3643   __ cmp(receiver, scratch);
3644   __ beq(&global_object);
3645   __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
3646   __ cmp(receiver, scratch);
3647   __ beq(&global_object);
3648
3649   // Deoptimize if the receiver is not a JS object.
3650   __ TestIfSmi(receiver, r0);
3651   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
3652   __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
3653   DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject);
3654
3655   __ b(&result_in_receiver);
3656   __ bind(&global_object);
3657   __ LoadP(result, FieldMemOperand(function, JSFunction::kContextOffset));
3658   __ LoadP(result, ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
3659   __ LoadP(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset));
3660   if (result.is(receiver)) {
3661     __ bind(&result_in_receiver);
3662   } else {
3663     Label result_ok;
3664     __ b(&result_ok);
3665     __ bind(&result_in_receiver);
3666     __ mr(result, receiver);
3667     __ bind(&result_ok);
3668   }
3669 }
3670
3671
3672 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3673   Register receiver = ToRegister(instr->receiver());
3674   Register function = ToRegister(instr->function());
3675   Register length = ToRegister(instr->length());
3676   Register elements = ToRegister(instr->elements());
3677   Register scratch = scratch0();
3678   DCHECK(receiver.is(r3));  // Used for parameter count.
3679   DCHECK(function.is(r4));  // Required by InvokeFunction.
3680   DCHECK(ToRegister(instr->result()).is(r3));
3681
3682   // Copy the arguments to this function possibly from the
3683   // adaptor frame below it.
3684   const uint32_t kArgumentsLimit = 1 * KB;
3685   __ cmpli(length, Operand(kArgumentsLimit));
3686   DeoptimizeIf(gt, instr, Deoptimizer::kTooManyArguments);
3687
3688   // Push the receiver and use the register to keep the original
3689   // number of arguments.
3690   __ push(receiver);
3691   __ mr(receiver, length);
3692   // The arguments are at a one pointer size offset from elements.
3693   __ addi(elements, elements, Operand(1 * kPointerSize));
3694
3695   // Loop through the arguments pushing them onto the execution
3696   // stack.
3697   Label invoke, loop;
3698   // length is a small non-negative integer, due to the test above.
3699   __ cmpi(length, Operand::Zero());
3700   __ beq(&invoke);
3701   __ mtctr(length);
3702   __ bind(&loop);
3703   __ ShiftLeftImm(r0, length, Operand(kPointerSizeLog2));
3704   __ LoadPX(scratch, MemOperand(elements, r0));
3705   __ push(scratch);
3706   __ addi(length, length, Operand(-1));
3707   __ bdnz(&loop);
3708
3709   __ bind(&invoke);
3710   DCHECK(instr->HasPointerMap());
3711   LPointerMap* pointers = instr->pointer_map();
3712   SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
3713   // The number of arguments is stored in receiver which is r3, as expected
3714   // by InvokeFunction.
3715   ParameterCount actual(receiver);
3716   __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
3717 }
3718
3719
3720 void LCodeGen::DoPushArgument(LPushArgument* instr) {
3721   LOperand* argument = instr->value();
3722   if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
3723     Abort(kDoPushArgumentNotImplementedForDoubleType);
3724   } else {
3725     Register argument_reg = EmitLoadRegister(argument, ip);
3726     __ push(argument_reg);
3727   }
3728 }
3729
3730
3731 void LCodeGen::DoDrop(LDrop* instr) { __ Drop(instr->count()); }
3732
3733
3734 void LCodeGen::DoThisFunction(LThisFunction* instr) {
3735   Register result = ToRegister(instr->result());
3736   __ LoadP(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
3737 }
3738
3739
3740 void LCodeGen::DoContext(LContext* instr) {
3741   // If there is a non-return use, the context must be moved to a register.
3742   Register result = ToRegister(instr->result());
3743   if (info()->IsOptimizing()) {
3744     __ LoadP(result, MemOperand(fp, StandardFrameConstants::kContextOffset));
3745   } else {
3746     // If there is no frame, the context must be in cp.
3747     DCHECK(result.is(cp));
3748   }
3749 }
3750
3751
3752 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3753   DCHECK(ToRegister(instr->context()).is(cp));
3754   __ push(cp);  // The context is the first argument.
3755   __ Move(scratch0(), instr->hydrogen()->pairs());
3756   __ push(scratch0());
3757   __ LoadSmiLiteral(scratch0(), Smi::FromInt(instr->hydrogen()->flags()));
3758   __ push(scratch0());
3759   CallRuntime(Runtime::kDeclareGlobals, 3, instr);
3760 }
3761
3762
3763 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3764                                  int formal_parameter_count, int arity,
3765                                  LInstruction* instr) {
3766   bool dont_adapt_arguments =
3767       formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3768   bool can_invoke_directly =
3769       dont_adapt_arguments || formal_parameter_count == arity;
3770
3771   Register function_reg = r4;
3772
3773   LPointerMap* pointers = instr->pointer_map();
3774
3775   if (can_invoke_directly) {
3776     // Change context.
3777     __ LoadP(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset));
3778
3779     // Set r3 to arguments count if adaption is not needed. Assumes that r3
3780     // is available to write to at this point.
3781     if (dont_adapt_arguments) {
3782       __ mov(r3, Operand(arity));
3783     }
3784
3785     bool is_self_call = function.is_identical_to(info()->closure());
3786
3787     // Invoke function.
3788     if (is_self_call) {
3789       __ CallSelf();
3790     } else {
3791       __ LoadP(ip, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
3792       __ CallJSEntry(ip);
3793     }
3794
3795     // Set up deoptimization.
3796     RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3797   } else {
3798     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3799     ParameterCount count(arity);
3800     ParameterCount expected(formal_parameter_count);
3801     __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator);
3802   }
3803 }
3804
3805
3806 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3807   DCHECK(instr->context() != NULL);
3808   DCHECK(ToRegister(instr->context()).is(cp));
3809   Register input = ToRegister(instr->value());
3810   Register result = ToRegister(instr->result());
3811   Register scratch = scratch0();
3812
3813   // Deoptimize if not a heap number.
3814   __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
3815   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3816   __ cmp(scratch, ip);
3817   DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
3818
3819   Label done;
3820   Register exponent = scratch0();
3821   scratch = no_reg;
3822   __ lwz(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3823   // Check the sign of the argument. If the argument is positive, just
3824   // return it.
3825   __ cmpwi(exponent, Operand::Zero());
3826   // Move the input to the result if necessary.
3827   __ Move(result, input);
3828   __ bge(&done);
3829
3830   // Input is negative. Reverse its sign.
3831   // Preserve the value of all registers.
3832   {
3833     PushSafepointRegistersScope scope(this);
3834
3835     // Registers were saved at the safepoint, so we can use
3836     // many scratch registers.
3837     Register tmp1 = input.is(r4) ? r3 : r4;
3838     Register tmp2 = input.is(r5) ? r3 : r5;
3839     Register tmp3 = input.is(r6) ? r3 : r6;
3840     Register tmp4 = input.is(r7) ? r3 : r7;
3841
3842     // exponent: floating point exponent value.
3843
3844     Label allocated, slow;
3845     __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
3846     __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
3847     __ b(&allocated);
3848
3849     // Slow case: Call the runtime system to do the number allocation.
3850     __ bind(&slow);
3851
3852     CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr,
3853                             instr->context());
3854     // Set the pointer to the new heap number in tmp.
3855     if (!tmp1.is(r3)) __ mr(tmp1, r3);
3856     // Restore input_reg after call to runtime.
3857     __ LoadFromSafepointRegisterSlot(input, input);
3858     __ lwz(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3859
3860     __ bind(&allocated);
3861     // exponent: floating point exponent value.
3862     // tmp1: allocated heap number.
3863     STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
3864     __ clrlwi(exponent, exponent, Operand(1));  // clear sign bit
3865     __ stw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
3866     __ lwz(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
3867     __ stw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
3868
3869     __ StoreToSafepointRegisterSlot(tmp1, result);
3870   }
3871
3872   __ bind(&done);
3873 }
3874
3875
3876 void LCodeGen::EmitMathAbs(LMathAbs* instr) {
3877   Register input = ToRegister(instr->value());
3878   Register result = ToRegister(instr->result());
3879   Label done;
3880   __ cmpi(input, Operand::Zero());
3881   __ Move(result, input);
3882   __ bge(&done);
3883   __ li(r0, Operand::Zero());  // clear xer
3884   __ mtxer(r0);
3885   __ neg(result, result, SetOE, SetRC);
3886   // Deoptimize on overflow.
3887   DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
3888   __ bind(&done);
3889 }
3890
3891
3892 #if V8_TARGET_ARCH_PPC64
3893 void LCodeGen::EmitInteger32MathAbs(LMathAbs* instr) {
3894   Register input = ToRegister(instr->value());
3895   Register result = ToRegister(instr->result());
3896   Label done;
3897   __ cmpwi(input, Operand::Zero());
3898   __ Move(result, input);
3899   __ bge(&done);
3900
3901   // Deoptimize on overflow.
3902   __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
3903   __ cmpw(input, r0);
3904   DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
3905
3906   __ neg(result, result);
3907   __ bind(&done);
3908 }
3909 #endif
3910
3911
3912 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3913   // Class for deferred case.
3914   class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode {
3915    public:
3916     DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3917         : LDeferredCode(codegen), instr_(instr) {}
3918     void Generate() override {
3919       codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3920     }
3921     LInstruction* instr() override { return instr_; }
3922
3923    private:
3924     LMathAbs* instr_;
3925   };
3926
3927   Representation r = instr->hydrogen()->value()->representation();
3928   if (r.IsDouble()) {
3929     DoubleRegister input = ToDoubleRegister(instr->value());
3930     DoubleRegister result = ToDoubleRegister(instr->result());
3931     __ fabs(result, input);
3932 #if V8_TARGET_ARCH_PPC64
3933   } else if (r.IsInteger32()) {
3934     EmitInteger32MathAbs(instr);
3935   } else if (r.IsSmi()) {
3936 #else
3937   } else if (r.IsSmiOrInteger32()) {
3938 #endif
3939     EmitMathAbs(instr);
3940   } else {
3941     // Representation is tagged.
3942     DeferredMathAbsTaggedHeapNumber* deferred =
3943         new (zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
3944     Register input = ToRegister(instr->value());
3945     // Smi check.
3946     __ JumpIfNotSmi(input, deferred->entry());
3947     // If smi, handle it directly.
3948     EmitMathAbs(instr);
3949     __ bind(deferred->exit());
3950   }
3951 }
3952
3953
3954 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3955   DoubleRegister input = ToDoubleRegister(instr->value());
3956   Register result = ToRegister(instr->result());
3957   Register input_high = scratch0();
3958   Register scratch = ip;
3959   Label done, exact;
3960
3961   __ TryInt32Floor(result, input, input_high, scratch, double_scratch0(), &done,
3962                    &exact);
3963   DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN);
3964
3965   __ bind(&exact);
3966   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3967     // Test for -0.
3968     __ cmpi(result, Operand::Zero());
3969     __ bne(&done);
3970     __ cmpwi(input_high, Operand::Zero());
3971     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
3972   }
3973   __ bind(&done);
3974 }
3975
3976
3977 void LCodeGen::DoMathRound(LMathRound* instr) {
3978   DoubleRegister input = ToDoubleRegister(instr->value());
3979   Register result = ToRegister(instr->result());
3980   DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
3981   DoubleRegister input_plus_dot_five = double_scratch1;
3982   Register scratch1 = scratch0();
3983   Register scratch2 = ip;
3984   DoubleRegister dot_five = double_scratch0();
3985   Label convert, done;
3986
3987   __ LoadDoubleLiteral(dot_five, 0.5, r0);
3988   __ fabs(double_scratch1, input);
3989   __ fcmpu(double_scratch1, dot_five);
3990   DeoptimizeIf(unordered, instr, Deoptimizer::kLostPrecisionOrNaN);
3991   // If input is in [-0.5, -0], the result is -0.
3992   // If input is in [+0, +0.5[, the result is +0.
3993   // If the input is +0.5, the result is 1.
3994   __ bgt(&convert);  // Out of [-0.5, +0.5].
3995   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3996 #if V8_TARGET_ARCH_PPC64
3997     __ MovDoubleToInt64(scratch1, input);
3998 #else
3999     __ MovDoubleHighToInt(scratch1, input);
4000 #endif
4001     __ cmpi(scratch1, Operand::Zero());
4002     // [-0.5, -0].
4003     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
4004   }
4005   __ fcmpu(input, dot_five);
4006   if (CpuFeatures::IsSupported(ISELECT)) {
4007     __ li(result, Operand(1));
4008     __ isel(lt, result, r0, result);
4009     __ b(&done);
4010   } else {
4011     Label return_zero;
4012     __ bne(&return_zero);
4013     __ li(result, Operand(1));  // +0.5.
4014     __ b(&done);
4015     // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on
4016     // flag kBailoutOnMinusZero.
4017     __ bind(&return_zero);
4018     __ li(result, Operand::Zero());
4019     __ b(&done);
4020   }
4021
4022   __ bind(&convert);
4023   __ fadd(input_plus_dot_five, input, dot_five);
4024   // Reuse dot_five (double_scratch0) as we no longer need this value.
4025   __ TryInt32Floor(result, input_plus_dot_five, scratch1, scratch2,
4026                    double_scratch0(), &done, &done);
4027   DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN);
4028   __ bind(&done);
4029 }
4030
4031
4032 void LCodeGen::DoMathFround(LMathFround* instr) {
4033   DoubleRegister input_reg = ToDoubleRegister(instr->value());
4034   DoubleRegister output_reg = ToDoubleRegister(instr->result());
4035   __ frsp(output_reg, input_reg);
4036 }
4037
4038
4039 void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
4040   DoubleRegister input = ToDoubleRegister(instr->value());
4041   DoubleRegister result = ToDoubleRegister(instr->result());
4042   __ fsqrt(result, input);
4043 }
4044
4045
4046 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
4047   DoubleRegister input = ToDoubleRegister(instr->value());
4048   DoubleRegister result = ToDoubleRegister(instr->result());
4049   DoubleRegister temp = double_scratch0();
4050
4051   // Note that according to ECMA-262 15.8.2.13:
4052   // Math.pow(-Infinity, 0.5) == Infinity
4053   // Math.sqrt(-Infinity) == NaN
4054   Label skip, done;
4055
4056   __ LoadDoubleLiteral(temp, -V8_INFINITY, scratch0());
4057   __ fcmpu(input, temp);
4058   __ bne(&skip);
4059   __ fneg(result, temp);
4060   __ b(&done);
4061
4062   // Add +0 to convert -0 to +0.
4063   __ bind(&skip);
4064   __ fadd(result, input, kDoubleRegZero);
4065   __ fsqrt(result, result);
4066   __ bind(&done);
4067 }
4068
4069
4070 void LCodeGen::DoPower(LPower* instr) {
4071   Representation exponent_type = instr->hydrogen()->right()->representation();
4072 // Having marked this as a call, we can use any registers.
4073 // Just make sure that the input/output registers are the expected ones.
4074   Register tagged_exponent = MathPowTaggedDescriptor::exponent();
4075   DCHECK(!instr->right()->IsDoubleRegister() ||
4076          ToDoubleRegister(instr->right()).is(d2));
4077   DCHECK(!instr->right()->IsRegister() ||
4078          ToRegister(instr->right()).is(tagged_exponent));
4079   DCHECK(ToDoubleRegister(instr->left()).is(d1));
4080   DCHECK(ToDoubleRegister(instr->result()).is(d3));
4081
4082   if (exponent_type.IsSmi()) {
4083     MathPowStub stub(isolate(), MathPowStub::TAGGED);
4084     __ CallStub(&stub);
4085   } else if (exponent_type.IsTagged()) {
4086     Label no_deopt;
4087     __ JumpIfSmi(tagged_exponent, &no_deopt);
4088     DCHECK(!r10.is(tagged_exponent));
4089     __ LoadP(r10, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
4090     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
4091     __ cmp(r10, ip);
4092     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
4093     __ bind(&no_deopt);
4094     MathPowStub stub(isolate(), MathPowStub::TAGGED);
4095     __ CallStub(&stub);
4096   } else if (exponent_type.IsInteger32()) {
4097     MathPowStub stub(isolate(), MathPowStub::INTEGER);
4098     __ CallStub(&stub);
4099   } else {
4100     DCHECK(exponent_type.IsDouble());
4101     MathPowStub stub(isolate(), MathPowStub::DOUBLE);
4102     __ CallStub(&stub);
4103   }
4104 }
4105
4106
4107 void LCodeGen::DoMathExp(LMathExp* instr) {
4108   DoubleRegister input = ToDoubleRegister(instr->value());
4109   DoubleRegister result = ToDoubleRegister(instr->result());
4110   DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
4111   DoubleRegister double_scratch2 = double_scratch0();
4112   Register temp1 = ToRegister(instr->temp1());
4113   Register temp2 = ToRegister(instr->temp2());
4114
4115   MathExpGenerator::EmitMathExp(masm(), input, result, double_scratch1,
4116                                 double_scratch2, temp1, temp2, scratch0());
4117 }
4118
4119
4120 void LCodeGen::DoMathLog(LMathLog* instr) {
4121   __ PrepareCallCFunction(0, 1, scratch0());
4122   __ MovToFloatParameter(ToDoubleRegister(instr->value()));
4123   __ CallCFunction(ExternalReference::math_log_double_function(isolate()), 0,
4124                    1);
4125   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
4126 }
4127
4128
4129 void LCodeGen::DoMathClz32(LMathClz32* instr) {
4130   Register input = ToRegister(instr->value());
4131   Register result = ToRegister(instr->result());
4132   __ cntlzw_(result, input);
4133 }
4134
4135
4136 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
4137   DCHECK(ToRegister(instr->context()).is(cp));
4138   DCHECK(ToRegister(instr->function()).is(r4));
4139   DCHECK(instr->HasPointerMap());
4140
4141   Handle<JSFunction> known_function = instr->hydrogen()->known_function();
4142   if (known_function.is_null()) {
4143     LPointerMap* pointers = instr->pointer_map();
4144     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
4145     ParameterCount count(instr->arity());
4146     __ InvokeFunction(r4, count, CALL_FUNCTION, generator);
4147   } else {
4148     CallKnownFunction(known_function,
4149                       instr->hydrogen()->formal_parameter_count(),
4150                       instr->arity(), instr);
4151   }
4152 }
4153
4154
4155 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
4156   DCHECK(ToRegister(instr->result()).is(r3));
4157
4158   if (instr->hydrogen()->IsTailCall()) {
4159     if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL);
4160
4161     if (instr->target()->IsConstantOperand()) {
4162       LConstantOperand* target = LConstantOperand::cast(instr->target());
4163       Handle<Code> code = Handle<Code>::cast(ToHandle(target));
4164       __ Jump(code, RelocInfo::CODE_TARGET);
4165     } else {
4166       DCHECK(instr->target()->IsRegister());
4167       Register target = ToRegister(instr->target());
4168       __ addi(ip, target, Operand(Code::kHeaderSize - kHeapObjectTag));
4169       __ JumpToJSEntry(ip);
4170     }
4171   } else {
4172     LPointerMap* pointers = instr->pointer_map();
4173     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
4174
4175     if (instr->target()->IsConstantOperand()) {
4176       LConstantOperand* target = LConstantOperand::cast(instr->target());
4177       Handle<Code> code = Handle<Code>::cast(ToHandle(target));
4178       generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
4179       __ Call(code, RelocInfo::CODE_TARGET);
4180     } else {
4181       DCHECK(instr->target()->IsRegister());
4182       Register target = ToRegister(instr->target());
4183       generator.BeforeCall(__ CallSize(target));
4184       __ addi(ip, target, Operand(Code::kHeaderSize - kHeapObjectTag));
4185       __ CallJSEntry(ip);
4186     }
4187     generator.AfterCall();
4188   }
4189 }
4190
4191
4192 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
4193   DCHECK(ToRegister(instr->function()).is(r4));
4194   DCHECK(ToRegister(instr->result()).is(r3));
4195
4196   if (instr->hydrogen()->pass_argument_count()) {
4197     __ mov(r3, Operand(instr->arity()));
4198   }
4199
4200   // Change context.
4201   __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
4202
4203   bool is_self_call = false;
4204   if (instr->hydrogen()->function()->IsConstant()) {
4205     HConstant* fun_const = HConstant::cast(instr->hydrogen()->function());
4206     Handle<JSFunction> jsfun =
4207         Handle<JSFunction>::cast(fun_const->handle(isolate()));
4208     is_self_call = jsfun.is_identical_to(info()->closure());
4209   }
4210
4211   if (is_self_call) {
4212     __ CallSelf();
4213   } else {
4214     __ LoadP(ip, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
4215     __ CallJSEntry(ip);
4216   }
4217
4218   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
4219 }
4220
4221
4222 void LCodeGen::DoCallFunction(LCallFunction* instr) {
4223   DCHECK(ToRegister(instr->context()).is(cp));
4224   DCHECK(ToRegister(instr->function()).is(r4));
4225   DCHECK(ToRegister(instr->result()).is(r3));
4226
4227   int arity = instr->arity();
4228   CallFunctionFlags flags = instr->hydrogen()->function_flags();
4229   if (instr->hydrogen()->HasVectorAndSlot()) {
4230     Register slot_register = ToRegister(instr->temp_slot());
4231     Register vector_register = ToRegister(instr->temp_vector());
4232     DCHECK(slot_register.is(r6));
4233     DCHECK(vector_register.is(r5));
4234
4235     AllowDeferredHandleDereference vector_structure_check;
4236     Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
4237     int index = vector->GetIndex(instr->hydrogen()->slot());
4238
4239     __ Move(vector_register, vector);
4240     __ LoadSmiLiteral(slot_register, Smi::FromInt(index));
4241
4242     CallICState::CallType call_type =
4243         (flags & CALL_AS_METHOD) ? CallICState::METHOD : CallICState::FUNCTION;
4244
4245     Handle<Code> ic =
4246         CodeFactory::CallICInOptimizedCode(isolate(), arity, call_type).code();
4247     CallCode(ic, RelocInfo::CODE_TARGET, instr);
4248   } else {
4249     CallFunctionStub stub(isolate(), arity, flags);
4250     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4251   }
4252 }
4253
4254
4255 void LCodeGen::DoCallNew(LCallNew* instr) {
4256   DCHECK(ToRegister(instr->context()).is(cp));
4257   DCHECK(ToRegister(instr->constructor()).is(r4));
4258   DCHECK(ToRegister(instr->result()).is(r3));
4259
4260   __ mov(r3, Operand(instr->arity()));
4261   // No cell in r5 for construct type feedback in optimized code
4262   __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
4263   CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
4264   CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4265 }
4266
4267
4268 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4269   DCHECK(ToRegister(instr->context()).is(cp));
4270   DCHECK(ToRegister(instr->constructor()).is(r4));
4271   DCHECK(ToRegister(instr->result()).is(r3));
4272
4273   __ mov(r3, Operand(instr->arity()));
4274   if (instr->arity() == 1) {
4275     // We only need the allocation site for the case we have a length argument.
4276     // The case may bail out to the runtime, which will determine the correct
4277     // elements kind with the site.
4278     __ Move(r5, instr->hydrogen()->site());
4279   } else {
4280     __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
4281   }
4282   ElementsKind kind = instr->hydrogen()->elements_kind();
4283   AllocationSiteOverrideMode override_mode =
4284       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
4285           ? DISABLE_ALLOCATION_SITES
4286           : DONT_OVERRIDE;
4287
4288   if (instr->arity() == 0) {
4289     ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
4290     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4291   } else if (instr->arity() == 1) {
4292     Label done;
4293     if (IsFastPackedElementsKind(kind)) {
4294       Label packed_case;
4295       // We might need a change here
4296       // look at the first argument
4297       __ LoadP(r8, MemOperand(sp, 0));
4298       __ cmpi(r8, Operand::Zero());
4299       __ beq(&packed_case);
4300
4301       ElementsKind holey_kind = GetHoleyElementsKind(kind);
4302       ArraySingleArgumentConstructorStub stub(isolate(), holey_kind,
4303                                               override_mode);
4304       CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4305       __ b(&done);
4306       __ bind(&packed_case);
4307     }
4308
4309     ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
4310     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4311     __ bind(&done);
4312   } else {
4313     ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
4314     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4315   }
4316 }
4317
4318
4319 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
4320   CallRuntime(instr->function(), instr->arity(), instr);
4321 }
4322
4323
4324 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
4325   Register function = ToRegister(instr->function());
4326   Register code_object = ToRegister(instr->code_object());
4327   __ addi(code_object, code_object,
4328           Operand(Code::kHeaderSize - kHeapObjectTag));
4329   __ StoreP(code_object,
4330             FieldMemOperand(function, JSFunction::kCodeEntryOffset), r0);
4331 }
4332
4333
4334 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
4335   Register result = ToRegister(instr->result());
4336   Register base = ToRegister(instr->base_object());
4337   if (instr->offset()->IsConstantOperand()) {
4338     LConstantOperand* offset = LConstantOperand::cast(instr->offset());
4339     __ Add(result, base, ToInteger32(offset), r0);
4340   } else {
4341     Register offset = ToRegister(instr->offset());
4342     __ add(result, base, offset);
4343   }
4344 }
4345
4346
4347 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
4348   HStoreNamedField* hinstr = instr->hydrogen();
4349   Representation representation = instr->representation();
4350
4351   Register object = ToRegister(instr->object());
4352   Register scratch = scratch0();
4353   HObjectAccess access = hinstr->access();
4354   int offset = access.offset();
4355
4356   if (access.IsExternalMemory()) {
4357     Register value = ToRegister(instr->value());
4358     MemOperand operand = MemOperand(object, offset);
4359     __ StoreRepresentation(value, operand, representation, r0);
4360     return;
4361   }
4362
4363   __ AssertNotSmi(object);
4364
4365 #if V8_TARGET_ARCH_PPC64
4366   DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() ||
4367          IsInteger32(LConstantOperand::cast(instr->value())));
4368 #else
4369   DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() ||
4370          IsSmi(LConstantOperand::cast(instr->value())));
4371 #endif
4372   if (!FLAG_unbox_double_fields && representation.IsDouble()) {
4373     DCHECK(access.IsInobject());
4374     DCHECK(!hinstr->has_transition());
4375     DCHECK(!hinstr->NeedsWriteBarrier());
4376     DoubleRegister value = ToDoubleRegister(instr->value());
4377     __ stfd(value, FieldMemOperand(object, offset));
4378     return;
4379   }
4380
4381   if (hinstr->has_transition()) {
4382     Handle<Map> transition = hinstr->transition_map();
4383     AddDeprecationDependency(transition);
4384     __ mov(scratch, Operand(transition));
4385     __ StoreP(scratch, FieldMemOperand(object, HeapObject::kMapOffset), r0);
4386     if (hinstr->NeedsWriteBarrierForMap()) {
4387       Register temp = ToRegister(instr->temp());
4388       // Update the write barrier for the map field.
4389       __ RecordWriteForMap(object, scratch, temp, GetLinkRegisterState(),
4390                            kSaveFPRegs);
4391     }
4392   }
4393
4394   // Do the store.
4395   Register record_dest = object;
4396   Register record_value = no_reg;
4397   Register record_scratch = scratch;
4398 #if V8_TARGET_ARCH_PPC64
4399   if (FLAG_unbox_double_fields && representation.IsDouble()) {
4400     DCHECK(access.IsInobject());
4401     DoubleRegister value = ToDoubleRegister(instr->value());
4402     __ stfd(value, FieldMemOperand(object, offset));
4403     if (hinstr->NeedsWriteBarrier()) {
4404       record_value = ToRegister(instr->value());
4405     }
4406   } else {
4407     if (representation.IsSmi() &&
4408         hinstr->value()->representation().IsInteger32()) {
4409       DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
4410       // 64-bit Smi optimization
4411       // Store int value directly to upper half of the smi.
4412       offset = SmiWordOffset(offset);
4413       representation = Representation::Integer32();
4414     }
4415 #endif
4416     if (access.IsInobject()) {
4417       Register value = ToRegister(instr->value());
4418       MemOperand operand = FieldMemOperand(object, offset);
4419       __ StoreRepresentation(value, operand, representation, r0);
4420       record_value = value;
4421     } else {
4422       Register value = ToRegister(instr->value());
4423       __ LoadP(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
4424       MemOperand operand = FieldMemOperand(scratch, offset);
4425       __ StoreRepresentation(value, operand, representation, r0);
4426       record_dest = scratch;
4427       record_value = value;
4428       record_scratch = object;
4429     }
4430 #if V8_TARGET_ARCH_PPC64
4431   }
4432 #endif
4433
4434   if (hinstr->NeedsWriteBarrier()) {
4435     __ RecordWriteField(record_dest, offset, record_value, record_scratch,
4436                         GetLinkRegisterState(), kSaveFPRegs,
4437                         EMIT_REMEMBERED_SET, hinstr->SmiCheckForWriteBarrier(),
4438                         hinstr->PointersToHereCheckForValue());
4439   }
4440 }
4441
4442
4443 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4444   DCHECK(ToRegister(instr->context()).is(cp));
4445   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4446   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4447
4448   if (instr->hydrogen()->HasVectorAndSlot()) {
4449     EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
4450   }
4451
4452   __ mov(StoreDescriptor::NameRegister(), Operand(instr->name()));
4453   Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
4454                         isolate(), instr->language_mode(),
4455                         instr->hydrogen()->initialization_state()).code();
4456   CallCode(ic, RelocInfo::CODE_TARGET, instr);
4457 }
4458
4459
4460 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
4461   Representation representation = instr->hydrogen()->length()->representation();
4462   DCHECK(representation.Equals(instr->hydrogen()->index()->representation()));
4463   DCHECK(representation.IsSmiOrInteger32());
4464
4465   Condition cc = instr->hydrogen()->allow_equality() ? lt : le;
4466   if (instr->length()->IsConstantOperand()) {
4467     int32_t length = ToInteger32(LConstantOperand::cast(instr->length()));
4468     Register index = ToRegister(instr->index());
4469     if (representation.IsSmi()) {
4470       __ Cmpli(index, Operand(Smi::FromInt(length)), r0);
4471     } else {
4472       __ Cmplwi(index, Operand(length), r0);
4473     }
4474     cc = CommuteCondition(cc);
4475   } else if (instr->index()->IsConstantOperand()) {
4476     int32_t index = ToInteger32(LConstantOperand::cast(instr->index()));
4477     Register length = ToRegister(instr->length());
4478     if (representation.IsSmi()) {
4479       __ Cmpli(length, Operand(Smi::FromInt(index)), r0);
4480     } else {
4481       __ Cmplwi(length, Operand(index), r0);
4482     }
4483   } else {
4484     Register index = ToRegister(instr->index());
4485     Register length = ToRegister(instr->length());
4486     if (representation.IsSmi()) {
4487       __ cmpl(length, index);
4488     } else {
4489       __ cmplw(length, index);
4490     }
4491   }
4492   if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4493     Label done;
4494     __ b(NegateCondition(cc), &done);
4495     __ stop("eliminated bounds check failed");
4496     __ bind(&done);
4497   } else {
4498     DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds);
4499   }
4500 }
4501
4502
4503 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4504   Register external_pointer = ToRegister(instr->elements());
4505   Register key = no_reg;
4506   ElementsKind elements_kind = instr->elements_kind();
4507   bool key_is_constant = instr->key()->IsConstantOperand();
4508   int constant_key = 0;
4509   if (key_is_constant) {
4510     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
4511     if (constant_key & 0xF0000000) {
4512       Abort(kArrayIndexConstantValueTooBig);
4513     }
4514   } else {
4515     key = ToRegister(instr->key());
4516   }
4517   int element_size_shift = ElementsKindToShiftSize(elements_kind);
4518   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
4519   int base_offset = instr->base_offset();
4520
4521   if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
4522       elements_kind == FLOAT32_ELEMENTS ||
4523       elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
4524       elements_kind == FLOAT64_ELEMENTS) {
4525     Register address = scratch0();
4526     DoubleRegister value(ToDoubleRegister(instr->value()));
4527     if (key_is_constant) {
4528       if (constant_key != 0) {
4529         __ Add(address, external_pointer, constant_key << element_size_shift,
4530                r0);
4531       } else {
4532         address = external_pointer;
4533       }
4534     } else {
4535       __ IndexToArrayOffset(r0, key, element_size_shift, key_is_smi);
4536       __ add(address, external_pointer, r0);
4537     }
4538     if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
4539         elements_kind == FLOAT32_ELEMENTS) {
4540       __ frsp(double_scratch0(), value);
4541       __ stfs(double_scratch0(), MemOperand(address, base_offset));
4542     } else {  // Storing doubles, not floats.
4543       __ stfd(value, MemOperand(address, base_offset));
4544     }
4545   } else {
4546     Register value(ToRegister(instr->value()));
4547     MemOperand mem_operand =
4548         PrepareKeyedOperand(key, external_pointer, key_is_constant, key_is_smi,
4549                             constant_key, element_size_shift, base_offset);
4550     switch (elements_kind) {
4551       case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
4552       case EXTERNAL_INT8_ELEMENTS:
4553       case EXTERNAL_UINT8_ELEMENTS:
4554       case UINT8_ELEMENTS:
4555       case UINT8_CLAMPED_ELEMENTS:
4556       case INT8_ELEMENTS:
4557         if (key_is_constant) {
4558           __ StoreByte(value, mem_operand, r0);
4559         } else {
4560           __ stbx(value, mem_operand);
4561         }
4562         break;
4563       case EXTERNAL_INT16_ELEMENTS:
4564       case EXTERNAL_UINT16_ELEMENTS:
4565       case INT16_ELEMENTS:
4566       case UINT16_ELEMENTS:
4567         if (key_is_constant) {
4568           __ StoreHalfWord(value, mem_operand, r0);
4569         } else {
4570           __ sthx(value, mem_operand);
4571         }
4572         break;
4573       case EXTERNAL_INT32_ELEMENTS:
4574       case EXTERNAL_UINT32_ELEMENTS:
4575       case INT32_ELEMENTS:
4576       case UINT32_ELEMENTS:
4577         if (key_is_constant) {
4578           __ StoreWord(value, mem_operand, r0);
4579         } else {
4580           __ stwx(value, mem_operand);
4581         }
4582         break;
4583       case FLOAT32_ELEMENTS:
4584       case FLOAT64_ELEMENTS:
4585       case EXTERNAL_FLOAT32_ELEMENTS:
4586       case EXTERNAL_FLOAT64_ELEMENTS:
4587       case FAST_DOUBLE_ELEMENTS:
4588       case FAST_ELEMENTS:
4589       case FAST_SMI_ELEMENTS:
4590       case FAST_HOLEY_DOUBLE_ELEMENTS:
4591       case FAST_HOLEY_ELEMENTS:
4592       case FAST_HOLEY_SMI_ELEMENTS:
4593       case DICTIONARY_ELEMENTS:
4594       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
4595       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
4596         UNREACHABLE();
4597         break;
4598     }
4599   }
4600 }
4601
4602
4603 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4604   DoubleRegister value = ToDoubleRegister(instr->value());
4605   Register elements = ToRegister(instr->elements());
4606   Register key = no_reg;
4607   Register scratch = scratch0();
4608   DoubleRegister double_scratch = double_scratch0();
4609   bool key_is_constant = instr->key()->IsConstantOperand();
4610   int constant_key = 0;
4611
4612   // Calculate the effective address of the slot in the array to store the
4613   // double value.
4614   if (key_is_constant) {
4615     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
4616     if (constant_key & 0xF0000000) {
4617       Abort(kArrayIndexConstantValueTooBig);
4618     }
4619   } else {
4620     key = ToRegister(instr->key());
4621   }
4622   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
4623   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
4624   int base_offset = instr->base_offset() + constant_key * kDoubleSize;
4625   if (!key_is_constant) {
4626     __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi);
4627     __ add(scratch, elements, scratch);
4628     elements = scratch;
4629   }
4630   if (!is_int16(base_offset)) {
4631     __ Add(scratch, elements, base_offset, r0);
4632     base_offset = 0;
4633     elements = scratch;
4634   }
4635
4636   if (instr->NeedsCanonicalization()) {
4637     // Turn potential sNaN value into qNaN.
4638     __ CanonicalizeNaN(double_scratch, value);
4639     __ stfd(double_scratch, MemOperand(elements, base_offset));
4640   } else {
4641     __ stfd(value, MemOperand(elements, base_offset));
4642   }
4643 }
4644
4645
4646 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4647   HStoreKeyed* hinstr = instr->hydrogen();
4648   Register value = ToRegister(instr->value());
4649   Register elements = ToRegister(instr->elements());
4650   Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
4651   Register scratch = scratch0();
4652   Register store_base = scratch;
4653   int offset = instr->base_offset();
4654
4655   // Do the store.
4656   if (instr->key()->IsConstantOperand()) {
4657     DCHECK(!hinstr->NeedsWriteBarrier());
4658     LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
4659     offset += ToInteger32(const_operand) * kPointerSize;
4660     store_base = elements;
4661   } else {
4662     // Even though the HLoadKeyed instruction forces the input
4663     // representation for the key to be an integer, the input gets replaced
4664     // during bound check elimination with the index argument to the bounds
4665     // check, which can be tagged, so that case must be handled here, too.
4666     if (hinstr->key()->representation().IsSmi()) {
4667       __ SmiToPtrArrayOffset(scratch, key);
4668     } else {
4669       __ ShiftLeftImm(scratch, key, Operand(kPointerSizeLog2));
4670     }
4671     __ add(scratch, elements, scratch);
4672   }
4673
4674   Representation representation = hinstr->value()->representation();
4675
4676 #if V8_TARGET_ARCH_PPC64
4677   // 64-bit Smi optimization
4678   if (representation.IsInteger32()) {
4679     DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
4680     DCHECK(hinstr->elements_kind() == FAST_SMI_ELEMENTS);
4681     // Store int value directly to upper half of the smi.
4682     offset = SmiWordOffset(offset);
4683   }
4684 #endif
4685
4686   __ StoreRepresentation(value, MemOperand(store_base, offset), representation,
4687                          r0);
4688
4689   if (hinstr->NeedsWriteBarrier()) {
4690     SmiCheck check_needed = hinstr->value()->type().IsHeapObject()
4691                                 ? OMIT_SMI_CHECK
4692                                 : INLINE_SMI_CHECK;
4693     // Compute address of modified element and store it into key register.
4694     __ Add(key, store_base, offset, r0);
4695     __ RecordWrite(elements, key, value, GetLinkRegisterState(), kSaveFPRegs,
4696                    EMIT_REMEMBERED_SET, check_needed,
4697                    hinstr->PointersToHereCheckForValue());
4698   }
4699 }
4700
4701
4702 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4703   // By cases: external, fast double
4704   if (instr->is_typed_elements()) {
4705     DoStoreKeyedExternalArray(instr);
4706   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
4707     DoStoreKeyedFixedDoubleArray(instr);
4708   } else {
4709     DoStoreKeyedFixedArray(instr);
4710   }
4711 }
4712
4713
4714 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4715   DCHECK(ToRegister(instr->context()).is(cp));
4716   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4717   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
4718   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4719
4720   if (instr->hydrogen()->HasVectorAndSlot()) {
4721     EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
4722   }
4723
4724   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
4725                         isolate(), instr->language_mode(),
4726                         instr->hydrogen()->initialization_state()).code();
4727   CallCode(ic, RelocInfo::CODE_TARGET, instr);
4728 }
4729
4730
4731 void LCodeGen::DoMaybeGrowElements(LMaybeGrowElements* instr) {
4732   class DeferredMaybeGrowElements final : public LDeferredCode {
4733    public:
4734     DeferredMaybeGrowElements(LCodeGen* codegen, LMaybeGrowElements* instr)
4735         : LDeferredCode(codegen), instr_(instr) {}
4736     void Generate() override { codegen()->DoDeferredMaybeGrowElements(instr_); }
4737     LInstruction* instr() override { return instr_; }
4738
4739    private:
4740     LMaybeGrowElements* instr_;
4741   };
4742
4743   Register result = r3;
4744   DeferredMaybeGrowElements* deferred =
4745       new (zone()) DeferredMaybeGrowElements(this, instr);
4746   LOperand* key = instr->key();
4747   LOperand* current_capacity = instr->current_capacity();
4748
4749   DCHECK(instr->hydrogen()->key()->representation().IsInteger32());
4750   DCHECK(instr->hydrogen()->current_capacity()->representation().IsInteger32());
4751   DCHECK(key->IsConstantOperand() || key->IsRegister());
4752   DCHECK(current_capacity->IsConstantOperand() ||
4753          current_capacity->IsRegister());
4754
4755   if (key->IsConstantOperand() && current_capacity->IsConstantOperand()) {
4756     int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
4757     int32_t constant_capacity =
4758         ToInteger32(LConstantOperand::cast(current_capacity));
4759     if (constant_key >= constant_capacity) {
4760       // Deferred case.
4761       __ b(deferred->entry());
4762     }
4763   } else if (key->IsConstantOperand()) {
4764     int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
4765     __ Cmpwi(ToRegister(current_capacity), Operand(constant_key), r0);
4766     __ ble(deferred->entry());
4767   } else if (current_capacity->IsConstantOperand()) {
4768     int32_t constant_capacity =
4769         ToInteger32(LConstantOperand::cast(current_capacity));
4770     __ Cmpwi(ToRegister(key), Operand(constant_capacity), r0);
4771     __ bge(deferred->entry());
4772   } else {
4773     __ cmpw(ToRegister(key), ToRegister(current_capacity));
4774     __ bge(deferred->entry());
4775   }
4776
4777   if (instr->elements()->IsRegister()) {
4778     __ Move(result, ToRegister(instr->elements()));
4779   } else {
4780     __ LoadP(result, ToMemOperand(instr->elements()));
4781   }
4782
4783   __ bind(deferred->exit());
4784 }
4785
4786
4787 void LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) {
4788   // TODO(3095996): Get rid of this. For now, we need to make the
4789   // result register contain a valid pointer because it is already
4790   // contained in the register pointer map.
4791   Register result = r3;
4792   __ li(result, Operand::Zero());
4793
4794   // We have to call a stub.
4795   {
4796     PushSafepointRegistersScope scope(this);
4797     if (instr->object()->IsRegister()) {
4798       __ Move(result, ToRegister(instr->object()));
4799     } else {
4800       __ LoadP(result, ToMemOperand(instr->object()));
4801     }
4802
4803     LOperand* key = instr->key();
4804     if (key->IsConstantOperand()) {
4805       __ LoadSmiLiteral(r6, ToSmi(LConstantOperand::cast(key)));
4806     } else {
4807       __ SmiTag(r6, ToRegister(key));
4808     }
4809
4810     GrowArrayElementsStub stub(isolate(), instr->hydrogen()->is_js_array(),
4811                                instr->hydrogen()->kind());
4812     __ CallStub(&stub);
4813     RecordSafepointWithLazyDeopt(
4814         instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4815     __ StoreToSafepointRegisterSlot(result, result);
4816   }
4817
4818   // Deopt on smi, which means the elements array changed to dictionary mode.
4819   __ TestIfSmi(result, r0);
4820   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
4821 }
4822
4823
4824 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4825   Register object_reg = ToRegister(instr->object());
4826   Register scratch = scratch0();
4827
4828   Handle<Map> from_map = instr->original_map();
4829   Handle<Map> to_map = instr->transitioned_map();
4830   ElementsKind from_kind = instr->from_kind();
4831   ElementsKind to_kind = instr->to_kind();
4832
4833   Label not_applicable;
4834   __ LoadP(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
4835   __ Cmpi(scratch, Operand(from_map), r0);
4836   __ bne(&not_applicable);
4837
4838   if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
4839     Register new_map_reg = ToRegister(instr->new_map_temp());
4840     __ mov(new_map_reg, Operand(to_map));
4841     __ StoreP(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset),
4842               r0);
4843     // Write barrier.
4844     __ RecordWriteForMap(object_reg, new_map_reg, scratch,
4845                          GetLinkRegisterState(), kDontSaveFPRegs);
4846   } else {
4847     DCHECK(ToRegister(instr->context()).is(cp));
4848     DCHECK(object_reg.is(r3));
4849     PushSafepointRegistersScope scope(this);
4850     __ Move(r4, to_map);
4851     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
4852     TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
4853     __ CallStub(&stub);
4854     RecordSafepointWithRegisters(instr->pointer_map(), 0,
4855                                  Safepoint::kLazyDeopt);
4856   }
4857   __ bind(&not_applicable);
4858 }
4859
4860
4861 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4862   Register object = ToRegister(instr->object());
4863   Register temp = ToRegister(instr->temp());
4864   Label no_memento_found;
4865   __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4866   DeoptimizeIf(eq, instr, Deoptimizer::kMementoFound);
4867   __ bind(&no_memento_found);
4868 }
4869
4870
4871 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4872   DCHECK(ToRegister(instr->context()).is(cp));
4873   DCHECK(ToRegister(instr->left()).is(r4));
4874   DCHECK(ToRegister(instr->right()).is(r3));
4875   StringAddStub stub(isolate(), instr->hydrogen()->flags(),
4876                      instr->hydrogen()->pretenure_flag());
4877   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4878 }
4879
4880
4881 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4882   class DeferredStringCharCodeAt final : public LDeferredCode {
4883    public:
4884     DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
4885         : LDeferredCode(codegen), instr_(instr) {}
4886     void Generate() override { codegen()->DoDeferredStringCharCodeAt(instr_); }
4887     LInstruction* instr() override { return instr_; }
4888
4889    private:
4890     LStringCharCodeAt* instr_;
4891   };
4892
4893   DeferredStringCharCodeAt* deferred =
4894       new (zone()) DeferredStringCharCodeAt(this, instr);
4895
4896   StringCharLoadGenerator::Generate(
4897       masm(), ToRegister(instr->string()), ToRegister(instr->index()),
4898       ToRegister(instr->result()), deferred->entry());
4899   __ bind(deferred->exit());
4900 }
4901
4902
4903 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
4904   Register string = ToRegister(instr->string());
4905   Register result = ToRegister(instr->result());
4906   Register scratch = scratch0();
4907
4908   // TODO(3095996): Get rid of this. For now, we need to make the
4909   // result register contain a valid pointer because it is already
4910   // contained in the register pointer map.
4911   __ li(result, Operand::Zero());
4912
4913   PushSafepointRegistersScope scope(this);
4914   __ push(string);
4915   // Push the index as a smi. This is safe because of the checks in
4916   // DoStringCharCodeAt above.
4917   if (instr->index()->IsConstantOperand()) {
4918     int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
4919     __ LoadSmiLiteral(scratch, Smi::FromInt(const_index));
4920     __ push(scratch);
4921   } else {
4922     Register index = ToRegister(instr->index());
4923     __ SmiTag(index);
4924     __ push(index);
4925   }
4926   CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2, instr,
4927                           instr->context());
4928   __ AssertSmi(r3);
4929   __ SmiUntag(r3);
4930   __ StoreToSafepointRegisterSlot(r3, result);
4931 }
4932
4933
4934 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4935   class DeferredStringCharFromCode final : public LDeferredCode {
4936    public:
4937     DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
4938         : LDeferredCode(codegen), instr_(instr) {}
4939     void Generate() override {
4940       codegen()->DoDeferredStringCharFromCode(instr_);
4941     }
4942     LInstruction* instr() override { return instr_; }
4943
4944    private:
4945     LStringCharFromCode* instr_;
4946   };
4947
4948   DeferredStringCharFromCode* deferred =
4949       new (zone()) DeferredStringCharFromCode(this, instr);
4950
4951   DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
4952   Register char_code = ToRegister(instr->char_code());
4953   Register result = ToRegister(instr->result());
4954   DCHECK(!char_code.is(result));
4955
4956   __ cmpli(char_code, Operand(String::kMaxOneByteCharCode));
4957   __ bgt(deferred->entry());
4958   __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
4959   __ ShiftLeftImm(r0, char_code, Operand(kPointerSizeLog2));
4960   __ add(result, result, r0);
4961   __ LoadP(result, FieldMemOperand(result, FixedArray::kHeaderSize));
4962   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
4963   __ cmp(result, ip);
4964   __ beq(deferred->entry());
4965   __ bind(deferred->exit());
4966 }
4967
4968
4969 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4970   Register char_code = ToRegister(instr->char_code());
4971   Register result = ToRegister(instr->result());
4972
4973   // TODO(3095996): Get rid of this. For now, we need to make the
4974   // result register contain a valid pointer because it is already
4975   // contained in the register pointer map.
4976   __ li(result, Operand::Zero());
4977
4978   PushSafepointRegistersScope scope(this);
4979   __ SmiTag(char_code);
4980   __ push(char_code);
4981   CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
4982   __ StoreToSafepointRegisterSlot(r3, result);
4983 }
4984
4985
4986 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4987   LOperand* input = instr->value();
4988   DCHECK(input->IsRegister() || input->IsStackSlot());
4989   LOperand* output = instr->result();
4990   DCHECK(output->IsDoubleRegister());
4991   if (input->IsStackSlot()) {
4992     Register scratch = scratch0();
4993     __ LoadP(scratch, ToMemOperand(input));
4994     __ ConvertIntToDouble(scratch, ToDoubleRegister(output));
4995   } else {
4996     __ ConvertIntToDouble(ToRegister(input), ToDoubleRegister(output));
4997   }
4998 }
4999
5000
5001 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
5002   LOperand* input = instr->value();
5003   LOperand* output = instr->result();
5004   __ ConvertUnsignedIntToDouble(ToRegister(input), ToDoubleRegister(output));
5005 }
5006
5007
5008 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
5009   class DeferredNumberTagI final : public LDeferredCode {
5010    public:
5011     DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
5012         : LDeferredCode(codegen), instr_(instr) {}
5013     void Generate() override {
5014       codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(),
5015                                        instr_->temp2(), SIGNED_INT32);
5016     }
5017     LInstruction* instr() override { return instr_; }
5018
5019    private:
5020     LNumberTagI* instr_;
5021   };
5022
5023   Register src = ToRegister(instr->value());
5024   Register dst = ToRegister(instr->result());
5025
5026   DeferredNumberTagI* deferred = new (zone()) DeferredNumberTagI(this, instr);
5027 #if V8_TARGET_ARCH_PPC64
5028   __ SmiTag(dst, src);
5029 #else
5030   __ SmiTagCheckOverflow(dst, src, r0);
5031   __ BranchOnOverflow(deferred->entry());
5032 #endif
5033   __ bind(deferred->exit());
5034 }
5035
5036
5037 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
5038   class DeferredNumberTagU final : public LDeferredCode {
5039    public:
5040     DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
5041         : LDeferredCode(codegen), instr_(instr) {}
5042     void Generate() override {
5043       codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(),
5044                                        instr_->temp2(), UNSIGNED_INT32);
5045     }
5046     LInstruction* instr() override { return instr_; }
5047
5048    private:
5049     LNumberTagU* instr_;
5050   };
5051
5052   Register input = ToRegister(instr->value());
5053   Register result = ToRegister(instr->result());
5054
5055   DeferredNumberTagU* deferred = new (zone()) DeferredNumberTagU(this, instr);
5056   __ Cmpli(input, Operand(Smi::kMaxValue), r0);
5057   __ bgt(deferred->entry());
5058   __ SmiTag(result, input);
5059   __ bind(deferred->exit());
5060 }
5061
5062
5063 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, LOperand* value,
5064                                      LOperand* temp1, LOperand* temp2,
5065                                      IntegerSignedness signedness) {
5066   Label done, slow;
5067   Register src = ToRegister(value);
5068   Register dst = ToRegister(instr->result());
5069   Register tmp1 = scratch0();
5070   Register tmp2 = ToRegister(temp1);
5071   Register tmp3 = ToRegister(temp2);
5072   DoubleRegister dbl_scratch = double_scratch0();
5073
5074   if (signedness == SIGNED_INT32) {
5075     // There was overflow, so bits 30 and 31 of the original integer
5076     // disagree. Try to allocate a heap number in new space and store
5077     // the value in there. If that fails, call the runtime system.
5078     if (dst.is(src)) {
5079       __ SmiUntag(src, dst);
5080       __ xoris(src, src, Operand(HeapNumber::kSignMask >> 16));
5081     }
5082     __ ConvertIntToDouble(src, dbl_scratch);
5083   } else {
5084     __ ConvertUnsignedIntToDouble(src, dbl_scratch);
5085   }
5086
5087   if (FLAG_inline_new) {
5088     __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
5089     __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow);
5090     __ b(&done);
5091   }
5092
5093   // Slow case: Call the runtime system to do the number allocation.
5094   __ bind(&slow);
5095   {
5096     // TODO(3095996): Put a valid pointer value in the stack slot where the
5097     // result register is stored, as this register is in the pointer map, but
5098     // contains an integer value.
5099     __ li(dst, Operand::Zero());
5100
5101     // Preserve the value of all registers.
5102     PushSafepointRegistersScope scope(this);
5103
5104     // NumberTagI and NumberTagD use the context from the frame, rather than
5105     // the environment's HContext or HInlinedContext value.
5106     // They only call Runtime::kAllocateHeapNumber.
5107     // The corresponding HChange instructions are added in a phase that does
5108     // not have easy access to the local context.
5109     __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
5110     __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
5111     RecordSafepointWithRegisters(instr->pointer_map(), 0,
5112                                  Safepoint::kNoLazyDeopt);
5113     __ StoreToSafepointRegisterSlot(r3, dst);
5114   }
5115
5116   // Done. Put the value in dbl_scratch into the value of the allocated heap
5117   // number.
5118   __ bind(&done);
5119   __ stfd(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
5120 }
5121
5122
5123 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
5124   class DeferredNumberTagD final : public LDeferredCode {
5125    public:
5126     DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
5127         : LDeferredCode(codegen), instr_(instr) {}
5128     void Generate() override { codegen()->DoDeferredNumberTagD(instr_); }
5129     LInstruction* instr() override { return instr_; }
5130
5131    private:
5132     LNumberTagD* instr_;
5133   };
5134
5135   DoubleRegister input_reg = ToDoubleRegister(instr->value());
5136   Register scratch = scratch0();
5137   Register reg = ToRegister(instr->result());
5138   Register temp1 = ToRegister(instr->temp());
5139   Register temp2 = ToRegister(instr->temp2());
5140
5141   DeferredNumberTagD* deferred = new (zone()) DeferredNumberTagD(this, instr);
5142   if (FLAG_inline_new) {
5143     __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
5144     __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
5145   } else {
5146     __ b(deferred->entry());
5147   }
5148   __ bind(deferred->exit());
5149   __ stfd(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset));
5150 }
5151
5152
5153 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
5154   // TODO(3095996): Get rid of this. For now, we need to make the
5155   // result register contain a valid pointer because it is already
5156   // contained in the register pointer map.
5157   Register reg = ToRegister(instr->result());
5158   __ li(reg, Operand::Zero());
5159
5160   PushSafepointRegistersScope scope(this);
5161   // NumberTagI and NumberTagD use the context from the frame, rather than
5162   // the environment's HContext or HInlinedContext value.
5163   // They only call Runtime::kAllocateHeapNumber.
5164   // The corresponding HChange instructions are added in a phase that does
5165   // not have easy access to the local context.
5166   __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
5167   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
5168   RecordSafepointWithRegisters(instr->pointer_map(), 0,
5169                                Safepoint::kNoLazyDeopt);
5170   __ StoreToSafepointRegisterSlot(r3, reg);
5171 }
5172
5173
5174 void LCodeGen::DoSmiTag(LSmiTag* instr) {
5175   HChange* hchange = instr->hydrogen();
5176   Register input = ToRegister(instr->value());
5177   Register output = ToRegister(instr->result());
5178   if (hchange->CheckFlag(HValue::kCanOverflow) &&
5179       hchange->value()->CheckFlag(HValue::kUint32)) {
5180     __ TestUnsignedSmiCandidate(input, r0);
5181     DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, cr0);
5182   }
5183 #if !V8_TARGET_ARCH_PPC64
5184   if (hchange->CheckFlag(HValue::kCanOverflow) &&
5185       !hchange->value()->CheckFlag(HValue::kUint32)) {
5186     __ SmiTagCheckOverflow(output, input, r0);
5187     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
5188   } else {
5189 #endif
5190     __ SmiTag(output, input);
5191 #if !V8_TARGET_ARCH_PPC64
5192   }
5193 #endif
5194 }
5195
5196
5197 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
5198   Register scratch = scratch0();
5199   Register input = ToRegister(instr->value());
5200   Register result = ToRegister(instr->result());
5201   if (instr->needs_check()) {
5202     // If the input is a HeapObject, value of scratch won't be zero.
5203     __ andi(scratch, input, Operand(kHeapObjectTag));
5204     __ SmiUntag(result, input);
5205     DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
5206   } else {
5207     __ SmiUntag(result, input);
5208   }
5209 }
5210
5211
5212 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
5213                                 DoubleRegister result_reg,
5214                                 NumberUntagDMode mode) {
5215   bool can_convert_undefined_to_nan =
5216       instr->hydrogen()->can_convert_undefined_to_nan();
5217   bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
5218
5219   Register scratch = scratch0();
5220   DCHECK(!result_reg.is(double_scratch0()));
5221
5222   Label convert, load_smi, done;
5223
5224   if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5225     // Smi check.
5226     __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
5227
5228     // Heap number map check.
5229     __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5230     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
5231     __ cmp(scratch, ip);
5232     if (can_convert_undefined_to_nan) {
5233       __ bne(&convert);
5234     } else {
5235       DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
5236     }
5237     // load heap number
5238     __ lfd(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5239     if (deoptimize_on_minus_zero) {
5240 #if V8_TARGET_ARCH_PPC64
5241       __ MovDoubleToInt64(scratch, result_reg);
5242       // rotate left by one for simple compare.
5243       __ rldicl(scratch, scratch, 1, 0);
5244       __ cmpi(scratch, Operand(1));
5245 #else
5246       __ MovDoubleToInt64(scratch, ip, result_reg);
5247       __ cmpi(ip, Operand::Zero());
5248       __ bne(&done);
5249       __ Cmpi(scratch, Operand(HeapNumber::kSignMask), r0);
5250 #endif
5251       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
5252     }
5253     __ b(&done);
5254     if (can_convert_undefined_to_nan) {
5255       __ bind(&convert);
5256       // Convert undefined (and hole) to NaN.
5257       __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5258       __ cmp(input_reg, ip);
5259       DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined);
5260       __ LoadRoot(scratch, Heap::kNanValueRootIndex);
5261       __ lfd(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
5262       __ b(&done);
5263     }
5264   } else {
5265     __ SmiUntag(scratch, input_reg);
5266     DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
5267   }
5268   // Smi to double register conversion
5269   __ bind(&load_smi);
5270   // scratch: untagged value of input_reg
5271   __ ConvertIntToDouble(scratch, result_reg);
5272   __ bind(&done);
5273 }
5274
5275
5276 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
5277   Register input_reg = ToRegister(instr->value());
5278   Register scratch1 = scratch0();
5279   Register scratch2 = ToRegister(instr->temp());
5280   DoubleRegister double_scratch = double_scratch0();
5281   DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2());
5282
5283   DCHECK(!scratch1.is(input_reg) && !scratch1.is(scratch2));
5284   DCHECK(!scratch2.is(input_reg) && !scratch2.is(scratch1));
5285
5286   Label done;
5287
5288   // Heap number map check.
5289   __ LoadP(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5290   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
5291   __ cmp(scratch1, ip);
5292
5293   if (instr->truncating()) {
5294     // Performs a truncating conversion of a floating point number as used by
5295     // the JS bitwise operations.
5296     Label no_heap_number, check_bools, check_false;
5297     __ bne(&no_heap_number);
5298     __ mr(scratch2, input_reg);
5299     __ TruncateHeapNumberToI(input_reg, scratch2);
5300     __ b(&done);
5301
5302     // Check for Oddballs. Undefined/False is converted to zero and True to one
5303     // for truncating conversions.
5304     __ bind(&no_heap_number);
5305     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5306     __ cmp(input_reg, ip);
5307     __ bne(&check_bools);
5308     __ li(input_reg, Operand::Zero());
5309     __ b(&done);
5310
5311     __ bind(&check_bools);
5312     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
5313     __ cmp(input_reg, ip);
5314     __ bne(&check_false);
5315     __ li(input_reg, Operand(1));
5316     __ b(&done);
5317
5318     __ bind(&check_false);
5319     __ LoadRoot(ip, Heap::kFalseValueRootIndex);
5320     __ cmp(input_reg, ip);
5321     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean);
5322     __ li(input_reg, Operand::Zero());
5323   } else {
5324     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
5325
5326     __ lfd(double_scratch2,
5327            FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5328     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5329       // preserve heap number pointer in scratch2 for minus zero check below
5330       __ mr(scratch2, input_reg);
5331     }
5332     __ TryDoubleToInt32Exact(input_reg, double_scratch2, scratch1,
5333                              double_scratch);
5334     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
5335
5336     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5337       __ cmpi(input_reg, Operand::Zero());
5338       __ bne(&done);
5339       __ lwz(scratch1,
5340              FieldMemOperand(scratch2, HeapNumber::kValueOffset +
5341                                            Register::kExponentOffset));
5342       __ cmpwi(scratch1, Operand::Zero());
5343       DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
5344     }
5345   }
5346   __ bind(&done);
5347 }
5348
5349
5350 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5351   class DeferredTaggedToI final : public LDeferredCode {
5352    public:
5353     DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
5354         : LDeferredCode(codegen), instr_(instr) {}
5355     void Generate() override { codegen()->DoDeferredTaggedToI(instr_); }
5356     LInstruction* instr() override { return instr_; }
5357
5358    private:
5359     LTaggedToI* instr_;
5360   };
5361
5362   LOperand* input = instr->value();
5363   DCHECK(input->IsRegister());
5364   DCHECK(input->Equals(instr->result()));
5365
5366   Register input_reg = ToRegister(input);
5367
5368   if (instr->hydrogen()->value()->representation().IsSmi()) {
5369     __ SmiUntag(input_reg);
5370   } else {
5371     DeferredTaggedToI* deferred = new (zone()) DeferredTaggedToI(this, instr);
5372
5373     // Branch to deferred code if the input is a HeapObject.
5374     __ JumpIfNotSmi(input_reg, deferred->entry());
5375
5376     __ SmiUntag(input_reg);
5377     __ bind(deferred->exit());
5378   }
5379 }
5380
5381
5382 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
5383   LOperand* input = instr->value();
5384   DCHECK(input->IsRegister());
5385   LOperand* result = instr->result();
5386   DCHECK(result->IsDoubleRegister());
5387
5388   Register input_reg = ToRegister(input);
5389   DoubleRegister result_reg = ToDoubleRegister(result);
5390
5391   HValue* value = instr->hydrogen()->value();
5392   NumberUntagDMode mode = value->representation().IsSmi()
5393                               ? NUMBER_CANDIDATE_IS_SMI
5394                               : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5395
5396   EmitNumberUntagD(instr, input_reg, result_reg, mode);
5397 }
5398
5399
5400 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5401   Register result_reg = ToRegister(instr->result());
5402   Register scratch1 = scratch0();
5403   DoubleRegister double_input = ToDoubleRegister(instr->value());
5404   DoubleRegister double_scratch = double_scratch0();
5405
5406   if (instr->truncating()) {
5407     __ TruncateDoubleToI(result_reg, double_input);
5408   } else {
5409     __ TryDoubleToInt32Exact(result_reg, double_input, scratch1,
5410                              double_scratch);
5411     // Deoptimize if the input wasn't a int32 (inside a double).
5412     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
5413     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5414       Label done;
5415       __ cmpi(result_reg, Operand::Zero());
5416       __ bne(&done);
5417 #if V8_TARGET_ARCH_PPC64
5418       __ MovDoubleToInt64(scratch1, double_input);
5419 #else
5420       __ MovDoubleHighToInt(scratch1, double_input);
5421 #endif
5422       __ cmpi(scratch1, Operand::Zero());
5423       DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
5424       __ bind(&done);
5425     }
5426   }
5427 }
5428
5429
5430 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5431   Register result_reg = ToRegister(instr->result());
5432   Register scratch1 = scratch0();
5433   DoubleRegister double_input = ToDoubleRegister(instr->value());
5434   DoubleRegister double_scratch = double_scratch0();
5435
5436   if (instr->truncating()) {
5437     __ TruncateDoubleToI(result_reg, double_input);
5438   } else {
5439     __ TryDoubleToInt32Exact(result_reg, double_input, scratch1,
5440                              double_scratch);
5441     // Deoptimize if the input wasn't a int32 (inside a double).
5442     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
5443     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5444       Label done;
5445       __ cmpi(result_reg, Operand::Zero());
5446       __ bne(&done);
5447 #if V8_TARGET_ARCH_PPC64
5448       __ MovDoubleToInt64(scratch1, double_input);
5449 #else
5450       __ MovDoubleHighToInt(scratch1, double_input);
5451 #endif
5452       __ cmpi(scratch1, Operand::Zero());
5453       DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
5454       __ bind(&done);
5455     }
5456   }
5457 #if V8_TARGET_ARCH_PPC64
5458   __ SmiTag(result_reg);
5459 #else
5460   __ SmiTagCheckOverflow(result_reg, r0);
5461   DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
5462 #endif
5463 }
5464
5465
5466 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5467   LOperand* input = instr->value();
5468   __ TestIfSmi(ToRegister(input), r0);
5469   DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
5470 }
5471
5472
5473 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5474   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5475     LOperand* input = instr->value();
5476     __ TestIfSmi(ToRegister(input), r0);
5477     DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
5478   }
5479 }
5480
5481
5482 void LCodeGen::DoCheckArrayBufferNotNeutered(
5483     LCheckArrayBufferNotNeutered* instr) {
5484   Register view = ToRegister(instr->view());
5485   Register scratch = scratch0();
5486
5487   __ LoadP(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
5488   __ lwz(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
5489   __ andi(r0, scratch, Operand(1 << JSArrayBuffer::WasNeutered::kShift));
5490   DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds, cr0);
5491 }
5492
5493
5494 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5495   Register input = ToRegister(instr->value());
5496   Register scratch = scratch0();
5497
5498   __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5499   __ lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5500
5501   if (instr->hydrogen()->is_interval_check()) {
5502     InstanceType first;
5503     InstanceType last;
5504     instr->hydrogen()->GetCheckInterval(&first, &last);
5505
5506     __ cmpli(scratch, Operand(first));
5507
5508     // If there is only one type in the interval check for equality.
5509     if (first == last) {
5510       DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
5511     } else {
5512       DeoptimizeIf(lt, instr, Deoptimizer::kWrongInstanceType);
5513       // Omit check for the last type.
5514       if (last != LAST_TYPE) {
5515         __ cmpli(scratch, Operand(last));
5516         DeoptimizeIf(gt, instr, Deoptimizer::kWrongInstanceType);
5517       }
5518     }
5519   } else {
5520     uint8_t mask;
5521     uint8_t tag;
5522     instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5523
5524     if (base::bits::IsPowerOfTwo32(mask)) {
5525       DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5526       __ andi(r0, scratch, Operand(mask));
5527       DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType,
5528                    cr0);
5529     } else {
5530       __ andi(scratch, scratch, Operand(mask));
5531       __ cmpi(scratch, Operand(tag));
5532       DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
5533     }
5534   }
5535 }
5536
5537
5538 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5539   Register reg = ToRegister(instr->value());
5540   Handle<HeapObject> object = instr->hydrogen()->object().handle();
5541   AllowDeferredHandleDereference smi_check;
5542   if (isolate()->heap()->InNewSpace(*object)) {
5543     Register reg = ToRegister(instr->value());
5544     Handle<Cell> cell = isolate()->factory()->NewCell(object);
5545     __ mov(ip, Operand(cell));
5546     __ LoadP(ip, FieldMemOperand(ip, Cell::kValueOffset));
5547     __ cmp(reg, ip);
5548   } else {
5549     __ Cmpi(reg, Operand(object), r0);
5550   }
5551   DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch);
5552 }
5553
5554
5555 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5556   Register temp = ToRegister(instr->temp());
5557   {
5558     PushSafepointRegistersScope scope(this);
5559     __ push(object);
5560     __ li(cp, Operand::Zero());
5561     __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5562     RecordSafepointWithRegisters(instr->pointer_map(), 1,
5563                                  Safepoint::kNoLazyDeopt);
5564     __ StoreToSafepointRegisterSlot(r3, temp);
5565   }
5566   __ TestIfSmi(temp, r0);
5567   DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, cr0);
5568 }
5569
5570
5571 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5572   class DeferredCheckMaps final : public LDeferredCode {
5573    public:
5574     DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5575         : LDeferredCode(codegen), instr_(instr), object_(object) {
5576       SetExit(check_maps());
5577     }
5578     void Generate() override {
5579       codegen()->DoDeferredInstanceMigration(instr_, object_);
5580     }
5581     Label* check_maps() { return &check_maps_; }
5582     LInstruction* instr() override { return instr_; }
5583
5584    private:
5585     LCheckMaps* instr_;
5586     Label check_maps_;
5587     Register object_;
5588   };
5589
5590   if (instr->hydrogen()->IsStabilityCheck()) {
5591     const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5592     for (int i = 0; i < maps->size(); ++i) {
5593       AddStabilityDependency(maps->at(i).handle());
5594     }
5595     return;
5596   }
5597
5598   Register object = ToRegister(instr->value());
5599   Register map_reg = ToRegister(instr->temp());
5600
5601   __ LoadP(map_reg, FieldMemOperand(object, HeapObject::kMapOffset));
5602
5603   DeferredCheckMaps* deferred = NULL;
5604   if (instr->hydrogen()->HasMigrationTarget()) {
5605     deferred = new (zone()) DeferredCheckMaps(this, instr, object);
5606     __ bind(deferred->check_maps());
5607   }
5608
5609   const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5610   Label success;
5611   for (int i = 0; i < maps->size() - 1; i++) {
5612     Handle<Map> map = maps->at(i).handle();
5613     __ CompareMap(map_reg, map, &success);
5614     __ beq(&success);
5615   }
5616
5617   Handle<Map> map = maps->at(maps->size() - 1).handle();
5618   __ CompareMap(map_reg, map, &success);
5619   if (instr->hydrogen()->HasMigrationTarget()) {
5620     __ bne(deferred->entry());
5621   } else {
5622     DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
5623   }
5624
5625   __ bind(&success);
5626 }
5627
5628
5629 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5630   DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
5631   Register result_reg = ToRegister(instr->result());
5632   __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0());
5633 }
5634
5635
5636 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5637   Register unclamped_reg = ToRegister(instr->unclamped());
5638   Register result_reg = ToRegister(instr->result());
5639   __ ClampUint8(result_reg, unclamped_reg);
5640 }
5641
5642
5643 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
5644   Register scratch = scratch0();
5645   Register input_reg = ToRegister(instr->unclamped());
5646   Register result_reg = ToRegister(instr->result());
5647   DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
5648   Label is_smi, done, heap_number;
5649
5650   // Both smi and heap number cases are handled.
5651   __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi);
5652
5653   // Check for heap number
5654   __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5655   __ Cmpi(scratch, Operand(factory()->heap_number_map()), r0);
5656   __ beq(&heap_number);
5657
5658   // Check for undefined. Undefined is converted to zero for clamping
5659   // conversions.
5660   __ Cmpi(input_reg, Operand(factory()->undefined_value()), r0);
5661   DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined);
5662   __ li(result_reg, Operand::Zero());
5663   __ b(&done);
5664
5665   // Heap number
5666   __ bind(&heap_number);
5667   __ lfd(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5668   __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0());
5669   __ b(&done);
5670
5671   // smi
5672   __ bind(&is_smi);
5673   __ ClampUint8(result_reg, result_reg);
5674
5675   __ bind(&done);
5676 }
5677
5678
5679 void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5680   DoubleRegister value_reg = ToDoubleRegister(instr->value());
5681   Register result_reg = ToRegister(instr->result());
5682
5683   if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5684     __ MovDoubleHighToInt(result_reg, value_reg);
5685   } else {
5686     __ MovDoubleLowToInt(result_reg, value_reg);
5687   }
5688 }
5689
5690
5691 void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5692   Register hi_reg = ToRegister(instr->hi());
5693   Register lo_reg = ToRegister(instr->lo());
5694   DoubleRegister result_reg = ToDoubleRegister(instr->result());
5695 #if V8_TARGET_ARCH_PPC64
5696   __ MovInt64ComponentsToDouble(result_reg, hi_reg, lo_reg, r0);
5697 #else
5698   __ MovInt64ToDouble(result_reg, hi_reg, lo_reg);
5699 #endif
5700 }
5701
5702
5703 void LCodeGen::DoAllocate(LAllocate* instr) {
5704   class DeferredAllocate final : public LDeferredCode {
5705    public:
5706     DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5707         : LDeferredCode(codegen), instr_(instr) {}
5708     void Generate() override { codegen()->DoDeferredAllocate(instr_); }
5709     LInstruction* instr() override { return instr_; }
5710
5711    private:
5712     LAllocate* instr_;
5713   };
5714
5715   DeferredAllocate* deferred = new (zone()) DeferredAllocate(this, instr);
5716
5717   Register result = ToRegister(instr->result());
5718   Register scratch = ToRegister(instr->temp1());
5719   Register scratch2 = ToRegister(instr->temp2());
5720
5721   // Allocate memory for the object.
5722   AllocationFlags flags = TAG_OBJECT;
5723   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5724     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5725   }
5726   if (instr->hydrogen()->IsOldSpaceAllocation()) {
5727     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5728     flags = static_cast<AllocationFlags>(flags | PRETENURE);
5729   }
5730
5731   if (instr->size()->IsConstantOperand()) {
5732     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5733     if (size <= Page::kMaxRegularHeapObjectSize) {
5734       __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
5735     } else {
5736       __ b(deferred->entry());
5737     }
5738   } else {
5739     Register size = ToRegister(instr->size());
5740     __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
5741   }
5742
5743   __ bind(deferred->exit());
5744
5745   if (instr->hydrogen()->MustPrefillWithFiller()) {
5746     if (instr->size()->IsConstantOperand()) {
5747       int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5748       __ LoadIntLiteral(scratch, size - kHeapObjectTag);
5749     } else {
5750       __ subi(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag));
5751     }
5752     __ mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
5753     Label loop;
5754     __ bind(&loop);
5755     __ subi(scratch, scratch, Operand(kPointerSize));
5756     __ StorePX(scratch2, MemOperand(result, scratch));
5757     __ cmpi(scratch, Operand::Zero());
5758     __ bge(&loop);
5759   }
5760 }
5761
5762
5763 void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
5764   Register result = ToRegister(instr->result());
5765
5766   // TODO(3095996): Get rid of this. For now, we need to make the
5767   // result register contain a valid pointer because it is already
5768   // contained in the register pointer map.
5769   __ LoadSmiLiteral(result, Smi::FromInt(0));
5770
5771   PushSafepointRegistersScope scope(this);
5772   if (instr->size()->IsRegister()) {
5773     Register size = ToRegister(instr->size());
5774     DCHECK(!size.is(result));
5775     __ SmiTag(size);
5776     __ push(size);
5777   } else {
5778     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5779 #if !V8_TARGET_ARCH_PPC64
5780     if (size >= 0 && size <= Smi::kMaxValue) {
5781 #endif
5782       __ Push(Smi::FromInt(size));
5783 #if !V8_TARGET_ARCH_PPC64
5784     } else {
5785       // We should never get here at runtime => abort
5786       __ stop("invalid allocation size");
5787       return;
5788     }
5789 #endif
5790   }
5791
5792   int flags = AllocateDoubleAlignFlag::encode(
5793       instr->hydrogen()->MustAllocateDoubleAligned());
5794   if (instr->hydrogen()->IsOldSpaceAllocation()) {
5795     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5796     flags = AllocateTargetSpace::update(flags, OLD_SPACE);
5797   } else {
5798     flags = AllocateTargetSpace::update(flags, NEW_SPACE);
5799   }
5800   __ Push(Smi::FromInt(flags));
5801
5802   CallRuntimeFromDeferred(Runtime::kAllocateInTargetSpace, 2, instr,
5803                           instr->context());
5804   __ StoreToSafepointRegisterSlot(r3, result);
5805 }
5806
5807
5808 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
5809   DCHECK(ToRegister(instr->value()).is(r3));
5810   __ push(r3);
5811   CallRuntime(Runtime::kToFastProperties, 1, instr);
5812 }
5813
5814
5815 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
5816   DCHECK(ToRegister(instr->context()).is(cp));
5817   Label materialized;
5818   // Registers will be used as follows:
5819   // r10 = literals array.
5820   // r4 = regexp literal.
5821   // r3 = regexp literal clone.
5822   // r5 and r7-r9 are used as temporaries.
5823   int literal_offset =
5824       FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
5825   __ Move(r10, instr->hydrogen()->literals());
5826   __ LoadP(r4, FieldMemOperand(r10, literal_offset));
5827   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5828   __ cmp(r4, ip);
5829   __ bne(&materialized);
5830
5831   // Create regexp literal using runtime function
5832   // Result will be in r3.
5833   __ LoadSmiLiteral(r9, Smi::FromInt(instr->hydrogen()->literal_index()));
5834   __ mov(r8, Operand(instr->hydrogen()->pattern()));
5835   __ mov(r7, Operand(instr->hydrogen()->flags()));
5836   __ Push(r10, r9, r8, r7);
5837   CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
5838   __ mr(r4, r3);
5839
5840   __ bind(&materialized);
5841   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
5842   Label allocated, runtime_allocate;
5843
5844   __ Allocate(size, r3, r5, r6, &runtime_allocate, TAG_OBJECT);
5845   __ b(&allocated);
5846
5847   __ bind(&runtime_allocate);
5848   __ LoadSmiLiteral(r3, Smi::FromInt(size));
5849   __ Push(r4, r3);
5850   CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5851   __ pop(r4);
5852
5853   __ bind(&allocated);
5854   // Copy the content into the newly allocated memory.
5855   __ CopyFields(r3, r4, r5.bit(), size / kPointerSize);
5856 }
5857
5858
5859 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
5860   DCHECK(ToRegister(instr->context()).is(cp));
5861   // Use the fast case closure allocation code that allocates in new
5862   // space for nested functions that don't need literals cloning.
5863   bool pretenure = instr->hydrogen()->pretenure();
5864   if (!pretenure && instr->hydrogen()->has_no_literals()) {
5865     FastNewClosureStub stub(isolate(), instr->hydrogen()->language_mode(),
5866                             instr->hydrogen()->kind());
5867     __ mov(r5, Operand(instr->hydrogen()->shared_info()));
5868     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5869   } else {
5870     __ mov(r5, Operand(instr->hydrogen()->shared_info()));
5871     __ mov(r4, Operand(pretenure ? factory()->true_value()
5872                                  : factory()->false_value()));
5873     __ Push(cp, r5, r4);
5874     CallRuntime(Runtime::kNewClosure, 3, instr);
5875   }
5876 }
5877
5878
5879 void LCodeGen::DoTypeof(LTypeof* instr) {
5880   DCHECK(ToRegister(instr->value()).is(r6));
5881   DCHECK(ToRegister(instr->result()).is(r3));
5882   Label end, do_call;
5883   Register value_register = ToRegister(instr->value());
5884   __ JumpIfNotSmi(value_register, &do_call);
5885   __ mov(r3, Operand(isolate()->factory()->number_string()));
5886   __ b(&end);
5887   __ bind(&do_call);
5888   TypeofStub stub(isolate());
5889   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5890   __ bind(&end);
5891 }
5892
5893
5894 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5895   Register input = ToRegister(instr->value());
5896
5897   Condition final_branch_condition =
5898       EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), input,
5899                    instr->type_literal());
5900   if (final_branch_condition != kNoCondition) {
5901     EmitBranch(instr, final_branch_condition);
5902   }
5903 }
5904
5905
5906 Condition LCodeGen::EmitTypeofIs(Label* true_label, Label* false_label,
5907                                  Register input, Handle<String> type_name) {
5908   Condition final_branch_condition = kNoCondition;
5909   Register scratch = scratch0();
5910   Factory* factory = isolate()->factory();
5911   if (String::Equals(type_name, factory->number_string())) {
5912     __ JumpIfSmi(input, true_label);
5913     __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5914     __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
5915     final_branch_condition = eq;
5916
5917   } else if (String::Equals(type_name, factory->string_string())) {
5918     __ JumpIfSmi(input, false_label);
5919     __ CompareObjectType(input, scratch, no_reg, FIRST_NONSTRING_TYPE);
5920     __ bge(false_label);
5921     __ lbz(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
5922     __ ExtractBit(r0, scratch, Map::kIsUndetectable);
5923     __ cmpi(r0, Operand::Zero());
5924     final_branch_condition = eq;
5925
5926   } else if (String::Equals(type_name, factory->symbol_string())) {
5927     __ JumpIfSmi(input, false_label);
5928     __ CompareObjectType(input, scratch, no_reg, SYMBOL_TYPE);
5929     final_branch_condition = eq;
5930
5931   } else if (String::Equals(type_name, factory->boolean_string())) {
5932     __ CompareRoot(input, Heap::kTrueValueRootIndex);
5933     __ beq(true_label);
5934     __ CompareRoot(input, Heap::kFalseValueRootIndex);
5935     final_branch_condition = eq;
5936
5937   } else if (String::Equals(type_name, factory->undefined_string())) {
5938     __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
5939     __ beq(true_label);
5940     __ JumpIfSmi(input, false_label);
5941     // Check for undetectable objects => true.
5942     __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5943     __ lbz(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
5944     __ ExtractBit(r0, scratch, Map::kIsUndetectable);
5945     __ cmpi(r0, Operand::Zero());
5946     final_branch_condition = ne;
5947
5948   } else if (String::Equals(type_name, factory->function_string())) {
5949     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
5950     Register type_reg = scratch;
5951     __ JumpIfSmi(input, false_label);
5952     __ CompareObjectType(input, scratch, type_reg, JS_FUNCTION_TYPE);
5953     __ beq(true_label);
5954     __ cmpi(type_reg, Operand(JS_FUNCTION_PROXY_TYPE));
5955     final_branch_condition = eq;
5956
5957   } else if (String::Equals(type_name, factory->object_string())) {
5958     Register map = scratch;
5959     __ JumpIfSmi(input, false_label);
5960     __ CompareRoot(input, Heap::kNullValueRootIndex);
5961     __ beq(true_label);
5962     __ CheckObjectTypeRange(input, map, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE,
5963                             LAST_NONCALLABLE_SPEC_OBJECT_TYPE, false_label);
5964     // Check for undetectable objects => false.
5965     __ lbz(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
5966     __ ExtractBit(r0, scratch, Map::kIsUndetectable);
5967     __ cmpi(r0, Operand::Zero());
5968     final_branch_condition = eq;
5969
5970   } else {
5971     __ b(false_label);
5972   }
5973
5974   return final_branch_condition;
5975 }
5976
5977
5978 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5979   Register temp1 = ToRegister(instr->temp());
5980
5981   EmitIsConstructCall(temp1, scratch0());
5982   EmitBranch(instr, eq);
5983 }
5984
5985
5986 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
5987   DCHECK(!temp1.is(temp2));
5988   // Get the frame pointer for the calling frame.
5989   __ LoadP(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
5990
5991   // Skip the arguments adaptor frame if it exists.
5992   Label check_frame_marker;
5993   __ LoadP(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
5994   __ CmpSmiLiteral(temp2, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
5995   __ bne(&check_frame_marker);
5996   __ LoadP(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
5997
5998   // Check the marker in the calling frame.
5999   __ bind(&check_frame_marker);
6000   __ LoadP(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
6001   __ CmpSmiLiteral(temp1, Smi::FromInt(StackFrame::CONSTRUCT), r0);
6002 }
6003
6004
6005 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
6006   if (!info()->IsStub()) {
6007     // Ensure that we have enough space after the previous lazy-bailout
6008     // instruction for patching the code here.
6009     int current_pc = masm()->pc_offset();
6010     if (current_pc < last_lazy_deopt_pc_ + space_needed) {
6011       int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
6012       DCHECK_EQ(0, padding_size % Assembler::kInstrSize);
6013       while (padding_size > 0) {
6014         __ nop();
6015         padding_size -= Assembler::kInstrSize;
6016       }
6017     }
6018   }
6019   last_lazy_deopt_pc_ = masm()->pc_offset();
6020 }
6021
6022
6023 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
6024   last_lazy_deopt_pc_ = masm()->pc_offset();
6025   DCHECK(instr->HasEnvironment());
6026   LEnvironment* env = instr->environment();
6027   RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6028   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6029 }
6030
6031
6032 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
6033   Deoptimizer::BailoutType type = instr->hydrogen()->type();
6034   // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
6035   // needed return address), even though the implementation of LAZY and EAGER is
6036   // now identical. When LAZY is eventually completely folded into EAGER, remove
6037   // the special case below.
6038   if (info()->IsStub() && type == Deoptimizer::EAGER) {
6039     type = Deoptimizer::LAZY;
6040   }
6041
6042   DeoptimizeIf(al, instr, instr->hydrogen()->reason(), type);
6043 }
6044
6045
6046 void LCodeGen::DoDummy(LDummy* instr) {
6047   // Nothing to see here, move on!
6048 }
6049
6050
6051 void LCodeGen::DoDummyUse(LDummyUse* instr) {
6052   // Nothing to see here, move on!
6053 }
6054
6055
6056 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
6057   PushSafepointRegistersScope scope(this);
6058   LoadContextFromDeferred(instr->context());
6059   __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
6060   RecordSafepointWithLazyDeopt(
6061       instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
6062   DCHECK(instr->HasEnvironment());
6063   LEnvironment* env = instr->environment();
6064   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6065 }
6066
6067
6068 void LCodeGen::DoStackCheck(LStackCheck* instr) {
6069   class DeferredStackCheck final : public LDeferredCode {
6070    public:
6071     DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
6072         : LDeferredCode(codegen), instr_(instr) {}
6073     void Generate() override { codegen()->DoDeferredStackCheck(instr_); }
6074     LInstruction* instr() override { return instr_; }
6075
6076    private:
6077     LStackCheck* instr_;
6078   };
6079
6080   DCHECK(instr->HasEnvironment());
6081   LEnvironment* env = instr->environment();
6082   // There is no LLazyBailout instruction for stack-checks. We have to
6083   // prepare for lazy deoptimization explicitly here.
6084   if (instr->hydrogen()->is_function_entry()) {
6085     // Perform stack overflow check.
6086     Label done;
6087     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
6088     __ cmpl(sp, ip);
6089     __ bge(&done);
6090     DCHECK(instr->context()->IsRegister());
6091     DCHECK(ToRegister(instr->context()).is(cp));
6092     CallCode(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET,
6093              instr);
6094     __ bind(&done);
6095   } else {
6096     DCHECK(instr->hydrogen()->is_backwards_branch());
6097     // Perform stack overflow check if this goto needs it before jumping.
6098     DeferredStackCheck* deferred_stack_check =
6099         new (zone()) DeferredStackCheck(this, instr);
6100     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
6101     __ cmpl(sp, ip);
6102     __ blt(deferred_stack_check->entry());
6103     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
6104     __ bind(instr->done_label());
6105     deferred_stack_check->SetExit(instr->done_label());
6106     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6107     // Don't record a deoptimization index for the safepoint here.
6108     // This will be done explicitly when emitting call and the safepoint in
6109     // the deferred code.
6110   }
6111 }
6112
6113
6114 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
6115   // This is a pseudo-instruction that ensures that the environment here is
6116   // properly registered for deoptimization and records the assembler's PC
6117   // offset.
6118   LEnvironment* environment = instr->environment();
6119
6120   // If the environment were already registered, we would have no way of
6121   // backpatching it with the spill slot operands.
6122   DCHECK(!environment->HasBeenRegistered());
6123   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6124
6125   GenerateOsrPrologue();
6126 }
6127
6128
6129 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
6130   __ TestIfSmi(r3, r0);
6131   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
6132
6133   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
6134   __ CompareObjectType(r3, r4, r4, LAST_JS_PROXY_TYPE);
6135   DeoptimizeIf(le, instr, Deoptimizer::kWrongInstanceType);
6136
6137   Label use_cache, call_runtime;
6138   Register null_value = r8;
6139   __ LoadRoot(null_value, Heap::kNullValueRootIndex);
6140   __ CheckEnumCache(null_value, &call_runtime);
6141
6142   __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
6143   __ b(&use_cache);
6144
6145   // Get the set of properties to enumerate.
6146   __ bind(&call_runtime);
6147   __ push(r3);
6148   CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
6149
6150   __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
6151   __ LoadRoot(ip, Heap::kMetaMapRootIndex);
6152   __ cmp(r4, ip);
6153   DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
6154   __ bind(&use_cache);
6155 }
6156
6157
6158 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6159   Register map = ToRegister(instr->map());
6160   Register result = ToRegister(instr->result());
6161   Label load_cache, done;
6162   __ EnumLength(result, map);
6163   __ CmpSmiLiteral(result, Smi::FromInt(0), r0);
6164   __ bne(&load_cache);
6165   __ mov(result, Operand(isolate()->factory()->empty_fixed_array()));
6166   __ b(&done);
6167
6168   __ bind(&load_cache);
6169   __ LoadInstanceDescriptors(map, result);
6170   __ LoadP(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
6171   __ LoadP(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
6172   __ cmpi(result, Operand::Zero());
6173   DeoptimizeIf(eq, instr, Deoptimizer::kNoCache);
6174
6175   __ bind(&done);
6176 }
6177
6178
6179 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6180   Register object = ToRegister(instr->value());
6181   Register map = ToRegister(instr->map());
6182   __ LoadP(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
6183   __ cmp(map, scratch0());
6184   DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
6185 }
6186
6187
6188 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
6189                                            Register result, Register object,
6190                                            Register index) {
6191   PushSafepointRegistersScope scope(this);
6192   __ Push(object, index);
6193   __ li(cp, Operand::Zero());
6194   __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
6195   RecordSafepointWithRegisters(instr->pointer_map(), 2,
6196                                Safepoint::kNoLazyDeopt);
6197   __ StoreToSafepointRegisterSlot(r3, result);
6198 }
6199
6200
6201 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6202   class DeferredLoadMutableDouble final : public LDeferredCode {
6203    public:
6204     DeferredLoadMutableDouble(LCodeGen* codegen, LLoadFieldByIndex* instr,
6205                               Register result, Register object, Register index)
6206         : LDeferredCode(codegen),
6207           instr_(instr),
6208           result_(result),
6209           object_(object),
6210           index_(index) {}
6211     void Generate() override {
6212       codegen()->DoDeferredLoadMutableDouble(instr_, result_, object_, index_);
6213     }
6214     LInstruction* instr() override { return instr_; }
6215
6216    private:
6217     LLoadFieldByIndex* instr_;
6218     Register result_;
6219     Register object_;
6220     Register index_;
6221   };
6222
6223   Register object = ToRegister(instr->object());
6224   Register index = ToRegister(instr->index());
6225   Register result = ToRegister(instr->result());
6226   Register scratch = scratch0();
6227
6228   DeferredLoadMutableDouble* deferred;
6229   deferred = new (zone())
6230       DeferredLoadMutableDouble(this, instr, result, object, index);
6231
6232   Label out_of_object, done;
6233
6234   __ TestBitMask(index, reinterpret_cast<uintptr_t>(Smi::FromInt(1)), r0);
6235   __ bne(deferred->entry(), cr0);
6236   __ ShiftRightArithImm(index, index, 1);
6237
6238   __ cmpi(index, Operand::Zero());
6239   __ blt(&out_of_object);
6240
6241   __ SmiToPtrArrayOffset(r0, index);
6242   __ add(scratch, object, r0);
6243   __ LoadP(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
6244
6245   __ b(&done);
6246
6247   __ bind(&out_of_object);
6248   __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
6249   // Index is equal to negated out of object property index plus 1.
6250   __ SmiToPtrArrayOffset(r0, index);
6251   __ sub(scratch, result, r0);
6252   __ LoadP(result,
6253            FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize));
6254   __ bind(deferred->exit());
6255   __ bind(&done);
6256 }
6257
6258
6259 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
6260   Register context = ToRegister(instr->context());
6261   __ StoreP(context, MemOperand(fp, StandardFrameConstants::kContextOffset));
6262 }
6263
6264
6265 void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) {
6266   Handle<ScopeInfo> scope_info = instr->scope_info();
6267   __ Push(scope_info);
6268   __ push(ToRegister(instr->function()));
6269   CallRuntime(Runtime::kPushBlockContext, 2, instr);
6270   RecordSafepoint(Safepoint::kNoLazyDeopt);
6271 }
6272
6273
6274 #undef __
6275 }  // namespace internal
6276 }  // namespace v8