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