• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // 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 distribution.
14 //
15 // - Neither the name of Sun Microsystems or the names of contributors may
16 // be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // The original source code covered by the above license above has been
32 // modified significantly by Google Inc.
33 // Copyright 2012 the V8 project authors. All rights reserved.
34 
35 #include "src/mips64/assembler-mips64.h"
36 
37 #if V8_TARGET_ARCH_MIPS64
38 
39 #include "src/base/cpu.h"
40 #include "src/mips64/assembler-mips64-inl.h"
41 
42 namespace v8 {
43 namespace internal {
44 
45 
46 // Get the CPU features enabled by the build. For cross compilation the
47 // preprocessor symbols CAN_USE_FPU_INSTRUCTIONS
48 // can be defined to enable FPU instructions when building the
49 // snapshot.
CpuFeaturesImpliedByCompiler()50 static unsigned CpuFeaturesImpliedByCompiler() {
51   unsigned answer = 0;
52 #ifdef CAN_USE_FPU_INSTRUCTIONS
53   answer |= 1u << FPU;
54 #endif  // def CAN_USE_FPU_INSTRUCTIONS
55 
56   // If the compiler is allowed to use FPU then we can use FPU too in our code
57   // generation even when generating snapshots.  This won't work for cross
58   // compilation.
59 #if defined(__mips__) && defined(__mips_hard_float) && __mips_hard_float != 0
60   answer |= 1u << FPU;
61 #endif
62 
63   return answer;
64 }
65 
66 
ProbeImpl(bool cross_compile)67 void CpuFeatures::ProbeImpl(bool cross_compile) {
68   supported_ |= CpuFeaturesImpliedByCompiler();
69 
70   // Only use statically determined features for cross compile (snapshot).
71   if (cross_compile) return;
72 
73   // If the compiler is allowed to use fpu then we can use fpu too in our
74   // code generation.
75 #ifndef __mips__
76   // For the simulator build, use FPU.
77   supported_ |= 1u << FPU;
78 #else
79   // Probe for additional features at runtime.
80   base::CPU cpu;
81   if (cpu.has_fpu()) supported_ |= 1u << FPU;
82 #endif
83 }
84 
85 
PrintTarget()86 void CpuFeatures::PrintTarget() { }
PrintFeatures()87 void CpuFeatures::PrintFeatures() { }
88 
89 
ToNumber(Register reg)90 int ToNumber(Register reg) {
91   DCHECK(reg.is_valid());
92   const int kNumbers[] = {
93     0,    // zero_reg
94     1,    // at
95     2,    // v0
96     3,    // v1
97     4,    // a0
98     5,    // a1
99     6,    // a2
100     7,    // a3
101     8,    // a4
102     9,    // a5
103     10,   // a6
104     11,   // a7
105     12,   // t0
106     13,   // t1
107     14,   // t2
108     15,   // t3
109     16,   // s0
110     17,   // s1
111     18,   // s2
112     19,   // s3
113     20,   // s4
114     21,   // s5
115     22,   // s6
116     23,   // s7
117     24,   // t8
118     25,   // t9
119     26,   // k0
120     27,   // k1
121     28,   // gp
122     29,   // sp
123     30,   // fp
124     31,   // ra
125   };
126   return kNumbers[reg.code()];
127 }
128 
129 
ToRegister(int num)130 Register ToRegister(int num) {
131   DCHECK(num >= 0 && num < kNumRegisters);
132   const Register kRegisters[] = {
133     zero_reg,
134     at,
135     v0, v1,
136     a0, a1, a2, a3, a4, a5, a6, a7,
137     t0, t1, t2, t3,
138     s0, s1, s2, s3, s4, s5, s6, s7,
139     t8, t9,
140     k0, k1,
141     gp,
142     sp,
143     fp,
144     ra
145   };
146   return kRegisters[num];
147 }
148 
149 
150 // -----------------------------------------------------------------------------
151 // Implementation of RelocInfo.
152 
153 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
154                                   1 << RelocInfo::INTERNAL_REFERENCE |
155                                   1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
156 
157 
IsCodedSpecially()158 bool RelocInfo::IsCodedSpecially() {
159   // The deserializer needs to know whether a pointer is specially coded.  Being
160   // specially coded on MIPS means that it is a lui/ori instruction, and that is
161   // always the case inside code objects.
162   return true;
163 }
164 
165 
IsInConstantPool()166 bool RelocInfo::IsInConstantPool() {
167   return false;
168 }
169 
wasm_memory_reference()170 Address RelocInfo::wasm_memory_reference() {
171   DCHECK(IsWasmMemoryReference(rmode_));
172   return Assembler::target_address_at(pc_, host_);
173 }
174 
wasm_global_reference()175 Address RelocInfo::wasm_global_reference() {
176   DCHECK(IsWasmGlobalReference(rmode_));
177   return Assembler::target_address_at(pc_, host_);
178 }
179 
wasm_memory_size_reference()180 uint32_t RelocInfo::wasm_memory_size_reference() {
181   DCHECK(IsWasmMemorySizeReference(rmode_));
182   return static_cast<uint32_t>(
183       reinterpret_cast<intptr_t>((Assembler::target_address_at(pc_, host_))));
184 }
185 
unchecked_update_wasm_memory_reference(Address address,ICacheFlushMode flush_mode)186 void RelocInfo::unchecked_update_wasm_memory_reference(
187     Address address, ICacheFlushMode flush_mode) {
188   Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
189 }
190 
unchecked_update_wasm_memory_size(uint32_t size,ICacheFlushMode flush_mode)191 void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
192                                                   ICacheFlushMode flush_mode) {
193   Assembler::set_target_address_at(isolate_, pc_, host_,
194                                    reinterpret_cast<Address>(size), flush_mode);
195 }
196 
197 // -----------------------------------------------------------------------------
198 // Implementation of Operand and MemOperand.
199 // See assembler-mips-inl.h for inlined constructors.
200 
Operand(Handle<Object> handle)201 Operand::Operand(Handle<Object> handle) {
202   AllowDeferredHandleDereference using_raw_address;
203   rm_ = no_reg;
204   // Verify all Objects referred by code are NOT in new space.
205   Object* obj = *handle;
206   if (obj->IsHeapObject()) {
207     DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
208     imm64_ = reinterpret_cast<intptr_t>(handle.location());
209     rmode_ = RelocInfo::EMBEDDED_OBJECT;
210   } else {
211     // No relocation needed.
212     imm64_ = reinterpret_cast<intptr_t>(obj);
213     rmode_ = RelocInfo::NONE64;
214   }
215 }
216 
217 
MemOperand(Register rm,int32_t offset)218 MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
219   offset_ = offset;
220 }
221 
222 
MemOperand(Register rm,int32_t unit,int32_t multiplier,OffsetAddend offset_addend)223 MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
224                        OffsetAddend offset_addend)
225     : Operand(rm) {
226   offset_ = unit * multiplier + offset_addend;
227 }
228 
229 
230 // -----------------------------------------------------------------------------
231 // Specific instructions, constants, and masks.
232 
233 static const int kNegOffset = 0x00008000;
234 // daddiu(sp, sp, 8) aka Pop() operation or part of Pop(r)
235 // operations as post-increment of sp.
236 const Instr kPopInstruction = DADDIU | (Register::kCode_sp << kRsShift) |
237                               (Register::kCode_sp << kRtShift) |
238                               (kPointerSize & kImm16Mask);  // NOLINT
239 // daddiu(sp, sp, -8) part of Push(r) operation as pre-decrement of sp.
240 const Instr kPushInstruction = DADDIU | (Register::kCode_sp << kRsShift) |
241                                (Register::kCode_sp << kRtShift) |
242                                (-kPointerSize & kImm16Mask);  // NOLINT
243 // sd(r, MemOperand(sp, 0))
244 const Instr kPushRegPattern =
245     SD | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
246 //  ld(r, MemOperand(sp, 0))
247 const Instr kPopRegPattern =
248     LD | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
249 
250 const Instr kLwRegFpOffsetPattern =
251     LW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
252 
253 const Instr kSwRegFpOffsetPattern =
254     SW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
255 
256 const Instr kLwRegFpNegOffsetPattern = LW | (Register::kCode_fp << kRsShift) |
257                                        (kNegOffset & kImm16Mask);  // NOLINT
258 
259 const Instr kSwRegFpNegOffsetPattern = SW | (Register::kCode_fp << kRsShift) |
260                                        (kNegOffset & kImm16Mask);  // NOLINT
261 // A mask for the Rt register for push, pop, lw, sw instructions.
262 const Instr kRtMask = kRtFieldMask;
263 const Instr kLwSwInstrTypeMask = 0xffe00000;
264 const Instr kLwSwInstrArgumentMask  = ~kLwSwInstrTypeMask;
265 const Instr kLwSwOffsetMask = kImm16Mask;
266 
267 
Assembler(Isolate * isolate,void * buffer,int buffer_size)268 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
269     : AssemblerBase(isolate, buffer, buffer_size),
270       recorded_ast_id_(TypeFeedbackId::None()),
271       positions_recorder_(this) {
272   reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
273 
274   last_trampoline_pool_end_ = 0;
275   no_trampoline_pool_before_ = 0;
276   trampoline_pool_blocked_nesting_ = 0;
277   // We leave space (16 * kTrampolineSlotsSize)
278   // for BlockTrampolinePoolScope buffer.
279   next_buffer_check_ = FLAG_force_long_branches
280       ? kMaxInt : kMaxBranchOffset - kTrampolineSlotsSize * 16;
281   internal_trampoline_exception_ = false;
282   last_bound_pos_ = 0;
283 
284   trampoline_emitted_ = FLAG_force_long_branches;
285   unbound_labels_count_ = 0;
286   block_buffer_growth_ = false;
287 
288   ClearRecordedAstId();
289 }
290 
291 
GetCode(CodeDesc * desc)292 void Assembler::GetCode(CodeDesc* desc) {
293   EmitForbiddenSlotInstruction();
294   DCHECK(pc_ <= reloc_info_writer.pos());  // No overlap.
295   // Set up code descriptor.
296   desc->buffer = buffer_;
297   desc->buffer_size = buffer_size_;
298   desc->instr_size = pc_offset();
299   desc->reloc_size =
300       static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
301   desc->origin = this;
302   desc->constant_pool_size = 0;
303   desc->unwinding_info_size = 0;
304   desc->unwinding_info = nullptr;
305 }
306 
307 
Align(int m)308 void Assembler::Align(int m) {
309   DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
310   EmitForbiddenSlotInstruction();
311   while ((pc_offset() & (m - 1)) != 0) {
312     nop();
313   }
314 }
315 
316 
CodeTargetAlign()317 void Assembler::CodeTargetAlign() {
318   // No advantage to aligning branch/call targets to more than
319   // single instruction, that I am aware of.
320   Align(4);
321 }
322 
323 
GetRtReg(Instr instr)324 Register Assembler::GetRtReg(Instr instr) {
325   Register rt;
326   rt.reg_code = (instr & kRtFieldMask) >> kRtShift;
327   return rt;
328 }
329 
330 
GetRsReg(Instr instr)331 Register Assembler::GetRsReg(Instr instr) {
332   Register rs;
333   rs.reg_code = (instr & kRsFieldMask) >> kRsShift;
334   return rs;
335 }
336 
337 
GetRdReg(Instr instr)338 Register Assembler::GetRdReg(Instr instr) {
339   Register rd;
340   rd.reg_code = (instr & kRdFieldMask) >> kRdShift;
341   return rd;
342 }
343 
344 
GetRt(Instr instr)345 uint32_t Assembler::GetRt(Instr instr) {
346   return (instr & kRtFieldMask) >> kRtShift;
347 }
348 
349 
GetRtField(Instr instr)350 uint32_t Assembler::GetRtField(Instr instr) {
351   return instr & kRtFieldMask;
352 }
353 
354 
GetRs(Instr instr)355 uint32_t Assembler::GetRs(Instr instr) {
356   return (instr & kRsFieldMask) >> kRsShift;
357 }
358 
359 
GetRsField(Instr instr)360 uint32_t Assembler::GetRsField(Instr instr) {
361   return instr & kRsFieldMask;
362 }
363 
364 
GetRd(Instr instr)365 uint32_t Assembler::GetRd(Instr instr) {
366   return  (instr & kRdFieldMask) >> kRdShift;
367 }
368 
369 
GetRdField(Instr instr)370 uint32_t Assembler::GetRdField(Instr instr) {
371   return  instr & kRdFieldMask;
372 }
373 
374 
GetSa(Instr instr)375 uint32_t Assembler::GetSa(Instr instr) {
376   return (instr & kSaFieldMask) >> kSaShift;
377 }
378 
379 
GetSaField(Instr instr)380 uint32_t Assembler::GetSaField(Instr instr) {
381   return instr & kSaFieldMask;
382 }
383 
384 
GetOpcodeField(Instr instr)385 uint32_t Assembler::GetOpcodeField(Instr instr) {
386   return instr & kOpcodeMask;
387 }
388 
389 
GetFunction(Instr instr)390 uint32_t Assembler::GetFunction(Instr instr) {
391   return (instr & kFunctionFieldMask) >> kFunctionShift;
392 }
393 
394 
GetFunctionField(Instr instr)395 uint32_t Assembler::GetFunctionField(Instr instr) {
396   return instr & kFunctionFieldMask;
397 }
398 
399 
GetImmediate16(Instr instr)400 uint32_t Assembler::GetImmediate16(Instr instr) {
401   return instr & kImm16Mask;
402 }
403 
404 
GetLabelConst(Instr instr)405 uint32_t Assembler::GetLabelConst(Instr instr) {
406   return instr & ~kImm16Mask;
407 }
408 
409 
IsPop(Instr instr)410 bool Assembler::IsPop(Instr instr) {
411   return (instr & ~kRtMask) == kPopRegPattern;
412 }
413 
414 
IsPush(Instr instr)415 bool Assembler::IsPush(Instr instr) {
416   return (instr & ~kRtMask) == kPushRegPattern;
417 }
418 
419 
IsSwRegFpOffset(Instr instr)420 bool Assembler::IsSwRegFpOffset(Instr instr) {
421   return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
422 }
423 
424 
IsLwRegFpOffset(Instr instr)425 bool Assembler::IsLwRegFpOffset(Instr instr) {
426   return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
427 }
428 
429 
IsSwRegFpNegOffset(Instr instr)430 bool Assembler::IsSwRegFpNegOffset(Instr instr) {
431   return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
432           kSwRegFpNegOffsetPattern);
433 }
434 
435 
IsLwRegFpNegOffset(Instr instr)436 bool Assembler::IsLwRegFpNegOffset(Instr instr) {
437   return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
438           kLwRegFpNegOffsetPattern);
439 }
440 
441 
442 // Labels refer to positions in the (to be) generated code.
443 // There are bound, linked, and unused labels.
444 //
445 // Bound labels refer to known positions in the already
446 // generated code. pos() is the position the label refers to.
447 //
448 // Linked labels refer to unknown positions in the code
449 // to be generated; pos() is the position of the last
450 // instruction using the label.
451 
452 // The link chain is terminated by a value in the instruction of -1,
453 // which is an otherwise illegal value (branch -1 is inf loop).
454 // The instruction 16-bit offset field addresses 32-bit words, but in
455 // code is conv to an 18-bit value addressing bytes, hence the -4 value.
456 
457 const int kEndOfChain = -4;
458 // Determines the end of the Jump chain (a subset of the label link chain).
459 const int kEndOfJumpChain = 0;
460 
461 
IsBranch(Instr instr)462 bool Assembler::IsBranch(Instr instr) {
463   uint32_t opcode   = GetOpcodeField(instr);
464   uint32_t rt_field = GetRtField(instr);
465   uint32_t rs_field = GetRsField(instr);
466   // Checks if the instruction is a branch.
467   bool isBranch =
468       opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ ||
469       opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL ||
470       (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
471                             rt_field == BLTZAL || rt_field == BGEZAL)) ||
472       (opcode == COP1 && rs_field == BC1) ||  // Coprocessor branch.
473       (opcode == COP1 && rs_field == BC1EQZ) ||
474       (opcode == COP1 && rs_field == BC1NEZ);
475   if (!isBranch && kArchVariant == kMips64r6) {
476     // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
477     // POP30 (BNVC, BNEC, BNEZALC) are branch ops.
478     isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC ||
479                 opcode == BALC ||
480                 (opcode == POP66 && rs_field != 0) ||  // BEQZC
481                 (opcode == POP76 && rs_field != 0);    // BNEZC
482   }
483   return isBranch;
484 }
485 
486 
IsBc(Instr instr)487 bool Assembler::IsBc(Instr instr) {
488   uint32_t opcode = GetOpcodeField(instr);
489   // Checks if the instruction is a BC or BALC.
490   return opcode == BC || opcode == BALC;
491 }
492 
493 
IsBzc(Instr instr)494 bool Assembler::IsBzc(Instr instr) {
495   uint32_t opcode = GetOpcodeField(instr);
496   // Checks if the instruction is BEQZC or BNEZC.
497   return (opcode == POP66 && GetRsField(instr) != 0) ||
498          (opcode == POP76 && GetRsField(instr) != 0);
499 }
500 
501 
IsEmittedConstant(Instr instr)502 bool Assembler::IsEmittedConstant(Instr instr) {
503   uint32_t label_constant = GetLabelConst(instr);
504   return label_constant == 0;  // Emitted label const in reg-exp engine.
505 }
506 
507 
IsBeq(Instr instr)508 bool Assembler::IsBeq(Instr instr) {
509   return GetOpcodeField(instr) == BEQ;
510 }
511 
512 
IsBne(Instr instr)513 bool Assembler::IsBne(Instr instr) {
514   return GetOpcodeField(instr) == BNE;
515 }
516 
517 
IsBeqzc(Instr instr)518 bool Assembler::IsBeqzc(Instr instr) {
519   uint32_t opcode = GetOpcodeField(instr);
520   return opcode == POP66 && GetRsField(instr) != 0;
521 }
522 
523 
IsBnezc(Instr instr)524 bool Assembler::IsBnezc(Instr instr) {
525   uint32_t opcode = GetOpcodeField(instr);
526   return opcode == POP76 && GetRsField(instr) != 0;
527 }
528 
529 
IsBeqc(Instr instr)530 bool Assembler::IsBeqc(Instr instr) {
531   uint32_t opcode = GetOpcodeField(instr);
532   uint32_t rs = GetRsField(instr);
533   uint32_t rt = GetRtField(instr);
534   return opcode == POP10 && rs != 0 && rs < rt;  // && rt != 0
535 }
536 
537 
IsBnec(Instr instr)538 bool Assembler::IsBnec(Instr instr) {
539   uint32_t opcode = GetOpcodeField(instr);
540   uint32_t rs = GetRsField(instr);
541   uint32_t rt = GetRtField(instr);
542   return opcode == POP30 && rs != 0 && rs < rt;  // && rt != 0
543 }
544 
545 
IsJump(Instr instr)546 bool Assembler::IsJump(Instr instr) {
547   uint32_t opcode   = GetOpcodeField(instr);
548   uint32_t rt_field = GetRtField(instr);
549   uint32_t rd_field = GetRdField(instr);
550   uint32_t function_field = GetFunctionField(instr);
551   // Checks if the instruction is a jump.
552   return opcode == J || opcode == JAL ||
553       (opcode == SPECIAL && rt_field == 0 &&
554       ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
555 }
556 
557 
IsJ(Instr instr)558 bool Assembler::IsJ(Instr instr) {
559   uint32_t opcode = GetOpcodeField(instr);
560   // Checks if the instruction is a jump.
561   return opcode == J;
562 }
563 
564 
IsJal(Instr instr)565 bool Assembler::IsJal(Instr instr) {
566   return GetOpcodeField(instr) == JAL;
567 }
568 
569 
IsJr(Instr instr)570 bool Assembler::IsJr(Instr instr) {
571   return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR;
572 }
573 
574 
IsJalr(Instr instr)575 bool Assembler::IsJalr(Instr instr) {
576   return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR;
577 }
578 
579 
IsLui(Instr instr)580 bool Assembler::IsLui(Instr instr) {
581   uint32_t opcode = GetOpcodeField(instr);
582   // Checks if the instruction is a load upper immediate.
583   return opcode == LUI;
584 }
585 
586 
IsOri(Instr instr)587 bool Assembler::IsOri(Instr instr) {
588   uint32_t opcode = GetOpcodeField(instr);
589   // Checks if the instruction is a load upper immediate.
590   return opcode == ORI;
591 }
592 
593 
IsNop(Instr instr,unsigned int type)594 bool Assembler::IsNop(Instr instr, unsigned int type) {
595   // See Assembler::nop(type).
596   DCHECK(type < 32);
597   uint32_t opcode = GetOpcodeField(instr);
598   uint32_t function = GetFunctionField(instr);
599   uint32_t rt = GetRt(instr);
600   uint32_t rd = GetRd(instr);
601   uint32_t sa = GetSa(instr);
602 
603   // Traditional mips nop == sll(zero_reg, zero_reg, 0)
604   // When marking non-zero type, use sll(zero_reg, at, type)
605   // to avoid use of mips ssnop and ehb special encodings
606   // of the sll instruction.
607 
608   Register nop_rt_reg = (type == 0) ? zero_reg : at;
609   bool ret = (opcode == SPECIAL && function == SLL &&
610               rd == static_cast<uint32_t>(ToNumber(zero_reg)) &&
611               rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) &&
612               sa == type);
613 
614   return ret;
615 }
616 
617 
GetBranchOffset(Instr instr)618 int32_t Assembler::GetBranchOffset(Instr instr) {
619   DCHECK(IsBranch(instr));
620   return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
621 }
622 
623 
IsLw(Instr instr)624 bool Assembler::IsLw(Instr instr) {
625   return (static_cast<uint32_t>(instr & kOpcodeMask) == LW);
626 }
627 
628 
GetLwOffset(Instr instr)629 int16_t Assembler::GetLwOffset(Instr instr) {
630   DCHECK(IsLw(instr));
631   return ((instr & kImm16Mask));
632 }
633 
634 
SetLwOffset(Instr instr,int16_t offset)635 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
636   DCHECK(IsLw(instr));
637 
638   // We actually create a new lw instruction based on the original one.
639   Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
640       | (offset & kImm16Mask);
641 
642   return temp_instr;
643 }
644 
645 
IsSw(Instr instr)646 bool Assembler::IsSw(Instr instr) {
647   return (static_cast<uint32_t>(instr & kOpcodeMask) == SW);
648 }
649 
650 
SetSwOffset(Instr instr,int16_t offset)651 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
652   DCHECK(IsSw(instr));
653   return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
654 }
655 
656 
IsAddImmediate(Instr instr)657 bool Assembler::IsAddImmediate(Instr instr) {
658   return ((instr & kOpcodeMask) == ADDIU || (instr & kOpcodeMask) == DADDIU);
659 }
660 
661 
SetAddImmediateOffset(Instr instr,int16_t offset)662 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
663   DCHECK(IsAddImmediate(instr));
664   return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
665 }
666 
667 
IsAndImmediate(Instr instr)668 bool Assembler::IsAndImmediate(Instr instr) {
669   return GetOpcodeField(instr) == ANDI;
670 }
671 
672 
OffsetSizeInBits(Instr instr)673 static Assembler::OffsetSize OffsetSizeInBits(Instr instr) {
674   if (kArchVariant == kMips64r6) {
675     if (Assembler::IsBc(instr)) {
676       return Assembler::OffsetSize::kOffset26;
677     } else if (Assembler::IsBzc(instr)) {
678       return Assembler::OffsetSize::kOffset21;
679     }
680   }
681   return Assembler::OffsetSize::kOffset16;
682 }
683 
684 
AddBranchOffset(int pos,Instr instr)685 static inline int32_t AddBranchOffset(int pos, Instr instr) {
686   int bits = OffsetSizeInBits(instr);
687   const int32_t mask = (1 << bits) - 1;
688   bits = 32 - bits;
689 
690   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
691   // the compiler uses arithmetic shifts for signed integers.
692   int32_t imm = ((instr & mask) << bits) >> (bits - 2);
693 
694   if (imm == kEndOfChain) {
695     // EndOfChain sentinel is returned directly, not relative to pc or pos.
696     return kEndOfChain;
697   } else {
698     return pos + Assembler::kBranchPCOffset + imm;
699   }
700 }
701 
702 
target_at(int pos,bool is_internal)703 int Assembler::target_at(int pos, bool is_internal) {
704   if (is_internal) {
705     int64_t* p = reinterpret_cast<int64_t*>(buffer_ + pos);
706     int64_t address = *p;
707     if (address == kEndOfJumpChain) {
708       return kEndOfChain;
709     } else {
710       int64_t instr_address = reinterpret_cast<int64_t>(p);
711       DCHECK(instr_address - address < INT_MAX);
712       int delta = static_cast<int>(instr_address - address);
713       DCHECK(pos > delta);
714       return pos - delta;
715     }
716   }
717   Instr instr = instr_at(pos);
718   if ((instr & ~kImm16Mask) == 0) {
719     // Emitted label constant, not part of a branch.
720     if (instr == 0) {
721        return kEndOfChain;
722      } else {
723        int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
724        return (imm18 + pos);
725      }
726   }
727   // Check we have a branch or jump instruction.
728   DCHECK(IsBranch(instr) || IsJ(instr) || IsJal(instr) || IsLui(instr));
729   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
730   // the compiler uses arithmetic shifts for signed integers.
731   if (IsBranch(instr)) {
732     return AddBranchOffset(pos, instr);
733   } else if (IsLui(instr)) {
734     Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
735     Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
736     Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize);
737     DCHECK(IsOri(instr_ori));
738     DCHECK(IsOri(instr_ori2));
739 
740     // TODO(plind) create named constants for shift values.
741     int64_t imm = static_cast<int64_t>(instr_lui & kImm16Mask) << 48;
742     imm |= static_cast<int64_t>(instr_ori & kImm16Mask) << 32;
743     imm |= static_cast<int64_t>(instr_ori2 & kImm16Mask) << 16;
744     // Sign extend address;
745     imm >>= 16;
746 
747     if (imm == kEndOfJumpChain) {
748       // EndOfChain sentinel is returned directly, not relative to pc or pos.
749       return kEndOfChain;
750     } else {
751       uint64_t instr_address = reinterpret_cast<int64_t>(buffer_ + pos);
752       DCHECK(instr_address - imm < INT_MAX);
753       int delta = static_cast<int>(instr_address - imm);
754       DCHECK(pos > delta);
755       return pos - delta;
756     }
757   } else {
758     DCHECK(IsJ(instr) || IsJal(instr));
759     int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
760     if (imm28 == kEndOfJumpChain) {
761       // EndOfChain sentinel is returned directly, not relative to pc or pos.
762       return kEndOfChain;
763     } else {
764       // Sign extend 28-bit offset.
765       int32_t delta = static_cast<int32_t>((imm28 << 4) >> 4);
766       return pos + delta;
767     }
768   }
769 }
770 
771 
SetBranchOffset(int32_t pos,int32_t target_pos,Instr instr)772 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
773                                     Instr instr) {
774   int32_t bits = OffsetSizeInBits(instr);
775   int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset);
776   DCHECK((imm & 3) == 0);
777   imm >>= 2;
778 
779   const int32_t mask = (1 << bits) - 1;
780   instr &= ~mask;
781   DCHECK(is_intn(imm, bits));
782 
783   return instr | (imm & mask);
784 }
785 
786 
target_at_put(int pos,int target_pos,bool is_internal)787 void Assembler::target_at_put(int pos, int target_pos, bool is_internal) {
788   if (is_internal) {
789     uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos;
790     *reinterpret_cast<uint64_t*>(buffer_ + pos) = imm;
791     return;
792   }
793   Instr instr = instr_at(pos);
794   if ((instr & ~kImm16Mask) == 0) {
795     DCHECK(target_pos == kEndOfChain || target_pos >= 0);
796     // Emitted label constant, not part of a branch.
797     // Make label relative to Code* of generated Code object.
798     instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
799     return;
800   }
801 
802   if (IsBranch(instr)) {
803     instr = SetBranchOffset(pos, target_pos, instr);
804     instr_at_put(pos, instr);
805   } else if (IsLui(instr)) {
806     Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
807     Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
808     Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize);
809     DCHECK(IsOri(instr_ori));
810     DCHECK(IsOri(instr_ori2));
811 
812     uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos;
813     DCHECK((imm & 3) == 0);
814 
815     instr_lui &= ~kImm16Mask;
816     instr_ori &= ~kImm16Mask;
817     instr_ori2 &= ~kImm16Mask;
818 
819     instr_at_put(pos + 0 * Assembler::kInstrSize,
820                  instr_lui | ((imm >> 32) & kImm16Mask));
821     instr_at_put(pos + 1 * Assembler::kInstrSize,
822                  instr_ori | ((imm >> 16) & kImm16Mask));
823     instr_at_put(pos + 3 * Assembler::kInstrSize,
824                  instr_ori2 | (imm & kImm16Mask));
825   } else if (IsJ(instr) || IsJal(instr)) {
826     int32_t imm28 = target_pos - pos;
827     DCHECK((imm28 & 3) == 0);
828 
829     uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2);
830     DCHECK(is_uint26(imm26));
831     // Place 26-bit signed offset with markings.
832     // When code is committed it will be resolved to j/jal.
833     int32_t mark = IsJ(instr) ? kJRawMark : kJalRawMark;
834     instr_at_put(pos, mark | (imm26 & kImm26Mask));
835   } else {
836     int32_t imm28 = target_pos - pos;
837     DCHECK((imm28 & 3) == 0);
838 
839     uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2);
840     DCHECK(is_uint26(imm26));
841     // Place raw 26-bit signed offset.
842     // When code is committed it will be resolved to j/jal.
843     instr &= ~kImm26Mask;
844     instr_at_put(pos, instr | (imm26 & kImm26Mask));
845   }
846 }
847 
848 
print(Label * L)849 void Assembler::print(Label* L) {
850   if (L->is_unused()) {
851     PrintF("unused label\n");
852   } else if (L->is_bound()) {
853     PrintF("bound label to %d\n", L->pos());
854   } else if (L->is_linked()) {
855     Label l = *L;
856     PrintF("unbound label");
857     while (l.is_linked()) {
858       PrintF("@ %d ", l.pos());
859       Instr instr = instr_at(l.pos());
860       if ((instr & ~kImm16Mask) == 0) {
861         PrintF("value\n");
862       } else {
863         PrintF("%d\n", instr);
864       }
865       next(&l, internal_reference_positions_.find(l.pos()) !=
866                    internal_reference_positions_.end());
867     }
868   } else {
869     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
870   }
871 }
872 
873 
bind_to(Label * L,int pos)874 void Assembler::bind_to(Label* L, int pos) {
875   DCHECK(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
876   int trampoline_pos = kInvalidSlotPos;
877   bool is_internal = false;
878   if (L->is_linked() && !trampoline_emitted_) {
879     unbound_labels_count_--;
880     next_buffer_check_ += kTrampolineSlotsSize;
881   }
882 
883   while (L->is_linked()) {
884     int fixup_pos = L->pos();
885     int dist = pos - fixup_pos;
886     is_internal = internal_reference_positions_.find(fixup_pos) !=
887                   internal_reference_positions_.end();
888     next(L, is_internal);  // Call next before overwriting link with target at
889                            // fixup_pos.
890     Instr instr = instr_at(fixup_pos);
891     if (is_internal) {
892       target_at_put(fixup_pos, pos, is_internal);
893     } else {
894       if (IsBranch(instr)) {
895         int branch_offset = BranchOffset(instr);
896         if (dist > branch_offset) {
897           if (trampoline_pos == kInvalidSlotPos) {
898             trampoline_pos = get_trampoline_entry(fixup_pos);
899             CHECK(trampoline_pos != kInvalidSlotPos);
900           }
901           CHECK((trampoline_pos - fixup_pos) <= branch_offset);
902           target_at_put(fixup_pos, trampoline_pos, false);
903           fixup_pos = trampoline_pos;
904           dist = pos - fixup_pos;
905         }
906         target_at_put(fixup_pos, pos, false);
907       } else {
908         DCHECK(IsJ(instr) || IsJal(instr) || IsLui(instr) ||
909                IsEmittedConstant(instr));
910         target_at_put(fixup_pos, pos, false);
911       }
912     }
913   }
914   L->bind_to(pos);
915 
916   // Keep track of the last bound label so we don't eliminate any instructions
917   // before a bound label.
918   if (pos > last_bound_pos_)
919     last_bound_pos_ = pos;
920 }
921 
922 
bind(Label * L)923 void Assembler::bind(Label* L) {
924   DCHECK(!L->is_bound());  // Label can only be bound once.
925   bind_to(L, pc_offset());
926 }
927 
928 
next(Label * L,bool is_internal)929 void Assembler::next(Label* L, bool is_internal) {
930   DCHECK(L->is_linked());
931   int link = target_at(L->pos(), is_internal);
932   if (link == kEndOfChain) {
933     L->Unuse();
934   } else {
935     DCHECK(link >= 0);
936     L->link_to(link);
937   }
938 }
939 
940 
is_near(Label * L)941 bool Assembler::is_near(Label* L) {
942   DCHECK(L->is_bound());
943   return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize;
944 }
945 
946 
is_near(Label * L,OffsetSize bits)947 bool Assembler::is_near(Label* L, OffsetSize bits) {
948   if (L == nullptr || !L->is_bound()) return true;
949   return ((pc_offset() - L->pos()) <
950           (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize);
951 }
952 
953 
is_near_branch(Label * L)954 bool Assembler::is_near_branch(Label* L) {
955   DCHECK(L->is_bound());
956   return kArchVariant == kMips64r6 ? is_near_r6(L) : is_near_pre_r6(L);
957 }
958 
959 
BranchOffset(Instr instr)960 int Assembler::BranchOffset(Instr instr) {
961   // At pre-R6 and for other R6 branches the offset is 16 bits.
962   int bits = OffsetSize::kOffset16;
963 
964   if (kArchVariant == kMips64r6) {
965     uint32_t opcode = GetOpcodeField(instr);
966     switch (opcode) {
967       // Checks BC or BALC.
968       case BC:
969       case BALC:
970         bits = OffsetSize::kOffset26;
971         break;
972 
973       // Checks BEQZC or BNEZC.
974       case POP66:
975       case POP76:
976         if (GetRsField(instr) != 0) bits = OffsetSize::kOffset21;
977         break;
978       default:
979         break;
980     }
981   }
982 
983   return (1 << (bits + 2 - 1)) - 1;
984 }
985 
986 
987 // We have to use a temporary register for things that can be relocated even
988 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
989 // space.  There is no guarantee that the relocated location can be similarly
990 // encoded.
MustUseReg(RelocInfo::Mode rmode)991 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
992   return !RelocInfo::IsNone(rmode);
993 }
994 
GenInstrRegister(Opcode opcode,Register rs,Register rt,Register rd,uint16_t sa,SecondaryField func)995 void Assembler::GenInstrRegister(Opcode opcode,
996                                  Register rs,
997                                  Register rt,
998                                  Register rd,
999                                  uint16_t sa,
1000                                  SecondaryField func) {
1001   DCHECK(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
1002   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1003       | (rd.code() << kRdShift) | (sa << kSaShift) | func;
1004   emit(instr);
1005 }
1006 
1007 
GenInstrRegister(Opcode opcode,Register rs,Register rt,uint16_t msb,uint16_t lsb,SecondaryField func)1008 void Assembler::GenInstrRegister(Opcode opcode,
1009                                  Register rs,
1010                                  Register rt,
1011                                  uint16_t msb,
1012                                  uint16_t lsb,
1013                                  SecondaryField func) {
1014   DCHECK(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
1015   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1016       | (msb << kRdShift) | (lsb << kSaShift) | func;
1017   emit(instr);
1018 }
1019 
1020 
GenInstrRegister(Opcode opcode,SecondaryField fmt,FPURegister ft,FPURegister fs,FPURegister fd,SecondaryField func)1021 void Assembler::GenInstrRegister(Opcode opcode,
1022                                  SecondaryField fmt,
1023                                  FPURegister ft,
1024                                  FPURegister fs,
1025                                  FPURegister fd,
1026                                  SecondaryField func) {
1027   DCHECK(fd.is_valid() && fs.is_valid() && ft.is_valid());
1028   Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
1029       | (fd.code() << kFdShift) | func;
1030   emit(instr);
1031 }
1032 
1033 
GenInstrRegister(Opcode opcode,FPURegister fr,FPURegister ft,FPURegister fs,FPURegister fd,SecondaryField func)1034 void Assembler::GenInstrRegister(Opcode opcode,
1035                                  FPURegister fr,
1036                                  FPURegister ft,
1037                                  FPURegister fs,
1038                                  FPURegister fd,
1039                                  SecondaryField func) {
1040   DCHECK(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
1041   Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
1042       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
1043   emit(instr);
1044 }
1045 
1046 
GenInstrRegister(Opcode opcode,SecondaryField fmt,Register rt,FPURegister fs,FPURegister fd,SecondaryField func)1047 void Assembler::GenInstrRegister(Opcode opcode,
1048                                  SecondaryField fmt,
1049                                  Register rt,
1050                                  FPURegister fs,
1051                                  FPURegister fd,
1052                                  SecondaryField func) {
1053   DCHECK(fd.is_valid() && fs.is_valid() && rt.is_valid());
1054   Instr instr = opcode | fmt | (rt.code() << kRtShift)
1055       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
1056   emit(instr);
1057 }
1058 
1059 
GenInstrRegister(Opcode opcode,SecondaryField fmt,Register rt,FPUControlRegister fs,SecondaryField func)1060 void Assembler::GenInstrRegister(Opcode opcode,
1061                                  SecondaryField fmt,
1062                                  Register rt,
1063                                  FPUControlRegister fs,
1064                                  SecondaryField func) {
1065   DCHECK(fs.is_valid() && rt.is_valid());
1066   Instr instr =
1067       opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
1068   emit(instr);
1069 }
1070 
1071 
1072 // Instructions with immediate value.
1073 // Registers are in the order of the instruction encoding, from left to right.
GenInstrImmediate(Opcode opcode,Register rs,Register rt,int32_t j,CompactBranchType is_compact_branch)1074 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt,
1075                                   int32_t j,
1076                                   CompactBranchType is_compact_branch) {
1077   DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
1078   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1079       | (j & kImm16Mask);
1080   emit(instr, is_compact_branch);
1081 }
1082 
1083 
GenInstrImmediate(Opcode opcode,Register rs,SecondaryField SF,int32_t j,CompactBranchType is_compact_branch)1084 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF,
1085                                   int32_t j,
1086                                   CompactBranchType is_compact_branch) {
1087   DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j)));
1088   Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
1089   emit(instr, is_compact_branch);
1090 }
1091 
1092 
GenInstrImmediate(Opcode opcode,Register rs,FPURegister ft,int32_t j,CompactBranchType is_compact_branch)1093 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft,
1094                                   int32_t j,
1095                                   CompactBranchType is_compact_branch) {
1096   DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
1097   Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
1098       | (j & kImm16Mask);
1099   emit(instr, is_compact_branch);
1100 }
1101 
1102 
GenInstrImmediate(Opcode opcode,Register rs,int32_t offset21,CompactBranchType is_compact_branch)1103 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21,
1104                                   CompactBranchType is_compact_branch) {
1105   DCHECK(rs.is_valid() && (is_int21(offset21)));
1106   Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
1107   emit(instr, is_compact_branch);
1108 }
1109 
1110 
GenInstrImmediate(Opcode opcode,Register rs,uint32_t offset21)1111 void Assembler::GenInstrImmediate(Opcode opcode, Register rs,
1112                                   uint32_t offset21) {
1113   DCHECK(rs.is_valid() && (is_uint21(offset21)));
1114   Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
1115   emit(instr);
1116 }
1117 
1118 
GenInstrImmediate(Opcode opcode,int32_t offset26,CompactBranchType is_compact_branch)1119 void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26,
1120                                   CompactBranchType is_compact_branch) {
1121   DCHECK(is_int26(offset26));
1122   Instr instr = opcode | (offset26 & kImm26Mask);
1123   emit(instr, is_compact_branch);
1124 }
1125 
1126 
GenInstrJump(Opcode opcode,uint32_t address)1127 void Assembler::GenInstrJump(Opcode opcode,
1128                              uint32_t address) {
1129   BlockTrampolinePoolScope block_trampoline_pool(this);
1130   DCHECK(is_uint26(address));
1131   Instr instr = opcode | address;
1132   emit(instr);
1133   BlockTrampolinePoolFor(1);  // For associated delay slot.
1134 }
1135 
1136 
1137 // Returns the next free trampoline entry.
get_trampoline_entry(int32_t pos)1138 int32_t Assembler::get_trampoline_entry(int32_t pos) {
1139   int32_t trampoline_entry = kInvalidSlotPos;
1140   if (!internal_trampoline_exception_) {
1141     if (trampoline_.start() > pos) {
1142      trampoline_entry = trampoline_.take_slot();
1143     }
1144 
1145     if (kInvalidSlotPos == trampoline_entry) {
1146       internal_trampoline_exception_ = true;
1147     }
1148   }
1149   return trampoline_entry;
1150 }
1151 
1152 
jump_address(Label * L)1153 uint64_t Assembler::jump_address(Label* L) {
1154   int64_t target_pos;
1155   if (L->is_bound()) {
1156     target_pos = L->pos();
1157   } else {
1158     if (L->is_linked()) {
1159       target_pos = L->pos();  // L's link.
1160       L->link_to(pc_offset());
1161     } else {
1162       L->link_to(pc_offset());
1163       return kEndOfJumpChain;
1164     }
1165   }
1166   uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos;
1167   DCHECK((imm & 3) == 0);
1168 
1169   return imm;
1170 }
1171 
1172 
jump_offset(Label * L)1173 uint64_t Assembler::jump_offset(Label* L) {
1174   int64_t target_pos;
1175   int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0;
1176 
1177   if (L->is_bound()) {
1178     target_pos = L->pos();
1179   } else {
1180     if (L->is_linked()) {
1181       target_pos = L->pos();  // L's link.
1182       L->link_to(pc_offset() + pad);
1183     } else {
1184       L->link_to(pc_offset() + pad);
1185       return kEndOfJumpChain;
1186     }
1187   }
1188   int64_t imm = target_pos - (pc_offset() + pad);
1189   DCHECK((imm & 3) == 0);
1190 
1191   return static_cast<uint64_t>(imm);
1192 }
1193 
1194 
branch_offset_helper(Label * L,OffsetSize bits)1195 int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) {
1196   int32_t target_pos;
1197   int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0;
1198 
1199   if (L->is_bound()) {
1200     target_pos = L->pos();
1201   } else {
1202     if (L->is_linked()) {
1203       target_pos = L->pos();
1204       L->link_to(pc_offset() + pad);
1205     } else {
1206       L->link_to(pc_offset() + pad);
1207       if (!trampoline_emitted_) {
1208         unbound_labels_count_++;
1209         next_buffer_check_ -= kTrampolineSlotsSize;
1210       }
1211       return kEndOfChain;
1212     }
1213   }
1214 
1215   int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad);
1216   DCHECK(is_intn(offset, bits + 2));
1217   DCHECK((offset & 3) == 0);
1218 
1219   return offset;
1220 }
1221 
1222 
label_at_put(Label * L,int at_offset)1223 void Assembler::label_at_put(Label* L, int at_offset) {
1224   int target_pos;
1225   if (L->is_bound()) {
1226     target_pos = L->pos();
1227     instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1228   } else {
1229     if (L->is_linked()) {
1230       target_pos = L->pos();  // L's link.
1231       int32_t imm18 = target_pos - at_offset;
1232       DCHECK((imm18 & 3) == 0);
1233       int32_t imm16 = imm18 >> 2;
1234       DCHECK(is_int16(imm16));
1235       instr_at_put(at_offset, (imm16 & kImm16Mask));
1236     } else {
1237       target_pos = kEndOfChain;
1238       instr_at_put(at_offset, 0);
1239       if (!trampoline_emitted_) {
1240         unbound_labels_count_++;
1241         next_buffer_check_ -= kTrampolineSlotsSize;
1242       }
1243     }
1244     L->link_to(at_offset);
1245   }
1246 }
1247 
1248 
1249 //------- Branch and jump instructions --------
1250 
b(int16_t offset)1251 void Assembler::b(int16_t offset) {
1252   beq(zero_reg, zero_reg, offset);
1253 }
1254 
1255 
bal(int16_t offset)1256 void Assembler::bal(int16_t offset) {
1257   bgezal(zero_reg, offset);
1258 }
1259 
1260 
bc(int32_t offset)1261 void Assembler::bc(int32_t offset) {
1262   DCHECK(kArchVariant == kMips64r6);
1263   GenInstrImmediate(BC, offset, CompactBranchType::COMPACT_BRANCH);
1264 }
1265 
1266 
balc(int32_t offset)1267 void Assembler::balc(int32_t offset) {
1268   DCHECK(kArchVariant == kMips64r6);
1269   GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH);
1270 }
1271 
1272 
beq(Register rs,Register rt,int16_t offset)1273 void Assembler::beq(Register rs, Register rt, int16_t offset) {
1274   BlockTrampolinePoolScope block_trampoline_pool(this);
1275   GenInstrImmediate(BEQ, rs, rt, offset);
1276   BlockTrampolinePoolFor(1);  // For associated delay slot.
1277 }
1278 
1279 
bgez(Register rs,int16_t offset)1280 void Assembler::bgez(Register rs, int16_t offset) {
1281   BlockTrampolinePoolScope block_trampoline_pool(this);
1282   GenInstrImmediate(REGIMM, rs, BGEZ, offset);
1283   BlockTrampolinePoolFor(1);  // For associated delay slot.
1284 }
1285 
1286 
bgezc(Register rt,int16_t offset)1287 void Assembler::bgezc(Register rt, int16_t offset) {
1288   DCHECK(kArchVariant == kMips64r6);
1289   DCHECK(!(rt.is(zero_reg)));
1290   GenInstrImmediate(BLEZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1291 }
1292 
1293 
bgeuc(Register rs,Register rt,int16_t offset)1294 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) {
1295   DCHECK(kArchVariant == kMips64r6);
1296   DCHECK(!(rs.is(zero_reg)));
1297   DCHECK(!(rt.is(zero_reg)));
1298   DCHECK(rs.code() != rt.code());
1299   GenInstrImmediate(BLEZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1300 }
1301 
1302 
bgec(Register rs,Register rt,int16_t offset)1303 void Assembler::bgec(Register rs, Register rt, int16_t offset) {
1304   DCHECK(kArchVariant == kMips64r6);
1305   DCHECK(!(rs.is(zero_reg)));
1306   DCHECK(!(rt.is(zero_reg)));
1307   DCHECK(rs.code() != rt.code());
1308   GenInstrImmediate(BLEZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1309 }
1310 
1311 
bgezal(Register rs,int16_t offset)1312 void Assembler::bgezal(Register rs, int16_t offset) {
1313   DCHECK(kArchVariant != kMips64r6 || rs.is(zero_reg));
1314   BlockTrampolinePoolScope block_trampoline_pool(this);
1315   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
1316   BlockTrampolinePoolFor(1);  // For associated delay slot.
1317 }
1318 
1319 
bgtz(Register rs,int16_t offset)1320 void Assembler::bgtz(Register rs, int16_t offset) {
1321   BlockTrampolinePoolScope block_trampoline_pool(this);
1322   GenInstrImmediate(BGTZ, rs, zero_reg, offset);
1323   BlockTrampolinePoolFor(1);  // For associated delay slot.
1324 }
1325 
1326 
bgtzc(Register rt,int16_t offset)1327 void Assembler::bgtzc(Register rt, int16_t offset) {
1328   DCHECK(kArchVariant == kMips64r6);
1329   DCHECK(!(rt.is(zero_reg)));
1330   GenInstrImmediate(BGTZL, zero_reg, rt, offset,
1331                     CompactBranchType::COMPACT_BRANCH);
1332 }
1333 
1334 
blez(Register rs,int16_t offset)1335 void Assembler::blez(Register rs, int16_t offset) {
1336   BlockTrampolinePoolScope block_trampoline_pool(this);
1337   GenInstrImmediate(BLEZ, rs, zero_reg, offset);
1338   BlockTrampolinePoolFor(1);  // For associated delay slot.
1339 }
1340 
1341 
blezc(Register rt,int16_t offset)1342 void Assembler::blezc(Register rt, int16_t offset) {
1343   DCHECK(kArchVariant == kMips64r6);
1344   DCHECK(!(rt.is(zero_reg)));
1345   GenInstrImmediate(BLEZL, zero_reg, rt, offset,
1346                     CompactBranchType::COMPACT_BRANCH);
1347 }
1348 
1349 
bltzc(Register rt,int16_t offset)1350 void Assembler::bltzc(Register rt, int16_t offset) {
1351   DCHECK(kArchVariant == kMips64r6);
1352   DCHECK(!rt.is(zero_reg));
1353   GenInstrImmediate(BGTZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1354 }
1355 
1356 
bltuc(Register rs,Register rt,int16_t offset)1357 void Assembler::bltuc(Register rs, Register rt, int16_t offset) {
1358   DCHECK(kArchVariant == kMips64r6);
1359   DCHECK(!(rs.is(zero_reg)));
1360   DCHECK(!(rt.is(zero_reg)));
1361   DCHECK(rs.code() != rt.code());
1362   GenInstrImmediate(BGTZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1363 }
1364 
1365 
bltc(Register rs,Register rt,int16_t offset)1366 void Assembler::bltc(Register rs, Register rt, int16_t offset) {
1367   DCHECK(kArchVariant == kMips64r6);
1368   DCHECK(!rs.is(zero_reg));
1369   DCHECK(!rt.is(zero_reg));
1370   DCHECK(rs.code() != rt.code());
1371   GenInstrImmediate(BGTZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1372 }
1373 
1374 
bltz(Register rs,int16_t offset)1375 void Assembler::bltz(Register rs, int16_t offset) {
1376   BlockTrampolinePoolScope block_trampoline_pool(this);
1377   GenInstrImmediate(REGIMM, rs, BLTZ, offset);
1378   BlockTrampolinePoolFor(1);  // For associated delay slot.
1379 }
1380 
1381 
bltzal(Register rs,int16_t offset)1382 void Assembler::bltzal(Register rs, int16_t offset) {
1383   DCHECK(kArchVariant != kMips64r6 || rs.is(zero_reg));
1384   BlockTrampolinePoolScope block_trampoline_pool(this);
1385   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
1386   BlockTrampolinePoolFor(1);  // For associated delay slot.
1387 }
1388 
1389 
bne(Register rs,Register rt,int16_t offset)1390 void Assembler::bne(Register rs, Register rt, int16_t offset) {
1391   BlockTrampolinePoolScope block_trampoline_pool(this);
1392   GenInstrImmediate(BNE, rs, rt, offset);
1393   BlockTrampolinePoolFor(1);  // For associated delay slot.
1394 }
1395 
1396 
bovc(Register rs,Register rt,int16_t offset)1397 void Assembler::bovc(Register rs, Register rt, int16_t offset) {
1398   DCHECK(kArchVariant == kMips64r6);
1399   if (rs.code() >= rt.code()) {
1400     GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1401   } else {
1402     GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1403   }
1404 }
1405 
1406 
bnvc(Register rs,Register rt,int16_t offset)1407 void Assembler::bnvc(Register rs, Register rt, int16_t offset) {
1408   DCHECK(kArchVariant == kMips64r6);
1409   if (rs.code() >= rt.code()) {
1410     GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1411   } else {
1412     GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1413   }
1414 }
1415 
1416 
blezalc(Register rt,int16_t offset)1417 void Assembler::blezalc(Register rt, int16_t offset) {
1418   DCHECK(kArchVariant == kMips64r6);
1419   DCHECK(!(rt.is(zero_reg)));
1420   GenInstrImmediate(BLEZ, zero_reg, rt, offset,
1421                     CompactBranchType::COMPACT_BRANCH);
1422 }
1423 
1424 
bgezalc(Register rt,int16_t offset)1425 void Assembler::bgezalc(Register rt, int16_t offset) {
1426   DCHECK(kArchVariant == kMips64r6);
1427   DCHECK(!(rt.is(zero_reg)));
1428   GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1429 }
1430 
1431 
bgezall(Register rs,int16_t offset)1432 void Assembler::bgezall(Register rs, int16_t offset) {
1433   DCHECK(kArchVariant != kMips64r6);
1434   DCHECK(!(rs.is(zero_reg)));
1435   BlockTrampolinePoolScope block_trampoline_pool(this);
1436   GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
1437   BlockTrampolinePoolFor(1);  // For associated delay slot.
1438 }
1439 
1440 
bltzalc(Register rt,int16_t offset)1441 void Assembler::bltzalc(Register rt, int16_t offset) {
1442   DCHECK(kArchVariant == kMips64r6);
1443   DCHECK(!(rt.is(zero_reg)));
1444   GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1445 }
1446 
1447 
bgtzalc(Register rt,int16_t offset)1448 void Assembler::bgtzalc(Register rt, int16_t offset) {
1449   DCHECK(kArchVariant == kMips64r6);
1450   DCHECK(!(rt.is(zero_reg)));
1451   GenInstrImmediate(BGTZ, zero_reg, rt, offset,
1452                     CompactBranchType::COMPACT_BRANCH);
1453 }
1454 
1455 
beqzalc(Register rt,int16_t offset)1456 void Assembler::beqzalc(Register rt, int16_t offset) {
1457   DCHECK(kArchVariant == kMips64r6);
1458   DCHECK(!(rt.is(zero_reg)));
1459   GenInstrImmediate(ADDI, zero_reg, rt, offset,
1460                     CompactBranchType::COMPACT_BRANCH);
1461 }
1462 
1463 
bnezalc(Register rt,int16_t offset)1464 void Assembler::bnezalc(Register rt, int16_t offset) {
1465   DCHECK(kArchVariant == kMips64r6);
1466   DCHECK(!(rt.is(zero_reg)));
1467   GenInstrImmediate(DADDI, zero_reg, rt, offset,
1468                     CompactBranchType::COMPACT_BRANCH);
1469 }
1470 
1471 
beqc(Register rs,Register rt,int16_t offset)1472 void Assembler::beqc(Register rs, Register rt, int16_t offset) {
1473   DCHECK(kArchVariant == kMips64r6);
1474   DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1475   if (rs.code() < rt.code()) {
1476     GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1477   } else {
1478     GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1479   }
1480 }
1481 
1482 
beqzc(Register rs,int32_t offset)1483 void Assembler::beqzc(Register rs, int32_t offset) {
1484   DCHECK(kArchVariant == kMips64r6);
1485   DCHECK(!(rs.is(zero_reg)));
1486   GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH);
1487 }
1488 
1489 
bnec(Register rs,Register rt,int16_t offset)1490 void Assembler::bnec(Register rs, Register rt, int16_t offset) {
1491   DCHECK(kArchVariant == kMips64r6);
1492   DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1493   if (rs.code() < rt.code()) {
1494     GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1495   } else {
1496     GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1497   }
1498 }
1499 
1500 
bnezc(Register rs,int32_t offset)1501 void Assembler::bnezc(Register rs, int32_t offset) {
1502   DCHECK(kArchVariant == kMips64r6);
1503   DCHECK(!(rs.is(zero_reg)));
1504   GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH);
1505 }
1506 
1507 
j(int64_t target)1508 void Assembler::j(int64_t target) {
1509   BlockTrampolinePoolScope block_trampoline_pool(this);
1510   GenInstrJump(J, static_cast<uint32_t>(target >> 2) & kImm26Mask);
1511   BlockTrampolinePoolFor(1);  // For associated delay slot.
1512 }
1513 
1514 
j(Label * target)1515 void Assembler::j(Label* target) {
1516   uint64_t imm = jump_offset(target);
1517   if (target->is_bound()) {
1518     BlockTrampolinePoolScope block_trampoline_pool(this);
1519     GenInstrJump(static_cast<Opcode>(kJRawMark),
1520                  static_cast<uint32_t>(imm >> 2) & kImm26Mask);
1521     BlockTrampolinePoolFor(1);  // For associated delay slot.
1522   } else {
1523     j(imm);
1524   }
1525 }
1526 
1527 
jal(Label * target)1528 void Assembler::jal(Label* target) {
1529   uint64_t imm = jump_offset(target);
1530   if (target->is_bound()) {
1531     BlockTrampolinePoolScope block_trampoline_pool(this);
1532     GenInstrJump(static_cast<Opcode>(kJalRawMark),
1533                  static_cast<uint32_t>(imm >> 2) & kImm26Mask);
1534     BlockTrampolinePoolFor(1);  // For associated delay slot.
1535   } else {
1536     jal(imm);
1537   }
1538 }
1539 
1540 
jr(Register rs)1541 void Assembler::jr(Register rs) {
1542   if (kArchVariant != kMips64r6) {
1543     BlockTrampolinePoolScope block_trampoline_pool(this);
1544     GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
1545     BlockTrampolinePoolFor(1);  // For associated delay slot.
1546   } else {
1547     jalr(rs, zero_reg);
1548   }
1549 }
1550 
1551 
jal(int64_t target)1552 void Assembler::jal(int64_t target) {
1553   BlockTrampolinePoolScope block_trampoline_pool(this);
1554   GenInstrJump(JAL, static_cast<uint32_t>(target >> 2) & kImm26Mask);
1555   BlockTrampolinePoolFor(1);  // For associated delay slot.
1556 }
1557 
1558 
jalr(Register rs,Register rd)1559 void Assembler::jalr(Register rs, Register rd) {
1560   DCHECK(rs.code() != rd.code());
1561   BlockTrampolinePoolScope block_trampoline_pool(this);
1562   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
1563   BlockTrampolinePoolFor(1);  // For associated delay slot.
1564 }
1565 
1566 
jic(Register rt,int16_t offset)1567 void Assembler::jic(Register rt, int16_t offset) {
1568   DCHECK(kArchVariant == kMips64r6);
1569   GenInstrImmediate(POP66, zero_reg, rt, offset);
1570 }
1571 
1572 
jialc(Register rt,int16_t offset)1573 void Assembler::jialc(Register rt, int16_t offset) {
1574   DCHECK(kArchVariant == kMips64r6);
1575   GenInstrImmediate(POP76, zero_reg, rt, offset);
1576 }
1577 
1578 
1579 // -------Data-processing-instructions---------
1580 
1581 // Arithmetic.
1582 
addu(Register rd,Register rs,Register rt)1583 void Assembler::addu(Register rd, Register rs, Register rt) {
1584   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
1585 }
1586 
1587 
addiu(Register rd,Register rs,int32_t j)1588 void Assembler::addiu(Register rd, Register rs, int32_t j) {
1589   GenInstrImmediate(ADDIU, rs, rd, j);
1590 }
1591 
1592 
subu(Register rd,Register rs,Register rt)1593 void Assembler::subu(Register rd, Register rs, Register rt) {
1594   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
1595 }
1596 
1597 
mul(Register rd,Register rs,Register rt)1598 void Assembler::mul(Register rd, Register rs, Register rt) {
1599   if (kArchVariant == kMips64r6) {
1600       GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH);
1601   } else {
1602       GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
1603   }
1604 }
1605 
1606 
muh(Register rd,Register rs,Register rt)1607 void Assembler::muh(Register rd, Register rs, Register rt) {
1608   DCHECK(kArchVariant == kMips64r6);
1609   GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH);
1610 }
1611 
1612 
mulu(Register rd,Register rs,Register rt)1613 void Assembler::mulu(Register rd, Register rs, Register rt) {
1614   DCHECK(kArchVariant == kMips64r6);
1615   GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH_U);
1616 }
1617 
1618 
muhu(Register rd,Register rs,Register rt)1619 void Assembler::muhu(Register rd, Register rs, Register rt) {
1620   DCHECK(kArchVariant == kMips64r6);
1621   GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH_U);
1622 }
1623 
1624 
dmul(Register rd,Register rs,Register rt)1625 void Assembler::dmul(Register rd, Register rs, Register rt) {
1626   DCHECK(kArchVariant == kMips64r6);
1627   GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH);
1628 }
1629 
1630 
dmuh(Register rd,Register rs,Register rt)1631 void Assembler::dmuh(Register rd, Register rs, Register rt) {
1632   DCHECK(kArchVariant == kMips64r6);
1633   GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH);
1634 }
1635 
1636 
dmulu(Register rd,Register rs,Register rt)1637 void Assembler::dmulu(Register rd, Register rs, Register rt) {
1638   DCHECK(kArchVariant == kMips64r6);
1639   GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH_U);
1640 }
1641 
1642 
dmuhu(Register rd,Register rs,Register rt)1643 void Assembler::dmuhu(Register rd, Register rs, Register rt) {
1644   DCHECK(kArchVariant == kMips64r6);
1645   GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH_U);
1646 }
1647 
1648 
mult(Register rs,Register rt)1649 void Assembler::mult(Register rs, Register rt) {
1650   DCHECK(kArchVariant != kMips64r6);
1651   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
1652 }
1653 
1654 
multu(Register rs,Register rt)1655 void Assembler::multu(Register rs, Register rt) {
1656   DCHECK(kArchVariant != kMips64r6);
1657   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
1658 }
1659 
1660 
daddiu(Register rd,Register rs,int32_t j)1661 void Assembler::daddiu(Register rd, Register rs, int32_t j) {
1662   GenInstrImmediate(DADDIU, rs, rd, j);
1663 }
1664 
1665 
div(Register rs,Register rt)1666 void Assembler::div(Register rs, Register rt) {
1667   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
1668 }
1669 
1670 
div(Register rd,Register rs,Register rt)1671 void Assembler::div(Register rd, Register rs, Register rt) {
1672   DCHECK(kArchVariant == kMips64r6);
1673   GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD);
1674 }
1675 
1676 
mod(Register rd,Register rs,Register rt)1677 void Assembler::mod(Register rd, Register rs, Register rt) {
1678   DCHECK(kArchVariant == kMips64r6);
1679   GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD);
1680 }
1681 
1682 
divu(Register rs,Register rt)1683 void Assembler::divu(Register rs, Register rt) {
1684   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
1685 }
1686 
1687 
divu(Register rd,Register rs,Register rt)1688 void Assembler::divu(Register rd, Register rs, Register rt) {
1689   DCHECK(kArchVariant == kMips64r6);
1690   GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD_U);
1691 }
1692 
1693 
modu(Register rd,Register rs,Register rt)1694 void Assembler::modu(Register rd, Register rs, Register rt) {
1695   DCHECK(kArchVariant == kMips64r6);
1696   GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD_U);
1697 }
1698 
1699 
daddu(Register rd,Register rs,Register rt)1700 void Assembler::daddu(Register rd, Register rs, Register rt) {
1701   GenInstrRegister(SPECIAL, rs, rt, rd, 0, DADDU);
1702 }
1703 
1704 
dsubu(Register rd,Register rs,Register rt)1705 void Assembler::dsubu(Register rd, Register rs, Register rt) {
1706   GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSUBU);
1707 }
1708 
1709 
dmult(Register rs,Register rt)1710 void Assembler::dmult(Register rs, Register rt) {
1711   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULT);
1712 }
1713 
1714 
dmultu(Register rs,Register rt)1715 void Assembler::dmultu(Register rs, Register rt) {
1716   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULTU);
1717 }
1718 
1719 
ddiv(Register rs,Register rt)1720 void Assembler::ddiv(Register rs, Register rt) {
1721   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIV);
1722 }
1723 
1724 
ddiv(Register rd,Register rs,Register rt)1725 void Assembler::ddiv(Register rd, Register rs, Register rt) {
1726   DCHECK(kArchVariant == kMips64r6);
1727   GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD);
1728 }
1729 
1730 
dmod(Register rd,Register rs,Register rt)1731 void Assembler::dmod(Register rd, Register rs, Register rt) {
1732   DCHECK(kArchVariant == kMips64r6);
1733   GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD);
1734 }
1735 
1736 
ddivu(Register rs,Register rt)1737 void Assembler::ddivu(Register rs, Register rt) {
1738   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIVU);
1739 }
1740 
1741 
ddivu(Register rd,Register rs,Register rt)1742 void Assembler::ddivu(Register rd, Register rs, Register rt) {
1743   DCHECK(kArchVariant == kMips64r6);
1744   GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD_U);
1745 }
1746 
1747 
dmodu(Register rd,Register rs,Register rt)1748 void Assembler::dmodu(Register rd, Register rs, Register rt) {
1749   DCHECK(kArchVariant == kMips64r6);
1750   GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD_U);
1751 }
1752 
1753 
1754 // Logical.
1755 
and_(Register rd,Register rs,Register rt)1756 void Assembler::and_(Register rd, Register rs, Register rt) {
1757   GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
1758 }
1759 
1760 
andi(Register rt,Register rs,int32_t j)1761 void Assembler::andi(Register rt, Register rs, int32_t j) {
1762   DCHECK(is_uint16(j));
1763   GenInstrImmediate(ANDI, rs, rt, j);
1764 }
1765 
1766 
or_(Register rd,Register rs,Register rt)1767 void Assembler::or_(Register rd, Register rs, Register rt) {
1768   GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
1769 }
1770 
1771 
ori(Register rt,Register rs,int32_t j)1772 void Assembler::ori(Register rt, Register rs, int32_t j) {
1773   DCHECK(is_uint16(j));
1774   GenInstrImmediate(ORI, rs, rt, j);
1775 }
1776 
1777 
xor_(Register rd,Register rs,Register rt)1778 void Assembler::xor_(Register rd, Register rs, Register rt) {
1779   GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
1780 }
1781 
1782 
xori(Register rt,Register rs,int32_t j)1783 void Assembler::xori(Register rt, Register rs, int32_t j) {
1784   DCHECK(is_uint16(j));
1785   GenInstrImmediate(XORI, rs, rt, j);
1786 }
1787 
1788 
nor(Register rd,Register rs,Register rt)1789 void Assembler::nor(Register rd, Register rs, Register rt) {
1790   GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
1791 }
1792 
1793 
1794 // Shifts.
sll(Register rd,Register rt,uint16_t sa,bool coming_from_nop)1795 void Assembler::sll(Register rd,
1796                     Register rt,
1797                     uint16_t sa,
1798                     bool coming_from_nop) {
1799   // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
1800   // generated using the sll instruction. They must be generated using
1801   // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
1802   // instructions.
1803   DCHECK(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
1804   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SLL);
1805 }
1806 
1807 
sllv(Register rd,Register rt,Register rs)1808 void Assembler::sllv(Register rd, Register rt, Register rs) {
1809   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
1810 }
1811 
1812 
srl(Register rd,Register rt,uint16_t sa)1813 void Assembler::srl(Register rd, Register rt, uint16_t sa) {
1814   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRL);
1815 }
1816 
1817 
srlv(Register rd,Register rt,Register rs)1818 void Assembler::srlv(Register rd, Register rt, Register rs) {
1819   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
1820 }
1821 
1822 
sra(Register rd,Register rt,uint16_t sa)1823 void Assembler::sra(Register rd, Register rt, uint16_t sa) {
1824   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRA);
1825 }
1826 
1827 
srav(Register rd,Register rt,Register rs)1828 void Assembler::srav(Register rd, Register rt, Register rs) {
1829   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
1830 }
1831 
1832 
rotr(Register rd,Register rt,uint16_t sa)1833 void Assembler::rotr(Register rd, Register rt, uint16_t sa) {
1834   // Should be called via MacroAssembler::Ror.
1835   DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1836   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
1837   Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
1838       | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
1839   emit(instr);
1840 }
1841 
1842 
rotrv(Register rd,Register rt,Register rs)1843 void Assembler::rotrv(Register rd, Register rt, Register rs) {
1844   // Should be called via MacroAssembler::Ror.
1845   DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1846   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
1847   Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1848      | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
1849   emit(instr);
1850 }
1851 
1852 
dsll(Register rd,Register rt,uint16_t sa)1853 void Assembler::dsll(Register rd, Register rt, uint16_t sa) {
1854   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL);
1855 }
1856 
1857 
dsllv(Register rd,Register rt,Register rs)1858 void Assembler::dsllv(Register rd, Register rt, Register rs) {
1859   GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSLLV);
1860 }
1861 
1862 
dsrl(Register rd,Register rt,uint16_t sa)1863 void Assembler::dsrl(Register rd, Register rt, uint16_t sa) {
1864   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL);
1865 }
1866 
1867 
dsrlv(Register rd,Register rt,Register rs)1868 void Assembler::dsrlv(Register rd, Register rt, Register rs) {
1869   GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRLV);
1870 }
1871 
1872 
drotr(Register rd,Register rt,uint16_t sa)1873 void Assembler::drotr(Register rd, Register rt, uint16_t sa) {
1874   DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1875   Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
1876       | (rd.code() << kRdShift) | (sa << kSaShift) | DSRL;
1877   emit(instr);
1878 }
1879 
drotr32(Register rd,Register rt,uint16_t sa)1880 void Assembler::drotr32(Register rd, Register rt, uint16_t sa) {
1881   DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1882   Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) |
1883                 (rd.code() << kRdShift) | (sa << kSaShift) | DSRL32;
1884   emit(instr);
1885 }
1886 
drotrv(Register rd,Register rt,Register rs)1887 void Assembler::drotrv(Register rd, Register rt, Register rs) {
1888   DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid() );
1889   Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1890       | (rd.code() << kRdShift) | (1 << kSaShift) | DSRLV;
1891   emit(instr);
1892 }
1893 
1894 
dsra(Register rd,Register rt,uint16_t sa)1895 void Assembler::dsra(Register rd, Register rt, uint16_t sa) {
1896   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA);
1897 }
1898 
1899 
dsrav(Register rd,Register rt,Register rs)1900 void Assembler::dsrav(Register rd, Register rt, Register rs) {
1901   GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRAV);
1902 }
1903 
1904 
dsll32(Register rd,Register rt,uint16_t sa)1905 void Assembler::dsll32(Register rd, Register rt, uint16_t sa) {
1906   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL32);
1907 }
1908 
1909 
dsrl32(Register rd,Register rt,uint16_t sa)1910 void Assembler::dsrl32(Register rd, Register rt, uint16_t sa) {
1911   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL32);
1912 }
1913 
1914 
dsra32(Register rd,Register rt,uint16_t sa)1915 void Assembler::dsra32(Register rd, Register rt, uint16_t sa) {
1916   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA32);
1917 }
1918 
1919 
lsa(Register rd,Register rt,Register rs,uint8_t sa)1920 void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) {
1921   DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1922   DCHECK(sa <= 3);
1923   DCHECK(kArchVariant == kMips64r6);
1924   Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift |
1925                 rd.code() << kRdShift | sa << kSaShift | LSA;
1926   emit(instr);
1927 }
1928 
1929 
dlsa(Register rd,Register rt,Register rs,uint8_t sa)1930 void Assembler::dlsa(Register rd, Register rt, Register rs, uint8_t sa) {
1931   DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1932   DCHECK(sa <= 3);
1933   DCHECK(kArchVariant == kMips64r6);
1934   Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift |
1935                 rd.code() << kRdShift | sa << kSaShift | DLSA;
1936   emit(instr);
1937 }
1938 
1939 
1940 // ------------Memory-instructions-------------
1941 
1942 // Helper for base-reg + offset, when offset is larger than int16.
LoadRegPlusOffsetToAt(const MemOperand & src)1943 void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
1944   DCHECK(!src.rm().is(at));
1945   DCHECK(is_int32(src.offset_));
1946   daddiu(at, zero_reg, (src.offset_ >> kLuiShift) & kImm16Mask);
1947   dsll(at, at, kLuiShift);
1948   ori(at, at, src.offset_ & kImm16Mask);  // Load 32-bit offset.
1949   daddu(at, at, src.rm());  // Add base register.
1950 }
1951 
1952 
lb(Register rd,const MemOperand & rs)1953 void Assembler::lb(Register rd, const MemOperand& rs) {
1954   if (is_int16(rs.offset_)) {
1955     GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
1956   } else {  // Offset > 16 bits, use multiple instructions to load.
1957     LoadRegPlusOffsetToAt(rs);
1958     GenInstrImmediate(LB, at, rd, 0);  // Equiv to lb(rd, MemOperand(at, 0));
1959   }
1960 }
1961 
1962 
lbu(Register rd,const MemOperand & rs)1963 void Assembler::lbu(Register rd, const MemOperand& rs) {
1964   if (is_int16(rs.offset_)) {
1965     GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
1966   } else {  // Offset > 16 bits, use multiple instructions to load.
1967     LoadRegPlusOffsetToAt(rs);
1968     GenInstrImmediate(LBU, at, rd, 0);  // Equiv to lbu(rd, MemOperand(at, 0));
1969   }
1970 }
1971 
1972 
lh(Register rd,const MemOperand & rs)1973 void Assembler::lh(Register rd, const MemOperand& rs) {
1974   if (is_int16(rs.offset_)) {
1975     GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
1976   } else {  // Offset > 16 bits, use multiple instructions to load.
1977     LoadRegPlusOffsetToAt(rs);
1978     GenInstrImmediate(LH, at, rd, 0);  // Equiv to lh(rd, MemOperand(at, 0));
1979   }
1980 }
1981 
1982 
lhu(Register rd,const MemOperand & rs)1983 void Assembler::lhu(Register rd, const MemOperand& rs) {
1984   if (is_int16(rs.offset_)) {
1985     GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
1986   } else {  // Offset > 16 bits, use multiple instructions to load.
1987     LoadRegPlusOffsetToAt(rs);
1988     GenInstrImmediate(LHU, at, rd, 0);  // Equiv to lhu(rd, MemOperand(at, 0));
1989   }
1990 }
1991 
1992 
lw(Register rd,const MemOperand & rs)1993 void Assembler::lw(Register rd, const MemOperand& rs) {
1994   if (is_int16(rs.offset_)) {
1995     GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
1996   } else {  // Offset > 16 bits, use multiple instructions to load.
1997     LoadRegPlusOffsetToAt(rs);
1998     GenInstrImmediate(LW, at, rd, 0);  // Equiv to lw(rd, MemOperand(at, 0));
1999   }
2000 }
2001 
2002 
lwu(Register rd,const MemOperand & rs)2003 void Assembler::lwu(Register rd, const MemOperand& rs) {
2004   if (is_int16(rs.offset_)) {
2005     GenInstrImmediate(LWU, rs.rm(), rd, rs.offset_);
2006   } else {  // Offset > 16 bits, use multiple instructions to load.
2007     LoadRegPlusOffsetToAt(rs);
2008     GenInstrImmediate(LWU, at, rd, 0);  // Equiv to lwu(rd, MemOperand(at, 0));
2009   }
2010 }
2011 
2012 
lwl(Register rd,const MemOperand & rs)2013 void Assembler::lwl(Register rd, const MemOperand& rs) {
2014   DCHECK(is_int16(rs.offset_));
2015   DCHECK(kArchVariant == kMips64r2);
2016   GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
2017 }
2018 
2019 
lwr(Register rd,const MemOperand & rs)2020 void Assembler::lwr(Register rd, const MemOperand& rs) {
2021   DCHECK(is_int16(rs.offset_));
2022   DCHECK(kArchVariant == kMips64r2);
2023   GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
2024 }
2025 
2026 
sb(Register rd,const MemOperand & rs)2027 void Assembler::sb(Register rd, const MemOperand& rs) {
2028   if (is_int16(rs.offset_)) {
2029     GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
2030   } else {  // Offset > 16 bits, use multiple instructions to store.
2031     LoadRegPlusOffsetToAt(rs);
2032     GenInstrImmediate(SB, at, rd, 0);  // Equiv to sb(rd, MemOperand(at, 0));
2033   }
2034 }
2035 
2036 
sh(Register rd,const MemOperand & rs)2037 void Assembler::sh(Register rd, const MemOperand& rs) {
2038   if (is_int16(rs.offset_)) {
2039     GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
2040   } else {  // Offset > 16 bits, use multiple instructions to store.
2041     LoadRegPlusOffsetToAt(rs);
2042     GenInstrImmediate(SH, at, rd, 0);  // Equiv to sh(rd, MemOperand(at, 0));
2043   }
2044 }
2045 
2046 
sw(Register rd,const MemOperand & rs)2047 void Assembler::sw(Register rd, const MemOperand& rs) {
2048   if (is_int16(rs.offset_)) {
2049     GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
2050   } else {  // Offset > 16 bits, use multiple instructions to store.
2051     LoadRegPlusOffsetToAt(rs);
2052     GenInstrImmediate(SW, at, rd, 0);  // Equiv to sw(rd, MemOperand(at, 0));
2053   }
2054 }
2055 
2056 
swl(Register rd,const MemOperand & rs)2057 void Assembler::swl(Register rd, const MemOperand& rs) {
2058   DCHECK(is_int16(rs.offset_));
2059   DCHECK(kArchVariant == kMips64r2);
2060   GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
2061 }
2062 
2063 
swr(Register rd,const MemOperand & rs)2064 void Assembler::swr(Register rd, const MemOperand& rs) {
2065   DCHECK(is_int16(rs.offset_));
2066   DCHECK(kArchVariant == kMips64r2);
2067   GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
2068 }
2069 
2070 
lui(Register rd,int32_t j)2071 void Assembler::lui(Register rd, int32_t j) {
2072   DCHECK(is_uint16(j));
2073   GenInstrImmediate(LUI, zero_reg, rd, j);
2074 }
2075 
2076 
aui(Register rt,Register rs,int32_t j)2077 void Assembler::aui(Register rt, Register rs, int32_t j) {
2078   // This instruction uses same opcode as 'lui'. The difference in encoding is
2079   // 'lui' has zero reg. for rs field.
2080   DCHECK(is_uint16(j));
2081   GenInstrImmediate(LUI, rs, rt, j);
2082 }
2083 
2084 
daui(Register rt,Register rs,int32_t j)2085 void Assembler::daui(Register rt, Register rs, int32_t j) {
2086   DCHECK(is_uint16(j));
2087   DCHECK(!rs.is(zero_reg));
2088   GenInstrImmediate(DAUI, rs, rt, j);
2089 }
2090 
2091 
dahi(Register rs,int32_t j)2092 void Assembler::dahi(Register rs, int32_t j) {
2093   DCHECK(is_uint16(j));
2094   GenInstrImmediate(REGIMM, rs, DAHI, j);
2095 }
2096 
2097 
dati(Register rs,int32_t j)2098 void Assembler::dati(Register rs, int32_t j) {
2099   DCHECK(is_uint16(j));
2100   GenInstrImmediate(REGIMM, rs, DATI, j);
2101 }
2102 
2103 
ldl(Register rd,const MemOperand & rs)2104 void Assembler::ldl(Register rd, const MemOperand& rs) {
2105   DCHECK(is_int16(rs.offset_));
2106   DCHECK(kArchVariant == kMips64r2);
2107   GenInstrImmediate(LDL, rs.rm(), rd, rs.offset_);
2108 }
2109 
2110 
ldr(Register rd,const MemOperand & rs)2111 void Assembler::ldr(Register rd, const MemOperand& rs) {
2112   DCHECK(is_int16(rs.offset_));
2113   DCHECK(kArchVariant == kMips64r2);
2114   GenInstrImmediate(LDR, rs.rm(), rd, rs.offset_);
2115 }
2116 
2117 
sdl(Register rd,const MemOperand & rs)2118 void Assembler::sdl(Register rd, const MemOperand& rs) {
2119   DCHECK(is_int16(rs.offset_));
2120   DCHECK(kArchVariant == kMips64r2);
2121   GenInstrImmediate(SDL, rs.rm(), rd, rs.offset_);
2122 }
2123 
2124 
sdr(Register rd,const MemOperand & rs)2125 void Assembler::sdr(Register rd, const MemOperand& rs) {
2126   DCHECK(is_int16(rs.offset_));
2127   DCHECK(kArchVariant == kMips64r2);
2128   GenInstrImmediate(SDR, rs.rm(), rd, rs.offset_);
2129 }
2130 
2131 
ld(Register rd,const MemOperand & rs)2132 void Assembler::ld(Register rd, const MemOperand& rs) {
2133   if (is_int16(rs.offset_)) {
2134     GenInstrImmediate(LD, rs.rm(), rd, rs.offset_);
2135   } else {  // Offset > 16 bits, use multiple instructions to load.
2136     LoadRegPlusOffsetToAt(rs);
2137     GenInstrImmediate(LD, at, rd, 0);  // Equiv to lw(rd, MemOperand(at, 0));
2138   }
2139 }
2140 
2141 
sd(Register rd,const MemOperand & rs)2142 void Assembler::sd(Register rd, const MemOperand& rs) {
2143   if (is_int16(rs.offset_)) {
2144     GenInstrImmediate(SD, rs.rm(), rd, rs.offset_);
2145   } else {  // Offset > 16 bits, use multiple instructions to store.
2146     LoadRegPlusOffsetToAt(rs);
2147     GenInstrImmediate(SD, at, rd, 0);  // Equiv to sw(rd, MemOperand(at, 0));
2148   }
2149 }
2150 
2151 
2152 // ---------PC-Relative instructions-----------
2153 
addiupc(Register rs,int32_t imm19)2154 void Assembler::addiupc(Register rs, int32_t imm19) {
2155   DCHECK(kArchVariant == kMips64r6);
2156   DCHECK(rs.is_valid() && is_int19(imm19));
2157   uint32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask);
2158   GenInstrImmediate(PCREL, rs, imm21);
2159 }
2160 
2161 
lwpc(Register rs,int32_t offset19)2162 void Assembler::lwpc(Register rs, int32_t offset19) {
2163   DCHECK(kArchVariant == kMips64r6);
2164   DCHECK(rs.is_valid() && is_int19(offset19));
2165   uint32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask);
2166   GenInstrImmediate(PCREL, rs, imm21);
2167 }
2168 
2169 
lwupc(Register rs,int32_t offset19)2170 void Assembler::lwupc(Register rs, int32_t offset19) {
2171   DCHECK(kArchVariant == kMips64r6);
2172   DCHECK(rs.is_valid() && is_int19(offset19));
2173   uint32_t imm21 = LWUPC << kImm19Bits | (offset19 & kImm19Mask);
2174   GenInstrImmediate(PCREL, rs, imm21);
2175 }
2176 
2177 
ldpc(Register rs,int32_t offset18)2178 void Assembler::ldpc(Register rs, int32_t offset18) {
2179   DCHECK(kArchVariant == kMips64r6);
2180   DCHECK(rs.is_valid() && is_int18(offset18));
2181   uint32_t imm21 = LDPC << kImm18Bits | (offset18 & kImm18Mask);
2182   GenInstrImmediate(PCREL, rs, imm21);
2183 }
2184 
2185 
auipc(Register rs,int16_t imm16)2186 void Assembler::auipc(Register rs, int16_t imm16) {
2187   DCHECK(kArchVariant == kMips64r6);
2188   DCHECK(rs.is_valid());
2189   uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask);
2190   GenInstrImmediate(PCREL, rs, imm21);
2191 }
2192 
2193 
aluipc(Register rs,int16_t imm16)2194 void Assembler::aluipc(Register rs, int16_t imm16) {
2195   DCHECK(kArchVariant == kMips64r6);
2196   DCHECK(rs.is_valid());
2197   uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask);
2198   GenInstrImmediate(PCREL, rs, imm21);
2199 }
2200 
2201 
2202 // -------------Misc-instructions--------------
2203 
2204 // Break / Trap instructions.
break_(uint32_t code,bool break_as_stop)2205 void Assembler::break_(uint32_t code, bool break_as_stop) {
2206   DCHECK((code & ~0xfffff) == 0);
2207   // We need to invalidate breaks that could be stops as well because the
2208   // simulator expects a char pointer after the stop instruction.
2209   // See constants-mips.h for explanation.
2210   DCHECK((break_as_stop &&
2211           code <= kMaxStopCode &&
2212           code > kMaxWatchpointCode) ||
2213          (!break_as_stop &&
2214           (code > kMaxStopCode ||
2215            code <= kMaxWatchpointCode)));
2216   Instr break_instr = SPECIAL | BREAK | (code << 6);
2217   emit(break_instr);
2218 }
2219 
2220 
stop(const char * msg,uint32_t code)2221 void Assembler::stop(const char* msg, uint32_t code) {
2222   DCHECK(code > kMaxWatchpointCode);
2223   DCHECK(code <= kMaxStopCode);
2224 #if defined(V8_HOST_ARCH_MIPS) || defined(V8_HOST_ARCH_MIPS64)
2225   break_(0x54321);
2226 #else  // V8_HOST_ARCH_MIPS
2227   BlockTrampolinePoolFor(3);
2228   // The Simulator will handle the stop instruction and get the message address.
2229   // On MIPS stop() is just a special kind of break_().
2230   break_(code, true);
2231   emit(reinterpret_cast<uint64_t>(msg));
2232 #endif
2233 }
2234 
2235 
tge(Register rs,Register rt,uint16_t code)2236 void Assembler::tge(Register rs, Register rt, uint16_t code) {
2237   DCHECK(is_uint10(code));
2238   Instr instr = SPECIAL | TGE | rs.code() << kRsShift
2239       | rt.code() << kRtShift | code << 6;
2240   emit(instr);
2241 }
2242 
2243 
tgeu(Register rs,Register rt,uint16_t code)2244 void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
2245   DCHECK(is_uint10(code));
2246   Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
2247       | rt.code() << kRtShift | code << 6;
2248   emit(instr);
2249 }
2250 
2251 
tlt(Register rs,Register rt,uint16_t code)2252 void Assembler::tlt(Register rs, Register rt, uint16_t code) {
2253   DCHECK(is_uint10(code));
2254   Instr instr =
2255       SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
2256   emit(instr);
2257 }
2258 
2259 
tltu(Register rs,Register rt,uint16_t code)2260 void Assembler::tltu(Register rs, Register rt, uint16_t code) {
2261   DCHECK(is_uint10(code));
2262   Instr instr =
2263       SPECIAL | TLTU | rs.code() << kRsShift
2264       | rt.code() << kRtShift | code << 6;
2265   emit(instr);
2266 }
2267 
2268 
teq(Register rs,Register rt,uint16_t code)2269 void Assembler::teq(Register rs, Register rt, uint16_t code) {
2270   DCHECK(is_uint10(code));
2271   Instr instr =
2272       SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
2273   emit(instr);
2274 }
2275 
2276 
tne(Register rs,Register rt,uint16_t code)2277 void Assembler::tne(Register rs, Register rt, uint16_t code) {
2278   DCHECK(is_uint10(code));
2279   Instr instr =
2280       SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
2281   emit(instr);
2282 }
2283 
sync()2284 void Assembler::sync() {
2285   Instr sync_instr = SPECIAL | SYNC;
2286   emit(sync_instr);
2287 }
2288 
2289 // Move from HI/LO register.
2290 
mfhi(Register rd)2291 void Assembler::mfhi(Register rd) {
2292   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
2293 }
2294 
2295 
mflo(Register rd)2296 void Assembler::mflo(Register rd) {
2297   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
2298 }
2299 
2300 
2301 // Set on less than instructions.
slt(Register rd,Register rs,Register rt)2302 void Assembler::slt(Register rd, Register rs, Register rt) {
2303   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
2304 }
2305 
2306 
sltu(Register rd,Register rs,Register rt)2307 void Assembler::sltu(Register rd, Register rs, Register rt) {
2308   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
2309 }
2310 
2311 
slti(Register rt,Register rs,int32_t j)2312 void Assembler::slti(Register rt, Register rs, int32_t j) {
2313   GenInstrImmediate(SLTI, rs, rt, j);
2314 }
2315 
2316 
sltiu(Register rt,Register rs,int32_t j)2317 void Assembler::sltiu(Register rt, Register rs, int32_t j) {
2318   GenInstrImmediate(SLTIU, rs, rt, j);
2319 }
2320 
2321 
2322 // Conditional move.
movz(Register rd,Register rs,Register rt)2323 void Assembler::movz(Register rd, Register rs, Register rt) {
2324   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
2325 }
2326 
2327 
movn(Register rd,Register rs,Register rt)2328 void Assembler::movn(Register rd, Register rs, Register rt) {
2329   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
2330 }
2331 
2332 
movt(Register rd,Register rs,uint16_t cc)2333 void Assembler::movt(Register rd, Register rs, uint16_t cc) {
2334   Register rt;
2335   rt.reg_code = (cc & 0x0007) << 2 | 1;
2336   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
2337 }
2338 
2339 
movf(Register rd,Register rs,uint16_t cc)2340 void Assembler::movf(Register rd, Register rs, uint16_t cc) {
2341   Register rt;
2342   rt.reg_code = (cc & 0x0007) << 2 | 0;
2343   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
2344 }
2345 
2346 
min_s(FPURegister fd,FPURegister fs,FPURegister ft)2347 void Assembler::min_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2348   min(S, fd, fs, ft);
2349 }
2350 
2351 
min_d(FPURegister fd,FPURegister fs,FPURegister ft)2352 void Assembler::min_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2353   min(D, fd, fs, ft);
2354 }
2355 
2356 
max_s(FPURegister fd,FPURegister fs,FPURegister ft)2357 void Assembler::max_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2358   max(S, fd, fs, ft);
2359 }
2360 
2361 
max_d(FPURegister fd,FPURegister fs,FPURegister ft)2362 void Assembler::max_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2363   max(D, fd, fs, ft);
2364 }
2365 
2366 
mina_s(FPURegister fd,FPURegister fs,FPURegister ft)2367 void Assembler::mina_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2368   mina(S, fd, fs, ft);
2369 }
2370 
2371 
mina_d(FPURegister fd,FPURegister fs,FPURegister ft)2372 void Assembler::mina_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2373   mina(D, fd, fs, ft);
2374 }
2375 
2376 
maxa_s(FPURegister fd,FPURegister fs,FPURegister ft)2377 void Assembler::maxa_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2378   maxa(S, fd, fs, ft);
2379 }
2380 
2381 
maxa_d(FPURegister fd,FPURegister fs,FPURegister ft)2382 void Assembler::maxa_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2383   maxa(D, fd, fs, ft);
2384 }
2385 
2386 
max(SecondaryField fmt,FPURegister fd,FPURegister fs,FPURegister ft)2387 void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs,
2388                     FPURegister ft) {
2389   DCHECK(kArchVariant == kMips64r6);
2390   DCHECK((fmt == D) || (fmt == S));
2391   GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
2392 }
2393 
2394 
min(SecondaryField fmt,FPURegister fd,FPURegister fs,FPURegister ft)2395 void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
2396                     FPURegister ft) {
2397   DCHECK(kArchVariant == kMips64r6);
2398   DCHECK((fmt == D) || (fmt == S));
2399   GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
2400 }
2401 
2402 
2403 // GPR.
seleqz(Register rd,Register rs,Register rt)2404 void Assembler::seleqz(Register rd, Register rs, Register rt) {
2405   DCHECK(kArchVariant == kMips64r6);
2406   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S);
2407 }
2408 
2409 
2410 // GPR.
selnez(Register rd,Register rs,Register rt)2411 void Assembler::selnez(Register rd, Register rs, Register rt) {
2412   DCHECK(kArchVariant == kMips64r6);
2413   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S);
2414 }
2415 
2416 
2417 // Bit twiddling.
clz(Register rd,Register rs)2418 void Assembler::clz(Register rd, Register rs) {
2419   if (kArchVariant != kMips64r6) {
2420     // Clz instr requires same GPR number in 'rd' and 'rt' fields.
2421     GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
2422   } else {
2423     GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6);
2424   }
2425 }
2426 
2427 
dclz(Register rd,Register rs)2428 void Assembler::dclz(Register rd, Register rs) {
2429   if (kArchVariant != kMips64r6) {
2430     // dclz instr requires same GPR number in 'rd' and 'rt' fields.
2431     GenInstrRegister(SPECIAL2, rs, rd, rd, 0, DCLZ);
2432   } else {
2433     GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, DCLZ_R6);
2434   }
2435 }
2436 
2437 
ins_(Register rt,Register rs,uint16_t pos,uint16_t size)2438 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
2439   // Should be called via MacroAssembler::Ins.
2440   // Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
2441   DCHECK((kArchVariant == kMips64r2) || (kArchVariant == kMips64r6));
2442   GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
2443 }
2444 
2445 
dins_(Register rt,Register rs,uint16_t pos,uint16_t size)2446 void Assembler::dins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
2447   // Should be called via MacroAssembler::Dins.
2448   // Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
2449   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2450   GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, DINS);
2451 }
2452 
2453 
ext_(Register rt,Register rs,uint16_t pos,uint16_t size)2454 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
2455   // Should be called via MacroAssembler::Ext.
2456   // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
2457   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2458   GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
2459 }
2460 
2461 
dext_(Register rt,Register rs,uint16_t pos,uint16_t size)2462 void Assembler::dext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
2463   // Should be called via MacroAssembler::Dext.
2464   // Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
2465   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2466   GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, DEXT);
2467 }
2468 
2469 
dextm(Register rt,Register rs,uint16_t pos,uint16_t size)2470 void Assembler::dextm(Register rt, Register rs, uint16_t pos, uint16_t size) {
2471   // Should be called via MacroAssembler::Dextm.
2472   // Dextm instr has 'rt' field as dest, and two uint5: msb, lsb.
2473   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2474   GenInstrRegister(SPECIAL3, rs, rt, size - 1 - 32, pos, DEXTM);
2475 }
2476 
2477 
dextu(Register rt,Register rs,uint16_t pos,uint16_t size)2478 void Assembler::dextu(Register rt, Register rs, uint16_t pos, uint16_t size) {
2479   // Should be called via MacroAssembler::Dextu.
2480   // Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
2481   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2482   GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos - 32, DEXTU);
2483 }
2484 
2485 
bitswap(Register rd,Register rt)2486 void Assembler::bitswap(Register rd, Register rt) {
2487   DCHECK(kArchVariant == kMips64r6);
2488   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BSHFL);
2489 }
2490 
2491 
dbitswap(Register rd,Register rt)2492 void Assembler::dbitswap(Register rd, Register rt) {
2493   DCHECK(kArchVariant == kMips64r6);
2494   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, DBSHFL);
2495 }
2496 
2497 
pref(int32_t hint,const MemOperand & rs)2498 void Assembler::pref(int32_t hint, const MemOperand& rs) {
2499   DCHECK(is_uint5(hint) && is_uint16(rs.offset_));
2500   Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift)
2501       | (rs.offset_);
2502   emit(instr);
2503 }
2504 
2505 
align(Register rd,Register rs,Register rt,uint8_t bp)2506 void Assembler::align(Register rd, Register rs, Register rt, uint8_t bp) {
2507   DCHECK(kArchVariant == kMips64r6);
2508   DCHECK(is_uint3(bp));
2509   uint16_t sa = (ALIGN << kBp2Bits) | bp;
2510   GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL);
2511 }
2512 
2513 
dalign(Register rd,Register rs,Register rt,uint8_t bp)2514 void Assembler::dalign(Register rd, Register rs, Register rt, uint8_t bp) {
2515   DCHECK(kArchVariant == kMips64r6);
2516   DCHECK(is_uint3(bp));
2517   uint16_t sa = (DALIGN << kBp3Bits) | bp;
2518   GenInstrRegister(SPECIAL3, rs, rt, rd, sa, DBSHFL);
2519 }
2520 
wsbh(Register rd,Register rt)2521 void Assembler::wsbh(Register rd, Register rt) {
2522   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2523   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
2524 }
2525 
dsbh(Register rd,Register rt)2526 void Assembler::dsbh(Register rd, Register rt) {
2527   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2528   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSBH, DBSHFL);
2529 }
2530 
dshd(Register rd,Register rt)2531 void Assembler::dshd(Register rd, Register rt) {
2532   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2533   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSHD, DBSHFL);
2534 }
2535 
seh(Register rd,Register rt)2536 void Assembler::seh(Register rd, Register rt) {
2537   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2538   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
2539 }
2540 
seb(Register rd,Register rt)2541 void Assembler::seb(Register rd, Register rt) {
2542   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2543   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
2544 }
2545 
2546 // --------Coprocessor-instructions----------------
2547 
2548 // Load, store, move.
lwc1(FPURegister fd,const MemOperand & src)2549 void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
2550   if (is_int16(src.offset_)) {
2551     GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
2552   } else {  // Offset > 16 bits, use multiple instructions to load.
2553     LoadRegPlusOffsetToAt(src);
2554     GenInstrImmediate(LWC1, at, fd, 0);
2555   }
2556 }
2557 
2558 
ldc1(FPURegister fd,const MemOperand & src)2559 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
2560   if (is_int16(src.offset_)) {
2561     GenInstrImmediate(LDC1, src.rm(), fd, src.offset_);
2562   } else {  // Offset > 16 bits, use multiple instructions to load.
2563     LoadRegPlusOffsetToAt(src);
2564     GenInstrImmediate(LDC1, at, fd, 0);
2565   }
2566 }
2567 
2568 
swc1(FPURegister fd,const MemOperand & src)2569 void Assembler::swc1(FPURegister fd, const MemOperand& src) {
2570   if (is_int16(src.offset_)) {
2571     GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
2572   } else {  // Offset > 16 bits, use multiple instructions to load.
2573     LoadRegPlusOffsetToAt(src);
2574     GenInstrImmediate(SWC1, at, fd, 0);
2575   }
2576 }
2577 
2578 
sdc1(FPURegister fd,const MemOperand & src)2579 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
2580   DCHECK(!src.rm().is(at));
2581   if (is_int16(src.offset_)) {
2582     GenInstrImmediate(SDC1, src.rm(), fd, src.offset_);
2583   } else {  // Offset > 16 bits, use multiple instructions to load.
2584     LoadRegPlusOffsetToAt(src);
2585     GenInstrImmediate(SDC1, at, fd, 0);
2586   }
2587 }
2588 
2589 
mtc1(Register rt,FPURegister fs)2590 void Assembler::mtc1(Register rt, FPURegister fs) {
2591   GenInstrRegister(COP1, MTC1, rt, fs, f0);
2592 }
2593 
2594 
mthc1(Register rt,FPURegister fs)2595 void Assembler::mthc1(Register rt, FPURegister fs) {
2596   GenInstrRegister(COP1, MTHC1, rt, fs, f0);
2597 }
2598 
2599 
dmtc1(Register rt,FPURegister fs)2600 void Assembler::dmtc1(Register rt, FPURegister fs) {
2601   GenInstrRegister(COP1, DMTC1, rt, fs, f0);
2602 }
2603 
2604 
mfc1(Register rt,FPURegister fs)2605 void Assembler::mfc1(Register rt, FPURegister fs) {
2606   GenInstrRegister(COP1, MFC1, rt, fs, f0);
2607 }
2608 
2609 
mfhc1(Register rt,FPURegister fs)2610 void Assembler::mfhc1(Register rt, FPURegister fs) {
2611   GenInstrRegister(COP1, MFHC1, rt, fs, f0);
2612 }
2613 
2614 
dmfc1(Register rt,FPURegister fs)2615 void Assembler::dmfc1(Register rt, FPURegister fs) {
2616   GenInstrRegister(COP1, DMFC1, rt, fs, f0);
2617 }
2618 
2619 
ctc1(Register rt,FPUControlRegister fs)2620 void Assembler::ctc1(Register rt, FPUControlRegister fs) {
2621   GenInstrRegister(COP1, CTC1, rt, fs);
2622 }
2623 
2624 
cfc1(Register rt,FPUControlRegister fs)2625 void Assembler::cfc1(Register rt, FPUControlRegister fs) {
2626   GenInstrRegister(COP1, CFC1, rt, fs);
2627 }
2628 
2629 
DoubleAsTwoUInt32(double d,uint32_t * lo,uint32_t * hi)2630 void Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
2631   uint64_t i;
2632   memcpy(&i, &d, 8);
2633 
2634   *lo = i & 0xffffffff;
2635   *hi = i >> 32;
2636 }
2637 
2638 
sel(SecondaryField fmt,FPURegister fd,FPURegister fs,FPURegister ft)2639 void Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs,
2640                     FPURegister ft) {
2641   DCHECK(kArchVariant == kMips64r6);
2642   DCHECK((fmt == D) || (fmt == S));
2643 
2644   GenInstrRegister(COP1, fmt, ft, fs, fd, SEL);
2645 }
2646 
2647 
sel_s(FPURegister fd,FPURegister fs,FPURegister ft)2648 void Assembler::sel_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2649   sel(S, fd, fs, ft);
2650 }
2651 
2652 
sel_d(FPURegister fd,FPURegister fs,FPURegister ft)2653 void Assembler::sel_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2654   sel(D, fd, fs, ft);
2655 }
2656 
2657 
2658 // FPR.
seleqz(SecondaryField fmt,FPURegister fd,FPURegister fs,FPURegister ft)2659 void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
2660                        FPURegister ft) {
2661   DCHECK((fmt == D) || (fmt == S));
2662   GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C);
2663 }
2664 
2665 
seleqz_d(FPURegister fd,FPURegister fs,FPURegister ft)2666 void Assembler::seleqz_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2667   seleqz(D, fd, fs, ft);
2668 }
2669 
2670 
seleqz_s(FPURegister fd,FPURegister fs,FPURegister ft)2671 void Assembler::seleqz_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2672   seleqz(S, fd, fs, ft);
2673 }
2674 
2675 
selnez_d(FPURegister fd,FPURegister fs,FPURegister ft)2676 void Assembler::selnez_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2677   selnez(D, fd, fs, ft);
2678 }
2679 
2680 
selnez_s(FPURegister fd,FPURegister fs,FPURegister ft)2681 void Assembler::selnez_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2682   selnez(S, fd, fs, ft);
2683 }
2684 
2685 
movz_s(FPURegister fd,FPURegister fs,Register rt)2686 void Assembler::movz_s(FPURegister fd, FPURegister fs, Register rt) {
2687   DCHECK(kArchVariant == kMips64r2);
2688   GenInstrRegister(COP1, S, rt, fs, fd, MOVZ_C);
2689 }
2690 
2691 
movz_d(FPURegister fd,FPURegister fs,Register rt)2692 void Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) {
2693   DCHECK(kArchVariant == kMips64r2);
2694   GenInstrRegister(COP1, D, rt, fs, fd, MOVZ_C);
2695 }
2696 
2697 
movt_s(FPURegister fd,FPURegister fs,uint16_t cc)2698 void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
2699   DCHECK(kArchVariant == kMips64r2);
2700   FPURegister ft;
2701   ft.reg_code = (cc & 0x0007) << 2 | 1;
2702   GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
2703 }
2704 
2705 
movt_d(FPURegister fd,FPURegister fs,uint16_t cc)2706 void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
2707   DCHECK(kArchVariant == kMips64r2);
2708   FPURegister ft;
2709   ft.reg_code = (cc & 0x0007) << 2 | 1;
2710   GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
2711 }
2712 
2713 
movf_s(FPURegister fd,FPURegister fs,uint16_t cc)2714 void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
2715   DCHECK(kArchVariant == kMips64r2);
2716   FPURegister ft;
2717   ft.reg_code = (cc & 0x0007) << 2 | 0;
2718   GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
2719 }
2720 
2721 
movf_d(FPURegister fd,FPURegister fs,uint16_t cc)2722 void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
2723   DCHECK(kArchVariant == kMips64r2);
2724   FPURegister ft;
2725   ft.reg_code = (cc & 0x0007) << 2 | 0;
2726   GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
2727 }
2728 
2729 
movn_s(FPURegister fd,FPURegister fs,Register rt)2730 void Assembler::movn_s(FPURegister fd, FPURegister fs, Register rt) {
2731   DCHECK(kArchVariant == kMips64r2);
2732   GenInstrRegister(COP1, S, rt, fs, fd, MOVN_C);
2733 }
2734 
2735 
movn_d(FPURegister fd,FPURegister fs,Register rt)2736 void Assembler::movn_d(FPURegister fd, FPURegister fs, Register rt) {
2737   DCHECK(kArchVariant == kMips64r2);
2738   GenInstrRegister(COP1, D, rt, fs, fd, MOVN_C);
2739 }
2740 
2741 
2742 // FPR.
selnez(SecondaryField fmt,FPURegister fd,FPURegister fs,FPURegister ft)2743 void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
2744                        FPURegister ft) {
2745   DCHECK(kArchVariant == kMips64r6);
2746   DCHECK((fmt == D) || (fmt == S));
2747   GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C);
2748 }
2749 
2750 
2751 // Arithmetic.
2752 
add_s(FPURegister fd,FPURegister fs,FPURegister ft)2753 void Assembler::add_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2754   GenInstrRegister(COP1, S, ft, fs, fd, ADD_D);
2755 }
2756 
2757 
add_d(FPURegister fd,FPURegister fs,FPURegister ft)2758 void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2759   GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
2760 }
2761 
2762 
sub_s(FPURegister fd,FPURegister fs,FPURegister ft)2763 void Assembler::sub_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2764   GenInstrRegister(COP1, S, ft, fs, fd, SUB_D);
2765 }
2766 
2767 
sub_d(FPURegister fd,FPURegister fs,FPURegister ft)2768 void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2769   GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
2770 }
2771 
2772 
mul_s(FPURegister fd,FPURegister fs,FPURegister ft)2773 void Assembler::mul_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2774   GenInstrRegister(COP1, S, ft, fs, fd, MUL_D);
2775 }
2776 
2777 
mul_d(FPURegister fd,FPURegister fs,FPURegister ft)2778 void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2779   GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
2780 }
2781 
2782 
madd_d(FPURegister fd,FPURegister fr,FPURegister fs,FPURegister ft)2783 void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
2784     FPURegister ft) {
2785   GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
2786 }
2787 
2788 
div_s(FPURegister fd,FPURegister fs,FPURegister ft)2789 void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2790   GenInstrRegister(COP1, S, ft, fs, fd, DIV_D);
2791 }
2792 
2793 
div_d(FPURegister fd,FPURegister fs,FPURegister ft)2794 void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2795   GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
2796 }
2797 
2798 
abs_s(FPURegister fd,FPURegister fs)2799 void Assembler::abs_s(FPURegister fd, FPURegister fs) {
2800   GenInstrRegister(COP1, S, f0, fs, fd, ABS_D);
2801 }
2802 
2803 
abs_d(FPURegister fd,FPURegister fs)2804 void Assembler::abs_d(FPURegister fd, FPURegister fs) {
2805   GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
2806 }
2807 
2808 
mov_d(FPURegister fd,FPURegister fs)2809 void Assembler::mov_d(FPURegister fd, FPURegister fs) {
2810   GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
2811 }
2812 
2813 
mov_s(FPURegister fd,FPURegister fs)2814 void Assembler::mov_s(FPURegister fd, FPURegister fs) {
2815   GenInstrRegister(COP1, S, f0, fs, fd, MOV_S);
2816 }
2817 
2818 
neg_s(FPURegister fd,FPURegister fs)2819 void Assembler::neg_s(FPURegister fd, FPURegister fs) {
2820   GenInstrRegister(COP1, S, f0, fs, fd, NEG_D);
2821 }
2822 
2823 
neg_d(FPURegister fd,FPURegister fs)2824 void Assembler::neg_d(FPURegister fd, FPURegister fs) {
2825   GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
2826 }
2827 
2828 
sqrt_s(FPURegister fd,FPURegister fs)2829 void Assembler::sqrt_s(FPURegister fd, FPURegister fs) {
2830   GenInstrRegister(COP1, S, f0, fs, fd, SQRT_D);
2831 }
2832 
2833 
sqrt_d(FPURegister fd,FPURegister fs)2834 void Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
2835   GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
2836 }
2837 
2838 
rsqrt_s(FPURegister fd,FPURegister fs)2839 void Assembler::rsqrt_s(FPURegister fd, FPURegister fs) {
2840   GenInstrRegister(COP1, S, f0, fs, fd, RSQRT_S);
2841 }
2842 
2843 
rsqrt_d(FPURegister fd,FPURegister fs)2844 void Assembler::rsqrt_d(FPURegister fd, FPURegister fs) {
2845   GenInstrRegister(COP1, D, f0, fs, fd, RSQRT_D);
2846 }
2847 
2848 
recip_d(FPURegister fd,FPURegister fs)2849 void Assembler::recip_d(FPURegister fd, FPURegister fs) {
2850   GenInstrRegister(COP1, D, f0, fs, fd, RECIP_D);
2851 }
2852 
2853 
recip_s(FPURegister fd,FPURegister fs)2854 void Assembler::recip_s(FPURegister fd, FPURegister fs) {
2855   GenInstrRegister(COP1, S, f0, fs, fd, RECIP_S);
2856 }
2857 
2858 
2859 // Conversions.
cvt_w_s(FPURegister fd,FPURegister fs)2860 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
2861   GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
2862 }
2863 
2864 
cvt_w_d(FPURegister fd,FPURegister fs)2865 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
2866   GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
2867 }
2868 
2869 
trunc_w_s(FPURegister fd,FPURegister fs)2870 void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
2871   GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
2872 }
2873 
2874 
trunc_w_d(FPURegister fd,FPURegister fs)2875 void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
2876   GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
2877 }
2878 
2879 
round_w_s(FPURegister fd,FPURegister fs)2880 void Assembler::round_w_s(FPURegister fd, FPURegister fs) {
2881   GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
2882 }
2883 
2884 
round_w_d(FPURegister fd,FPURegister fs)2885 void Assembler::round_w_d(FPURegister fd, FPURegister fs) {
2886   GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
2887 }
2888 
2889 
floor_w_s(FPURegister fd,FPURegister fs)2890 void Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
2891   GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
2892 }
2893 
2894 
floor_w_d(FPURegister fd,FPURegister fs)2895 void Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
2896   GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
2897 }
2898 
2899 
ceil_w_s(FPURegister fd,FPURegister fs)2900 void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
2901   GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
2902 }
2903 
2904 
ceil_w_d(FPURegister fd,FPURegister fs)2905 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
2906   GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
2907 }
2908 
2909 
rint_s(FPURegister fd,FPURegister fs)2910 void Assembler::rint_s(FPURegister fd, FPURegister fs) { rint(S, fd, fs); }
2911 
2912 
rint_d(FPURegister fd,FPURegister fs)2913 void Assembler::rint_d(FPURegister fd, FPURegister fs) { rint(D, fd, fs); }
2914 
2915 
rint(SecondaryField fmt,FPURegister fd,FPURegister fs)2916 void Assembler::rint(SecondaryField fmt, FPURegister fd, FPURegister fs) {
2917   DCHECK(kArchVariant == kMips64r6);
2918   GenInstrRegister(COP1, fmt, f0, fs, fd, RINT);
2919 }
2920 
2921 
cvt_l_s(FPURegister fd,FPURegister fs)2922 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
2923   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2924   GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
2925 }
2926 
2927 
cvt_l_d(FPURegister fd,FPURegister fs)2928 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
2929   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2930   GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
2931 }
2932 
2933 
trunc_l_s(FPURegister fd,FPURegister fs)2934 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
2935   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2936   GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
2937 }
2938 
2939 
trunc_l_d(FPURegister fd,FPURegister fs)2940 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
2941   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2942   GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
2943 }
2944 
2945 
round_l_s(FPURegister fd,FPURegister fs)2946 void Assembler::round_l_s(FPURegister fd, FPURegister fs) {
2947   GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
2948 }
2949 
2950 
round_l_d(FPURegister fd,FPURegister fs)2951 void Assembler::round_l_d(FPURegister fd, FPURegister fs) {
2952   GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
2953 }
2954 
2955 
floor_l_s(FPURegister fd,FPURegister fs)2956 void Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
2957   GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
2958 }
2959 
2960 
floor_l_d(FPURegister fd,FPURegister fs)2961 void Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
2962   GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
2963 }
2964 
2965 
ceil_l_s(FPURegister fd,FPURegister fs)2966 void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
2967   GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
2968 }
2969 
2970 
ceil_l_d(FPURegister fd,FPURegister fs)2971 void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
2972   GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
2973 }
2974 
2975 
class_s(FPURegister fd,FPURegister fs)2976 void Assembler::class_s(FPURegister fd, FPURegister fs) {
2977   DCHECK(kArchVariant == kMips64r6);
2978   GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S);
2979 }
2980 
2981 
class_d(FPURegister fd,FPURegister fs)2982 void Assembler::class_d(FPURegister fd, FPURegister fs) {
2983   DCHECK(kArchVariant == kMips64r6);
2984   GenInstrRegister(COP1, D, f0, fs, fd, CLASS_D);
2985 }
2986 
2987 
mina(SecondaryField fmt,FPURegister fd,FPURegister fs,FPURegister ft)2988 void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs,
2989                      FPURegister ft) {
2990   DCHECK(kArchVariant == kMips64r6);
2991   DCHECK((fmt == D) || (fmt == S));
2992   GenInstrRegister(COP1, fmt, ft, fs, fd, MINA);
2993 }
2994 
2995 
maxa(SecondaryField fmt,FPURegister fd,FPURegister fs,FPURegister ft)2996 void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs,
2997                      FPURegister ft) {
2998   DCHECK(kArchVariant == kMips64r6);
2999   DCHECK((fmt == D) || (fmt == S));
3000   GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA);
3001 }
3002 
3003 
cvt_s_w(FPURegister fd,FPURegister fs)3004 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
3005   GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
3006 }
3007 
3008 
cvt_s_l(FPURegister fd,FPURegister fs)3009 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
3010   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
3011   GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
3012 }
3013 
3014 
cvt_s_d(FPURegister fd,FPURegister fs)3015 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
3016   GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
3017 }
3018 
3019 
cvt_d_w(FPURegister fd,FPURegister fs)3020 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
3021   GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
3022 }
3023 
3024 
cvt_d_l(FPURegister fd,FPURegister fs)3025 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
3026   DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
3027   GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
3028 }
3029 
3030 
cvt_d_s(FPURegister fd,FPURegister fs)3031 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
3032   GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
3033 }
3034 
3035 
3036 // Conditions for >= MIPSr6.
cmp(FPUCondition cond,SecondaryField fmt,FPURegister fd,FPURegister fs,FPURegister ft)3037 void Assembler::cmp(FPUCondition cond, SecondaryField fmt,
3038     FPURegister fd, FPURegister fs, FPURegister ft) {
3039   DCHECK(kArchVariant == kMips64r6);
3040   DCHECK((fmt & ~(31 << kRsShift)) == 0);
3041   Instr instr = COP1 | fmt | ft.code() << kFtShift |
3042       fs.code() << kFsShift | fd.code() << kFdShift | (0 << 5) | cond;
3043   emit(instr);
3044 }
3045 
3046 
cmp_s(FPUCondition cond,FPURegister fd,FPURegister fs,FPURegister ft)3047 void Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs,
3048                       FPURegister ft) {
3049   cmp(cond, W, fd, fs, ft);
3050 }
3051 
cmp_d(FPUCondition cond,FPURegister fd,FPURegister fs,FPURegister ft)3052 void Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs,
3053                       FPURegister ft) {
3054   cmp(cond, L, fd, fs, ft);
3055 }
3056 
3057 
bc1eqz(int16_t offset,FPURegister ft)3058 void Assembler::bc1eqz(int16_t offset, FPURegister ft) {
3059   DCHECK(kArchVariant == kMips64r6);
3060   Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask);
3061   emit(instr);
3062 }
3063 
3064 
bc1nez(int16_t offset,FPURegister ft)3065 void Assembler::bc1nez(int16_t offset, FPURegister ft) {
3066   DCHECK(kArchVariant == kMips64r6);
3067   Instr instr = COP1 | BC1NEZ | ft.code() << kFtShift | (offset & kImm16Mask);
3068   emit(instr);
3069 }
3070 
3071 
3072 // Conditions for < MIPSr6.
c(FPUCondition cond,SecondaryField fmt,FPURegister fs,FPURegister ft,uint16_t cc)3073 void Assembler::c(FPUCondition cond, SecondaryField fmt,
3074     FPURegister fs, FPURegister ft, uint16_t cc) {
3075   DCHECK(kArchVariant != kMips64r6);
3076   DCHECK(is_uint3(cc));
3077   DCHECK(fmt == S || fmt == D);
3078   DCHECK((fmt & ~(31 << kRsShift)) == 0);
3079   Instr instr = COP1 | fmt | ft.code() << kFtShift | fs.code() << kFsShift
3080       | cc << 8 | 3 << 4 | cond;
3081   emit(instr);
3082 }
3083 
3084 
c_s(FPUCondition cond,FPURegister fs,FPURegister ft,uint16_t cc)3085 void Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft,
3086                     uint16_t cc) {
3087   c(cond, S, fs, ft, cc);
3088 }
3089 
3090 
c_d(FPUCondition cond,FPURegister fs,FPURegister ft,uint16_t cc)3091 void Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft,
3092                     uint16_t cc) {
3093   c(cond, D, fs, ft, cc);
3094 }
3095 
3096 
fcmp(FPURegister src1,const double src2,FPUCondition cond)3097 void Assembler::fcmp(FPURegister src1, const double src2,
3098       FPUCondition cond) {
3099   DCHECK(src2 == 0.0);
3100   mtc1(zero_reg, f14);
3101   cvt_d_w(f14, f14);
3102   c(cond, D, src1, f14, 0);
3103 }
3104 
3105 
bc1f(int16_t offset,uint16_t cc)3106 void Assembler::bc1f(int16_t offset, uint16_t cc) {
3107   DCHECK(is_uint3(cc));
3108   Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
3109   emit(instr);
3110 }
3111 
3112 
bc1t(int16_t offset,uint16_t cc)3113 void Assembler::bc1t(int16_t offset, uint16_t cc) {
3114   DCHECK(is_uint3(cc));
3115   Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
3116   emit(instr);
3117 }
3118 
3119 
RelocateInternalReference(RelocInfo::Mode rmode,byte * pc,intptr_t pc_delta)3120 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
3121                                          intptr_t pc_delta) {
3122   if (RelocInfo::IsInternalReference(rmode)) {
3123     int64_t* p = reinterpret_cast<int64_t*>(pc);
3124     if (*p == kEndOfJumpChain) {
3125       return 0;  // Number of instructions patched.
3126     }
3127     *p += pc_delta;
3128     return 2;  // Number of instructions patched.
3129   }
3130   Instr instr = instr_at(pc);
3131   DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
3132   if (IsLui(instr)) {
3133     Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
3134     Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
3135     Instr instr_ori2 = instr_at(pc + 3 * Assembler::kInstrSize);
3136     DCHECK(IsOri(instr_ori));
3137     DCHECK(IsOri(instr_ori2));
3138     // TODO(plind): symbolic names for the shifts.
3139     int64_t imm = (instr_lui & static_cast<int64_t>(kImm16Mask)) << 48;
3140     imm |= (instr_ori & static_cast<int64_t>(kImm16Mask)) << 32;
3141     imm |= (instr_ori2 & static_cast<int64_t>(kImm16Mask)) << 16;
3142     // Sign extend address.
3143     imm >>= 16;
3144 
3145     if (imm == kEndOfJumpChain) {
3146       return 0;  // Number of instructions patched.
3147     }
3148     imm += pc_delta;
3149     DCHECK((imm & 3) == 0);
3150 
3151     instr_lui &= ~kImm16Mask;
3152     instr_ori &= ~kImm16Mask;
3153     instr_ori2 &= ~kImm16Mask;
3154 
3155     instr_at_put(pc + 0 * Assembler::kInstrSize,
3156                  instr_lui | ((imm >> 32) & kImm16Mask));
3157     instr_at_put(pc + 1 * Assembler::kInstrSize,
3158                  instr_ori | (imm >> 16 & kImm16Mask));
3159     instr_at_put(pc + 3 * Assembler::kInstrSize,
3160                  instr_ori2 | (imm & kImm16Mask));
3161     return 4;  // Number of instructions patched.
3162   } else if (IsJ(instr) || IsJal(instr)) {
3163     // Regular j/jal relocation.
3164     uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
3165     imm28 += pc_delta;
3166     imm28 &= kImm28Mask;
3167     instr &= ~kImm26Mask;
3168     DCHECK((imm28 & 3) == 0);
3169     uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2);
3170     instr_at_put(pc, instr | (imm26 & kImm26Mask));
3171     return 1;  // Number of instructions patched.
3172   } else {
3173     DCHECK(((instr & kJumpRawMask) == kJRawMark) ||
3174            ((instr & kJumpRawMask) == kJalRawMark));
3175     // Unbox raw offset and emit j/jal.
3176     int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
3177     // Sign extend 28-bit offset to 32-bit.
3178     imm28 = (imm28 << 4) >> 4;
3179     uint64_t target =
3180         static_cast<int64_t>(imm28) + reinterpret_cast<uint64_t>(pc);
3181     target &= kImm28Mask;
3182     DCHECK((imm28 & 3) == 0);
3183     uint32_t imm26 = static_cast<uint32_t>(target >> 2);
3184     // Check markings whether to emit j or jal.
3185     uint32_t unbox = (instr & kJRawMark) ? J : JAL;
3186     instr_at_put(pc, unbox | (imm26 & kImm26Mask));
3187     return 1;  // Number of instructions patched.
3188   }
3189 }
3190 
3191 
GrowBuffer()3192 void Assembler::GrowBuffer() {
3193   if (!own_buffer_) FATAL("external code buffer is too small");
3194 
3195   // Compute new buffer size.
3196   CodeDesc desc;  // The new buffer.
3197   if (buffer_size_ < 1 * MB) {
3198     desc.buffer_size = 2*buffer_size_;
3199   } else {
3200     desc.buffer_size = buffer_size_ + 1*MB;
3201   }
3202   CHECK_GT(desc.buffer_size, 0);  // No overflow.
3203 
3204   // Set up new buffer.
3205   desc.buffer = NewArray<byte>(desc.buffer_size);
3206   desc.origin = this;
3207 
3208   desc.instr_size = pc_offset();
3209   desc.reloc_size =
3210       static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
3211 
3212   // Copy the data.
3213   intptr_t pc_delta = desc.buffer - buffer_;
3214   intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
3215       (buffer_ + buffer_size_);
3216   MemMove(desc.buffer, buffer_, desc.instr_size);
3217   MemMove(reloc_info_writer.pos() + rc_delta,
3218               reloc_info_writer.pos(), desc.reloc_size);
3219 
3220   // Switch buffers.
3221   DeleteArray(buffer_);
3222   buffer_ = desc.buffer;
3223   buffer_size_ = desc.buffer_size;
3224   pc_ += pc_delta;
3225   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
3226                                reloc_info_writer.last_pc() + pc_delta);
3227 
3228   // Relocate runtime entries.
3229   for (RelocIterator it(desc); !it.done(); it.next()) {
3230     RelocInfo::Mode rmode = it.rinfo()->rmode();
3231     if (rmode == RelocInfo::INTERNAL_REFERENCE) {
3232       byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
3233       RelocateInternalReference(rmode, p, pc_delta);
3234     }
3235   }
3236   DCHECK(!overflow());
3237 }
3238 
3239 
db(uint8_t data)3240 void Assembler::db(uint8_t data) {
3241   CheckForEmitInForbiddenSlot();
3242   EmitHelper(data);
3243 }
3244 
3245 
dd(uint32_t data)3246 void Assembler::dd(uint32_t data) {
3247   CheckForEmitInForbiddenSlot();
3248   EmitHelper(data);
3249 }
3250 
3251 
dq(uint64_t data)3252 void Assembler::dq(uint64_t data) {
3253   CheckForEmitInForbiddenSlot();
3254   EmitHelper(data);
3255 }
3256 
3257 
dd(Label * label)3258 void Assembler::dd(Label* label) {
3259   uint64_t data;
3260   CheckForEmitInForbiddenSlot();
3261   if (label->is_bound()) {
3262     data = reinterpret_cast<uint64_t>(buffer_ + label->pos());
3263   } else {
3264     data = jump_address(label);
3265     unbound_labels_count_++;
3266     internal_reference_positions_.insert(label->pos());
3267   }
3268   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
3269   EmitHelper(data);
3270 }
3271 
3272 
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data)3273 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3274   // We do not try to reuse pool constants.
3275   RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
3276   if (rmode >= RelocInfo::COMMENT &&
3277       rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL) {
3278     // Adjust code for new modes.
3279     DCHECK(RelocInfo::IsDebugBreakSlot(rmode)
3280            || RelocInfo::IsComment(rmode)
3281            || RelocInfo::IsPosition(rmode));
3282     // These modes do not need an entry in the constant pool.
3283   }
3284   if (!RelocInfo::IsNone(rinfo.rmode())) {
3285     // Don't record external references unless the heap will be serialized.
3286     if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
3287         !serializer_enabled() && !emit_debug_code()) {
3288       return;
3289     }
3290     DCHECK(buffer_space() >= kMaxRelocSize);  // Too late to grow buffer here.
3291     if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
3292       RelocInfo reloc_info_with_ast_id(isolate(), pc_, rmode,
3293                                        RecordedAstId().ToInt(), NULL);
3294       ClearRecordedAstId();
3295       reloc_info_writer.Write(&reloc_info_with_ast_id);
3296     } else {
3297       reloc_info_writer.Write(&rinfo);
3298     }
3299   }
3300 }
3301 
3302 
BlockTrampolinePoolFor(int instructions)3303 void Assembler::BlockTrampolinePoolFor(int instructions) {
3304   CheckTrampolinePoolQuick(instructions);
3305   BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
3306 }
3307 
3308 
CheckTrampolinePool()3309 void Assembler::CheckTrampolinePool() {
3310   // Some small sequences of instructions must not be broken up by the
3311   // insertion of a trampoline pool; such sequences are protected by setting
3312   // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
3313   // which are both checked here. Also, recursive calls to CheckTrampolinePool
3314   // are blocked by trampoline_pool_blocked_nesting_.
3315   if ((trampoline_pool_blocked_nesting_ > 0) ||
3316       (pc_offset() < no_trampoline_pool_before_)) {
3317     // Emission is currently blocked; make sure we try again as soon as
3318     // possible.
3319     if (trampoline_pool_blocked_nesting_ > 0) {
3320       next_buffer_check_ = pc_offset() + kInstrSize;
3321     } else {
3322       next_buffer_check_ = no_trampoline_pool_before_;
3323     }
3324     return;
3325   }
3326 
3327   DCHECK(!trampoline_emitted_);
3328   DCHECK(unbound_labels_count_ >= 0);
3329   if (unbound_labels_count_ > 0) {
3330     // First we emit jump (2 instructions), then we emit trampoline pool.
3331     { BlockTrampolinePoolScope block_trampoline_pool(this);
3332       Label after_pool;
3333       if (kArchVariant == kMips64r6) {
3334         bc(&after_pool);
3335       } else {
3336         b(&after_pool);
3337       }
3338       nop();
3339 
3340       int pool_start = pc_offset();
3341       for (int i = 0; i < unbound_labels_count_; i++) {
3342         { BlockGrowBufferScope block_buf_growth(this);
3343           // Buffer growth (and relocation) must be blocked for internal
3344           // references until associated instructions are emitted and available
3345           // to be patched.
3346           RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
3347           j(&after_pool);
3348         }
3349         nop();
3350       }
3351       bind(&after_pool);
3352       trampoline_ = Trampoline(pool_start, unbound_labels_count_);
3353 
3354       trampoline_emitted_ = true;
3355       // As we are only going to emit trampoline once, we need to prevent any
3356       // further emission.
3357       next_buffer_check_ = kMaxInt;
3358     }
3359   } else {
3360     // Number of branches to unbound label at this point is zero, so we can
3361     // move next buffer check to maximum.
3362     next_buffer_check_ = pc_offset() +
3363         kMaxBranchOffset - kTrampolineSlotsSize * 16;
3364   }
3365   return;
3366 }
3367 
3368 
target_address_at(Address pc)3369 Address Assembler::target_address_at(Address pc) {
3370   Instr instr0 = instr_at(pc);
3371   Instr instr1 = instr_at(pc + 1 * kInstrSize);
3372   Instr instr3 = instr_at(pc + 3 * kInstrSize);
3373 
3374   // Interpret 4 instructions for address generated by li: See listing in
3375   // Assembler::set_target_address_at() just below.
3376   if ((GetOpcodeField(instr0) == LUI) && (GetOpcodeField(instr1) == ORI) &&
3377       (GetOpcodeField(instr3) == ORI)) {
3378     // Assemble the 48 bit value.
3379      int64_t addr  = static_cast<int64_t>(
3380           ((uint64_t)(GetImmediate16(instr0)) << 32) |
3381           ((uint64_t)(GetImmediate16(instr1)) << 16) |
3382           ((uint64_t)(GetImmediate16(instr3))));
3383 
3384     // Sign extend to get canonical address.
3385     addr = (addr << 16) >> 16;
3386     return reinterpret_cast<Address>(addr);
3387   }
3388   // We should never get here, force a bad address if we do.
3389   UNREACHABLE();
3390   return (Address)0x0;
3391 }
3392 
3393 
3394 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32
3395 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap
3396 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted.
3397 // OS::nan_value() returns a qNaN.
QuietNaN(HeapObject * object)3398 void Assembler::QuietNaN(HeapObject* object) {
3399   HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN());
3400 }
3401 
3402 
3403 // On Mips64, a target address is stored in a 4-instruction sequence:
3404 //    0: lui(rd, (j.imm64_ >> 32) & kImm16Mask);
3405 //    1: ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
3406 //    2: dsll(rd, rd, 16);
3407 //    3: ori(rd, rd, j.imm32_ & kImm16Mask);
3408 //
3409 // Patching the address must replace all the lui & ori instructions,
3410 // and flush the i-cache.
3411 //
3412 // There is an optimization below, which emits a nop when the address
3413 // fits in just 16 bits. This is unlikely to help, and should be benchmarked,
3414 // and possibly removed.
set_target_address_at(Isolate * isolate,Address pc,Address target,ICacheFlushMode icache_flush_mode)3415 void Assembler::set_target_address_at(Isolate* isolate, Address pc,
3416                                       Address target,
3417                                       ICacheFlushMode icache_flush_mode) {
3418 // There is an optimization where only 4 instructions are used to load address
3419 // in code on MIP64 because only 48-bits of address is effectively used.
3420 // It relies on fact the upper [63:48] bits are not used for virtual address
3421 // translation and they have to be set according to value of bit 47 in order
3422 // get canonical address.
3423   Instr instr1 = instr_at(pc + kInstrSize);
3424   uint32_t rt_code = GetRt(instr1);
3425   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
3426   uint64_t itarget = reinterpret_cast<uint64_t>(target);
3427 
3428 #ifdef DEBUG
3429   // Check we have the result from a li macro-instruction.
3430   Instr instr0 = instr_at(pc);
3431   Instr instr3 = instr_at(pc + kInstrSize * 3);
3432   CHECK((GetOpcodeField(instr0) == LUI && GetOpcodeField(instr1) == ORI &&
3433          GetOpcodeField(instr3) == ORI));
3434 #endif
3435 
3436   // Must use 4 instructions to insure patchable code.
3437   // lui rt, upper-16.
3438   // ori rt, rt, lower-16.
3439   // dsll rt, rt, 16.
3440   // ori rt rt, lower-16.
3441   *p = LUI | (rt_code << kRtShift) | ((itarget >> 32) & kImm16Mask);
3442   *(p + 1) = ORI | (rt_code << kRtShift) | (rt_code << kRsShift)
3443       | ((itarget >> 16) & kImm16Mask);
3444   *(p + 3) = ORI | (rt_code << kRsShift) | (rt_code << kRtShift)
3445       | (itarget & kImm16Mask);
3446 
3447   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
3448     Assembler::FlushICache(isolate, pc, 4 * Assembler::kInstrSize);
3449   }
3450 }
3451 
3452 }  // namespace internal
3453 }  // namespace v8
3454 
3455 #endif  // V8_TARGET_ARCH_MIPS64
3456