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