Home | History | Annotate | Download | only in mips
      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 
     36 #include "src/v8.h"
     37 
     38 #if V8_TARGET_ARCH_MIPS
     39 
     40 #include "src/mips/assembler-mips-inl.h"
     41 #include "src/serialize.h"
     42 
     43 namespace v8 {
     44 namespace internal {
     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.
     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 
     67 const char* DoubleRegister::AllocationIndexToString(int index) {
     68   ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
     69   const char* const names[] = {
     70     "f0",
     71     "f2",
     72     "f4",
     73     "f6",
     74     "f8",
     75     "f10",
     76     "f12",
     77     "f14",
     78     "f16",
     79     "f18",
     80     "f20",
     81     "f22",
     82     "f24",
     83     "f26"
     84   };
     85   return names[index];
     86 }
     87 
     88 
     89 void CpuFeatures::ProbeImpl(bool cross_compile) {
     90   supported_ |= CpuFeaturesImpliedByCompiler();
     91 
     92   // Only use statically determined features for cross compile (snapshot).
     93   if (cross_compile) return;
     94 
     95   // If the compiler is allowed to use fpu then we can use fpu too in our
     96   // code generation.
     97 #ifndef __mips__
     98   // For the simulator build, use FPU.
     99   supported_ |= 1u << FPU;
    100 #else
    101   // Probe for additional features at runtime.
    102   CPU cpu;
    103   if (cpu.has_fpu()) supported_ |= 1u << FPU;
    104 #endif
    105 }
    106 
    107 
    108 void CpuFeatures::PrintTarget() { }
    109 void CpuFeatures::PrintFeatures() { }
    110 
    111 
    112 int ToNumber(Register reg) {
    113   ASSERT(reg.is_valid());
    114   const int kNumbers[] = {
    115     0,    // zero_reg
    116     1,    // at
    117     2,    // v0
    118     3,    // v1
    119     4,    // a0
    120     5,    // a1
    121     6,    // a2
    122     7,    // a3
    123     8,    // t0
    124     9,    // t1
    125     10,   // t2
    126     11,   // t3
    127     12,   // t4
    128     13,   // t5
    129     14,   // t6
    130     15,   // t7
    131     16,   // s0
    132     17,   // s1
    133     18,   // s2
    134     19,   // s3
    135     20,   // s4
    136     21,   // s5
    137     22,   // s6
    138     23,   // s7
    139     24,   // t8
    140     25,   // t9
    141     26,   // k0
    142     27,   // k1
    143     28,   // gp
    144     29,   // sp
    145     30,   // fp
    146     31,   // ra
    147   };
    148   return kNumbers[reg.code()];
    149 }
    150 
    151 
    152 Register ToRegister(int num) {
    153   ASSERT(num >= 0 && num < kNumRegisters);
    154   const Register kRegisters[] = {
    155     zero_reg,
    156     at,
    157     v0, v1,
    158     a0, a1, a2, a3,
    159     t0, t1, t2, t3, t4, t5, t6, t7,
    160     s0, s1, s2, s3, s4, s5, s6, s7,
    161     t8, t9,
    162     k0, k1,
    163     gp,
    164     sp,
    165     fp,
    166     ra
    167   };
    168   return kRegisters[num];
    169 }
    170 
    171 
    172 // -----------------------------------------------------------------------------
    173 // Implementation of RelocInfo.
    174 
    175 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
    176                                   1 << RelocInfo::INTERNAL_REFERENCE;
    177 
    178 
    179 bool RelocInfo::IsCodedSpecially() {
    180   // The deserializer needs to know whether a pointer is specially coded.  Being
    181   // specially coded on MIPS means that it is a lui/ori instruction, and that is
    182   // always the case inside code objects.
    183   return true;
    184 }
    185 
    186 
    187 bool RelocInfo::IsInConstantPool() {
    188   return false;
    189 }
    190 
    191 
    192 // Patch the code at the current address with the supplied instructions.
    193 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
    194   Instr* pc = reinterpret_cast<Instr*>(pc_);
    195   Instr* instr = reinterpret_cast<Instr*>(instructions);
    196   for (int i = 0; i < instruction_count; i++) {
    197     *(pc + i) = *(instr + i);
    198   }
    199 
    200   // Indicate that code has changed.
    201   CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
    202 }
    203 
    204 
    205 // Patch the code at the current PC with a call to the target address.
    206 // Additional guard instructions can be added if required.
    207 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
    208   // Patch the code at the current address with a call to the target.
    209   UNIMPLEMENTED_MIPS();
    210 }
    211 
    212 
    213 // -----------------------------------------------------------------------------
    214 // Implementation of Operand and MemOperand.
    215 // See assembler-mips-inl.h for inlined constructors.
    216 
    217 Operand::Operand(Handle<Object> handle) {
    218   AllowDeferredHandleDereference using_raw_address;
    219   rm_ = no_reg;
    220   // Verify all Objects referred by code are NOT in new space.
    221   Object* obj = *handle;
    222   if (obj->IsHeapObject()) {
    223     ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
    224     imm32_ = reinterpret_cast<intptr_t>(handle.location());
    225     rmode_ = RelocInfo::EMBEDDED_OBJECT;
    226   } else {
    227     // No relocation needed.
    228     imm32_ = reinterpret_cast<intptr_t>(obj);
    229     rmode_ = RelocInfo::NONE32;
    230   }
    231 }
    232 
    233 
    234 MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
    235   offset_ = offset;
    236 }
    237 
    238 
    239 MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
    240                        OffsetAddend offset_addend) : Operand(rm) {
    241   offset_ = unit * multiplier + offset_addend;
    242 }
    243 
    244 
    245 // -----------------------------------------------------------------------------
    246 // Specific instructions, constants, and masks.
    247 
    248 static const int kNegOffset = 0x00008000;
    249 // addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
    250 // operations as post-increment of sp.
    251 const Instr kPopInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
    252       | (kRegister_sp_Code << kRtShift)
    253       | (kPointerSize & kImm16Mask);  // NOLINT
    254 // addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
    255 const Instr kPushInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
    256       | (kRegister_sp_Code << kRtShift)
    257       | (-kPointerSize & kImm16Mask);  // NOLINT
    258 // sw(r, MemOperand(sp, 0))
    259 const Instr kPushRegPattern = SW | (kRegister_sp_Code << kRsShift)
    260       | (0 & kImm16Mask);  // NOLINT
    261 //  lw(r, MemOperand(sp, 0))
    262 const Instr kPopRegPattern = LW | (kRegister_sp_Code << kRsShift)
    263       | (0 & kImm16Mask);  // NOLINT
    264 
    265 const Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
    266       | (0 & kImm16Mask);  // NOLINT
    267 
    268 const Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
    269       | (0 & kImm16Mask);  // NOLINT
    270 
    271 const Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
    272       | (kNegOffset & kImm16Mask);  // NOLINT
    273 
    274 const Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
    275       | (kNegOffset & kImm16Mask);  // NOLINT
    276 // A mask for the Rt register for push, pop, lw, sw instructions.
    277 const Instr kRtMask = kRtFieldMask;
    278 const Instr kLwSwInstrTypeMask = 0xffe00000;
    279 const Instr kLwSwInstrArgumentMask  = ~kLwSwInstrTypeMask;
    280 const Instr kLwSwOffsetMask = kImm16Mask;
    281 
    282 
    283 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
    284     : AssemblerBase(isolate, buffer, buffer_size),
    285       recorded_ast_id_(TypeFeedbackId::None()),
    286       positions_recorder_(this) {
    287   reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
    288 
    289   last_trampoline_pool_end_ = 0;
    290   no_trampoline_pool_before_ = 0;
    291   trampoline_pool_blocked_nesting_ = 0;
    292   // We leave space (16 * kTrampolineSlotsSize)
    293   // for BlockTrampolinePoolScope buffer.
    294   next_buffer_check_ = FLAG_force_long_branches
    295       ? kMaxInt : kMaxBranchOffset - kTrampolineSlotsSize * 16;
    296   internal_trampoline_exception_ = false;
    297   last_bound_pos_ = 0;
    298 
    299   trampoline_emitted_ = FLAG_force_long_branches;
    300   unbound_labels_count_ = 0;
    301   block_buffer_growth_ = false;
    302 
    303   ClearRecordedAstId();
    304 }
    305 
    306 
    307 void Assembler::GetCode(CodeDesc* desc) {
    308   ASSERT(pc_ <= reloc_info_writer.pos());  // No overlap.
    309   // Set up code descriptor.
    310   desc->buffer = buffer_;
    311   desc->buffer_size = buffer_size_;
    312   desc->instr_size = pc_offset();
    313   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
    314   desc->origin = this;
    315 }
    316 
    317 
    318 void Assembler::Align(int m) {
    319   ASSERT(m >= 4 && IsPowerOf2(m));
    320   while ((pc_offset() & (m - 1)) != 0) {
    321     nop();
    322   }
    323 }
    324 
    325 
    326 void Assembler::CodeTargetAlign() {
    327   // No advantage to aligning branch/call targets to more than
    328   // single instruction, that I am aware of.
    329   Align(4);
    330 }
    331 
    332 
    333 Register Assembler::GetRtReg(Instr instr) {
    334   Register rt;
    335   rt.code_ = (instr & kRtFieldMask) >> kRtShift;
    336   return rt;
    337 }
    338 
    339 
    340 Register Assembler::GetRsReg(Instr instr) {
    341   Register rs;
    342   rs.code_ = (instr & kRsFieldMask) >> kRsShift;
    343   return rs;
    344 }
    345 
    346 
    347 Register Assembler::GetRdReg(Instr instr) {
    348   Register rd;
    349   rd.code_ = (instr & kRdFieldMask) >> kRdShift;
    350   return rd;
    351 }
    352 
    353 
    354 uint32_t Assembler::GetRt(Instr instr) {
    355   return (instr & kRtFieldMask) >> kRtShift;
    356 }
    357 
    358 
    359 uint32_t Assembler::GetRtField(Instr instr) {
    360   return instr & kRtFieldMask;
    361 }
    362 
    363 
    364 uint32_t Assembler::GetRs(Instr instr) {
    365   return (instr & kRsFieldMask) >> kRsShift;
    366 }
    367 
    368 
    369 uint32_t Assembler::GetRsField(Instr instr) {
    370   return instr & kRsFieldMask;
    371 }
    372 
    373 
    374 uint32_t Assembler::GetRd(Instr instr) {
    375   return  (instr & kRdFieldMask) >> kRdShift;
    376 }
    377 
    378 
    379 uint32_t Assembler::GetRdField(Instr instr) {
    380   return  instr & kRdFieldMask;
    381 }
    382 
    383 
    384 uint32_t Assembler::GetSa(Instr instr) {
    385   return (instr & kSaFieldMask) >> kSaShift;
    386 }
    387 
    388 
    389 uint32_t Assembler::GetSaField(Instr instr) {
    390   return instr & kSaFieldMask;
    391 }
    392 
    393 
    394 uint32_t Assembler::GetOpcodeField(Instr instr) {
    395   return instr & kOpcodeMask;
    396 }
    397 
    398 
    399 uint32_t Assembler::GetFunction(Instr instr) {
    400   return (instr & kFunctionFieldMask) >> kFunctionShift;
    401 }
    402 
    403 
    404 uint32_t Assembler::GetFunctionField(Instr instr) {
    405   return instr & kFunctionFieldMask;
    406 }
    407 
    408 
    409 uint32_t Assembler::GetImmediate16(Instr instr) {
    410   return instr & kImm16Mask;
    411 }
    412 
    413 
    414 uint32_t Assembler::GetLabelConst(Instr instr) {
    415   return instr & ~kImm16Mask;
    416 }
    417 
    418 
    419 bool Assembler::IsPop(Instr instr) {
    420   return (instr & ~kRtMask) == kPopRegPattern;
    421 }
    422 
    423 
    424 bool Assembler::IsPush(Instr instr) {
    425   return (instr & ~kRtMask) == kPushRegPattern;
    426 }
    427 
    428 
    429 bool Assembler::IsSwRegFpOffset(Instr instr) {
    430   return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
    431 }
    432 
    433 
    434 bool Assembler::IsLwRegFpOffset(Instr instr) {
    435   return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
    436 }
    437 
    438 
    439 bool Assembler::IsSwRegFpNegOffset(Instr instr) {
    440   return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
    441           kSwRegFpNegOffsetPattern);
    442 }
    443 
    444 
    445 bool Assembler::IsLwRegFpNegOffset(Instr instr) {
    446   return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
    447           kLwRegFpNegOffsetPattern);
    448 }
    449 
    450 
    451 // Labels refer to positions in the (to be) generated code.
    452 // There are bound, linked, and unused labels.
    453 //
    454 // Bound labels refer to known positions in the already
    455 // generated code. pos() is the position the label refers to.
    456 //
    457 // Linked labels refer to unknown positions in the code
    458 // to be generated; pos() is the position of the last
    459 // instruction using the label.
    460 
    461 // The link chain is terminated by a value in the instruction of -1,
    462 // which is an otherwise illegal value (branch -1 is inf loop).
    463 // The instruction 16-bit offset field addresses 32-bit words, but in
    464 // code is conv to an 18-bit value addressing bytes, hence the -4 value.
    465 
    466 const int kEndOfChain = -4;
    467 // Determines the end of the Jump chain (a subset of the label link chain).
    468 const int kEndOfJumpChain = 0;
    469 
    470 
    471 bool Assembler::IsBranch(Instr instr) {
    472   uint32_t opcode   = GetOpcodeField(instr);
    473   uint32_t rt_field = GetRtField(instr);
    474   uint32_t rs_field = GetRsField(instr);
    475   // Checks if the instruction is a branch.
    476   return opcode == BEQ ||
    477       opcode == BNE ||
    478       opcode == BLEZ ||
    479       opcode == BGTZ ||
    480       opcode == BEQL ||
    481       opcode == BNEL ||
    482       opcode == BLEZL ||
    483       opcode == BGTZL ||
    484       (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
    485                             rt_field == BLTZAL || rt_field == BGEZAL)) ||
    486       (opcode == COP1 && rs_field == BC1);  // Coprocessor branch.
    487 }
    488 
    489 
    490 bool Assembler::IsEmittedConstant(Instr instr) {
    491   uint32_t label_constant = GetLabelConst(instr);
    492   return label_constant == 0;  // Emitted label const in reg-exp engine.
    493 }
    494 
    495 
    496 bool Assembler::IsBeq(Instr instr) {
    497   return GetOpcodeField(instr) == BEQ;
    498 }
    499 
    500 
    501 bool Assembler::IsBne(Instr instr) {
    502   return GetOpcodeField(instr) == BNE;
    503 }
    504 
    505 
    506 bool Assembler::IsJump(Instr instr) {
    507   uint32_t opcode   = GetOpcodeField(instr);
    508   uint32_t rt_field = GetRtField(instr);
    509   uint32_t rd_field = GetRdField(instr);
    510   uint32_t function_field = GetFunctionField(instr);
    511   // Checks if the instruction is a jump.
    512   return opcode == J || opcode == JAL ||
    513       (opcode == SPECIAL && rt_field == 0 &&
    514       ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
    515 }
    516 
    517 
    518 bool Assembler::IsJ(Instr instr) {
    519   uint32_t opcode = GetOpcodeField(instr);
    520   // Checks if the instruction is a jump.
    521   return opcode == J;
    522 }
    523 
    524 
    525 bool Assembler::IsJal(Instr instr) {
    526   return GetOpcodeField(instr) == JAL;
    527 }
    528 
    529 
    530 bool Assembler::IsJr(Instr instr) {
    531   return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR;
    532 }
    533 
    534 
    535 bool Assembler::IsJalr(Instr instr) {
    536   return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR;
    537 }
    538 
    539 
    540 bool Assembler::IsLui(Instr instr) {
    541   uint32_t opcode = GetOpcodeField(instr);
    542   // Checks if the instruction is a load upper immediate.
    543   return opcode == LUI;
    544 }
    545 
    546 
    547 bool Assembler::IsOri(Instr instr) {
    548   uint32_t opcode = GetOpcodeField(instr);
    549   // Checks if the instruction is a load upper immediate.
    550   return opcode == ORI;
    551 }
    552 
    553 
    554 bool Assembler::IsNop(Instr instr, unsigned int type) {
    555   // See Assembler::nop(type).
    556   ASSERT(type < 32);
    557   uint32_t opcode = GetOpcodeField(instr);
    558   uint32_t function = GetFunctionField(instr);
    559   uint32_t rt = GetRt(instr);
    560   uint32_t rd = GetRd(instr);
    561   uint32_t sa = GetSa(instr);
    562 
    563   // Traditional mips nop == sll(zero_reg, zero_reg, 0)
    564   // When marking non-zero type, use sll(zero_reg, at, type)
    565   // to avoid use of mips ssnop and ehb special encodings
    566   // of the sll instruction.
    567 
    568   Register nop_rt_reg = (type == 0) ? zero_reg : at;
    569   bool ret = (opcode == SPECIAL && function == SLL &&
    570               rd == static_cast<uint32_t>(ToNumber(zero_reg)) &&
    571               rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) &&
    572               sa == type);
    573 
    574   return ret;
    575 }
    576 
    577 
    578 int32_t Assembler::GetBranchOffset(Instr instr) {
    579   ASSERT(IsBranch(instr));
    580   return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
    581 }
    582 
    583 
    584 bool Assembler::IsLw(Instr instr) {
    585   return ((instr & kOpcodeMask) == LW);
    586 }
    587 
    588 
    589 int16_t Assembler::GetLwOffset(Instr instr) {
    590   ASSERT(IsLw(instr));
    591   return ((instr & kImm16Mask));
    592 }
    593 
    594 
    595 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
    596   ASSERT(IsLw(instr));
    597 
    598   // We actually create a new lw instruction based on the original one.
    599   Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
    600       | (offset & kImm16Mask);
    601 
    602   return temp_instr;
    603 }
    604 
    605 
    606 bool Assembler::IsSw(Instr instr) {
    607   return ((instr & kOpcodeMask) == SW);
    608 }
    609 
    610 
    611 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
    612   ASSERT(IsSw(instr));
    613   return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
    614 }
    615 
    616 
    617 bool Assembler::IsAddImmediate(Instr instr) {
    618   return ((instr & kOpcodeMask) == ADDIU);
    619 }
    620 
    621 
    622 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
    623   ASSERT(IsAddImmediate(instr));
    624   return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
    625 }
    626 
    627 
    628 bool Assembler::IsAndImmediate(Instr instr) {
    629   return GetOpcodeField(instr) == ANDI;
    630 }
    631 
    632 
    633 int Assembler::target_at(int32_t pos) {
    634   Instr instr = instr_at(pos);
    635   if ((instr & ~kImm16Mask) == 0) {
    636     // Emitted label constant, not part of a branch.
    637     if (instr == 0) {
    638        return kEndOfChain;
    639      } else {
    640        int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
    641        return (imm18 + pos);
    642      }
    643   }
    644   // Check we have a branch or jump instruction.
    645   ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr));
    646   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
    647   // the compiler uses arithmectic shifts for signed integers.
    648   if (IsBranch(instr)) {
    649     int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
    650 
    651     if (imm18 == kEndOfChain) {
    652       // EndOfChain sentinel is returned directly, not relative to pc or pos.
    653       return kEndOfChain;
    654     } else {
    655       return pos + kBranchPCOffset + imm18;
    656     }
    657   } else if (IsLui(instr)) {
    658     Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
    659     Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
    660     ASSERT(IsOri(instr_ori));
    661     int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
    662     imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
    663 
    664     if (imm == kEndOfJumpChain) {
    665       // EndOfChain sentinel is returned directly, not relative to pc or pos.
    666       return kEndOfChain;
    667     } else {
    668       uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
    669       int32_t delta = instr_address - imm;
    670       ASSERT(pos > delta);
    671       return pos - delta;
    672     }
    673   } else {
    674     int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
    675     if (imm28 == kEndOfJumpChain) {
    676       // EndOfChain sentinel is returned directly, not relative to pc or pos.
    677       return kEndOfChain;
    678     } else {
    679       uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
    680       instr_address &= kImm28Mask;
    681       int32_t delta = instr_address - imm28;
    682       ASSERT(pos > delta);
    683       return pos - delta;
    684     }
    685   }
    686 }
    687 
    688 
    689 void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
    690   Instr instr = instr_at(pos);
    691   if ((instr & ~kImm16Mask) == 0) {
    692     ASSERT(target_pos == kEndOfChain || target_pos >= 0);
    693     // Emitted label constant, not part of a branch.
    694     // Make label relative to Code* of generated Code object.
    695     instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
    696     return;
    697   }
    698 
    699   ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr));
    700   if (IsBranch(instr)) {
    701     int32_t imm18 = target_pos - (pos + kBranchPCOffset);
    702     ASSERT((imm18 & 3) == 0);
    703 
    704     instr &= ~kImm16Mask;
    705     int32_t imm16 = imm18 >> 2;
    706     ASSERT(is_int16(imm16));
    707 
    708     instr_at_put(pos, instr | (imm16 & kImm16Mask));
    709   } else if (IsLui(instr)) {
    710     Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
    711     Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
    712     ASSERT(IsOri(instr_ori));
    713     uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
    714     ASSERT((imm & 3) == 0);
    715 
    716     instr_lui &= ~kImm16Mask;
    717     instr_ori &= ~kImm16Mask;
    718 
    719     instr_at_put(pos + 0 * Assembler::kInstrSize,
    720                  instr_lui | ((imm & kHiMask) >> kLuiShift));
    721     instr_at_put(pos + 1 * Assembler::kInstrSize,
    722                  instr_ori | (imm & kImm16Mask));
    723   } else {
    724     uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos;
    725     imm28 &= kImm28Mask;
    726     ASSERT((imm28 & 3) == 0);
    727 
    728     instr &= ~kImm26Mask;
    729     uint32_t imm26 = imm28 >> 2;
    730     ASSERT(is_uint26(imm26));
    731 
    732     instr_at_put(pos, instr | (imm26 & kImm26Mask));
    733   }
    734 }
    735 
    736 
    737 void Assembler::print(Label* L) {
    738   if (L->is_unused()) {
    739     PrintF("unused label\n");
    740   } else if (L->is_bound()) {
    741     PrintF("bound label to %d\n", L->pos());
    742   } else if (L->is_linked()) {
    743     Label l = *L;
    744     PrintF("unbound label");
    745     while (l.is_linked()) {
    746       PrintF("@ %d ", l.pos());
    747       Instr instr = instr_at(l.pos());
    748       if ((instr & ~kImm16Mask) == 0) {
    749         PrintF("value\n");
    750       } else {
    751         PrintF("%d\n", instr);
    752       }
    753       next(&l);
    754     }
    755   } else {
    756     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
    757   }
    758 }
    759 
    760 
    761 void Assembler::bind_to(Label* L, int pos) {
    762   ASSERT(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
    763   int32_t trampoline_pos = kInvalidSlotPos;
    764   if (L->is_linked() && !trampoline_emitted_) {
    765     unbound_labels_count_--;
    766     next_buffer_check_ += kTrampolineSlotsSize;
    767   }
    768 
    769   while (L->is_linked()) {
    770     int32_t fixup_pos = L->pos();
    771     int32_t dist = pos - fixup_pos;
    772     next(L);  // Call next before overwriting link with target at fixup_pos.
    773     Instr instr = instr_at(fixup_pos);
    774     if (IsBranch(instr)) {
    775       if (dist > kMaxBranchOffset) {
    776         if (trampoline_pos == kInvalidSlotPos) {
    777           trampoline_pos = get_trampoline_entry(fixup_pos);
    778           CHECK(trampoline_pos != kInvalidSlotPos);
    779         }
    780         ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
    781         target_at_put(fixup_pos, trampoline_pos);
    782         fixup_pos = trampoline_pos;
    783         dist = pos - fixup_pos;
    784       }
    785       target_at_put(fixup_pos, pos);
    786     } else {
    787       ASSERT(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr));
    788       target_at_put(fixup_pos, pos);
    789     }
    790   }
    791   L->bind_to(pos);
    792 
    793   // Keep track of the last bound label so we don't eliminate any instructions
    794   // before a bound label.
    795   if (pos > last_bound_pos_)
    796     last_bound_pos_ = pos;
    797 }
    798 
    799 
    800 void Assembler::bind(Label* L) {
    801   ASSERT(!L->is_bound());  // Label can only be bound once.
    802   bind_to(L, pc_offset());
    803 }
    804 
    805 
    806 void Assembler::next(Label* L) {
    807   ASSERT(L->is_linked());
    808   int link = target_at(L->pos());
    809   if (link == kEndOfChain) {
    810     L->Unuse();
    811   } else {
    812     ASSERT(link >= 0);
    813     L->link_to(link);
    814   }
    815 }
    816 
    817 
    818 bool Assembler::is_near(Label* L) {
    819   if (L->is_bound()) {
    820     return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize);
    821   }
    822   return false;
    823 }
    824 
    825 
    826 // We have to use a temporary register for things that can be relocated even
    827 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
    828 // space.  There is no guarantee that the relocated location can be similarly
    829 // encoded.
    830 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
    831   return !RelocInfo::IsNone(rmode);
    832 }
    833 
    834 void Assembler::GenInstrRegister(Opcode opcode,
    835                                  Register rs,
    836                                  Register rt,
    837                                  Register rd,
    838                                  uint16_t sa,
    839                                  SecondaryField func) {
    840   ASSERT(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
    841   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
    842       | (rd.code() << kRdShift) | (sa << kSaShift) | func;
    843   emit(instr);
    844 }
    845 
    846 
    847 void Assembler::GenInstrRegister(Opcode opcode,
    848                                  Register rs,
    849                                  Register rt,
    850                                  uint16_t msb,
    851                                  uint16_t lsb,
    852                                  SecondaryField func) {
    853   ASSERT(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
    854   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
    855       | (msb << kRdShift) | (lsb << kSaShift) | func;
    856   emit(instr);
    857 }
    858 
    859 
    860 void Assembler::GenInstrRegister(Opcode opcode,
    861                                  SecondaryField fmt,
    862                                  FPURegister ft,
    863                                  FPURegister fs,
    864                                  FPURegister fd,
    865                                  SecondaryField func) {
    866   ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
    867   Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
    868       | (fd.code() << kFdShift) | func;
    869   emit(instr);
    870 }
    871 
    872 
    873 void Assembler::GenInstrRegister(Opcode opcode,
    874                                  FPURegister fr,
    875                                  FPURegister ft,
    876                                  FPURegister fs,
    877                                  FPURegister fd,
    878                                  SecondaryField func) {
    879   ASSERT(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
    880   Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
    881       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
    882   emit(instr);
    883 }
    884 
    885 
    886 void Assembler::GenInstrRegister(Opcode opcode,
    887                                  SecondaryField fmt,
    888                                  Register rt,
    889                                  FPURegister fs,
    890                                  FPURegister fd,
    891                                  SecondaryField func) {
    892   ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
    893   Instr instr = opcode | fmt | (rt.code() << kRtShift)
    894       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
    895   emit(instr);
    896 }
    897 
    898 
    899 void Assembler::GenInstrRegister(Opcode opcode,
    900                                  SecondaryField fmt,
    901                                  Register rt,
    902                                  FPUControlRegister fs,
    903                                  SecondaryField func) {
    904   ASSERT(fs.is_valid() && rt.is_valid());
    905   Instr instr =
    906       opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
    907   emit(instr);
    908 }
    909 
    910 
    911 // Instructions with immediate value.
    912 // Registers are in the order of the instruction encoding, from left to right.
    913 void Assembler::GenInstrImmediate(Opcode opcode,
    914                                   Register rs,
    915                                   Register rt,
    916                                   int32_t j) {
    917   ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
    918   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
    919       | (j & kImm16Mask);
    920   emit(instr);
    921 }
    922 
    923 
    924 void Assembler::GenInstrImmediate(Opcode opcode,
    925                                   Register rs,
    926                                   SecondaryField SF,
    927                                   int32_t j) {
    928   ASSERT(rs.is_valid() && (is_int16(j) || is_uint16(j)));
    929   Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
    930   emit(instr);
    931 }
    932 
    933 
    934 void Assembler::GenInstrImmediate(Opcode opcode,
    935                                   Register rs,
    936                                   FPURegister ft,
    937                                   int32_t j) {
    938   ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
    939   Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
    940       | (j & kImm16Mask);
    941   emit(instr);
    942 }
    943 
    944 
    945 void Assembler::GenInstrJump(Opcode opcode,
    946                              uint32_t address) {
    947   BlockTrampolinePoolScope block_trampoline_pool(this);
    948   ASSERT(is_uint26(address));
    949   Instr instr = opcode | address;
    950   emit(instr);
    951   BlockTrampolinePoolFor(1);  // For associated delay slot.
    952 }
    953 
    954 
    955 // Returns the next free trampoline entry.
    956 int32_t Assembler::get_trampoline_entry(int32_t pos) {
    957   int32_t trampoline_entry = kInvalidSlotPos;
    958 
    959   if (!internal_trampoline_exception_) {
    960     if (trampoline_.start() > pos) {
    961      trampoline_entry = trampoline_.take_slot();
    962     }
    963 
    964     if (kInvalidSlotPos == trampoline_entry) {
    965       internal_trampoline_exception_ = true;
    966     }
    967   }
    968   return trampoline_entry;
    969 }
    970 
    971 
    972 uint32_t Assembler::jump_address(Label* L) {
    973   int32_t target_pos;
    974 
    975   if (L->is_bound()) {
    976     target_pos = L->pos();
    977   } else {
    978     if (L->is_linked()) {
    979       target_pos = L->pos();  // L's link.
    980       L->link_to(pc_offset());
    981     } else {
    982       L->link_to(pc_offset());
    983       return kEndOfJumpChain;
    984     }
    985   }
    986 
    987   uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
    988   ASSERT((imm & 3) == 0);
    989 
    990   return imm;
    991 }
    992 
    993 
    994 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
    995   int32_t target_pos;
    996 
    997   if (L->is_bound()) {
    998     target_pos = L->pos();
    999   } else {
   1000     if (L->is_linked()) {
   1001       target_pos = L->pos();
   1002       L->link_to(pc_offset());
   1003     } else {
   1004       L->link_to(pc_offset());
   1005       if (!trampoline_emitted_) {
   1006         unbound_labels_count_++;
   1007         next_buffer_check_ -= kTrampolineSlotsSize;
   1008       }
   1009       return kEndOfChain;
   1010     }
   1011   }
   1012 
   1013   int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
   1014   ASSERT((offset & 3) == 0);
   1015   ASSERT(is_int16(offset >> 2));
   1016 
   1017   return offset;
   1018 }
   1019 
   1020 
   1021 void Assembler::label_at_put(Label* L, int at_offset) {
   1022   int target_pos;
   1023   if (L->is_bound()) {
   1024     target_pos = L->pos();
   1025     instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
   1026   } else {
   1027     if (L->is_linked()) {
   1028       target_pos = L->pos();  // L's link.
   1029       int32_t imm18 = target_pos - at_offset;
   1030       ASSERT((imm18 & 3) == 0);
   1031       int32_t imm16 = imm18 >> 2;
   1032       ASSERT(is_int16(imm16));
   1033       instr_at_put(at_offset, (imm16 & kImm16Mask));
   1034     } else {
   1035       target_pos = kEndOfChain;
   1036       instr_at_put(at_offset, 0);
   1037       if (!trampoline_emitted_) {
   1038         unbound_labels_count_++;
   1039         next_buffer_check_ -= kTrampolineSlotsSize;
   1040       }
   1041     }
   1042     L->link_to(at_offset);
   1043   }
   1044 }
   1045 
   1046 
   1047 //------- Branch and jump instructions --------
   1048 
   1049 void Assembler::b(int16_t offset) {
   1050   beq(zero_reg, zero_reg, offset);
   1051 }
   1052 
   1053 
   1054 void Assembler::bal(int16_t offset) {
   1055   positions_recorder()->WriteRecordedPositions();
   1056   bgezal(zero_reg, offset);
   1057 }
   1058 
   1059 
   1060 void Assembler::beq(Register rs, Register rt, int16_t offset) {
   1061   BlockTrampolinePoolScope block_trampoline_pool(this);
   1062   GenInstrImmediate(BEQ, rs, rt, offset);
   1063   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1064 }
   1065 
   1066 
   1067 void Assembler::bgez(Register rs, int16_t offset) {
   1068   BlockTrampolinePoolScope block_trampoline_pool(this);
   1069   GenInstrImmediate(REGIMM, rs, BGEZ, offset);
   1070   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1071 }
   1072 
   1073 
   1074 void Assembler::bgezal(Register rs, int16_t offset) {
   1075   BlockTrampolinePoolScope block_trampoline_pool(this);
   1076   positions_recorder()->WriteRecordedPositions();
   1077   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
   1078   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1079 }
   1080 
   1081 
   1082 void Assembler::bgtz(Register rs, int16_t offset) {
   1083   BlockTrampolinePoolScope block_trampoline_pool(this);
   1084   GenInstrImmediate(BGTZ, rs, zero_reg, offset);
   1085   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1086 }
   1087 
   1088 
   1089 void Assembler::blez(Register rs, int16_t offset) {
   1090   BlockTrampolinePoolScope block_trampoline_pool(this);
   1091   GenInstrImmediate(BLEZ, rs, zero_reg, offset);
   1092   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1093 }
   1094 
   1095 
   1096 void Assembler::bltz(Register rs, int16_t offset) {
   1097   BlockTrampolinePoolScope block_trampoline_pool(this);
   1098   GenInstrImmediate(REGIMM, rs, BLTZ, offset);
   1099   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1100 }
   1101 
   1102 
   1103 void Assembler::bltzal(Register rs, int16_t offset) {
   1104   BlockTrampolinePoolScope block_trampoline_pool(this);
   1105   positions_recorder()->WriteRecordedPositions();
   1106   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
   1107   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1108 }
   1109 
   1110 
   1111 void Assembler::bne(Register rs, Register rt, int16_t offset) {
   1112   BlockTrampolinePoolScope block_trampoline_pool(this);
   1113   GenInstrImmediate(BNE, rs, rt, offset);
   1114   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1115 }
   1116 
   1117 
   1118 void Assembler::j(int32_t target) {
   1119 #if DEBUG
   1120   // Get pc of delay slot.
   1121   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
   1122   bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
   1123                   (kImm26Bits + kImmFieldShift)) == 0;
   1124   ASSERT(in_range && ((target & 3) == 0));
   1125 #endif
   1126   GenInstrJump(J, target >> 2);
   1127 }
   1128 
   1129 
   1130 void Assembler::jr(Register rs) {
   1131   BlockTrampolinePoolScope block_trampoline_pool(this);
   1132   if (rs.is(ra)) {
   1133     positions_recorder()->WriteRecordedPositions();
   1134   }
   1135   GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
   1136   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1137 }
   1138 
   1139 
   1140 void Assembler::jal(int32_t target) {
   1141 #ifdef DEBUG
   1142   // Get pc of delay slot.
   1143   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
   1144   bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
   1145                   (kImm26Bits + kImmFieldShift)) == 0;
   1146   ASSERT(in_range && ((target & 3) == 0));
   1147 #endif
   1148   positions_recorder()->WriteRecordedPositions();
   1149   GenInstrJump(JAL, target >> 2);
   1150 }
   1151 
   1152 
   1153 void Assembler::jalr(Register rs, Register rd) {
   1154   BlockTrampolinePoolScope block_trampoline_pool(this);
   1155   positions_recorder()->WriteRecordedPositions();
   1156   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
   1157   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1158 }
   1159 
   1160 
   1161 void Assembler::j_or_jr(int32_t target, Register rs) {
   1162   // Get pc of delay slot.
   1163   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
   1164   bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
   1165                   (kImm26Bits + kImmFieldShift)) == 0;
   1166   if (in_range) {
   1167       j(target);
   1168   } else {
   1169       jr(t9);
   1170   }
   1171 }
   1172 
   1173 
   1174 void Assembler::jal_or_jalr(int32_t target, Register rs) {
   1175   // Get pc of delay slot.
   1176   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
   1177   bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
   1178                   (kImm26Bits+kImmFieldShift)) == 0;
   1179   if (in_range) {
   1180       jal(target);
   1181   } else {
   1182       jalr(t9);
   1183   }
   1184 }
   1185 
   1186 
   1187 // -------Data-processing-instructions---------
   1188 
   1189 // Arithmetic.
   1190 
   1191 void Assembler::addu(Register rd, Register rs, Register rt) {
   1192   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
   1193 }
   1194 
   1195 
   1196 void Assembler::addiu(Register rd, Register rs, int32_t j) {
   1197   GenInstrImmediate(ADDIU, rs, rd, j);
   1198 }
   1199 
   1200 
   1201 void Assembler::subu(Register rd, Register rs, Register rt) {
   1202   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
   1203 }
   1204 
   1205 
   1206 void Assembler::mul(Register rd, Register rs, Register rt) {
   1207   GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
   1208 }
   1209 
   1210 
   1211 void Assembler::mult(Register rs, Register rt) {
   1212   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
   1213 }
   1214 
   1215 
   1216 void Assembler::multu(Register rs, Register rt) {
   1217   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
   1218 }
   1219 
   1220 
   1221 void Assembler::div(Register rs, Register rt) {
   1222   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
   1223 }
   1224 
   1225 
   1226 void Assembler::divu(Register rs, Register rt) {
   1227   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
   1228 }
   1229 
   1230 
   1231 // Logical.
   1232 
   1233 void Assembler::and_(Register rd, Register rs, Register rt) {
   1234   GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
   1235 }
   1236 
   1237 
   1238 void Assembler::andi(Register rt, Register rs, int32_t j) {
   1239   ASSERT(is_uint16(j));
   1240   GenInstrImmediate(ANDI, rs, rt, j);
   1241 }
   1242 
   1243 
   1244 void Assembler::or_(Register rd, Register rs, Register rt) {
   1245   GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
   1246 }
   1247 
   1248 
   1249 void Assembler::ori(Register rt, Register rs, int32_t j) {
   1250   ASSERT(is_uint16(j));
   1251   GenInstrImmediate(ORI, rs, rt, j);
   1252 }
   1253 
   1254 
   1255 void Assembler::xor_(Register rd, Register rs, Register rt) {
   1256   GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
   1257 }
   1258 
   1259 
   1260 void Assembler::xori(Register rt, Register rs, int32_t j) {
   1261   ASSERT(is_uint16(j));
   1262   GenInstrImmediate(XORI, rs, rt, j);
   1263 }
   1264 
   1265 
   1266 void Assembler::nor(Register rd, Register rs, Register rt) {
   1267   GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
   1268 }
   1269 
   1270 
   1271 // Shifts.
   1272 void Assembler::sll(Register rd,
   1273                     Register rt,
   1274                     uint16_t sa,
   1275                     bool coming_from_nop) {
   1276   // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
   1277   // generated using the sll instruction. They must be generated using
   1278   // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
   1279   // instructions.
   1280   ASSERT(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
   1281   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL);
   1282 }
   1283 
   1284 
   1285 void Assembler::sllv(Register rd, Register rt, Register rs) {
   1286   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
   1287 }
   1288 
   1289 
   1290 void Assembler::srl(Register rd, Register rt, uint16_t sa) {
   1291   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL);
   1292 }
   1293 
   1294 
   1295 void Assembler::srlv(Register rd, Register rt, Register rs) {
   1296   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
   1297 }
   1298 
   1299 
   1300 void Assembler::sra(Register rd, Register rt, uint16_t sa) {
   1301   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA);
   1302 }
   1303 
   1304 
   1305 void Assembler::srav(Register rd, Register rt, Register rs) {
   1306   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
   1307 }
   1308 
   1309 
   1310 void Assembler::rotr(Register rd, Register rt, uint16_t sa) {
   1311   // Should be called via MacroAssembler::Ror.
   1312   ASSERT(rd.is_valid() && rt.is_valid() && is_uint5(sa));
   1313   ASSERT(kArchVariant == kMips32r2);
   1314   Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
   1315       | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
   1316   emit(instr);
   1317 }
   1318 
   1319 
   1320 void Assembler::rotrv(Register rd, Register rt, Register rs) {
   1321   // Should be called via MacroAssembler::Ror.
   1322   ASSERT(rd.is_valid() && rt.is_valid() && rs.is_valid() );
   1323   ASSERT(kArchVariant == kMips32r2);
   1324   Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
   1325      | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
   1326   emit(instr);
   1327 }
   1328 
   1329 
   1330 // ------------Memory-instructions-------------
   1331 
   1332 // Helper for base-reg + offset, when offset is larger than int16.
   1333 void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
   1334   ASSERT(!src.rm().is(at));
   1335   lui(at, (src.offset_ >> kLuiShift) & kImm16Mask);
   1336   ori(at, at, src.offset_ & kImm16Mask);  // Load 32-bit offset.
   1337   addu(at, at, src.rm());  // Add base register.
   1338 }
   1339 
   1340 
   1341 void Assembler::lb(Register rd, const MemOperand& rs) {
   1342   if (is_int16(rs.offset_)) {
   1343     GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
   1344   } else {  // Offset > 16 bits, use multiple instructions to load.
   1345     LoadRegPlusOffsetToAt(rs);
   1346     GenInstrImmediate(LB, at, rd, 0);  // Equiv to lb(rd, MemOperand(at, 0));
   1347   }
   1348 }
   1349 
   1350 
   1351 void Assembler::lbu(Register rd, const MemOperand& rs) {
   1352   if (is_int16(rs.offset_)) {
   1353     GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
   1354   } else {  // Offset > 16 bits, use multiple instructions to load.
   1355     LoadRegPlusOffsetToAt(rs);
   1356     GenInstrImmediate(LBU, at, rd, 0);  // Equiv to lbu(rd, MemOperand(at, 0));
   1357   }
   1358 }
   1359 
   1360 
   1361 void Assembler::lh(Register rd, const MemOperand& rs) {
   1362   if (is_int16(rs.offset_)) {
   1363     GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
   1364   } else {  // Offset > 16 bits, use multiple instructions to load.
   1365     LoadRegPlusOffsetToAt(rs);
   1366     GenInstrImmediate(LH, at, rd, 0);  // Equiv to lh(rd, MemOperand(at, 0));
   1367   }
   1368 }
   1369 
   1370 
   1371 void Assembler::lhu(Register rd, const MemOperand& rs) {
   1372   if (is_int16(rs.offset_)) {
   1373     GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
   1374   } else {  // Offset > 16 bits, use multiple instructions to load.
   1375     LoadRegPlusOffsetToAt(rs);
   1376     GenInstrImmediate(LHU, at, rd, 0);  // Equiv to lhu(rd, MemOperand(at, 0));
   1377   }
   1378 }
   1379 
   1380 
   1381 void Assembler::lw(Register rd, const MemOperand& rs) {
   1382   if (is_int16(rs.offset_)) {
   1383     GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
   1384   } else {  // Offset > 16 bits, use multiple instructions to load.
   1385     LoadRegPlusOffsetToAt(rs);
   1386     GenInstrImmediate(LW, at, rd, 0);  // Equiv to lw(rd, MemOperand(at, 0));
   1387   }
   1388 }
   1389 
   1390 
   1391 void Assembler::lwl(Register rd, const MemOperand& rs) {
   1392   GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
   1393 }
   1394 
   1395 
   1396 void Assembler::lwr(Register rd, const MemOperand& rs) {
   1397   GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
   1398 }
   1399 
   1400 
   1401 void Assembler::sb(Register rd, const MemOperand& rs) {
   1402   if (is_int16(rs.offset_)) {
   1403     GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
   1404   } else {  // Offset > 16 bits, use multiple instructions to store.
   1405     LoadRegPlusOffsetToAt(rs);
   1406     GenInstrImmediate(SB, at, rd, 0);  // Equiv to sb(rd, MemOperand(at, 0));
   1407   }
   1408 }
   1409 
   1410 
   1411 void Assembler::sh(Register rd, const MemOperand& rs) {
   1412   if (is_int16(rs.offset_)) {
   1413     GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
   1414   } else {  // Offset > 16 bits, use multiple instructions to store.
   1415     LoadRegPlusOffsetToAt(rs);
   1416     GenInstrImmediate(SH, at, rd, 0);  // Equiv to sh(rd, MemOperand(at, 0));
   1417   }
   1418 }
   1419 
   1420 
   1421 void Assembler::sw(Register rd, const MemOperand& rs) {
   1422   if (is_int16(rs.offset_)) {
   1423     GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
   1424   } else {  // Offset > 16 bits, use multiple instructions to store.
   1425     LoadRegPlusOffsetToAt(rs);
   1426     GenInstrImmediate(SW, at, rd, 0);  // Equiv to sw(rd, MemOperand(at, 0));
   1427   }
   1428 }
   1429 
   1430 
   1431 void Assembler::swl(Register rd, const MemOperand& rs) {
   1432   GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
   1433 }
   1434 
   1435 
   1436 void Assembler::swr(Register rd, const MemOperand& rs) {
   1437   GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
   1438 }
   1439 
   1440 
   1441 void Assembler::lui(Register rd, int32_t j) {
   1442   ASSERT(is_uint16(j));
   1443   GenInstrImmediate(LUI, zero_reg, rd, j);
   1444 }
   1445 
   1446 
   1447 // -------------Misc-instructions--------------
   1448 
   1449 // Break / Trap instructions.
   1450 void Assembler::break_(uint32_t code, bool break_as_stop) {
   1451   ASSERT((code & ~0xfffff) == 0);
   1452   // We need to invalidate breaks that could be stops as well because the
   1453   // simulator expects a char pointer after the stop instruction.
   1454   // See constants-mips.h for explanation.
   1455   ASSERT((break_as_stop &&
   1456           code <= kMaxStopCode &&
   1457           code > kMaxWatchpointCode) ||
   1458          (!break_as_stop &&
   1459           (code > kMaxStopCode ||
   1460            code <= kMaxWatchpointCode)));
   1461   Instr break_instr = SPECIAL | BREAK | (code << 6);
   1462   emit(break_instr);
   1463 }
   1464 
   1465 
   1466 void Assembler::stop(const char* msg, uint32_t code) {
   1467   ASSERT(code > kMaxWatchpointCode);
   1468   ASSERT(code <= kMaxStopCode);
   1469 #if V8_HOST_ARCH_MIPS
   1470   break_(0x54321);
   1471 #else  // V8_HOST_ARCH_MIPS
   1472   BlockTrampolinePoolFor(2);
   1473   // The Simulator will handle the stop instruction and get the message address.
   1474   // On MIPS stop() is just a special kind of break_().
   1475   break_(code, true);
   1476   emit(reinterpret_cast<Instr>(msg));
   1477 #endif
   1478 }
   1479 
   1480 
   1481 void Assembler::tge(Register rs, Register rt, uint16_t code) {
   1482   ASSERT(is_uint10(code));
   1483   Instr instr = SPECIAL | TGE | rs.code() << kRsShift
   1484       | rt.code() << kRtShift | code << 6;
   1485   emit(instr);
   1486 }
   1487 
   1488 
   1489 void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
   1490   ASSERT(is_uint10(code));
   1491   Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
   1492       | rt.code() << kRtShift | code << 6;
   1493   emit(instr);
   1494 }
   1495 
   1496 
   1497 void Assembler::tlt(Register rs, Register rt, uint16_t code) {
   1498   ASSERT(is_uint10(code));
   1499   Instr instr =
   1500       SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
   1501   emit(instr);
   1502 }
   1503 
   1504 
   1505 void Assembler::tltu(Register rs, Register rt, uint16_t code) {
   1506   ASSERT(is_uint10(code));
   1507   Instr instr =
   1508       SPECIAL | TLTU | rs.code() << kRsShift
   1509       | rt.code() << kRtShift | code << 6;
   1510   emit(instr);
   1511 }
   1512 
   1513 
   1514 void Assembler::teq(Register rs, Register rt, uint16_t code) {
   1515   ASSERT(is_uint10(code));
   1516   Instr instr =
   1517       SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
   1518   emit(instr);
   1519 }
   1520 
   1521 
   1522 void Assembler::tne(Register rs, Register rt, uint16_t code) {
   1523   ASSERT(is_uint10(code));
   1524   Instr instr =
   1525       SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
   1526   emit(instr);
   1527 }
   1528 
   1529 
   1530 // Move from HI/LO register.
   1531 
   1532 void Assembler::mfhi(Register rd) {
   1533   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
   1534 }
   1535 
   1536 
   1537 void Assembler::mflo(Register rd) {
   1538   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
   1539 }
   1540 
   1541 
   1542 // Set on less than instructions.
   1543 void Assembler::slt(Register rd, Register rs, Register rt) {
   1544   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
   1545 }
   1546 
   1547 
   1548 void Assembler::sltu(Register rd, Register rs, Register rt) {
   1549   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
   1550 }
   1551 
   1552 
   1553 void Assembler::slti(Register rt, Register rs, int32_t j) {
   1554   GenInstrImmediate(SLTI, rs, rt, j);
   1555 }
   1556 
   1557 
   1558 void Assembler::sltiu(Register rt, Register rs, int32_t j) {
   1559   GenInstrImmediate(SLTIU, rs, rt, j);
   1560 }
   1561 
   1562 
   1563 // Conditional move.
   1564 void Assembler::movz(Register rd, Register rs, Register rt) {
   1565   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
   1566 }
   1567 
   1568 
   1569 void Assembler::movn(Register rd, Register rs, Register rt) {
   1570   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
   1571 }
   1572 
   1573 
   1574 void Assembler::movt(Register rd, Register rs, uint16_t cc) {
   1575   Register rt;
   1576   rt.code_ = (cc & 0x0007) << 2 | 1;
   1577   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
   1578 }
   1579 
   1580 
   1581 void Assembler::movf(Register rd, Register rs, uint16_t cc) {
   1582   Register rt;
   1583   rt.code_ = (cc & 0x0007) << 2 | 0;
   1584   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
   1585 }
   1586 
   1587 
   1588 // Bit twiddling.
   1589 void Assembler::clz(Register rd, Register rs) {
   1590   // Clz instr requires same GPR number in 'rd' and 'rt' fields.
   1591   GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
   1592 }
   1593 
   1594 
   1595 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
   1596   // Should be called via MacroAssembler::Ins.
   1597   // Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
   1598   ASSERT(kArchVariant == kMips32r2);
   1599   GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
   1600 }
   1601 
   1602 
   1603 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
   1604   // Should be called via MacroAssembler::Ext.
   1605   // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
   1606   ASSERT(kArchVariant == kMips32r2);
   1607   GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
   1608 }
   1609 
   1610 
   1611 void Assembler::pref(int32_t hint, const MemOperand& rs) {
   1612   ASSERT(kArchVariant != kLoongson);
   1613   ASSERT(is_uint5(hint) && is_uint16(rs.offset_));
   1614   Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift)
   1615       | (rs.offset_);
   1616   emit(instr);
   1617 }
   1618 
   1619 
   1620 // --------Coprocessor-instructions----------------
   1621 
   1622 // Load, store, move.
   1623 void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
   1624   GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
   1625 }
   1626 
   1627 
   1628 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
   1629   // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
   1630   // load to two 32-bit loads.
   1631   GenInstrImmediate(LWC1, src.rm(), fd, src.offset_ +
   1632       Register::kMantissaOffset);
   1633   FPURegister nextfpreg;
   1634   nextfpreg.setcode(fd.code() + 1);
   1635   GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ +
   1636       Register::kExponentOffset);
   1637 }
   1638 
   1639 
   1640 void Assembler::swc1(FPURegister fd, const MemOperand& src) {
   1641   GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
   1642 }
   1643 
   1644 
   1645 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
   1646   // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
   1647   // store to two 32-bit stores.
   1648   GenInstrImmediate(SWC1, src.rm(), fd, src.offset_ +
   1649       Register::kMantissaOffset);
   1650   FPURegister nextfpreg;
   1651   nextfpreg.setcode(fd.code() + 1);
   1652   GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ +
   1653       Register::kExponentOffset);
   1654 }
   1655 
   1656 
   1657 void Assembler::mtc1(Register rt, FPURegister fs) {
   1658   GenInstrRegister(COP1, MTC1, rt, fs, f0);
   1659 }
   1660 
   1661 
   1662 void Assembler::mfc1(Register rt, FPURegister fs) {
   1663   GenInstrRegister(COP1, MFC1, rt, fs, f0);
   1664 }
   1665 
   1666 
   1667 void Assembler::ctc1(Register rt, FPUControlRegister fs) {
   1668   GenInstrRegister(COP1, CTC1, rt, fs);
   1669 }
   1670 
   1671 
   1672 void Assembler::cfc1(Register rt, FPUControlRegister fs) {
   1673   GenInstrRegister(COP1, CFC1, rt, fs);
   1674 }
   1675 
   1676 
   1677 void Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
   1678   uint64_t i;
   1679   memcpy(&i, &d, 8);
   1680 
   1681   *lo = i & 0xffffffff;
   1682   *hi = i >> 32;
   1683 }
   1684 
   1685 
   1686 // Arithmetic.
   1687 
   1688 void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   1689   GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
   1690 }
   1691 
   1692 
   1693 void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   1694   GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
   1695 }
   1696 
   1697 
   1698 void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   1699   GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
   1700 }
   1701 
   1702 
   1703 void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
   1704     FPURegister ft) {
   1705   GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
   1706 }
   1707 
   1708 
   1709 void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   1710   GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
   1711 }
   1712 
   1713 
   1714 void Assembler::abs_d(FPURegister fd, FPURegister fs) {
   1715   GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
   1716 }
   1717 
   1718 
   1719 void Assembler::mov_d(FPURegister fd, FPURegister fs) {
   1720   GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
   1721 }
   1722 
   1723 
   1724 void Assembler::neg_d(FPURegister fd, FPURegister fs) {
   1725   GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
   1726 }
   1727 
   1728 
   1729 void Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
   1730   GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
   1731 }
   1732 
   1733 
   1734 // Conversions.
   1735 
   1736 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
   1737   GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
   1738 }
   1739 
   1740 
   1741 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
   1742   GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
   1743 }
   1744 
   1745 
   1746 void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
   1747   GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
   1748 }
   1749 
   1750 
   1751 void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
   1752   GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
   1753 }
   1754 
   1755 
   1756 void Assembler::round_w_s(FPURegister fd, FPURegister fs) {
   1757   GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
   1758 }
   1759 
   1760 
   1761 void Assembler::round_w_d(FPURegister fd, FPURegister fs) {
   1762   GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
   1763 }
   1764 
   1765 
   1766 void Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
   1767   GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
   1768 }
   1769 
   1770 
   1771 void Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
   1772   GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
   1773 }
   1774 
   1775 
   1776 void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
   1777   GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
   1778 }
   1779 
   1780 
   1781 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
   1782   GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
   1783 }
   1784 
   1785 
   1786 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
   1787   ASSERT(kArchVariant == kMips32r2);
   1788   GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
   1789 }
   1790 
   1791 
   1792 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
   1793   ASSERT(kArchVariant == kMips32r2);
   1794   GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
   1795 }
   1796 
   1797 
   1798 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
   1799   ASSERT(kArchVariant == kMips32r2);
   1800   GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
   1801 }
   1802 
   1803 
   1804 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
   1805   ASSERT(kArchVariant == kMips32r2);
   1806   GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
   1807 }
   1808 
   1809 
   1810 void Assembler::round_l_s(FPURegister fd, FPURegister fs) {
   1811   GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
   1812 }
   1813 
   1814 
   1815 void Assembler::round_l_d(FPURegister fd, FPURegister fs) {
   1816   GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
   1817 }
   1818 
   1819 
   1820 void Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
   1821   GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
   1822 }
   1823 
   1824 
   1825 void Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
   1826   GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
   1827 }
   1828 
   1829 
   1830 void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
   1831   GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
   1832 }
   1833 
   1834 
   1835 void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
   1836   GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
   1837 }
   1838 
   1839 
   1840 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
   1841   GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
   1842 }
   1843 
   1844 
   1845 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
   1846   ASSERT(kArchVariant == kMips32r2);
   1847   GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
   1848 }
   1849 
   1850 
   1851 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
   1852   GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
   1853 }
   1854 
   1855 
   1856 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
   1857   GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
   1858 }
   1859 
   1860 
   1861 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
   1862   ASSERT(kArchVariant == kMips32r2);
   1863   GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
   1864 }
   1865 
   1866 
   1867 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
   1868   GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
   1869 }
   1870 
   1871 
   1872 // Conditions.
   1873 void Assembler::c(FPUCondition cond, SecondaryField fmt,
   1874     FPURegister fs, FPURegister ft, uint16_t cc) {
   1875   ASSERT(is_uint3(cc));
   1876   ASSERT((fmt & ~(31 << kRsShift)) == 0);
   1877   Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
   1878       | cc << 8 | 3 << 4 | cond;
   1879   emit(instr);
   1880 }
   1881 
   1882 
   1883 void Assembler::fcmp(FPURegister src1, const double src2,
   1884       FPUCondition cond) {
   1885   ASSERT(src2 == 0.0);
   1886   mtc1(zero_reg, f14);
   1887   cvt_d_w(f14, f14);
   1888   c(cond, D, src1, f14, 0);
   1889 }
   1890 
   1891 
   1892 void Assembler::bc1f(int16_t offset, uint16_t cc) {
   1893   ASSERT(is_uint3(cc));
   1894   Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
   1895   emit(instr);
   1896 }
   1897 
   1898 
   1899 void Assembler::bc1t(int16_t offset, uint16_t cc) {
   1900   ASSERT(is_uint3(cc));
   1901   Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
   1902   emit(instr);
   1903 }
   1904 
   1905 
   1906 // Debugging.
   1907 void Assembler::RecordJSReturn() {
   1908   positions_recorder()->WriteRecordedPositions();
   1909   CheckBuffer();
   1910   RecordRelocInfo(RelocInfo::JS_RETURN);
   1911 }
   1912 
   1913 
   1914 void Assembler::RecordDebugBreakSlot() {
   1915   positions_recorder()->WriteRecordedPositions();
   1916   CheckBuffer();
   1917   RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
   1918 }
   1919 
   1920 
   1921 void Assembler::RecordComment(const char* msg) {
   1922   if (FLAG_code_comments) {
   1923     CheckBuffer();
   1924     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
   1925   }
   1926 }
   1927 
   1928 
   1929 int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) {
   1930   Instr instr = instr_at(pc);
   1931   ASSERT(IsJ(instr) || IsLui(instr));
   1932   if (IsLui(instr)) {
   1933     Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
   1934     Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
   1935     ASSERT(IsOri(instr_ori));
   1936     int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
   1937     imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
   1938     if (imm == kEndOfJumpChain) {
   1939       return 0;  // Number of instructions patched.
   1940     }
   1941     imm += pc_delta;
   1942     ASSERT((imm & 3) == 0);
   1943 
   1944     instr_lui &= ~kImm16Mask;
   1945     instr_ori &= ~kImm16Mask;
   1946 
   1947     instr_at_put(pc + 0 * Assembler::kInstrSize,
   1948                  instr_lui | ((imm >> kLuiShift) & kImm16Mask));
   1949     instr_at_put(pc + 1 * Assembler::kInstrSize,
   1950                  instr_ori | (imm & kImm16Mask));
   1951     return 2;  // Number of instructions patched.
   1952   } else {
   1953     uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
   1954     if (static_cast<int32_t>(imm28) == kEndOfJumpChain) {
   1955       return 0;  // Number of instructions patched.
   1956     }
   1957     imm28 += pc_delta;
   1958     imm28 &= kImm28Mask;
   1959     ASSERT((imm28 & 3) == 0);
   1960 
   1961     instr &= ~kImm26Mask;
   1962     uint32_t imm26 = imm28 >> 2;
   1963     ASSERT(is_uint26(imm26));
   1964 
   1965     instr_at_put(pc, instr | (imm26 & kImm26Mask));
   1966     return 1;  // Number of instructions patched.
   1967   }
   1968 }
   1969 
   1970 
   1971 void Assembler::GrowBuffer() {
   1972   if (!own_buffer_) FATAL("external code buffer is too small");
   1973 
   1974   // Compute new buffer size.
   1975   CodeDesc desc;  // The new buffer.
   1976   if (buffer_size_ < 4*KB) {
   1977     desc.buffer_size = 4*KB;
   1978   } else if (buffer_size_ < 1*MB) {
   1979     desc.buffer_size = 2*buffer_size_;
   1980   } else {
   1981     desc.buffer_size = buffer_size_ + 1*MB;
   1982   }
   1983   CHECK_GT(desc.buffer_size, 0);  // No overflow.
   1984 
   1985   // Set up new buffer.
   1986   desc.buffer = NewArray<byte>(desc.buffer_size);
   1987 
   1988   desc.instr_size = pc_offset();
   1989   desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
   1990 
   1991   // Copy the data.
   1992   int pc_delta = desc.buffer - buffer_;
   1993   int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
   1994   MemMove(desc.buffer, buffer_, desc.instr_size);
   1995   MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
   1996           desc.reloc_size);
   1997 
   1998   // Switch buffers.
   1999   DeleteArray(buffer_);
   2000   buffer_ = desc.buffer;
   2001   buffer_size_ = desc.buffer_size;
   2002   pc_ += pc_delta;
   2003   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
   2004                                reloc_info_writer.last_pc() + pc_delta);
   2005 
   2006   // Relocate runtime entries.
   2007   for (RelocIterator it(desc); !it.done(); it.next()) {
   2008     RelocInfo::Mode rmode = it.rinfo()->rmode();
   2009     if (rmode == RelocInfo::INTERNAL_REFERENCE) {
   2010       byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
   2011       RelocateInternalReference(p, pc_delta);
   2012     }
   2013   }
   2014 
   2015   ASSERT(!overflow());
   2016 }
   2017 
   2018 
   2019 void Assembler::db(uint8_t data) {
   2020   CheckBuffer();
   2021   *reinterpret_cast<uint8_t*>(pc_) = data;
   2022   pc_ += sizeof(uint8_t);
   2023 }
   2024 
   2025 
   2026 void Assembler::dd(uint32_t data) {
   2027   CheckBuffer();
   2028   *reinterpret_cast<uint32_t*>(pc_) = data;
   2029   pc_ += sizeof(uint32_t);
   2030 }
   2031 
   2032 
   2033 void Assembler::emit_code_stub_address(Code* stub) {
   2034   CheckBuffer();
   2035   *reinterpret_cast<uint32_t*>(pc_) =
   2036       reinterpret_cast<uint32_t>(stub->instruction_start());
   2037   pc_ += sizeof(uint32_t);
   2038 }
   2039 
   2040 
   2041 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
   2042   // We do not try to reuse pool constants.
   2043   RelocInfo rinfo(pc_, rmode, data, NULL);
   2044   if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
   2045     // Adjust code for new modes.
   2046     ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
   2047            || RelocInfo::IsJSReturn(rmode)
   2048            || RelocInfo::IsComment(rmode)
   2049            || RelocInfo::IsPosition(rmode));
   2050     // These modes do not need an entry in the constant pool.
   2051   }
   2052   if (!RelocInfo::IsNone(rinfo.rmode())) {
   2053     // Don't record external references unless the heap will be serialized.
   2054     if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
   2055         !serializer_enabled() && !emit_debug_code()) {
   2056       return;
   2057     }
   2058     ASSERT(buffer_space() >= kMaxRelocSize);  // Too late to grow buffer here.
   2059     if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
   2060       RelocInfo reloc_info_with_ast_id(pc_,
   2061                                        rmode,
   2062                                        RecordedAstId().ToInt(),
   2063                                        NULL);
   2064       ClearRecordedAstId();
   2065       reloc_info_writer.Write(&reloc_info_with_ast_id);
   2066     } else {
   2067       reloc_info_writer.Write(&rinfo);
   2068     }
   2069   }
   2070 }
   2071 
   2072 
   2073 void Assembler::BlockTrampolinePoolFor(int instructions) {
   2074   BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
   2075 }
   2076 
   2077 
   2078 void Assembler::CheckTrampolinePool() {
   2079   // Some small sequences of instructions must not be broken up by the
   2080   // insertion of a trampoline pool; such sequences are protected by setting
   2081   // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
   2082   // which are both checked here. Also, recursive calls to CheckTrampolinePool
   2083   // are blocked by trampoline_pool_blocked_nesting_.
   2084   if ((trampoline_pool_blocked_nesting_ > 0) ||
   2085       (pc_offset() < no_trampoline_pool_before_)) {
   2086     // Emission is currently blocked; make sure we try again as soon as
   2087     // possible.
   2088     if (trampoline_pool_blocked_nesting_ > 0) {
   2089       next_buffer_check_ = pc_offset() + kInstrSize;
   2090     } else {
   2091       next_buffer_check_ = no_trampoline_pool_before_;
   2092     }
   2093     return;
   2094   }
   2095 
   2096   ASSERT(!trampoline_emitted_);
   2097   ASSERT(unbound_labels_count_ >= 0);
   2098   if (unbound_labels_count_ > 0) {
   2099     // First we emit jump (2 instructions), then we emit trampoline pool.
   2100     { BlockTrampolinePoolScope block_trampoline_pool(this);
   2101       Label after_pool;
   2102       b(&after_pool);
   2103       nop();
   2104 
   2105       int pool_start = pc_offset();
   2106       for (int i = 0; i < unbound_labels_count_; i++) {
   2107         uint32_t imm32;
   2108         imm32 = jump_address(&after_pool);
   2109         { BlockGrowBufferScope block_buf_growth(this);
   2110           // Buffer growth (and relocation) must be blocked for internal
   2111           // references until associated instructions are emitted and available
   2112           // to be patched.
   2113           RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
   2114           lui(at, (imm32 & kHiMask) >> kLuiShift);
   2115           ori(at, at, (imm32 & kImm16Mask));
   2116         }
   2117         jr(at);
   2118         nop();
   2119       }
   2120       bind(&after_pool);
   2121       trampoline_ = Trampoline(pool_start, unbound_labels_count_);
   2122 
   2123       trampoline_emitted_ = true;
   2124       // As we are only going to emit trampoline once, we need to prevent any
   2125       // further emission.
   2126       next_buffer_check_ = kMaxInt;
   2127     }
   2128   } else {
   2129     // Number of branches to unbound label at this point is zero, so we can
   2130     // move next buffer check to maximum.
   2131     next_buffer_check_ = pc_offset() +
   2132         kMaxBranchOffset - kTrampolineSlotsSize * 16;
   2133   }
   2134   return;
   2135 }
   2136 
   2137 
   2138 Address Assembler::target_address_at(Address pc) {
   2139   Instr instr1 = instr_at(pc);
   2140   Instr instr2 = instr_at(pc + kInstrSize);
   2141   // Interpret 2 instructions generated by li: lui/ori
   2142   if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) {
   2143     // Assemble the 32 bit value.
   2144     return reinterpret_cast<Address>(
   2145         (GetImmediate16(instr1) << 16) | GetImmediate16(instr2));
   2146   }
   2147 
   2148   // We should never get here, force a bad address if we do.
   2149   UNREACHABLE();
   2150   return (Address)0x0;
   2151 }
   2152 
   2153 
   2154 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32
   2155 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap
   2156 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted.
   2157 // OS::nan_value() returns a qNaN.
   2158 void Assembler::QuietNaN(HeapObject* object) {
   2159   HeapNumber::cast(object)->set_value(OS::nan_value());
   2160 }
   2161 
   2162 
   2163 // On Mips, a target address is stored in a lui/ori instruction pair, each
   2164 // of which load 16 bits of the 32-bit address to a register.
   2165 // Patching the address must replace both instr, and flush the i-cache.
   2166 //
   2167 // There is an optimization below, which emits a nop when the address
   2168 // fits in just 16 bits. This is unlikely to help, and should be benchmarked,
   2169 // and possibly removed.
   2170 void Assembler::set_target_address_at(Address pc,
   2171                                       Address target,
   2172                                       ICacheFlushMode icache_flush_mode) {
   2173   Instr instr2 = instr_at(pc + kInstrSize);
   2174   uint32_t rt_code = GetRtField(instr2);
   2175   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
   2176   uint32_t itarget = reinterpret_cast<uint32_t>(target);
   2177 
   2178 #ifdef DEBUG
   2179   // Check we have the result from a li macro-instruction, using instr pair.
   2180   Instr instr1 = instr_at(pc);
   2181   CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI));
   2182 #endif
   2183 
   2184   // Must use 2 instructions to insure patchable code => just use lui and ori.
   2185   // lui rt, upper-16.
   2186   // ori rt rt, lower-16.
   2187   *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
   2188   *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
   2189 
   2190   // The following code is an optimization for the common case of Call()
   2191   // or Jump() which is load to register, and jump through register:
   2192   //     li(t9, address); jalr(t9)    (or jr(t9)).
   2193   // If the destination address is in the same 256 MB page as the call, it
   2194   // is faster to do a direct jal, or j, rather than jump thru register, since
   2195   // that lets the cpu pipeline prefetch the target address. However each
   2196   // time the address above is patched, we have to patch the direct jal/j
   2197   // instruction, as well as possibly revert to jalr/jr if we now cross a
   2198   // 256 MB page. Note that with the jal/j instructions, we do not need to
   2199   // load the register, but that code is left, since it makes it easy to
   2200   // revert this process. A further optimization could try replacing the
   2201   // li sequence with nops.
   2202   // This optimization can only be applied if the rt-code from instr2 is the
   2203   // register used for the jalr/jr. Finally, we have to skip 'jr ra', which is
   2204   // mips return. Occasionally this lands after an li().
   2205 
   2206   Instr instr3 = instr_at(pc + 2 * kInstrSize);
   2207   uint32_t ipc = reinterpret_cast<uint32_t>(pc + 3 * kInstrSize);
   2208   bool in_range = ((ipc ^ itarget) >> (kImm26Bits + kImmFieldShift)) == 0;
   2209   uint32_t target_field =
   2210       static_cast<uint32_t>(itarget & kJumpAddrMask) >> kImmFieldShift;
   2211   bool patched_jump = false;
   2212 
   2213 #ifndef ALLOW_JAL_IN_BOUNDARY_REGION
   2214   // This is a workaround to the 24k core E156 bug (affect some 34k cores also).
   2215   // Since the excluded space is only 64KB out of 256MB (0.02 %), we will just
   2216   // apply this workaround for all cores so we don't have to identify the core.
   2217   if (in_range) {
   2218     // The 24k core E156 bug has some very specific requirements, we only check
   2219     // the most simple one: if the address of the delay slot instruction is in
   2220     // the first or last 32 KB of the 256 MB segment.
   2221     uint32_t segment_mask = ((256 * MB) - 1) ^ ((32 * KB) - 1);
   2222     uint32_t ipc_segment_addr = ipc & segment_mask;
   2223     if (ipc_segment_addr == 0 || ipc_segment_addr == segment_mask)
   2224       in_range = false;
   2225   }
   2226 #endif
   2227 
   2228   if (IsJalr(instr3)) {
   2229     // Try to convert JALR to JAL.
   2230     if (in_range && GetRt(instr2) == GetRs(instr3)) {
   2231       *(p+2) = JAL | target_field;
   2232       patched_jump = true;
   2233     }
   2234   } else if (IsJr(instr3)) {
   2235     // Try to convert JR to J, skip returns (jr ra).
   2236     bool is_ret = static_cast<int>(GetRs(instr3)) == ra.code();
   2237     if (in_range && !is_ret && GetRt(instr2) == GetRs(instr3)) {
   2238       *(p+2) = J | target_field;
   2239       patched_jump = true;
   2240     }
   2241   } else if (IsJal(instr3)) {
   2242     if (in_range) {
   2243       // We are patching an already converted JAL.
   2244       *(p+2) = JAL | target_field;
   2245     } else {
   2246       // Patch JAL, but out of range, revert to JALR.
   2247       // JALR rs reg is the rt reg specified in the ORI instruction.
   2248       uint32_t rs_field = GetRt(instr2) << kRsShift;
   2249       uint32_t rd_field = ra.code() << kRdShift;  // Return-address (ra) reg.
   2250       *(p+2) = SPECIAL | rs_field | rd_field | JALR;
   2251     }
   2252     patched_jump = true;
   2253   } else if (IsJ(instr3)) {
   2254     if (in_range) {
   2255       // We are patching an already converted J (jump).
   2256       *(p+2) = J | target_field;
   2257     } else {
   2258       // Trying patch J, but out of range, just go back to JR.
   2259       // JR 'rs' reg is the 'rt' reg specified in the ORI instruction (instr2).
   2260       uint32_t rs_field = GetRt(instr2) << kRsShift;
   2261       *(p+2) = SPECIAL | rs_field | JR;
   2262     }
   2263     patched_jump = true;
   2264   }
   2265 
   2266   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
   2267     CPU::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t));
   2268   }
   2269 }
   2270 
   2271 
   2272 void Assembler::JumpLabelToJumpRegister(Address pc) {
   2273   // Address pc points to lui/ori instructions.
   2274   // Jump to label may follow at pc + 2 * kInstrSize.
   2275   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
   2276 #ifdef DEBUG
   2277   Instr instr1 = instr_at(pc);
   2278 #endif
   2279   Instr instr2 = instr_at(pc + 1 * kInstrSize);
   2280   Instr instr3 = instr_at(pc + 2 * kInstrSize);
   2281   bool patched = false;
   2282 
   2283   if (IsJal(instr3)) {
   2284     ASSERT(GetOpcodeField(instr1) == LUI);
   2285     ASSERT(GetOpcodeField(instr2) == ORI);
   2286 
   2287     uint32_t rs_field = GetRt(instr2) << kRsShift;
   2288     uint32_t rd_field = ra.code() << kRdShift;  // Return-address (ra) reg.
   2289     *(p+2) = SPECIAL | rs_field | rd_field | JALR;
   2290     patched = true;
   2291   } else if (IsJ(instr3)) {
   2292     ASSERT(GetOpcodeField(instr1) == LUI);
   2293     ASSERT(GetOpcodeField(instr2) == ORI);
   2294 
   2295     uint32_t rs_field = GetRt(instr2) << kRsShift;
   2296     *(p+2) = SPECIAL | rs_field | JR;
   2297     patched = true;
   2298   }
   2299 
   2300   if (patched) {
   2301       CPU::FlushICache(pc+2, sizeof(Address));
   2302   }
   2303 }
   2304 
   2305 
   2306 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
   2307   // No out-of-line constant pool support.
   2308   ASSERT(!FLAG_enable_ool_constant_pool);
   2309   return isolate->factory()->empty_constant_pool_array();
   2310 }
   2311 
   2312 
   2313 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
   2314   // No out-of-line constant pool support.
   2315   ASSERT(!FLAG_enable_ool_constant_pool);
   2316   return;
   2317 }
   2318 
   2319 
   2320 } }  // namespace v8::internal
   2321 
   2322 #endif  // V8_TARGET_ARCH_MIPS
   2323