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