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