Home | History | Annotate | Download | only in ppc
      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 <assert.h>  // For assert
      6 #include <limits.h>  // For LONG_MIN, LONG_MAX.
      7 
      8 #if V8_TARGET_ARCH_PPC
      9 
     10 #include "src/base/bits.h"
     11 #include "src/base/division-by-constant.h"
     12 #include "src/bootstrapper.h"
     13 #include "src/codegen.h"
     14 #include "src/debug/debug.h"
     15 #include "src/register-configuration.h"
     16 #include "src/runtime/runtime.h"
     17 
     18 #include "src/ppc/macro-assembler-ppc.h"
     19 
     20 namespace v8 {
     21 namespace internal {
     22 
     23 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
     24                                CodeObjectRequired create_code_object)
     25     : Assembler(arg_isolate, buffer, size),
     26       generating_stub_(false),
     27       has_frame_(false) {
     28   if (create_code_object == CodeObjectRequired::kYes) {
     29     code_object_ =
     30         Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
     31   }
     32 }
     33 
     34 
     35 void MacroAssembler::Jump(Register target) {
     36   mtctr(target);
     37   bctr();
     38 }
     39 
     40 
     41 void MacroAssembler::JumpToJSEntry(Register target) {
     42   Move(ip, target);
     43   Jump(ip);
     44 }
     45 
     46 
     47 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
     48                           Condition cond, CRegister cr) {
     49   Label skip;
     50 
     51   if (cond != al) b(NegateCondition(cond), &skip, cr);
     52 
     53   DCHECK(rmode == RelocInfo::CODE_TARGET || rmode == RelocInfo::RUNTIME_ENTRY);
     54 
     55   mov(ip, Operand(target, rmode));
     56   mtctr(ip);
     57   bctr();
     58 
     59   bind(&skip);
     60 }
     61 
     62 
     63 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode, Condition cond,
     64                           CRegister cr) {
     65   DCHECK(!RelocInfo::IsCodeTarget(rmode));
     66   Jump(reinterpret_cast<intptr_t>(target), rmode, cond, cr);
     67 }
     68 
     69 
     70 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
     71                           Condition cond) {
     72   DCHECK(RelocInfo::IsCodeTarget(rmode));
     73   // 'code' is always generated ppc code, never THUMB code
     74   AllowDeferredHandleDereference embedding_raw_address;
     75   Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
     76 }
     77 
     78 
     79 int MacroAssembler::CallSize(Register target) { return 2 * kInstrSize; }
     80 
     81 
     82 void MacroAssembler::Call(Register target) {
     83   BlockTrampolinePoolScope block_trampoline_pool(this);
     84   Label start;
     85   bind(&start);
     86 
     87   // branch via link register and set LK bit for return point
     88   mtctr(target);
     89   bctrl();
     90 
     91   DCHECK_EQ(CallSize(target), SizeOfCodeGeneratedSince(&start));
     92 }
     93 
     94 
     95 void MacroAssembler::CallJSEntry(Register target) {
     96   DCHECK(target.is(ip));
     97   Call(target);
     98 }
     99 
    100 
    101 int MacroAssembler::CallSize(Address target, RelocInfo::Mode rmode,
    102                              Condition cond) {
    103   Operand mov_operand = Operand(reinterpret_cast<intptr_t>(target), rmode);
    104   return (2 + instructions_required_for_mov(ip, mov_operand)) * kInstrSize;
    105 }
    106 
    107 
    108 int MacroAssembler::CallSizeNotPredictableCodeSize(Address target,
    109                                                    RelocInfo::Mode rmode,
    110                                                    Condition cond) {
    111   return (2 + kMovInstructionsNoConstantPool) * kInstrSize;
    112 }
    113 
    114 
    115 void MacroAssembler::Call(Address target, RelocInfo::Mode rmode,
    116                           Condition cond) {
    117   BlockTrampolinePoolScope block_trampoline_pool(this);
    118   DCHECK(cond == al);
    119 
    120 #ifdef DEBUG
    121   // Check the expected size before generating code to ensure we assume the same
    122   // constant pool availability (e.g., whether constant pool is full or not).
    123   int expected_size = CallSize(target, rmode, cond);
    124   Label start;
    125   bind(&start);
    126 #endif
    127   // This can likely be optimized to make use of bc() with 24bit relative
    128   //
    129   // RecordRelocInfo(x.rmode_, x.imm_);
    130   // bc( BA, .... offset, LKset);
    131   //
    132 
    133   mov(ip, Operand(reinterpret_cast<intptr_t>(target), rmode));
    134   mtctr(ip);
    135   bctrl();
    136 
    137   DCHECK_EQ(expected_size, SizeOfCodeGeneratedSince(&start));
    138 }
    139 
    140 
    141 int MacroAssembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode,
    142                              TypeFeedbackId ast_id, Condition cond) {
    143   AllowDeferredHandleDereference using_raw_address;
    144   return CallSize(reinterpret_cast<Address>(code.location()), rmode, cond);
    145 }
    146 
    147 
    148 void MacroAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
    149                           TypeFeedbackId ast_id, Condition cond) {
    150   BlockTrampolinePoolScope block_trampoline_pool(this);
    151   DCHECK(RelocInfo::IsCodeTarget(rmode));
    152 
    153 #ifdef DEBUG
    154   // Check the expected size before generating code to ensure we assume the same
    155   // constant pool availability (e.g., whether constant pool is full or not).
    156   int expected_size = CallSize(code, rmode, ast_id, cond);
    157   Label start;
    158   bind(&start);
    159 #endif
    160 
    161   if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
    162     SetRecordedAstId(ast_id);
    163     rmode = RelocInfo::CODE_TARGET_WITH_ID;
    164   }
    165   AllowDeferredHandleDereference using_raw_address;
    166   Call(reinterpret_cast<Address>(code.location()), rmode, cond);
    167   DCHECK_EQ(expected_size, SizeOfCodeGeneratedSince(&start));
    168 }
    169 
    170 
    171 void MacroAssembler::Drop(int count) {
    172   if (count > 0) {
    173     Add(sp, sp, count * kPointerSize, r0);
    174   }
    175 }
    176 
    177 void MacroAssembler::Drop(Register count, Register scratch) {
    178   ShiftLeftImm(scratch, count, Operand(kPointerSizeLog2));
    179   add(sp, sp, scratch);
    180 }
    181 
    182 void MacroAssembler::Call(Label* target) { b(target, SetLK); }
    183 
    184 
    185 void MacroAssembler::Push(Handle<Object> handle) {
    186   mov(r0, Operand(handle));
    187   push(r0);
    188 }
    189 
    190 
    191 void MacroAssembler::Move(Register dst, Handle<Object> value) {
    192   mov(dst, Operand(value));
    193 }
    194 
    195 
    196 void MacroAssembler::Move(Register dst, Register src, Condition cond) {
    197   DCHECK(cond == al);
    198   if (!dst.is(src)) {
    199     mr(dst, src);
    200   }
    201 }
    202 
    203 
    204 void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) {
    205   if (!dst.is(src)) {
    206     fmr(dst, src);
    207   }
    208 }
    209 
    210 
    211 void MacroAssembler::MultiPush(RegList regs, Register location) {
    212   int16_t num_to_push = NumberOfBitsSet(regs);
    213   int16_t stack_offset = num_to_push * kPointerSize;
    214 
    215   subi(location, location, Operand(stack_offset));
    216   for (int16_t i = Register::kNumRegisters - 1; i >= 0; i--) {
    217     if ((regs & (1 << i)) != 0) {
    218       stack_offset -= kPointerSize;
    219       StoreP(ToRegister(i), MemOperand(location, stack_offset));
    220     }
    221   }
    222 }
    223 
    224 
    225 void MacroAssembler::MultiPop(RegList regs, Register location) {
    226   int16_t stack_offset = 0;
    227 
    228   for (int16_t i = 0; i < Register::kNumRegisters; i++) {
    229     if ((regs & (1 << i)) != 0) {
    230       LoadP(ToRegister(i), MemOperand(location, stack_offset));
    231       stack_offset += kPointerSize;
    232     }
    233   }
    234   addi(location, location, Operand(stack_offset));
    235 }
    236 
    237 
    238 void MacroAssembler::MultiPushDoubles(RegList dregs, Register location) {
    239   int16_t num_to_push = NumberOfBitsSet(dregs);
    240   int16_t stack_offset = num_to_push * kDoubleSize;
    241 
    242   subi(location, location, Operand(stack_offset));
    243   for (int16_t i = DoubleRegister::kNumRegisters - 1; i >= 0; i--) {
    244     if ((dregs & (1 << i)) != 0) {
    245       DoubleRegister dreg = DoubleRegister::from_code(i);
    246       stack_offset -= kDoubleSize;
    247       stfd(dreg, MemOperand(location, stack_offset));
    248     }
    249   }
    250 }
    251 
    252 
    253 void MacroAssembler::MultiPopDoubles(RegList dregs, Register location) {
    254   int16_t stack_offset = 0;
    255 
    256   for (int16_t i = 0; i < DoubleRegister::kNumRegisters; i++) {
    257     if ((dregs & (1 << i)) != 0) {
    258       DoubleRegister dreg = DoubleRegister::from_code(i);
    259       lfd(dreg, MemOperand(location, stack_offset));
    260       stack_offset += kDoubleSize;
    261     }
    262   }
    263   addi(location, location, Operand(stack_offset));
    264 }
    265 
    266 
    267 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index,
    268                               Condition cond) {
    269   DCHECK(cond == al);
    270   LoadP(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), r0);
    271 }
    272 
    273 
    274 void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index,
    275                                Condition cond) {
    276   DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
    277   DCHECK(cond == al);
    278   StoreP(source, MemOperand(kRootRegister, index << kPointerSizeLog2), r0);
    279 }
    280 
    281 
    282 void MacroAssembler::InNewSpace(Register object, Register scratch,
    283                                 Condition cond, Label* branch) {
    284   DCHECK(cond == eq || cond == ne);
    285   CheckPageFlag(object, scratch, MemoryChunk::kIsInNewSpaceMask, cond, branch);
    286 }
    287 
    288 
    289 void MacroAssembler::RecordWriteField(
    290     Register object, int offset, Register value, Register dst,
    291     LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
    292     RememberedSetAction remembered_set_action, SmiCheck smi_check,
    293     PointersToHereCheck pointers_to_here_check_for_value) {
    294   // First, check if a write barrier is even needed. The tests below
    295   // catch stores of Smis.
    296   Label done;
    297 
    298   // Skip barrier if writing a smi.
    299   if (smi_check == INLINE_SMI_CHECK) {
    300     JumpIfSmi(value, &done);
    301   }
    302 
    303   // Although the object register is tagged, the offset is relative to the start
    304   // of the object, so so offset must be a multiple of kPointerSize.
    305   DCHECK(IsAligned(offset, kPointerSize));
    306 
    307   Add(dst, object, offset - kHeapObjectTag, r0);
    308   if (emit_debug_code()) {
    309     Label ok;
    310     andi(r0, dst, Operand((1 << kPointerSizeLog2) - 1));
    311     beq(&ok, cr0);
    312     stop("Unaligned cell in write barrier");
    313     bind(&ok);
    314   }
    315 
    316   RecordWrite(object, dst, value, lr_status, save_fp, remembered_set_action,
    317               OMIT_SMI_CHECK, pointers_to_here_check_for_value);
    318 
    319   bind(&done);
    320 
    321   // Clobber clobbered input registers when running with the debug-code flag
    322   // turned on to provoke errors.
    323   if (emit_debug_code()) {
    324     mov(value, Operand(bit_cast<intptr_t>(kZapValue + 4)));
    325     mov(dst, Operand(bit_cast<intptr_t>(kZapValue + 8)));
    326   }
    327 }
    328 
    329 
    330 // Will clobber 4 registers: object, map, dst, ip.  The
    331 // register 'object' contains a heap object pointer.
    332 void MacroAssembler::RecordWriteForMap(Register object, Register map,
    333                                        Register dst,
    334                                        LinkRegisterStatus lr_status,
    335                                        SaveFPRegsMode fp_mode) {
    336   if (emit_debug_code()) {
    337     LoadP(dst, FieldMemOperand(map, HeapObject::kMapOffset));
    338     Cmpi(dst, Operand(isolate()->factory()->meta_map()), r0);
    339     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
    340   }
    341 
    342   if (!FLAG_incremental_marking) {
    343     return;
    344   }
    345 
    346   if (emit_debug_code()) {
    347     LoadP(ip, FieldMemOperand(object, HeapObject::kMapOffset));
    348     cmp(ip, map);
    349     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
    350   }
    351 
    352   Label done;
    353 
    354   // A single check of the map's pages interesting flag suffices, since it is
    355   // only set during incremental collection, and then it's also guaranteed that
    356   // the from object's page's interesting flag is also set.  This optimization
    357   // relies on the fact that maps can never be in new space.
    358   CheckPageFlag(map,
    359                 map,  // Used as scratch.
    360                 MemoryChunk::kPointersToHereAreInterestingMask, eq, &done);
    361 
    362   addi(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
    363   if (emit_debug_code()) {
    364     Label ok;
    365     andi(r0, dst, Operand((1 << kPointerSizeLog2) - 1));
    366     beq(&ok, cr0);
    367     stop("Unaligned cell in write barrier");
    368     bind(&ok);
    369   }
    370 
    371   // Record the actual write.
    372   if (lr_status == kLRHasNotBeenSaved) {
    373     mflr(r0);
    374     push(r0);
    375   }
    376   RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
    377                        fp_mode);
    378   CallStub(&stub);
    379   if (lr_status == kLRHasNotBeenSaved) {
    380     pop(r0);
    381     mtlr(r0);
    382   }
    383 
    384   bind(&done);
    385 
    386   // Count number of write barriers in generated code.
    387   isolate()->counters()->write_barriers_static()->Increment();
    388   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, ip, dst);
    389 
    390   // Clobber clobbered registers when running with the debug-code flag
    391   // turned on to provoke errors.
    392   if (emit_debug_code()) {
    393     mov(dst, Operand(bit_cast<intptr_t>(kZapValue + 12)));
    394     mov(map, Operand(bit_cast<intptr_t>(kZapValue + 16)));
    395   }
    396 }
    397 
    398 
    399 // Will clobber 4 registers: object, address, scratch, ip.  The
    400 // register 'object' contains a heap object pointer.  The heap object
    401 // tag is shifted away.
    402 void MacroAssembler::RecordWrite(
    403     Register object, Register address, Register value,
    404     LinkRegisterStatus lr_status, SaveFPRegsMode fp_mode,
    405     RememberedSetAction remembered_set_action, SmiCheck smi_check,
    406     PointersToHereCheck pointers_to_here_check_for_value) {
    407   DCHECK(!object.is(value));
    408   if (emit_debug_code()) {
    409     LoadP(r0, MemOperand(address));
    410     cmp(r0, value);
    411     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
    412   }
    413 
    414   if (remembered_set_action == OMIT_REMEMBERED_SET &&
    415       !FLAG_incremental_marking) {
    416     return;
    417   }
    418 
    419   // First, check if a write barrier is even needed. The tests below
    420   // catch stores of smis and stores into the young generation.
    421   Label done;
    422 
    423   if (smi_check == INLINE_SMI_CHECK) {
    424     JumpIfSmi(value, &done);
    425   }
    426 
    427   if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
    428     CheckPageFlag(value,
    429                   value,  // Used as scratch.
    430                   MemoryChunk::kPointersToHereAreInterestingMask, eq, &done);
    431   }
    432   CheckPageFlag(object,
    433                 value,  // Used as scratch.
    434                 MemoryChunk::kPointersFromHereAreInterestingMask, eq, &done);
    435 
    436   // Record the actual write.
    437   if (lr_status == kLRHasNotBeenSaved) {
    438     mflr(r0);
    439     push(r0);
    440   }
    441   RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
    442                        fp_mode);
    443   CallStub(&stub);
    444   if (lr_status == kLRHasNotBeenSaved) {
    445     pop(r0);
    446     mtlr(r0);
    447   }
    448 
    449   bind(&done);
    450 
    451   // Count number of write barriers in generated code.
    452   isolate()->counters()->write_barriers_static()->Increment();
    453   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, ip,
    454                    value);
    455 
    456   // Clobber clobbered registers when running with the debug-code flag
    457   // turned on to provoke errors.
    458   if (emit_debug_code()) {
    459     mov(address, Operand(bit_cast<intptr_t>(kZapValue + 12)));
    460     mov(value, Operand(bit_cast<intptr_t>(kZapValue + 16)));
    461   }
    462 }
    463 
    464 void MacroAssembler::RecordWriteCodeEntryField(Register js_function,
    465                                                Register code_entry,
    466                                                Register scratch) {
    467   const int offset = JSFunction::kCodeEntryOffset;
    468 
    469   // Since a code entry (value) is always in old space, we don't need to update
    470   // remembered set. If incremental marking is off, there is nothing for us to
    471   // do.
    472   if (!FLAG_incremental_marking) return;
    473 
    474   DCHECK(js_function.is(r4));
    475   DCHECK(code_entry.is(r7));
    476   DCHECK(scratch.is(r8));
    477   AssertNotSmi(js_function);
    478 
    479   if (emit_debug_code()) {
    480     addi(scratch, js_function, Operand(offset - kHeapObjectTag));
    481     LoadP(ip, MemOperand(scratch));
    482     cmp(ip, code_entry);
    483     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
    484   }
    485 
    486   // First, check if a write barrier is even needed. The tests below
    487   // catch stores of Smis and stores into young gen.
    488   Label done;
    489 
    490   CheckPageFlag(code_entry, scratch,
    491                 MemoryChunk::kPointersToHereAreInterestingMask, eq, &done);
    492   CheckPageFlag(js_function, scratch,
    493                 MemoryChunk::kPointersFromHereAreInterestingMask, eq, &done);
    494 
    495   const Register dst = scratch;
    496   addi(dst, js_function, Operand(offset - kHeapObjectTag));
    497 
    498   // Save caller-saved registers.  js_function and code_entry are in the
    499   // caller-saved register list.
    500   DCHECK(kJSCallerSaved & js_function.bit());
    501   DCHECK(kJSCallerSaved & code_entry.bit());
    502   mflr(r0);
    503   MultiPush(kJSCallerSaved | r0.bit());
    504 
    505   int argument_count = 3;
    506   PrepareCallCFunction(argument_count, code_entry);
    507 
    508   mr(r3, js_function);
    509   mr(r4, dst);
    510   mov(r5, Operand(ExternalReference::isolate_address(isolate())));
    511 
    512   {
    513     AllowExternalCallThatCantCauseGC scope(this);
    514     CallCFunction(
    515         ExternalReference::incremental_marking_record_write_code_entry_function(
    516             isolate()),
    517         argument_count);
    518   }
    519 
    520   // Restore caller-saved registers (including js_function and code_entry).
    521   MultiPop(kJSCallerSaved | r0.bit());
    522   mtlr(r0);
    523 
    524   bind(&done);
    525 }
    526 
    527 void MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
    528                                          Register address, Register scratch,
    529                                          SaveFPRegsMode fp_mode,
    530                                          RememberedSetFinalAction and_then) {
    531   Label done;
    532   if (emit_debug_code()) {
    533     Label ok;
    534     JumpIfNotInNewSpace(object, scratch, &ok);
    535     stop("Remembered set pointer is in new space");
    536     bind(&ok);
    537   }
    538   // Load store buffer top.
    539   ExternalReference store_buffer =
    540       ExternalReference::store_buffer_top(isolate());
    541   mov(ip, Operand(store_buffer));
    542   LoadP(scratch, MemOperand(ip));
    543   // Store pointer to buffer and increment buffer top.
    544   StoreP(address, MemOperand(scratch));
    545   addi(scratch, scratch, Operand(kPointerSize));
    546   // Write back new top of buffer.
    547   StoreP(scratch, MemOperand(ip));
    548   // Call stub on end of buffer.
    549   // Check for end of buffer.
    550   TestBitMask(scratch, StoreBuffer::kStoreBufferMask, r0);
    551 
    552   if (and_then == kFallThroughAtEnd) {
    553     bne(&done, cr0);
    554   } else {
    555     DCHECK(and_then == kReturnAtEnd);
    556     Ret(ne, cr0);
    557   }
    558   mflr(r0);
    559   push(r0);
    560   StoreBufferOverflowStub store_buffer_overflow(isolate(), fp_mode);
    561   CallStub(&store_buffer_overflow);
    562   pop(r0);
    563   mtlr(r0);
    564   bind(&done);
    565   if (and_then == kReturnAtEnd) {
    566     Ret();
    567   }
    568 }
    569 
    570 void MacroAssembler::PushCommonFrame(Register marker_reg) {
    571   int fp_delta = 0;
    572   mflr(r0);
    573   if (FLAG_enable_embedded_constant_pool) {
    574     if (marker_reg.is_valid()) {
    575       Push(r0, fp, kConstantPoolRegister, marker_reg);
    576       fp_delta = 2;
    577     } else {
    578       Push(r0, fp, kConstantPoolRegister);
    579       fp_delta = 1;
    580     }
    581   } else {
    582     if (marker_reg.is_valid()) {
    583       Push(r0, fp, marker_reg);
    584       fp_delta = 1;
    585     } else {
    586       Push(r0, fp);
    587       fp_delta = 0;
    588     }
    589   }
    590   addi(fp, sp, Operand(fp_delta * kPointerSize));
    591 }
    592 
    593 void MacroAssembler::PopCommonFrame(Register marker_reg) {
    594   if (FLAG_enable_embedded_constant_pool) {
    595     if (marker_reg.is_valid()) {
    596       Pop(r0, fp, kConstantPoolRegister, marker_reg);
    597     } else {
    598       Pop(r0, fp, kConstantPoolRegister);
    599     }
    600   } else {
    601     if (marker_reg.is_valid()) {
    602       Pop(r0, fp, marker_reg);
    603     } else {
    604       Pop(r0, fp);
    605     }
    606   }
    607   mtlr(r0);
    608 }
    609 
    610 void MacroAssembler::PushStandardFrame(Register function_reg) {
    611   int fp_delta = 0;
    612   mflr(r0);
    613   if (FLAG_enable_embedded_constant_pool) {
    614     if (function_reg.is_valid()) {
    615       Push(r0, fp, kConstantPoolRegister, cp, function_reg);
    616       fp_delta = 3;
    617     } else {
    618       Push(r0, fp, kConstantPoolRegister, cp);
    619       fp_delta = 2;
    620     }
    621   } else {
    622     if (function_reg.is_valid()) {
    623       Push(r0, fp, cp, function_reg);
    624       fp_delta = 2;
    625     } else {
    626       Push(r0, fp, cp);
    627       fp_delta = 1;
    628     }
    629   }
    630   addi(fp, sp, Operand(fp_delta * kPointerSize));
    631 }
    632 
    633 void MacroAssembler::RestoreFrameStateForTailCall() {
    634   if (FLAG_enable_embedded_constant_pool) {
    635     LoadP(kConstantPoolRegister,
    636           MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
    637     set_constant_pool_available(false);
    638   }
    639   LoadP(r0, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
    640   LoadP(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
    641   mtlr(r0);
    642 }
    643 
    644 const RegList MacroAssembler::kSafepointSavedRegisters = Register::kAllocatable;
    645 const int MacroAssembler::kNumSafepointSavedRegisters =
    646     Register::kNumAllocatable;
    647 
    648 // Push and pop all registers that can hold pointers.
    649 void MacroAssembler::PushSafepointRegisters() {
    650   // Safepoints expect a block of kNumSafepointRegisters values on the
    651   // stack, so adjust the stack for unsaved registers.
    652   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
    653   DCHECK(num_unsaved >= 0);
    654   if (num_unsaved > 0) {
    655     subi(sp, sp, Operand(num_unsaved * kPointerSize));
    656   }
    657   MultiPush(kSafepointSavedRegisters);
    658 }
    659 
    660 
    661 void MacroAssembler::PopSafepointRegisters() {
    662   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
    663   MultiPop(kSafepointSavedRegisters);
    664   if (num_unsaved > 0) {
    665     addi(sp, sp, Operand(num_unsaved * kPointerSize));
    666   }
    667 }
    668 
    669 
    670 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
    671   StoreP(src, SafepointRegisterSlot(dst));
    672 }
    673 
    674 
    675 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
    676   LoadP(dst, SafepointRegisterSlot(src));
    677 }
    678 
    679 
    680 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
    681   // The registers are pushed starting with the highest encoding,
    682   // which means that lowest encodings are closest to the stack pointer.
    683   RegList regs = kSafepointSavedRegisters;
    684   int index = 0;
    685 
    686   DCHECK(reg_code >= 0 && reg_code < kNumRegisters);
    687 
    688   for (int16_t i = 0; i < reg_code; i++) {
    689     if ((regs & (1 << i)) != 0) {
    690       index++;
    691     }
    692   }
    693 
    694   return index;
    695 }
    696 
    697 
    698 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
    699   return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
    700 }
    701 
    702 
    703 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
    704   // General purpose registers are pushed last on the stack.
    705   const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
    706   int doubles_size = config->num_allocatable_double_registers() * kDoubleSize;
    707   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
    708   return MemOperand(sp, doubles_size + register_offset);
    709 }
    710 
    711 
    712 void MacroAssembler::CanonicalizeNaN(const DoubleRegister dst,
    713                                      const DoubleRegister src) {
    714   // Turn potential sNaN into qNaN.
    715   fsub(dst, src, kDoubleRegZero);
    716 }
    717 
    718 void MacroAssembler::ConvertIntToDouble(Register src, DoubleRegister dst) {
    719   MovIntToDouble(dst, src, r0);
    720   fcfid(dst, dst);
    721 }
    722 
    723 void MacroAssembler::ConvertUnsignedIntToDouble(Register src,
    724                                                 DoubleRegister dst) {
    725   MovUnsignedIntToDouble(dst, src, r0);
    726   fcfid(dst, dst);
    727 }
    728 
    729 void MacroAssembler::ConvertIntToFloat(Register src, DoubleRegister dst) {
    730   MovIntToDouble(dst, src, r0);
    731   fcfids(dst, dst);
    732 }
    733 
    734 void MacroAssembler::ConvertUnsignedIntToFloat(Register src,
    735                                                DoubleRegister dst) {
    736   MovUnsignedIntToDouble(dst, src, r0);
    737   fcfids(dst, dst);
    738 }
    739 
    740 #if V8_TARGET_ARCH_PPC64
    741 void MacroAssembler::ConvertInt64ToDouble(Register src,
    742                                           DoubleRegister double_dst) {
    743   MovInt64ToDouble(double_dst, src);
    744   fcfid(double_dst, double_dst);
    745 }
    746 
    747 
    748 void MacroAssembler::ConvertUnsignedInt64ToFloat(Register src,
    749                                                  DoubleRegister double_dst) {
    750   MovInt64ToDouble(double_dst, src);
    751   fcfidus(double_dst, double_dst);
    752 }
    753 
    754 
    755 void MacroAssembler::ConvertUnsignedInt64ToDouble(Register src,
    756                                                   DoubleRegister double_dst) {
    757   MovInt64ToDouble(double_dst, src);
    758   fcfidu(double_dst, double_dst);
    759 }
    760 
    761 
    762 void MacroAssembler::ConvertInt64ToFloat(Register src,
    763                                          DoubleRegister double_dst) {
    764   MovInt64ToDouble(double_dst, src);
    765   fcfids(double_dst, double_dst);
    766 }
    767 #endif
    768 
    769 
    770 void MacroAssembler::ConvertDoubleToInt64(const DoubleRegister double_input,
    771 #if !V8_TARGET_ARCH_PPC64
    772                                           const Register dst_hi,
    773 #endif
    774                                           const Register dst,
    775                                           const DoubleRegister double_dst,
    776                                           FPRoundingMode rounding_mode) {
    777   if (rounding_mode == kRoundToZero) {
    778     fctidz(double_dst, double_input);
    779   } else {
    780     SetRoundingMode(rounding_mode);
    781     fctid(double_dst, double_input);
    782     ResetRoundingMode();
    783   }
    784 
    785   MovDoubleToInt64(
    786 #if !V8_TARGET_ARCH_PPC64
    787       dst_hi,
    788 #endif
    789       dst, double_dst);
    790 }
    791 
    792 #if V8_TARGET_ARCH_PPC64
    793 void MacroAssembler::ConvertDoubleToUnsignedInt64(
    794     const DoubleRegister double_input, const Register dst,
    795     const DoubleRegister double_dst, FPRoundingMode rounding_mode) {
    796   if (rounding_mode == kRoundToZero) {
    797     fctiduz(double_dst, double_input);
    798   } else {
    799     SetRoundingMode(rounding_mode);
    800     fctidu(double_dst, double_input);
    801     ResetRoundingMode();
    802   }
    803 
    804   MovDoubleToInt64(dst, double_dst);
    805 }
    806 #endif
    807 
    808 #if !V8_TARGET_ARCH_PPC64
    809 void MacroAssembler::ShiftLeftPair(Register dst_low, Register dst_high,
    810                                    Register src_low, Register src_high,
    811                                    Register scratch, Register shift) {
    812   DCHECK(!AreAliased(dst_low, src_high, shift));
    813   DCHECK(!AreAliased(dst_high, src_low, shift));
    814   Label less_than_32;
    815   Label done;
    816   cmpi(shift, Operand(32));
    817   blt(&less_than_32);
    818   // If shift >= 32
    819   andi(scratch, shift, Operand(0x1f));
    820   slw(dst_high, src_low, scratch);
    821   li(dst_low, Operand::Zero());
    822   b(&done);
    823   bind(&less_than_32);
    824   // If shift < 32
    825   subfic(scratch, shift, Operand(32));
    826   slw(dst_high, src_high, shift);
    827   srw(scratch, src_low, scratch);
    828   orx(dst_high, dst_high, scratch);
    829   slw(dst_low, src_low, shift);
    830   bind(&done);
    831 }
    832 
    833 void MacroAssembler::ShiftLeftPair(Register dst_low, Register dst_high,
    834                                    Register src_low, Register src_high,
    835                                    uint32_t shift) {
    836   DCHECK(!AreAliased(dst_low, src_high));
    837   DCHECK(!AreAliased(dst_high, src_low));
    838   if (shift == 32) {
    839     Move(dst_high, src_low);
    840     li(dst_low, Operand::Zero());
    841   } else if (shift > 32) {
    842     shift &= 0x1f;
    843     slwi(dst_high, src_low, Operand(shift));
    844     li(dst_low, Operand::Zero());
    845   } else if (shift == 0) {
    846     Move(dst_low, src_low);
    847     Move(dst_high, src_high);
    848   } else {
    849     slwi(dst_high, src_high, Operand(shift));
    850     rlwimi(dst_high, src_low, shift, 32 - shift, 31);
    851     slwi(dst_low, src_low, Operand(shift));
    852   }
    853 }
    854 
    855 void MacroAssembler::ShiftRightPair(Register dst_low, Register dst_high,
    856                                     Register src_low, Register src_high,
    857                                     Register scratch, Register shift) {
    858   DCHECK(!AreAliased(dst_low, src_high, shift));
    859   DCHECK(!AreAliased(dst_high, src_low, shift));
    860   Label less_than_32;
    861   Label done;
    862   cmpi(shift, Operand(32));
    863   blt(&less_than_32);
    864   // If shift >= 32
    865   andi(scratch, shift, Operand(0x1f));
    866   srw(dst_low, src_high, scratch);
    867   li(dst_high, Operand::Zero());
    868   b(&done);
    869   bind(&less_than_32);
    870   // If shift < 32
    871   subfic(scratch, shift, Operand(32));
    872   srw(dst_low, src_low, shift);
    873   slw(scratch, src_high, scratch);
    874   orx(dst_low, dst_low, scratch);
    875   srw(dst_high, src_high, shift);
    876   bind(&done);
    877 }
    878 
    879 void MacroAssembler::ShiftRightPair(Register dst_low, Register dst_high,
    880                                     Register src_low, Register src_high,
    881                                     uint32_t shift) {
    882   DCHECK(!AreAliased(dst_low, src_high));
    883   DCHECK(!AreAliased(dst_high, src_low));
    884   if (shift == 32) {
    885     Move(dst_low, src_high);
    886     li(dst_high, Operand::Zero());
    887   } else if (shift > 32) {
    888     shift &= 0x1f;
    889     srwi(dst_low, src_high, Operand(shift));
    890     li(dst_high, Operand::Zero());
    891   } else if (shift == 0) {
    892     Move(dst_low, src_low);
    893     Move(dst_high, src_high);
    894   } else {
    895     srwi(dst_low, src_low, Operand(shift));
    896     rlwimi(dst_low, src_high, 32 - shift, 0, shift - 1);
    897     srwi(dst_high, src_high, Operand(shift));
    898   }
    899 }
    900 
    901 void MacroAssembler::ShiftRightAlgPair(Register dst_low, Register dst_high,
    902                                        Register src_low, Register src_high,
    903                                        Register scratch, Register shift) {
    904   DCHECK(!AreAliased(dst_low, src_high, shift));
    905   DCHECK(!AreAliased(dst_high, src_low, shift));
    906   Label less_than_32;
    907   Label done;
    908   cmpi(shift, Operand(32));
    909   blt(&less_than_32);
    910   // If shift >= 32
    911   andi(scratch, shift, Operand(0x1f));
    912   sraw(dst_low, src_high, scratch);
    913   srawi(dst_high, src_high, 31);
    914   b(&done);
    915   bind(&less_than_32);
    916   // If shift < 32
    917   subfic(scratch, shift, Operand(32));
    918   srw(dst_low, src_low, shift);
    919   slw(scratch, src_high, scratch);
    920   orx(dst_low, dst_low, scratch);
    921   sraw(dst_high, src_high, shift);
    922   bind(&done);
    923 }
    924 
    925 void MacroAssembler::ShiftRightAlgPair(Register dst_low, Register dst_high,
    926                                        Register src_low, Register src_high,
    927                                        uint32_t shift) {
    928   DCHECK(!AreAliased(dst_low, src_high));
    929   DCHECK(!AreAliased(dst_high, src_low));
    930   if (shift == 32) {
    931     Move(dst_low, src_high);
    932     srawi(dst_high, src_high, 31);
    933   } else if (shift > 32) {
    934     shift &= 0x1f;
    935     srawi(dst_low, src_high, shift);
    936     srawi(dst_high, src_high, 31);
    937   } else if (shift == 0) {
    938     Move(dst_low, src_low);
    939     Move(dst_high, src_high);
    940   } else {
    941     srwi(dst_low, src_low, Operand(shift));
    942     rlwimi(dst_low, src_high, 32 - shift, 0, shift - 1);
    943     srawi(dst_high, src_high, shift);
    944   }
    945 }
    946 #endif
    947 
    948 void MacroAssembler::LoadConstantPoolPointerRegisterFromCodeTargetAddress(
    949     Register code_target_address) {
    950   lwz(kConstantPoolRegister,
    951       MemOperand(code_target_address,
    952                  Code::kConstantPoolOffset - Code::kHeaderSize));
    953   add(kConstantPoolRegister, kConstantPoolRegister, code_target_address);
    954 }
    955 
    956 
    957 void MacroAssembler::LoadConstantPoolPointerRegister(Register base,
    958                                                      int code_start_delta) {
    959   add_label_offset(kConstantPoolRegister, base, ConstantPoolPosition(),
    960                    code_start_delta);
    961 }
    962 
    963 
    964 void MacroAssembler::LoadConstantPoolPointerRegister() {
    965   mov_label_addr(kConstantPoolRegister, ConstantPoolPosition());
    966 }
    967 
    968 void MacroAssembler::StubPrologue(StackFrame::Type type, Register base,
    969                                   int prologue_offset) {
    970   {
    971     ConstantPoolUnavailableScope constant_pool_unavailable(this);
    972     LoadSmiLiteral(r11, Smi::FromInt(type));
    973     PushCommonFrame(r11);
    974   }
    975   if (FLAG_enable_embedded_constant_pool) {
    976     if (!base.is(no_reg)) {
    977       // base contains prologue address
    978       LoadConstantPoolPointerRegister(base, -prologue_offset);
    979     } else {
    980       LoadConstantPoolPointerRegister();
    981     }
    982     set_constant_pool_available(true);
    983   }
    984 }
    985 
    986 
    987 void MacroAssembler::Prologue(bool code_pre_aging, Register base,
    988                               int prologue_offset) {
    989   DCHECK(!base.is(no_reg));
    990   {
    991     PredictableCodeSizeScope predictible_code_size_scope(
    992         this, kNoCodeAgeSequenceLength);
    993     Assembler::BlockTrampolinePoolScope block_trampoline_pool(this);
    994     // The following instructions must remain together and unmodified
    995     // for code aging to work properly.
    996     if (code_pre_aging) {
    997       // Pre-age the code.
    998       // This matches the code found in PatchPlatformCodeAge()
    999       Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
   1000       intptr_t target = reinterpret_cast<intptr_t>(stub->instruction_start());
   1001       // Don't use Call -- we need to preserve ip and lr
   1002       nop();  // marker to detect sequence (see IsOld)
   1003       mov(r3, Operand(target));
   1004       Jump(r3);
   1005       for (int i = 0; i < kCodeAgingSequenceNops; i++) {
   1006         nop();
   1007       }
   1008     } else {
   1009       // This matches the code found in GetNoCodeAgeSequence()
   1010       PushStandardFrame(r4);
   1011       for (int i = 0; i < kNoCodeAgeSequenceNops; i++) {
   1012         nop();
   1013       }
   1014     }
   1015   }
   1016   if (FLAG_enable_embedded_constant_pool) {
   1017     // base contains prologue address
   1018     LoadConstantPoolPointerRegister(base, -prologue_offset);
   1019     set_constant_pool_available(true);
   1020   }
   1021 }
   1022 
   1023 
   1024 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   1025   LoadP(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   1026   LoadP(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
   1027   LoadP(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
   1028 }
   1029 
   1030 
   1031 void MacroAssembler::EnterFrame(StackFrame::Type type,
   1032                                 bool load_constant_pool_pointer_reg) {
   1033   if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) {
   1034     // Push type explicitly so we can leverage the constant pool.
   1035     // This path cannot rely on ip containing code entry.
   1036     PushCommonFrame();
   1037     LoadConstantPoolPointerRegister();
   1038     LoadSmiLiteral(ip, Smi::FromInt(type));
   1039     push(ip);
   1040   } else {
   1041     LoadSmiLiteral(ip, Smi::FromInt(type));
   1042     PushCommonFrame(ip);
   1043   }
   1044   if (type == StackFrame::INTERNAL) {
   1045     mov(r0, Operand(CodeObject()));
   1046     push(r0);
   1047   }
   1048 }
   1049 
   1050 
   1051 int MacroAssembler::LeaveFrame(StackFrame::Type type, int stack_adjustment) {
   1052   ConstantPoolUnavailableScope constant_pool_unavailable(this);
   1053   // r3: preserved
   1054   // r4: preserved
   1055   // r5: preserved
   1056 
   1057   // Drop the execution stack down to the frame pointer and restore
   1058   // the caller's state.
   1059   int frame_ends;
   1060   LoadP(r0, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
   1061   LoadP(ip, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   1062   if (FLAG_enable_embedded_constant_pool) {
   1063     LoadP(kConstantPoolRegister,
   1064           MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
   1065   }
   1066   mtlr(r0);
   1067   frame_ends = pc_offset();
   1068   Add(sp, fp, StandardFrameConstants::kCallerSPOffset + stack_adjustment, r0);
   1069   mr(fp, ip);
   1070   return frame_ends;
   1071 }
   1072 
   1073 void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
   1074                                        Register argc) {
   1075   int fp_delta = 0;
   1076   mflr(r0);
   1077   if (FLAG_enable_embedded_constant_pool) {
   1078     if (target.is_valid()) {
   1079       Push(r0, fp, kConstantPoolRegister, context, target);
   1080       fp_delta = 3;
   1081     } else {
   1082       Push(r0, fp, kConstantPoolRegister, context);
   1083       fp_delta = 2;
   1084     }
   1085   } else {
   1086     if (target.is_valid()) {
   1087       Push(r0, fp, context, target);
   1088       fp_delta = 2;
   1089     } else {
   1090       Push(r0, fp, context);
   1091       fp_delta = 1;
   1092     }
   1093   }
   1094   addi(fp, sp, Operand(fp_delta * kPointerSize));
   1095   Push(argc);
   1096 }
   1097 
   1098 void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
   1099                                        Register argc) {
   1100   Pop(argc);
   1101   if (FLAG_enable_embedded_constant_pool) {
   1102     if (target.is_valid()) {
   1103       Pop(r0, fp, kConstantPoolRegister, context, target);
   1104     } else {
   1105       Pop(r0, fp, kConstantPoolRegister, context);
   1106     }
   1107   } else {
   1108     if (target.is_valid()) {
   1109       Pop(r0, fp, context, target);
   1110     } else {
   1111       Pop(r0, fp, context);
   1112     }
   1113   }
   1114   mtlr(r0);
   1115 }
   1116 
   1117 // ExitFrame layout (probably wrongish.. needs updating)
   1118 //
   1119 //  SP -> previousSP
   1120 //        LK reserved
   1121 //        code
   1122 //        sp_on_exit (for debug?)
   1123 // oldSP->prev SP
   1124 //        LK
   1125 //        <parameters on stack>
   1126 
   1127 // Prior to calling EnterExitFrame, we've got a bunch of parameters
   1128 // on the stack that we need to wrap a real frame around.. so first
   1129 // we reserve a slot for LK and push the previous SP which is captured
   1130 // in the fp register (r31)
   1131 // Then - we buy a new frame
   1132 
   1133 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
   1134                                     StackFrame::Type frame_type) {
   1135   DCHECK(frame_type == StackFrame::EXIT ||
   1136          frame_type == StackFrame::BUILTIN_EXIT);
   1137   // Set up the frame structure on the stack.
   1138   DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
   1139   DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
   1140   DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
   1141   DCHECK(stack_space > 0);
   1142 
   1143   // This is an opportunity to build a frame to wrap
   1144   // all of the pushes that have happened inside of V8
   1145   // since we were called from C code
   1146 
   1147   LoadSmiLiteral(ip, Smi::FromInt(frame_type));
   1148   PushCommonFrame(ip);
   1149   // Reserve room for saved entry sp and code object.
   1150   subi(sp, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp));
   1151 
   1152   if (emit_debug_code()) {
   1153     li(r8, Operand::Zero());
   1154     StoreP(r8, MemOperand(fp, ExitFrameConstants::kSPOffset));
   1155   }
   1156   if (FLAG_enable_embedded_constant_pool) {
   1157     StoreP(kConstantPoolRegister,
   1158            MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
   1159   }
   1160   mov(r8, Operand(CodeObject()));
   1161   StoreP(r8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
   1162 
   1163   // Save the frame pointer and the context in top.
   1164   mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
   1165   StoreP(fp, MemOperand(r8));
   1166   mov(r8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1167   StoreP(cp, MemOperand(r8));
   1168 
   1169   // Optionally save all volatile double registers.
   1170   if (save_doubles) {
   1171     MultiPushDoubles(kCallerSavedDoubles);
   1172     // Note that d0 will be accessible at
   1173     //   fp - ExitFrameConstants::kFrameSize -
   1174     //   kNumCallerSavedDoubles * kDoubleSize,
   1175     // since the sp slot and code slot were pushed after the fp.
   1176   }
   1177 
   1178   addi(sp, sp, Operand(-stack_space * kPointerSize));
   1179 
   1180   // Allocate and align the frame preparing for calling the runtime
   1181   // function.
   1182   const int frame_alignment = ActivationFrameAlignment();
   1183   if (frame_alignment > kPointerSize) {
   1184     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
   1185     ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
   1186   }
   1187   li(r0, Operand::Zero());
   1188   StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize));
   1189 
   1190   // Set the exit frame sp value to point just before the return address
   1191   // location.
   1192   addi(r8, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
   1193   StoreP(r8, MemOperand(fp, ExitFrameConstants::kSPOffset));
   1194 }
   1195 
   1196 
   1197 void MacroAssembler::InitializeNewString(Register string, Register length,
   1198                                          Heap::RootListIndex map_index,
   1199                                          Register scratch1, Register scratch2) {
   1200   SmiTag(scratch1, length);
   1201   LoadRoot(scratch2, map_index);
   1202   StoreP(scratch1, FieldMemOperand(string, String::kLengthOffset), r0);
   1203   li(scratch1, Operand(String::kEmptyHashField));
   1204   StoreP(scratch2, FieldMemOperand(string, HeapObject::kMapOffset), r0);
   1205   StoreP(scratch1, FieldMemOperand(string, String::kHashFieldSlot), r0);
   1206 }
   1207 
   1208 
   1209 int MacroAssembler::ActivationFrameAlignment() {
   1210 #if !defined(USE_SIMULATOR)
   1211   // Running on the real platform. Use the alignment as mandated by the local
   1212   // environment.
   1213   // Note: This will break if we ever start generating snapshots on one PPC
   1214   // platform for another PPC platform with a different alignment.
   1215   return base::OS::ActivationFrameAlignment();
   1216 #else  // Simulated
   1217   // If we are using the simulator then we should always align to the expected
   1218   // alignment. As the simulator is used to generate snapshots we do not know
   1219   // if the target platform will need alignment, so this is controlled from a
   1220   // flag.
   1221   return FLAG_sim_stack_alignment;
   1222 #endif
   1223 }
   1224 
   1225 
   1226 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
   1227                                     bool restore_context,
   1228                                     bool argument_count_is_length) {
   1229   ConstantPoolUnavailableScope constant_pool_unavailable(this);
   1230   // Optionally restore all double registers.
   1231   if (save_doubles) {
   1232     // Calculate the stack location of the saved doubles and restore them.
   1233     const int kNumRegs = kNumCallerSavedDoubles;
   1234     const int offset =
   1235         (ExitFrameConstants::kFixedFrameSizeFromFp + kNumRegs * kDoubleSize);
   1236     addi(r6, fp, Operand(-offset));
   1237     MultiPopDoubles(kCallerSavedDoubles, r6);
   1238   }
   1239 
   1240   // Clear top frame.
   1241   li(r6, Operand::Zero());
   1242   mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
   1243   StoreP(r6, MemOperand(ip));
   1244 
   1245   // Restore current context from top and clear it in debug mode.
   1246   if (restore_context) {
   1247     mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1248     LoadP(cp, MemOperand(ip));
   1249   }
   1250 #ifdef DEBUG
   1251   mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1252   StoreP(r6, MemOperand(ip));
   1253 #endif
   1254 
   1255   // Tear down the exit frame, pop the arguments, and return.
   1256   LeaveFrame(StackFrame::EXIT);
   1257 
   1258   if (argument_count.is_valid()) {
   1259     if (!argument_count_is_length) {
   1260       ShiftLeftImm(argument_count, argument_count, Operand(kPointerSizeLog2));
   1261     }
   1262     add(sp, sp, argument_count);
   1263   }
   1264 }
   1265 
   1266 
   1267 void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) {
   1268   Move(dst, d1);
   1269 }
   1270 
   1271 
   1272 void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) {
   1273   Move(dst, d1);
   1274 }
   1275 
   1276 void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
   1277                                         Register caller_args_count_reg,
   1278                                         Register scratch0, Register scratch1) {
   1279 #if DEBUG
   1280   if (callee_args_count.is_reg()) {
   1281     DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
   1282                        scratch1));
   1283   } else {
   1284     DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
   1285   }
   1286 #endif
   1287 
   1288   // Calculate the end of destination area where we will put the arguments
   1289   // after we drop current frame. We add kPointerSize to count the receiver
   1290   // argument which is not included into formal parameters count.
   1291   Register dst_reg = scratch0;
   1292   ShiftLeftImm(dst_reg, caller_args_count_reg, Operand(kPointerSizeLog2));
   1293   add(dst_reg, fp, dst_reg);
   1294   addi(dst_reg, dst_reg,
   1295        Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
   1296 
   1297   Register src_reg = caller_args_count_reg;
   1298   // Calculate the end of source area. +kPointerSize is for the receiver.
   1299   if (callee_args_count.is_reg()) {
   1300     ShiftLeftImm(src_reg, callee_args_count.reg(), Operand(kPointerSizeLog2));
   1301     add(src_reg, sp, src_reg);
   1302     addi(src_reg, src_reg, Operand(kPointerSize));
   1303   } else {
   1304     Add(src_reg, sp, (callee_args_count.immediate() + 1) * kPointerSize, r0);
   1305   }
   1306 
   1307   if (FLAG_debug_code) {
   1308     cmpl(src_reg, dst_reg);
   1309     Check(lt, kStackAccessBelowStackPointer);
   1310   }
   1311 
   1312   // Restore caller's frame pointer and return address now as they will be
   1313   // overwritten by the copying loop.
   1314   RestoreFrameStateForTailCall();
   1315 
   1316   // Now copy callee arguments to the caller frame going backwards to avoid
   1317   // callee arguments corruption (source and destination areas could overlap).
   1318 
   1319   // Both src_reg and dst_reg are pointing to the word after the one to copy,
   1320   // so they must be pre-decremented in the loop.
   1321   Register tmp_reg = scratch1;
   1322   Label loop;
   1323   if (callee_args_count.is_reg()) {
   1324     addi(tmp_reg, callee_args_count.reg(), Operand(1));  // +1 for receiver
   1325   } else {
   1326     mov(tmp_reg, Operand(callee_args_count.immediate() + 1));
   1327   }
   1328   mtctr(tmp_reg);
   1329   bind(&loop);
   1330   LoadPU(tmp_reg, MemOperand(src_reg, -kPointerSize));
   1331   StorePU(tmp_reg, MemOperand(dst_reg, -kPointerSize));
   1332   bdnz(&loop);
   1333 
   1334   // Leave current frame.
   1335   mr(sp, dst_reg);
   1336 }
   1337 
   1338 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
   1339                                     const ParameterCount& actual, Label* done,
   1340                                     bool* definitely_mismatches,
   1341                                     InvokeFlag flag,
   1342                                     const CallWrapper& call_wrapper) {
   1343   bool definitely_matches = false;
   1344   *definitely_mismatches = false;
   1345   Label regular_invoke;
   1346 
   1347   // Check whether the expected and actual arguments count match. If not,
   1348   // setup registers according to contract with ArgumentsAdaptorTrampoline:
   1349   //  r3: actual arguments count
   1350   //  r4: function (passed through to callee)
   1351   //  r5: expected arguments count
   1352 
   1353   // The code below is made a lot easier because the calling code already sets
   1354   // up actual and expected registers according to the contract if values are
   1355   // passed in registers.
   1356 
   1357   // ARM has some sanity checks as per below, considering add them for PPC
   1358   //  DCHECK(actual.is_immediate() || actual.reg().is(r3));
   1359   //  DCHECK(expected.is_immediate() || expected.reg().is(r5));
   1360 
   1361   if (expected.is_immediate()) {
   1362     DCHECK(actual.is_immediate());
   1363     mov(r3, Operand(actual.immediate()));
   1364     if (expected.immediate() == actual.immediate()) {
   1365       definitely_matches = true;
   1366     } else {
   1367       const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
   1368       if (expected.immediate() == sentinel) {
   1369         // Don't worry about adapting arguments for builtins that
   1370         // don't want that done. Skip adaption code by making it look
   1371         // like we have a match between expected and actual number of
   1372         // arguments.
   1373         definitely_matches = true;
   1374       } else {
   1375         *definitely_mismatches = true;
   1376         mov(r5, Operand(expected.immediate()));
   1377       }
   1378     }
   1379   } else {
   1380     if (actual.is_immediate()) {
   1381       mov(r3, Operand(actual.immediate()));
   1382       cmpi(expected.reg(), Operand(actual.immediate()));
   1383       beq(&regular_invoke);
   1384     } else {
   1385       cmp(expected.reg(), actual.reg());
   1386       beq(&regular_invoke);
   1387     }
   1388   }
   1389 
   1390   if (!definitely_matches) {
   1391     Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
   1392     if (flag == CALL_FUNCTION) {
   1393       call_wrapper.BeforeCall(CallSize(adaptor));
   1394       Call(adaptor);
   1395       call_wrapper.AfterCall();
   1396       if (!*definitely_mismatches) {
   1397         b(done);
   1398       }
   1399     } else {
   1400       Jump(adaptor, RelocInfo::CODE_TARGET);
   1401     }
   1402     bind(&regular_invoke);
   1403   }
   1404 }
   1405 
   1406 
   1407 void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
   1408                                              const ParameterCount& expected,
   1409                                              const ParameterCount& actual) {
   1410   Label skip_flooding;
   1411   ExternalReference last_step_action =
   1412       ExternalReference::debug_last_step_action_address(isolate());
   1413   STATIC_ASSERT(StepFrame > StepIn);
   1414   mov(r7, Operand(last_step_action));
   1415   LoadByte(r7, MemOperand(r7), r0);
   1416   extsb(r7, r7);
   1417   cmpi(r7, Operand(StepIn));
   1418   blt(&skip_flooding);
   1419   {
   1420     FrameScope frame(this,
   1421                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
   1422     if (expected.is_reg()) {
   1423       SmiTag(expected.reg());
   1424       Push(expected.reg());
   1425     }
   1426     if (actual.is_reg()) {
   1427       SmiTag(actual.reg());
   1428       Push(actual.reg());
   1429     }
   1430     if (new_target.is_valid()) {
   1431       Push(new_target);
   1432     }
   1433     Push(fun, fun);
   1434     CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
   1435     Pop(fun);
   1436     if (new_target.is_valid()) {
   1437       Pop(new_target);
   1438     }
   1439     if (actual.is_reg()) {
   1440       Pop(actual.reg());
   1441       SmiUntag(actual.reg());
   1442     }
   1443     if (expected.is_reg()) {
   1444       Pop(expected.reg());
   1445       SmiUntag(expected.reg());
   1446     }
   1447   }
   1448   bind(&skip_flooding);
   1449 }
   1450 
   1451 
   1452 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
   1453                                         const ParameterCount& expected,
   1454                                         const ParameterCount& actual,
   1455                                         InvokeFlag flag,
   1456                                         const CallWrapper& call_wrapper) {
   1457   // You can't call a function without a valid frame.
   1458   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1459   DCHECK(function.is(r4));
   1460   DCHECK_IMPLIES(new_target.is_valid(), new_target.is(r6));
   1461 
   1462   if (call_wrapper.NeedsDebugStepCheck()) {
   1463     FloodFunctionIfStepping(function, new_target, expected, actual);
   1464   }
   1465 
   1466   // Clear the new.target register if not given.
   1467   if (!new_target.is_valid()) {
   1468     LoadRoot(r6, Heap::kUndefinedValueRootIndex);
   1469   }
   1470 
   1471   Label done;
   1472   bool definitely_mismatches = false;
   1473   InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
   1474                  call_wrapper);
   1475   if (!definitely_mismatches) {
   1476     // We call indirectly through the code field in the function to
   1477     // allow recompilation to take effect without changing any of the
   1478     // call sites.
   1479     Register code = ip;
   1480     LoadP(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
   1481     if (flag == CALL_FUNCTION) {
   1482       call_wrapper.BeforeCall(CallSize(code));
   1483       CallJSEntry(code);
   1484       call_wrapper.AfterCall();
   1485     } else {
   1486       DCHECK(flag == JUMP_FUNCTION);
   1487       JumpToJSEntry(code);
   1488     }
   1489 
   1490     // Continue here if InvokePrologue does handle the invocation due to
   1491     // mismatched parameter counts.
   1492     bind(&done);
   1493   }
   1494 }
   1495 
   1496 
   1497 void MacroAssembler::InvokeFunction(Register fun, Register new_target,
   1498                                     const ParameterCount& actual,
   1499                                     InvokeFlag flag,
   1500                                     const CallWrapper& call_wrapper) {
   1501   // You can't call a function without a valid frame.
   1502   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1503 
   1504   // Contract with called JS functions requires that function is passed in r4.
   1505   DCHECK(fun.is(r4));
   1506 
   1507   Register expected_reg = r5;
   1508   Register temp_reg = r7;
   1509 
   1510   LoadP(temp_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
   1511   LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
   1512   LoadWordArith(expected_reg,
   1513                 FieldMemOperand(
   1514                     temp_reg, SharedFunctionInfo::kFormalParameterCountOffset));
   1515 #if !defined(V8_TARGET_ARCH_PPC64)
   1516   SmiUntag(expected_reg);
   1517 #endif
   1518 
   1519   ParameterCount expected(expected_reg);
   1520   InvokeFunctionCode(fun, new_target, expected, actual, flag, call_wrapper);
   1521 }
   1522 
   1523 
   1524 void MacroAssembler::InvokeFunction(Register function,
   1525                                     const ParameterCount& expected,
   1526                                     const ParameterCount& actual,
   1527                                     InvokeFlag flag,
   1528                                     const CallWrapper& call_wrapper) {
   1529   // You can't call a function without a valid frame.
   1530   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1531 
   1532   // Contract with called JS functions requires that function is passed in r4.
   1533   DCHECK(function.is(r4));
   1534 
   1535   // Get the function and setup the context.
   1536   LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
   1537 
   1538   InvokeFunctionCode(r4, no_reg, expected, actual, flag, call_wrapper);
   1539 }
   1540 
   1541 
   1542 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
   1543                                     const ParameterCount& expected,
   1544                                     const ParameterCount& actual,
   1545                                     InvokeFlag flag,
   1546                                     const CallWrapper& call_wrapper) {
   1547   Move(r4, function);
   1548   InvokeFunction(r4, expected, actual, flag, call_wrapper);
   1549 }
   1550 
   1551 
   1552 void MacroAssembler::IsObjectJSStringType(Register object, Register scratch,
   1553                                           Label* fail) {
   1554   DCHECK(kNotStringTag != 0);
   1555 
   1556   LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   1557   lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   1558   andi(r0, scratch, Operand(kIsNotStringMask));
   1559   bne(fail, cr0);
   1560 }
   1561 
   1562 
   1563 void MacroAssembler::IsObjectNameType(Register object, Register scratch,
   1564                                       Label* fail) {
   1565   LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   1566   lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   1567   cmpi(scratch, Operand(LAST_NAME_TYPE));
   1568   bgt(fail);
   1569 }
   1570 
   1571 
   1572 void MacroAssembler::DebugBreak() {
   1573   li(r3, Operand::Zero());
   1574   mov(r4,
   1575       Operand(ExternalReference(Runtime::kHandleDebuggerStatement, isolate())));
   1576   CEntryStub ces(isolate(), 1);
   1577   DCHECK(AllowThisStubCall(&ces));
   1578   Call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
   1579 }
   1580 
   1581 
   1582 void MacroAssembler::PushStackHandler() {
   1583   // Adjust this code if not the case.
   1584   STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
   1585   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
   1586 
   1587   // Link the current handler as the next handler.
   1588   // Preserve r3-r7.
   1589   mov(r8, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   1590   LoadP(r0, MemOperand(r8));
   1591   push(r0);
   1592 
   1593   // Set this new handler as the current one.
   1594   StoreP(sp, MemOperand(r8));
   1595 }
   1596 
   1597 
   1598 void MacroAssembler::PopStackHandler() {
   1599   STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
   1600   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   1601 
   1602   pop(r4);
   1603   mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   1604   StoreP(r4, MemOperand(ip));
   1605 }
   1606 
   1607 
   1608 // Compute the hash code from the untagged key.  This must be kept in sync with
   1609 // ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
   1610 // code-stub-hydrogen.cc
   1611 void MacroAssembler::GetNumberHash(Register t0, Register scratch) {
   1612   // First of all we assign the hash seed to scratch.
   1613   LoadRoot(scratch, Heap::kHashSeedRootIndex);
   1614   SmiUntag(scratch);
   1615 
   1616   // Xor original key with a seed.
   1617   xor_(t0, t0, scratch);
   1618 
   1619   // Compute the hash code from the untagged key.  This must be kept in sync
   1620   // with ComputeIntegerHash in utils.h.
   1621   //
   1622   // hash = ~hash + (hash << 15);
   1623   notx(scratch, t0);
   1624   slwi(t0, t0, Operand(15));
   1625   add(t0, scratch, t0);
   1626   // hash = hash ^ (hash >> 12);
   1627   srwi(scratch, t0, Operand(12));
   1628   xor_(t0, t0, scratch);
   1629   // hash = hash + (hash << 2);
   1630   slwi(scratch, t0, Operand(2));
   1631   add(t0, t0, scratch);
   1632   // hash = hash ^ (hash >> 4);
   1633   srwi(scratch, t0, Operand(4));
   1634   xor_(t0, t0, scratch);
   1635   // hash = hash * 2057;
   1636   mr(r0, t0);
   1637   slwi(scratch, t0, Operand(3));
   1638   add(t0, t0, scratch);
   1639   slwi(scratch, r0, Operand(11));
   1640   add(t0, t0, scratch);
   1641   // hash = hash ^ (hash >> 16);
   1642   srwi(scratch, t0, Operand(16));
   1643   xor_(t0, t0, scratch);
   1644   // hash & 0x3fffffff
   1645   ExtractBitRange(t0, t0, 29, 0);
   1646 }
   1647 
   1648 void MacroAssembler::Allocate(int object_size, Register result,
   1649                               Register scratch1, Register scratch2,
   1650                               Label* gc_required, AllocationFlags flags) {
   1651   DCHECK(object_size <= kMaxRegularHeapObjectSize);
   1652   DCHECK((flags & ALLOCATION_FOLDED) == 0);
   1653   if (!FLAG_inline_new) {
   1654     if (emit_debug_code()) {
   1655       // Trash the registers to simulate an allocation failure.
   1656       li(result, Operand(0x7091));
   1657       li(scratch1, Operand(0x7191));
   1658       li(scratch2, Operand(0x7291));
   1659     }
   1660     b(gc_required);
   1661     return;
   1662   }
   1663 
   1664   DCHECK(!AreAliased(result, scratch1, scratch2, ip));
   1665 
   1666   // Make object size into bytes.
   1667   if ((flags & SIZE_IN_WORDS) != 0) {
   1668     object_size *= kPointerSize;
   1669   }
   1670   DCHECK_EQ(0, static_cast<int>(object_size & kObjectAlignmentMask));
   1671 
   1672   // Check relative positions of allocation top and limit addresses.
   1673   ExternalReference allocation_top =
   1674       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1675   ExternalReference allocation_limit =
   1676       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   1677 
   1678   intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
   1679   intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
   1680   DCHECK((limit - top) == kPointerSize);
   1681 
   1682   // Set up allocation top address register.
   1683   Register top_address = scratch1;
   1684   // This code stores a temporary value in ip. This is OK, as the code below
   1685   // does not need ip for implicit literal generation.
   1686   Register alloc_limit = ip;
   1687   Register result_end = scratch2;
   1688   mov(top_address, Operand(allocation_top));
   1689 
   1690   if ((flags & RESULT_CONTAINS_TOP) == 0) {
   1691     // Load allocation top into result and allocation limit into ip.
   1692     LoadP(result, MemOperand(top_address));
   1693     LoadP(alloc_limit, MemOperand(top_address, kPointerSize));
   1694   } else {
   1695     if (emit_debug_code()) {
   1696       // Assert that result actually contains top on entry.
   1697       LoadP(alloc_limit, MemOperand(top_address));
   1698       cmp(result, alloc_limit);
   1699       Check(eq, kUnexpectedAllocationTop);
   1700     }
   1701     // Load allocation limit. Result already contains allocation top.
   1702     LoadP(alloc_limit, MemOperand(top_address, limit - top));
   1703   }
   1704 
   1705   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1706     // Align the next allocation. Storing the filler map without checking top is
   1707     // safe in new-space because the limit of the heap is aligned there.
   1708 #if V8_TARGET_ARCH_PPC64
   1709     STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
   1710 #else
   1711     STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   1712     andi(result_end, result, Operand(kDoubleAlignmentMask));
   1713     Label aligned;
   1714     beq(&aligned, cr0);
   1715     if ((flags & PRETENURE) != 0) {
   1716       cmpl(result, alloc_limit);
   1717       bge(gc_required);
   1718     }
   1719     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   1720     stw(result_end, MemOperand(result));
   1721     addi(result, result, Operand(kDoubleSize / 2));
   1722     bind(&aligned);
   1723 #endif
   1724   }
   1725 
   1726   // Calculate new top and bail out if new space is exhausted. Use result
   1727   // to calculate the new top.
   1728   sub(r0, alloc_limit, result);
   1729   if (is_int16(object_size)) {
   1730     cmpi(r0, Operand(object_size));
   1731     blt(gc_required);
   1732     addi(result_end, result, Operand(object_size));
   1733   } else {
   1734     Cmpi(r0, Operand(object_size), result_end);
   1735     blt(gc_required);
   1736     add(result_end, result, result_end);
   1737   }
   1738 
   1739   if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
   1740     // The top pointer is not updated for allocation folding dominators.
   1741     StoreP(result_end, MemOperand(top_address));
   1742   }
   1743 
   1744   // Tag object.
   1745   addi(result, result, Operand(kHeapObjectTag));
   1746 }
   1747 
   1748 
   1749 void MacroAssembler::Allocate(Register object_size, Register result,
   1750                               Register result_end, Register scratch,
   1751                               Label* gc_required, AllocationFlags flags) {
   1752   DCHECK((flags & ALLOCATION_FOLDED) == 0);
   1753   if (!FLAG_inline_new) {
   1754     if (emit_debug_code()) {
   1755       // Trash the registers to simulate an allocation failure.
   1756       li(result, Operand(0x7091));
   1757       li(scratch, Operand(0x7191));
   1758       li(result_end, Operand(0x7291));
   1759     }
   1760     b(gc_required);
   1761     return;
   1762   }
   1763 
   1764   // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
   1765   // is not specified. Other registers must not overlap.
   1766   DCHECK(!AreAliased(object_size, result, scratch, ip));
   1767   DCHECK(!AreAliased(result_end, result, scratch, ip));
   1768   DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
   1769 
   1770   // Check relative positions of allocation top and limit addresses.
   1771   ExternalReference allocation_top =
   1772       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1773   ExternalReference allocation_limit =
   1774       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   1775   intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
   1776   intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
   1777   DCHECK((limit - top) == kPointerSize);
   1778 
   1779   // Set up allocation top address and allocation limit registers.
   1780   Register top_address = scratch;
   1781   // This code stores a temporary value in ip. This is OK, as the code below
   1782   // does not need ip for implicit literal generation.
   1783   Register alloc_limit = ip;
   1784   mov(top_address, Operand(allocation_top));
   1785 
   1786   if ((flags & RESULT_CONTAINS_TOP) == 0) {
   1787     // Load allocation top into result and allocation limit into alloc_limit..
   1788     LoadP(result, MemOperand(top_address));
   1789     LoadP(alloc_limit, MemOperand(top_address, kPointerSize));
   1790   } else {
   1791     if (emit_debug_code()) {
   1792       // Assert that result actually contains top on entry.
   1793       LoadP(alloc_limit, MemOperand(top_address));
   1794       cmp(result, alloc_limit);
   1795       Check(eq, kUnexpectedAllocationTop);
   1796     }
   1797     // Load allocation limit. Result already contains allocation top.
   1798     LoadP(alloc_limit, MemOperand(top_address, limit - top));
   1799   }
   1800 
   1801   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1802     // Align the next allocation. Storing the filler map without checking top is
   1803     // safe in new-space because the limit of the heap is aligned there.
   1804 #if V8_TARGET_ARCH_PPC64
   1805     STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
   1806 #else
   1807     STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   1808     andi(result_end, result, Operand(kDoubleAlignmentMask));
   1809     Label aligned;
   1810     beq(&aligned, cr0);
   1811     if ((flags & PRETENURE) != 0) {
   1812       cmpl(result, alloc_limit);
   1813       bge(gc_required);
   1814     }
   1815     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   1816     stw(result_end, MemOperand(result));
   1817     addi(result, result, Operand(kDoubleSize / 2));
   1818     bind(&aligned);
   1819 #endif
   1820   }
   1821 
   1822   // Calculate new top and bail out if new space is exhausted. Use result
   1823   // to calculate the new top. Object size may be in words so a shift is
   1824   // required to get the number of bytes.
   1825   sub(r0, alloc_limit, result);
   1826   if ((flags & SIZE_IN_WORDS) != 0) {
   1827     ShiftLeftImm(result_end, object_size, Operand(kPointerSizeLog2));
   1828     cmp(r0, result_end);
   1829     blt(gc_required);
   1830     add(result_end, result, result_end);
   1831   } else {
   1832     cmp(r0, object_size);
   1833     blt(gc_required);
   1834     add(result_end, result, object_size);
   1835   }
   1836 
   1837   // Update allocation top. result temporarily holds the new top.
   1838   if (emit_debug_code()) {
   1839     andi(r0, result_end, Operand(kObjectAlignmentMask));
   1840     Check(eq, kUnalignedAllocationInNewSpace, cr0);
   1841   }
   1842   if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
   1843     // The top pointer is not updated for allocation folding dominators.
   1844     StoreP(result_end, MemOperand(top_address));
   1845   }
   1846 
   1847   // Tag object.
   1848   addi(result, result, Operand(kHeapObjectTag));
   1849 }
   1850 
   1851 void MacroAssembler::FastAllocate(Register object_size, Register result,
   1852                                   Register result_end, Register scratch,
   1853                                   AllocationFlags flags) {
   1854   // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
   1855   // is not specified. Other registers must not overlap.
   1856   DCHECK(!AreAliased(object_size, result, scratch, ip));
   1857   DCHECK(!AreAliased(result_end, result, scratch, ip));
   1858   DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
   1859 
   1860   ExternalReference allocation_top =
   1861       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1862 
   1863   Register top_address = scratch;
   1864   mov(top_address, Operand(allocation_top));
   1865   LoadP(result, MemOperand(top_address));
   1866 
   1867   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1868     // Align the next allocation. Storing the filler map without checking top is
   1869     // safe in new-space because the limit of the heap is aligned there.
   1870 #if V8_TARGET_ARCH_PPC64
   1871     STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
   1872 #else
   1873     DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
   1874     andi(result_end, result, Operand(kDoubleAlignmentMask));
   1875     Label aligned;
   1876     beq(&aligned);
   1877     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   1878     stw(result_end, MemOperand(result));
   1879     addi(result, result, Operand(kDoubleSize / 2));
   1880     bind(&aligned);
   1881 #endif
   1882   }
   1883 
   1884   // Calculate new top using result. Object size may be in words so a shift is
   1885   // required to get the number of bytes.
   1886   if ((flags & SIZE_IN_WORDS) != 0) {
   1887     ShiftLeftImm(result_end, object_size, Operand(kPointerSizeLog2));
   1888     add(result_end, result, result_end);
   1889   } else {
   1890     add(result_end, result, object_size);
   1891   }
   1892 
   1893   // Update allocation top. result temporarily holds the new top.
   1894   if (emit_debug_code()) {
   1895     andi(r0, result_end, Operand(kObjectAlignmentMask));
   1896     Check(eq, kUnalignedAllocationInNewSpace, cr0);
   1897   }
   1898   StoreP(result_end, MemOperand(top_address));
   1899 
   1900   // Tag object.
   1901   addi(result, result, Operand(kHeapObjectTag));
   1902 }
   1903 
   1904 void MacroAssembler::FastAllocate(int object_size, Register result,
   1905                                   Register scratch1, Register scratch2,
   1906                                   AllocationFlags flags) {
   1907   DCHECK(object_size <= kMaxRegularHeapObjectSize);
   1908   DCHECK(!AreAliased(result, scratch1, scratch2, ip));
   1909 
   1910   // Make object size into bytes.
   1911   if ((flags & SIZE_IN_WORDS) != 0) {
   1912     object_size *= kPointerSize;
   1913   }
   1914   DCHECK_EQ(0, object_size & kObjectAlignmentMask);
   1915 
   1916   ExternalReference allocation_top =
   1917       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1918 
   1919   // Set up allocation top address register.
   1920   Register top_address = scratch1;
   1921   Register result_end = scratch2;
   1922   mov(top_address, Operand(allocation_top));
   1923   LoadP(result, MemOperand(top_address));
   1924 
   1925   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1926     // Align the next allocation. Storing the filler map without checking top is
   1927     // safe in new-space because the limit of the heap is aligned there.
   1928 #if V8_TARGET_ARCH_PPC64
   1929     STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
   1930 #else
   1931     DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
   1932     andi(result_end, result, Operand(kDoubleAlignmentMask));
   1933     Label aligned;
   1934     beq(&aligned);
   1935     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   1936     stw(result_end, MemOperand(result));
   1937     addi(result, result, Operand(kDoubleSize / 2));
   1938     bind(&aligned);
   1939 #endif
   1940   }
   1941 
   1942   // Calculate new top using result.
   1943   Add(result_end, result, object_size, r0);
   1944 
   1945   // The top pointer is not updated for allocation folding dominators.
   1946   StoreP(result_end, MemOperand(top_address));
   1947 
   1948   // Tag object.
   1949   addi(result, result, Operand(kHeapObjectTag));
   1950 }
   1951 
   1952 
   1953 void MacroAssembler::AllocateTwoByteString(Register result, Register length,
   1954                                            Register scratch1, Register scratch2,
   1955                                            Register scratch3,
   1956                                            Label* gc_required) {
   1957   // Calculate the number of bytes needed for the characters in the string while
   1958   // observing object alignment.
   1959   DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
   1960   slwi(scratch1, length, Operand(1));  // Length in bytes, not chars.
   1961   addi(scratch1, scratch1,
   1962        Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize));
   1963   mov(r0, Operand(~kObjectAlignmentMask));
   1964   and_(scratch1, scratch1, r0);
   1965 
   1966   // Allocate two-byte string in new space.
   1967   Allocate(scratch1, result, scratch2, scratch3, gc_required,
   1968            NO_ALLOCATION_FLAGS);
   1969 
   1970   // Set the map, length and hash field.
   1971   InitializeNewString(result, length, Heap::kStringMapRootIndex, scratch1,
   1972                       scratch2);
   1973 }
   1974 
   1975 
   1976 void MacroAssembler::AllocateOneByteString(Register result, Register length,
   1977                                            Register scratch1, Register scratch2,
   1978                                            Register scratch3,
   1979                                            Label* gc_required) {
   1980   // Calculate the number of bytes needed for the characters in the string while
   1981   // observing object alignment.
   1982   DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
   1983   DCHECK(kCharSize == 1);
   1984   addi(scratch1, length,
   1985        Operand(kObjectAlignmentMask + SeqOneByteString::kHeaderSize));
   1986   li(r0, Operand(~kObjectAlignmentMask));
   1987   and_(scratch1, scratch1, r0);
   1988 
   1989   // Allocate one-byte string in new space.
   1990   Allocate(scratch1, result, scratch2, scratch3, gc_required,
   1991            NO_ALLOCATION_FLAGS);
   1992 
   1993   // Set the map, length and hash field.
   1994   InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
   1995                       scratch1, scratch2);
   1996 }
   1997 
   1998 
   1999 void MacroAssembler::AllocateTwoByteConsString(Register result, Register length,
   2000                                                Register scratch1,
   2001                                                Register scratch2,
   2002                                                Label* gc_required) {
   2003   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
   2004            NO_ALLOCATION_FLAGS);
   2005 
   2006   InitializeNewString(result, length, Heap::kConsStringMapRootIndex, scratch1,
   2007                       scratch2);
   2008 }
   2009 
   2010 
   2011 void MacroAssembler::AllocateOneByteConsString(Register result, Register length,
   2012                                                Register scratch1,
   2013                                                Register scratch2,
   2014                                                Label* gc_required) {
   2015   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
   2016            NO_ALLOCATION_FLAGS);
   2017 
   2018   InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
   2019                       scratch1, scratch2);
   2020 }
   2021 
   2022 
   2023 void MacroAssembler::AllocateTwoByteSlicedString(Register result,
   2024                                                  Register length,
   2025                                                  Register scratch1,
   2026                                                  Register scratch2,
   2027                                                  Label* gc_required) {
   2028   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
   2029            NO_ALLOCATION_FLAGS);
   2030 
   2031   InitializeNewString(result, length, Heap::kSlicedStringMapRootIndex, scratch1,
   2032                       scratch2);
   2033 }
   2034 
   2035 
   2036 void MacroAssembler::AllocateOneByteSlicedString(Register result,
   2037                                                  Register length,
   2038                                                  Register scratch1,
   2039                                                  Register scratch2,
   2040                                                  Label* gc_required) {
   2041   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
   2042            NO_ALLOCATION_FLAGS);
   2043 
   2044   InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
   2045                       scratch1, scratch2);
   2046 }
   2047 
   2048 
   2049 void MacroAssembler::CompareObjectType(Register object, Register map,
   2050                                        Register type_reg, InstanceType type) {
   2051   const Register temp = type_reg.is(no_reg) ? r0 : type_reg;
   2052 
   2053   LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
   2054   CompareInstanceType(map, temp, type);
   2055 }
   2056 
   2057 
   2058 void MacroAssembler::CompareInstanceType(Register map, Register type_reg,
   2059                                          InstanceType type) {
   2060   STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
   2061   STATIC_ASSERT(LAST_TYPE < 256);
   2062   lbz(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
   2063   cmpi(type_reg, Operand(type));
   2064 }
   2065 
   2066 
   2067 void MacroAssembler::CompareRoot(Register obj, Heap::RootListIndex index) {
   2068   DCHECK(!obj.is(r0));
   2069   LoadRoot(r0, index);
   2070   cmp(obj, r0);
   2071 }
   2072 
   2073 void MacroAssembler::CheckFastObjectElements(Register map, Register scratch,
   2074                                              Label* fail) {
   2075   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   2076   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   2077   STATIC_ASSERT(FAST_ELEMENTS == 2);
   2078   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
   2079   lbz(scratch, FieldMemOperand(map, Map::kBitField2Offset));
   2080   cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
   2081   ble(fail);
   2082   cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue));
   2083   bgt(fail);
   2084 }
   2085 
   2086 
   2087 void MacroAssembler::CheckFastSmiElements(Register map, Register scratch,
   2088                                           Label* fail) {
   2089   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   2090   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   2091   lbz(scratch, FieldMemOperand(map, Map::kBitField2Offset));
   2092   cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
   2093   bgt(fail);
   2094 }
   2095 
   2096 
   2097 void MacroAssembler::StoreNumberToDoubleElements(
   2098     Register value_reg, Register key_reg, Register elements_reg,
   2099     Register scratch1, DoubleRegister double_scratch, Label* fail,
   2100     int elements_offset) {
   2101   DCHECK(!AreAliased(value_reg, key_reg, elements_reg, scratch1));
   2102   Label smi_value, store;
   2103 
   2104   // Handle smi values specially.
   2105   JumpIfSmi(value_reg, &smi_value);
   2106 
   2107   // Ensure that the object is a heap number
   2108   CheckMap(value_reg, scratch1, isolate()->factory()->heap_number_map(), fail,
   2109            DONT_DO_SMI_CHECK);
   2110 
   2111   lfd(double_scratch, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
   2112   // Double value, turn potential sNaN into qNaN.
   2113   CanonicalizeNaN(double_scratch);
   2114   b(&store);
   2115 
   2116   bind(&smi_value);
   2117   SmiToDouble(double_scratch, value_reg);
   2118 
   2119   bind(&store);
   2120   SmiToDoubleArrayOffset(scratch1, key_reg);
   2121   add(scratch1, elements_reg, scratch1);
   2122   stfd(double_scratch, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize -
   2123                                                      elements_offset));
   2124 }
   2125 
   2126 
   2127 void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left,
   2128                                             Register right,
   2129                                             Register overflow_dst,
   2130                                             Register scratch) {
   2131   DCHECK(!dst.is(overflow_dst));
   2132   DCHECK(!dst.is(scratch));
   2133   DCHECK(!overflow_dst.is(scratch));
   2134   DCHECK(!overflow_dst.is(left));
   2135   DCHECK(!overflow_dst.is(right));
   2136 
   2137   bool left_is_right = left.is(right);
   2138   RCBit xorRC = left_is_right ? SetRC : LeaveRC;
   2139 
   2140   // C = A+B; C overflows if A/B have same sign and C has diff sign than A
   2141   if (dst.is(left)) {
   2142     mr(scratch, left);            // Preserve left.
   2143     add(dst, left, right);        // Left is overwritten.
   2144     xor_(overflow_dst, dst, scratch, xorRC);  // Original left.
   2145     if (!left_is_right) xor_(scratch, dst, right);
   2146   } else if (dst.is(right)) {
   2147     mr(scratch, right);           // Preserve right.
   2148     add(dst, left, right);        // Right is overwritten.
   2149     xor_(overflow_dst, dst, left, xorRC);
   2150     if (!left_is_right) xor_(scratch, dst, scratch);  // Original right.
   2151   } else {
   2152     add(dst, left, right);
   2153     xor_(overflow_dst, dst, left, xorRC);
   2154     if (!left_is_right) xor_(scratch, dst, right);
   2155   }
   2156   if (!left_is_right) and_(overflow_dst, scratch, overflow_dst, SetRC);
   2157 }
   2158 
   2159 
   2160 void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left,
   2161                                             intptr_t right,
   2162                                             Register overflow_dst,
   2163                                             Register scratch) {
   2164   Register original_left = left;
   2165   DCHECK(!dst.is(overflow_dst));
   2166   DCHECK(!dst.is(scratch));
   2167   DCHECK(!overflow_dst.is(scratch));
   2168   DCHECK(!overflow_dst.is(left));
   2169 
   2170   // C = A+B; C overflows if A/B have same sign and C has diff sign than A
   2171   if (dst.is(left)) {
   2172     // Preserve left.
   2173     original_left = overflow_dst;
   2174     mr(original_left, left);
   2175   }
   2176   Add(dst, left, right, scratch);
   2177   xor_(overflow_dst, dst, original_left);
   2178   if (right >= 0) {
   2179     and_(overflow_dst, overflow_dst, dst, SetRC);
   2180   } else {
   2181     andc(overflow_dst, overflow_dst, dst, SetRC);
   2182   }
   2183 }
   2184 
   2185 
   2186 void MacroAssembler::SubAndCheckForOverflow(Register dst, Register left,
   2187                                             Register right,
   2188                                             Register overflow_dst,
   2189                                             Register scratch) {
   2190   DCHECK(!dst.is(overflow_dst));
   2191   DCHECK(!dst.is(scratch));
   2192   DCHECK(!overflow_dst.is(scratch));
   2193   DCHECK(!overflow_dst.is(left));
   2194   DCHECK(!overflow_dst.is(right));
   2195 
   2196   // C = A-B; C overflows if A/B have diff signs and C has diff sign than A
   2197   if (dst.is(left)) {
   2198     mr(scratch, left);      // Preserve left.
   2199     sub(dst, left, right);  // Left is overwritten.
   2200     xor_(overflow_dst, dst, scratch);
   2201     xor_(scratch, scratch, right);
   2202     and_(overflow_dst, overflow_dst, scratch, SetRC);
   2203   } else if (dst.is(right)) {
   2204     mr(scratch, right);     // Preserve right.
   2205     sub(dst, left, right);  // Right is overwritten.
   2206     xor_(overflow_dst, dst, left);
   2207     xor_(scratch, left, scratch);
   2208     and_(overflow_dst, overflow_dst, scratch, SetRC);
   2209   } else {
   2210     sub(dst, left, right);
   2211     xor_(overflow_dst, dst, left);
   2212     xor_(scratch, left, right);
   2213     and_(overflow_dst, scratch, overflow_dst, SetRC);
   2214   }
   2215 }
   2216 
   2217 
   2218 void MacroAssembler::CompareMap(Register obj, Register scratch, Handle<Map> map,
   2219                                 Label* early_success) {
   2220   LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   2221   CompareMap(scratch, map, early_success);
   2222 }
   2223 
   2224 
   2225 void MacroAssembler::CompareMap(Register obj_map, Handle<Map> map,
   2226                                 Label* early_success) {
   2227   mov(r0, Operand(map));
   2228   cmp(obj_map, r0);
   2229 }
   2230 
   2231 
   2232 void MacroAssembler::CheckMap(Register obj, Register scratch, Handle<Map> map,
   2233                               Label* fail, SmiCheckType smi_check_type) {
   2234   if (smi_check_type == DO_SMI_CHECK) {
   2235     JumpIfSmi(obj, fail);
   2236   }
   2237 
   2238   Label success;
   2239   CompareMap(obj, scratch, map, &success);
   2240   bne(fail);
   2241   bind(&success);
   2242 }
   2243 
   2244 
   2245 void MacroAssembler::CheckMap(Register obj, Register scratch,
   2246                               Heap::RootListIndex index, Label* fail,
   2247                               SmiCheckType smi_check_type) {
   2248   if (smi_check_type == DO_SMI_CHECK) {
   2249     JumpIfSmi(obj, fail);
   2250   }
   2251   LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   2252   LoadRoot(r0, index);
   2253   cmp(scratch, r0);
   2254   bne(fail);
   2255 }
   2256 
   2257 
   2258 void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
   2259                                      Register scratch2, Handle<WeakCell> cell,
   2260                                      Handle<Code> success,
   2261                                      SmiCheckType smi_check_type) {
   2262   Label fail;
   2263   if (smi_check_type == DO_SMI_CHECK) {
   2264     JumpIfSmi(obj, &fail);
   2265   }
   2266   LoadP(scratch1, FieldMemOperand(obj, HeapObject::kMapOffset));
   2267   CmpWeakValue(scratch1, cell, scratch2);
   2268   Jump(success, RelocInfo::CODE_TARGET, eq);
   2269   bind(&fail);
   2270 }
   2271 
   2272 
   2273 void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
   2274                                   Register scratch, CRegister cr) {
   2275   mov(scratch, Operand(cell));
   2276   LoadP(scratch, FieldMemOperand(scratch, WeakCell::kValueOffset));
   2277   cmp(value, scratch, cr);
   2278 }
   2279 
   2280 
   2281 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
   2282   mov(value, Operand(cell));
   2283   LoadP(value, FieldMemOperand(value, WeakCell::kValueOffset));
   2284 }
   2285 
   2286 
   2287 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
   2288                                    Label* miss) {
   2289   GetWeakValue(value, cell);
   2290   JumpIfSmi(value, miss);
   2291 }
   2292 
   2293 
   2294 void MacroAssembler::GetMapConstructor(Register result, Register map,
   2295                                        Register temp, Register temp2) {
   2296   Label done, loop;
   2297   LoadP(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
   2298   bind(&loop);
   2299   JumpIfSmi(result, &done);
   2300   CompareObjectType(result, temp, temp2, MAP_TYPE);
   2301   bne(&done);
   2302   LoadP(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
   2303   b(&loop);
   2304   bind(&done);
   2305 }
   2306 
   2307 
   2308 void MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
   2309                                              Register scratch, Label* miss) {
   2310   // Get the prototype or initial map from the function.
   2311   LoadP(result,
   2312         FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   2313 
   2314   // If the prototype or initial map is the hole, don't return it and
   2315   // simply miss the cache instead. This will allow us to allocate a
   2316   // prototype object on-demand in the runtime system.
   2317   LoadRoot(r0, Heap::kTheHoleValueRootIndex);
   2318   cmp(result, r0);
   2319   beq(miss);
   2320 
   2321   // If the function does not have an initial map, we're done.
   2322   Label done;
   2323   CompareObjectType(result, scratch, scratch, MAP_TYPE);
   2324   bne(&done);
   2325 
   2326   // Get the prototype from the initial map.
   2327   LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset));
   2328 
   2329   // All done.
   2330   bind(&done);
   2331 }
   2332 
   2333 
   2334 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id,
   2335                               Condition cond) {
   2336   DCHECK(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
   2337   Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond);
   2338 }
   2339 
   2340 
   2341 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
   2342   Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
   2343 }
   2344 
   2345 
   2346 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   2347   return has_frame_ || !stub->SometimesSetsUpAFrame();
   2348 }
   2349 
   2350 void MacroAssembler::SmiToDouble(DoubleRegister value, Register smi) {
   2351   SmiUntag(ip, smi);
   2352   ConvertIntToDouble(ip, value);
   2353 }
   2354 
   2355 
   2356 void MacroAssembler::TestDoubleIsInt32(DoubleRegister double_input,
   2357                                        Register scratch1, Register scratch2,
   2358                                        DoubleRegister double_scratch) {
   2359   TryDoubleToInt32Exact(scratch1, double_input, scratch2, double_scratch);
   2360 }
   2361 
   2362 void MacroAssembler::TestDoubleIsMinusZero(DoubleRegister input,
   2363                                            Register scratch1,
   2364                                            Register scratch2) {
   2365 #if V8_TARGET_ARCH_PPC64
   2366   MovDoubleToInt64(scratch1, input);
   2367   rotldi(scratch1, scratch1, 1);
   2368   cmpi(scratch1, Operand(1));
   2369 #else
   2370   MovDoubleToInt64(scratch1, scratch2, input);
   2371   Label done;
   2372   cmpi(scratch2, Operand::Zero());
   2373   bne(&done);
   2374   lis(scratch2, Operand(SIGN_EXT_IMM16(0x8000)));
   2375   cmp(scratch1, scratch2);
   2376   bind(&done);
   2377 #endif
   2378 }
   2379 
   2380 void MacroAssembler::TestDoubleSign(DoubleRegister input, Register scratch) {
   2381 #if V8_TARGET_ARCH_PPC64
   2382   MovDoubleToInt64(scratch, input);
   2383 #else
   2384   MovDoubleHighToInt(scratch, input);
   2385 #endif
   2386   cmpi(scratch, Operand::Zero());
   2387 }
   2388 
   2389 void MacroAssembler::TestHeapNumberSign(Register input, Register scratch) {
   2390 #if V8_TARGET_ARCH_PPC64
   2391   LoadP(scratch, FieldMemOperand(input, HeapNumber::kValueOffset));
   2392 #else
   2393   lwz(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset));
   2394 #endif
   2395   cmpi(scratch, Operand::Zero());
   2396 }
   2397 
   2398 void MacroAssembler::TryDoubleToInt32Exact(Register result,
   2399                                            DoubleRegister double_input,
   2400                                            Register scratch,
   2401                                            DoubleRegister double_scratch) {
   2402   Label done;
   2403   DCHECK(!double_input.is(double_scratch));
   2404 
   2405   ConvertDoubleToInt64(double_input,
   2406 #if !V8_TARGET_ARCH_PPC64
   2407                        scratch,
   2408 #endif
   2409                        result, double_scratch);
   2410 
   2411 #if V8_TARGET_ARCH_PPC64
   2412   TestIfInt32(result, r0);
   2413 #else
   2414   TestIfInt32(scratch, result, r0);
   2415 #endif
   2416   bne(&done);
   2417 
   2418   // convert back and compare
   2419   fcfid(double_scratch, double_scratch);
   2420   fcmpu(double_scratch, double_input);
   2421   bind(&done);
   2422 }
   2423 
   2424 
   2425 void MacroAssembler::TryInt32Floor(Register result, DoubleRegister double_input,
   2426                                    Register input_high, Register scratch,
   2427                                    DoubleRegister double_scratch, Label* done,
   2428                                    Label* exact) {
   2429   DCHECK(!result.is(input_high));
   2430   DCHECK(!double_input.is(double_scratch));
   2431   Label exception;
   2432 
   2433   MovDoubleHighToInt(input_high, double_input);
   2434 
   2435   // Test for NaN/Inf
   2436   ExtractBitMask(result, input_high, HeapNumber::kExponentMask);
   2437   cmpli(result, Operand(0x7ff));
   2438   beq(&exception);
   2439 
   2440   // Convert (rounding to -Inf)
   2441   ConvertDoubleToInt64(double_input,
   2442 #if !V8_TARGET_ARCH_PPC64
   2443                        scratch,
   2444 #endif
   2445                        result, double_scratch, kRoundToMinusInf);
   2446 
   2447 // Test for overflow
   2448 #if V8_TARGET_ARCH_PPC64
   2449   TestIfInt32(result, r0);
   2450 #else
   2451   TestIfInt32(scratch, result, r0);
   2452 #endif
   2453   bne(&exception);
   2454 
   2455   // Test for exactness
   2456   fcfid(double_scratch, double_scratch);
   2457   fcmpu(double_scratch, double_input);
   2458   beq(exact);
   2459   b(done);
   2460 
   2461   bind(&exception);
   2462 }
   2463 
   2464 
   2465 void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
   2466                                                 DoubleRegister double_input,
   2467                                                 Label* done) {
   2468   DoubleRegister double_scratch = kScratchDoubleReg;
   2469 #if !V8_TARGET_ARCH_PPC64
   2470   Register scratch = ip;
   2471 #endif
   2472 
   2473   ConvertDoubleToInt64(double_input,
   2474 #if !V8_TARGET_ARCH_PPC64
   2475                        scratch,
   2476 #endif
   2477                        result, double_scratch);
   2478 
   2479 // Test for overflow
   2480 #if V8_TARGET_ARCH_PPC64
   2481   TestIfInt32(result, r0);
   2482 #else
   2483   TestIfInt32(scratch, result, r0);
   2484 #endif
   2485   beq(done);
   2486 }
   2487 
   2488 
   2489 void MacroAssembler::TruncateDoubleToI(Register result,
   2490                                        DoubleRegister double_input) {
   2491   Label done;
   2492 
   2493   TryInlineTruncateDoubleToI(result, double_input, &done);
   2494 
   2495   // If we fell through then inline version didn't succeed - call stub instead.
   2496   mflr(r0);
   2497   push(r0);
   2498   // Put input on stack.
   2499   stfdu(double_input, MemOperand(sp, -kDoubleSize));
   2500 
   2501   DoubleToIStub stub(isolate(), sp, result, 0, true, true);
   2502   CallStub(&stub);
   2503 
   2504   addi(sp, sp, Operand(kDoubleSize));
   2505   pop(r0);
   2506   mtlr(r0);
   2507 
   2508   bind(&done);
   2509 }
   2510 
   2511 
   2512 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
   2513   Label done;
   2514   DoubleRegister double_scratch = kScratchDoubleReg;
   2515   DCHECK(!result.is(object));
   2516 
   2517   lfd(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
   2518   TryInlineTruncateDoubleToI(result, double_scratch, &done);
   2519 
   2520   // If we fell through then inline version didn't succeed - call stub instead.
   2521   mflr(r0);
   2522   push(r0);
   2523   DoubleToIStub stub(isolate(), object, result,
   2524                      HeapNumber::kValueOffset - kHeapObjectTag, true, true);
   2525   CallStub(&stub);
   2526   pop(r0);
   2527   mtlr(r0);
   2528 
   2529   bind(&done);
   2530 }
   2531 
   2532 
   2533 void MacroAssembler::TruncateNumberToI(Register object, Register result,
   2534                                        Register heap_number_map,
   2535                                        Register scratch1, Label* not_number) {
   2536   Label done;
   2537   DCHECK(!result.is(object));
   2538 
   2539   UntagAndJumpIfSmi(result, object, &done);
   2540   JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
   2541   TruncateHeapNumberToI(result, object);
   2542 
   2543   bind(&done);
   2544 }
   2545 
   2546 
   2547 void MacroAssembler::GetLeastBitsFromSmi(Register dst, Register src,
   2548                                          int num_least_bits) {
   2549 #if V8_TARGET_ARCH_PPC64
   2550   rldicl(dst, src, kBitsPerPointer - kSmiShift,
   2551          kBitsPerPointer - num_least_bits);
   2552 #else
   2553   rlwinm(dst, src, kBitsPerPointer - kSmiShift,
   2554          kBitsPerPointer - num_least_bits, 31);
   2555 #endif
   2556 }
   2557 
   2558 
   2559 void MacroAssembler::GetLeastBitsFromInt32(Register dst, Register src,
   2560                                            int num_least_bits) {
   2561   rlwinm(dst, src, 0, 32 - num_least_bits, 31);
   2562 }
   2563 
   2564 
   2565 void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
   2566                                  SaveFPRegsMode save_doubles) {
   2567   // All parameters are on the stack.  r3 has the return value after call.
   2568 
   2569   // If the expected number of arguments of the runtime function is
   2570   // constant, we check that the actual number of arguments match the
   2571   // expectation.
   2572   CHECK(f->nargs < 0 || f->nargs == num_arguments);
   2573 
   2574   // TODO(1236192): Most runtime routines don't need the number of
   2575   // arguments passed in because it is constant. At some point we
   2576   // should remove this need and make the runtime routine entry code
   2577   // smarter.
   2578   mov(r3, Operand(num_arguments));
   2579   mov(r4, Operand(ExternalReference(f, isolate())));
   2580   CEntryStub stub(isolate(),
   2581 #if V8_TARGET_ARCH_PPC64
   2582                   f->result_size,
   2583 #else
   2584                   1,
   2585 #endif
   2586                   save_doubles);
   2587   CallStub(&stub);
   2588 }
   2589 
   2590 
   2591 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
   2592                                            int num_arguments) {
   2593   mov(r3, Operand(num_arguments));
   2594   mov(r4, Operand(ext));
   2595 
   2596   CEntryStub stub(isolate(), 1);
   2597   CallStub(&stub);
   2598 }
   2599 
   2600 
   2601 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
   2602   const Runtime::Function* function = Runtime::FunctionForId(fid);
   2603   DCHECK_EQ(1, function->result_size);
   2604   if (function->nargs >= 0) {
   2605     mov(r3, Operand(function->nargs));
   2606   }
   2607   JumpToExternalReference(ExternalReference(fid, isolate()));
   2608 }
   2609 
   2610 
   2611 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
   2612                                              bool builtin_exit_frame) {
   2613   mov(r4, Operand(builtin));
   2614   CEntryStub stub(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
   2615                   builtin_exit_frame);
   2616   Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
   2617 }
   2618 
   2619 
   2620 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
   2621                                 Register scratch1, Register scratch2) {
   2622   if (FLAG_native_code_counters && counter->Enabled()) {
   2623     mov(scratch1, Operand(value));
   2624     mov(scratch2, Operand(ExternalReference(counter)));
   2625     stw(scratch1, MemOperand(scratch2));
   2626   }
   2627 }
   2628 
   2629 
   2630 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
   2631                                       Register scratch1, Register scratch2) {
   2632   DCHECK(value > 0);
   2633   if (FLAG_native_code_counters && counter->Enabled()) {
   2634     mov(scratch2, Operand(ExternalReference(counter)));
   2635     lwz(scratch1, MemOperand(scratch2));
   2636     addi(scratch1, scratch1, Operand(value));
   2637     stw(scratch1, MemOperand(scratch2));
   2638   }
   2639 }
   2640 
   2641 
   2642 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
   2643                                       Register scratch1, Register scratch2) {
   2644   DCHECK(value > 0);
   2645   if (FLAG_native_code_counters && counter->Enabled()) {
   2646     mov(scratch2, Operand(ExternalReference(counter)));
   2647     lwz(scratch1, MemOperand(scratch2));
   2648     subi(scratch1, scratch1, Operand(value));
   2649     stw(scratch1, MemOperand(scratch2));
   2650   }
   2651 }
   2652 
   2653 
   2654 void MacroAssembler::Assert(Condition cond, BailoutReason reason,
   2655                             CRegister cr) {
   2656   if (emit_debug_code()) Check(cond, reason, cr);
   2657 }
   2658 
   2659 
   2660 void MacroAssembler::AssertFastElements(Register elements) {
   2661   if (emit_debug_code()) {
   2662     DCHECK(!elements.is(r0));
   2663     Label ok;
   2664     push(elements);
   2665     LoadP(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
   2666     LoadRoot(r0, Heap::kFixedArrayMapRootIndex);
   2667     cmp(elements, r0);
   2668     beq(&ok);
   2669     LoadRoot(r0, Heap::kFixedDoubleArrayMapRootIndex);
   2670     cmp(elements, r0);
   2671     beq(&ok);
   2672     LoadRoot(r0, Heap::kFixedCOWArrayMapRootIndex);
   2673     cmp(elements, r0);
   2674     beq(&ok);
   2675     Abort(kJSObjectWithFastElementsMapHasSlowElements);
   2676     bind(&ok);
   2677     pop(elements);
   2678   }
   2679 }
   2680 
   2681 
   2682 void MacroAssembler::Check(Condition cond, BailoutReason reason, CRegister cr) {
   2683   Label L;
   2684   b(cond, &L, cr);
   2685   Abort(reason);
   2686   // will not return here
   2687   bind(&L);
   2688 }
   2689 
   2690 
   2691 void MacroAssembler::Abort(BailoutReason reason) {
   2692   Label abort_start;
   2693   bind(&abort_start);
   2694 #ifdef DEBUG
   2695   const char* msg = GetBailoutReason(reason);
   2696   if (msg != NULL) {
   2697     RecordComment("Abort message: ");
   2698     RecordComment(msg);
   2699   }
   2700 
   2701   if (FLAG_trap_on_abort) {
   2702     stop(msg);
   2703     return;
   2704   }
   2705 #endif
   2706 
   2707   // Check if Abort() has already been initialized.
   2708   DCHECK(isolate()->builtins()->Abort()->IsHeapObject());
   2709 
   2710   LoadSmiLiteral(r4, Smi::FromInt(static_cast<int>(reason)));
   2711 
   2712   // Disable stub call restrictions to always allow calls to abort.
   2713   if (!has_frame_) {
   2714     // We don't actually want to generate a pile of code for this, so just
   2715     // claim there is a stack frame, without generating one.
   2716     FrameScope scope(this, StackFrame::NONE);
   2717     Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
   2718   } else {
   2719     Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
   2720   }
   2721   // will not return here
   2722 }
   2723 
   2724 
   2725 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
   2726   if (context_chain_length > 0) {
   2727     // Move up the chain of contexts to the context containing the slot.
   2728     LoadP(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2729     for (int i = 1; i < context_chain_length; i++) {
   2730       LoadP(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2731     }
   2732   } else {
   2733     // Slot is in the current function context.  Move it into the
   2734     // destination register in case we store into it (the write barrier
   2735     // cannot be allowed to destroy the context in esi).
   2736     mr(dst, cp);
   2737   }
   2738 }
   2739 
   2740 
   2741 void MacroAssembler::LoadTransitionedArrayMapConditional(
   2742     ElementsKind expected_kind, ElementsKind transitioned_kind,
   2743     Register map_in_out, Register scratch, Label* no_map_match) {
   2744   DCHECK(IsFastElementsKind(expected_kind));
   2745   DCHECK(IsFastElementsKind(transitioned_kind));
   2746 
   2747   // Check that the function's map is the same as the expected cached map.
   2748   LoadP(scratch, NativeContextMemOperand());
   2749   LoadP(ip, ContextMemOperand(scratch, Context::ArrayMapIndex(expected_kind)));
   2750   cmp(map_in_out, ip);
   2751   bne(no_map_match);
   2752 
   2753   // Use the transitioned cached map.
   2754   LoadP(map_in_out,
   2755         ContextMemOperand(scratch, Context::ArrayMapIndex(transitioned_kind)));
   2756 }
   2757 
   2758 
   2759 void MacroAssembler::LoadNativeContextSlot(int index, Register dst) {
   2760   LoadP(dst, NativeContextMemOperand());
   2761   LoadP(dst, ContextMemOperand(dst, index));
   2762 }
   2763 
   2764 
   2765 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
   2766                                                   Register map,
   2767                                                   Register scratch) {
   2768   // Load the initial map. The global functions all have initial maps.
   2769   LoadP(map,
   2770         FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   2771   if (emit_debug_code()) {
   2772     Label ok, fail;
   2773     CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
   2774     b(&ok);
   2775     bind(&fail);
   2776     Abort(kGlobalFunctionsMustHaveInitialMap);
   2777     bind(&ok);
   2778   }
   2779 }
   2780 
   2781 
   2782 void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
   2783     Register reg, Register scratch, Label* not_power_of_two_or_zero) {
   2784   subi(scratch, reg, Operand(1));
   2785   cmpi(scratch, Operand::Zero());
   2786   blt(not_power_of_two_or_zero);
   2787   and_(r0, scratch, reg, SetRC);
   2788   bne(not_power_of_two_or_zero, cr0);
   2789 }
   2790 
   2791 
   2792 void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
   2793                                                      Register scratch,
   2794                                                      Label* zero_and_neg,
   2795                                                      Label* not_power_of_two) {
   2796   subi(scratch, reg, Operand(1));
   2797   cmpi(scratch, Operand::Zero());
   2798   blt(zero_and_neg);
   2799   and_(r0, scratch, reg, SetRC);
   2800   bne(not_power_of_two, cr0);
   2801 }
   2802 
   2803 #if !V8_TARGET_ARCH_PPC64
   2804 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
   2805   DCHECK(!reg.is(overflow));
   2806   mr(overflow, reg);  // Save original value.
   2807   SmiTag(reg);
   2808   xor_(overflow, overflow, reg, SetRC);  // Overflow if (value ^ 2 * value) < 0.
   2809 }
   2810 
   2811 
   2812 void MacroAssembler::SmiTagCheckOverflow(Register dst, Register src,
   2813                                          Register overflow) {
   2814   if (dst.is(src)) {
   2815     // Fall back to slower case.
   2816     SmiTagCheckOverflow(dst, overflow);
   2817   } else {
   2818     DCHECK(!dst.is(src));
   2819     DCHECK(!dst.is(overflow));
   2820     DCHECK(!src.is(overflow));
   2821     SmiTag(dst, src);
   2822     xor_(overflow, dst, src, SetRC);  // Overflow if (value ^ 2 * value) < 0.
   2823   }
   2824 }
   2825 #endif
   2826 
   2827 void MacroAssembler::JumpIfNotBothSmi(Register reg1, Register reg2,
   2828                                       Label* on_not_both_smi) {
   2829   STATIC_ASSERT(kSmiTag == 0);
   2830   orx(r0, reg1, reg2, LeaveRC);
   2831   JumpIfNotSmi(r0, on_not_both_smi);
   2832 }
   2833 
   2834 
   2835 void MacroAssembler::UntagAndJumpIfSmi(Register dst, Register src,
   2836                                        Label* smi_case) {
   2837   STATIC_ASSERT(kSmiTag == 0);
   2838   TestBitRange(src, kSmiTagSize - 1, 0, r0);
   2839   SmiUntag(dst, src);
   2840   beq(smi_case, cr0);
   2841 }
   2842 
   2843 
   2844 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, Register src,
   2845                                           Label* non_smi_case) {
   2846   STATIC_ASSERT(kSmiTag == 0);
   2847   TestBitRange(src, kSmiTagSize - 1, 0, r0);
   2848   SmiUntag(dst, src);
   2849   bne(non_smi_case, cr0);
   2850 }
   2851 
   2852 
   2853 void MacroAssembler::JumpIfEitherSmi(Register reg1, Register reg2,
   2854                                      Label* on_either_smi) {
   2855   STATIC_ASSERT(kSmiTag == 0);
   2856   JumpIfSmi(reg1, on_either_smi);
   2857   JumpIfSmi(reg2, on_either_smi);
   2858 }
   2859 
   2860 void MacroAssembler::AssertNotNumber(Register object) {
   2861   if (emit_debug_code()) {
   2862     STATIC_ASSERT(kSmiTag == 0);
   2863     TestIfSmi(object, r0);
   2864     Check(ne, kOperandIsANumber, cr0);
   2865     push(object);
   2866     CompareObjectType(object, object, object, HEAP_NUMBER_TYPE);
   2867     pop(object);
   2868     Check(ne, kOperandIsANumber);
   2869   }
   2870 }
   2871 
   2872 void MacroAssembler::AssertNotSmi(Register object) {
   2873   if (emit_debug_code()) {
   2874     STATIC_ASSERT(kSmiTag == 0);
   2875     TestIfSmi(object, r0);
   2876     Check(ne, kOperandIsASmi, cr0);
   2877   }
   2878 }
   2879 
   2880 
   2881 void MacroAssembler::AssertSmi(Register object) {
   2882   if (emit_debug_code()) {
   2883     STATIC_ASSERT(kSmiTag == 0);
   2884     TestIfSmi(object, r0);
   2885     Check(eq, kOperandIsNotSmi, cr0);
   2886   }
   2887 }
   2888 
   2889 
   2890 void MacroAssembler::AssertString(Register object) {
   2891   if (emit_debug_code()) {
   2892     STATIC_ASSERT(kSmiTag == 0);
   2893     TestIfSmi(object, r0);
   2894     Check(ne, kOperandIsASmiAndNotAString, cr0);
   2895     push(object);
   2896     LoadP(object, FieldMemOperand(object, HeapObject::kMapOffset));
   2897     CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
   2898     pop(object);
   2899     Check(lt, kOperandIsNotAString);
   2900   }
   2901 }
   2902 
   2903 
   2904 void MacroAssembler::AssertName(Register object) {
   2905   if (emit_debug_code()) {
   2906     STATIC_ASSERT(kSmiTag == 0);
   2907     TestIfSmi(object, r0);
   2908     Check(ne, kOperandIsASmiAndNotAName, cr0);
   2909     push(object);
   2910     LoadP(object, FieldMemOperand(object, HeapObject::kMapOffset));
   2911     CompareInstanceType(object, object, LAST_NAME_TYPE);
   2912     pop(object);
   2913     Check(le, kOperandIsNotAName);
   2914   }
   2915 }
   2916 
   2917 
   2918 void MacroAssembler::AssertFunction(Register object) {
   2919   if (emit_debug_code()) {
   2920     STATIC_ASSERT(kSmiTag == 0);
   2921     TestIfSmi(object, r0);
   2922     Check(ne, kOperandIsASmiAndNotAFunction, cr0);
   2923     push(object);
   2924     CompareObjectType(object, object, object, JS_FUNCTION_TYPE);
   2925     pop(object);
   2926     Check(eq, kOperandIsNotAFunction);
   2927   }
   2928 }
   2929 
   2930 
   2931 void MacroAssembler::AssertBoundFunction(Register object) {
   2932   if (emit_debug_code()) {
   2933     STATIC_ASSERT(kSmiTag == 0);
   2934     TestIfSmi(object, r0);
   2935     Check(ne, kOperandIsASmiAndNotABoundFunction, cr0);
   2936     push(object);
   2937     CompareObjectType(object, object, object, JS_BOUND_FUNCTION_TYPE);
   2938     pop(object);
   2939     Check(eq, kOperandIsNotABoundFunction);
   2940   }
   2941 }
   2942 
   2943 void MacroAssembler::AssertGeneratorObject(Register object) {
   2944   if (emit_debug_code()) {
   2945     STATIC_ASSERT(kSmiTag == 0);
   2946     TestIfSmi(object, r0);
   2947     Check(ne, kOperandIsASmiAndNotAGeneratorObject, cr0);
   2948     push(object);
   2949     CompareObjectType(object, object, object, JS_GENERATOR_OBJECT_TYPE);
   2950     pop(object);
   2951     Check(eq, kOperandIsNotAGeneratorObject);
   2952   }
   2953 }
   2954 
   2955 void MacroAssembler::AssertReceiver(Register object) {
   2956   if (emit_debug_code()) {
   2957     STATIC_ASSERT(kSmiTag == 0);
   2958     TestIfSmi(object, r0);
   2959     Check(ne, kOperandIsASmiAndNotAReceiver, cr0);
   2960     push(object);
   2961     STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
   2962     CompareObjectType(object, object, object, FIRST_JS_RECEIVER_TYPE);
   2963     pop(object);
   2964     Check(ge, kOperandIsNotAReceiver);
   2965   }
   2966 }
   2967 
   2968 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
   2969                                                      Register scratch) {
   2970   if (emit_debug_code()) {
   2971     Label done_checking;
   2972     AssertNotSmi(object);
   2973     CompareRoot(object, Heap::kUndefinedValueRootIndex);
   2974     beq(&done_checking);
   2975     LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   2976     CompareRoot(scratch, Heap::kAllocationSiteMapRootIndex);
   2977     Assert(eq, kExpectedUndefinedOrCell);
   2978     bind(&done_checking);
   2979   }
   2980 }
   2981 
   2982 
   2983 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
   2984   if (emit_debug_code()) {
   2985     CompareRoot(reg, index);
   2986     Check(eq, kHeapNumberMapRegisterClobbered);
   2987   }
   2988 }
   2989 
   2990 
   2991 void MacroAssembler::JumpIfNotHeapNumber(Register object,
   2992                                          Register heap_number_map,
   2993                                          Register scratch,
   2994                                          Label* on_not_heap_number) {
   2995   LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   2996   AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
   2997   cmp(scratch, heap_number_map);
   2998   bne(on_not_heap_number);
   2999 }
   3000 
   3001 
   3002 void MacroAssembler::JumpIfNonSmisNotBothSequentialOneByteStrings(
   3003     Register first, Register second, Register scratch1, Register scratch2,
   3004     Label* failure) {
   3005   // Test that both first and second are sequential one-byte strings.
   3006   // Assume that they are non-smis.
   3007   LoadP(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
   3008   LoadP(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
   3009   lbz(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
   3010   lbz(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
   3011 
   3012   JumpIfBothInstanceTypesAreNotSequentialOneByte(scratch1, scratch2, scratch1,
   3013                                                  scratch2, failure);
   3014 }
   3015 
   3016 void MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register first,
   3017                                                            Register second,
   3018                                                            Register scratch1,
   3019                                                            Register scratch2,
   3020                                                            Label* failure) {
   3021   // Check that neither is a smi.
   3022   and_(scratch1, first, second);
   3023   JumpIfSmi(scratch1, failure);
   3024   JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1,
   3025                                                scratch2, failure);
   3026 }
   3027 
   3028 
   3029 void MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
   3030                                                      Label* not_unique_name) {
   3031   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
   3032   Label succeed;
   3033   andi(r0, reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
   3034   beq(&succeed, cr0);
   3035   cmpi(reg, Operand(SYMBOL_TYPE));
   3036   bne(not_unique_name);
   3037 
   3038   bind(&succeed);
   3039 }
   3040 
   3041 
   3042 // Allocates a heap number or jumps to the need_gc label if the young space
   3043 // is full and a scavenge is needed.
   3044 void MacroAssembler::AllocateHeapNumber(Register result, Register scratch1,
   3045                                         Register scratch2,
   3046                                         Register heap_number_map,
   3047                                         Label* gc_required,
   3048                                         MutableMode mode) {
   3049   // Allocate an object in the heap for the heap number and tag it as a heap
   3050   // object.
   3051   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
   3052            NO_ALLOCATION_FLAGS);
   3053 
   3054   Heap::RootListIndex map_index = mode == MUTABLE
   3055                                       ? Heap::kMutableHeapNumberMapRootIndex
   3056                                       : Heap::kHeapNumberMapRootIndex;
   3057   AssertIsRoot(heap_number_map, map_index);
   3058 
   3059   // Store heap number map in the allocated object.
   3060   StoreP(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset),
   3061         r0);
   3062 }
   3063 
   3064 
   3065 void MacroAssembler::AllocateHeapNumberWithValue(
   3066     Register result, DoubleRegister value, Register scratch1, Register scratch2,
   3067     Register heap_number_map, Label* gc_required) {
   3068   AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required);
   3069   stfd(value, FieldMemOperand(result, HeapNumber::kValueOffset));
   3070 }
   3071 
   3072 
   3073 void MacroAssembler::AllocateJSValue(Register result, Register constructor,
   3074                                      Register value, Register scratch1,
   3075                                      Register scratch2, Label* gc_required) {
   3076   DCHECK(!result.is(constructor));
   3077   DCHECK(!result.is(scratch1));
   3078   DCHECK(!result.is(scratch2));
   3079   DCHECK(!result.is(value));
   3080 
   3081   // Allocate JSValue in new space.
   3082   Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
   3083            NO_ALLOCATION_FLAGS);
   3084 
   3085   // Initialize the JSValue.
   3086   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
   3087   StoreP(scratch1, FieldMemOperand(result, HeapObject::kMapOffset), r0);
   3088   LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
   3089   StoreP(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset), r0);
   3090   StoreP(scratch1, FieldMemOperand(result, JSObject::kElementsOffset), r0);
   3091   StoreP(value, FieldMemOperand(result, JSValue::kValueOffset), r0);
   3092   STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
   3093 }
   3094 
   3095 void MacroAssembler::InitializeNFieldsWithFiller(Register current_address,
   3096                                                  Register count,
   3097                                                  Register filler) {
   3098   Label loop;
   3099   mtctr(count);
   3100   bind(&loop);
   3101   StoreP(filler, MemOperand(current_address));
   3102   addi(current_address, current_address, Operand(kPointerSize));
   3103   bdnz(&loop);
   3104 }
   3105 
   3106 void MacroAssembler::InitializeFieldsWithFiller(Register current_address,
   3107                                                 Register end_address,
   3108                                                 Register filler) {
   3109   Label done;
   3110   sub(r0, end_address, current_address, LeaveOE, SetRC);
   3111   beq(&done, cr0);
   3112   ShiftRightImm(r0, r0, Operand(kPointerSizeLog2));
   3113   InitializeNFieldsWithFiller(current_address, r0, filler);
   3114   bind(&done);
   3115 }
   3116 
   3117 
   3118 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
   3119     Register first, Register second, Register scratch1, Register scratch2,
   3120     Label* failure) {
   3121   const int kFlatOneByteStringMask =
   3122       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
   3123   const int kFlatOneByteStringTag =
   3124       kStringTag | kOneByteStringTag | kSeqStringTag;
   3125   andi(scratch1, first, Operand(kFlatOneByteStringMask));
   3126   andi(scratch2, second, Operand(kFlatOneByteStringMask));
   3127   cmpi(scratch1, Operand(kFlatOneByteStringTag));
   3128   bne(failure);
   3129   cmpi(scratch2, Operand(kFlatOneByteStringTag));
   3130   bne(failure);
   3131 }
   3132 
   3133 
   3134 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(Register type,
   3135                                                               Register scratch,
   3136                                                               Label* failure) {
   3137   const int kFlatOneByteStringMask =
   3138       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
   3139   const int kFlatOneByteStringTag =
   3140       kStringTag | kOneByteStringTag | kSeqStringTag;
   3141   andi(scratch, type, Operand(kFlatOneByteStringMask));
   3142   cmpi(scratch, Operand(kFlatOneByteStringTag));
   3143   bne(failure);
   3144 }
   3145 
   3146 static const int kRegisterPassedArguments = 8;
   3147 
   3148 
   3149 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
   3150                                               int num_double_arguments) {
   3151   int stack_passed_words = 0;
   3152   if (num_double_arguments > DoubleRegister::kNumRegisters) {
   3153     stack_passed_words +=
   3154         2 * (num_double_arguments - DoubleRegister::kNumRegisters);
   3155   }
   3156   // Up to 8 simple arguments are passed in registers r3..r10.
   3157   if (num_reg_arguments > kRegisterPassedArguments) {
   3158     stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
   3159   }
   3160   return stack_passed_words;
   3161 }
   3162 
   3163 
   3164 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, Register index,
   3165                                                Register value,
   3166                                                uint32_t encoding_mask) {
   3167   Label is_object;
   3168   TestIfSmi(string, r0);
   3169   Check(ne, kNonObject, cr0);
   3170 
   3171   LoadP(ip, FieldMemOperand(string, HeapObject::kMapOffset));
   3172   lbz(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
   3173 
   3174   andi(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
   3175   cmpi(ip, Operand(encoding_mask));
   3176   Check(eq, kUnexpectedStringType);
   3177 
   3178 // The index is assumed to be untagged coming in, tag it to compare with the
   3179 // string length without using a temp register, it is restored at the end of
   3180 // this function.
   3181 #if !V8_TARGET_ARCH_PPC64
   3182   Label index_tag_ok, index_tag_bad;
   3183   JumpIfNotSmiCandidate(index, r0, &index_tag_bad);
   3184 #endif
   3185   SmiTag(index, index);
   3186 #if !V8_TARGET_ARCH_PPC64
   3187   b(&index_tag_ok);
   3188   bind(&index_tag_bad);
   3189   Abort(kIndexIsTooLarge);
   3190   bind(&index_tag_ok);
   3191 #endif
   3192 
   3193   LoadP(ip, FieldMemOperand(string, String::kLengthOffset));
   3194   cmp(index, ip);
   3195   Check(lt, kIndexIsTooLarge);
   3196 
   3197   DCHECK(Smi::kZero == 0);
   3198   cmpi(index, Operand::Zero());
   3199   Check(ge, kIndexIsNegative);
   3200 
   3201   SmiUntag(index, index);
   3202 }
   3203 
   3204 
   3205 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
   3206                                           int num_double_arguments,
   3207                                           Register scratch) {
   3208   int frame_alignment = ActivationFrameAlignment();
   3209   int stack_passed_arguments =
   3210       CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
   3211   int stack_space = kNumRequiredStackFrameSlots;
   3212 
   3213   if (frame_alignment > kPointerSize) {
   3214     // Make stack end at alignment and make room for stack arguments
   3215     // -- preserving original value of sp.
   3216     mr(scratch, sp);
   3217     addi(sp, sp, Operand(-(stack_passed_arguments + 1) * kPointerSize));
   3218     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
   3219     ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
   3220     StoreP(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
   3221   } else {
   3222     // Make room for stack arguments
   3223     stack_space += stack_passed_arguments;
   3224   }
   3225 
   3226   // Allocate frame with required slots to make ABI work.
   3227   li(r0, Operand::Zero());
   3228   StorePU(r0, MemOperand(sp, -stack_space * kPointerSize));
   3229 }
   3230 
   3231 
   3232 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
   3233                                           Register scratch) {
   3234   PrepareCallCFunction(num_reg_arguments, 0, scratch);
   3235 }
   3236 
   3237 
   3238 void MacroAssembler::MovToFloatParameter(DoubleRegister src) { Move(d1, src); }
   3239 
   3240 
   3241 void MacroAssembler::MovToFloatResult(DoubleRegister src) { Move(d1, src); }
   3242 
   3243 
   3244 void MacroAssembler::MovToFloatParameters(DoubleRegister src1,
   3245                                           DoubleRegister src2) {
   3246   if (src2.is(d1)) {
   3247     DCHECK(!src1.is(d2));
   3248     Move(d2, src2);
   3249     Move(d1, src1);
   3250   } else {
   3251     Move(d1, src1);
   3252     Move(d2, src2);
   3253   }
   3254 }
   3255 
   3256 
   3257 void MacroAssembler::CallCFunction(ExternalReference function,
   3258                                    int num_reg_arguments,
   3259                                    int num_double_arguments) {
   3260   mov(ip, Operand(function));
   3261   CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments);
   3262 }
   3263 
   3264 
   3265 void MacroAssembler::CallCFunction(Register function, int num_reg_arguments,
   3266                                    int num_double_arguments) {
   3267   CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
   3268 }
   3269 
   3270 
   3271 void MacroAssembler::CallCFunction(ExternalReference function,
   3272                                    int num_arguments) {
   3273   CallCFunction(function, num_arguments, 0);
   3274 }
   3275 
   3276 
   3277 void MacroAssembler::CallCFunction(Register function, int num_arguments) {
   3278   CallCFunction(function, num_arguments, 0);
   3279 }
   3280 
   3281 
   3282 void MacroAssembler::CallCFunctionHelper(Register function,
   3283                                          int num_reg_arguments,
   3284                                          int num_double_arguments) {
   3285   DCHECK(has_frame());
   3286 
   3287   // Just call directly. The function called cannot cause a GC, or
   3288   // allow preemption, so the return address in the link register
   3289   // stays correct.
   3290   Register dest = function;
   3291   if (ABI_USES_FUNCTION_DESCRIPTORS) {
   3292     // AIX/PPC64BE Linux uses a function descriptor. When calling C code be
   3293     // aware of this descriptor and pick up values from it
   3294     LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(function, kPointerSize));
   3295     LoadP(ip, MemOperand(function, 0));
   3296     dest = ip;
   3297   } else if (ABI_CALL_VIA_IP) {
   3298     Move(ip, function);
   3299     dest = ip;
   3300   }
   3301 
   3302   Call(dest);
   3303 
   3304   // Remove frame bought in PrepareCallCFunction
   3305   int stack_passed_arguments =
   3306       CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
   3307   int stack_space = kNumRequiredStackFrameSlots + stack_passed_arguments;
   3308   if (ActivationFrameAlignment() > kPointerSize) {
   3309     LoadP(sp, MemOperand(sp, stack_space * kPointerSize));
   3310   } else {
   3311     addi(sp, sp, Operand(stack_space * kPointerSize));
   3312   }
   3313 }
   3314 
   3315 
   3316 void MacroAssembler::DecodeConstantPoolOffset(Register result,
   3317                                               Register location) {
   3318   Label overflow_access, done;
   3319   DCHECK(!AreAliased(result, location, r0));
   3320 
   3321   // Determine constant pool access type
   3322   // Caller has already placed the instruction word at location in result.
   3323   ExtractBitRange(r0, result, 31, 26);
   3324   cmpi(r0, Operand(ADDIS >> 26));
   3325   beq(&overflow_access);
   3326 
   3327   // Regular constant pool access
   3328   // extract the load offset
   3329   andi(result, result, Operand(kImm16Mask));
   3330   b(&done);
   3331 
   3332   bind(&overflow_access);
   3333   // Overflow constant pool access
   3334   // shift addis immediate
   3335   slwi(r0, result, Operand(16));
   3336   // sign-extend and add the load offset
   3337   lwz(result, MemOperand(location, kInstrSize));
   3338   extsh(result, result);
   3339   add(result, r0, result);
   3340 
   3341   bind(&done);
   3342 }
   3343 
   3344 
   3345 void MacroAssembler::CheckPageFlag(
   3346     Register object,
   3347     Register scratch,  // scratch may be same register as object
   3348     int mask, Condition cc, Label* condition_met) {
   3349   DCHECK(cc == ne || cc == eq);
   3350   ClearRightImm(scratch, object, Operand(kPageSizeBits));
   3351   LoadP(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
   3352 
   3353   And(r0, scratch, Operand(mask), SetRC);
   3354 
   3355   if (cc == ne) {
   3356     bne(condition_met, cr0);
   3357   }
   3358   if (cc == eq) {
   3359     beq(condition_met, cr0);
   3360   }
   3361 }
   3362 
   3363 
   3364 void MacroAssembler::JumpIfBlack(Register object, Register scratch0,
   3365                                  Register scratch1, Label* on_black) {
   3366   HasColor(object, scratch0, scratch1, on_black, 1, 1);  // kBlackBitPattern.
   3367   DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
   3368 }
   3369 
   3370 
   3371 void MacroAssembler::HasColor(Register object, Register bitmap_scratch,
   3372                               Register mask_scratch, Label* has_color,
   3373                               int first_bit, int second_bit) {
   3374   DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, no_reg));
   3375 
   3376   GetMarkBits(object, bitmap_scratch, mask_scratch);
   3377 
   3378   Label other_color, word_boundary;
   3379   lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3380   // Test the first bit
   3381   and_(r0, ip, mask_scratch, SetRC);
   3382   b(first_bit == 1 ? eq : ne, &other_color, cr0);
   3383   // Shift left 1
   3384   // May need to load the next cell
   3385   slwi(mask_scratch, mask_scratch, Operand(1), SetRC);
   3386   beq(&word_boundary, cr0);
   3387   // Test the second bit
   3388   and_(r0, ip, mask_scratch, SetRC);
   3389   b(second_bit == 1 ? ne : eq, has_color, cr0);
   3390   b(&other_color);
   3391 
   3392   bind(&word_boundary);
   3393   lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kIntSize));
   3394   andi(r0, ip, Operand(1));
   3395   b(second_bit == 1 ? ne : eq, has_color, cr0);
   3396   bind(&other_color);
   3397 }
   3398 
   3399 
   3400 void MacroAssembler::GetMarkBits(Register addr_reg, Register bitmap_reg,
   3401                                  Register mask_reg) {
   3402   DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
   3403   DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0);
   3404   lis(r0, Operand((~Page::kPageAlignmentMask >> 16)));
   3405   and_(bitmap_reg, addr_reg, r0);
   3406   const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
   3407   ExtractBitRange(mask_reg, addr_reg, kLowBits - 1, kPointerSizeLog2);
   3408   ExtractBitRange(ip, addr_reg, kPageSizeBits - 1, kLowBits);
   3409   ShiftLeftImm(ip, ip, Operand(Bitmap::kBytesPerCellLog2));
   3410   add(bitmap_reg, bitmap_reg, ip);
   3411   li(ip, Operand(1));
   3412   slw(mask_reg, ip, mask_reg);
   3413 }
   3414 
   3415 
   3416 void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
   3417                                  Register mask_scratch, Register load_scratch,
   3418                                  Label* value_is_white) {
   3419   DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ip));
   3420   GetMarkBits(value, bitmap_scratch, mask_scratch);
   3421 
   3422   // If the value is black or grey we don't need to do anything.
   3423   DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
   3424   DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
   3425   DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
   3426   DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
   3427 
   3428   // Since both black and grey have a 1 in the first position and white does
   3429   // not have a 1 there we only need to check one bit.
   3430   lwz(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3431   and_(r0, mask_scratch, load_scratch, SetRC);
   3432   beq(value_is_white, cr0);
   3433 }
   3434 
   3435 
   3436 // Saturate a value into 8-bit unsigned integer
   3437 //   if input_value < 0, output_value is 0
   3438 //   if input_value > 255, output_value is 255
   3439 //   otherwise output_value is the input_value
   3440 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
   3441   int satval = (1 << 8) - 1;
   3442 
   3443   if (CpuFeatures::IsSupported(ISELECT)) {
   3444     // set to 0 if negative
   3445     cmpi(input_reg, Operand::Zero());
   3446     isel(lt, output_reg, r0, input_reg);
   3447 
   3448     // set to satval if > satval
   3449     li(r0, Operand(satval));
   3450     cmpi(output_reg, Operand(satval));
   3451     isel(lt, output_reg, output_reg, r0);
   3452   } else {
   3453     Label done, negative_label, overflow_label;
   3454     cmpi(input_reg, Operand::Zero());
   3455     blt(&negative_label);
   3456 
   3457     cmpi(input_reg, Operand(satval));
   3458     bgt(&overflow_label);
   3459     if (!output_reg.is(input_reg)) {
   3460       mr(output_reg, input_reg);
   3461     }
   3462     b(&done);
   3463 
   3464     bind(&negative_label);
   3465     li(output_reg, Operand::Zero());  // set to 0 if negative
   3466     b(&done);
   3467 
   3468     bind(&overflow_label);  // set to satval if > satval
   3469     li(output_reg, Operand(satval));
   3470 
   3471     bind(&done);
   3472   }
   3473 }
   3474 
   3475 
   3476 void MacroAssembler::SetRoundingMode(FPRoundingMode RN) { mtfsfi(7, RN); }
   3477 
   3478 
   3479 void MacroAssembler::ResetRoundingMode() {
   3480   mtfsfi(7, kRoundToNearest);  // reset (default is kRoundToNearest)
   3481 }
   3482 
   3483 
   3484 void MacroAssembler::ClampDoubleToUint8(Register result_reg,
   3485                                         DoubleRegister input_reg,
   3486                                         DoubleRegister double_scratch) {
   3487   Label above_zero;
   3488   Label done;
   3489   Label in_bounds;
   3490 
   3491   LoadDoubleLiteral(double_scratch, 0.0, result_reg);
   3492   fcmpu(input_reg, double_scratch);
   3493   bgt(&above_zero);
   3494 
   3495   // Double value is less than zero, NaN or Inf, return 0.
   3496   LoadIntLiteral(result_reg, 0);
   3497   b(&done);
   3498 
   3499   // Double value is >= 255, return 255.
   3500   bind(&above_zero);
   3501   LoadDoubleLiteral(double_scratch, 255.0, result_reg);
   3502   fcmpu(input_reg, double_scratch);
   3503   ble(&in_bounds);
   3504   LoadIntLiteral(result_reg, 255);
   3505   b(&done);
   3506 
   3507   // In 0-255 range, round and truncate.
   3508   bind(&in_bounds);
   3509 
   3510   // round to nearest (default rounding mode)
   3511   fctiw(double_scratch, input_reg);
   3512   MovDoubleLowToInt(result_reg, double_scratch);
   3513   bind(&done);
   3514 }
   3515 
   3516 
   3517 void MacroAssembler::LoadInstanceDescriptors(Register map,
   3518                                              Register descriptors) {
   3519   LoadP(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
   3520 }
   3521 
   3522 
   3523 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
   3524   lwz(dst, FieldMemOperand(map, Map::kBitField3Offset));
   3525   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
   3526 }
   3527 
   3528 
   3529 void MacroAssembler::EnumLength(Register dst, Register map) {
   3530   STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
   3531   lwz(dst, FieldMemOperand(map, Map::kBitField3Offset));
   3532   ExtractBitMask(dst, dst, Map::EnumLengthBits::kMask);
   3533   SmiTag(dst);
   3534 }
   3535 
   3536 
   3537 void MacroAssembler::LoadAccessor(Register dst, Register holder,
   3538                                   int accessor_index,
   3539                                   AccessorComponent accessor) {
   3540   LoadP(dst, FieldMemOperand(holder, HeapObject::kMapOffset));
   3541   LoadInstanceDescriptors(dst, dst);
   3542   LoadP(dst,
   3543         FieldMemOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
   3544   const int getterOffset = AccessorPair::kGetterOffset;
   3545   const int setterOffset = AccessorPair::kSetterOffset;
   3546   int offset = ((accessor == ACCESSOR_GETTER) ? getterOffset : setterOffset);
   3547   LoadP(dst, FieldMemOperand(dst, offset));
   3548 }
   3549 
   3550 
   3551 void MacroAssembler::CheckEnumCache(Label* call_runtime) {
   3552   Register null_value = r8;
   3553   Register empty_fixed_array_value = r9;
   3554   LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
   3555   Label next, start;
   3556   mr(r5, r3);
   3557 
   3558   // Check if the enum length field is properly initialized, indicating that
   3559   // there is an enum cache.
   3560   LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
   3561 
   3562   EnumLength(r6, r4);
   3563   CmpSmiLiteral(r6, Smi::FromInt(kInvalidEnumCacheSentinel), r0);
   3564   beq(call_runtime);
   3565 
   3566   LoadRoot(null_value, Heap::kNullValueRootIndex);
   3567   b(&start);
   3568 
   3569   bind(&next);
   3570   LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
   3571 
   3572   // For all objects but the receiver, check that the cache is empty.
   3573   EnumLength(r6, r4);
   3574   CmpSmiLiteral(r6, Smi::kZero, r0);
   3575   bne(call_runtime);
   3576 
   3577   bind(&start);
   3578 
   3579   // Check that there are no elements. Register r5 contains the current JS
   3580   // object we've reached through the prototype chain.
   3581   Label no_elements;
   3582   LoadP(r5, FieldMemOperand(r5, JSObject::kElementsOffset));
   3583   cmp(r5, empty_fixed_array_value);
   3584   beq(&no_elements);
   3585 
   3586   // Second chance, the object may be using the empty slow element dictionary.
   3587   CompareRoot(r5, Heap::kEmptySlowElementDictionaryRootIndex);
   3588   bne(call_runtime);
   3589 
   3590   bind(&no_elements);
   3591   LoadP(r5, FieldMemOperand(r4, Map::kPrototypeOffset));
   3592   cmp(r5, null_value);
   3593   bne(&next);
   3594 }
   3595 
   3596 
   3597 ////////////////////////////////////////////////////////////////////////////////
   3598 //
   3599 // New MacroAssembler Interfaces added for PPC
   3600 //
   3601 ////////////////////////////////////////////////////////////////////////////////
   3602 void MacroAssembler::LoadIntLiteral(Register dst, int value) {
   3603   mov(dst, Operand(value));
   3604 }
   3605 
   3606 
   3607 void MacroAssembler::LoadSmiLiteral(Register dst, Smi* smi) {
   3608   mov(dst, Operand(smi));
   3609 }
   3610 
   3611 
   3612 void MacroAssembler::LoadDoubleLiteral(DoubleRegister result, double value,
   3613                                        Register scratch) {
   3614   if (FLAG_enable_embedded_constant_pool && is_constant_pool_available() &&
   3615       !(scratch.is(r0) && ConstantPoolAccessIsInOverflow())) {
   3616     ConstantPoolEntry::Access access = ConstantPoolAddEntry(value);
   3617     if (access == ConstantPoolEntry::OVERFLOWED) {
   3618       addis(scratch, kConstantPoolRegister, Operand::Zero());
   3619       lfd(result, MemOperand(scratch, 0));
   3620     } else {
   3621       lfd(result, MemOperand(kConstantPoolRegister, 0));
   3622     }
   3623     return;
   3624   }
   3625 
   3626   // avoid gcc strict aliasing error using union cast
   3627   union {
   3628     double dval;
   3629 #if V8_TARGET_ARCH_PPC64
   3630     intptr_t ival;
   3631 #else
   3632     intptr_t ival[2];
   3633 #endif
   3634   } litVal;
   3635 
   3636   litVal.dval = value;
   3637 
   3638 #if V8_TARGET_ARCH_PPC64
   3639   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3640     mov(scratch, Operand(litVal.ival));
   3641     mtfprd(result, scratch);
   3642     return;
   3643   }
   3644 #endif
   3645 
   3646   addi(sp, sp, Operand(-kDoubleSize));
   3647 #if V8_TARGET_ARCH_PPC64
   3648   mov(scratch, Operand(litVal.ival));
   3649   std(scratch, MemOperand(sp));
   3650 #else
   3651   LoadIntLiteral(scratch, litVal.ival[0]);
   3652   stw(scratch, MemOperand(sp, 0));
   3653   LoadIntLiteral(scratch, litVal.ival[1]);
   3654   stw(scratch, MemOperand(sp, 4));
   3655 #endif
   3656   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3657   lfd(result, MemOperand(sp, 0));
   3658   addi(sp, sp, Operand(kDoubleSize));
   3659 }
   3660 
   3661 
   3662 void MacroAssembler::MovIntToDouble(DoubleRegister dst, Register src,
   3663                                     Register scratch) {
   3664 // sign-extend src to 64-bit
   3665 #if V8_TARGET_ARCH_PPC64
   3666   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3667     mtfprwa(dst, src);
   3668     return;
   3669   }
   3670 #endif
   3671 
   3672   DCHECK(!src.is(scratch));
   3673   subi(sp, sp, Operand(kDoubleSize));
   3674 #if V8_TARGET_ARCH_PPC64
   3675   extsw(scratch, src);
   3676   std(scratch, MemOperand(sp, 0));
   3677 #else
   3678   srawi(scratch, src, 31);
   3679   stw(scratch, MemOperand(sp, Register::kExponentOffset));
   3680   stw(src, MemOperand(sp, Register::kMantissaOffset));
   3681 #endif
   3682   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3683   lfd(dst, MemOperand(sp, 0));
   3684   addi(sp, sp, Operand(kDoubleSize));
   3685 }
   3686 
   3687 
   3688 void MacroAssembler::MovUnsignedIntToDouble(DoubleRegister dst, Register src,
   3689                                             Register scratch) {
   3690 // zero-extend src to 64-bit
   3691 #if V8_TARGET_ARCH_PPC64
   3692   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3693     mtfprwz(dst, src);
   3694     return;
   3695   }
   3696 #endif
   3697 
   3698   DCHECK(!src.is(scratch));
   3699   subi(sp, sp, Operand(kDoubleSize));
   3700 #if V8_TARGET_ARCH_PPC64
   3701   clrldi(scratch, src, Operand(32));
   3702   std(scratch, MemOperand(sp, 0));
   3703 #else
   3704   li(scratch, Operand::Zero());
   3705   stw(scratch, MemOperand(sp, Register::kExponentOffset));
   3706   stw(src, MemOperand(sp, Register::kMantissaOffset));
   3707 #endif
   3708   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3709   lfd(dst, MemOperand(sp, 0));
   3710   addi(sp, sp, Operand(kDoubleSize));
   3711 }
   3712 
   3713 
   3714 void MacroAssembler::MovInt64ToDouble(DoubleRegister dst,
   3715 #if !V8_TARGET_ARCH_PPC64
   3716                                       Register src_hi,
   3717 #endif
   3718                                       Register src) {
   3719 #if V8_TARGET_ARCH_PPC64
   3720   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3721     mtfprd(dst, src);
   3722     return;
   3723   }
   3724 #endif
   3725 
   3726   subi(sp, sp, Operand(kDoubleSize));
   3727 #if V8_TARGET_ARCH_PPC64
   3728   std(src, MemOperand(sp, 0));
   3729 #else
   3730   stw(src_hi, MemOperand(sp, Register::kExponentOffset));
   3731   stw(src, MemOperand(sp, Register::kMantissaOffset));
   3732 #endif
   3733   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3734   lfd(dst, MemOperand(sp, 0));
   3735   addi(sp, sp, Operand(kDoubleSize));
   3736 }
   3737 
   3738 
   3739 #if V8_TARGET_ARCH_PPC64
   3740 void MacroAssembler::MovInt64ComponentsToDouble(DoubleRegister dst,
   3741                                                 Register src_hi,
   3742                                                 Register src_lo,
   3743                                                 Register scratch) {
   3744   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3745     sldi(scratch, src_hi, Operand(32));
   3746     rldimi(scratch, src_lo, 0, 32);
   3747     mtfprd(dst, scratch);
   3748     return;
   3749   }
   3750 
   3751   subi(sp, sp, Operand(kDoubleSize));
   3752   stw(src_hi, MemOperand(sp, Register::kExponentOffset));
   3753   stw(src_lo, MemOperand(sp, Register::kMantissaOffset));
   3754   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3755   lfd(dst, MemOperand(sp));
   3756   addi(sp, sp, Operand(kDoubleSize));
   3757 }
   3758 #endif
   3759 
   3760 
   3761 void MacroAssembler::InsertDoubleLow(DoubleRegister dst, Register src,
   3762                                      Register scratch) {
   3763 #if V8_TARGET_ARCH_PPC64
   3764   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3765     mffprd(scratch, dst);
   3766     rldimi(scratch, src, 0, 32);
   3767     mtfprd(dst, scratch);
   3768     return;
   3769   }
   3770 #endif
   3771 
   3772   subi(sp, sp, Operand(kDoubleSize));
   3773   stfd(dst, MemOperand(sp));
   3774   stw(src, MemOperand(sp, Register::kMantissaOffset));
   3775   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3776   lfd(dst, MemOperand(sp));
   3777   addi(sp, sp, Operand(kDoubleSize));
   3778 }
   3779 
   3780 
   3781 void MacroAssembler::InsertDoubleHigh(DoubleRegister dst, Register src,
   3782                                       Register scratch) {
   3783 #if V8_TARGET_ARCH_PPC64
   3784   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3785     mffprd(scratch, dst);
   3786     rldimi(scratch, src, 32, 0);
   3787     mtfprd(dst, scratch);
   3788     return;
   3789   }
   3790 #endif
   3791 
   3792   subi(sp, sp, Operand(kDoubleSize));
   3793   stfd(dst, MemOperand(sp));
   3794   stw(src, MemOperand(sp, Register::kExponentOffset));
   3795   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3796   lfd(dst, MemOperand(sp));
   3797   addi(sp, sp, Operand(kDoubleSize));
   3798 }
   3799 
   3800 
   3801 void MacroAssembler::MovDoubleLowToInt(Register dst, DoubleRegister src) {
   3802 #if V8_TARGET_ARCH_PPC64
   3803   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3804     mffprwz(dst, src);
   3805     return;
   3806   }
   3807 #endif
   3808 
   3809   subi(sp, sp, Operand(kDoubleSize));
   3810   stfd(src, MemOperand(sp));
   3811   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3812   lwz(dst, MemOperand(sp, Register::kMantissaOffset));
   3813   addi(sp, sp, Operand(kDoubleSize));
   3814 }
   3815 
   3816 
   3817 void MacroAssembler::MovDoubleHighToInt(Register dst, DoubleRegister src) {
   3818 #if V8_TARGET_ARCH_PPC64
   3819   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3820     mffprd(dst, src);
   3821     srdi(dst, dst, Operand(32));
   3822     return;
   3823   }
   3824 #endif
   3825 
   3826   subi(sp, sp, Operand(kDoubleSize));
   3827   stfd(src, MemOperand(sp));
   3828   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3829   lwz(dst, MemOperand(sp, Register::kExponentOffset));
   3830   addi(sp, sp, Operand(kDoubleSize));
   3831 }
   3832 
   3833 
   3834 void MacroAssembler::MovDoubleToInt64(
   3835 #if !V8_TARGET_ARCH_PPC64
   3836     Register dst_hi,
   3837 #endif
   3838     Register dst, DoubleRegister src) {
   3839 #if V8_TARGET_ARCH_PPC64
   3840   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3841     mffprd(dst, src);
   3842     return;
   3843   }
   3844 #endif
   3845 
   3846   subi(sp, sp, Operand(kDoubleSize));
   3847   stfd(src, MemOperand(sp));
   3848   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3849 #if V8_TARGET_ARCH_PPC64
   3850   ld(dst, MemOperand(sp, 0));
   3851 #else
   3852   lwz(dst_hi, MemOperand(sp, Register::kExponentOffset));
   3853   lwz(dst, MemOperand(sp, Register::kMantissaOffset));
   3854 #endif
   3855   addi(sp, sp, Operand(kDoubleSize));
   3856 }
   3857 
   3858 
   3859 void MacroAssembler::MovIntToFloat(DoubleRegister dst, Register src) {
   3860   subi(sp, sp, Operand(kFloatSize));
   3861   stw(src, MemOperand(sp, 0));
   3862   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3863   lfs(dst, MemOperand(sp, 0));
   3864   addi(sp, sp, Operand(kFloatSize));
   3865 }
   3866 
   3867 
   3868 void MacroAssembler::MovFloatToInt(Register dst, DoubleRegister src) {
   3869   subi(sp, sp, Operand(kFloatSize));
   3870   frsp(src, src);
   3871   stfs(src, MemOperand(sp, 0));
   3872   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3873   lwz(dst, MemOperand(sp, 0));
   3874   addi(sp, sp, Operand(kFloatSize));
   3875 }
   3876 
   3877 
   3878 void MacroAssembler::Add(Register dst, Register src, intptr_t value,
   3879                          Register scratch) {
   3880   if (is_int16(value)) {
   3881     addi(dst, src, Operand(value));
   3882   } else {
   3883     mov(scratch, Operand(value));
   3884     add(dst, src, scratch);
   3885   }
   3886 }
   3887 
   3888 
   3889 void MacroAssembler::Cmpi(Register src1, const Operand& src2, Register scratch,
   3890                           CRegister cr) {
   3891   intptr_t value = src2.immediate();
   3892   if (is_int16(value)) {
   3893     cmpi(src1, src2, cr);
   3894   } else {
   3895     mov(scratch, src2);
   3896     cmp(src1, scratch, cr);
   3897   }
   3898 }
   3899 
   3900 
   3901 void MacroAssembler::Cmpli(Register src1, const Operand& src2, Register scratch,
   3902                            CRegister cr) {
   3903   intptr_t value = src2.immediate();
   3904   if (is_uint16(value)) {
   3905     cmpli(src1, src2, cr);
   3906   } else {
   3907     mov(scratch, src2);
   3908     cmpl(src1, scratch, cr);
   3909   }
   3910 }
   3911 
   3912 
   3913 void MacroAssembler::Cmpwi(Register src1, const Operand& src2, Register scratch,
   3914                            CRegister cr) {
   3915   intptr_t value = src2.immediate();
   3916   if (is_int16(value)) {
   3917     cmpwi(src1, src2, cr);
   3918   } else {
   3919     mov(scratch, src2);
   3920     cmpw(src1, scratch, cr);
   3921   }
   3922 }
   3923 
   3924 
   3925 void MacroAssembler::Cmplwi(Register src1, const Operand& src2,
   3926                             Register scratch, CRegister cr) {
   3927   intptr_t value = src2.immediate();
   3928   if (is_uint16(value)) {
   3929     cmplwi(src1, src2, cr);
   3930   } else {
   3931     mov(scratch, src2);
   3932     cmplw(src1, scratch, cr);
   3933   }
   3934 }
   3935 
   3936 
   3937 void MacroAssembler::And(Register ra, Register rs, const Operand& rb,
   3938                          RCBit rc) {
   3939   if (rb.is_reg()) {
   3940     and_(ra, rs, rb.rm(), rc);
   3941   } else {
   3942     if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == SetRC) {
   3943       andi(ra, rs, rb);
   3944     } else {
   3945       // mov handles the relocation.
   3946       DCHECK(!rs.is(r0));
   3947       mov(r0, rb);
   3948       and_(ra, rs, r0, rc);
   3949     }
   3950   }
   3951 }
   3952 
   3953 
   3954 void MacroAssembler::Or(Register ra, Register rs, const Operand& rb, RCBit rc) {
   3955   if (rb.is_reg()) {
   3956     orx(ra, rs, rb.rm(), rc);
   3957   } else {
   3958     if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == LeaveRC) {
   3959       ori(ra, rs, rb);
   3960     } else {
   3961       // mov handles the relocation.
   3962       DCHECK(!rs.is(r0));
   3963       mov(r0, rb);
   3964       orx(ra, rs, r0, rc);
   3965     }
   3966   }
   3967 }
   3968 
   3969 
   3970 void MacroAssembler::Xor(Register ra, Register rs, const Operand& rb,
   3971                          RCBit rc) {
   3972   if (rb.is_reg()) {
   3973     xor_(ra, rs, rb.rm(), rc);
   3974   } else {
   3975     if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == LeaveRC) {
   3976       xori(ra, rs, rb);
   3977     } else {
   3978       // mov handles the relocation.
   3979       DCHECK(!rs.is(r0));
   3980       mov(r0, rb);
   3981       xor_(ra, rs, r0, rc);
   3982     }
   3983   }
   3984 }
   3985 
   3986 
   3987 void MacroAssembler::CmpSmiLiteral(Register src1, Smi* smi, Register scratch,
   3988                                    CRegister cr) {
   3989 #if V8_TARGET_ARCH_PPC64
   3990   LoadSmiLiteral(scratch, smi);
   3991   cmp(src1, scratch, cr);
   3992 #else
   3993   Cmpi(src1, Operand(smi), scratch, cr);
   3994 #endif
   3995 }
   3996 
   3997 
   3998 void MacroAssembler::CmplSmiLiteral(Register src1, Smi* smi, Register scratch,
   3999                                     CRegister cr) {
   4000 #if V8_TARGET_ARCH_PPC64
   4001   LoadSmiLiteral(scratch, smi);
   4002   cmpl(src1, scratch, cr);
   4003 #else
   4004   Cmpli(src1, Operand(smi), scratch, cr);
   4005 #endif
   4006 }
   4007 
   4008 
   4009 void MacroAssembler::AddSmiLiteral(Register dst, Register src, Smi* smi,
   4010                                    Register scratch) {
   4011 #if V8_TARGET_ARCH_PPC64
   4012   LoadSmiLiteral(scratch, smi);
   4013   add(dst, src, scratch);
   4014 #else
   4015   Add(dst, src, reinterpret_cast<intptr_t>(smi), scratch);
   4016 #endif
   4017 }
   4018 
   4019 
   4020 void MacroAssembler::SubSmiLiteral(Register dst, Register src, Smi* smi,
   4021                                    Register scratch) {
   4022 #if V8_TARGET_ARCH_PPC64
   4023   LoadSmiLiteral(scratch, smi);
   4024   sub(dst, src, scratch);
   4025 #else
   4026   Add(dst, src, -(reinterpret_cast<intptr_t>(smi)), scratch);
   4027 #endif
   4028 }
   4029 
   4030 
   4031 void MacroAssembler::AndSmiLiteral(Register dst, Register src, Smi* smi,
   4032                                    Register scratch, RCBit rc) {
   4033 #if V8_TARGET_ARCH_PPC64
   4034   LoadSmiLiteral(scratch, smi);
   4035   and_(dst, src, scratch, rc);
   4036 #else
   4037   And(dst, src, Operand(smi), rc);
   4038 #endif
   4039 }
   4040 
   4041 
   4042 // Load a "pointer" sized value from the memory location
   4043 void MacroAssembler::LoadP(Register dst, const MemOperand& mem,
   4044                            Register scratch) {
   4045   int offset = mem.offset();
   4046 
   4047   if (!is_int16(offset)) {
   4048     /* cannot use d-form */
   4049     DCHECK(!scratch.is(no_reg));
   4050     mov(scratch, Operand(offset));
   4051     LoadPX(dst, MemOperand(mem.ra(), scratch));
   4052   } else {
   4053 #if V8_TARGET_ARCH_PPC64
   4054     int misaligned = (offset & 3);
   4055     if (misaligned) {
   4056       // adjust base to conform to offset alignment requirements
   4057       // Todo: enhance to use scratch if dst is unsuitable
   4058       DCHECK(!dst.is(r0));
   4059       addi(dst, mem.ra(), Operand((offset & 3) - 4));
   4060       ld(dst, MemOperand(dst, (offset & ~3) + 4));
   4061     } else {
   4062       ld(dst, mem);
   4063     }
   4064 #else
   4065     lwz(dst, mem);
   4066 #endif
   4067   }
   4068 }
   4069 
   4070 void MacroAssembler::LoadPU(Register dst, const MemOperand& mem,
   4071                             Register scratch) {
   4072   int offset = mem.offset();
   4073 
   4074   if (!is_int16(offset)) {
   4075     /* cannot use d-form */
   4076     DCHECK(!scratch.is(no_reg));
   4077     mov(scratch, Operand(offset));
   4078     LoadPUX(dst, MemOperand(mem.ra(), scratch));
   4079   } else {
   4080 #if V8_TARGET_ARCH_PPC64
   4081     ldu(dst, mem);
   4082 #else
   4083     lwzu(dst, mem);
   4084 #endif
   4085   }
   4086 }
   4087 
   4088 // Store a "pointer" sized value to the memory location
   4089 void MacroAssembler::StoreP(Register src, const MemOperand& mem,
   4090                             Register scratch) {
   4091   int offset = mem.offset();
   4092 
   4093   if (!is_int16(offset)) {
   4094     /* cannot use d-form */
   4095     DCHECK(!scratch.is(no_reg));
   4096     mov(scratch, Operand(offset));
   4097     StorePX(src, MemOperand(mem.ra(), scratch));
   4098   } else {
   4099 #if V8_TARGET_ARCH_PPC64
   4100     int misaligned = (offset & 3);
   4101     if (misaligned) {
   4102       // adjust base to conform to offset alignment requirements
   4103       // a suitable scratch is required here
   4104       DCHECK(!scratch.is(no_reg));
   4105       if (scratch.is(r0)) {
   4106         LoadIntLiteral(scratch, offset);
   4107         stdx(src, MemOperand(mem.ra(), scratch));
   4108       } else {
   4109         addi(scratch, mem.ra(), Operand((offset & 3) - 4));
   4110         std(src, MemOperand(scratch, (offset & ~3) + 4));
   4111       }
   4112     } else {
   4113       std(src, mem);
   4114     }
   4115 #else
   4116     stw(src, mem);
   4117 #endif
   4118   }
   4119 }
   4120 
   4121 void MacroAssembler::StorePU(Register src, const MemOperand& mem,
   4122                              Register scratch) {
   4123   int offset = mem.offset();
   4124 
   4125   if (!is_int16(offset)) {
   4126     /* cannot use d-form */
   4127     DCHECK(!scratch.is(no_reg));
   4128     mov(scratch, Operand(offset));
   4129     StorePUX(src, MemOperand(mem.ra(), scratch));
   4130   } else {
   4131 #if V8_TARGET_ARCH_PPC64
   4132     stdu(src, mem);
   4133 #else
   4134     stwu(src, mem);
   4135 #endif
   4136   }
   4137 }
   4138 
   4139 void MacroAssembler::LoadWordArith(Register dst, const MemOperand& mem,
   4140                                    Register scratch) {
   4141   int offset = mem.offset();
   4142 
   4143   if (!is_int16(offset)) {
   4144     DCHECK(!scratch.is(no_reg));
   4145     mov(scratch, Operand(offset));
   4146     lwax(dst, MemOperand(mem.ra(), scratch));
   4147   } else {
   4148 #if V8_TARGET_ARCH_PPC64
   4149     int misaligned = (offset & 3);
   4150     if (misaligned) {
   4151       // adjust base to conform to offset alignment requirements
   4152       // Todo: enhance to use scratch if dst is unsuitable
   4153       DCHECK(!dst.is(r0));
   4154       addi(dst, mem.ra(), Operand((offset & 3) - 4));
   4155       lwa(dst, MemOperand(dst, (offset & ~3) + 4));
   4156     } else {
   4157       lwa(dst, mem);
   4158     }
   4159 #else
   4160     lwz(dst, mem);
   4161 #endif
   4162   }
   4163 }
   4164 
   4165 
   4166 // Variable length depending on whether offset fits into immediate field
   4167 // MemOperand currently only supports d-form
   4168 void MacroAssembler::LoadWord(Register dst, const MemOperand& mem,
   4169                               Register scratch) {
   4170   Register base = mem.ra();
   4171   int offset = mem.offset();
   4172 
   4173   if (!is_int16(offset)) {
   4174     LoadIntLiteral(scratch, offset);
   4175     lwzx(dst, MemOperand(base, scratch));
   4176   } else {
   4177     lwz(dst, mem);
   4178   }
   4179 }
   4180 
   4181 
   4182 // Variable length depending on whether offset fits into immediate field
   4183 // MemOperand current only supports d-form
   4184 void MacroAssembler::StoreWord(Register src, const MemOperand& mem,
   4185                                Register scratch) {
   4186   Register base = mem.ra();
   4187   int offset = mem.offset();
   4188 
   4189   if (!is_int16(offset)) {
   4190     LoadIntLiteral(scratch, offset);
   4191     stwx(src, MemOperand(base, scratch));
   4192   } else {
   4193     stw(src, mem);
   4194   }
   4195 }
   4196 
   4197 
   4198 void MacroAssembler::LoadHalfWordArith(Register dst, const MemOperand& mem,
   4199                                        Register scratch) {
   4200   int offset = mem.offset();
   4201 
   4202   if (!is_int16(offset)) {
   4203     DCHECK(!scratch.is(no_reg));
   4204     mov(scratch, Operand(offset));
   4205     lhax(dst, MemOperand(mem.ra(), scratch));
   4206   } else {
   4207     lha(dst, mem);
   4208   }
   4209 }
   4210 
   4211 
   4212 // Variable length depending on whether offset fits into immediate field
   4213 // MemOperand currently only supports d-form
   4214 void MacroAssembler::LoadHalfWord(Register dst, const MemOperand& mem,
   4215                                   Register scratch) {
   4216   Register base = mem.ra();
   4217   int offset = mem.offset();
   4218 
   4219   if (!is_int16(offset)) {
   4220     LoadIntLiteral(scratch, offset);
   4221     lhzx(dst, MemOperand(base, scratch));
   4222   } else {
   4223     lhz(dst, mem);
   4224   }
   4225 }
   4226 
   4227 
   4228 // Variable length depending on whether offset fits into immediate field
   4229 // MemOperand current only supports d-form
   4230 void MacroAssembler::StoreHalfWord(Register src, const MemOperand& mem,
   4231                                    Register scratch) {
   4232   Register base = mem.ra();
   4233   int offset = mem.offset();
   4234 
   4235   if (!is_int16(offset)) {
   4236     LoadIntLiteral(scratch, offset);
   4237     sthx(src, MemOperand(base, scratch));
   4238   } else {
   4239     sth(src, mem);
   4240   }
   4241 }
   4242 
   4243 
   4244 // Variable length depending on whether offset fits into immediate field
   4245 // MemOperand currently only supports d-form
   4246 void MacroAssembler::LoadByte(Register dst, const MemOperand& mem,
   4247                               Register scratch) {
   4248   Register base = mem.ra();
   4249   int offset = mem.offset();
   4250 
   4251   if (!is_int16(offset)) {
   4252     LoadIntLiteral(scratch, offset);
   4253     lbzx(dst, MemOperand(base, scratch));
   4254   } else {
   4255     lbz(dst, mem);
   4256   }
   4257 }
   4258 
   4259 
   4260 // Variable length depending on whether offset fits into immediate field
   4261 // MemOperand current only supports d-form
   4262 void MacroAssembler::StoreByte(Register src, const MemOperand& mem,
   4263                                Register scratch) {
   4264   Register base = mem.ra();
   4265   int offset = mem.offset();
   4266 
   4267   if (!is_int16(offset)) {
   4268     LoadIntLiteral(scratch, offset);
   4269     stbx(src, MemOperand(base, scratch));
   4270   } else {
   4271     stb(src, mem);
   4272   }
   4273 }
   4274 
   4275 
   4276 void MacroAssembler::LoadRepresentation(Register dst, const MemOperand& mem,
   4277                                         Representation r, Register scratch) {
   4278   DCHECK(!r.IsDouble());
   4279   if (r.IsInteger8()) {
   4280     LoadByte(dst, mem, scratch);
   4281     extsb(dst, dst);
   4282   } else if (r.IsUInteger8()) {
   4283     LoadByte(dst, mem, scratch);
   4284   } else if (r.IsInteger16()) {
   4285     LoadHalfWordArith(dst, mem, scratch);
   4286   } else if (r.IsUInteger16()) {
   4287     LoadHalfWord(dst, mem, scratch);
   4288 #if V8_TARGET_ARCH_PPC64
   4289   } else if (r.IsInteger32()) {
   4290     LoadWordArith(dst, mem, scratch);
   4291 #endif
   4292   } else {
   4293     LoadP(dst, mem, scratch);
   4294   }
   4295 }
   4296 
   4297 
   4298 void MacroAssembler::StoreRepresentation(Register src, const MemOperand& mem,
   4299                                          Representation r, Register scratch) {
   4300   DCHECK(!r.IsDouble());
   4301   if (r.IsInteger8() || r.IsUInteger8()) {
   4302     StoreByte(src, mem, scratch);
   4303   } else if (r.IsInteger16() || r.IsUInteger16()) {
   4304     StoreHalfWord(src, mem, scratch);
   4305 #if V8_TARGET_ARCH_PPC64
   4306   } else if (r.IsInteger32()) {
   4307     StoreWord(src, mem, scratch);
   4308 #endif
   4309   } else {
   4310     if (r.IsHeapObject()) {
   4311       AssertNotSmi(src);
   4312     } else if (r.IsSmi()) {
   4313       AssertSmi(src);
   4314     }
   4315     StoreP(src, mem, scratch);
   4316   }
   4317 }
   4318 
   4319 
   4320 void MacroAssembler::LoadDouble(DoubleRegister dst, const MemOperand& mem,
   4321                                 Register scratch) {
   4322   Register base = mem.ra();
   4323   int offset = mem.offset();
   4324 
   4325   if (!is_int16(offset)) {
   4326     mov(scratch, Operand(offset));
   4327     lfdx(dst, MemOperand(base, scratch));
   4328   } else {
   4329     lfd(dst, mem);
   4330   }
   4331 }
   4332 
   4333 void MacroAssembler::LoadDoubleU(DoubleRegister dst, const MemOperand& mem,
   4334                                 Register scratch) {
   4335   Register base = mem.ra();
   4336   int offset = mem.offset();
   4337 
   4338   if (!is_int16(offset)) {
   4339     mov(scratch, Operand(offset));
   4340     lfdux(dst, MemOperand(base, scratch));
   4341   } else {
   4342     lfdu(dst, mem);
   4343   }
   4344 }
   4345 
   4346 void MacroAssembler::LoadSingle(DoubleRegister dst, const MemOperand& mem,
   4347                                 Register scratch) {
   4348   Register base = mem.ra();
   4349   int offset = mem.offset();
   4350 
   4351   if (!is_int16(offset)) {
   4352     mov(scratch, Operand(offset));
   4353     lfsx(dst, MemOperand(base, scratch));
   4354   } else {
   4355     lfs(dst, mem);
   4356   }
   4357 }
   4358 
   4359 void MacroAssembler::LoadSingleU(DoubleRegister dst, const MemOperand& mem,
   4360                                 Register scratch) {
   4361   Register base = mem.ra();
   4362   int offset = mem.offset();
   4363 
   4364   if (!is_int16(offset)) {
   4365     mov(scratch, Operand(offset));
   4366     lfsux(dst, MemOperand(base, scratch));
   4367   } else {
   4368     lfsu(dst, mem);
   4369   }
   4370 }
   4371 
   4372 void MacroAssembler::StoreDouble(DoubleRegister src, const MemOperand& mem,
   4373                                  Register scratch) {
   4374   Register base = mem.ra();
   4375   int offset = mem.offset();
   4376 
   4377   if (!is_int16(offset)) {
   4378     mov(scratch, Operand(offset));
   4379     stfdx(src, MemOperand(base, scratch));
   4380   } else {
   4381     stfd(src, mem);
   4382   }
   4383 }
   4384 
   4385 void MacroAssembler::StoreDoubleU(DoubleRegister src, const MemOperand& mem,
   4386                                  Register scratch) {
   4387   Register base = mem.ra();
   4388   int offset = mem.offset();
   4389 
   4390   if (!is_int16(offset)) {
   4391     mov(scratch, Operand(offset));
   4392     stfdux(src, MemOperand(base, scratch));
   4393   } else {
   4394     stfdu(src, mem);
   4395   }
   4396 }
   4397 
   4398 void MacroAssembler::StoreSingle(DoubleRegister src, const MemOperand& mem,
   4399                                  Register scratch) {
   4400   Register base = mem.ra();
   4401   int offset = mem.offset();
   4402 
   4403   if (!is_int16(offset)) {
   4404     mov(scratch, Operand(offset));
   4405     stfsx(src, MemOperand(base, scratch));
   4406   } else {
   4407     stfs(src, mem);
   4408   }
   4409 }
   4410 
   4411 void MacroAssembler::StoreSingleU(DoubleRegister src, const MemOperand& mem,
   4412                                  Register scratch) {
   4413   Register base = mem.ra();
   4414   int offset = mem.offset();
   4415 
   4416   if (!is_int16(offset)) {
   4417     mov(scratch, Operand(offset));
   4418     stfsux(src, MemOperand(base, scratch));
   4419   } else {
   4420     stfsu(src, mem);
   4421   }
   4422 }
   4423 
   4424 void MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg,
   4425                                                      Register scratch_reg,
   4426                                                      Register scratch2_reg,
   4427                                                      Label* no_memento_found) {
   4428   Label map_check;
   4429   Label top_check;
   4430   ExternalReference new_space_allocation_top_adr =
   4431       ExternalReference::new_space_allocation_top_address(isolate());
   4432   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   4433   const int kMementoLastWordOffset =
   4434       kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
   4435   Register mask = scratch2_reg;
   4436 
   4437   DCHECK(!AreAliased(receiver_reg, scratch_reg, mask));
   4438 
   4439   // Bail out if the object is not in new space.
   4440   JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
   4441 
   4442   DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0);
   4443   lis(mask, Operand((~Page::kPageAlignmentMask >> 16)));
   4444   addi(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
   4445 
   4446   // If the object is in new space, we need to check whether it is on the same
   4447   // page as the current top.
   4448   mov(ip, Operand(new_space_allocation_top_adr));
   4449   LoadP(ip, MemOperand(ip));
   4450   Xor(r0, scratch_reg, Operand(ip));
   4451   and_(r0, r0, mask, SetRC);
   4452   beq(&top_check, cr0);
   4453   // The object is on a different page than allocation top. Bail out if the
   4454   // object sits on the page boundary as no memento can follow and we cannot
   4455   // touch the memory following it.
   4456   xor_(r0, scratch_reg, receiver_reg);
   4457   and_(r0, r0, mask, SetRC);
   4458   bne(no_memento_found, cr0);
   4459   // Continue with the actual map check.
   4460   b(&map_check);
   4461   // If top is on the same page as the current object, we need to check whether
   4462   // we are below top.
   4463   bind(&top_check);
   4464   cmp(scratch_reg, ip);
   4465   bge(no_memento_found);
   4466   // Memento map check.
   4467   bind(&map_check);
   4468   LoadP(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
   4469   Cmpi(scratch_reg, Operand(isolate()->factory()->allocation_memento_map()),
   4470        r0);
   4471 }
   4472 
   4473 Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
   4474                                    Register reg4, Register reg5,
   4475                                    Register reg6) {
   4476   RegList regs = 0;
   4477   if (reg1.is_valid()) regs |= reg1.bit();
   4478   if (reg2.is_valid()) regs |= reg2.bit();
   4479   if (reg3.is_valid()) regs |= reg3.bit();
   4480   if (reg4.is_valid()) regs |= reg4.bit();
   4481   if (reg5.is_valid()) regs |= reg5.bit();
   4482   if (reg6.is_valid()) regs |= reg6.bit();
   4483 
   4484   const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   4485   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
   4486     int code = config->GetAllocatableGeneralCode(i);
   4487     Register candidate = Register::from_code(code);
   4488     if (regs & candidate.bit()) continue;
   4489     return candidate;
   4490   }
   4491   UNREACHABLE();
   4492   return no_reg;
   4493 }
   4494 
   4495 
   4496 void MacroAssembler::JumpIfDictionaryInPrototypeChain(Register object,
   4497                                                       Register scratch0,
   4498                                                       Register scratch1,
   4499                                                       Label* found) {
   4500   DCHECK(!scratch1.is(scratch0));
   4501   Register current = scratch0;
   4502   Label loop_again, end;
   4503 
   4504   // scratch contained elements pointer.
   4505   mr(current, object);
   4506   LoadP(current, FieldMemOperand(current, HeapObject::kMapOffset));
   4507   LoadP(current, FieldMemOperand(current, Map::kPrototypeOffset));
   4508   CompareRoot(current, Heap::kNullValueRootIndex);
   4509   beq(&end);
   4510 
   4511   // Loop based on the map going up the prototype chain.
   4512   bind(&loop_again);
   4513   LoadP(current, FieldMemOperand(current, HeapObject::kMapOffset));
   4514 
   4515   STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
   4516   STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
   4517   lbz(scratch1, FieldMemOperand(current, Map::kInstanceTypeOffset));
   4518   cmpi(scratch1, Operand(JS_OBJECT_TYPE));
   4519   blt(found);
   4520 
   4521   lbz(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
   4522   DecodeField<Map::ElementsKindBits>(scratch1);
   4523   cmpi(scratch1, Operand(DICTIONARY_ELEMENTS));
   4524   beq(found);
   4525   LoadP(current, FieldMemOperand(current, Map::kPrototypeOffset));
   4526   CompareRoot(current, Heap::kNullValueRootIndex);
   4527   bne(&loop_again);
   4528 
   4529   bind(&end);
   4530 }
   4531 
   4532 
   4533 #ifdef DEBUG
   4534 bool AreAliased(Register reg1, Register reg2, Register reg3, Register reg4,
   4535                 Register reg5, Register reg6, Register reg7, Register reg8,
   4536                 Register reg9, Register reg10) {
   4537   int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() + reg3.is_valid() +
   4538                         reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
   4539                         reg7.is_valid() + reg8.is_valid() + reg9.is_valid() +
   4540                         reg10.is_valid();
   4541 
   4542   RegList regs = 0;
   4543   if (reg1.is_valid()) regs |= reg1.bit();
   4544   if (reg2.is_valid()) regs |= reg2.bit();
   4545   if (reg3.is_valid()) regs |= reg3.bit();
   4546   if (reg4.is_valid()) regs |= reg4.bit();
   4547   if (reg5.is_valid()) regs |= reg5.bit();
   4548   if (reg6.is_valid()) regs |= reg6.bit();
   4549   if (reg7.is_valid()) regs |= reg7.bit();
   4550   if (reg8.is_valid()) regs |= reg8.bit();
   4551   if (reg9.is_valid()) regs |= reg9.bit();
   4552   if (reg10.is_valid()) regs |= reg10.bit();
   4553   int n_of_non_aliasing_regs = NumRegs(regs);
   4554 
   4555   return n_of_valid_regs != n_of_non_aliasing_regs;
   4556 }
   4557 #endif
   4558 
   4559 
   4560 CodePatcher::CodePatcher(Isolate* isolate, byte* address, int instructions,
   4561                          FlushICache flush_cache)
   4562     : address_(address),
   4563       size_(instructions * Assembler::kInstrSize),
   4564       masm_(isolate, address, size_ + Assembler::kGap, CodeObjectRequired::kNo),
   4565       flush_cache_(flush_cache) {
   4566   // Create a new macro assembler pointing to the address of the code to patch.
   4567   // The size is adjusted with kGap on order for the assembler to generate size
   4568   // bytes of instructions without failing with buffer size constraints.
   4569   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   4570 }
   4571 
   4572 
   4573 CodePatcher::~CodePatcher() {
   4574   // Indicate that code has changed.
   4575   if (flush_cache_ == FLUSH) {
   4576     Assembler::FlushICache(masm_.isolate(), address_, size_);
   4577   }
   4578 
   4579   // Check that the code was patched as expected.
   4580   DCHECK(masm_.pc_ == address_ + size_);
   4581   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   4582 }
   4583 
   4584 
   4585 void CodePatcher::Emit(Instr instr) { masm()->emit(instr); }
   4586 
   4587 
   4588 void CodePatcher::EmitCondition(Condition cond) {
   4589   Instr instr = Assembler::instr_at(masm_.pc_);
   4590   switch (cond) {
   4591     case eq:
   4592       instr = (instr & ~kCondMask) | BT;
   4593       break;
   4594     case ne:
   4595       instr = (instr & ~kCondMask) | BF;
   4596       break;
   4597     default:
   4598       UNIMPLEMENTED();
   4599   }
   4600   masm_.emit(instr);
   4601 }
   4602 
   4603 
   4604 void MacroAssembler::TruncatingDiv(Register result, Register dividend,
   4605                                    int32_t divisor) {
   4606   DCHECK(!dividend.is(result));
   4607   DCHECK(!dividend.is(r0));
   4608   DCHECK(!result.is(r0));
   4609   base::MagicNumbersForDivision<uint32_t> mag =
   4610       base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
   4611   mov(r0, Operand(mag.multiplier));
   4612   mulhw(result, dividend, r0);
   4613   bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
   4614   if (divisor > 0 && neg) {
   4615     add(result, result, dividend);
   4616   }
   4617   if (divisor < 0 && !neg && mag.multiplier > 0) {
   4618     sub(result, result, dividend);
   4619   }
   4620   if (mag.shift > 0) srawi(result, result, mag.shift);
   4621   ExtractBit(r0, dividend, 31);
   4622   add(result, result, r0);
   4623 }
   4624 
   4625 }  // namespace internal
   4626 }  // namespace v8
   4627 
   4628 #endif  // V8_TARGET_ARCH_PPC
   4629