• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
46 namespace v8 {
47 namespace internal {
48 
49 // Get the CPU features enabled by the build.
CpuFeaturesImpliedByCompiler()50 static unsigned CpuFeaturesImpliedByCompiler() {
51   unsigned answer = 0;
52   return answer;
53 }
54 
55 
ProbeImpl(bool cross_compile)56 void 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 
PrintTarget()112 void 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 
PrintFeatures()125 void CpuFeatures::PrintFeatures() {
126   printf("FPU=%d\n", CpuFeatures::IsSupported(FPU));
127 }
128 
129 
ToRegister(int num)130 Register 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 
143 const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE |
144                                   1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
145 
146 
IsCodedSpecially()147 bool 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 
IsInConstantPool()156 bool 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 
wasm_memory_reference()164 Address RelocInfo::wasm_memory_reference() {
165   DCHECK(IsWasmMemoryReference(rmode_));
166   return Assembler::target_address_at(pc_, host_);
167 }
168 
wasm_memory_size_reference()169 uint32_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 
wasm_global_reference()175 Address RelocInfo::wasm_global_reference() {
176   DCHECK(IsWasmGlobalReference(rmode_));
177   return Assembler::target_address_at(pc_, host_);
178 }
179 
wasm_function_table_size_reference()180 uint32_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 
unchecked_update_wasm_memory_reference(Address address,ICacheFlushMode flush_mode)186 void 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 
unchecked_update_wasm_size(uint32_t size,ICacheFlushMode flush_mode)191 void 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 
Operand(Handle<Object> handle)201 Operand::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 
MemOperand(Register rn,int32_t offset)217 MemOperand::MemOperand(Register rn, int32_t offset) {
218   ra_ = rn;
219   rb_ = no_reg;
220   offset_ = offset;
221 }
222 
223 
MemOperand(Register ra,Register rb)224 MemOperand::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 
Assembler(Isolate * isolate,void * buffer,int buffer_size)234 Assembler::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 
GetCode(CodeDesc * desc)254 void 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 
Align(int m)273 void 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 
CodeTargetAlign()282 void Assembler::CodeTargetAlign() { Align(8); }
283 
284 
GetCondition(Instr instr)285 Condition 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 
IsLis(Instr instr)298 bool Assembler::IsLis(Instr instr) {
299   return ((instr & kOpcodeMask) == ADDIS) && GetRA(instr).is(r0);
300 }
301 
302 
IsLi(Instr instr)303 bool Assembler::IsLi(Instr instr) {
304   return ((instr & kOpcodeMask) == ADDI) && GetRA(instr).is(r0);
305 }
306 
307 
IsAddic(Instr instr)308 bool Assembler::IsAddic(Instr instr) { return (instr & kOpcodeMask) == ADDIC; }
309 
310 
IsOri(Instr instr)311 bool Assembler::IsOri(Instr instr) { return (instr & kOpcodeMask) == ORI; }
312 
313 
IsBranch(Instr instr)314 bool Assembler::IsBranch(Instr instr) { return ((instr & kOpcodeMask) == BCX); }
315 
316 
GetRA(Instr instr)317 Register Assembler::GetRA(Instr instr) {
318   Register reg;
319   reg.reg_code = Instruction::RAValue(instr);
320   return reg;
321 }
322 
323 
GetRB(Instr instr)324 Register 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)
Is64BitLoadIntoR12(Instr instr1,Instr instr2,Instr instr3,Instr instr4,Instr instr5)333 bool 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)
Is32BitLoadIntoR12(Instr instr1,Instr instr2)347 bool 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 
IsCmpRegister(Instr instr)356 bool Assembler::IsCmpRegister(Instr instr) {
357   return (((instr & kOpcodeMask) == EXT2) &&
358           ((EXT2 | (instr & kExt2OpcodeMask)) == CMP));
359 }
360 
361 
IsRlwinm(Instr instr)362 bool Assembler::IsRlwinm(Instr instr) {
363   return ((instr & kOpcodeMask) == RLWINMX);
364 }
365 
366 
IsAndi(Instr instr)367 bool Assembler::IsAndi(Instr instr) { return ((instr & kOpcodeMask) == ANDIx); }
368 
369 
370 #if V8_TARGET_ARCH_PPC64
IsRldicl(Instr instr)371 bool Assembler::IsRldicl(Instr instr) {
372   return (((instr & kOpcodeMask) == EXT5) &&
373           ((EXT5 | (instr & kExt5OpcodeMask)) == RLDICL));
374 }
375 #endif
376 
377 
IsCmpImmediate(Instr instr)378 bool Assembler::IsCmpImmediate(Instr instr) {
379   return ((instr & kOpcodeMask) == CMPI);
380 }
381 
382 
IsCrSet(Instr instr)383 bool Assembler::IsCrSet(Instr instr) {
384   return (((instr & kOpcodeMask) == EXT1) &&
385           ((EXT1 | (instr & kExt1OpcodeMask)) == CREQV));
386 }
387 
388 
GetCmpImmediateRegister(Instr instr)389 Register Assembler::GetCmpImmediateRegister(Instr instr) {
390   DCHECK(IsCmpImmediate(instr));
391   return GetRA(instr);
392 }
393 
394 
GetCmpImmediateRawImmediate(Instr instr)395 int 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)
413 const int kEndOfChain = -4;
414 
415 
416 // Dummy opcodes for unbound label mov instructions or jump table entries.
417 enum {
418   kUnboundMovLabelOffsetOpcode = 0 << 26,
419   kUnboundAddLabelOffsetOpcode = 1 << 26,
420   kUnboundMovLabelAddrOpcode = 2 << 26,
421   kUnboundJumpTableEntryOpcode = 3 << 26
422 };
423 
424 
target_at(int pos)425 int 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 
target_at_put(int pos,int target_pos,bool * is_branch)456 void 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 
max_reach_from(int pos)536 int 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 
bind_to(Label * L,int pos)558 void 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 
bind(Label * L)590 void Assembler::bind(Label* L) {
591   DCHECK(!L->is_bound());  // label can only be bound once
592   bind_to(L, pc_offset());
593 }
594 
595 
next(Label * L)596 void 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 
is_near(Label * L,Condition cond)608 bool 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 
a_form(Instr instr,DoubleRegister frt,DoubleRegister fra,DoubleRegister frb,RCBit r)619 void 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 
d_form(Instr instr,Register rt,Register ra,const intptr_t val,bool signed_disp)625 void 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 
x_form(Instr instr,Register ra,Register rs,Register rb,RCBit r)644 void 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 
xo_form(Instr instr,Register rt,Register ra,Register rb,OEBit o,RCBit r)649 void 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 
xx3_form(Instr instr,DoubleRegister t,DoubleRegister a,DoubleRegister b)654 void 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 
md_form(Instr instr,Register ra,Register rs,int shift,int maskbit,RCBit r)663 void 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 
mds_form(Instr instr,Register ra,Register rs,Register rb,int maskbit,RCBit r)675 void 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.
get_trampoline_entry()686 int32_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 
link(Label * L)700 int 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 
bclr(BOfield bo,int condition_bit,LKBit lk)724 void Assembler::bclr(BOfield bo, int condition_bit, LKBit lk) {
725   emit(EXT1 | bo | condition_bit * B16 | BCLRX | lk);
726 }
727 
728 
bcctr(BOfield bo,int condition_bit,LKBit lk)729 void 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
blr()735 void Assembler::blr() { bclr(BA, 0, LeaveLK); }
736 
737 
738 // Pseudo op - branch to count register -- used for "jump"
bctr()739 void Assembler::bctr() { bcctr(BA, 0, LeaveLK); }
740 
741 
bctrl()742 void Assembler::bctrl() { bcctr(BA, 0, SetLK); }
743 
744 
bc(int branch_offset,BOfield bo,int condition_bit,LKBit lk)745 void 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 
b(int branch_offset,LKBit lk)752 void 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 
xori(Register dst,Register src,const Operand & imm)759 void Assembler::xori(Register dst, Register src, const Operand& imm) {
760   d_form(XORI, src, dst, imm.imm_, false);
761 }
762 
763 
xoris(Register ra,Register rs,const Operand & imm)764 void Assembler::xoris(Register ra, Register rs, const Operand& imm) {
765   d_form(XORIS, rs, ra, imm.imm_, false);
766 }
767 
768 
xor_(Register dst,Register src1,Register src2,RCBit rc)769 void Assembler::xor_(Register dst, Register src1, Register src2, RCBit rc) {
770   x_form(EXT2 | XORX, dst, src1, src2, rc);
771 }
772 
773 
cntlzw_(Register ra,Register rs,RCBit rc)774 void Assembler::cntlzw_(Register ra, Register rs, RCBit rc) {
775   x_form(EXT2 | CNTLZWX, ra, rs, r0, rc);
776 }
777 
778 
popcntw(Register ra,Register rs)779 void Assembler::popcntw(Register ra, Register rs) {
780   emit(EXT2 | POPCNTW | rs.code() * B21 | ra.code() * B16);
781 }
782 
783 
and_(Register ra,Register rs,Register rb,RCBit rc)784 void Assembler::and_(Register ra, Register rs, Register rb, RCBit rc) {
785   x_form(EXT2 | ANDX, ra, rs, rb, rc);
786 }
787 
788 
rlwinm(Register ra,Register rs,int sh,int mb,int me,RCBit rc)789 void 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 
rlwnm(Register ra,Register rs,Register rb,int mb,int me,RCBit rc)799 void 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 
rlwimi(Register ra,Register rs,int sh,int mb,int me,RCBit rc)808 void 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 
slwi(Register dst,Register src,const Operand & val,RCBit rc)818 void 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 
srwi(Register dst,Register src,const Operand & val,RCBit rc)824 void 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 
clrrwi(Register dst,Register src,const Operand & val,RCBit rc)830 void 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 
clrlwi(Register dst,Register src,const Operand & val,RCBit rc)837 void 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 
srawi(Register ra,Register rs,int sh,RCBit r)844 void 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 
srw(Register dst,Register src1,Register src2,RCBit r)849 void Assembler::srw(Register dst, Register src1, Register src2, RCBit r) {
850   x_form(EXT2 | SRWX, dst, src1, src2, r);
851 }
852 
853 
slw(Register dst,Register src1,Register src2,RCBit r)854 void Assembler::slw(Register dst, Register src1, Register src2, RCBit r) {
855   x_form(EXT2 | SLWX, dst, src1, src2, r);
856 }
857 
858 
sraw(Register ra,Register rs,Register rb,RCBit r)859 void Assembler::sraw(Register ra, Register rs, Register rb, RCBit r) {
860   x_form(EXT2 | SRAW, ra, rs, rb, r);
861 }
862 
863 
rotlw(Register ra,Register rs,Register rb,RCBit r)864 void Assembler::rotlw(Register ra, Register rs, Register rb, RCBit r) {
865   rlwnm(ra, rs, rb, 0, 31, r);
866 }
867 
868 
rotlwi(Register ra,Register rs,int sh,RCBit r)869 void Assembler::rotlwi(Register ra, Register rs, int sh, RCBit r) {
870   rlwinm(ra, rs, sh, 0, 31, r);
871 }
872 
873 
rotrwi(Register ra,Register rs,int sh,RCBit r)874 void Assembler::rotrwi(Register ra, Register rs, int sh, RCBit r) {
875   rlwinm(ra, rs, 32 - sh, 0, 31, r);
876 }
877 
878 
subi(Register dst,Register src,const Operand & imm)879 void Assembler::subi(Register dst, Register src, const Operand& imm) {
880   addi(dst, src, Operand(-(imm.imm_)));
881 }
882 
addc(Register dst,Register src1,Register src2,OEBit o,RCBit r)883 void 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 
adde(Register dst,Register src1,Register src2,OEBit o,RCBit r)888 void 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 
addze(Register dst,Register src1,OEBit o,RCBit r)893 void 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 
sub(Register dst,Register src1,Register src2,OEBit o,RCBit r)899 void 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 
subc(Register dst,Register src1,Register src2,OEBit o,RCBit r)904 void 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 
sube(Register dst,Register src1,Register src2,OEBit o,RCBit r)909 void 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 
subfic(Register dst,Register src,const Operand & imm)914 void Assembler::subfic(Register dst, Register src, const Operand& imm) {
915   d_form(SUBFIC, dst, src, imm.imm_, true);
916 }
917 
918 
add(Register dst,Register src1,Register src2,OEBit o,RCBit r)919 void 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
mullw(Register dst,Register src1,Register src2,OEBit o,RCBit r)926 void 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
mulhw(Register dst,Register src1,Register src2,RCBit r)933 void 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
mulhwu(Register dst,Register src1,Register src2,RCBit r)939 void 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
divw(Register dst,Register src1,Register src2,OEBit o,RCBit r)945 void 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
divwu(Register dst,Register src1,Register src2,OEBit o,RCBit r)952 void 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 
modsw(Register rt,Register ra,Register rb)957 void Assembler::modsw(Register rt, Register ra, Register rb) {
958   x_form(EXT2 | MODSW, ra, rt, rb, LeaveRC);
959 }
960 
moduw(Register rt,Register ra,Register rb)961 void Assembler::moduw(Register rt, Register ra, Register rb) {
962   x_form(EXT2 | MODUW, ra, rt, rb, LeaveRC);
963 }
964 
addi(Register dst,Register src,const Operand & imm)965 void 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 
addis(Register dst,Register src,const Operand & imm)971 void 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 
addic(Register dst,Register src,const Operand & imm)977 void Assembler::addic(Register dst, Register src, const Operand& imm) {
978   d_form(ADDIC, dst, src, imm.imm_, true);
979 }
980 
981 
andi(Register ra,Register rs,const Operand & imm)982 void Assembler::andi(Register ra, Register rs, const Operand& imm) {
983   d_form(ANDIx, rs, ra, imm.imm_, false);
984 }
985 
986 
andis(Register ra,Register rs,const Operand & imm)987 void Assembler::andis(Register ra, Register rs, const Operand& imm) {
988   d_form(ANDISx, rs, ra, imm.imm_, false);
989 }
990 
991 
nor(Register dst,Register src1,Register src2,RCBit r)992 void Assembler::nor(Register dst, Register src1, Register src2, RCBit r) {
993   x_form(EXT2 | NORX, dst, src1, src2, r);
994 }
995 
996 
notx(Register dst,Register src,RCBit r)997 void Assembler::notx(Register dst, Register src, RCBit r) {
998   x_form(EXT2 | NORX, dst, src, src, r);
999 }
1000 
1001 
ori(Register ra,Register rs,const Operand & imm)1002 void Assembler::ori(Register ra, Register rs, const Operand& imm) {
1003   d_form(ORI, rs, ra, imm.imm_, false);
1004 }
1005 
1006 
oris(Register dst,Register src,const Operand & imm)1007 void Assembler::oris(Register dst, Register src, const Operand& imm) {
1008   d_form(ORIS, src, dst, imm.imm_, false);
1009 }
1010 
1011 
orx(Register dst,Register src1,Register src2,RCBit rc)1012 void Assembler::orx(Register dst, Register src1, Register src2, RCBit rc) {
1013   x_form(EXT2 | ORX, dst, src1, src2, rc);
1014 }
1015 
1016 
orc(Register dst,Register src1,Register src2,RCBit rc)1017 void Assembler::orc(Register dst, Register src1, Register src2, RCBit rc) {
1018   x_form(EXT2 | ORC, dst, src1, src2, rc);
1019 }
1020 
1021 
cmpi(Register src1,const Operand & src2,CRegister cr)1022 void 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 
cmpli(Register src1,const Operand & src2,CRegister cr)1036 void 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 
cmp(Register src1,Register src2,CRegister cr)1050 void 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 
cmpl(Register src1,Register src2,CRegister cr)1062 void 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 
cmpwi(Register src1,const Operand & src2,CRegister cr)1074 void 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 
cmplwi(Register src1,const Operand & src2,CRegister cr)1092 void 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 
cmpw(Register src1,Register src2,CRegister cr)1102 void 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 
cmplw(Register src1,Register src2,CRegister cr)1110 void 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 
isel(Register rt,Register ra,Register rb,int cb)1118 void 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
li(Register dst,const Operand & imm)1125 void Assembler::li(Register dst, const Operand& imm) {
1126   d_form(ADDI, dst, r0, imm.imm_, true);
1127 }
1128 
1129 
lis(Register dst,const Operand & imm)1130 void Assembler::lis(Register dst, const Operand& imm) {
1131   d_form(ADDIS, dst, r0, imm.imm_, true);
1132 }
1133 
1134 
1135 // Pseudo op - move register
mr(Register dst,Register src)1136 void Assembler::mr(Register dst, Register src) {
1137   // actually or(dst, src, src)
1138   orx(dst, src, src);
1139 }
1140 
1141 
lbz(Register dst,const MemOperand & src)1142 void 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 
lbzx(Register rt,const MemOperand & src)1148 void 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 
lbzux(Register rt,const MemOperand & src)1157 void 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 
lhz(Register dst,const MemOperand & src)1166 void 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 
lhzx(Register rt,const MemOperand & src)1172 void 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 
lhzux(Register rt,const MemOperand & src)1181 void 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 
lhax(Register rt,const MemOperand & src)1190 void 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 
lwz(Register dst,const MemOperand & src)1198 void 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 
lwzu(Register dst,const MemOperand & src)1204 void 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 
lwzx(Register rt,const MemOperand & src)1210 void 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 
lwzux(Register rt,const MemOperand & src)1219 void 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 
lha(Register dst,const MemOperand & src)1228 void 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 
lwa(Register dst,const MemOperand & src)1234 void 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 
lwax(Register rt,const MemOperand & src)1247 void 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 
ldbrx(Register dst,const MemOperand & src)1259 void Assembler::ldbrx(Register dst, const MemOperand& src) {
1260   x_form(EXT2 | LDBRX, src.ra(), dst, src.rb(), LeaveRC);
1261 }
1262 
1263 
lwbrx(Register dst,const MemOperand & src)1264 void Assembler::lwbrx(Register dst, const MemOperand& src) {
1265   x_form(EXT2 | LWBRX, src.ra(), dst, src.rb(), LeaveRC);
1266 }
1267 
1268 
lhbrx(Register dst,const MemOperand & src)1269 void Assembler::lhbrx(Register dst, const MemOperand& src) {
1270   x_form(EXT2 | LHBRX, src.ra(), dst, src.rb(), LeaveRC);
1271 }
1272 
1273 
stb(Register dst,const MemOperand & src)1274 void 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 
stbx(Register rs,const MemOperand & src)1280 void 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 
stbux(Register rs,const MemOperand & src)1289 void 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 
sth(Register dst,const MemOperand & src)1298 void 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 
sthx(Register rs,const MemOperand & src)1304 void 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 
sthux(Register rs,const MemOperand & src)1313 void 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 
stw(Register dst,const MemOperand & src)1322 void 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 
stwu(Register dst,const MemOperand & src)1328 void 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 
stwx(Register rs,const MemOperand & src)1334 void 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 
stwux(Register rs,const MemOperand & src)1343 void 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 
extsb(Register rs,Register ra,RCBit rc)1352 void Assembler::extsb(Register rs, Register ra, RCBit rc) {
1353   emit(EXT2 | EXTSB | ra.code() * B21 | rs.code() * B16 | rc);
1354 }
1355 
1356 
extsh(Register rs,Register ra,RCBit rc)1357 void Assembler::extsh(Register rs, Register ra, RCBit rc) {
1358   emit(EXT2 | EXTSH | ra.code() * B21 | rs.code() * B16 | rc);
1359 }
1360 
1361 
extsw(Register rs,Register ra,RCBit rc)1362 void 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 
neg(Register rt,Register ra,OEBit o,RCBit r)1372 void 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 
andc(Register dst,Register src1,Register src2,RCBit rc)1377 void 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
ld(Register rd,const MemOperand & src)1384 void 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 
ldx(Register rd,const MemOperand & src)1393 void 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 
ldu(Register rd,const MemOperand & src)1401 void 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 
ldux(Register rd,const MemOperand & src)1410 void 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 
std(Register rs,const MemOperand & src)1418 void 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 
stdx(Register rs,const MemOperand & src)1427 void 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 
stdu(Register rs,const MemOperand & src)1435 void 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 
stdux(Register rs,const MemOperand & src)1444 void 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 
rldic(Register ra,Register rs,int sh,int mb,RCBit r)1452 void 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 
rldicl(Register ra,Register rs,int sh,int mb,RCBit r)1457 void 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 
rldcl(Register ra,Register rs,Register rb,int mb,RCBit r)1462 void 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 
rldicr(Register ra,Register rs,int sh,int me,RCBit r)1467 void 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 
sldi(Register dst,Register src,const Operand & val,RCBit rc)1472 void 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 
srdi(Register dst,Register src,const Operand & val,RCBit rc)1478 void 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 
clrrdi(Register dst,Register src,const Operand & val,RCBit rc)1484 void 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 
clrldi(Register dst,Register src,const Operand & val,RCBit rc)1491 void 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 
rldimi(Register ra,Register rs,int sh,int mb,RCBit r)1498 void 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 
sradi(Register ra,Register rs,int sh,RCBit r)1503 void 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 
srd(Register dst,Register src1,Register src2,RCBit r)1512 void Assembler::srd(Register dst, Register src1, Register src2, RCBit r) {
1513   x_form(EXT2 | SRDX, dst, src1, src2, r);
1514 }
1515 
1516 
sld(Register dst,Register src1,Register src2,RCBit r)1517 void Assembler::sld(Register dst, Register src1, Register src2, RCBit r) {
1518   x_form(EXT2 | SLDX, dst, src1, src2, r);
1519 }
1520 
1521 
srad(Register ra,Register rs,Register rb,RCBit r)1522 void Assembler::srad(Register ra, Register rs, Register rb, RCBit r) {
1523   x_form(EXT2 | SRAD, ra, rs, rb, r);
1524 }
1525 
1526 
rotld(Register ra,Register rs,Register rb,RCBit r)1527 void Assembler::rotld(Register ra, Register rs, Register rb, RCBit r) {
1528   rldcl(ra, rs, rb, 0, r);
1529 }
1530 
1531 
rotldi(Register ra,Register rs,int sh,RCBit r)1532 void Assembler::rotldi(Register ra, Register rs, int sh, RCBit r) {
1533   rldicl(ra, rs, sh, 0, r);
1534 }
1535 
1536 
rotrdi(Register ra,Register rs,int sh,RCBit r)1537 void Assembler::rotrdi(Register ra, Register rs, int sh, RCBit r) {
1538   rldicl(ra, rs, 64 - sh, 0, r);
1539 }
1540 
1541 
cntlzd_(Register ra,Register rs,RCBit rc)1542 void Assembler::cntlzd_(Register ra, Register rs, RCBit rc) {
1543   x_form(EXT2 | CNTLZDX, ra, rs, r0, rc);
1544 }
1545 
1546 
popcntd(Register ra,Register rs)1547 void Assembler::popcntd(Register ra, Register rs) {
1548   emit(EXT2 | POPCNTD | rs.code() * B21 | ra.code() * B16);
1549 }
1550 
1551 
mulld(Register dst,Register src1,Register src2,OEBit o,RCBit r)1552 void 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 
divd(Register dst,Register src1,Register src2,OEBit o,RCBit r)1558 void 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 
divdu(Register dst,Register src1,Register src2,OEBit o,RCBit r)1564 void 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 
modsd(Register rt,Register ra,Register rb)1569 void Assembler::modsd(Register rt, Register ra, Register rb) {
1570   x_form(EXT2 | MODSD, ra, rt, rb, LeaveRC);
1571 }
1572 
modud(Register rt,Register ra,Register rb)1573 void 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.
function_descriptor()1582 void 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 
instructions_required_for_mov(Register dst,const Operand & src) const1594 int 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 
use_constant_pool_for_mov(Register dst,const Operand & src,bool canOptimize) const1609 bool 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 
EnsureSpaceFor(int space_needed)1637 void Assembler::EnsureSpaceFor(int space_needed) {
1638   if (buffer_space() <= (kGap + space_needed)) {
1639     GrowBuffer(space_needed);
1640   }
1641 }
1642 
1643 
must_output_reloc_info(const Assembler * assembler) const1644 bool 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
mov(Register dst,const Operand & src)1661 void 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 
bitwise_mov(Register dst,intptr_t value)1736 void 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 
bitwise_mov32(Register dst,int32_t value)1759 void 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 
bitwise_add32(Register dst,Register src,int32_t value)1768 void 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 
mov_label_offset(Register dst,Label * label)1783 void 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 
add_label_offset(Register dst,Register base,Label * label,int delta)1810 void 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 
mov_label_addr(Register dst,Label * label)1834 void 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 
emit_label_addr(Label * label)1864 void 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
crxor(int bt,int ba,int bb)1893 void Assembler::crxor(int bt, int ba, int bb) {
1894   emit(EXT1 | CRXOR | bt * B21 | ba * B16 | bb * B11);
1895 }
1896 
1897 
creqv(int bt,int ba,int bb)1898 void Assembler::creqv(int bt, int ba, int bb) {
1899   emit(EXT1 | CREQV | bt * B21 | ba * B16 | bb * B11);
1900 }
1901 
1902 
mflr(Register dst)1903 void Assembler::mflr(Register dst) {
1904   emit(EXT2 | MFSPR | dst.code() * B21 | 256 << 11);  // Ignore RC bit
1905 }
1906 
1907 
mtlr(Register src)1908 void Assembler::mtlr(Register src) {
1909   emit(EXT2 | MTSPR | src.code() * B21 | 256 << 11);  // Ignore RC bit
1910 }
1911 
1912 
mtctr(Register src)1913 void Assembler::mtctr(Register src) {
1914   emit(EXT2 | MTSPR | src.code() * B21 | 288 << 11);  // Ignore RC bit
1915 }
1916 
1917 
mtxer(Register src)1918 void Assembler::mtxer(Register src) {
1919   emit(EXT2 | MTSPR | src.code() * B21 | 32 << 11);
1920 }
1921 
1922 
mcrfs(CRegister cr,FPSCRBit bit)1923 void 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 
mfcr(Register dst)1931 void Assembler::mfcr(Register dst) { emit(EXT2 | MFCR | dst.code() * B21); }
1932 
1933 
1934 #if V8_TARGET_ARCH_PPC64
mffprd(Register dst,DoubleRegister src)1935 void Assembler::mffprd(Register dst, DoubleRegister src) {
1936   emit(EXT2 | MFVSRD | src.code() * B21 | dst.code() * B16);
1937 }
1938 
1939 
mffprwz(Register dst,DoubleRegister src)1940 void Assembler::mffprwz(Register dst, DoubleRegister src) {
1941   emit(EXT2 | MFVSRWZ | src.code() * B21 | dst.code() * B16);
1942 }
1943 
1944 
mtfprd(DoubleRegister dst,Register src)1945 void Assembler::mtfprd(DoubleRegister dst, Register src) {
1946   emit(EXT2 | MTVSRD | dst.code() * B21 | src.code() * B16);
1947 }
1948 
1949 
mtfprwz(DoubleRegister dst,Register src)1950 void Assembler::mtfprwz(DoubleRegister dst, Register src) {
1951   emit(EXT2 | MTVSRWZ | dst.code() * B21 | src.code() * B16);
1952 }
1953 
1954 
mtfprwa(DoubleRegister dst,Register src)1955 void 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 .
stop(const char * msg,Condition cond,int32_t code,CRegister cr)1964 void 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 
bkpt(uint32_t imm16)1977 void Assembler::bkpt(uint32_t imm16) { emit(0x7d821008); }
1978 
1979 
dcbf(Register ra,Register rb)1980 void Assembler::dcbf(Register ra, Register rb) {
1981   emit(EXT2 | DCBF | ra.code() * B16 | rb.code() * B11);
1982 }
1983 
1984 
sync()1985 void Assembler::sync() { emit(EXT2 | SYNC); }
1986 
1987 
lwsync()1988 void Assembler::lwsync() { emit(EXT2 | SYNC | 1 * B21); }
1989 
1990 
icbi(Register ra,Register rb)1991 void Assembler::icbi(Register ra, Register rb) {
1992   emit(EXT2 | ICBI | ra.code() * B16 | rb.code() * B11);
1993 }
1994 
1995 
isync()1996 void Assembler::isync() { emit(EXT1 | ISYNC); }
1997 
1998 
1999 // Floating point support
2000 
lfd(const DoubleRegister frt,const MemOperand & src)2001 void 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 
lfdu(const DoubleRegister frt,const MemOperand & src)2012 void 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 
lfdx(const DoubleRegister frt,const MemOperand & src)2023 void 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 
lfdux(const DoubleRegister frt,const MemOperand & src)2032 void 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 
lfs(const DoubleRegister frt,const MemOperand & src)2041 void 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 
lfsu(const DoubleRegister frt,const MemOperand & src)2052 void 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 
lfsx(const DoubleRegister frt,const MemOperand & src)2063 void 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 
lfsux(const DoubleRegister frt,const MemOperand & src)2072 void 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 
stfd(const DoubleRegister frs,const MemOperand & src)2081 void 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 
stfdu(const DoubleRegister frs,const MemOperand & src)2092 void 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 
stfdx(const DoubleRegister frs,const MemOperand & src)2103 void 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 
stfdux(const DoubleRegister frs,const MemOperand & src)2112 void 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 
stfs(const DoubleRegister frs,const MemOperand & src)2121 void 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 
stfsu(const DoubleRegister frs,const MemOperand & src)2132 void 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 
stfsx(const DoubleRegister frs,const MemOperand & src)2143 void 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 
stfsux(const DoubleRegister frs,const MemOperand & src)2152 void 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 
fsub(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frb,RCBit rc)2161 void 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 
fadd(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frb,RCBit rc)2167 void 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 
fmul(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frc,RCBit rc)2173 void 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 
fdiv(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frb,RCBit rc)2180 void 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 
fcmpu(const DoubleRegister fra,const DoubleRegister frb,CRegister cr)2186 void 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 
fmr(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2193 void 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 
fctiwz(const DoubleRegister frt,const DoubleRegister frb)2199 void Assembler::fctiwz(const DoubleRegister frt, const DoubleRegister frb) {
2200   emit(EXT4 | FCTIWZ | frt.code() * B21 | frb.code() * B11);
2201 }
2202 
2203 
fctiw(const DoubleRegister frt,const DoubleRegister frb)2204 void Assembler::fctiw(const DoubleRegister frt, const DoubleRegister frb) {
2205   emit(EXT4 | FCTIW | frt.code() * B21 | frb.code() * B11);
2206 }
2207 
2208 
frin(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2209 void 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 
friz(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2215 void 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 
frip(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2221 void 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 
frim(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2227 void 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 
frsp(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2233 void 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 
fcfid(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2239 void 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 
fcfidu(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2245 void 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 
fcfidus(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2251 void 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 
fcfids(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2257 void 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 
fctid(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2263 void 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 
fctidz(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2269 void 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 
fctidu(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2275 void 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 
fctiduz(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2281 void 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 
fsel(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frc,const DoubleRegister frb,RCBit rc)2287 void 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 
fneg(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2295 void 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 
mtfsb0(FPSCRBit bit,RCBit rc)2301 void 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 
mtfsb1(FPSCRBit bit,RCBit rc)2308 void 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 
mtfsfi(int bf,int immediate,RCBit rc)2315 void Assembler::mtfsfi(int bf, int immediate, RCBit rc) {
2316   emit(EXT4 | MTFSFI | bf * B23 | immediate * B12 | rc);
2317 }
2318 
2319 
mffs(const DoubleRegister frt,RCBit rc)2320 void Assembler::mffs(const DoubleRegister frt, RCBit rc) {
2321   emit(EXT4 | MFFS | frt.code() * B21 | rc);
2322 }
2323 
2324 
mtfsf(const DoubleRegister frb,bool L,int FLM,bool W,RCBit rc)2325 void 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 
fsqrt(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2331 void 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 
fabs(const DoubleRegister frt,const DoubleRegister frb,RCBit rc)2337 void 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 
fmadd(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frc,const DoubleRegister frb,RCBit rc)2343 void 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 
fmsub(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frc,const DoubleRegister frb,RCBit rc)2351 void 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 
xsadddp(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frb)2360 void Assembler::xsadddp(const DoubleRegister frt, const DoubleRegister fra,
2361                         const DoubleRegister frb) {
2362   xx3_form(EXT6 | XSADDDP, frt, fra, frb);
2363 }
xssubdp(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frb)2364 void Assembler::xssubdp(const DoubleRegister frt, const DoubleRegister fra,
2365                         const DoubleRegister frb) {
2366   xx3_form(EXT6 | XSSUBDP, frt, fra, frb);
2367 }
xsdivdp(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frb)2368 void Assembler::xsdivdp(const DoubleRegister frt, const DoubleRegister fra,
2369                         const DoubleRegister frb) {
2370   xx3_form(EXT6 | XSDIVDP, frt, fra, frb);
2371 }
xsmuldp(const DoubleRegister frt,const DoubleRegister fra,const DoubleRegister frb)2372 void 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.
nop(int type)2378 void 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 
IsNop(Instr instr,int type)2398 bool 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 
GrowBuffer(int needed)2417 void 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 
db(uint8_t data)2464 void Assembler::db(uint8_t data) {
2465   CheckBuffer();
2466   *reinterpret_cast<uint8_t*>(pc_) = data;
2467   pc_ += sizeof(uint8_t);
2468 }
2469 
2470 
dd(uint32_t data)2471 void Assembler::dd(uint32_t data) {
2472   CheckBuffer();
2473   *reinterpret_cast<uint32_t*>(pc_) = data;
2474   pc_ += sizeof(uint32_t);
2475 }
2476 
2477 
dq(uint64_t value)2478 void Assembler::dq(uint64_t value) {
2479   CheckBuffer();
2480   *reinterpret_cast<uint64_t*>(pc_) = value;
2481   pc_ += sizeof(uint64_t);
2482 }
2483 
2484 
dp(uintptr_t data)2485 void Assembler::dp(uintptr_t data) {
2486   CheckBuffer();
2487   *reinterpret_cast<uintptr_t*>(pc_) = data;
2488   pc_ += sizeof(uintptr_t);
2489 }
2490 
2491 
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data)2492 void 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 
EmitRelocations()2508 void 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 
BlockTrampolinePoolFor(int instructions)2535 void Assembler::BlockTrampolinePoolFor(int instructions) {
2536   BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
2537 }
2538 
2539 
CheckTrampolinePool()2540 void 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