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     mov(r11, Operand(StackFrame::TypeToMarker(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 void MacroAssembler::EmitLoadFeedbackVector(Register vector) {
   1024   LoadP(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   1025   LoadP(vector, FieldMemOperand(vector, JSFunction::kFeedbackVectorOffset));
   1026   LoadP(vector, FieldMemOperand(vector, Cell::kValueOffset));
   1027 }
   1028 
   1029 
   1030 void MacroAssembler::EnterFrame(StackFrame::Type type,
   1031                                 bool load_constant_pool_pointer_reg) {
   1032   if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) {
   1033     // Push type explicitly so we can leverage the constant pool.
   1034     // This path cannot rely on ip containing code entry.
   1035     PushCommonFrame();
   1036     LoadConstantPoolPointerRegister();
   1037     mov(ip, Operand(StackFrame::TypeToMarker(type)));
   1038     push(ip);
   1039   } else {
   1040     mov(ip, Operand(StackFrame::TypeToMarker(type)));
   1041     PushCommonFrame(ip);
   1042   }
   1043   if (type == StackFrame::INTERNAL) {
   1044     mov(r0, Operand(CodeObject()));
   1045     push(r0);
   1046   }
   1047 }
   1048 
   1049 
   1050 int MacroAssembler::LeaveFrame(StackFrame::Type type, int stack_adjustment) {
   1051   ConstantPoolUnavailableScope constant_pool_unavailable(this);
   1052   // r3: preserved
   1053   // r4: preserved
   1054   // r5: preserved
   1055 
   1056   // Drop the execution stack down to the frame pointer and restore
   1057   // the caller's state.
   1058   int frame_ends;
   1059   LoadP(r0, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
   1060   LoadP(ip, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   1061   if (FLAG_enable_embedded_constant_pool) {
   1062     LoadP(kConstantPoolRegister,
   1063           MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
   1064   }
   1065   mtlr(r0);
   1066   frame_ends = pc_offset();
   1067   Add(sp, fp, StandardFrameConstants::kCallerSPOffset + stack_adjustment, r0);
   1068   mr(fp, ip);
   1069   return frame_ends;
   1070 }
   1071 
   1072 void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
   1073                                        Register argc) {
   1074   int fp_delta = 0;
   1075   mflr(r0);
   1076   if (FLAG_enable_embedded_constant_pool) {
   1077     if (target.is_valid()) {
   1078       Push(r0, fp, kConstantPoolRegister, context, target);
   1079       fp_delta = 3;
   1080     } else {
   1081       Push(r0, fp, kConstantPoolRegister, context);
   1082       fp_delta = 2;
   1083     }
   1084   } else {
   1085     if (target.is_valid()) {
   1086       Push(r0, fp, context, target);
   1087       fp_delta = 2;
   1088     } else {
   1089       Push(r0, fp, context);
   1090       fp_delta = 1;
   1091     }
   1092   }
   1093   addi(fp, sp, Operand(fp_delta * kPointerSize));
   1094   Push(argc);
   1095 }
   1096 
   1097 void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
   1098                                        Register argc) {
   1099   Pop(argc);
   1100   if (FLAG_enable_embedded_constant_pool) {
   1101     if (target.is_valid()) {
   1102       Pop(r0, fp, kConstantPoolRegister, context, target);
   1103     } else {
   1104       Pop(r0, fp, kConstantPoolRegister, context);
   1105     }
   1106   } else {
   1107     if (target.is_valid()) {
   1108       Pop(r0, fp, context, target);
   1109     } else {
   1110       Pop(r0, fp, context);
   1111     }
   1112   }
   1113   mtlr(r0);
   1114 }
   1115 
   1116 // ExitFrame layout (probably wrongish.. needs updating)
   1117 //
   1118 //  SP -> previousSP
   1119 //        LK reserved
   1120 //        code
   1121 //        sp_on_exit (for debug?)
   1122 // oldSP->prev SP
   1123 //        LK
   1124 //        <parameters on stack>
   1125 
   1126 // Prior to calling EnterExitFrame, we've got a bunch of parameters
   1127 // on the stack that we need to wrap a real frame around.. so first
   1128 // we reserve a slot for LK and push the previous SP which is captured
   1129 // in the fp register (r31)
   1130 // Then - we buy a new frame
   1131 
   1132 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
   1133                                     StackFrame::Type frame_type) {
   1134   DCHECK(frame_type == StackFrame::EXIT ||
   1135          frame_type == StackFrame::BUILTIN_EXIT);
   1136   // Set up the frame structure on the stack.
   1137   DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
   1138   DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
   1139   DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
   1140   DCHECK(stack_space > 0);
   1141 
   1142   // This is an opportunity to build a frame to wrap
   1143   // all of the pushes that have happened inside of V8
   1144   // since we were called from C code
   1145 
   1146   mov(ip, Operand(StackFrame::TypeToMarker(frame_type)));
   1147   PushCommonFrame(ip);
   1148   // Reserve room for saved entry sp and code object.
   1149   subi(sp, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp));
   1150 
   1151   if (emit_debug_code()) {
   1152     li(r8, Operand::Zero());
   1153     StoreP(r8, MemOperand(fp, ExitFrameConstants::kSPOffset));
   1154   }
   1155   if (FLAG_enable_embedded_constant_pool) {
   1156     StoreP(kConstantPoolRegister,
   1157            MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
   1158   }
   1159   mov(r8, Operand(CodeObject()));
   1160   StoreP(r8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
   1161 
   1162   // Save the frame pointer and the context in top.
   1163   mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
   1164   StoreP(fp, MemOperand(r8));
   1165   mov(r8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1166   StoreP(cp, MemOperand(r8));
   1167 
   1168   // Optionally save all volatile double registers.
   1169   if (save_doubles) {
   1170     MultiPushDoubles(kCallerSavedDoubles);
   1171     // Note that d0 will be accessible at
   1172     //   fp - ExitFrameConstants::kFrameSize -
   1173     //   kNumCallerSavedDoubles * kDoubleSize,
   1174     // since the sp slot and code slot were pushed after the fp.
   1175   }
   1176 
   1177   addi(sp, sp, Operand(-stack_space * kPointerSize));
   1178 
   1179   // Allocate and align the frame preparing for calling the runtime
   1180   // function.
   1181   const int frame_alignment = ActivationFrameAlignment();
   1182   if (frame_alignment > kPointerSize) {
   1183     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
   1184     ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
   1185   }
   1186   li(r0, Operand::Zero());
   1187   StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize));
   1188 
   1189   // Set the exit frame sp value to point just before the return address
   1190   // location.
   1191   addi(r8, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
   1192   StoreP(r8, MemOperand(fp, ExitFrameConstants::kSPOffset));
   1193 }
   1194 
   1195 int MacroAssembler::ActivationFrameAlignment() {
   1196 #if !defined(USE_SIMULATOR)
   1197   // Running on the real platform. Use the alignment as mandated by the local
   1198   // environment.
   1199   // Note: This will break if we ever start generating snapshots on one PPC
   1200   // platform for another PPC platform with a different alignment.
   1201   return base::OS::ActivationFrameAlignment();
   1202 #else  // Simulated
   1203   // If we are using the simulator then we should always align to the expected
   1204   // alignment. As the simulator is used to generate snapshots we do not know
   1205   // if the target platform will need alignment, so this is controlled from a
   1206   // flag.
   1207   return FLAG_sim_stack_alignment;
   1208 #endif
   1209 }
   1210 
   1211 
   1212 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
   1213                                     bool restore_context,
   1214                                     bool argument_count_is_length) {
   1215   ConstantPoolUnavailableScope constant_pool_unavailable(this);
   1216   // Optionally restore all double registers.
   1217   if (save_doubles) {
   1218     // Calculate the stack location of the saved doubles and restore them.
   1219     const int kNumRegs = kNumCallerSavedDoubles;
   1220     const int offset =
   1221         (ExitFrameConstants::kFixedFrameSizeFromFp + kNumRegs * kDoubleSize);
   1222     addi(r6, fp, Operand(-offset));
   1223     MultiPopDoubles(kCallerSavedDoubles, r6);
   1224   }
   1225 
   1226   // Clear top frame.
   1227   li(r6, Operand::Zero());
   1228   mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
   1229   StoreP(r6, MemOperand(ip));
   1230 
   1231   // Restore current context from top and clear it in debug mode.
   1232   if (restore_context) {
   1233     mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1234     LoadP(cp, MemOperand(ip));
   1235   }
   1236 #ifdef DEBUG
   1237   mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1238   StoreP(r6, MemOperand(ip));
   1239 #endif
   1240 
   1241   // Tear down the exit frame, pop the arguments, and return.
   1242   LeaveFrame(StackFrame::EXIT);
   1243 
   1244   if (argument_count.is_valid()) {
   1245     if (!argument_count_is_length) {
   1246       ShiftLeftImm(argument_count, argument_count, Operand(kPointerSizeLog2));
   1247     }
   1248     add(sp, sp, argument_count);
   1249   }
   1250 }
   1251 
   1252 
   1253 void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) {
   1254   Move(dst, d1);
   1255 }
   1256 
   1257 
   1258 void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) {
   1259   Move(dst, d1);
   1260 }
   1261 
   1262 void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
   1263                                         Register caller_args_count_reg,
   1264                                         Register scratch0, Register scratch1) {
   1265 #if DEBUG
   1266   if (callee_args_count.is_reg()) {
   1267     DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
   1268                        scratch1));
   1269   } else {
   1270     DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
   1271   }
   1272 #endif
   1273 
   1274   // Calculate the end of destination area where we will put the arguments
   1275   // after we drop current frame. We add kPointerSize to count the receiver
   1276   // argument which is not included into formal parameters count.
   1277   Register dst_reg = scratch0;
   1278   ShiftLeftImm(dst_reg, caller_args_count_reg, Operand(kPointerSizeLog2));
   1279   add(dst_reg, fp, dst_reg);
   1280   addi(dst_reg, dst_reg,
   1281        Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
   1282 
   1283   Register src_reg = caller_args_count_reg;
   1284   // Calculate the end of source area. +kPointerSize is for the receiver.
   1285   if (callee_args_count.is_reg()) {
   1286     ShiftLeftImm(src_reg, callee_args_count.reg(), Operand(kPointerSizeLog2));
   1287     add(src_reg, sp, src_reg);
   1288     addi(src_reg, src_reg, Operand(kPointerSize));
   1289   } else {
   1290     Add(src_reg, sp, (callee_args_count.immediate() + 1) * kPointerSize, r0);
   1291   }
   1292 
   1293   if (FLAG_debug_code) {
   1294     cmpl(src_reg, dst_reg);
   1295     Check(lt, kStackAccessBelowStackPointer);
   1296   }
   1297 
   1298   // Restore caller's frame pointer and return address now as they will be
   1299   // overwritten by the copying loop.
   1300   RestoreFrameStateForTailCall();
   1301 
   1302   // Now copy callee arguments to the caller frame going backwards to avoid
   1303   // callee arguments corruption (source and destination areas could overlap).
   1304 
   1305   // Both src_reg and dst_reg are pointing to the word after the one to copy,
   1306   // so they must be pre-decremented in the loop.
   1307   Register tmp_reg = scratch1;
   1308   Label loop;
   1309   if (callee_args_count.is_reg()) {
   1310     addi(tmp_reg, callee_args_count.reg(), Operand(1));  // +1 for receiver
   1311   } else {
   1312     mov(tmp_reg, Operand(callee_args_count.immediate() + 1));
   1313   }
   1314   mtctr(tmp_reg);
   1315   bind(&loop);
   1316   LoadPU(tmp_reg, MemOperand(src_reg, -kPointerSize));
   1317   StorePU(tmp_reg, MemOperand(dst_reg, -kPointerSize));
   1318   bdnz(&loop);
   1319 
   1320   // Leave current frame.
   1321   mr(sp, dst_reg);
   1322 }
   1323 
   1324 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
   1325                                     const ParameterCount& actual, Label* done,
   1326                                     bool* definitely_mismatches,
   1327                                     InvokeFlag flag,
   1328                                     const CallWrapper& call_wrapper) {
   1329   bool definitely_matches = false;
   1330   *definitely_mismatches = false;
   1331   Label regular_invoke;
   1332 
   1333   // Check whether the expected and actual arguments count match. If not,
   1334   // setup registers according to contract with ArgumentsAdaptorTrampoline:
   1335   //  r3: actual arguments count
   1336   //  r4: function (passed through to callee)
   1337   //  r5: expected arguments count
   1338 
   1339   // The code below is made a lot easier because the calling code already sets
   1340   // up actual and expected registers according to the contract if values are
   1341   // passed in registers.
   1342 
   1343   // ARM has some sanity checks as per below, considering add them for PPC
   1344   //  DCHECK(actual.is_immediate() || actual.reg().is(r3));
   1345   //  DCHECK(expected.is_immediate() || expected.reg().is(r5));
   1346 
   1347   if (expected.is_immediate()) {
   1348     DCHECK(actual.is_immediate());
   1349     mov(r3, Operand(actual.immediate()));
   1350     if (expected.immediate() == actual.immediate()) {
   1351       definitely_matches = true;
   1352     } else {
   1353       const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
   1354       if (expected.immediate() == sentinel) {
   1355         // Don't worry about adapting arguments for builtins that
   1356         // don't want that done. Skip adaption code by making it look
   1357         // like we have a match between expected and actual number of
   1358         // arguments.
   1359         definitely_matches = true;
   1360       } else {
   1361         *definitely_mismatches = true;
   1362         mov(r5, Operand(expected.immediate()));
   1363       }
   1364     }
   1365   } else {
   1366     if (actual.is_immediate()) {
   1367       mov(r3, Operand(actual.immediate()));
   1368       cmpi(expected.reg(), Operand(actual.immediate()));
   1369       beq(&regular_invoke);
   1370     } else {
   1371       cmp(expected.reg(), actual.reg());
   1372       beq(&regular_invoke);
   1373     }
   1374   }
   1375 
   1376   if (!definitely_matches) {
   1377     Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
   1378     if (flag == CALL_FUNCTION) {
   1379       call_wrapper.BeforeCall(CallSize(adaptor));
   1380       Call(adaptor);
   1381       call_wrapper.AfterCall();
   1382       if (!*definitely_mismatches) {
   1383         b(done);
   1384       }
   1385     } else {
   1386       Jump(adaptor, RelocInfo::CODE_TARGET);
   1387     }
   1388     bind(&regular_invoke);
   1389   }
   1390 }
   1391 
   1392 void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
   1393                                     const ParameterCount& expected,
   1394                                     const ParameterCount& actual) {
   1395   Label skip_hook;
   1396   ExternalReference debug_hook_avtive =
   1397       ExternalReference::debug_hook_on_function_call_address(isolate());
   1398   mov(r7, Operand(debug_hook_avtive));
   1399   LoadByte(r7, MemOperand(r7), r0);
   1400   extsb(r7, r7);
   1401   CmpSmiLiteral(r7, Smi::kZero, r0);
   1402   beq(&skip_hook);
   1403   {
   1404     FrameScope frame(this,
   1405                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
   1406     if (expected.is_reg()) {
   1407       SmiTag(expected.reg());
   1408       Push(expected.reg());
   1409     }
   1410     if (actual.is_reg()) {
   1411       SmiTag(actual.reg());
   1412       Push(actual.reg());
   1413     }
   1414     if (new_target.is_valid()) {
   1415       Push(new_target);
   1416     }
   1417     Push(fun, fun);
   1418     CallRuntime(Runtime::kDebugOnFunctionCall);
   1419     Pop(fun);
   1420     if (new_target.is_valid()) {
   1421       Pop(new_target);
   1422     }
   1423     if (actual.is_reg()) {
   1424       Pop(actual.reg());
   1425       SmiUntag(actual.reg());
   1426     }
   1427     if (expected.is_reg()) {
   1428       Pop(expected.reg());
   1429       SmiUntag(expected.reg());
   1430     }
   1431   }
   1432   bind(&skip_hook);
   1433 }
   1434 
   1435 
   1436 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
   1437                                         const ParameterCount& expected,
   1438                                         const ParameterCount& actual,
   1439                                         InvokeFlag flag,
   1440                                         const CallWrapper& call_wrapper) {
   1441   // You can't call a function without a valid frame.
   1442   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1443   DCHECK(function.is(r4));
   1444   DCHECK_IMPLIES(new_target.is_valid(), new_target.is(r6));
   1445 
   1446   if (call_wrapper.NeedsDebugHookCheck()) {
   1447     CheckDebugHook(function, new_target, expected, actual);
   1448   }
   1449 
   1450   // Clear the new.target register if not given.
   1451   if (!new_target.is_valid()) {
   1452     LoadRoot(r6, Heap::kUndefinedValueRootIndex);
   1453   }
   1454 
   1455   Label done;
   1456   bool definitely_mismatches = false;
   1457   InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
   1458                  call_wrapper);
   1459   if (!definitely_mismatches) {
   1460     // We call indirectly through the code field in the function to
   1461     // allow recompilation to take effect without changing any of the
   1462     // call sites.
   1463     Register code = ip;
   1464     LoadP(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
   1465     if (flag == CALL_FUNCTION) {
   1466       call_wrapper.BeforeCall(CallSize(code));
   1467       CallJSEntry(code);
   1468       call_wrapper.AfterCall();
   1469     } else {
   1470       DCHECK(flag == JUMP_FUNCTION);
   1471       JumpToJSEntry(code);
   1472     }
   1473 
   1474     // Continue here if InvokePrologue does handle the invocation due to
   1475     // mismatched parameter counts.
   1476     bind(&done);
   1477   }
   1478 }
   1479 
   1480 
   1481 void MacroAssembler::InvokeFunction(Register fun, Register new_target,
   1482                                     const ParameterCount& actual,
   1483                                     InvokeFlag flag,
   1484                                     const CallWrapper& call_wrapper) {
   1485   // You can't call a function without a valid frame.
   1486   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1487 
   1488   // Contract with called JS functions requires that function is passed in r4.
   1489   DCHECK(fun.is(r4));
   1490 
   1491   Register expected_reg = r5;
   1492   Register temp_reg = r7;
   1493 
   1494   LoadP(temp_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
   1495   LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
   1496   LoadWordArith(expected_reg,
   1497                 FieldMemOperand(
   1498                     temp_reg, SharedFunctionInfo::kFormalParameterCountOffset));
   1499 #if !defined(V8_TARGET_ARCH_PPC64)
   1500   SmiUntag(expected_reg);
   1501 #endif
   1502 
   1503   ParameterCount expected(expected_reg);
   1504   InvokeFunctionCode(fun, new_target, expected, actual, flag, call_wrapper);
   1505 }
   1506 
   1507 
   1508 void MacroAssembler::InvokeFunction(Register function,
   1509                                     const ParameterCount& expected,
   1510                                     const ParameterCount& actual,
   1511                                     InvokeFlag flag,
   1512                                     const CallWrapper& call_wrapper) {
   1513   // You can't call a function without a valid frame.
   1514   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1515 
   1516   // Contract with called JS functions requires that function is passed in r4.
   1517   DCHECK(function.is(r4));
   1518 
   1519   // Get the function and setup the context.
   1520   LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
   1521 
   1522   InvokeFunctionCode(r4, no_reg, expected, actual, flag, call_wrapper);
   1523 }
   1524 
   1525 
   1526 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
   1527                                     const ParameterCount& expected,
   1528                                     const ParameterCount& actual,
   1529                                     InvokeFlag flag,
   1530                                     const CallWrapper& call_wrapper) {
   1531   Move(r4, function);
   1532   InvokeFunction(r4, expected, actual, flag, call_wrapper);
   1533 }
   1534 
   1535 
   1536 void MacroAssembler::IsObjectJSStringType(Register object, Register scratch,
   1537                                           Label* fail) {
   1538   DCHECK(kNotStringTag != 0);
   1539 
   1540   LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   1541   lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   1542   andi(r0, scratch, Operand(kIsNotStringMask));
   1543   bne(fail, cr0);
   1544 }
   1545 
   1546 
   1547 void MacroAssembler::IsObjectNameType(Register object, Register scratch,
   1548                                       Label* fail) {
   1549   LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   1550   lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   1551   cmpi(scratch, Operand(LAST_NAME_TYPE));
   1552   bgt(fail);
   1553 }
   1554 
   1555 
   1556 void MacroAssembler::MaybeDropFrames() {
   1557   // Check whether we need to drop frames to restart a function on the stack.
   1558   ExternalReference restart_fp =
   1559       ExternalReference::debug_restart_fp_address(isolate());
   1560   mov(r4, Operand(restart_fp));
   1561   LoadWordArith(r4, MemOperand(r4));
   1562   cmpi(r4, Operand::Zero());
   1563   Jump(isolate()->builtins()->FrameDropperTrampoline(), RelocInfo::CODE_TARGET,
   1564        ne);
   1565 }
   1566 
   1567 void MacroAssembler::PushStackHandler() {
   1568   // Adjust this code if not the case.
   1569   STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
   1570   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
   1571 
   1572   // Link the current handler as the next handler.
   1573   // Preserve r3-r7.
   1574   mov(r8, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   1575   LoadP(r0, MemOperand(r8));
   1576   push(r0);
   1577 
   1578   // Set this new handler as the current one.
   1579   StoreP(sp, MemOperand(r8));
   1580 }
   1581 
   1582 
   1583 void MacroAssembler::PopStackHandler() {
   1584   STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
   1585   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   1586 
   1587   pop(r4);
   1588   mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   1589   StoreP(r4, MemOperand(ip));
   1590 }
   1591 
   1592 
   1593 // Compute the hash code from the untagged key.  This must be kept in sync with
   1594 // ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
   1595 // code-stub-hydrogen.cc
   1596 void MacroAssembler::GetNumberHash(Register t0, Register scratch) {
   1597   // First of all we assign the hash seed to scratch.
   1598   LoadRoot(scratch, Heap::kHashSeedRootIndex);
   1599   SmiUntag(scratch);
   1600 
   1601   // Xor original key with a seed.
   1602   xor_(t0, t0, scratch);
   1603 
   1604   // Compute the hash code from the untagged key.  This must be kept in sync
   1605   // with ComputeIntegerHash in utils.h.
   1606   //
   1607   // hash = ~hash + (hash << 15);
   1608   notx(scratch, t0);
   1609   slwi(t0, t0, Operand(15));
   1610   add(t0, scratch, t0);
   1611   // hash = hash ^ (hash >> 12);
   1612   srwi(scratch, t0, Operand(12));
   1613   xor_(t0, t0, scratch);
   1614   // hash = hash + (hash << 2);
   1615   slwi(scratch, t0, Operand(2));
   1616   add(t0, t0, scratch);
   1617   // hash = hash ^ (hash >> 4);
   1618   srwi(scratch, t0, Operand(4));
   1619   xor_(t0, t0, scratch);
   1620   // hash = hash * 2057;
   1621   mr(r0, t0);
   1622   slwi(scratch, t0, Operand(3));
   1623   add(t0, t0, scratch);
   1624   slwi(scratch, r0, Operand(11));
   1625   add(t0, t0, scratch);
   1626   // hash = hash ^ (hash >> 16);
   1627   srwi(scratch, t0, Operand(16));
   1628   xor_(t0, t0, scratch);
   1629   // hash & 0x3fffffff
   1630   ExtractBitRange(t0, t0, 29, 0);
   1631 }
   1632 
   1633 void MacroAssembler::Allocate(int object_size, Register result,
   1634                               Register scratch1, Register scratch2,
   1635                               Label* gc_required, AllocationFlags flags) {
   1636   DCHECK(object_size <= kMaxRegularHeapObjectSize);
   1637   DCHECK((flags & ALLOCATION_FOLDED) == 0);
   1638   if (!FLAG_inline_new) {
   1639     if (emit_debug_code()) {
   1640       // Trash the registers to simulate an allocation failure.
   1641       li(result, Operand(0x7091));
   1642       li(scratch1, Operand(0x7191));
   1643       li(scratch2, Operand(0x7291));
   1644     }
   1645     b(gc_required);
   1646     return;
   1647   }
   1648 
   1649   DCHECK(!AreAliased(result, scratch1, scratch2, ip));
   1650 
   1651   // Make object size into bytes.
   1652   if ((flags & SIZE_IN_WORDS) != 0) {
   1653     object_size *= kPointerSize;
   1654   }
   1655   DCHECK_EQ(0, static_cast<int>(object_size & kObjectAlignmentMask));
   1656 
   1657   // Check relative positions of allocation top and limit addresses.
   1658   ExternalReference allocation_top =
   1659       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1660   ExternalReference allocation_limit =
   1661       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   1662 
   1663   intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
   1664   intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
   1665   DCHECK((limit - top) == kPointerSize);
   1666 
   1667   // Set up allocation top address register.
   1668   Register top_address = scratch1;
   1669   // This code stores a temporary value in ip. This is OK, as the code below
   1670   // does not need ip for implicit literal generation.
   1671   Register alloc_limit = ip;
   1672   Register result_end = scratch2;
   1673   mov(top_address, Operand(allocation_top));
   1674 
   1675   if ((flags & RESULT_CONTAINS_TOP) == 0) {
   1676     // Load allocation top into result and allocation limit into ip.
   1677     LoadP(result, MemOperand(top_address));
   1678     LoadP(alloc_limit, MemOperand(top_address, kPointerSize));
   1679   } else {
   1680     if (emit_debug_code()) {
   1681       // Assert that result actually contains top on entry.
   1682       LoadP(alloc_limit, MemOperand(top_address));
   1683       cmp(result, alloc_limit);
   1684       Check(eq, kUnexpectedAllocationTop);
   1685     }
   1686     // Load allocation limit. Result already contains allocation top.
   1687     LoadP(alloc_limit, MemOperand(top_address, limit - top));
   1688   }
   1689 
   1690   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1691     // Align the next allocation. Storing the filler map without checking top is
   1692     // safe in new-space because the limit of the heap is aligned there.
   1693 #if V8_TARGET_ARCH_PPC64
   1694     STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
   1695 #else
   1696     STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   1697     andi(result_end, result, Operand(kDoubleAlignmentMask));
   1698     Label aligned;
   1699     beq(&aligned, cr0);
   1700     if ((flags & PRETENURE) != 0) {
   1701       cmpl(result, alloc_limit);
   1702       bge(gc_required);
   1703     }
   1704     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   1705     stw(result_end, MemOperand(result));
   1706     addi(result, result, Operand(kDoubleSize / 2));
   1707     bind(&aligned);
   1708 #endif
   1709   }
   1710 
   1711   // Calculate new top and bail out if new space is exhausted. Use result
   1712   // to calculate the new top.
   1713   sub(r0, alloc_limit, result);
   1714   if (is_int16(object_size)) {
   1715     cmpi(r0, Operand(object_size));
   1716     blt(gc_required);
   1717     addi(result_end, result, Operand(object_size));
   1718   } else {
   1719     Cmpi(r0, Operand(object_size), result_end);
   1720     blt(gc_required);
   1721     add(result_end, result, result_end);
   1722   }
   1723 
   1724   if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
   1725     // The top pointer is not updated for allocation folding dominators.
   1726     StoreP(result_end, MemOperand(top_address));
   1727   }
   1728 
   1729   // Tag object.
   1730   addi(result, result, Operand(kHeapObjectTag));
   1731 }
   1732 
   1733 
   1734 void MacroAssembler::Allocate(Register object_size, Register result,
   1735                               Register result_end, Register scratch,
   1736                               Label* gc_required, AllocationFlags flags) {
   1737   DCHECK((flags & ALLOCATION_FOLDED) == 0);
   1738   if (!FLAG_inline_new) {
   1739     if (emit_debug_code()) {
   1740       // Trash the registers to simulate an allocation failure.
   1741       li(result, Operand(0x7091));
   1742       li(scratch, Operand(0x7191));
   1743       li(result_end, Operand(0x7291));
   1744     }
   1745     b(gc_required);
   1746     return;
   1747   }
   1748 
   1749   // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
   1750   // is not specified. Other registers must not overlap.
   1751   DCHECK(!AreAliased(object_size, result, scratch, ip));
   1752   DCHECK(!AreAliased(result_end, result, scratch, ip));
   1753   DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
   1754 
   1755   // Check relative positions of allocation top and limit addresses.
   1756   ExternalReference allocation_top =
   1757       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1758   ExternalReference allocation_limit =
   1759       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   1760   intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
   1761   intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
   1762   DCHECK((limit - top) == kPointerSize);
   1763 
   1764   // Set up allocation top address and allocation limit registers.
   1765   Register top_address = scratch;
   1766   // This code stores a temporary value in ip. This is OK, as the code below
   1767   // does not need ip for implicit literal generation.
   1768   Register alloc_limit = ip;
   1769   mov(top_address, Operand(allocation_top));
   1770 
   1771   if ((flags & RESULT_CONTAINS_TOP) == 0) {
   1772     // Load allocation top into result and allocation limit into alloc_limit..
   1773     LoadP(result, MemOperand(top_address));
   1774     LoadP(alloc_limit, MemOperand(top_address, kPointerSize));
   1775   } else {
   1776     if (emit_debug_code()) {
   1777       // Assert that result actually contains top on entry.
   1778       LoadP(alloc_limit, MemOperand(top_address));
   1779       cmp(result, alloc_limit);
   1780       Check(eq, kUnexpectedAllocationTop);
   1781     }
   1782     // Load allocation limit. Result already contains allocation top.
   1783     LoadP(alloc_limit, MemOperand(top_address, limit - top));
   1784   }
   1785 
   1786   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1787     // Align the next allocation. Storing the filler map without checking top is
   1788     // safe in new-space because the limit of the heap is aligned there.
   1789 #if V8_TARGET_ARCH_PPC64
   1790     STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
   1791 #else
   1792     STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   1793     andi(result_end, result, Operand(kDoubleAlignmentMask));
   1794     Label aligned;
   1795     beq(&aligned, cr0);
   1796     if ((flags & PRETENURE) != 0) {
   1797       cmpl(result, alloc_limit);
   1798       bge(gc_required);
   1799     }
   1800     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   1801     stw(result_end, MemOperand(result));
   1802     addi(result, result, Operand(kDoubleSize / 2));
   1803     bind(&aligned);
   1804 #endif
   1805   }
   1806 
   1807   // Calculate new top and bail out if new space is exhausted. Use result
   1808   // to calculate the new top. Object size may be in words so a shift is
   1809   // required to get the number of bytes.
   1810   sub(r0, alloc_limit, result);
   1811   if ((flags & SIZE_IN_WORDS) != 0) {
   1812     ShiftLeftImm(result_end, object_size, Operand(kPointerSizeLog2));
   1813     cmp(r0, result_end);
   1814     blt(gc_required);
   1815     add(result_end, result, result_end);
   1816   } else {
   1817     cmp(r0, object_size);
   1818     blt(gc_required);
   1819     add(result_end, result, object_size);
   1820   }
   1821 
   1822   // Update allocation top. result temporarily holds the new top.
   1823   if (emit_debug_code()) {
   1824     andi(r0, result_end, Operand(kObjectAlignmentMask));
   1825     Check(eq, kUnalignedAllocationInNewSpace, cr0);
   1826   }
   1827   if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
   1828     // The top pointer is not updated for allocation folding dominators.
   1829     StoreP(result_end, MemOperand(top_address));
   1830   }
   1831 
   1832   // Tag object.
   1833   addi(result, result, Operand(kHeapObjectTag));
   1834 }
   1835 
   1836 void MacroAssembler::FastAllocate(Register object_size, Register result,
   1837                                   Register result_end, Register scratch,
   1838                                   AllocationFlags flags) {
   1839   // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
   1840   // is not specified. Other registers must not overlap.
   1841   DCHECK(!AreAliased(object_size, result, scratch, ip));
   1842   DCHECK(!AreAliased(result_end, result, scratch, ip));
   1843   DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
   1844 
   1845   ExternalReference allocation_top =
   1846       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1847 
   1848   Register top_address = scratch;
   1849   mov(top_address, Operand(allocation_top));
   1850   LoadP(result, MemOperand(top_address));
   1851 
   1852   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1853     // Align the next allocation. Storing the filler map without checking top is
   1854     // safe in new-space because the limit of the heap is aligned there.
   1855 #if V8_TARGET_ARCH_PPC64
   1856     STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
   1857 #else
   1858     DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
   1859     andi(result_end, result, Operand(kDoubleAlignmentMask));
   1860     Label aligned;
   1861     beq(&aligned);
   1862     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   1863     stw(result_end, MemOperand(result));
   1864     addi(result, result, Operand(kDoubleSize / 2));
   1865     bind(&aligned);
   1866 #endif
   1867   }
   1868 
   1869   // Calculate new top using result. Object size may be in words so a shift is
   1870   // required to get the number of bytes.
   1871   if ((flags & SIZE_IN_WORDS) != 0) {
   1872     ShiftLeftImm(result_end, object_size, Operand(kPointerSizeLog2));
   1873     add(result_end, result, result_end);
   1874   } else {
   1875     add(result_end, result, object_size);
   1876   }
   1877 
   1878   // Update allocation top. result temporarily holds the new top.
   1879   if (emit_debug_code()) {
   1880     andi(r0, result_end, Operand(kObjectAlignmentMask));
   1881     Check(eq, kUnalignedAllocationInNewSpace, cr0);
   1882   }
   1883   StoreP(result_end, MemOperand(top_address));
   1884 
   1885   // Tag object.
   1886   addi(result, result, Operand(kHeapObjectTag));
   1887 }
   1888 
   1889 void MacroAssembler::FastAllocate(int object_size, Register result,
   1890                                   Register scratch1, Register scratch2,
   1891                                   AllocationFlags flags) {
   1892   DCHECK(object_size <= kMaxRegularHeapObjectSize);
   1893   DCHECK(!AreAliased(result, scratch1, scratch2, ip));
   1894 
   1895   // Make object size into bytes.
   1896   if ((flags & SIZE_IN_WORDS) != 0) {
   1897     object_size *= kPointerSize;
   1898   }
   1899   DCHECK_EQ(0, object_size & kObjectAlignmentMask);
   1900 
   1901   ExternalReference allocation_top =
   1902       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1903 
   1904   // Set up allocation top address register.
   1905   Register top_address = scratch1;
   1906   Register result_end = scratch2;
   1907   mov(top_address, Operand(allocation_top));
   1908   LoadP(result, MemOperand(top_address));
   1909 
   1910   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1911     // Align the next allocation. Storing the filler map without checking top is
   1912     // safe in new-space because the limit of the heap is aligned there.
   1913 #if V8_TARGET_ARCH_PPC64
   1914     STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
   1915 #else
   1916     DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
   1917     andi(result_end, result, Operand(kDoubleAlignmentMask));
   1918     Label aligned;
   1919     beq(&aligned);
   1920     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   1921     stw(result_end, MemOperand(result));
   1922     addi(result, result, Operand(kDoubleSize / 2));
   1923     bind(&aligned);
   1924 #endif
   1925   }
   1926 
   1927   // Calculate new top using result.
   1928   Add(result_end, result, object_size, r0);
   1929 
   1930   // The top pointer is not updated for allocation folding dominators.
   1931   StoreP(result_end, MemOperand(top_address));
   1932 
   1933   // Tag object.
   1934   addi(result, result, Operand(kHeapObjectTag));
   1935 }
   1936 
   1937 void MacroAssembler::CompareObjectType(Register object, Register map,
   1938                                        Register type_reg, InstanceType type) {
   1939   const Register temp = type_reg.is(no_reg) ? r0 : type_reg;
   1940 
   1941   LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
   1942   CompareInstanceType(map, temp, type);
   1943 }
   1944 
   1945 
   1946 void MacroAssembler::CompareInstanceType(Register map, Register type_reg,
   1947                                          InstanceType type) {
   1948   STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
   1949   STATIC_ASSERT(LAST_TYPE < 256);
   1950   lbz(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
   1951   cmpi(type_reg, Operand(type));
   1952 }
   1953 
   1954 
   1955 void MacroAssembler::CompareRoot(Register obj, Heap::RootListIndex index) {
   1956   DCHECK(!obj.is(r0));
   1957   LoadRoot(r0, index);
   1958   cmp(obj, r0);
   1959 }
   1960 
   1961 void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left,
   1962                                             Register right,
   1963                                             Register overflow_dst,
   1964                                             Register scratch) {
   1965   DCHECK(!dst.is(overflow_dst));
   1966   DCHECK(!dst.is(scratch));
   1967   DCHECK(!overflow_dst.is(scratch));
   1968   DCHECK(!overflow_dst.is(left));
   1969   DCHECK(!overflow_dst.is(right));
   1970 
   1971   bool left_is_right = left.is(right);
   1972   RCBit xorRC = left_is_right ? SetRC : LeaveRC;
   1973 
   1974   // C = A+B; C overflows if A/B have same sign and C has diff sign than A
   1975   if (dst.is(left)) {
   1976     mr(scratch, left);            // Preserve left.
   1977     add(dst, left, right);        // Left is overwritten.
   1978     xor_(overflow_dst, dst, scratch, xorRC);  // Original left.
   1979     if (!left_is_right) xor_(scratch, dst, right);
   1980   } else if (dst.is(right)) {
   1981     mr(scratch, right);           // Preserve right.
   1982     add(dst, left, right);        // Right is overwritten.
   1983     xor_(overflow_dst, dst, left, xorRC);
   1984     if (!left_is_right) xor_(scratch, dst, scratch);  // Original right.
   1985   } else {
   1986     add(dst, left, right);
   1987     xor_(overflow_dst, dst, left, xorRC);
   1988     if (!left_is_right) xor_(scratch, dst, right);
   1989   }
   1990   if (!left_is_right) and_(overflow_dst, scratch, overflow_dst, SetRC);
   1991 }
   1992 
   1993 
   1994 void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left,
   1995                                             intptr_t right,
   1996                                             Register overflow_dst,
   1997                                             Register scratch) {
   1998   Register original_left = left;
   1999   DCHECK(!dst.is(overflow_dst));
   2000   DCHECK(!dst.is(scratch));
   2001   DCHECK(!overflow_dst.is(scratch));
   2002   DCHECK(!overflow_dst.is(left));
   2003 
   2004   // C = A+B; C overflows if A/B have same sign and C has diff sign than A
   2005   if (dst.is(left)) {
   2006     // Preserve left.
   2007     original_left = overflow_dst;
   2008     mr(original_left, left);
   2009   }
   2010   Add(dst, left, right, scratch);
   2011   xor_(overflow_dst, dst, original_left);
   2012   if (right >= 0) {
   2013     and_(overflow_dst, overflow_dst, dst, SetRC);
   2014   } else {
   2015     andc(overflow_dst, overflow_dst, dst, SetRC);
   2016   }
   2017 }
   2018 
   2019 
   2020 void MacroAssembler::SubAndCheckForOverflow(Register dst, Register left,
   2021                                             Register right,
   2022                                             Register overflow_dst,
   2023                                             Register scratch) {
   2024   DCHECK(!dst.is(overflow_dst));
   2025   DCHECK(!dst.is(scratch));
   2026   DCHECK(!overflow_dst.is(scratch));
   2027   DCHECK(!overflow_dst.is(left));
   2028   DCHECK(!overflow_dst.is(right));
   2029 
   2030   // C = A-B; C overflows if A/B have diff signs and C has diff sign than A
   2031   if (dst.is(left)) {
   2032     mr(scratch, left);      // Preserve left.
   2033     sub(dst, left, right);  // Left is overwritten.
   2034     xor_(overflow_dst, dst, scratch);
   2035     xor_(scratch, scratch, right);
   2036     and_(overflow_dst, overflow_dst, scratch, SetRC);
   2037   } else if (dst.is(right)) {
   2038     mr(scratch, right);     // Preserve right.
   2039     sub(dst, left, right);  // Right is overwritten.
   2040     xor_(overflow_dst, dst, left);
   2041     xor_(scratch, left, scratch);
   2042     and_(overflow_dst, overflow_dst, scratch, SetRC);
   2043   } else {
   2044     sub(dst, left, right);
   2045     xor_(overflow_dst, dst, left);
   2046     xor_(scratch, left, right);
   2047     and_(overflow_dst, scratch, overflow_dst, SetRC);
   2048   }
   2049 }
   2050 
   2051 
   2052 void MacroAssembler::CompareMap(Register obj, Register scratch, Handle<Map> map,
   2053                                 Label* early_success) {
   2054   LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   2055   CompareMap(scratch, map, early_success);
   2056 }
   2057 
   2058 
   2059 void MacroAssembler::CompareMap(Register obj_map, Handle<Map> map,
   2060                                 Label* early_success) {
   2061   mov(r0, Operand(map));
   2062   cmp(obj_map, r0);
   2063 }
   2064 
   2065 
   2066 void MacroAssembler::CheckMap(Register obj, Register scratch, Handle<Map> map,
   2067                               Label* fail, SmiCheckType smi_check_type) {
   2068   if (smi_check_type == DO_SMI_CHECK) {
   2069     JumpIfSmi(obj, fail);
   2070   }
   2071 
   2072   Label success;
   2073   CompareMap(obj, scratch, map, &success);
   2074   bne(fail);
   2075   bind(&success);
   2076 }
   2077 
   2078 
   2079 void MacroAssembler::CheckMap(Register obj, Register scratch,
   2080                               Heap::RootListIndex index, Label* fail,
   2081                               SmiCheckType smi_check_type) {
   2082   if (smi_check_type == DO_SMI_CHECK) {
   2083     JumpIfSmi(obj, fail);
   2084   }
   2085   LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   2086   LoadRoot(r0, index);
   2087   cmp(scratch, r0);
   2088   bne(fail);
   2089 }
   2090 
   2091 
   2092 void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
   2093                                      Register scratch2, Handle<WeakCell> cell,
   2094                                      Handle<Code> success,
   2095                                      SmiCheckType smi_check_type) {
   2096   Label fail;
   2097   if (smi_check_type == DO_SMI_CHECK) {
   2098     JumpIfSmi(obj, &fail);
   2099   }
   2100   LoadP(scratch1, FieldMemOperand(obj, HeapObject::kMapOffset));
   2101   CmpWeakValue(scratch1, cell, scratch2);
   2102   Jump(success, RelocInfo::CODE_TARGET, eq);
   2103   bind(&fail);
   2104 }
   2105 
   2106 
   2107 void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
   2108                                   Register scratch, CRegister cr) {
   2109   mov(scratch, Operand(cell));
   2110   LoadP(scratch, FieldMemOperand(scratch, WeakCell::kValueOffset));
   2111   cmp(value, scratch, cr);
   2112 }
   2113 
   2114 
   2115 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
   2116   mov(value, Operand(cell));
   2117   LoadP(value, FieldMemOperand(value, WeakCell::kValueOffset));
   2118 }
   2119 
   2120 
   2121 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
   2122                                    Label* miss) {
   2123   GetWeakValue(value, cell);
   2124   JumpIfSmi(value, miss);
   2125 }
   2126 
   2127 
   2128 void MacroAssembler::GetMapConstructor(Register result, Register map,
   2129                                        Register temp, Register temp2) {
   2130   Label done, loop;
   2131   LoadP(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
   2132   bind(&loop);
   2133   JumpIfSmi(result, &done);
   2134   CompareObjectType(result, temp, temp2, MAP_TYPE);
   2135   bne(&done);
   2136   LoadP(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
   2137   b(&loop);
   2138   bind(&done);
   2139 }
   2140 
   2141 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id,
   2142                               Condition cond) {
   2143   DCHECK(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
   2144   Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond);
   2145 }
   2146 
   2147 
   2148 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
   2149   Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
   2150 }
   2151 
   2152 
   2153 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   2154   return has_frame_ || !stub->SometimesSetsUpAFrame();
   2155 }
   2156 
   2157 void MacroAssembler::SmiToDouble(DoubleRegister value, Register smi) {
   2158   SmiUntag(ip, smi);
   2159   ConvertIntToDouble(ip, value);
   2160 }
   2161 
   2162 
   2163 void MacroAssembler::TestDoubleIsInt32(DoubleRegister double_input,
   2164                                        Register scratch1, Register scratch2,
   2165                                        DoubleRegister double_scratch) {
   2166   TryDoubleToInt32Exact(scratch1, double_input, scratch2, double_scratch);
   2167 }
   2168 
   2169 void MacroAssembler::TestDoubleIsMinusZero(DoubleRegister input,
   2170                                            Register scratch1,
   2171                                            Register scratch2) {
   2172 #if V8_TARGET_ARCH_PPC64
   2173   MovDoubleToInt64(scratch1, input);
   2174   rotldi(scratch1, scratch1, 1);
   2175   cmpi(scratch1, Operand(1));
   2176 #else
   2177   MovDoubleToInt64(scratch1, scratch2, input);
   2178   Label done;
   2179   cmpi(scratch2, Operand::Zero());
   2180   bne(&done);
   2181   lis(scratch2, Operand(SIGN_EXT_IMM16(0x8000)));
   2182   cmp(scratch1, scratch2);
   2183   bind(&done);
   2184 #endif
   2185 }
   2186 
   2187 void MacroAssembler::TestDoubleSign(DoubleRegister input, Register scratch) {
   2188 #if V8_TARGET_ARCH_PPC64
   2189   MovDoubleToInt64(scratch, input);
   2190 #else
   2191   MovDoubleHighToInt(scratch, input);
   2192 #endif
   2193   cmpi(scratch, Operand::Zero());
   2194 }
   2195 
   2196 void MacroAssembler::TestHeapNumberSign(Register input, Register scratch) {
   2197 #if V8_TARGET_ARCH_PPC64
   2198   LoadP(scratch, FieldMemOperand(input, HeapNumber::kValueOffset));
   2199 #else
   2200   lwz(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset));
   2201 #endif
   2202   cmpi(scratch, Operand::Zero());
   2203 }
   2204 
   2205 void MacroAssembler::TryDoubleToInt32Exact(Register result,
   2206                                            DoubleRegister double_input,
   2207                                            Register scratch,
   2208                                            DoubleRegister double_scratch) {
   2209   Label done;
   2210   DCHECK(!double_input.is(double_scratch));
   2211 
   2212   ConvertDoubleToInt64(double_input,
   2213 #if !V8_TARGET_ARCH_PPC64
   2214                        scratch,
   2215 #endif
   2216                        result, double_scratch);
   2217 
   2218 #if V8_TARGET_ARCH_PPC64
   2219   TestIfInt32(result, r0);
   2220 #else
   2221   TestIfInt32(scratch, result, r0);
   2222 #endif
   2223   bne(&done);
   2224 
   2225   // convert back and compare
   2226   fcfid(double_scratch, double_scratch);
   2227   fcmpu(double_scratch, double_input);
   2228   bind(&done);
   2229 }
   2230 
   2231 
   2232 void MacroAssembler::TryInt32Floor(Register result, DoubleRegister double_input,
   2233                                    Register input_high, Register scratch,
   2234                                    DoubleRegister double_scratch, Label* done,
   2235                                    Label* exact) {
   2236   DCHECK(!result.is(input_high));
   2237   DCHECK(!double_input.is(double_scratch));
   2238   Label exception;
   2239 
   2240   MovDoubleHighToInt(input_high, double_input);
   2241 
   2242   // Test for NaN/Inf
   2243   ExtractBitMask(result, input_high, HeapNumber::kExponentMask);
   2244   cmpli(result, Operand(0x7ff));
   2245   beq(&exception);
   2246 
   2247   // Convert (rounding to -Inf)
   2248   ConvertDoubleToInt64(double_input,
   2249 #if !V8_TARGET_ARCH_PPC64
   2250                        scratch,
   2251 #endif
   2252                        result, double_scratch, kRoundToMinusInf);
   2253 
   2254 // Test for overflow
   2255 #if V8_TARGET_ARCH_PPC64
   2256   TestIfInt32(result, r0);
   2257 #else
   2258   TestIfInt32(scratch, result, r0);
   2259 #endif
   2260   bne(&exception);
   2261 
   2262   // Test for exactness
   2263   fcfid(double_scratch, double_scratch);
   2264   fcmpu(double_scratch, double_input);
   2265   beq(exact);
   2266   b(done);
   2267 
   2268   bind(&exception);
   2269 }
   2270 
   2271 
   2272 void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
   2273                                                 DoubleRegister double_input,
   2274                                                 Label* done) {
   2275   DoubleRegister double_scratch = kScratchDoubleReg;
   2276 #if !V8_TARGET_ARCH_PPC64
   2277   Register scratch = ip;
   2278 #endif
   2279 
   2280   ConvertDoubleToInt64(double_input,
   2281 #if !V8_TARGET_ARCH_PPC64
   2282                        scratch,
   2283 #endif
   2284                        result, double_scratch);
   2285 
   2286 // Test for overflow
   2287 #if V8_TARGET_ARCH_PPC64
   2288   TestIfInt32(result, r0);
   2289 #else
   2290   TestIfInt32(scratch, result, r0);
   2291 #endif
   2292   beq(done);
   2293 }
   2294 
   2295 
   2296 void MacroAssembler::TruncateDoubleToI(Register result,
   2297                                        DoubleRegister double_input) {
   2298   Label done;
   2299 
   2300   TryInlineTruncateDoubleToI(result, double_input, &done);
   2301 
   2302   // If we fell through then inline version didn't succeed - call stub instead.
   2303   mflr(r0);
   2304   push(r0);
   2305   // Put input on stack.
   2306   stfdu(double_input, MemOperand(sp, -kDoubleSize));
   2307 
   2308   DoubleToIStub stub(isolate(), sp, result, 0, true, true);
   2309   CallStub(&stub);
   2310 
   2311   addi(sp, sp, Operand(kDoubleSize));
   2312   pop(r0);
   2313   mtlr(r0);
   2314 
   2315   bind(&done);
   2316 }
   2317 
   2318 
   2319 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
   2320   Label done;
   2321   DoubleRegister double_scratch = kScratchDoubleReg;
   2322   DCHECK(!result.is(object));
   2323 
   2324   lfd(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
   2325   TryInlineTruncateDoubleToI(result, double_scratch, &done);
   2326 
   2327   // If we fell through then inline version didn't succeed - call stub instead.
   2328   mflr(r0);
   2329   push(r0);
   2330   DoubleToIStub stub(isolate(), object, result,
   2331                      HeapNumber::kValueOffset - kHeapObjectTag, true, true);
   2332   CallStub(&stub);
   2333   pop(r0);
   2334   mtlr(r0);
   2335 
   2336   bind(&done);
   2337 }
   2338 
   2339 
   2340 void MacroAssembler::TruncateNumberToI(Register object, Register result,
   2341                                        Register heap_number_map,
   2342                                        Register scratch1, Label* not_number) {
   2343   Label done;
   2344   DCHECK(!result.is(object));
   2345 
   2346   UntagAndJumpIfSmi(result, object, &done);
   2347   JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
   2348   TruncateHeapNumberToI(result, object);
   2349 
   2350   bind(&done);
   2351 }
   2352 
   2353 
   2354 void MacroAssembler::GetLeastBitsFromSmi(Register dst, Register src,
   2355                                          int num_least_bits) {
   2356 #if V8_TARGET_ARCH_PPC64
   2357   rldicl(dst, src, kBitsPerPointer - kSmiShift,
   2358          kBitsPerPointer - num_least_bits);
   2359 #else
   2360   rlwinm(dst, src, kBitsPerPointer - kSmiShift,
   2361          kBitsPerPointer - num_least_bits, 31);
   2362 #endif
   2363 }
   2364 
   2365 
   2366 void MacroAssembler::GetLeastBitsFromInt32(Register dst, Register src,
   2367                                            int num_least_bits) {
   2368   rlwinm(dst, src, 0, 32 - num_least_bits, 31);
   2369 }
   2370 
   2371 
   2372 void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
   2373                                  SaveFPRegsMode save_doubles) {
   2374   // All parameters are on the stack.  r3 has the return value after call.
   2375 
   2376   // If the expected number of arguments of the runtime function is
   2377   // constant, we check that the actual number of arguments match the
   2378   // expectation.
   2379   CHECK(f->nargs < 0 || f->nargs == num_arguments);
   2380 
   2381   // TODO(1236192): Most runtime routines don't need the number of
   2382   // arguments passed in because it is constant. At some point we
   2383   // should remove this need and make the runtime routine entry code
   2384   // smarter.
   2385   mov(r3, Operand(num_arguments));
   2386   mov(r4, Operand(ExternalReference(f, isolate())));
   2387   CEntryStub stub(isolate(),
   2388 #if V8_TARGET_ARCH_PPC64
   2389                   f->result_size,
   2390 #else
   2391                   1,
   2392 #endif
   2393                   save_doubles);
   2394   CallStub(&stub);
   2395 }
   2396 
   2397 
   2398 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
   2399                                            int num_arguments) {
   2400   mov(r3, Operand(num_arguments));
   2401   mov(r4, Operand(ext));
   2402 
   2403   CEntryStub stub(isolate(), 1);
   2404   CallStub(&stub);
   2405 }
   2406 
   2407 
   2408 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
   2409   const Runtime::Function* function = Runtime::FunctionForId(fid);
   2410   DCHECK_EQ(1, function->result_size);
   2411   if (function->nargs >= 0) {
   2412     mov(r3, Operand(function->nargs));
   2413   }
   2414   JumpToExternalReference(ExternalReference(fid, isolate()));
   2415 }
   2416 
   2417 
   2418 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
   2419                                              bool builtin_exit_frame) {
   2420   mov(r4, Operand(builtin));
   2421   CEntryStub stub(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
   2422                   builtin_exit_frame);
   2423   Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
   2424 }
   2425 
   2426 
   2427 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
   2428                                 Register scratch1, Register scratch2) {
   2429   if (FLAG_native_code_counters && counter->Enabled()) {
   2430     mov(scratch1, Operand(value));
   2431     mov(scratch2, Operand(ExternalReference(counter)));
   2432     stw(scratch1, MemOperand(scratch2));
   2433   }
   2434 }
   2435 
   2436 
   2437 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
   2438                                       Register scratch1, Register scratch2) {
   2439   DCHECK(value > 0);
   2440   if (FLAG_native_code_counters && counter->Enabled()) {
   2441     mov(scratch2, Operand(ExternalReference(counter)));
   2442     lwz(scratch1, MemOperand(scratch2));
   2443     addi(scratch1, scratch1, Operand(value));
   2444     stw(scratch1, MemOperand(scratch2));
   2445   }
   2446 }
   2447 
   2448 
   2449 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
   2450                                       Register scratch1, Register scratch2) {
   2451   DCHECK(value > 0);
   2452   if (FLAG_native_code_counters && counter->Enabled()) {
   2453     mov(scratch2, Operand(ExternalReference(counter)));
   2454     lwz(scratch1, MemOperand(scratch2));
   2455     subi(scratch1, scratch1, Operand(value));
   2456     stw(scratch1, MemOperand(scratch2));
   2457   }
   2458 }
   2459 
   2460 
   2461 void MacroAssembler::Assert(Condition cond, BailoutReason reason,
   2462                             CRegister cr) {
   2463   if (emit_debug_code()) Check(cond, reason, cr);
   2464 }
   2465 
   2466 
   2467 void MacroAssembler::AssertFastElements(Register elements) {
   2468   if (emit_debug_code()) {
   2469     DCHECK(!elements.is(r0));
   2470     Label ok;
   2471     push(elements);
   2472     LoadP(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
   2473     LoadRoot(r0, Heap::kFixedArrayMapRootIndex);
   2474     cmp(elements, r0);
   2475     beq(&ok);
   2476     LoadRoot(r0, Heap::kFixedDoubleArrayMapRootIndex);
   2477     cmp(elements, r0);
   2478     beq(&ok);
   2479     LoadRoot(r0, Heap::kFixedCOWArrayMapRootIndex);
   2480     cmp(elements, r0);
   2481     beq(&ok);
   2482     Abort(kJSObjectWithFastElementsMapHasSlowElements);
   2483     bind(&ok);
   2484     pop(elements);
   2485   }
   2486 }
   2487 
   2488 
   2489 void MacroAssembler::Check(Condition cond, BailoutReason reason, CRegister cr) {
   2490   Label L;
   2491   b(cond, &L, cr);
   2492   Abort(reason);
   2493   // will not return here
   2494   bind(&L);
   2495 }
   2496 
   2497 
   2498 void MacroAssembler::Abort(BailoutReason reason) {
   2499   Label abort_start;
   2500   bind(&abort_start);
   2501 #ifdef DEBUG
   2502   const char* msg = GetBailoutReason(reason);
   2503   if (msg != NULL) {
   2504     RecordComment("Abort message: ");
   2505     RecordComment(msg);
   2506   }
   2507 
   2508   if (FLAG_trap_on_abort) {
   2509     stop(msg);
   2510     return;
   2511   }
   2512 #endif
   2513 
   2514   // Check if Abort() has already been initialized.
   2515   DCHECK(isolate()->builtins()->Abort()->IsHeapObject());
   2516 
   2517   LoadSmiLiteral(r4, Smi::FromInt(static_cast<int>(reason)));
   2518 
   2519   // Disable stub call restrictions to always allow calls to abort.
   2520   if (!has_frame_) {
   2521     // We don't actually want to generate a pile of code for this, so just
   2522     // claim there is a stack frame, without generating one.
   2523     FrameScope scope(this, StackFrame::NONE);
   2524     Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
   2525   } else {
   2526     Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
   2527   }
   2528   // will not return here
   2529 }
   2530 
   2531 
   2532 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
   2533   if (context_chain_length > 0) {
   2534     // Move up the chain of contexts to the context containing the slot.
   2535     LoadP(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2536     for (int i = 1; i < context_chain_length; i++) {
   2537       LoadP(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2538     }
   2539   } else {
   2540     // Slot is in the current function context.  Move it into the
   2541     // destination register in case we store into it (the write barrier
   2542     // cannot be allowed to destroy the context in esi).
   2543     mr(dst, cp);
   2544   }
   2545 }
   2546 
   2547 void MacroAssembler::LoadNativeContextSlot(int index, Register dst) {
   2548   LoadP(dst, NativeContextMemOperand());
   2549   LoadP(dst, ContextMemOperand(dst, index));
   2550 }
   2551 
   2552 
   2553 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
   2554                                                   Register map,
   2555                                                   Register scratch) {
   2556   // Load the initial map. The global functions all have initial maps.
   2557   LoadP(map,
   2558         FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   2559   if (emit_debug_code()) {
   2560     Label ok, fail;
   2561     CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
   2562     b(&ok);
   2563     bind(&fail);
   2564     Abort(kGlobalFunctionsMustHaveInitialMap);
   2565     bind(&ok);
   2566   }
   2567 }
   2568 
   2569 
   2570 void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
   2571     Register reg, Register scratch, Label* not_power_of_two_or_zero) {
   2572   subi(scratch, reg, Operand(1));
   2573   cmpi(scratch, Operand::Zero());
   2574   blt(not_power_of_two_or_zero);
   2575   and_(r0, scratch, reg, SetRC);
   2576   bne(not_power_of_two_or_zero, cr0);
   2577 }
   2578 
   2579 
   2580 void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
   2581                                                      Register scratch,
   2582                                                      Label* zero_and_neg,
   2583                                                      Label* not_power_of_two) {
   2584   subi(scratch, reg, Operand(1));
   2585   cmpi(scratch, Operand::Zero());
   2586   blt(zero_and_neg);
   2587   and_(r0, scratch, reg, SetRC);
   2588   bne(not_power_of_two, cr0);
   2589 }
   2590 
   2591 #if !V8_TARGET_ARCH_PPC64
   2592 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
   2593   DCHECK(!reg.is(overflow));
   2594   mr(overflow, reg);  // Save original value.
   2595   SmiTag(reg);
   2596   xor_(overflow, overflow, reg, SetRC);  // Overflow if (value ^ 2 * value) < 0.
   2597 }
   2598 
   2599 
   2600 void MacroAssembler::SmiTagCheckOverflow(Register dst, Register src,
   2601                                          Register overflow) {
   2602   if (dst.is(src)) {
   2603     // Fall back to slower case.
   2604     SmiTagCheckOverflow(dst, overflow);
   2605   } else {
   2606     DCHECK(!dst.is(src));
   2607     DCHECK(!dst.is(overflow));
   2608     DCHECK(!src.is(overflow));
   2609     SmiTag(dst, src);
   2610     xor_(overflow, dst, src, SetRC);  // Overflow if (value ^ 2 * value) < 0.
   2611   }
   2612 }
   2613 #endif
   2614 
   2615 void MacroAssembler::JumpIfNotBothSmi(Register reg1, Register reg2,
   2616                                       Label* on_not_both_smi) {
   2617   STATIC_ASSERT(kSmiTag == 0);
   2618   orx(r0, reg1, reg2, LeaveRC);
   2619   JumpIfNotSmi(r0, on_not_both_smi);
   2620 }
   2621 
   2622 
   2623 void MacroAssembler::UntagAndJumpIfSmi(Register dst, Register src,
   2624                                        Label* smi_case) {
   2625   STATIC_ASSERT(kSmiTag == 0);
   2626   TestBitRange(src, kSmiTagSize - 1, 0, r0);
   2627   SmiUntag(dst, src);
   2628   beq(smi_case, cr0);
   2629 }
   2630 
   2631 void MacroAssembler::JumpIfEitherSmi(Register reg1, Register reg2,
   2632                                      Label* on_either_smi) {
   2633   STATIC_ASSERT(kSmiTag == 0);
   2634   JumpIfSmi(reg1, on_either_smi);
   2635   JumpIfSmi(reg2, on_either_smi);
   2636 }
   2637 
   2638 void MacroAssembler::AssertNotNumber(Register object) {
   2639   if (emit_debug_code()) {
   2640     STATIC_ASSERT(kSmiTag == 0);
   2641     TestIfSmi(object, r0);
   2642     Check(ne, kOperandIsANumber, cr0);
   2643     push(object);
   2644     CompareObjectType(object, object, object, HEAP_NUMBER_TYPE);
   2645     pop(object);
   2646     Check(ne, kOperandIsANumber);
   2647   }
   2648 }
   2649 
   2650 void MacroAssembler::AssertNotSmi(Register object) {
   2651   if (emit_debug_code()) {
   2652     STATIC_ASSERT(kSmiTag == 0);
   2653     TestIfSmi(object, r0);
   2654     Check(ne, kOperandIsASmi, cr0);
   2655   }
   2656 }
   2657 
   2658 
   2659 void MacroAssembler::AssertSmi(Register object) {
   2660   if (emit_debug_code()) {
   2661     STATIC_ASSERT(kSmiTag == 0);
   2662     TestIfSmi(object, r0);
   2663     Check(eq, kOperandIsNotSmi, cr0);
   2664   }
   2665 }
   2666 
   2667 
   2668 void MacroAssembler::AssertString(Register object) {
   2669   if (emit_debug_code()) {
   2670     STATIC_ASSERT(kSmiTag == 0);
   2671     TestIfSmi(object, r0);
   2672     Check(ne, kOperandIsASmiAndNotAString, cr0);
   2673     push(object);
   2674     LoadP(object, FieldMemOperand(object, HeapObject::kMapOffset));
   2675     CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
   2676     pop(object);
   2677     Check(lt, kOperandIsNotAString);
   2678   }
   2679 }
   2680 
   2681 
   2682 void MacroAssembler::AssertName(Register object) {
   2683   if (emit_debug_code()) {
   2684     STATIC_ASSERT(kSmiTag == 0);
   2685     TestIfSmi(object, r0);
   2686     Check(ne, kOperandIsASmiAndNotAName, cr0);
   2687     push(object);
   2688     LoadP(object, FieldMemOperand(object, HeapObject::kMapOffset));
   2689     CompareInstanceType(object, object, LAST_NAME_TYPE);
   2690     pop(object);
   2691     Check(le, kOperandIsNotAName);
   2692   }
   2693 }
   2694 
   2695 
   2696 void MacroAssembler::AssertFunction(Register object) {
   2697   if (emit_debug_code()) {
   2698     STATIC_ASSERT(kSmiTag == 0);
   2699     TestIfSmi(object, r0);
   2700     Check(ne, kOperandIsASmiAndNotAFunction, cr0);
   2701     push(object);
   2702     CompareObjectType(object, object, object, JS_FUNCTION_TYPE);
   2703     pop(object);
   2704     Check(eq, kOperandIsNotAFunction);
   2705   }
   2706 }
   2707 
   2708 
   2709 void MacroAssembler::AssertBoundFunction(Register object) {
   2710   if (emit_debug_code()) {
   2711     STATIC_ASSERT(kSmiTag == 0);
   2712     TestIfSmi(object, r0);
   2713     Check(ne, kOperandIsASmiAndNotABoundFunction, cr0);
   2714     push(object);
   2715     CompareObjectType(object, object, object, JS_BOUND_FUNCTION_TYPE);
   2716     pop(object);
   2717     Check(eq, kOperandIsNotABoundFunction);
   2718   }
   2719 }
   2720 
   2721 void MacroAssembler::AssertGeneratorObject(Register object) {
   2722   if (emit_debug_code()) {
   2723     STATIC_ASSERT(kSmiTag == 0);
   2724     TestIfSmi(object, r0);
   2725     Check(ne, kOperandIsASmiAndNotAGeneratorObject, cr0);
   2726     push(object);
   2727     CompareObjectType(object, object, object, JS_GENERATOR_OBJECT_TYPE);
   2728     pop(object);
   2729     Check(eq, kOperandIsNotAGeneratorObject);
   2730   }
   2731 }
   2732 
   2733 void MacroAssembler::AssertReceiver(Register object) {
   2734   if (emit_debug_code()) {
   2735     STATIC_ASSERT(kSmiTag == 0);
   2736     TestIfSmi(object, r0);
   2737     Check(ne, kOperandIsASmiAndNotAReceiver, cr0);
   2738     push(object);
   2739     STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
   2740     CompareObjectType(object, object, object, FIRST_JS_RECEIVER_TYPE);
   2741     pop(object);
   2742     Check(ge, kOperandIsNotAReceiver);
   2743   }
   2744 }
   2745 
   2746 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
   2747                                                      Register scratch) {
   2748   if (emit_debug_code()) {
   2749     Label done_checking;
   2750     AssertNotSmi(object);
   2751     CompareRoot(object, Heap::kUndefinedValueRootIndex);
   2752     beq(&done_checking);
   2753     LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   2754     CompareRoot(scratch, Heap::kAllocationSiteMapRootIndex);
   2755     Assert(eq, kExpectedUndefinedOrCell);
   2756     bind(&done_checking);
   2757   }
   2758 }
   2759 
   2760 
   2761 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
   2762   if (emit_debug_code()) {
   2763     CompareRoot(reg, index);
   2764     Check(eq, kHeapNumberMapRegisterClobbered);
   2765   }
   2766 }
   2767 
   2768 
   2769 void MacroAssembler::JumpIfNotHeapNumber(Register object,
   2770                                          Register heap_number_map,
   2771                                          Register scratch,
   2772                                          Label* on_not_heap_number) {
   2773   LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   2774   AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
   2775   cmp(scratch, heap_number_map);
   2776   bne(on_not_heap_number);
   2777 }
   2778 
   2779 
   2780 void MacroAssembler::JumpIfNonSmisNotBothSequentialOneByteStrings(
   2781     Register first, Register second, Register scratch1, Register scratch2,
   2782     Label* failure) {
   2783   // Test that both first and second are sequential one-byte strings.
   2784   // Assume that they are non-smis.
   2785   LoadP(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
   2786   LoadP(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
   2787   lbz(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
   2788   lbz(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
   2789 
   2790   JumpIfBothInstanceTypesAreNotSequentialOneByte(scratch1, scratch2, scratch1,
   2791                                                  scratch2, failure);
   2792 }
   2793 
   2794 void MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register first,
   2795                                                            Register second,
   2796                                                            Register scratch1,
   2797                                                            Register scratch2,
   2798                                                            Label* failure) {
   2799   // Check that neither is a smi.
   2800   and_(scratch1, first, second);
   2801   JumpIfSmi(scratch1, failure);
   2802   JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1,
   2803                                                scratch2, failure);
   2804 }
   2805 
   2806 
   2807 void MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
   2808                                                      Label* not_unique_name) {
   2809   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
   2810   Label succeed;
   2811   andi(r0, reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
   2812   beq(&succeed, cr0);
   2813   cmpi(reg, Operand(SYMBOL_TYPE));
   2814   bne(not_unique_name);
   2815 
   2816   bind(&succeed);
   2817 }
   2818 
   2819 
   2820 // Allocates a heap number or jumps to the need_gc label if the young space
   2821 // is full and a scavenge is needed.
   2822 void MacroAssembler::AllocateHeapNumber(Register result, Register scratch1,
   2823                                         Register scratch2,
   2824                                         Register heap_number_map,
   2825                                         Label* gc_required,
   2826                                         MutableMode mode) {
   2827   // Allocate an object in the heap for the heap number and tag it as a heap
   2828   // object.
   2829   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
   2830            NO_ALLOCATION_FLAGS);
   2831 
   2832   Heap::RootListIndex map_index = mode == MUTABLE
   2833                                       ? Heap::kMutableHeapNumberMapRootIndex
   2834                                       : Heap::kHeapNumberMapRootIndex;
   2835   AssertIsRoot(heap_number_map, map_index);
   2836 
   2837   // Store heap number map in the allocated object.
   2838   StoreP(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset),
   2839         r0);
   2840 }
   2841 
   2842 
   2843 void MacroAssembler::AllocateHeapNumberWithValue(
   2844     Register result, DoubleRegister value, Register scratch1, Register scratch2,
   2845     Register heap_number_map, Label* gc_required) {
   2846   AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required);
   2847   stfd(value, FieldMemOperand(result, HeapNumber::kValueOffset));
   2848 }
   2849 
   2850 
   2851 void MacroAssembler::AllocateJSValue(Register result, Register constructor,
   2852                                      Register value, Register scratch1,
   2853                                      Register scratch2, Label* gc_required) {
   2854   DCHECK(!result.is(constructor));
   2855   DCHECK(!result.is(scratch1));
   2856   DCHECK(!result.is(scratch2));
   2857   DCHECK(!result.is(value));
   2858 
   2859   // Allocate JSValue in new space.
   2860   Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
   2861            NO_ALLOCATION_FLAGS);
   2862 
   2863   // Initialize the JSValue.
   2864   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
   2865   StoreP(scratch1, FieldMemOperand(result, HeapObject::kMapOffset), r0);
   2866   LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
   2867   StoreP(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset), r0);
   2868   StoreP(scratch1, FieldMemOperand(result, JSObject::kElementsOffset), r0);
   2869   StoreP(value, FieldMemOperand(result, JSValue::kValueOffset), r0);
   2870   STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
   2871 }
   2872 
   2873 void MacroAssembler::InitializeNFieldsWithFiller(Register current_address,
   2874                                                  Register count,
   2875                                                  Register filler) {
   2876   Label loop;
   2877   mtctr(count);
   2878   bind(&loop);
   2879   StoreP(filler, MemOperand(current_address));
   2880   addi(current_address, current_address, Operand(kPointerSize));
   2881   bdnz(&loop);
   2882 }
   2883 
   2884 void MacroAssembler::InitializeFieldsWithFiller(Register current_address,
   2885                                                 Register end_address,
   2886                                                 Register filler) {
   2887   Label done;
   2888   sub(r0, end_address, current_address, LeaveOE, SetRC);
   2889   beq(&done, cr0);
   2890   ShiftRightImm(r0, r0, Operand(kPointerSizeLog2));
   2891   InitializeNFieldsWithFiller(current_address, r0, filler);
   2892   bind(&done);
   2893 }
   2894 
   2895 
   2896 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
   2897     Register first, Register second, Register scratch1, Register scratch2,
   2898     Label* failure) {
   2899   const int kFlatOneByteStringMask =
   2900       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
   2901   const int kFlatOneByteStringTag =
   2902       kStringTag | kOneByteStringTag | kSeqStringTag;
   2903   andi(scratch1, first, Operand(kFlatOneByteStringMask));
   2904   andi(scratch2, second, Operand(kFlatOneByteStringMask));
   2905   cmpi(scratch1, Operand(kFlatOneByteStringTag));
   2906   bne(failure);
   2907   cmpi(scratch2, Operand(kFlatOneByteStringTag));
   2908   bne(failure);
   2909 }
   2910 
   2911 static const int kRegisterPassedArguments = 8;
   2912 
   2913 
   2914 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
   2915                                               int num_double_arguments) {
   2916   int stack_passed_words = 0;
   2917   if (num_double_arguments > DoubleRegister::kNumRegisters) {
   2918     stack_passed_words +=
   2919         2 * (num_double_arguments - DoubleRegister::kNumRegisters);
   2920   }
   2921   // Up to 8 simple arguments are passed in registers r3..r10.
   2922   if (num_reg_arguments > kRegisterPassedArguments) {
   2923     stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
   2924   }
   2925   return stack_passed_words;
   2926 }
   2927 
   2928 
   2929 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, Register index,
   2930                                                Register value,
   2931                                                uint32_t encoding_mask) {
   2932   Label is_object;
   2933   TestIfSmi(string, r0);
   2934   Check(ne, kNonObject, cr0);
   2935 
   2936   LoadP(ip, FieldMemOperand(string, HeapObject::kMapOffset));
   2937   lbz(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
   2938 
   2939   andi(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
   2940   cmpi(ip, Operand(encoding_mask));
   2941   Check(eq, kUnexpectedStringType);
   2942 
   2943 // The index is assumed to be untagged coming in, tag it to compare with the
   2944 // string length without using a temp register, it is restored at the end of
   2945 // this function.
   2946 #if !V8_TARGET_ARCH_PPC64
   2947   Label index_tag_ok, index_tag_bad;
   2948   JumpIfNotSmiCandidate(index, r0, &index_tag_bad);
   2949 #endif
   2950   SmiTag(index, index);
   2951 #if !V8_TARGET_ARCH_PPC64
   2952   b(&index_tag_ok);
   2953   bind(&index_tag_bad);
   2954   Abort(kIndexIsTooLarge);
   2955   bind(&index_tag_ok);
   2956 #endif
   2957 
   2958   LoadP(ip, FieldMemOperand(string, String::kLengthOffset));
   2959   cmp(index, ip);
   2960   Check(lt, kIndexIsTooLarge);
   2961 
   2962   DCHECK(Smi::kZero == 0);
   2963   cmpi(index, Operand::Zero());
   2964   Check(ge, kIndexIsNegative);
   2965 
   2966   SmiUntag(index, index);
   2967 }
   2968 
   2969 
   2970 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
   2971                                           int num_double_arguments,
   2972                                           Register scratch) {
   2973   int frame_alignment = ActivationFrameAlignment();
   2974   int stack_passed_arguments =
   2975       CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
   2976   int stack_space = kNumRequiredStackFrameSlots;
   2977 
   2978   if (frame_alignment > kPointerSize) {
   2979     // Make stack end at alignment and make room for stack arguments
   2980     // -- preserving original value of sp.
   2981     mr(scratch, sp);
   2982     addi(sp, sp, Operand(-(stack_passed_arguments + 1) * kPointerSize));
   2983     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
   2984     ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
   2985     StoreP(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
   2986   } else {
   2987     // Make room for stack arguments
   2988     stack_space += stack_passed_arguments;
   2989   }
   2990 
   2991   // Allocate frame with required slots to make ABI work.
   2992   li(r0, Operand::Zero());
   2993   StorePU(r0, MemOperand(sp, -stack_space * kPointerSize));
   2994 }
   2995 
   2996 
   2997 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
   2998                                           Register scratch) {
   2999   PrepareCallCFunction(num_reg_arguments, 0, scratch);
   3000 }
   3001 
   3002 
   3003 void MacroAssembler::MovToFloatParameter(DoubleRegister src) { Move(d1, src); }
   3004 
   3005 
   3006 void MacroAssembler::MovToFloatResult(DoubleRegister src) { Move(d1, src); }
   3007 
   3008 
   3009 void MacroAssembler::MovToFloatParameters(DoubleRegister src1,
   3010                                           DoubleRegister src2) {
   3011   if (src2.is(d1)) {
   3012     DCHECK(!src1.is(d2));
   3013     Move(d2, src2);
   3014     Move(d1, src1);
   3015   } else {
   3016     Move(d1, src1);
   3017     Move(d2, src2);
   3018   }
   3019 }
   3020 
   3021 
   3022 void MacroAssembler::CallCFunction(ExternalReference function,
   3023                                    int num_reg_arguments,
   3024                                    int num_double_arguments) {
   3025   mov(ip, Operand(function));
   3026   CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments);
   3027 }
   3028 
   3029 
   3030 void MacroAssembler::CallCFunction(Register function, int num_reg_arguments,
   3031                                    int num_double_arguments) {
   3032   CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
   3033 }
   3034 
   3035 
   3036 void MacroAssembler::CallCFunction(ExternalReference function,
   3037                                    int num_arguments) {
   3038   CallCFunction(function, num_arguments, 0);
   3039 }
   3040 
   3041 
   3042 void MacroAssembler::CallCFunction(Register function, int num_arguments) {
   3043   CallCFunction(function, num_arguments, 0);
   3044 }
   3045 
   3046 
   3047 void MacroAssembler::CallCFunctionHelper(Register function,
   3048                                          int num_reg_arguments,
   3049                                          int num_double_arguments) {
   3050   DCHECK(has_frame());
   3051 
   3052   // Just call directly. The function called cannot cause a GC, or
   3053   // allow preemption, so the return address in the link register
   3054   // stays correct.
   3055   Register dest = function;
   3056   if (ABI_USES_FUNCTION_DESCRIPTORS) {
   3057     // AIX/PPC64BE Linux uses a function descriptor. When calling C code be
   3058     // aware of this descriptor and pick up values from it
   3059     LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(function, kPointerSize));
   3060     LoadP(ip, MemOperand(function, 0));
   3061     dest = ip;
   3062   } else if (ABI_CALL_VIA_IP) {
   3063     Move(ip, function);
   3064     dest = ip;
   3065   }
   3066 
   3067   Call(dest);
   3068 
   3069   // Remove frame bought in PrepareCallCFunction
   3070   int stack_passed_arguments =
   3071       CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
   3072   int stack_space = kNumRequiredStackFrameSlots + stack_passed_arguments;
   3073   if (ActivationFrameAlignment() > kPointerSize) {
   3074     LoadP(sp, MemOperand(sp, stack_space * kPointerSize));
   3075   } else {
   3076     addi(sp, sp, Operand(stack_space * kPointerSize));
   3077   }
   3078 }
   3079 
   3080 
   3081 void MacroAssembler::DecodeConstantPoolOffset(Register result,
   3082                                               Register location) {
   3083   Label overflow_access, done;
   3084   DCHECK(!AreAliased(result, location, r0));
   3085 
   3086   // Determine constant pool access type
   3087   // Caller has already placed the instruction word at location in result.
   3088   ExtractBitRange(r0, result, 31, 26);
   3089   cmpi(r0, Operand(ADDIS >> 26));
   3090   beq(&overflow_access);
   3091 
   3092   // Regular constant pool access
   3093   // extract the load offset
   3094   andi(result, result, Operand(kImm16Mask));
   3095   b(&done);
   3096 
   3097   bind(&overflow_access);
   3098   // Overflow constant pool access
   3099   // shift addis immediate
   3100   slwi(r0, result, Operand(16));
   3101   // sign-extend and add the load offset
   3102   lwz(result, MemOperand(location, kInstrSize));
   3103   extsh(result, result);
   3104   add(result, r0, result);
   3105 
   3106   bind(&done);
   3107 }
   3108 
   3109 
   3110 void MacroAssembler::CheckPageFlag(
   3111     Register object,
   3112     Register scratch,  // scratch may be same register as object
   3113     int mask, Condition cc, Label* condition_met) {
   3114   DCHECK(cc == ne || cc == eq);
   3115   ClearRightImm(scratch, object, Operand(kPageSizeBits));
   3116   LoadP(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
   3117 
   3118   And(r0, scratch, Operand(mask), SetRC);
   3119 
   3120   if (cc == ne) {
   3121     bne(condition_met, cr0);
   3122   }
   3123   if (cc == eq) {
   3124     beq(condition_met, cr0);
   3125   }
   3126 }
   3127 
   3128 
   3129 void MacroAssembler::JumpIfBlack(Register object, Register scratch0,
   3130                                  Register scratch1, Label* on_black) {
   3131   HasColor(object, scratch0, scratch1, on_black, 1, 1);  // kBlackBitPattern.
   3132   DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
   3133 }
   3134 
   3135 
   3136 void MacroAssembler::HasColor(Register object, Register bitmap_scratch,
   3137                               Register mask_scratch, Label* has_color,
   3138                               int first_bit, int second_bit) {
   3139   DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, no_reg));
   3140 
   3141   GetMarkBits(object, bitmap_scratch, mask_scratch);
   3142 
   3143   Label other_color, word_boundary;
   3144   lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3145   // Test the first bit
   3146   and_(r0, ip, mask_scratch, SetRC);
   3147   b(first_bit == 1 ? eq : ne, &other_color, cr0);
   3148   // Shift left 1
   3149   // May need to load the next cell
   3150   slwi(mask_scratch, mask_scratch, Operand(1), SetRC);
   3151   beq(&word_boundary, cr0);
   3152   // Test the second bit
   3153   and_(r0, ip, mask_scratch, SetRC);
   3154   b(second_bit == 1 ? ne : eq, has_color, cr0);
   3155   b(&other_color);
   3156 
   3157   bind(&word_boundary);
   3158   lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kIntSize));
   3159   andi(r0, ip, Operand(1));
   3160   b(second_bit == 1 ? ne : eq, has_color, cr0);
   3161   bind(&other_color);
   3162 }
   3163 
   3164 
   3165 void MacroAssembler::GetMarkBits(Register addr_reg, Register bitmap_reg,
   3166                                  Register mask_reg) {
   3167   DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
   3168   DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0);
   3169   lis(r0, Operand((~Page::kPageAlignmentMask >> 16)));
   3170   and_(bitmap_reg, addr_reg, r0);
   3171   const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
   3172   ExtractBitRange(mask_reg, addr_reg, kLowBits - 1, kPointerSizeLog2);
   3173   ExtractBitRange(ip, addr_reg, kPageSizeBits - 1, kLowBits);
   3174   ShiftLeftImm(ip, ip, Operand(Bitmap::kBytesPerCellLog2));
   3175   add(bitmap_reg, bitmap_reg, ip);
   3176   li(ip, Operand(1));
   3177   slw(mask_reg, ip, mask_reg);
   3178 }
   3179 
   3180 
   3181 void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
   3182                                  Register mask_scratch, Register load_scratch,
   3183                                  Label* value_is_white) {
   3184   DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ip));
   3185   GetMarkBits(value, bitmap_scratch, mask_scratch);
   3186 
   3187   // If the value is black or grey we don't need to do anything.
   3188   DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
   3189   DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
   3190   DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
   3191   DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
   3192 
   3193   // Since both black and grey have a 1 in the first position and white does
   3194   // not have a 1 there we only need to check one bit.
   3195   lwz(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3196   and_(r0, mask_scratch, load_scratch, SetRC);
   3197   beq(value_is_white, cr0);
   3198 }
   3199 
   3200 
   3201 // Saturate a value into 8-bit unsigned integer
   3202 //   if input_value < 0, output_value is 0
   3203 //   if input_value > 255, output_value is 255
   3204 //   otherwise output_value is the input_value
   3205 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
   3206   int satval = (1 << 8) - 1;
   3207 
   3208   if (CpuFeatures::IsSupported(ISELECT)) {
   3209     // set to 0 if negative
   3210     cmpi(input_reg, Operand::Zero());
   3211     isel(lt, output_reg, r0, input_reg);
   3212 
   3213     // set to satval if > satval
   3214     li(r0, Operand(satval));
   3215     cmpi(output_reg, Operand(satval));
   3216     isel(lt, output_reg, output_reg, r0);
   3217   } else {
   3218     Label done, negative_label, overflow_label;
   3219     cmpi(input_reg, Operand::Zero());
   3220     blt(&negative_label);
   3221 
   3222     cmpi(input_reg, Operand(satval));
   3223     bgt(&overflow_label);
   3224     if (!output_reg.is(input_reg)) {
   3225       mr(output_reg, input_reg);
   3226     }
   3227     b(&done);
   3228 
   3229     bind(&negative_label);
   3230     li(output_reg, Operand::Zero());  // set to 0 if negative
   3231     b(&done);
   3232 
   3233     bind(&overflow_label);  // set to satval if > satval
   3234     li(output_reg, Operand(satval));
   3235 
   3236     bind(&done);
   3237   }
   3238 }
   3239 
   3240 
   3241 void MacroAssembler::SetRoundingMode(FPRoundingMode RN) { mtfsfi(7, RN); }
   3242 
   3243 
   3244 void MacroAssembler::ResetRoundingMode() {
   3245   mtfsfi(7, kRoundToNearest);  // reset (default is kRoundToNearest)
   3246 }
   3247 
   3248 
   3249 void MacroAssembler::ClampDoubleToUint8(Register result_reg,
   3250                                         DoubleRegister input_reg,
   3251                                         DoubleRegister double_scratch) {
   3252   Label above_zero;
   3253   Label done;
   3254   Label in_bounds;
   3255 
   3256   LoadDoubleLiteral(double_scratch, 0.0, result_reg);
   3257   fcmpu(input_reg, double_scratch);
   3258   bgt(&above_zero);
   3259 
   3260   // Double value is less than zero, NaN or Inf, return 0.
   3261   LoadIntLiteral(result_reg, 0);
   3262   b(&done);
   3263 
   3264   // Double value is >= 255, return 255.
   3265   bind(&above_zero);
   3266   LoadDoubleLiteral(double_scratch, 255.0, result_reg);
   3267   fcmpu(input_reg, double_scratch);
   3268   ble(&in_bounds);
   3269   LoadIntLiteral(result_reg, 255);
   3270   b(&done);
   3271 
   3272   // In 0-255 range, round and truncate.
   3273   bind(&in_bounds);
   3274 
   3275   // round to nearest (default rounding mode)
   3276   fctiw(double_scratch, input_reg);
   3277   MovDoubleLowToInt(result_reg, double_scratch);
   3278   bind(&done);
   3279 }
   3280 
   3281 
   3282 void MacroAssembler::LoadInstanceDescriptors(Register map,
   3283                                              Register descriptors) {
   3284   LoadP(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
   3285 }
   3286 
   3287 
   3288 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
   3289   lwz(dst, FieldMemOperand(map, Map::kBitField3Offset));
   3290   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
   3291 }
   3292 
   3293 
   3294 void MacroAssembler::EnumLength(Register dst, Register map) {
   3295   STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
   3296   lwz(dst, FieldMemOperand(map, Map::kBitField3Offset));
   3297   ExtractBitMask(dst, dst, Map::EnumLengthBits::kMask);
   3298   SmiTag(dst);
   3299 }
   3300 
   3301 
   3302 void MacroAssembler::LoadAccessor(Register dst, Register holder,
   3303                                   int accessor_index,
   3304                                   AccessorComponent accessor) {
   3305   LoadP(dst, FieldMemOperand(holder, HeapObject::kMapOffset));
   3306   LoadInstanceDescriptors(dst, dst);
   3307   LoadP(dst,
   3308         FieldMemOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
   3309   const int getterOffset = AccessorPair::kGetterOffset;
   3310   const int setterOffset = AccessorPair::kSetterOffset;
   3311   int offset = ((accessor == ACCESSOR_GETTER) ? getterOffset : setterOffset);
   3312   LoadP(dst, FieldMemOperand(dst, offset));
   3313 }
   3314 
   3315 
   3316 void MacroAssembler::CheckEnumCache(Label* call_runtime) {
   3317   Register null_value = r8;
   3318   Register empty_fixed_array_value = r9;
   3319   LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
   3320   Label next, start;
   3321   mr(r5, r3);
   3322 
   3323   // Check if the enum length field is properly initialized, indicating that
   3324   // there is an enum cache.
   3325   LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
   3326 
   3327   EnumLength(r6, r4);
   3328   CmpSmiLiteral(r6, Smi::FromInt(kInvalidEnumCacheSentinel), r0);
   3329   beq(call_runtime);
   3330 
   3331   LoadRoot(null_value, Heap::kNullValueRootIndex);
   3332   b(&start);
   3333 
   3334   bind(&next);
   3335   LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
   3336 
   3337   // For all objects but the receiver, check that the cache is empty.
   3338   EnumLength(r6, r4);
   3339   CmpSmiLiteral(r6, Smi::kZero, r0);
   3340   bne(call_runtime);
   3341 
   3342   bind(&start);
   3343 
   3344   // Check that there are no elements. Register r5 contains the current JS
   3345   // object we've reached through the prototype chain.
   3346   Label no_elements;
   3347   LoadP(r5, FieldMemOperand(r5, JSObject::kElementsOffset));
   3348   cmp(r5, empty_fixed_array_value);
   3349   beq(&no_elements);
   3350 
   3351   // Second chance, the object may be using the empty slow element dictionary.
   3352   CompareRoot(r5, Heap::kEmptySlowElementDictionaryRootIndex);
   3353   bne(call_runtime);
   3354 
   3355   bind(&no_elements);
   3356   LoadP(r5, FieldMemOperand(r4, Map::kPrototypeOffset));
   3357   cmp(r5, null_value);
   3358   bne(&next);
   3359 }
   3360 
   3361 
   3362 ////////////////////////////////////////////////////////////////////////////////
   3363 //
   3364 // New MacroAssembler Interfaces added for PPC
   3365 //
   3366 ////////////////////////////////////////////////////////////////////////////////
   3367 void MacroAssembler::LoadIntLiteral(Register dst, int value) {
   3368   mov(dst, Operand(value));
   3369 }
   3370 
   3371 
   3372 void MacroAssembler::LoadSmiLiteral(Register dst, Smi* smi) {
   3373   mov(dst, Operand(smi));
   3374 }
   3375 
   3376 
   3377 void MacroAssembler::LoadDoubleLiteral(DoubleRegister result, double value,
   3378                                        Register scratch) {
   3379   if (FLAG_enable_embedded_constant_pool && is_constant_pool_available() &&
   3380       !(scratch.is(r0) && ConstantPoolAccessIsInOverflow())) {
   3381     ConstantPoolEntry::Access access = ConstantPoolAddEntry(value);
   3382     if (access == ConstantPoolEntry::OVERFLOWED) {
   3383       addis(scratch, kConstantPoolRegister, Operand::Zero());
   3384       lfd(result, MemOperand(scratch, 0));
   3385     } else {
   3386       lfd(result, MemOperand(kConstantPoolRegister, 0));
   3387     }
   3388     return;
   3389   }
   3390 
   3391   // avoid gcc strict aliasing error using union cast
   3392   union {
   3393     double dval;
   3394 #if V8_TARGET_ARCH_PPC64
   3395     intptr_t ival;
   3396 #else
   3397     intptr_t ival[2];
   3398 #endif
   3399   } litVal;
   3400 
   3401   litVal.dval = value;
   3402 
   3403 #if V8_TARGET_ARCH_PPC64
   3404   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3405     mov(scratch, Operand(litVal.ival));
   3406     mtfprd(result, scratch);
   3407     return;
   3408   }
   3409 #endif
   3410 
   3411   addi(sp, sp, Operand(-kDoubleSize));
   3412 #if V8_TARGET_ARCH_PPC64
   3413   mov(scratch, Operand(litVal.ival));
   3414   std(scratch, MemOperand(sp));
   3415 #else
   3416   LoadIntLiteral(scratch, litVal.ival[0]);
   3417   stw(scratch, MemOperand(sp, 0));
   3418   LoadIntLiteral(scratch, litVal.ival[1]);
   3419   stw(scratch, MemOperand(sp, 4));
   3420 #endif
   3421   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3422   lfd(result, MemOperand(sp, 0));
   3423   addi(sp, sp, Operand(kDoubleSize));
   3424 }
   3425 
   3426 
   3427 void MacroAssembler::MovIntToDouble(DoubleRegister dst, Register src,
   3428                                     Register scratch) {
   3429 // sign-extend src to 64-bit
   3430 #if V8_TARGET_ARCH_PPC64
   3431   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3432     mtfprwa(dst, src);
   3433     return;
   3434   }
   3435 #endif
   3436 
   3437   DCHECK(!src.is(scratch));
   3438   subi(sp, sp, Operand(kDoubleSize));
   3439 #if V8_TARGET_ARCH_PPC64
   3440   extsw(scratch, src);
   3441   std(scratch, MemOperand(sp, 0));
   3442 #else
   3443   srawi(scratch, src, 31);
   3444   stw(scratch, MemOperand(sp, Register::kExponentOffset));
   3445   stw(src, MemOperand(sp, Register::kMantissaOffset));
   3446 #endif
   3447   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3448   lfd(dst, MemOperand(sp, 0));
   3449   addi(sp, sp, Operand(kDoubleSize));
   3450 }
   3451 
   3452 
   3453 void MacroAssembler::MovUnsignedIntToDouble(DoubleRegister dst, Register src,
   3454                                             Register scratch) {
   3455 // zero-extend src to 64-bit
   3456 #if V8_TARGET_ARCH_PPC64
   3457   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3458     mtfprwz(dst, src);
   3459     return;
   3460   }
   3461 #endif
   3462 
   3463   DCHECK(!src.is(scratch));
   3464   subi(sp, sp, Operand(kDoubleSize));
   3465 #if V8_TARGET_ARCH_PPC64
   3466   clrldi(scratch, src, Operand(32));
   3467   std(scratch, MemOperand(sp, 0));
   3468 #else
   3469   li(scratch, Operand::Zero());
   3470   stw(scratch, MemOperand(sp, Register::kExponentOffset));
   3471   stw(src, MemOperand(sp, Register::kMantissaOffset));
   3472 #endif
   3473   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3474   lfd(dst, MemOperand(sp, 0));
   3475   addi(sp, sp, Operand(kDoubleSize));
   3476 }
   3477 
   3478 
   3479 void MacroAssembler::MovInt64ToDouble(DoubleRegister dst,
   3480 #if !V8_TARGET_ARCH_PPC64
   3481                                       Register src_hi,
   3482 #endif
   3483                                       Register src) {
   3484 #if V8_TARGET_ARCH_PPC64
   3485   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3486     mtfprd(dst, src);
   3487     return;
   3488   }
   3489 #endif
   3490 
   3491   subi(sp, sp, Operand(kDoubleSize));
   3492 #if V8_TARGET_ARCH_PPC64
   3493   std(src, MemOperand(sp, 0));
   3494 #else
   3495   stw(src_hi, MemOperand(sp, Register::kExponentOffset));
   3496   stw(src, MemOperand(sp, Register::kMantissaOffset));
   3497 #endif
   3498   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3499   lfd(dst, MemOperand(sp, 0));
   3500   addi(sp, sp, Operand(kDoubleSize));
   3501 }
   3502 
   3503 
   3504 #if V8_TARGET_ARCH_PPC64
   3505 void MacroAssembler::MovInt64ComponentsToDouble(DoubleRegister dst,
   3506                                                 Register src_hi,
   3507                                                 Register src_lo,
   3508                                                 Register scratch) {
   3509   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3510     sldi(scratch, src_hi, Operand(32));
   3511     rldimi(scratch, src_lo, 0, 32);
   3512     mtfprd(dst, scratch);
   3513     return;
   3514   }
   3515 
   3516   subi(sp, sp, Operand(kDoubleSize));
   3517   stw(src_hi, MemOperand(sp, Register::kExponentOffset));
   3518   stw(src_lo, MemOperand(sp, Register::kMantissaOffset));
   3519   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3520   lfd(dst, MemOperand(sp));
   3521   addi(sp, sp, Operand(kDoubleSize));
   3522 }
   3523 #endif
   3524 
   3525 
   3526 void MacroAssembler::InsertDoubleLow(DoubleRegister dst, Register src,
   3527                                      Register scratch) {
   3528 #if V8_TARGET_ARCH_PPC64
   3529   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3530     mffprd(scratch, dst);
   3531     rldimi(scratch, src, 0, 32);
   3532     mtfprd(dst, scratch);
   3533     return;
   3534   }
   3535 #endif
   3536 
   3537   subi(sp, sp, Operand(kDoubleSize));
   3538   stfd(dst, MemOperand(sp));
   3539   stw(src, MemOperand(sp, Register::kMantissaOffset));
   3540   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3541   lfd(dst, MemOperand(sp));
   3542   addi(sp, sp, Operand(kDoubleSize));
   3543 }
   3544 
   3545 
   3546 void MacroAssembler::InsertDoubleHigh(DoubleRegister dst, Register src,
   3547                                       Register scratch) {
   3548 #if V8_TARGET_ARCH_PPC64
   3549   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3550     mffprd(scratch, dst);
   3551     rldimi(scratch, src, 32, 0);
   3552     mtfprd(dst, scratch);
   3553     return;
   3554   }
   3555 #endif
   3556 
   3557   subi(sp, sp, Operand(kDoubleSize));
   3558   stfd(dst, MemOperand(sp));
   3559   stw(src, MemOperand(sp, Register::kExponentOffset));
   3560   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3561   lfd(dst, MemOperand(sp));
   3562   addi(sp, sp, Operand(kDoubleSize));
   3563 }
   3564 
   3565 
   3566 void MacroAssembler::MovDoubleLowToInt(Register dst, DoubleRegister src) {
   3567 #if V8_TARGET_ARCH_PPC64
   3568   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3569     mffprwz(dst, src);
   3570     return;
   3571   }
   3572 #endif
   3573 
   3574   subi(sp, sp, Operand(kDoubleSize));
   3575   stfd(src, MemOperand(sp));
   3576   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3577   lwz(dst, MemOperand(sp, Register::kMantissaOffset));
   3578   addi(sp, sp, Operand(kDoubleSize));
   3579 }
   3580 
   3581 
   3582 void MacroAssembler::MovDoubleHighToInt(Register dst, DoubleRegister src) {
   3583 #if V8_TARGET_ARCH_PPC64
   3584   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3585     mffprd(dst, src);
   3586     srdi(dst, dst, Operand(32));
   3587     return;
   3588   }
   3589 #endif
   3590 
   3591   subi(sp, sp, Operand(kDoubleSize));
   3592   stfd(src, MemOperand(sp));
   3593   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3594   lwz(dst, MemOperand(sp, Register::kExponentOffset));
   3595   addi(sp, sp, Operand(kDoubleSize));
   3596 }
   3597 
   3598 
   3599 void MacroAssembler::MovDoubleToInt64(
   3600 #if !V8_TARGET_ARCH_PPC64
   3601     Register dst_hi,
   3602 #endif
   3603     Register dst, DoubleRegister src) {
   3604 #if V8_TARGET_ARCH_PPC64
   3605   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
   3606     mffprd(dst, src);
   3607     return;
   3608   }
   3609 #endif
   3610 
   3611   subi(sp, sp, Operand(kDoubleSize));
   3612   stfd(src, MemOperand(sp));
   3613   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3614 #if V8_TARGET_ARCH_PPC64
   3615   ld(dst, MemOperand(sp, 0));
   3616 #else
   3617   lwz(dst_hi, MemOperand(sp, Register::kExponentOffset));
   3618   lwz(dst, MemOperand(sp, Register::kMantissaOffset));
   3619 #endif
   3620   addi(sp, sp, Operand(kDoubleSize));
   3621 }
   3622 
   3623 
   3624 void MacroAssembler::MovIntToFloat(DoubleRegister dst, Register src) {
   3625   subi(sp, sp, Operand(kFloatSize));
   3626   stw(src, MemOperand(sp, 0));
   3627   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3628   lfs(dst, MemOperand(sp, 0));
   3629   addi(sp, sp, Operand(kFloatSize));
   3630 }
   3631 
   3632 
   3633 void MacroAssembler::MovFloatToInt(Register dst, DoubleRegister src) {
   3634   subi(sp, sp, Operand(kFloatSize));
   3635   stfs(src, MemOperand(sp, 0));
   3636   nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
   3637   lwz(dst, MemOperand(sp, 0));
   3638   addi(sp, sp, Operand(kFloatSize));
   3639 }
   3640 
   3641 
   3642 void MacroAssembler::Add(Register dst, Register src, intptr_t value,
   3643                          Register scratch) {
   3644   if (is_int16(value)) {
   3645     addi(dst, src, Operand(value));
   3646   } else {
   3647     mov(scratch, Operand(value));
   3648     add(dst, src, scratch);
   3649   }
   3650 }
   3651 
   3652 
   3653 void MacroAssembler::Cmpi(Register src1, const Operand& src2, Register scratch,
   3654                           CRegister cr) {
   3655   intptr_t value = src2.immediate();
   3656   if (is_int16(value)) {
   3657     cmpi(src1, src2, cr);
   3658   } else {
   3659     mov(scratch, src2);
   3660     cmp(src1, scratch, cr);
   3661   }
   3662 }
   3663 
   3664 
   3665 void MacroAssembler::Cmpli(Register src1, const Operand& src2, Register scratch,
   3666                            CRegister cr) {
   3667   intptr_t value = src2.immediate();
   3668   if (is_uint16(value)) {
   3669     cmpli(src1, src2, cr);
   3670   } else {
   3671     mov(scratch, src2);
   3672     cmpl(src1, scratch, cr);
   3673   }
   3674 }
   3675 
   3676 
   3677 void MacroAssembler::Cmpwi(Register src1, const Operand& src2, Register scratch,
   3678                            CRegister cr) {
   3679   intptr_t value = src2.immediate();
   3680   if (is_int16(value)) {
   3681     cmpwi(src1, src2, cr);
   3682   } else {
   3683     mov(scratch, src2);
   3684     cmpw(src1, scratch, cr);
   3685   }
   3686 }
   3687 
   3688 
   3689 void MacroAssembler::Cmplwi(Register src1, const Operand& src2,
   3690                             Register scratch, CRegister cr) {
   3691   intptr_t value = src2.immediate();
   3692   if (is_uint16(value)) {
   3693     cmplwi(src1, src2, cr);
   3694   } else {
   3695     mov(scratch, src2);
   3696     cmplw(src1, scratch, cr);
   3697   }
   3698 }
   3699 
   3700 
   3701 void MacroAssembler::And(Register ra, Register rs, const Operand& rb,
   3702                          RCBit rc) {
   3703   if (rb.is_reg()) {
   3704     and_(ra, rs, rb.rm(), rc);
   3705   } else {
   3706     if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == SetRC) {
   3707       andi(ra, rs, rb);
   3708     } else {
   3709       // mov handles the relocation.
   3710       DCHECK(!rs.is(r0));
   3711       mov(r0, rb);
   3712       and_(ra, rs, r0, rc);
   3713     }
   3714   }
   3715 }
   3716 
   3717 
   3718 void MacroAssembler::Or(Register ra, Register rs, const Operand& rb, RCBit rc) {
   3719   if (rb.is_reg()) {
   3720     orx(ra, rs, rb.rm(), rc);
   3721   } else {
   3722     if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == LeaveRC) {
   3723       ori(ra, rs, rb);
   3724     } else {
   3725       // mov handles the relocation.
   3726       DCHECK(!rs.is(r0));
   3727       mov(r0, rb);
   3728       orx(ra, rs, r0, rc);
   3729     }
   3730   }
   3731 }
   3732 
   3733 
   3734 void MacroAssembler::Xor(Register ra, Register rs, const Operand& rb,
   3735                          RCBit rc) {
   3736   if (rb.is_reg()) {
   3737     xor_(ra, rs, rb.rm(), rc);
   3738   } else {
   3739     if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == LeaveRC) {
   3740       xori(ra, rs, rb);
   3741     } else {
   3742       // mov handles the relocation.
   3743       DCHECK(!rs.is(r0));
   3744       mov(r0, rb);
   3745       xor_(ra, rs, r0, rc);
   3746     }
   3747   }
   3748 }
   3749 
   3750 
   3751 void MacroAssembler::CmpSmiLiteral(Register src1, Smi* smi, Register scratch,
   3752                                    CRegister cr) {
   3753 #if V8_TARGET_ARCH_PPC64
   3754   LoadSmiLiteral(scratch, smi);
   3755   cmp(src1, scratch, cr);
   3756 #else
   3757   Cmpi(src1, Operand(smi), scratch, cr);
   3758 #endif
   3759 }
   3760 
   3761 
   3762 void MacroAssembler::CmplSmiLiteral(Register src1, Smi* smi, Register scratch,
   3763                                     CRegister cr) {
   3764 #if V8_TARGET_ARCH_PPC64
   3765   LoadSmiLiteral(scratch, smi);
   3766   cmpl(src1, scratch, cr);
   3767 #else
   3768   Cmpli(src1, Operand(smi), scratch, cr);
   3769 #endif
   3770 }
   3771 
   3772 
   3773 void MacroAssembler::AddSmiLiteral(Register dst, Register src, Smi* smi,
   3774                                    Register scratch) {
   3775 #if V8_TARGET_ARCH_PPC64
   3776   LoadSmiLiteral(scratch, smi);
   3777   add(dst, src, scratch);
   3778 #else
   3779   Add(dst, src, reinterpret_cast<intptr_t>(smi), scratch);
   3780 #endif
   3781 }
   3782 
   3783 
   3784 void MacroAssembler::SubSmiLiteral(Register dst, Register src, Smi* smi,
   3785                                    Register scratch) {
   3786 #if V8_TARGET_ARCH_PPC64
   3787   LoadSmiLiteral(scratch, smi);
   3788   sub(dst, src, scratch);
   3789 #else
   3790   Add(dst, src, -(reinterpret_cast<intptr_t>(smi)), scratch);
   3791 #endif
   3792 }
   3793 
   3794 
   3795 void MacroAssembler::AndSmiLiteral(Register dst, Register src, Smi* smi,
   3796                                    Register scratch, RCBit rc) {
   3797 #if V8_TARGET_ARCH_PPC64
   3798   LoadSmiLiteral(scratch, smi);
   3799   and_(dst, src, scratch, rc);
   3800 #else
   3801   And(dst, src, Operand(smi), rc);
   3802 #endif
   3803 }
   3804 
   3805 
   3806 // Load a "pointer" sized value from the memory location
   3807 void MacroAssembler::LoadP(Register dst, const MemOperand& mem,
   3808                            Register scratch) {
   3809   int offset = mem.offset();
   3810 
   3811   if (!is_int16(offset)) {
   3812     /* cannot use d-form */
   3813     DCHECK(!scratch.is(no_reg));
   3814     mov(scratch, Operand(offset));
   3815     LoadPX(dst, MemOperand(mem.ra(), scratch));
   3816   } else {
   3817 #if V8_TARGET_ARCH_PPC64
   3818     int misaligned = (offset & 3);
   3819     if (misaligned) {
   3820       // adjust base to conform to offset alignment requirements
   3821       // Todo: enhance to use scratch if dst is unsuitable
   3822       DCHECK(!dst.is(r0));
   3823       addi(dst, mem.ra(), Operand((offset & 3) - 4));
   3824       ld(dst, MemOperand(dst, (offset & ~3) + 4));
   3825     } else {
   3826       ld(dst, mem);
   3827     }
   3828 #else
   3829     lwz(dst, mem);
   3830 #endif
   3831   }
   3832 }
   3833 
   3834 void MacroAssembler::LoadPU(Register dst, const MemOperand& mem,
   3835                             Register scratch) {
   3836   int offset = mem.offset();
   3837 
   3838   if (!is_int16(offset)) {
   3839     /* cannot use d-form */
   3840     DCHECK(!scratch.is(no_reg));
   3841     mov(scratch, Operand(offset));
   3842     LoadPUX(dst, MemOperand(mem.ra(), scratch));
   3843   } else {
   3844 #if V8_TARGET_ARCH_PPC64
   3845     ldu(dst, mem);
   3846 #else
   3847     lwzu(dst, mem);
   3848 #endif
   3849   }
   3850 }
   3851 
   3852 // Store a "pointer" sized value to the memory location
   3853 void MacroAssembler::StoreP(Register src, const MemOperand& mem,
   3854                             Register scratch) {
   3855   int offset = mem.offset();
   3856 
   3857   if (!is_int16(offset)) {
   3858     /* cannot use d-form */
   3859     DCHECK(!scratch.is(no_reg));
   3860     mov(scratch, Operand(offset));
   3861     StorePX(src, MemOperand(mem.ra(), scratch));
   3862   } else {
   3863 #if V8_TARGET_ARCH_PPC64
   3864     int misaligned = (offset & 3);
   3865     if (misaligned) {
   3866       // adjust base to conform to offset alignment requirements
   3867       // a suitable scratch is required here
   3868       DCHECK(!scratch.is(no_reg));
   3869       if (scratch.is(r0)) {
   3870         LoadIntLiteral(scratch, offset);
   3871         stdx(src, MemOperand(mem.ra(), scratch));
   3872       } else {
   3873         addi(scratch, mem.ra(), Operand((offset & 3) - 4));
   3874         std(src, MemOperand(scratch, (offset & ~3) + 4));
   3875       }
   3876     } else {
   3877       std(src, mem);
   3878     }
   3879 #else
   3880     stw(src, mem);
   3881 #endif
   3882   }
   3883 }
   3884 
   3885 void MacroAssembler::StorePU(Register src, const MemOperand& mem,
   3886                              Register scratch) {
   3887   int offset = mem.offset();
   3888 
   3889   if (!is_int16(offset)) {
   3890     /* cannot use d-form */
   3891     DCHECK(!scratch.is(no_reg));
   3892     mov(scratch, Operand(offset));
   3893     StorePUX(src, MemOperand(mem.ra(), scratch));
   3894   } else {
   3895 #if V8_TARGET_ARCH_PPC64
   3896     stdu(src, mem);
   3897 #else
   3898     stwu(src, mem);
   3899 #endif
   3900   }
   3901 }
   3902 
   3903 void MacroAssembler::LoadWordArith(Register dst, const MemOperand& mem,
   3904                                    Register scratch) {
   3905   int offset = mem.offset();
   3906 
   3907   if (!is_int16(offset)) {
   3908     DCHECK(!scratch.is(no_reg));
   3909     mov(scratch, Operand(offset));
   3910     lwax(dst, MemOperand(mem.ra(), scratch));
   3911   } else {
   3912 #if V8_TARGET_ARCH_PPC64
   3913     int misaligned = (offset & 3);
   3914     if (misaligned) {
   3915       // adjust base to conform to offset alignment requirements
   3916       // Todo: enhance to use scratch if dst is unsuitable
   3917       DCHECK(!dst.is(r0));
   3918       addi(dst, mem.ra(), Operand((offset & 3) - 4));
   3919       lwa(dst, MemOperand(dst, (offset & ~3) + 4));
   3920     } else {
   3921       lwa(dst, mem);
   3922     }
   3923 #else
   3924     lwz(dst, mem);
   3925 #endif
   3926   }
   3927 }
   3928 
   3929 
   3930 // Variable length depending on whether offset fits into immediate field
   3931 // MemOperand currently only supports d-form
   3932 void MacroAssembler::LoadWord(Register dst, const MemOperand& mem,
   3933                               Register scratch) {
   3934   Register base = mem.ra();
   3935   int offset = mem.offset();
   3936 
   3937   if (!is_int16(offset)) {
   3938     LoadIntLiteral(scratch, offset);
   3939     lwzx(dst, MemOperand(base, scratch));
   3940   } else {
   3941     lwz(dst, mem);
   3942   }
   3943 }
   3944 
   3945 
   3946 // Variable length depending on whether offset fits into immediate field
   3947 // MemOperand current only supports d-form
   3948 void MacroAssembler::StoreWord(Register src, const MemOperand& mem,
   3949                                Register scratch) {
   3950   Register base = mem.ra();
   3951   int offset = mem.offset();
   3952 
   3953   if (!is_int16(offset)) {
   3954     LoadIntLiteral(scratch, offset);
   3955     stwx(src, MemOperand(base, scratch));
   3956   } else {
   3957     stw(src, mem);
   3958   }
   3959 }
   3960 
   3961 
   3962 void MacroAssembler::LoadHalfWordArith(Register dst, const MemOperand& mem,
   3963                                        Register scratch) {
   3964   int offset = mem.offset();
   3965 
   3966   if (!is_int16(offset)) {
   3967     DCHECK(!scratch.is(no_reg));
   3968     mov(scratch, Operand(offset));
   3969     lhax(dst, MemOperand(mem.ra(), scratch));
   3970   } else {
   3971     lha(dst, mem);
   3972   }
   3973 }
   3974 
   3975 
   3976 // Variable length depending on whether offset fits into immediate field
   3977 // MemOperand currently only supports d-form
   3978 void MacroAssembler::LoadHalfWord(Register dst, const MemOperand& mem,
   3979                                   Register scratch) {
   3980   Register base = mem.ra();
   3981   int offset = mem.offset();
   3982 
   3983   if (!is_int16(offset)) {
   3984     LoadIntLiteral(scratch, offset);
   3985     lhzx(dst, MemOperand(base, scratch));
   3986   } else {
   3987     lhz(dst, mem);
   3988   }
   3989 }
   3990 
   3991 
   3992 // Variable length depending on whether offset fits into immediate field
   3993 // MemOperand current only supports d-form
   3994 void MacroAssembler::StoreHalfWord(Register src, const MemOperand& mem,
   3995                                    Register scratch) {
   3996   Register base = mem.ra();
   3997   int offset = mem.offset();
   3998 
   3999   if (!is_int16(offset)) {
   4000     LoadIntLiteral(scratch, offset);
   4001     sthx(src, MemOperand(base, scratch));
   4002   } else {
   4003     sth(src, mem);
   4004   }
   4005 }
   4006 
   4007 
   4008 // Variable length depending on whether offset fits into immediate field
   4009 // MemOperand currently only supports d-form
   4010 void MacroAssembler::LoadByte(Register dst, const MemOperand& mem,
   4011                               Register scratch) {
   4012   Register base = mem.ra();
   4013   int offset = mem.offset();
   4014 
   4015   if (!is_int16(offset)) {
   4016     LoadIntLiteral(scratch, offset);
   4017     lbzx(dst, MemOperand(base, scratch));
   4018   } else {
   4019     lbz(dst, mem);
   4020   }
   4021 }
   4022 
   4023 
   4024 // Variable length depending on whether offset fits into immediate field
   4025 // MemOperand current only supports d-form
   4026 void MacroAssembler::StoreByte(Register src, const MemOperand& mem,
   4027                                Register scratch) {
   4028   Register base = mem.ra();
   4029   int offset = mem.offset();
   4030 
   4031   if (!is_int16(offset)) {
   4032     LoadIntLiteral(scratch, offset);
   4033     stbx(src, MemOperand(base, scratch));
   4034   } else {
   4035     stb(src, mem);
   4036   }
   4037 }
   4038 
   4039 
   4040 void MacroAssembler::LoadRepresentation(Register dst, const MemOperand& mem,
   4041                                         Representation r, Register scratch) {
   4042   DCHECK(!r.IsDouble());
   4043   if (r.IsInteger8()) {
   4044     LoadByte(dst, mem, scratch);
   4045     extsb(dst, dst);
   4046   } else if (r.IsUInteger8()) {
   4047     LoadByte(dst, mem, scratch);
   4048   } else if (r.IsInteger16()) {
   4049     LoadHalfWordArith(dst, mem, scratch);
   4050   } else if (r.IsUInteger16()) {
   4051     LoadHalfWord(dst, mem, scratch);
   4052 #if V8_TARGET_ARCH_PPC64
   4053   } else if (r.IsInteger32()) {
   4054     LoadWordArith(dst, mem, scratch);
   4055 #endif
   4056   } else {
   4057     LoadP(dst, mem, scratch);
   4058   }
   4059 }
   4060 
   4061 
   4062 void MacroAssembler::StoreRepresentation(Register src, const MemOperand& mem,
   4063                                          Representation r, Register scratch) {
   4064   DCHECK(!r.IsDouble());
   4065   if (r.IsInteger8() || r.IsUInteger8()) {
   4066     StoreByte(src, mem, scratch);
   4067   } else if (r.IsInteger16() || r.IsUInteger16()) {
   4068     StoreHalfWord(src, mem, scratch);
   4069 #if V8_TARGET_ARCH_PPC64
   4070   } else if (r.IsInteger32()) {
   4071     StoreWord(src, mem, scratch);
   4072 #endif
   4073   } else {
   4074     if (r.IsHeapObject()) {
   4075       AssertNotSmi(src);
   4076     } else if (r.IsSmi()) {
   4077       AssertSmi(src);
   4078     }
   4079     StoreP(src, mem, scratch);
   4080   }
   4081 }
   4082 
   4083 
   4084 void MacroAssembler::LoadDouble(DoubleRegister dst, const MemOperand& mem,
   4085                                 Register scratch) {
   4086   Register base = mem.ra();
   4087   int offset = mem.offset();
   4088 
   4089   if (!is_int16(offset)) {
   4090     mov(scratch, Operand(offset));
   4091     lfdx(dst, MemOperand(base, scratch));
   4092   } else {
   4093     lfd(dst, mem);
   4094   }
   4095 }
   4096 
   4097 void MacroAssembler::LoadDoubleU(DoubleRegister dst, const MemOperand& mem,
   4098                                 Register scratch) {
   4099   Register base = mem.ra();
   4100   int offset = mem.offset();
   4101 
   4102   if (!is_int16(offset)) {
   4103     mov(scratch, Operand(offset));
   4104     lfdux(dst, MemOperand(base, scratch));
   4105   } else {
   4106     lfdu(dst, mem);
   4107   }
   4108 }
   4109 
   4110 void MacroAssembler::LoadSingle(DoubleRegister dst, const MemOperand& mem,
   4111                                 Register scratch) {
   4112   Register base = mem.ra();
   4113   int offset = mem.offset();
   4114 
   4115   if (!is_int16(offset)) {
   4116     mov(scratch, Operand(offset));
   4117     lfsx(dst, MemOperand(base, scratch));
   4118   } else {
   4119     lfs(dst, mem);
   4120   }
   4121 }
   4122 
   4123 void MacroAssembler::LoadSingleU(DoubleRegister dst, const MemOperand& mem,
   4124                                 Register scratch) {
   4125   Register base = mem.ra();
   4126   int offset = mem.offset();
   4127 
   4128   if (!is_int16(offset)) {
   4129     mov(scratch, Operand(offset));
   4130     lfsux(dst, MemOperand(base, scratch));
   4131   } else {
   4132     lfsu(dst, mem);
   4133   }
   4134 }
   4135 
   4136 void MacroAssembler::StoreDouble(DoubleRegister src, const MemOperand& mem,
   4137                                  Register scratch) {
   4138   Register base = mem.ra();
   4139   int offset = mem.offset();
   4140 
   4141   if (!is_int16(offset)) {
   4142     mov(scratch, Operand(offset));
   4143     stfdx(src, MemOperand(base, scratch));
   4144   } else {
   4145     stfd(src, mem);
   4146   }
   4147 }
   4148 
   4149 void MacroAssembler::StoreDoubleU(DoubleRegister src, const MemOperand& mem,
   4150                                  Register scratch) {
   4151   Register base = mem.ra();
   4152   int offset = mem.offset();
   4153 
   4154   if (!is_int16(offset)) {
   4155     mov(scratch, Operand(offset));
   4156     stfdux(src, MemOperand(base, scratch));
   4157   } else {
   4158     stfdu(src, mem);
   4159   }
   4160 }
   4161 
   4162 void MacroAssembler::StoreSingle(DoubleRegister src, const MemOperand& mem,
   4163                                  Register scratch) {
   4164   Register base = mem.ra();
   4165   int offset = mem.offset();
   4166 
   4167   if (!is_int16(offset)) {
   4168     mov(scratch, Operand(offset));
   4169     stfsx(src, MemOperand(base, scratch));
   4170   } else {
   4171     stfs(src, mem);
   4172   }
   4173 }
   4174 
   4175 void MacroAssembler::StoreSingleU(DoubleRegister src, const MemOperand& mem,
   4176                                  Register scratch) {
   4177   Register base = mem.ra();
   4178   int offset = mem.offset();
   4179 
   4180   if (!is_int16(offset)) {
   4181     mov(scratch, Operand(offset));
   4182     stfsux(src, MemOperand(base, scratch));
   4183   } else {
   4184     stfsu(src, mem);
   4185   }
   4186 }
   4187 
   4188 void MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg,
   4189                                                      Register scratch_reg,
   4190                                                      Register scratch2_reg,
   4191                                                      Label* no_memento_found) {
   4192   Label map_check;
   4193   Label top_check;
   4194   ExternalReference new_space_allocation_top_adr =
   4195       ExternalReference::new_space_allocation_top_address(isolate());
   4196   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   4197   const int kMementoLastWordOffset =
   4198       kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
   4199   Register mask = scratch2_reg;
   4200 
   4201   DCHECK(!AreAliased(receiver_reg, scratch_reg, mask));
   4202 
   4203   // Bail out if the object is not in new space.
   4204   JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
   4205 
   4206   DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0);
   4207   lis(mask, Operand((~Page::kPageAlignmentMask >> 16)));
   4208   addi(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
   4209 
   4210   // If the object is in new space, we need to check whether it is on the same
   4211   // page as the current top.
   4212   mov(ip, Operand(new_space_allocation_top_adr));
   4213   LoadP(ip, MemOperand(ip));
   4214   Xor(r0, scratch_reg, Operand(ip));
   4215   and_(r0, r0, mask, SetRC);
   4216   beq(&top_check, cr0);
   4217   // The object is on a different page than allocation top. Bail out if the
   4218   // object sits on the page boundary as no memento can follow and we cannot
   4219   // touch the memory following it.
   4220   xor_(r0, scratch_reg, receiver_reg);
   4221   and_(r0, r0, mask, SetRC);
   4222   bne(no_memento_found, cr0);
   4223   // Continue with the actual map check.
   4224   b(&map_check);
   4225   // If top is on the same page as the current object, we need to check whether
   4226   // we are below top.
   4227   bind(&top_check);
   4228   cmp(scratch_reg, ip);
   4229   bge(no_memento_found);
   4230   // Memento map check.
   4231   bind(&map_check);
   4232   LoadP(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
   4233   Cmpi(scratch_reg, Operand(isolate()->factory()->allocation_memento_map()),
   4234        r0);
   4235 }
   4236 
   4237 Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
   4238                                    Register reg4, Register reg5,
   4239                                    Register reg6) {
   4240   RegList regs = 0;
   4241   if (reg1.is_valid()) regs |= reg1.bit();
   4242   if (reg2.is_valid()) regs |= reg2.bit();
   4243   if (reg3.is_valid()) regs |= reg3.bit();
   4244   if (reg4.is_valid()) regs |= reg4.bit();
   4245   if (reg5.is_valid()) regs |= reg5.bit();
   4246   if (reg6.is_valid()) regs |= reg6.bit();
   4247 
   4248   const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   4249   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
   4250     int code = config->GetAllocatableGeneralCode(i);
   4251     Register candidate = Register::from_code(code);
   4252     if (regs & candidate.bit()) continue;
   4253     return candidate;
   4254   }
   4255   UNREACHABLE();
   4256   return no_reg;
   4257 }
   4258 
   4259 #ifdef DEBUG
   4260 bool AreAliased(Register reg1, Register reg2, Register reg3, Register reg4,
   4261                 Register reg5, Register reg6, Register reg7, Register reg8,
   4262                 Register reg9, Register reg10) {
   4263   int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() + reg3.is_valid() +
   4264                         reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
   4265                         reg7.is_valid() + reg8.is_valid() + reg9.is_valid() +
   4266                         reg10.is_valid();
   4267 
   4268   RegList regs = 0;
   4269   if (reg1.is_valid()) regs |= reg1.bit();
   4270   if (reg2.is_valid()) regs |= reg2.bit();
   4271   if (reg3.is_valid()) regs |= reg3.bit();
   4272   if (reg4.is_valid()) regs |= reg4.bit();
   4273   if (reg5.is_valid()) regs |= reg5.bit();
   4274   if (reg6.is_valid()) regs |= reg6.bit();
   4275   if (reg7.is_valid()) regs |= reg7.bit();
   4276   if (reg8.is_valid()) regs |= reg8.bit();
   4277   if (reg9.is_valid()) regs |= reg9.bit();
   4278   if (reg10.is_valid()) regs |= reg10.bit();
   4279   int n_of_non_aliasing_regs = NumRegs(regs);
   4280 
   4281   return n_of_valid_regs != n_of_non_aliasing_regs;
   4282 }
   4283 #endif
   4284 
   4285 
   4286 CodePatcher::CodePatcher(Isolate* isolate, byte* address, int instructions,
   4287                          FlushICache flush_cache)
   4288     : address_(address),
   4289       size_(instructions * Assembler::kInstrSize),
   4290       masm_(isolate, address, size_ + Assembler::kGap, CodeObjectRequired::kNo),
   4291       flush_cache_(flush_cache) {
   4292   // Create a new macro assembler pointing to the address of the code to patch.
   4293   // The size is adjusted with kGap on order for the assembler to generate size
   4294   // bytes of instructions without failing with buffer size constraints.
   4295   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   4296 }
   4297 
   4298 
   4299 CodePatcher::~CodePatcher() {
   4300   // Indicate that code has changed.
   4301   if (flush_cache_ == FLUSH) {
   4302     Assembler::FlushICache(masm_.isolate(), address_, size_);
   4303   }
   4304 
   4305   // Check that the code was patched as expected.
   4306   DCHECK(masm_.pc_ == address_ + size_);
   4307   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   4308 }
   4309 
   4310 
   4311 void CodePatcher::Emit(Instr instr) { masm()->emit(instr); }
   4312 
   4313 
   4314 void CodePatcher::EmitCondition(Condition cond) {
   4315   Instr instr = Assembler::instr_at(masm_.pc_);
   4316   switch (cond) {
   4317     case eq:
   4318       instr = (instr & ~kCondMask) | BT;
   4319       break;
   4320     case ne:
   4321       instr = (instr & ~kCondMask) | BF;
   4322       break;
   4323     default:
   4324       UNIMPLEMENTED();
   4325   }
   4326   masm_.emit(instr);
   4327 }
   4328 
   4329 
   4330 void MacroAssembler::TruncatingDiv(Register result, Register dividend,
   4331                                    int32_t divisor) {
   4332   DCHECK(!dividend.is(result));
   4333   DCHECK(!dividend.is(r0));
   4334   DCHECK(!result.is(r0));
   4335   base::MagicNumbersForDivision<uint32_t> mag =
   4336       base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
   4337   mov(r0, Operand(mag.multiplier));
   4338   mulhw(result, dividend, r0);
   4339   bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
   4340   if (divisor > 0 && neg) {
   4341     add(result, result, dividend);
   4342   }
   4343   if (divisor < 0 && !neg && mag.multiplier > 0) {
   4344     sub(result, result, dividend);
   4345   }
   4346   if (mag.shift > 0) srawi(result, result, mag.shift);
   4347   ExtractBit(r0, dividend, 31);
   4348   add(result, result, r0);
   4349 }
   4350 
   4351 }  // namespace internal
   4352 }  // namespace v8
   4353 
   4354 #endif  // V8_TARGET_ARCH_PPC
   4355