1// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
33// The original source code covered by the above license above has been
34// modified significantly by Google Inc.
35// Copyright 2014 the V8 project authors. All rights reserved.
36
37#include "src/ppc/assembler-ppc.h"
38
39#if V8_TARGET_ARCH_PPC
40
41#include "src/base/bits.h"
42#include "src/base/cpu.h"
43#include "src/macro-assembler.h"
44#include "src/ppc/assembler-ppc-inl.h"
45
46namespace v8 {
47namespace internal {
48
49// Get the CPU features enabled by the build.
50static unsigned CpuFeaturesImpliedByCompiler() {
51  unsigned answer = 0;
52  return answer;
53}
54
55
56void CpuFeatures::ProbeImpl(bool cross_compile) {
57  supported_ |= CpuFeaturesImpliedByCompiler();
58  icache_line_size_ = 128;
59
60  // Only use statically determined features for cross compile (snapshot).
61  if (cross_compile) return;
62
63// Detect whether frim instruction is supported (POWER5+)
64// For now we will just check for processors we know do not
65// support it
66#ifndef USE_SIMULATOR
67  // Probe for additional features at runtime.
68  base::CPU cpu;
69  if (cpu.part() == base::CPU::PPC_POWER9) {
70    supported_ |= (1u << MODULO);
71  }
72#if V8_TARGET_ARCH_PPC64
73  if (cpu.part() == base::CPU::PPC_POWER8) {
74    supported_ |= (1u << FPR_GPR_MOV);
75  }
76#endif
77  if (cpu.part() == base::CPU::PPC_POWER6 ||
78      cpu.part() == base::CPU::PPC_POWER7 ||
79      cpu.part() == base::CPU::PPC_POWER8) {
80    supported_ |= (1u << LWSYNC);
81  }
82  if (cpu.part() == base::CPU::PPC_POWER7 ||
83      cpu.part() == base::CPU::PPC_POWER8) {
84    supported_ |= (1u << ISELECT);
85    supported_ |= (1u << VSX);
86  }
87#if V8_OS_LINUX
88  if (!(cpu.part() == base::CPU::PPC_G5 || cpu.part() == base::CPU::PPC_G4)) {
89    // Assume support
90    supported_ |= (1u << FPU);
91  }
92  if (cpu.icache_line_size() != base::CPU::UNKNOWN_CACHE_LINE_SIZE) {
93    icache_line_size_ = cpu.icache_line_size();
94  }
95#elif V8_OS_AIX
96  // Assume support FP support and default cache line size
97  supported_ |= (1u << FPU);
98#endif
99#else  // Simulator
100  supported_ |= (1u << FPU);
101  supported_ |= (1u << LWSYNC);
102  supported_ |= (1u << ISELECT);
103  supported_ |= (1u << VSX);
104  supported_ |= (1u << MODULO);
105#if V8_TARGET_ARCH_PPC64
106  supported_ |= (1u << FPR_GPR_MOV);
107#endif
108#endif
109}
110
111
112void CpuFeatures::PrintTarget() {
113  const char* ppc_arch = NULL;
114
115#if V8_TARGET_ARCH_PPC64
116  ppc_arch = "ppc64";
117#else
118  ppc_arch = "ppc";
119#endif
120
121  printf("target %s\n", ppc_arch);
122}
123
124
125void CpuFeatures::PrintFeatures() {
126  printf("FPU=%d\n", CpuFeatures::IsSupported(FPU));
127}
128
129
130Register ToRegister(int num) {
131  DCHECK(num >= 0 && num < kNumRegisters);
132  const Register kRegisters[] = {r0,  sp,  r2,  r3,  r4,  r5,  r6,  r7,
133                                 r8,  r9,  r10, r11, ip,  r13, r14, r15,
134                                 r16, r17, r18, r19, r20, r21, r22, r23,
135                                 r24, r25, r26, r27, r28, r29, r30, fp};
136  return kRegisters[num];
137}
138
139
140// -----------------------------------------------------------------------------
141// Implementation of RelocInfo
142
143const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE |
144                                  1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
145
146
147bool RelocInfo::IsCodedSpecially() {
148  // The deserializer needs to know whether a pointer is specially
149  // coded.  Being specially coded on PPC means that it is a lis/ori
150  // instruction sequence or is a constant pool entry, and these are
151  // always the case inside code objects.
152  return true;
153}
154
155
156bool RelocInfo::IsInConstantPool() {
157  if (FLAG_enable_embedded_constant_pool) {
158    Address constant_pool = host_->constant_pool();
159    return (constant_pool && Assembler::IsConstantPoolLoadStart(pc_));
160  }
161  return false;
162}
163
164Address RelocInfo::wasm_memory_reference() {
165  DCHECK(IsWasmMemoryReference(rmode_));
166  return Assembler::target_address_at(pc_, host_);
167}
168
169uint32_t RelocInfo::wasm_memory_size_reference() {
170  DCHECK(IsWasmMemorySizeReference(rmode_));
171  return static_cast<uint32_t>(
172     reinterpret_cast<intptr_t>(Assembler::target_address_at(pc_, host_)));
173}
174
175Address RelocInfo::wasm_global_reference() {
176  DCHECK(IsWasmGlobalReference(rmode_));
177  return Assembler::target_address_at(pc_, host_);
178}
179
180uint32_t RelocInfo::wasm_function_table_size_reference() {
181  DCHECK(IsWasmFunctionTableSizeReference(rmode_));
182  return static_cast<uint32_t>(
183      reinterpret_cast<intptr_t>(Assembler::target_address_at(pc_, host_)));
184}
185
186void RelocInfo::unchecked_update_wasm_memory_reference(
187    Address address, ICacheFlushMode flush_mode) {
188  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
189}
190
191void RelocInfo::unchecked_update_wasm_size(uint32_t size,
192                                           ICacheFlushMode flush_mode) {
193  Assembler::set_target_address_at(isolate_, pc_, host_,
194                                   reinterpret_cast<Address>(size), flush_mode);
195}
196
197// -----------------------------------------------------------------------------
198// Implementation of Operand and MemOperand
199// See assembler-ppc-inl.h for inlined constructors
200
201Operand::Operand(Handle<Object> handle) {
202  AllowDeferredHandleDereference using_raw_address;
203  rm_ = no_reg;
204  // Verify all Objects referred by code are NOT in new space.
205  Object* obj = *handle;
206  if (obj->IsHeapObject()) {
207    imm_ = reinterpret_cast<intptr_t>(handle.location());
208    rmode_ = RelocInfo::EMBEDDED_OBJECT;
209  } else {
210    // no relocation needed
211    imm_ = reinterpret_cast<intptr_t>(obj);
212    rmode_ = kRelocInfo_NONEPTR;
213  }
214}
215
216
217MemOperand::MemOperand(Register rn, int32_t offset) {
218  ra_ = rn;
219  rb_ = no_reg;
220  offset_ = offset;
221}
222
223
224MemOperand::MemOperand(Register ra, Register rb) {
225  ra_ = ra;
226  rb_ = rb;
227  offset_ = 0;
228}
229
230
231// -----------------------------------------------------------------------------
232// Specific instructions, constants, and masks.
233
234Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
235    : AssemblerBase(isolate, buffer, buffer_size),
236      recorded_ast_id_(TypeFeedbackId::None()),
237      constant_pool_builder_(kLoadPtrMaxReachBits, kLoadDoubleMaxReachBits) {
238  reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
239
240  no_trampoline_pool_before_ = 0;
241  trampoline_pool_blocked_nesting_ = 0;
242  constant_pool_entry_sharing_blocked_nesting_ = 0;
243  next_trampoline_check_ = kMaxInt;
244  internal_trampoline_exception_ = false;
245  last_bound_pos_ = 0;
246  optimizable_cmpi_pos_ = -1;
247  trampoline_emitted_ = FLAG_force_long_branches;
248  tracked_branch_count_ = 0;
249  ClearRecordedAstId();
250  relocations_.reserve(128);
251}
252
253
254void Assembler::GetCode(CodeDesc* desc) {
255  // Emit constant pool if necessary.
256  int constant_pool_offset = EmitConstantPool();
257
258  EmitRelocations();
259
260  // Set up code descriptor.
261  desc->buffer = buffer_;
262  desc->buffer_size = buffer_size_;
263  desc->instr_size = pc_offset();
264  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
265  desc->constant_pool_size =
266      (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0);
267  desc->origin = this;
268  desc->unwinding_info_size = 0;
269  desc->unwinding_info = nullptr;
270}
271
272
273void Assembler::Align(int m) {
274  DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
275  DCHECK((pc_offset() & (kInstrSize - 1)) == 0);
276  while ((pc_offset() & (m - 1)) != 0) {
277    nop();
278  }
279}
280
281
282void Assembler::CodeTargetAlign() { Align(8); }
283
284
285Condition Assembler::GetCondition(Instr instr) {
286  switch (instr & kCondMask) {
287    case BT:
288      return eq;
289    case BF:
290      return ne;
291    default:
292      UNIMPLEMENTED();
293  }
294  return al;
295}
296
297
298bool Assembler::IsLis(Instr instr) {
299  return ((instr & kOpcodeMask) == ADDIS) && GetRA(instr).is(r0);
300}
301
302
303bool Assembler::IsLi(Instr instr) {
304  return ((instr & kOpcodeMask) == ADDI) && GetRA(instr).is(r0);
305}
306
307
308bool Assembler::IsAddic(Instr instr) { return (instr & kOpcodeMask) == ADDIC; }
309
310
311bool Assembler::IsOri(Instr instr) { return (instr & kOpcodeMask) == ORI; }
312
313
314bool Assembler::IsBranch(Instr instr) { return ((instr & kOpcodeMask) == BCX); }
315
316
317Register Assembler::GetRA(Instr instr) {
318  Register reg;
319  reg.reg_code = Instruction::RAValue(instr);
320  return reg;
321}
322
323
324Register Assembler::GetRB(Instr instr) {
325  Register reg;
326  reg.reg_code = Instruction::RBValue(instr);
327  return reg;
328}
329
330
331#if V8_TARGET_ARCH_PPC64
332// This code assumes a FIXED_SEQUENCE for 64bit loads (lis/ori)
333bool Assembler::Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
334                                   Instr instr4, Instr instr5) {
335  // Check the instructions are indeed a five part load (into r12)
336  // 3d800000       lis     r12, 0
337  // 618c0000       ori     r12, r12, 0
338  // 798c07c6       rldicr  r12, r12, 32, 31
339  // 658c00c3       oris    r12, r12, 195
340  // 618ccd40       ori     r12, r12, 52544
341  return (((instr1 >> 16) == 0x3d80) && ((instr2 >> 16) == 0x618c) &&
342          (instr3 == 0x798c07c6) && ((instr4 >> 16) == 0x658c) &&
343          ((instr5 >> 16) == 0x618c));
344}
345#else
346// This code assumes a FIXED_SEQUENCE for 32bit loads (lis/ori)
347bool Assembler::Is32BitLoadIntoR12(Instr instr1, Instr instr2) {
348  // Check the instruction is indeed a two part load (into r12)
349  // 3d802553       lis     r12, 9555
350  // 618c5000       ori   r12, r12, 20480
351  return (((instr1 >> 16) == 0x3d80) && ((instr2 >> 16) == 0x618c));
352}
353#endif
354
355
356bool Assembler::IsCmpRegister(Instr instr) {
357  return (((instr & kOpcodeMask) == EXT2) &&
358          ((EXT2 | (instr & kExt2OpcodeMask)) == CMP));
359}
360
361
362bool Assembler::IsRlwinm(Instr instr) {
363  return ((instr & kOpcodeMask) == RLWINMX);
364}
365
366
367bool Assembler::IsAndi(Instr instr) { return ((instr & kOpcodeMask) == ANDIx); }
368
369
370#if V8_TARGET_ARCH_PPC64
371bool Assembler::IsRldicl(Instr instr) {
372  return (((instr & kOpcodeMask) == EXT5) &&
373          ((EXT5 | (instr & kExt5OpcodeMask)) == RLDICL));
374}
375#endif
376
377
378bool Assembler::IsCmpImmediate(Instr instr) {
379  return ((instr & kOpcodeMask) == CMPI);
380}
381
382
383bool Assembler::IsCrSet(Instr instr) {
384  return (((instr & kOpcodeMask) == EXT1) &&
385          ((EXT1 | (instr & kExt1OpcodeMask)) == CREQV));
386}
387
388
389Register Assembler::GetCmpImmediateRegister(Instr instr) {
390  DCHECK(IsCmpImmediate(instr));
391  return GetRA(instr);
392}
393
394
395int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
396  DCHECK(IsCmpImmediate(instr));
397  return instr & kOff16Mask;
398}
399
400
401// Labels refer to positions in the (to be) generated code.
402// There are bound, linked, and unused labels.
403//
404// Bound labels refer to known positions in the already
405// generated code. pos() is the position the label refers to.
406//
407// Linked labels refer to unknown positions in the code
408// to be generated; pos() is the position of the last
409// instruction using the label.
410
411
412// The link chain is terminated by a negative code position (must be aligned)
413const int kEndOfChain = -4;
414
415
416// Dummy opcodes for unbound label mov instructions or jump table entries.
417enum {
418  kUnboundMovLabelOffsetOpcode = 0 << 26,
419  kUnboundAddLabelOffsetOpcode = 1 << 26,
420  kUnboundMovLabelAddrOpcode = 2 << 26,
421  kUnboundJumpTableEntryOpcode = 3 << 26
422};
423
424
425int Assembler::target_at(int pos) {
426  Instr instr = instr_at(pos);
427  // check which type of branch this is 16 or 26 bit offset
428  uint32_t opcode = instr & kOpcodeMask;
429  int link;
430  switch (opcode) {
431    case BX:
432      link = SIGN_EXT_IMM26(instr & kImm26Mask);
433      link &= ~(kAAMask | kLKMask);  // discard AA|LK bits if present
434      break;
435    case BCX:
436      link = SIGN_EXT_IMM16((instr & kImm16Mask));
437      link &= ~(kAAMask | kLKMask);  // discard AA|LK bits if present
438      break;
439    case kUnboundMovLabelOffsetOpcode:
440    case kUnboundAddLabelOffsetOpcode:
441    case kUnboundMovLabelAddrOpcode:
442    case kUnboundJumpTableEntryOpcode:
443      link = SIGN_EXT_IMM26(instr & kImm26Mask);
444      link <<= 2;
445      break;
446    default:
447      DCHECK(false);
448      return -1;
449  }
450
451  if (link == 0) return kEndOfChain;
452  return pos + link;
453}
454
455
456void Assembler::target_at_put(int pos, int target_pos, bool* is_branch) {
457  Instr instr = instr_at(pos);
458  uint32_t opcode = instr & kOpcodeMask;
459
460  if (is_branch != nullptr) {
461    *is_branch = (opcode == BX || opcode == BCX);
462  }
463
464  switch (opcode) {
465    case BX: {
466      int imm26 = target_pos - pos;
467      CHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0);
468      if (imm26 == kInstrSize && !(instr & kLKMask)) {
469        // Branch to next instr without link.
470        instr = ORI;  // nop: ori, 0,0,0
471      } else {
472        instr &= ((~kImm26Mask) | kAAMask | kLKMask);
473        instr |= (imm26 & kImm26Mask);
474      }
475      instr_at_put(pos, instr);
476      break;
477    }
478    case BCX: {
479      int imm16 = target_pos - pos;
480      CHECK(is_int16(imm16) && (imm16 & (kAAMask | kLKMask)) == 0);
481      if (imm16 == kInstrSize && !(instr & kLKMask)) {
482        // Branch to next instr without link.
483        instr = ORI;  // nop: ori, 0,0,0
484      } else {
485        instr &= ((~kImm16Mask) | kAAMask | kLKMask);
486        instr |= (imm16 & kImm16Mask);
487      }
488      instr_at_put(pos, instr);
489      break;
490    }
491    case kUnboundMovLabelOffsetOpcode: {
492      // Load the position of the label relative to the generated code object
493      // pointer in a register.
494      Register dst = Register::from_code(instr_at(pos + kInstrSize));
495      int32_t offset = target_pos + (Code::kHeaderSize - kHeapObjectTag);
496      CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 2,
497                          CodePatcher::DONT_FLUSH);
498      patcher.masm()->bitwise_mov32(dst, offset);
499      break;
500    }
501    case kUnboundAddLabelOffsetOpcode: {
502      // dst = base + position + immediate
503      Instr operands = instr_at(pos + kInstrSize);
504      Register dst = Register::from_code((operands >> 21) & 0x1f);
505      Register base = Register::from_code((operands >> 16) & 0x1f);
506      int32_t offset = target_pos + SIGN_EXT_IMM16(operands & kImm16Mask);
507      CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 2,
508                          CodePatcher::DONT_FLUSH);
509      patcher.masm()->bitwise_add32(dst, base, offset);
510      break;
511    }
512    case kUnboundMovLabelAddrOpcode: {
513      // Load the address of the label in a register.
514      Register dst = Register::from_code(instr_at(pos + kInstrSize));
515      CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
516                          kMovInstructionsNoConstantPool,
517                          CodePatcher::DONT_FLUSH);
518      // Keep internal references relative until EmitRelocations.
519      patcher.masm()->bitwise_mov(dst, target_pos);
520      break;
521    }
522    case kUnboundJumpTableEntryOpcode: {
523      CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
524                          kPointerSize / kInstrSize, CodePatcher::DONT_FLUSH);
525      // Keep internal references relative until EmitRelocations.
526      patcher.masm()->dp(target_pos);
527      break;
528    }
529    default:
530      DCHECK(false);
531      break;
532  }
533}
534
535
536int Assembler::max_reach_from(int pos) {
537  Instr instr = instr_at(pos);
538  uint32_t opcode = instr & kOpcodeMask;
539
540  // check which type of branch this is 16 or 26 bit offset
541  switch (opcode) {
542    case BX:
543      return 26;
544    case BCX:
545      return 16;
546    case kUnboundMovLabelOffsetOpcode:
547    case kUnboundAddLabelOffsetOpcode:
548    case kUnboundMovLabelAddrOpcode:
549    case kUnboundJumpTableEntryOpcode:
550      return 0;  // no limit on reach
551  }
552
553  DCHECK(false);
554  return 0;
555}
556
557
558void Assembler::bind_to(Label* L, int pos) {
559  DCHECK(0 <= pos && pos <= pc_offset());  // must have a valid binding position
560  int32_t trampoline_pos = kInvalidSlotPos;
561  bool is_branch = false;
562  while (L->is_linked()) {
563    int fixup_pos = L->pos();
564    int32_t offset = pos - fixup_pos;
565    int maxReach = max_reach_from(fixup_pos);
566    next(L);  // call next before overwriting link with target at fixup_pos
567    if (maxReach && is_intn(offset, maxReach) == false) {
568      if (trampoline_pos == kInvalidSlotPos) {
569        trampoline_pos = get_trampoline_entry();
570        CHECK(trampoline_pos != kInvalidSlotPos);
571        target_at_put(trampoline_pos, pos);
572      }
573      target_at_put(fixup_pos, trampoline_pos);
574    } else {
575      target_at_put(fixup_pos, pos, &is_branch);
576    }
577  }
578  L->bind_to(pos);
579
580  if (!trampoline_emitted_ && is_branch) {
581    UntrackBranch();
582  }
583
584  // Keep track of the last bound label so we don't eliminate any instructions
585  // before a bound label.
586  if (pos > last_bound_pos_) last_bound_pos_ = pos;
587}
588
589
590void Assembler::bind(Label* L) {
591  DCHECK(!L->is_bound());  // label can only be bound once
592  bind_to(L, pc_offset());
593}
594
595
596void Assembler::next(Label* L) {
597  DCHECK(L->is_linked());
598  int link = target_at(L->pos());
599  if (link == kEndOfChain) {
600    L->Unuse();
601  } else {
602    DCHECK(link >= 0);
603    L->link_to(link);
604  }
605}
606
607
608bool Assembler::is_near(Label* L, Condition cond) {
609  DCHECK(L->is_bound());
610  if (L->is_bound() == false) return false;
611
612  int maxReach = ((cond == al) ? 26 : 16);
613  int offset = L->pos() - pc_offset();
614
615  return is_intn(offset, maxReach);
616}
617
618
619void Assembler::a_form(Instr instr, DoubleRegister frt, DoubleRegister fra,
620                       DoubleRegister frb, RCBit r) {
621  emit(instr | frt.code() * B21 | fra.code() * B16 | frb.code() * B11 | r);
622}
623
624
625void Assembler::d_form(Instr instr, Register rt, Register ra,
626                       const intptr_t val, bool signed_disp) {
627  if (signed_disp) {
628    if (!is_int16(val)) {
629      PrintF("val = %" V8PRIdPTR ", 0x%" V8PRIxPTR "\n", val, val);
630    }
631    CHECK(is_int16(val));
632  } else {
633    if (!is_uint16(val)) {
634      PrintF("val = %" V8PRIdPTR ", 0x%" V8PRIxPTR
635             ", is_unsigned_imm16(val)=%d, kImm16Mask=0x%x\n",
636             val, val, is_uint16(val), kImm16Mask);
637    }
638    CHECK(is_uint16(val));
639  }
640  emit(instr | rt.code() * B21 | ra.code() * B16 | (kImm16Mask & val));
641}
642
643
644void Assembler::x_form(Instr instr, Register ra, Register rs, Register rb,
645                       RCBit r) {
646  emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | r);
647}
648
649void Assembler::xo_form(Instr instr, Register rt, Register ra, Register rb,
650                        OEBit o, RCBit r) {
651  emit(instr | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 | o | r);
652}
653
654void Assembler::xx3_form(Instr instr, DoubleRegister t, DoubleRegister a,
655                         DoubleRegister b) {
656  int AX = ((a.code() & 0x20) >> 5) & 0x1;
657  int BX = ((b.code() & 0x20) >> 5) & 0x1;
658  int TX = ((t.code() & 0x20) >> 5) & 0x1;
659  emit(instr | (t.code() & 0x1F) * B21 | (a.code() & 0x1F) * B16 | (b.code()
660       & 0x1F) * B11 | AX * B2 | BX * B1 | TX);
661}
662
663void Assembler::md_form(Instr instr, Register ra, Register rs, int shift,
664                        int maskbit, RCBit r) {
665  int sh0_4 = shift & 0x1f;
666  int sh5 = (shift >> 5) & 0x1;
667  int m0_4 = maskbit & 0x1f;
668  int m5 = (maskbit >> 5) & 0x1;
669
670  emit(instr | rs.code() * B21 | ra.code() * B16 | sh0_4 * B11 | m0_4 * B6 |
671       m5 * B5 | sh5 * B1 | r);
672}
673
674
675void Assembler::mds_form(Instr instr, Register ra, Register rs, Register rb,
676                         int maskbit, RCBit r) {
677  int m0_4 = maskbit & 0x1f;
678  int m5 = (maskbit >> 5) & 0x1;
679
680  emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | m0_4 * B6 |
681       m5 * B5 | r);
682}
683
684
685// Returns the next free trampoline entry.
686int32_t Assembler::get_trampoline_entry() {
687  int32_t trampoline_entry = kInvalidSlotPos;
688
689  if (!internal_trampoline_exception_) {
690    trampoline_entry = trampoline_.take_slot();
691
692    if (kInvalidSlotPos == trampoline_entry) {
693      internal_trampoline_exception_ = true;
694    }
695  }
696  return trampoline_entry;
697}
698
699
700int Assembler::link(Label* L) {
701  int position;
702  if (L->is_bound()) {
703    position = L->pos();
704  } else {
705    if (L->is_linked()) {
706      position = L->pos();  // L's link
707    } else {
708      // was: target_pos = kEndOfChain;
709      // However, using self to mark the first reference
710      // should avoid most instances of branch offset overflow.  See
711      // target_at() for where this is converted back to kEndOfChain.
712      position = pc_offset();
713    }
714    L->link_to(pc_offset());
715  }
716
717  return position;
718}
719
720
721// Branch instructions.
722
723
724void Assembler::bclr(BOfield bo, int condition_bit, LKBit lk) {
725  emit(EXT1 | bo | condition_bit * B16 | BCLRX | lk);
726}
727
728
729void Assembler::bcctr(BOfield bo, int condition_bit, LKBit lk) {
730  emit(EXT1 | bo | condition_bit * B16 | BCCTRX | lk);
731}
732
733
734// Pseudo op - branch to link register
735void Assembler::blr() { bclr(BA, 0, LeaveLK); }
736
737
738// Pseudo op - branch to count register -- used for "jump"
739void Assembler::bctr() { bcctr(BA, 0, LeaveLK); }
740
741
742void Assembler::bctrl() { bcctr(BA, 0, SetLK); }
743
744
745void Assembler::bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk) {
746  int imm16 = branch_offset;
747  CHECK(is_int16(imm16) && (imm16 & (kAAMask | kLKMask)) == 0);
748  emit(BCX | bo | condition_bit * B16 | (imm16 & kImm16Mask) | lk);
749}
750
751
752void Assembler::b(int branch_offset, LKBit lk) {
753  int imm26 = branch_offset;
754  CHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0);
755  emit(BX | (imm26 & kImm26Mask) | lk);
756}
757
758
759void Assembler::xori(Register dst, Register src, const Operand& imm) {
760  d_form(XORI, src, dst, imm.imm_, false);
761}
762
763
764void Assembler::xoris(Register ra, Register rs, const Operand& imm) {
765  d_form(XORIS, rs, ra, imm.imm_, false);
766}
767
768
769void Assembler::xor_(Register dst, Register src1, Register src2, RCBit rc) {
770  x_form(EXT2 | XORX, dst, src1, src2, rc);
771}
772
773
774void Assembler::cntlzw_(Register ra, Register rs, RCBit rc) {
775  x_form(EXT2 | CNTLZWX, ra, rs, r0, rc);
776}
777
778
779void Assembler::popcntw(Register ra, Register rs) {
780  emit(EXT2 | POPCNTW | rs.code() * B21 | ra.code() * B16);
781}
782
783
784void Assembler::and_(Register ra, Register rs, Register rb, RCBit rc) {
785  x_form(EXT2 | ANDX, ra, rs, rb, rc);
786}
787
788
789void Assembler::rlwinm(Register ra, Register rs, int sh, int mb, int me,
790                       RCBit rc) {
791  sh &= 0x1f;
792  mb &= 0x1f;
793  me &= 0x1f;
794  emit(RLWINMX | rs.code() * B21 | ra.code() * B16 | sh * B11 | mb * B6 |
795       me << 1 | rc);
796}
797
798
799void Assembler::rlwnm(Register ra, Register rs, Register rb, int mb, int me,
800                      RCBit rc) {
801  mb &= 0x1f;
802  me &= 0x1f;
803  emit(RLWNMX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | mb * B6 |
804       me << 1 | rc);
805}
806
807
808void Assembler::rlwimi(Register ra, Register rs, int sh, int mb, int me,
809                       RCBit rc) {
810  sh &= 0x1f;
811  mb &= 0x1f;
812  me &= 0x1f;
813  emit(RLWIMIX | rs.code() * B21 | ra.code() * B16 | sh * B11 | mb * B6 |
814       me << 1 | rc);
815}
816
817
818void Assembler::slwi(Register dst, Register src, const Operand& val, RCBit rc) {
819  DCHECK((32 > val.imm_) && (val.imm_ >= 0));
820  rlwinm(dst, src, val.imm_, 0, 31 - val.imm_, rc);
821}
822
823
824void Assembler::srwi(Register dst, Register src, const Operand& val, RCBit rc) {
825  DCHECK((32 > val.imm_) && (val.imm_ >= 0));
826  rlwinm(dst, src, 32 - val.imm_, val.imm_, 31, rc);
827}
828
829
830void Assembler::clrrwi(Register dst, Register src, const Operand& val,
831                       RCBit rc) {
832  DCHECK((32 > val.imm_) && (val.imm_ >= 0));
833  rlwinm(dst, src, 0, 0, 31 - val.imm_, rc);
834}
835
836
837void Assembler::clrlwi(Register dst, Register src, const Operand& val,
838                       RCBit rc) {
839  DCHECK((32 > val.imm_) && (val.imm_ >= 0));
840  rlwinm(dst, src, 0, val.imm_, 31, rc);
841}
842
843
844void Assembler::srawi(Register ra, Register rs, int sh, RCBit r) {
845  emit(EXT2 | SRAWIX | rs.code() * B21 | ra.code() * B16 | sh * B11 | r);
846}
847
848
849void Assembler::srw(Register dst, Register src1, Register src2, RCBit r) {
850  x_form(EXT2 | SRWX, dst, src1, src2, r);
851}
852
853
854void Assembler::slw(Register dst, Register src1, Register src2, RCBit r) {
855  x_form(EXT2 | SLWX, dst, src1, src2, r);
856}
857
858
859void Assembler::sraw(Register ra, Register rs, Register rb, RCBit r) {
860  x_form(EXT2 | SRAW, ra, rs, rb, r);
861}
862
863
864void Assembler::rotlw(Register ra, Register rs, Register rb, RCBit r) {
865  rlwnm(ra, rs, rb, 0, 31, r);
866}
867
868
869void Assembler::rotlwi(Register ra, Register rs, int sh, RCBit r) {
870  rlwinm(ra, rs, sh, 0, 31, r);
871}
872
873
874void Assembler::rotrwi(Register ra, Register rs, int sh, RCBit r) {
875  rlwinm(ra, rs, 32 - sh, 0, 31, r);
876}
877
878
879void Assembler::subi(Register dst, Register src, const Operand& imm) {
880  addi(dst, src, Operand(-(imm.imm_)));
881}
882
883void Assembler::addc(Register dst, Register src1, Register src2, OEBit o,
884                     RCBit r) {
885  xo_form(EXT2 | ADDCX, dst, src1, src2, o, r);
886}
887
888void Assembler::adde(Register dst, Register src1, Register src2, OEBit o,
889                     RCBit r) {
890  xo_form(EXT2 | ADDEX, dst, src1, src2, o, r);
891}
892
893void Assembler::addze(Register dst, Register src1, OEBit o, RCBit r) {
894  // a special xo_form
895  emit(EXT2 | ADDZEX | dst.code() * B21 | src1.code() * B16 | o | r);
896}
897
898
899void Assembler::sub(Register dst, Register src1, Register src2, OEBit o,
900                    RCBit r) {
901  xo_form(EXT2 | SUBFX, dst, src2, src1, o, r);
902}
903
904void Assembler::subc(Register dst, Register src1, Register src2, OEBit o,
905                     RCBit r) {
906  xo_form(EXT2 | SUBFCX, dst, src2, src1, o, r);
907}
908
909void Assembler::sube(Register dst, Register src1, Register src2, OEBit o,
910                     RCBit r) {
911  xo_form(EXT2 | SUBFEX, dst, src2, src1, o, r);
912}
913
914void Assembler::subfic(Register dst, Register src, const Operand& imm) {
915  d_form(SUBFIC, dst, src, imm.imm_, true);
916}
917
918
919void Assembler::add(Register dst, Register src1, Register src2, OEBit o,
920                    RCBit r) {
921  xo_form(EXT2 | ADDX, dst, src1, src2, o, r);
922}
923
924
925// Multiply low word
926void Assembler::mullw(Register dst, Register src1, Register src2, OEBit o,
927                      RCBit r) {
928  xo_form(EXT2 | MULLW, dst, src1, src2, o, r);
929}
930
931
932// Multiply hi word
933void Assembler::mulhw(Register dst, Register src1, Register src2, RCBit r) {
934  xo_form(EXT2 | MULHWX, dst, src1, src2, LeaveOE, r);
935}
936
937
938// Multiply hi word unsigned
939void Assembler::mulhwu(Register dst, Register src1, Register src2, RCBit r) {
940  xo_form(EXT2 | MULHWUX, dst, src1, src2, LeaveOE, r);
941}
942
943
944// Divide word
945void Assembler::divw(Register dst, Register src1, Register src2, OEBit o,
946                     RCBit r) {
947  xo_form(EXT2 | DIVW, dst, src1, src2, o, r);
948}
949
950
951// Divide word unsigned
952void Assembler::divwu(Register dst, Register src1, Register src2, OEBit o,
953                      RCBit r) {
954  xo_form(EXT2 | DIVWU, dst, src1, src2, o, r);
955}
956
957void Assembler::modsw(Register rt, Register ra, Register rb) {
958  x_form(EXT2 | MODSW, ra, rt, rb, LeaveRC);
959}
960
961void Assembler::moduw(Register rt, Register ra, Register rb) {
962  x_form(EXT2 | MODUW, ra, rt, rb, LeaveRC);
963}
964
965void Assembler::addi(Register dst, Register src, const Operand& imm) {
966  DCHECK(!src.is(r0));  // use li instead to show intent
967  d_form(ADDI, dst, src, imm.imm_, true);
968}
969
970
971void Assembler::addis(Register dst, Register src, const Operand& imm) {
972  DCHECK(!src.is(r0));  // use lis instead to show intent
973  d_form(ADDIS, dst, src, imm.imm_, true);
974}
975
976
977void Assembler::addic(Register dst, Register src, const Operand& imm) {
978  d_form(ADDIC, dst, src, imm.imm_, true);
979}
980
981
982void Assembler::andi(Register ra, Register rs, const Operand& imm) {
983  d_form(ANDIx, rs, ra, imm.imm_, false);
984}
985
986
987void Assembler::andis(Register ra, Register rs, const Operand& imm) {
988  d_form(ANDISx, rs, ra, imm.imm_, false);
989}
990
991
992void Assembler::nor(Register dst, Register src1, Register src2, RCBit r) {
993  x_form(EXT2 | NORX, dst, src1, src2, r);
994}
995
996
997void Assembler::notx(Register dst, Register src, RCBit r) {
998  x_form(EXT2 | NORX, dst, src, src, r);
999}
1000
1001
1002void Assembler::ori(Register ra, Register rs, const Operand& imm) {
1003  d_form(ORI, rs, ra, imm.imm_, false);
1004}
1005
1006
1007void Assembler::oris(Register dst, Register src, const Operand& imm) {
1008  d_form(ORIS, src, dst, imm.imm_, false);
1009}
1010
1011
1012void Assembler::orx(Register dst, Register src1, Register src2, RCBit rc) {
1013  x_form(EXT2 | ORX, dst, src1, src2, rc);
1014}
1015
1016
1017void Assembler::orc(Register dst, Register src1, Register src2, RCBit rc) {
1018  x_form(EXT2 | ORC, dst, src1, src2, rc);
1019}
1020
1021
1022void Assembler::cmpi(Register src1, const Operand& src2, CRegister cr) {
1023  intptr_t imm16 = src2.imm_;
1024#if V8_TARGET_ARCH_PPC64
1025  int L = 1;
1026#else
1027  int L = 0;
1028#endif
1029  DCHECK(is_int16(imm16));
1030  DCHECK(cr.code() >= 0 && cr.code() <= 7);
1031  imm16 &= kImm16Mask;
1032  emit(CMPI | cr.code() * B23 | L * B21 | src1.code() * B16 | imm16);
1033}
1034
1035
1036void Assembler::cmpli(Register src1, const Operand& src2, CRegister cr) {
1037  uintptr_t uimm16 = src2.imm_;
1038#if V8_TARGET_ARCH_PPC64
1039  int L = 1;
1040#else
1041  int L = 0;
1042#endif
1043  DCHECK(is_uint16(uimm16));
1044  DCHECK(cr.code() >= 0 && cr.code() <= 7);
1045  uimm16 &= kImm16Mask;
1046  emit(CMPLI | cr.code() * B23 | L * B21 | src1.code() * B16 | uimm16);
1047}
1048
1049
1050void Assembler::cmp(Register src1, Register src2, CRegister cr) {
1051#if V8_TARGET_ARCH_PPC64
1052  int L = 1;
1053#else
1054  int L = 0;
1055#endif
1056  DCHECK(cr.code() >= 0 && cr.code() <= 7);
1057  emit(EXT2 | CMP | cr.code() * B23 | L * B21 | src1.code() * B16 |
1058       src2.code() * B11);
1059}
1060
1061
1062void Assembler::cmpl(Register src1, Register src2, CRegister cr) {
1063#if V8_TARGET_ARCH_PPC64
1064  int L = 1;
1065#else
1066  int L = 0;
1067#endif
1068  DCHECK(cr.code() >= 0 && cr.code() <= 7);
1069  emit(EXT2 | CMPL | cr.code() * B23 | L * B21 | src1.code() * B16 |
1070       src2.code() * B11);
1071}
1072
1073
1074void Assembler::cmpwi(Register src1, const Operand& src2, CRegister cr) {
1075  intptr_t imm16 = src2.imm_;
1076  int L = 0;
1077  int pos = pc_offset();
1078  DCHECK(is_int16(imm16));
1079  DCHECK(cr.code() >= 0 && cr.code() <= 7);
1080  imm16 &= kImm16Mask;
1081
1082  // For cmpwi against 0, save postition and cr for later examination
1083  // of potential optimization.
1084  if (imm16 == 0 && pos > 0 && last_bound_pos_ != pos) {
1085    optimizable_cmpi_pos_ = pos;
1086    cmpi_cr_ = cr;
1087  }
1088  emit(CMPI | cr.code() * B23 | L * B21 | src1.code() * B16 | imm16);
1089}
1090
1091
1092void Assembler::cmplwi(Register src1, const Operand& src2, CRegister cr) {
1093  uintptr_t uimm16 = src2.imm_;
1094  int L = 0;
1095  DCHECK(is_uint16(uimm16));
1096  DCHECK(cr.code() >= 0 && cr.code() <= 7);
1097  uimm16 &= kImm16Mask;
1098  emit(CMPLI | cr.code() * B23 | L * B21 | src1.code() * B16 | uimm16);
1099}
1100
1101
1102void Assembler::cmpw(Register src1, Register src2, CRegister cr) {
1103  int L = 0;
1104  DCHECK(cr.code() >= 0 && cr.code() <= 7);
1105  emit(EXT2 | CMP | cr.code() * B23 | L * B21 | src1.code() * B16 |
1106       src2.code() * B11);
1107}
1108
1109
1110void Assembler::cmplw(Register src1, Register src2, CRegister cr) {
1111  int L = 0;
1112  DCHECK(cr.code() >= 0 && cr.code() <= 7);
1113  emit(EXT2 | CMPL | cr.code() * B23 | L * B21 | src1.code() * B16 |
1114       src2.code() * B11);
1115}
1116
1117
1118void Assembler::isel(Register rt, Register ra, Register rb, int cb) {
1119  emit(EXT2 | ISEL | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1120       cb * B6);
1121}
1122
1123
1124// Pseudo op - load immediate
1125void Assembler::li(Register dst, const Operand& imm) {
1126  d_form(ADDI, dst, r0, imm.imm_, true);
1127}
1128
1129
1130void Assembler::lis(Register dst, const Operand& imm) {
1131  d_form(ADDIS, dst, r0, imm.imm_, true);
1132}
1133
1134
1135// Pseudo op - move register
1136void Assembler::mr(Register dst, Register src) {
1137  // actually or(dst, src, src)
1138  orx(dst, src, src);
1139}
1140
1141
1142void Assembler::lbz(Register dst, const MemOperand& src) {
1143  DCHECK(!src.ra_.is(r0));
1144  d_form(LBZ, dst, src.ra(), src.offset(), true);
1145}
1146
1147
1148void Assembler::lbzx(Register rt, const MemOperand& src) {
1149  Register ra = src.ra();
1150  Register rb = src.rb();
1151  DCHECK(!ra.is(r0));
1152  emit(EXT2 | LBZX | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1153       LeaveRC);
1154}
1155
1156
1157void Assembler::lbzux(Register rt, const MemOperand& src) {
1158  Register ra = src.ra();
1159  Register rb = src.rb();
1160  DCHECK(!ra.is(r0));
1161  emit(EXT2 | LBZUX | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1162       LeaveRC);
1163}
1164
1165
1166void Assembler::lhz(Register dst, const MemOperand& src) {
1167  DCHECK(!src.ra_.is(r0));
1168  d_form(LHZ, dst, src.ra(), src.offset(), true);
1169}
1170
1171
1172void Assembler::lhzx(Register rt, const MemOperand& src) {
1173  Register ra = src.ra();
1174  Register rb = src.rb();
1175  DCHECK(!ra.is(r0));
1176  emit(EXT2 | LHZX | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1177       LeaveRC);
1178}
1179
1180
1181void Assembler::lhzux(Register rt, const MemOperand& src) {
1182  Register ra = src.ra();
1183  Register rb = src.rb();
1184  DCHECK(!ra.is(r0));
1185  emit(EXT2 | LHZUX | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1186       LeaveRC);
1187}
1188
1189
1190void Assembler::lhax(Register rt, const MemOperand& src) {
1191  Register ra = src.ra();
1192  Register rb = src.rb();
1193  DCHECK(!ra.is(r0));
1194  emit(EXT2 | LHAX | rt.code() * B21 | ra.code() * B16 | rb.code() * B11);
1195}
1196
1197
1198void Assembler::lwz(Register dst, const MemOperand& src) {
1199  DCHECK(!src.ra_.is(r0));
1200  d_form(LWZ, dst, src.ra(), src.offset(), true);
1201}
1202
1203
1204void Assembler::lwzu(Register dst, const MemOperand& src) {
1205  DCHECK(!src.ra_.is(r0));
1206  d_form(LWZU, dst, src.ra(), src.offset(), true);
1207}
1208
1209
1210void Assembler::lwzx(Register rt, const MemOperand& src) {
1211  Register ra = src.ra();
1212  Register rb = src.rb();
1213  DCHECK(!ra.is(r0));
1214  emit(EXT2 | LWZX | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1215       LeaveRC);
1216}
1217
1218
1219void Assembler::lwzux(Register rt, const MemOperand& src) {
1220  Register ra = src.ra();
1221  Register rb = src.rb();
1222  DCHECK(!ra.is(r0));
1223  emit(EXT2 | LWZUX | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1224       LeaveRC);
1225}
1226
1227
1228void Assembler::lha(Register dst, const MemOperand& src) {
1229  DCHECK(!src.ra_.is(r0));
1230  d_form(LHA, dst, src.ra(), src.offset(), true);
1231}
1232
1233
1234void Assembler::lwa(Register dst, const MemOperand& src) {
1235#if V8_TARGET_ARCH_PPC64
1236  int offset = src.offset();
1237  DCHECK(!src.ra_.is(r0));
1238  CHECK(!(offset & 3) && is_int16(offset));
1239  offset = kImm16Mask & offset;
1240  emit(LD | dst.code() * B21 | src.ra().code() * B16 | offset | 2);
1241#else
1242  lwz(dst, src);
1243#endif
1244}
1245
1246
1247void Assembler::lwax(Register rt, const MemOperand& src) {
1248#if V8_TARGET_ARCH_PPC64
1249  Register ra = src.ra();
1250  Register rb = src.rb();
1251  DCHECK(!ra.is(r0));
1252  emit(EXT2 | LWAX | rt.code() * B21 | ra.code() * B16 | rb.code() * B11);
1253#else
1254  lwzx(rt, src);
1255#endif
1256}
1257
1258
1259void Assembler::ldbrx(Register dst, const MemOperand& src) {
1260  x_form(EXT2 | LDBRX, src.ra(), dst, src.rb(), LeaveRC);
1261}
1262
1263
1264void Assembler::lwbrx(Register dst, const MemOperand& src) {
1265  x_form(EXT2 | LWBRX, src.ra(), dst, src.rb(), LeaveRC);
1266}
1267
1268
1269void Assembler::lhbrx(Register dst, const MemOperand& src) {
1270  x_form(EXT2 | LHBRX, src.ra(), dst, src.rb(), LeaveRC);
1271}
1272
1273
1274void Assembler::stb(Register dst, const MemOperand& src) {
1275  DCHECK(!src.ra_.is(r0));
1276  d_form(STB, dst, src.ra(), src.offset(), true);
1277}
1278
1279
1280void Assembler::stbx(Register rs, const MemOperand& src) {
1281  Register ra = src.ra();
1282  Register rb = src.rb();
1283  DCHECK(!ra.is(r0));
1284  emit(EXT2 | STBX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1285       LeaveRC);
1286}
1287
1288
1289void Assembler::stbux(Register rs, const MemOperand& src) {
1290  Register ra = src.ra();
1291  Register rb = src.rb();
1292  DCHECK(!ra.is(r0));
1293  emit(EXT2 | STBUX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1294       LeaveRC);
1295}
1296
1297
1298void Assembler::sth(Register dst, const MemOperand& src) {
1299  DCHECK(!src.ra_.is(r0));
1300  d_form(STH, dst, src.ra(), src.offset(), true);
1301}
1302
1303
1304void Assembler::sthx(Register rs, const MemOperand& src) {
1305  Register ra = src.ra();
1306  Register rb = src.rb();
1307  DCHECK(!ra.is(r0));
1308  emit(EXT2 | STHX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1309       LeaveRC);
1310}
1311
1312
1313void Assembler::sthux(Register rs, const MemOperand& src) {
1314  Register ra = src.ra();
1315  Register rb = src.rb();
1316  DCHECK(!ra.is(r0));
1317  emit(EXT2 | STHUX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1318       LeaveRC);
1319}
1320
1321
1322void Assembler::stw(Register dst, const MemOperand& src) {
1323  DCHECK(!src.ra_.is(r0));
1324  d_form(STW, dst, src.ra(), src.offset(), true);
1325}
1326
1327
1328void Assembler::stwu(Register dst, const MemOperand& src) {
1329  DCHECK(!src.ra_.is(r0));
1330  d_form(STWU, dst, src.ra(), src.offset(), true);
1331}
1332
1333
1334void Assembler::stwx(Register rs, const MemOperand& src) {
1335  Register ra = src.ra();
1336  Register rb = src.rb();
1337  DCHECK(!ra.is(r0));
1338  emit(EXT2 | STWX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1339       LeaveRC);
1340}
1341
1342
1343void Assembler::stwux(Register rs, const MemOperand& src) {
1344  Register ra = src.ra();
1345  Register rb = src.rb();
1346  DCHECK(!ra.is(r0));
1347  emit(EXT2 | STWUX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
1348       LeaveRC);
1349}
1350
1351
1352void Assembler::extsb(Register rs, Register ra, RCBit rc) {
1353  emit(EXT2 | EXTSB | ra.code() * B21 | rs.code() * B16 | rc);
1354}
1355
1356
1357void Assembler::extsh(Register rs, Register ra, RCBit rc) {
1358  emit(EXT2 | EXTSH | ra.code() * B21 | rs.code() * B16 | rc);
1359}
1360
1361
1362void Assembler::extsw(Register rs, Register ra, RCBit rc) {
1363#if V8_TARGET_ARCH_PPC64
1364  emit(EXT2 | EXTSW | ra.code() * B21 | rs.code() * B16 | rc);
1365#else
1366  // nop on 32-bit
1367  DCHECK(rs.is(ra) && rc == LeaveRC);
1368#endif
1369}
1370
1371
1372void Assembler::neg(Register rt, Register ra, OEBit o, RCBit r) {
1373  emit(EXT2 | NEGX | rt.code() * B21 | ra.code() * B16 | o | r);
1374}
1375
1376
1377void Assembler::andc(Register dst, Register src1, Register src2, RCBit rc) {
1378  x_form(EXT2 | ANDCX, dst, src1, src2, rc);
1379}
1380
1381
1382#if V8_TARGET_ARCH_PPC64
1383// 64bit specific instructions
1384void Assembler::ld(Register rd, const MemOperand& src) {
1385  int offset = src.offset();
1386  DCHECK(!src.ra_.is(r0));
1387  CHECK(!(offset & 3) && is_int16(offset));
1388  offset = kImm16Mask & offset;
1389  emit(LD | rd.code() * B21 | src.ra().code() * B16 | offset);
1390}
1391
1392
1393void Assembler::ldx(Register rd, const MemOperand& src) {
1394  Register ra = src.ra();
1395  Register rb = src.rb();
1396  DCHECK(!ra.is(r0));
1397  emit(EXT2 | LDX | rd.code() * B21 | ra.code() * B16 | rb.code() * B11);
1398}
1399
1400
1401void Assembler::ldu(Register rd, const MemOperand& src) {
1402  int offset = src.offset();
1403  DCHECK(!src.ra_.is(r0));
1404  CHECK(!(offset & 3) && is_int16(offset));
1405  offset = kImm16Mask & offset;
1406  emit(LD | rd.code() * B21 | src.ra().code() * B16 | offset | 1);
1407}
1408
1409
1410void Assembler::ldux(Register rd, const MemOperand& src) {
1411  Register ra = src.ra();
1412  Register rb = src.rb();
1413  DCHECK(!ra.is(r0));
1414  emit(EXT2 | LDUX | rd.code() * B21 | ra.code() * B16 | rb.code() * B11);
1415}
1416
1417
1418void Assembler::std(Register rs, const MemOperand& src) {
1419  int offset = src.offset();
1420  DCHECK(!src.ra_.is(r0));
1421  CHECK(!(offset & 3) && is_int16(offset));
1422  offset = kImm16Mask & offset;
1423  emit(STD | rs.code() * B21 | src.ra().code() * B16 | offset);
1424}
1425
1426
1427void Assembler::stdx(Register rs, const MemOperand& src) {
1428  Register ra = src.ra();
1429  Register rb = src.rb();
1430  DCHECK(!ra.is(r0));
1431  emit(EXT2 | STDX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11);
1432}
1433
1434
1435void Assembler::stdu(Register rs, const MemOperand& src) {
1436  int offset = src.offset();
1437  DCHECK(!src.ra_.is(r0));
1438  CHECK(!(offset & 3) && is_int16(offset));
1439  offset = kImm16Mask & offset;
1440  emit(STD | rs.code() * B21 | src.ra().code() * B16 | offset | 1);
1441}
1442
1443
1444void Assembler::stdux(Register rs, const MemOperand& src) {
1445  Register ra = src.ra();
1446  Register rb = src.rb();
1447  DCHECK(!ra.is(r0));
1448  emit(EXT2 | STDUX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11);
1449}
1450
1451
1452void Assembler::rldic(Register ra, Register rs, int sh, int mb, RCBit r) {
1453  md_form(EXT5 | RLDIC, ra, rs, sh, mb, r);
1454}
1455
1456
1457void Assembler::rldicl(Register ra, Register rs, int sh, int mb, RCBit r) {
1458  md_form(EXT5 | RLDICL, ra, rs, sh, mb, r);
1459}
1460
1461
1462void Assembler::rldcl(Register ra, Register rs, Register rb, int mb, RCBit r) {
1463  mds_form(EXT5 | RLDCL, ra, rs, rb, mb, r);
1464}
1465
1466
1467void Assembler::rldicr(Register ra, Register rs, int sh, int me, RCBit r) {
1468  md_form(EXT5 | RLDICR, ra, rs, sh, me, r);
1469}
1470
1471
1472void Assembler::sldi(Register dst, Register src, const Operand& val, RCBit rc) {
1473  DCHECK((64 > val.imm_) && (val.imm_ >= 0));
1474  rldicr(dst, src, val.imm_, 63 - val.imm_, rc);
1475}
1476
1477
1478void Assembler::srdi(Register dst, Register src, const Operand& val, RCBit rc) {
1479  DCHECK((64 > val.imm_) && (val.imm_ >= 0));
1480  rldicl(dst, src, 64 - val.imm_, val.imm_, rc);
1481}
1482
1483
1484void Assembler::clrrdi(Register dst, Register src, const Operand& val,
1485                       RCBit rc) {
1486  DCHECK((64 > val.imm_) && (val.imm_ >= 0));
1487  rldicr(dst, src, 0, 63 - val.imm_, rc);
1488}
1489
1490
1491void Assembler::clrldi(Register dst, Register src, const Operand& val,
1492                       RCBit rc) {
1493  DCHECK((64 > val.imm_) && (val.imm_ >= 0));
1494  rldicl(dst, src, 0, val.imm_, rc);
1495}
1496
1497
1498void Assembler::rldimi(Register ra, Register rs, int sh, int mb, RCBit r) {
1499  md_form(EXT5 | RLDIMI, ra, rs, sh, mb, r);
1500}
1501
1502
1503void Assembler::sradi(Register ra, Register rs, int sh, RCBit r) {
1504  int sh0_4 = sh & 0x1f;
1505  int sh5 = (sh >> 5) & 0x1;
1506
1507  emit(EXT2 | SRADIX | rs.code() * B21 | ra.code() * B16 | sh0_4 * B11 |
1508       sh5 * B1 | r);
1509}
1510
1511
1512void Assembler::srd(Register dst, Register src1, Register src2, RCBit r) {
1513  x_form(EXT2 | SRDX, dst, src1, src2, r);
1514}
1515
1516
1517void Assembler::sld(Register dst, Register src1, Register src2, RCBit r) {
1518  x_form(EXT2 | SLDX, dst, src1, src2, r);
1519}
1520
1521
1522void Assembler::srad(Register ra, Register rs, Register rb, RCBit r) {
1523  x_form(EXT2 | SRAD, ra, rs, rb, r);
1524}
1525
1526
1527void Assembler::rotld(Register ra, Register rs, Register rb, RCBit r) {
1528  rldcl(ra, rs, rb, 0, r);
1529}
1530
1531
1532void Assembler::rotldi(Register ra, Register rs, int sh, RCBit r) {
1533  rldicl(ra, rs, sh, 0, r);
1534}
1535
1536
1537void Assembler::rotrdi(Register ra, Register rs, int sh, RCBit r) {
1538  rldicl(ra, rs, 64 - sh, 0, r);
1539}
1540
1541
1542void Assembler::cntlzd_(Register ra, Register rs, RCBit rc) {
1543  x_form(EXT2 | CNTLZDX, ra, rs, r0, rc);
1544}
1545
1546
1547void Assembler::popcntd(Register ra, Register rs) {
1548  emit(EXT2 | POPCNTD | rs.code() * B21 | ra.code() * B16);
1549}
1550
1551
1552void Assembler::mulld(Register dst, Register src1, Register src2, OEBit o,
1553                      RCBit r) {
1554  xo_form(EXT2 | MULLD, dst, src1, src2, o, r);
1555}
1556
1557
1558void Assembler::divd(Register dst, Register src1, Register src2, OEBit o,
1559                     RCBit r) {
1560  xo_form(EXT2 | DIVD, dst, src1, src2, o, r);
1561}
1562
1563
1564void Assembler::divdu(Register dst, Register src1, Register src2, OEBit o,
1565                      RCBit r) {
1566  xo_form(EXT2 | DIVDU, dst, src1, src2, o, r);
1567}
1568
1569void Assembler::modsd(Register rt, Register ra, Register rb) {
1570  x_form(EXT2 | MODSD, ra, rt, rb, LeaveRC);
1571}
1572
1573void Assembler::modud(Register rt, Register ra, Register rb) {
1574  x_form(EXT2 | MODUD, ra, rt, rb, LeaveRC);
1575}
1576#endif
1577
1578
1579// Function descriptor for AIX.
1580// Code address skips the function descriptor "header".
1581// TOC and static chain are ignored and set to 0.
1582void Assembler::function_descriptor() {
1583  if (ABI_USES_FUNCTION_DESCRIPTORS) {
1584    Label instructions;
1585    DCHECK(pc_offset() == 0);
1586    emit_label_addr(&instructions);
1587    dp(0);
1588    dp(0);
1589    bind(&instructions);
1590  }
1591}
1592
1593
1594int Assembler::instructions_required_for_mov(Register dst,
1595                                             const Operand& src) const {
1596  bool canOptimize =
1597      !(src.must_output_reloc_info(this) || is_trampoline_pool_blocked());
1598  if (use_constant_pool_for_mov(dst, src, canOptimize)) {
1599    if (ConstantPoolAccessIsInOverflow()) {
1600      return kMovInstructionsConstantPool + 1;
1601    }
1602    return kMovInstructionsConstantPool;
1603  }
1604  DCHECK(!canOptimize);
1605  return kMovInstructionsNoConstantPool;
1606}
1607
1608
1609bool Assembler::use_constant_pool_for_mov(Register dst, const Operand& src,
1610                                          bool canOptimize) const {
1611  if (!FLAG_enable_embedded_constant_pool || !is_constant_pool_available()) {
1612    // If there is no constant pool available, we must use a mov
1613    // immediate sequence.
1614    return false;
1615  }
1616
1617  intptr_t value = src.immediate();
1618#if V8_TARGET_ARCH_PPC64
1619  bool allowOverflow = !((canOptimize && is_int32(value)) || dst.is(r0));
1620#else
1621  bool allowOverflow = !(canOptimize || dst.is(r0));
1622#endif
1623  if (canOptimize && is_int16(value)) {
1624    // Prefer a single-instruction load-immediate.
1625    return false;
1626  }
1627  if (!allowOverflow && ConstantPoolAccessIsInOverflow()) {
1628    // Prefer non-relocatable two-instruction bitwise-mov32 over
1629    // overflow sequence.
1630    return false;
1631  }
1632
1633  return true;
1634}
1635
1636
1637void Assembler::EnsureSpaceFor(int space_needed) {
1638  if (buffer_space() <= (kGap + space_needed)) {
1639    GrowBuffer(space_needed);
1640  }
1641}
1642
1643
1644bool Operand::must_output_reloc_info(const Assembler* assembler) const {
1645  if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
1646    if (assembler != NULL && assembler->predictable_code_size()) return true;
1647    return assembler->serializer_enabled();
1648  } else if (RelocInfo::IsNone(rmode_)) {
1649    return false;
1650  }
1651  return true;
1652}
1653
1654
1655// Primarily used for loading constants
1656// This should really move to be in macro-assembler as it
1657// is really a pseudo instruction
1658// Some usages of this intend for a FIXED_SEQUENCE to be used
1659// Todo - break this dependency so we can optimize mov() in general
1660// and only use the generic version when we require a fixed sequence
1661void Assembler::mov(Register dst, const Operand& src) {
1662  intptr_t value = src.immediate();
1663  bool relocatable = src.must_output_reloc_info(this);
1664  bool canOptimize;
1665
1666  canOptimize =
1667      !(relocatable || (is_trampoline_pool_blocked() && !is_int16(value)));
1668
1669  if (use_constant_pool_for_mov(dst, src, canOptimize)) {
1670    DCHECK(is_constant_pool_available());
1671    if (relocatable) {
1672      RecordRelocInfo(src.rmode_);
1673    }
1674    ConstantPoolEntry::Access access = ConstantPoolAddEntry(src.rmode_, value);
1675#if V8_TARGET_ARCH_PPC64
1676    if (access == ConstantPoolEntry::OVERFLOWED) {
1677      addis(dst, kConstantPoolRegister, Operand::Zero());
1678      ld(dst, MemOperand(dst, 0));
1679    } else {
1680      ld(dst, MemOperand(kConstantPoolRegister, 0));
1681    }
1682#else
1683    if (access == ConstantPoolEntry::OVERFLOWED) {
1684      addis(dst, kConstantPoolRegister, Operand::Zero());
1685      lwz(dst, MemOperand(dst, 0));
1686    } else {
1687      lwz(dst, MemOperand(kConstantPoolRegister, 0));
1688    }
1689#endif
1690    return;
1691  }
1692
1693  if (canOptimize) {
1694    if (is_int16(value)) {
1695      li(dst, Operand(value));
1696    } else {
1697      uint16_t u16;
1698#if V8_TARGET_ARCH_PPC64
1699      if (is_int32(value)) {
1700#endif
1701        lis(dst, Operand(value >> 16));
1702#if V8_TARGET_ARCH_PPC64
1703      } else {
1704        if (is_int48(value)) {
1705          li(dst, Operand(value >> 32));
1706        } else {
1707          lis(dst, Operand(value >> 48));
1708          u16 = ((value >> 32) & 0xffff);
1709          if (u16) {
1710            ori(dst, dst, Operand(u16));
1711          }
1712        }
1713        sldi(dst, dst, Operand(32));
1714        u16 = ((value >> 16) & 0xffff);
1715        if (u16) {
1716          oris(dst, dst, Operand(u16));
1717        }
1718      }
1719#endif
1720      u16 = (value & 0xffff);
1721      if (u16) {
1722        ori(dst, dst, Operand(u16));
1723      }
1724    }
1725    return;
1726  }
1727
1728  DCHECK(!canOptimize);
1729  if (relocatable) {
1730    RecordRelocInfo(src.rmode_);
1731  }
1732  bitwise_mov(dst, value);
1733}
1734
1735
1736void Assembler::bitwise_mov(Register dst, intptr_t value) {
1737    BlockTrampolinePoolScope block_trampoline_pool(this);
1738#if V8_TARGET_ARCH_PPC64
1739    int32_t hi_32 = static_cast<int32_t>(value >> 32);
1740    int32_t lo_32 = static_cast<int32_t>(value);
1741    int hi_word = static_cast<int>(hi_32 >> 16);
1742    int lo_word = static_cast<int>(hi_32 & 0xffff);
1743    lis(dst, Operand(SIGN_EXT_IMM16(hi_word)));
1744    ori(dst, dst, Operand(lo_word));
1745    sldi(dst, dst, Operand(32));
1746    hi_word = static_cast<int>(((lo_32 >> 16) & 0xffff));
1747    lo_word = static_cast<int>(lo_32 & 0xffff);
1748    oris(dst, dst, Operand(hi_word));
1749    ori(dst, dst, Operand(lo_word));
1750#else
1751    int hi_word = static_cast<int>(value >> 16);
1752    int lo_word = static_cast<int>(value & 0xffff);
1753    lis(dst, Operand(SIGN_EXT_IMM16(hi_word)));
1754    ori(dst, dst, Operand(lo_word));
1755#endif
1756}
1757
1758
1759void Assembler::bitwise_mov32(Register dst, int32_t value) {
1760  BlockTrampolinePoolScope block_trampoline_pool(this);
1761  int hi_word = static_cast<int>(value >> 16);
1762  int lo_word = static_cast<int>(value & 0xffff);
1763  lis(dst, Operand(SIGN_EXT_IMM16(hi_word)));
1764  ori(dst, dst, Operand(lo_word));
1765}
1766
1767
1768void Assembler::bitwise_add32(Register dst, Register src, int32_t value) {
1769  BlockTrampolinePoolScope block_trampoline_pool(this);
1770  if (is_int16(value)) {
1771    addi(dst, src, Operand(value));
1772    nop();
1773  } else {
1774    int hi_word = static_cast<int>(value >> 16);
1775    int lo_word = static_cast<int>(value & 0xffff);
1776    if (lo_word & 0x8000) hi_word++;
1777    addis(dst, src, Operand(SIGN_EXT_IMM16(hi_word)));
1778    addic(dst, dst, Operand(SIGN_EXT_IMM16(lo_word)));
1779  }
1780}
1781
1782
1783void Assembler::mov_label_offset(Register dst, Label* label) {
1784  int position = link(label);
1785  if (label->is_bound()) {
1786    // Load the position of the label relative to the generated code object.
1787    mov(dst, Operand(position + Code::kHeaderSize - kHeapObjectTag));
1788  } else {
1789    // Encode internal reference to unbound label. We use a dummy opcode
1790    // such that it won't collide with any opcode that might appear in the
1791    // label's chain.  Encode the destination register in the 2nd instruction.
1792    int link = position - pc_offset();
1793    DCHECK_EQ(0, link & 3);
1794    link >>= 2;
1795    DCHECK(is_int26(link));
1796
1797    // When the label is bound, these instructions will be patched
1798    // with a 2 instruction mov sequence that will load the
1799    // destination register with the position of the label from the
1800    // beginning of the code.
1801    //
1802    // target_at extracts the link and target_at_put patches the instructions.
1803    BlockTrampolinePoolScope block_trampoline_pool(this);
1804    emit(kUnboundMovLabelOffsetOpcode | (link & kImm26Mask));
1805    emit(dst.code());
1806  }
1807}
1808
1809
1810void Assembler::add_label_offset(Register dst, Register base, Label* label,
1811                                 int delta) {
1812  int position = link(label);
1813  if (label->is_bound()) {
1814    // dst = base + position + delta
1815    position += delta;
1816    bitwise_add32(dst, base, position);
1817  } else {
1818    // Encode internal reference to unbound label. We use a dummy opcode
1819    // such that it won't collide with any opcode that might appear in the
1820    // label's chain.  Encode the operands in the 2nd instruction.
1821    int link = position - pc_offset();
1822    DCHECK_EQ(0, link & 3);
1823    link >>= 2;
1824    DCHECK(is_int26(link));
1825    DCHECK(is_int16(delta));
1826
1827    BlockTrampolinePoolScope block_trampoline_pool(this);
1828    emit(kUnboundAddLabelOffsetOpcode | (link & kImm26Mask));
1829    emit(dst.code() * B21 | base.code() * B16 | (delta & kImm16Mask));
1830  }
1831}
1832
1833
1834void Assembler::mov_label_addr(Register dst, Label* label) {
1835  CheckBuffer();
1836  RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
1837  int position = link(label);
1838  if (label->is_bound()) {
1839    // Keep internal references relative until EmitRelocations.
1840    bitwise_mov(dst, position);
1841  } else {
1842    // Encode internal reference to unbound label. We use a dummy opcode
1843    // such that it won't collide with any opcode that might appear in the
1844    // label's chain.  Encode the destination register in the 2nd instruction.
1845    int link = position - pc_offset();
1846    DCHECK_EQ(0, link & 3);
1847    link >>= 2;
1848    DCHECK(is_int26(link));
1849
1850    // When the label is bound, these instructions will be patched
1851    // with a multi-instruction mov sequence that will load the
1852    // destination register with the address of the label.
1853    //
1854    // target_at extracts the link and target_at_put patches the instructions.
1855    BlockTrampolinePoolScope block_trampoline_pool(this);
1856    emit(kUnboundMovLabelAddrOpcode | (link & kImm26Mask));
1857    emit(dst.code());
1858    DCHECK(kMovInstructionsNoConstantPool >= 2);
1859    for (int i = 0; i < kMovInstructionsNoConstantPool - 2; i++) nop();
1860  }
1861}
1862
1863
1864void Assembler::emit_label_addr(Label* label) {
1865  CheckBuffer();
1866  RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
1867  int position = link(label);
1868  if (label->is_bound()) {
1869    // Keep internal references relative until EmitRelocations.
1870    dp(position);
1871  } else {
1872    // Encode internal reference to unbound label. We use a dummy opcode
1873    // such that it won't collide with any opcode that might appear in the
1874    // label's chain.
1875    int link = position - pc_offset();
1876    DCHECK_EQ(0, link & 3);
1877    link >>= 2;
1878    DCHECK(is_int26(link));
1879
1880    // When the label is bound, the instruction(s) will be patched
1881    // as a jump table entry containing the label address.  target_at extracts
1882    // the link and target_at_put patches the instruction(s).
1883    BlockTrampolinePoolScope block_trampoline_pool(this);
1884    emit(kUnboundJumpTableEntryOpcode | (link & kImm26Mask));
1885#if V8_TARGET_ARCH_PPC64
1886    nop();
1887#endif
1888  }
1889}
1890
1891
1892// Special register instructions
1893void Assembler::crxor(int bt, int ba, int bb) {
1894  emit(EXT1 | CRXOR | bt * B21 | ba * B16 | bb * B11);
1895}
1896
1897
1898void Assembler::creqv(int bt, int ba, int bb) {
1899  emit(EXT1 | CREQV | bt * B21 | ba * B16 | bb * B11);
1900}
1901
1902
1903void Assembler::mflr(Register dst) {
1904  emit(EXT2 | MFSPR | dst.code() * B21 | 256 << 11);  // Ignore RC bit
1905}
1906
1907
1908void Assembler::mtlr(Register src) {
1909  emit(EXT2 | MTSPR | src.code() * B21 | 256 << 11);  // Ignore RC bit
1910}
1911
1912
1913void Assembler::mtctr(Register src) {
1914  emit(EXT2 | MTSPR | src.code() * B21 | 288 << 11);  // Ignore RC bit
1915}
1916
1917
1918void Assembler::mtxer(Register src) {
1919  emit(EXT2 | MTSPR | src.code() * B21 | 32 << 11);
1920}
1921
1922
1923void Assembler::mcrfs(CRegister cr, FPSCRBit bit) {
1924  DCHECK(static_cast<int>(bit) < 32);
1925  int bf = cr.code();
1926  int bfa = bit / CRWIDTH;
1927  emit(EXT4 | MCRFS | bf * B23 | bfa * B18);
1928}
1929
1930
1931void Assembler::mfcr(Register dst) { emit(EXT2 | MFCR | dst.code() * B21); }
1932
1933
1934#if V8_TARGET_ARCH_PPC64
1935void Assembler::mffprd(Register dst, DoubleRegister src) {
1936  emit(EXT2 | MFVSRD | src.code() * B21 | dst.code() * B16);
1937}
1938
1939
1940void Assembler::mffprwz(Register dst, DoubleRegister src) {
1941  emit(EXT2 | MFVSRWZ | src.code() * B21 | dst.code() * B16);
1942}
1943
1944
1945void Assembler::mtfprd(DoubleRegister dst, Register src) {
1946  emit(EXT2 | MTVSRD | dst.code() * B21 | src.code() * B16);
1947}
1948
1949
1950void Assembler::mtfprwz(DoubleRegister dst, Register src) {
1951  emit(EXT2 | MTVSRWZ | dst.code() * B21 | src.code() * B16);
1952}
1953
1954
1955void Assembler::mtfprwa(DoubleRegister dst, Register src) {
1956  emit(EXT2 | MTVSRWA | dst.code() * B21 | src.code() * B16);
1957}
1958#endif
1959
1960
1961// Exception-generating instructions and debugging support.
1962// Stops with a non-negative code less than kNumOfWatchedStops support
1963// enabling/disabling and a counter feature. See simulator-ppc.h .
1964void Assembler::stop(const char* msg, Condition cond, int32_t code,
1965                     CRegister cr) {
1966  if (cond != al) {
1967    Label skip;
1968    b(NegateCondition(cond), &skip, cr);
1969    bkpt(0);
1970    bind(&skip);
1971  } else {
1972    bkpt(0);
1973  }
1974}
1975
1976
1977void Assembler::bkpt(uint32_t imm16) { emit(0x7d821008); }
1978
1979
1980void Assembler::dcbf(Register ra, Register rb) {
1981  emit(EXT2 | DCBF | ra.code() * B16 | rb.code() * B11);
1982}
1983
1984
1985void Assembler::sync() { emit(EXT2 | SYNC); }
1986
1987
1988void Assembler::lwsync() { emit(EXT2 | SYNC | 1 * B21); }
1989
1990
1991void Assembler::icbi(Register ra, Register rb) {
1992  emit(EXT2 | ICBI | ra.code() * B16 | rb.code() * B11);
1993}
1994
1995
1996void Assembler::isync() { emit(EXT1 | ISYNC); }
1997
1998
1999// Floating point support
2000
2001void Assembler::lfd(const DoubleRegister frt, const MemOperand& src) {
2002  int offset = src.offset();
2003  Register ra = src.ra();
2004  DCHECK(!ra.is(r0));
2005  CHECK(is_int16(offset));
2006  int imm16 = offset & kImm16Mask;
2007  // could be x_form instruction with some casting magic
2008  emit(LFD | frt.code() * B21 | ra.code() * B16 | imm16);
2009}
2010
2011
2012void Assembler::lfdu(const DoubleRegister frt, const MemOperand& src) {
2013  int offset = src.offset();
2014  Register ra = src.ra();
2015  DCHECK(!ra.is(r0));
2016  CHECK(is_int16(offset));
2017  int imm16 = offset & kImm16Mask;
2018  // could be x_form instruction with some casting magic
2019  emit(LFDU | frt.code() * B21 | ra.code() * B16 | imm16);
2020}
2021
2022
2023void Assembler::lfdx(const DoubleRegister frt, const MemOperand& src) {
2024  Register ra = src.ra();
2025  Register rb = src.rb();
2026  DCHECK(!ra.is(r0));
2027  emit(EXT2 | LFDX | frt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
2028       LeaveRC);
2029}
2030
2031
2032void Assembler::lfdux(const DoubleRegister frt, const MemOperand& src) {
2033  Register ra = src.ra();
2034  Register rb = src.rb();
2035  DCHECK(!ra.is(r0));
2036  emit(EXT2 | LFDUX | frt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
2037       LeaveRC);
2038}
2039
2040
2041void Assembler::lfs(const DoubleRegister frt, const MemOperand& src) {
2042  int offset = src.offset();
2043  Register ra = src.ra();
2044  CHECK(is_int16(offset));
2045  DCHECK(!ra.is(r0));
2046  int imm16 = offset & kImm16Mask;
2047  // could be x_form instruction with some casting magic
2048  emit(LFS | frt.code() * B21 | ra.code() * B16 | imm16);
2049}
2050
2051
2052void Assembler::lfsu(const DoubleRegister frt, const MemOperand& src) {
2053  int offset = src.offset();
2054  Register ra = src.ra();
2055  CHECK(is_int16(offset));
2056  DCHECK(!ra.is(r0));
2057  int imm16 = offset & kImm16Mask;
2058  // could be x_form instruction with some casting magic
2059  emit(LFSU | frt.code() * B21 | ra.code() * B16 | imm16);
2060}
2061
2062
2063void Assembler::lfsx(const DoubleRegister frt, const MemOperand& src) {
2064  Register ra = src.ra();
2065  Register rb = src.rb();
2066  DCHECK(!ra.is(r0));
2067  emit(EXT2 | LFSX | frt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
2068       LeaveRC);
2069}
2070
2071
2072void Assembler::lfsux(const DoubleRegister frt, const MemOperand& src) {
2073  Register ra = src.ra();
2074  Register rb = src.rb();
2075  DCHECK(!ra.is(r0));
2076  emit(EXT2 | LFSUX | frt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
2077       LeaveRC);
2078}
2079
2080
2081void Assembler::stfd(const DoubleRegister frs, const MemOperand& src) {
2082  int offset = src.offset();
2083  Register ra = src.ra();
2084  CHECK(is_int16(offset));
2085  DCHECK(!ra.is(r0));
2086  int imm16 = offset & kImm16Mask;
2087  // could be x_form instruction with some casting magic
2088  emit(STFD | frs.code() * B21 | ra.code() * B16 | imm16);
2089}
2090
2091
2092void Assembler::stfdu(const DoubleRegister frs, const MemOperand& src) {
2093  int offset = src.offset();
2094  Register ra = src.ra();
2095  CHECK(is_int16(offset));
2096  DCHECK(!ra.is(r0));
2097  int imm16 = offset & kImm16Mask;
2098  // could be x_form instruction with some casting magic
2099  emit(STFDU | frs.code() * B21 | ra.code() * B16 | imm16);
2100}
2101
2102
2103void Assembler::stfdx(const DoubleRegister frs, const MemOperand& src) {
2104  Register ra = src.ra();
2105  Register rb = src.rb();
2106  DCHECK(!ra.is(r0));
2107  emit(EXT2 | STFDX | frs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
2108       LeaveRC);
2109}
2110
2111
2112void Assembler::stfdux(const DoubleRegister frs, const MemOperand& src) {
2113  Register ra = src.ra();
2114  Register rb = src.rb();
2115  DCHECK(!ra.is(r0));
2116  emit(EXT2 | STFDUX | frs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
2117       LeaveRC);
2118}
2119
2120
2121void Assembler::stfs(const DoubleRegister frs, const MemOperand& src) {
2122  int offset = src.offset();
2123  Register ra = src.ra();
2124  CHECK(is_int16(offset));
2125  DCHECK(!ra.is(r0));
2126  int imm16 = offset & kImm16Mask;
2127  // could be x_form instruction with some casting magic
2128  emit(STFS | frs.code() * B21 | ra.code() * B16 | imm16);
2129}
2130
2131
2132void Assembler::stfsu(const DoubleRegister frs, const MemOperand& src) {
2133  int offset = src.offset();
2134  Register ra = src.ra();
2135  CHECK(is_int16(offset));
2136  DCHECK(!ra.is(r0));
2137  int imm16 = offset & kImm16Mask;
2138  // could be x_form instruction with some casting magic
2139  emit(STFSU | frs.code() * B21 | ra.code() * B16 | imm16);
2140}
2141
2142
2143void Assembler::stfsx(const DoubleRegister frs, const MemOperand& src) {
2144  Register ra = src.ra();
2145  Register rb = src.rb();
2146  DCHECK(!ra.is(r0));
2147  emit(EXT2 | STFSX | frs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
2148       LeaveRC);
2149}
2150
2151
2152void Assembler::stfsux(const DoubleRegister frs, const MemOperand& src) {
2153  Register ra = src.ra();
2154  Register rb = src.rb();
2155  DCHECK(!ra.is(r0));
2156  emit(EXT2 | STFSUX | frs.code() * B21 | ra.code() * B16 | rb.code() * B11 |
2157       LeaveRC);
2158}
2159
2160
2161void Assembler::fsub(const DoubleRegister frt, const DoubleRegister fra,
2162                     const DoubleRegister frb, RCBit rc) {
2163  a_form(EXT4 | FSUB, frt, fra, frb, rc);
2164}
2165
2166
2167void Assembler::fadd(const DoubleRegister frt, const DoubleRegister fra,
2168                     const DoubleRegister frb, RCBit rc) {
2169  a_form(EXT4 | FADD, frt, fra, frb, rc);
2170}
2171
2172
2173void Assembler::fmul(const DoubleRegister frt, const DoubleRegister fra,
2174                     const DoubleRegister frc, RCBit rc) {
2175  emit(EXT4 | FMUL | frt.code() * B21 | fra.code() * B16 | frc.code() * B6 |
2176       rc);
2177}
2178
2179
2180void Assembler::fdiv(const DoubleRegister frt, const DoubleRegister fra,
2181                     const DoubleRegister frb, RCBit rc) {
2182  a_form(EXT4 | FDIV, frt, fra, frb, rc);
2183}
2184
2185
2186void Assembler::fcmpu(const DoubleRegister fra, const DoubleRegister frb,
2187                      CRegister cr) {
2188  DCHECK(cr.code() >= 0 && cr.code() <= 7);
2189  emit(EXT4 | FCMPU | cr.code() * B23 | fra.code() * B16 | frb.code() * B11);
2190}
2191
2192
2193void Assembler::fmr(const DoubleRegister frt, const DoubleRegister frb,
2194                    RCBit rc) {
2195  emit(EXT4 | FMR | frt.code() * B21 | frb.code() * B11 | rc);
2196}
2197
2198
2199void Assembler::fctiwz(const DoubleRegister frt, const DoubleRegister frb) {
2200  emit(EXT4 | FCTIWZ | frt.code() * B21 | frb.code() * B11);
2201}
2202
2203
2204void Assembler::fctiw(const DoubleRegister frt, const DoubleRegister frb) {
2205  emit(EXT4 | FCTIW | frt.code() * B21 | frb.code() * B11);
2206}
2207
2208
2209void Assembler::frin(const DoubleRegister frt, const DoubleRegister frb,
2210                     RCBit rc) {
2211  emit(EXT4 | FRIN | frt.code() * B21 | frb.code() * B11 | rc);
2212}
2213
2214
2215void Assembler::friz(const DoubleRegister frt, const DoubleRegister frb,
2216                     RCBit rc) {
2217  emit(EXT4 | FRIZ | frt.code() * B21 | frb.code() * B11 | rc);
2218}
2219
2220
2221void Assembler::frip(const DoubleRegister frt, const DoubleRegister frb,
2222                     RCBit rc) {
2223  emit(EXT4 | FRIP | frt.code() * B21 | frb.code() * B11 | rc);
2224}
2225
2226
2227void Assembler::frim(const DoubleRegister frt, const DoubleRegister frb,
2228                     RCBit rc) {
2229  emit(EXT4 | FRIM | frt.code() * B21 | frb.code() * B11 | rc);
2230}
2231
2232
2233void Assembler::frsp(const DoubleRegister frt, const DoubleRegister frb,
2234                     RCBit rc) {
2235  emit(EXT4 | FRSP | frt.code() * B21 | frb.code() * B11 | rc);
2236}
2237
2238
2239void Assembler::fcfid(const DoubleRegister frt, const DoubleRegister frb,
2240                      RCBit rc) {
2241  emit(EXT4 | FCFID | frt.code() * B21 | frb.code() * B11 | rc);
2242}
2243
2244
2245void Assembler::fcfidu(const DoubleRegister frt, const DoubleRegister frb,
2246                       RCBit rc) {
2247  emit(EXT4 | FCFIDU | frt.code() * B21 | frb.code() * B11 | rc);
2248}
2249
2250
2251void Assembler::fcfidus(const DoubleRegister frt, const DoubleRegister frb,
2252                        RCBit rc) {
2253  emit(EXT3 | FCFIDUS | frt.code() * B21 | frb.code() * B11 | rc);
2254}
2255
2256
2257void Assembler::fcfids(const DoubleRegister frt, const DoubleRegister frb,
2258                       RCBit rc) {
2259  emit(EXT3 | FCFIDS | frt.code() * B21 | frb.code() * B11 | rc);
2260}
2261
2262
2263void Assembler::fctid(const DoubleRegister frt, const DoubleRegister frb,
2264                      RCBit rc) {
2265  emit(EXT4 | FCTID | frt.code() * B21 | frb.code() * B11 | rc);
2266}
2267
2268
2269void Assembler::fctidz(const DoubleRegister frt, const DoubleRegister frb,
2270                       RCBit rc) {
2271  emit(EXT4 | FCTIDZ | frt.code() * B21 | frb.code() * B11 | rc);
2272}
2273
2274
2275void Assembler::fctidu(const DoubleRegister frt, const DoubleRegister frb,
2276                       RCBit rc) {
2277  emit(EXT4 | FCTIDU | frt.code() * B21 | frb.code() * B11 | rc);
2278}
2279
2280
2281void Assembler::fctiduz(const DoubleRegister frt, const DoubleRegister frb,
2282                        RCBit rc) {
2283  emit(EXT4 | FCTIDUZ | frt.code() * B21 | frb.code() * B11 | rc);
2284}
2285
2286
2287void Assembler::fsel(const DoubleRegister frt, const DoubleRegister fra,
2288                     const DoubleRegister frc, const DoubleRegister frb,
2289                     RCBit rc) {
2290  emit(EXT4 | FSEL | frt.code() * B21 | fra.code() * B16 | frb.code() * B11 |
2291       frc.code() * B6 | rc);
2292}
2293
2294
2295void Assembler::fneg(const DoubleRegister frt, const DoubleRegister frb,
2296                     RCBit rc) {
2297  emit(EXT4 | FNEG | frt.code() * B21 | frb.code() * B11 | rc);
2298}
2299
2300
2301void Assembler::mtfsb0(FPSCRBit bit, RCBit rc) {
2302  DCHECK(static_cast<int>(bit) < 32);
2303  int bt = bit;
2304  emit(EXT4 | MTFSB0 | bt * B21 | rc);
2305}
2306
2307
2308void Assembler::mtfsb1(FPSCRBit bit, RCBit rc) {
2309  DCHECK(static_cast<int>(bit) < 32);
2310  int bt = bit;
2311  emit(EXT4 | MTFSB1 | bt * B21 | rc);
2312}
2313
2314
2315void Assembler::mtfsfi(int bf, int immediate, RCBit rc) {
2316  emit(EXT4 | MTFSFI | bf * B23 | immediate * B12 | rc);
2317}
2318
2319
2320void Assembler::mffs(const DoubleRegister frt, RCBit rc) {
2321  emit(EXT4 | MFFS | frt.code() * B21 | rc);
2322}
2323
2324
2325void Assembler::mtfsf(const DoubleRegister frb, bool L, int FLM, bool W,
2326                      RCBit rc) {
2327  emit(EXT4 | MTFSF | frb.code() * B11 | W * B16 | FLM * B17 | L * B25 | rc);
2328}
2329
2330
2331void Assembler::fsqrt(const DoubleRegister frt, const DoubleRegister frb,
2332                      RCBit rc) {
2333  emit(EXT4 | FSQRT | frt.code() * B21 | frb.code() * B11 | rc);
2334}
2335
2336
2337void Assembler::fabs(const DoubleRegister frt, const DoubleRegister frb,
2338                     RCBit rc) {
2339  emit(EXT4 | FABS | frt.code() * B21 | frb.code() * B11 | rc);
2340}
2341
2342
2343void Assembler::fmadd(const DoubleRegister frt, const DoubleRegister fra,
2344                      const DoubleRegister frc, const DoubleRegister frb,
2345                      RCBit rc) {
2346  emit(EXT4 | FMADD | frt.code() * B21 | fra.code() * B16 | frb.code() * B11 |
2347       frc.code() * B6 | rc);
2348}
2349
2350
2351void Assembler::fmsub(const DoubleRegister frt, const DoubleRegister fra,
2352                      const DoubleRegister frc, const DoubleRegister frb,
2353                      RCBit rc) {
2354  emit(EXT4 | FMSUB | frt.code() * B21 | fra.code() * B16 | frb.code() * B11 |
2355       frc.code() * B6 | rc);
2356}
2357
2358// Support for VSX instructions
2359
2360void Assembler::xsadddp(const DoubleRegister frt, const DoubleRegister fra,
2361                        const DoubleRegister frb) {
2362  xx3_form(EXT6 | XSADDDP, frt, fra, frb);
2363}
2364void Assembler::xssubdp(const DoubleRegister frt, const DoubleRegister fra,
2365                        const DoubleRegister frb) {
2366  xx3_form(EXT6 | XSSUBDP, frt, fra, frb);
2367}
2368void Assembler::xsdivdp(const DoubleRegister frt, const DoubleRegister fra,
2369                        const DoubleRegister frb) {
2370  xx3_form(EXT6 | XSDIVDP, frt, fra, frb);
2371}
2372void Assembler::xsmuldp(const DoubleRegister frt, const DoubleRegister fra,
2373                        const DoubleRegister frb) {
2374  xx3_form(EXT6 | XSMULDP, frt, fra, frb);
2375}
2376
2377// Pseudo instructions.
2378void Assembler::nop(int type) {
2379  Register reg = r0;
2380  switch (type) {
2381    case NON_MARKING_NOP:
2382      reg = r0;
2383      break;
2384    case GROUP_ENDING_NOP:
2385      reg = r2;
2386      break;
2387    case DEBUG_BREAK_NOP:
2388      reg = r3;
2389      break;
2390    default:
2391      UNIMPLEMENTED();
2392  }
2393
2394  ori(reg, reg, Operand::Zero());
2395}
2396
2397
2398bool Assembler::IsNop(Instr instr, int type) {
2399  int reg = 0;
2400  switch (type) {
2401    case NON_MARKING_NOP:
2402      reg = 0;
2403      break;
2404    case GROUP_ENDING_NOP:
2405      reg = 2;
2406      break;
2407    case DEBUG_BREAK_NOP:
2408      reg = 3;
2409      break;
2410    default:
2411      UNIMPLEMENTED();
2412  }
2413  return instr == (ORI | reg * B21 | reg * B16);
2414}
2415
2416
2417void Assembler::GrowBuffer(int needed) {
2418  if (!own_buffer_) FATAL("external code buffer is too small");
2419
2420  // Compute new buffer size.
2421  CodeDesc desc;  // the new buffer
2422  if (buffer_size_ < 4 * KB) {
2423    desc.buffer_size = 4 * KB;
2424  } else if (buffer_size_ < 1 * MB) {
2425    desc.buffer_size = 2 * buffer_size_;
2426  } else {
2427    desc.buffer_size = buffer_size_ + 1 * MB;
2428  }
2429  int space = buffer_space() + (desc.buffer_size - buffer_size_);
2430  if (space < needed) {
2431    desc.buffer_size += needed - space;
2432  }
2433  CHECK_GT(desc.buffer_size, 0);  // no overflow
2434
2435  // Set up new buffer.
2436  desc.buffer = NewArray<byte>(desc.buffer_size);
2437  desc.origin = this;
2438
2439  desc.instr_size = pc_offset();
2440  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
2441
2442  // Copy the data.
2443  intptr_t pc_delta = desc.buffer - buffer_;
2444  intptr_t rc_delta =
2445      (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2446  memmove(desc.buffer, buffer_, desc.instr_size);
2447  memmove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
2448          desc.reloc_size);
2449
2450  // Switch buffers.
2451  DeleteArray(buffer_);
2452  buffer_ = desc.buffer;
2453  buffer_size_ = desc.buffer_size;
2454  pc_ += pc_delta;
2455  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2456                               reloc_info_writer.last_pc() + pc_delta);
2457
2458  // Nothing else to do here since we keep all internal references and
2459  // deferred relocation entries relative to the buffer (until
2460  // EmitRelocations).
2461}
2462
2463
2464void Assembler::db(uint8_t data) {
2465  CheckBuffer();
2466  *reinterpret_cast<uint8_t*>(pc_) = data;
2467  pc_ += sizeof(uint8_t);
2468}
2469
2470
2471void Assembler::dd(uint32_t data) {
2472  CheckBuffer();
2473  *reinterpret_cast<uint32_t*>(pc_) = data;
2474  pc_ += sizeof(uint32_t);
2475}
2476
2477
2478void Assembler::dq(uint64_t value) {
2479  CheckBuffer();
2480  *reinterpret_cast<uint64_t*>(pc_) = value;
2481  pc_ += sizeof(uint64_t);
2482}
2483
2484
2485void Assembler::dp(uintptr_t data) {
2486  CheckBuffer();
2487  *reinterpret_cast<uintptr_t*>(pc_) = data;
2488  pc_ += sizeof(uintptr_t);
2489}
2490
2491
2492void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2493  if (RelocInfo::IsNone(rmode) ||
2494      // Don't record external references unless the heap will be serialized.
2495      (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() &&
2496       !emit_debug_code())) {
2497    return;
2498  }
2499  if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2500    data = RecordedAstId().ToInt();
2501    ClearRecordedAstId();
2502  }
2503  DeferredRelocInfo rinfo(pc_offset(), rmode, data);
2504  relocations_.push_back(rinfo);
2505}
2506
2507
2508void Assembler::EmitRelocations() {
2509  EnsureSpaceFor(relocations_.size() * kMaxRelocSize);
2510
2511  for (std::vector<DeferredRelocInfo>::iterator it = relocations_.begin();
2512       it != relocations_.end(); it++) {
2513    RelocInfo::Mode rmode = it->rmode();
2514    Address pc = buffer_ + it->position();
2515    Code* code = NULL;
2516    RelocInfo rinfo(isolate(), pc, rmode, it->data(), code);
2517
2518    // Fix up internal references now that they are guaranteed to be bound.
2519    if (RelocInfo::IsInternalReference(rmode)) {
2520      // Jump table entry
2521      intptr_t pos = reinterpret_cast<intptr_t>(Memory::Address_at(pc));
2522      Memory::Address_at(pc) = buffer_ + pos;
2523    } else if (RelocInfo::IsInternalReferenceEncoded(rmode)) {
2524      // mov sequence
2525      intptr_t pos = reinterpret_cast<intptr_t>(target_address_at(pc, code));
2526      set_target_address_at(isolate(), pc, code, buffer_ + pos,
2527                            SKIP_ICACHE_FLUSH);
2528    }
2529
2530    reloc_info_writer.Write(&rinfo);
2531  }
2532}
2533
2534
2535void Assembler::BlockTrampolinePoolFor(int instructions) {
2536  BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
2537}
2538
2539
2540void Assembler::CheckTrampolinePool() {
2541  // Some small sequences of instructions must not be broken up by the
2542  // insertion of a trampoline pool; such sequences are protected by setting
2543  // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
2544  // which are both checked here. Also, recursive calls to CheckTrampolinePool
2545  // are blocked by trampoline_pool_blocked_nesting_.
2546  if (trampoline_pool_blocked_nesting_ > 0) return;
2547  if (pc_offset() < no_trampoline_pool_before_) {
2548    next_trampoline_check_ = no_trampoline_pool_before_;
2549    return;
2550  }
2551
2552  DCHECK(!trampoline_emitted_);
2553  if (tracked_branch_count_ > 0) {
2554    int size = tracked_branch_count_ * kInstrSize;
2555
2556    // As we are only going to emit trampoline once, we need to prevent any
2557    // further emission.
2558    trampoline_emitted_ = true;
2559    next_trampoline_check_ = kMaxInt;
2560
2561    // First we emit jump, then we emit trampoline pool.
2562    b(size + kInstrSize, LeaveLK);
2563    for (int i = size; i > 0; i -= kInstrSize) {
2564      b(i, LeaveLK);
2565    }
2566
2567    trampoline_ = Trampoline(pc_offset() - size, tracked_branch_count_);
2568  }
2569}
2570
2571
2572}  // namespace internal
2573}  // namespace v8
2574
2575#endif  // V8_TARGET_ARCH_PPC
2576