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 2010 the V8 project authors. All rights reserved.
     34 
     35 
     36 #include "v8.h"
     37 #include "mips/assembler-mips-inl.h"
     38 #include "serialize.h"
     39 
     40 
     41 namespace v8 {
     42 namespace internal {
     43 
     44 
     45 
     46 const Register no_reg = { -1 };
     47 
     48 const Register zero_reg = { 0 };
     49 const Register at = { 1 };
     50 const Register v0 = { 2 };
     51 const Register v1 = { 3 };
     52 const Register a0 = { 4 };
     53 const Register a1 = { 5 };
     54 const Register a2 = { 6 };
     55 const Register a3 = { 7 };
     56 const Register t0 = { 8 };
     57 const Register t1 = { 9 };
     58 const Register t2 = { 10 };
     59 const Register t3 = { 11 };
     60 const Register t4 = { 12 };
     61 const Register t5 = { 13 };
     62 const Register t6 = { 14 };
     63 const Register t7 = { 15 };
     64 const Register s0 = { 16 };
     65 const Register s1 = { 17 };
     66 const Register s2 = { 18 };
     67 const Register s3 = { 19 };
     68 const Register s4 = { 20 };
     69 const Register s5 = { 21 };
     70 const Register s6 = { 22 };
     71 const Register s7 = { 23 };
     72 const Register t8 = { 24 };
     73 const Register t9 = { 25 };
     74 const Register k0 = { 26 };
     75 const Register k1 = { 27 };
     76 const Register gp = { 28 };
     77 const Register sp = { 29 };
     78 const Register s8_fp = { 30 };
     79 const Register ra = { 31 };
     80 
     81 
     82 const FPURegister no_creg = { -1 };
     83 
     84 const FPURegister f0 = { 0 };
     85 const FPURegister f1 = { 1 };
     86 const FPURegister f2 = { 2 };
     87 const FPURegister f3 = { 3 };
     88 const FPURegister f4 = { 4 };
     89 const FPURegister f5 = { 5 };
     90 const FPURegister f6 = { 6 };
     91 const FPURegister f7 = { 7 };
     92 const FPURegister f8 = { 8 };
     93 const FPURegister f9 = { 9 };
     94 const FPURegister f10 = { 10 };
     95 const FPURegister f11 = { 11 };
     96 const FPURegister f12 = { 12 };
     97 const FPURegister f13 = { 13 };
     98 const FPURegister f14 = { 14 };
     99 const FPURegister f15 = { 15 };
    100 const FPURegister f16 = { 16 };
    101 const FPURegister f17 = { 17 };
    102 const FPURegister f18 = { 18 };
    103 const FPURegister f19 = { 19 };
    104 const FPURegister f20 = { 20 };
    105 const FPURegister f21 = { 21 };
    106 const FPURegister f22 = { 22 };
    107 const FPURegister f23 = { 23 };
    108 const FPURegister f24 = { 24 };
    109 const FPURegister f25 = { 25 };
    110 const FPURegister f26 = { 26 };
    111 const FPURegister f27 = { 27 };
    112 const FPURegister f28 = { 28 };
    113 const FPURegister f29 = { 29 };
    114 const FPURegister f30 = { 30 };
    115 const FPURegister f31 = { 31 };
    116 
    117 int ToNumber(Register reg) {
    118   ASSERT(reg.is_valid());
    119   const int kNumbers[] = {
    120     0,    // zero_reg
    121     1,    // at
    122     2,    // v0
    123     3,    // v1
    124     4,    // a0
    125     5,    // a1
    126     6,    // a2
    127     7,    // a3
    128     8,    // t0
    129     9,    // t1
    130     10,   // t2
    131     11,   // t3
    132     12,   // t4
    133     13,   // t5
    134     14,   // t6
    135     15,   // t7
    136     16,   // s0
    137     17,   // s1
    138     18,   // s2
    139     19,   // s3
    140     20,   // s4
    141     21,   // s5
    142     22,   // s6
    143     23,   // s7
    144     24,   // t8
    145     25,   // t9
    146     26,   // k0
    147     27,   // k1
    148     28,   // gp
    149     29,   // sp
    150     30,   // s8_fp
    151     31,   // ra
    152   };
    153   return kNumbers[reg.code()];
    154 }
    155 
    156 Register ToRegister(int num) {
    157   ASSERT(num >= 0 && num < kNumRegisters);
    158   const Register kRegisters[] = {
    159     zero_reg,
    160     at,
    161     v0, v1,
    162     a0, a1, a2, a3,
    163     t0, t1, t2, t3, t4, t5, t6, t7,
    164     s0, s1, s2, s3, s4, s5, s6, s7,
    165     t8, t9,
    166     k0, k1,
    167     gp,
    168     sp,
    169     s8_fp,
    170     ra
    171   };
    172   return kRegisters[num];
    173 }
    174 
    175 
    176 // -----------------------------------------------------------------------------
    177 // Implementation of RelocInfo.
    178 
    179 const int RelocInfo::kApplyMask = 0;
    180 
    181 // Patch the code at the current address with the supplied instructions.
    182 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
    183   Instr* pc = reinterpret_cast<Instr*>(pc_);
    184   Instr* instr = reinterpret_cast<Instr*>(instructions);
    185   for (int i = 0; i < instruction_count; i++) {
    186     *(pc + i) = *(instr + i);
    187   }
    188 
    189   // Indicate that code has changed.
    190   CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
    191 }
    192 
    193 
    194 // Patch the code at the current PC with a call to the target address.
    195 // Additional guard instructions can be added if required.
    196 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
    197   // Patch the code at the current address with a call to the target.
    198   UNIMPLEMENTED_MIPS();
    199 }
    200 
    201 
    202 // -----------------------------------------------------------------------------
    203 // Implementation of Operand and MemOperand.
    204 // See assembler-mips-inl.h for inlined constructors.
    205 
    206 Operand::Operand(Handle<Object> handle) {
    207   rm_ = no_reg;
    208   // Verify all Objects referred by code are NOT in new space.
    209   Object* obj = *handle;
    210   ASSERT(!Heap::InNewSpace(obj));
    211   if (obj->IsHeapObject()) {
    212     imm32_ = reinterpret_cast<intptr_t>(handle.location());
    213     rmode_ = RelocInfo::EMBEDDED_OBJECT;
    214   } else {
    215     // No relocation needed.
    216     imm32_ = reinterpret_cast<intptr_t>(obj);
    217     rmode_ = RelocInfo::NONE;
    218   }
    219 }
    220 
    221 MemOperand::MemOperand(Register rm, int16_t offset) : Operand(rm) {
    222   offset_ = offset;
    223 }
    224 
    225 
    226 // -----------------------------------------------------------------------------
    227 // Implementation of Assembler.
    228 
    229 static const int kMinimalBufferSize = 4*KB;
    230 static byte* spare_buffer_ = NULL;
    231 
    232 Assembler::Assembler(void* buffer, int buffer_size) {
    233   if (buffer == NULL) {
    234     // Do our own buffer management.
    235     if (buffer_size <= kMinimalBufferSize) {
    236       buffer_size = kMinimalBufferSize;
    237 
    238       if (spare_buffer_ != NULL) {
    239         buffer = spare_buffer_;
    240         spare_buffer_ = NULL;
    241       }
    242     }
    243     if (buffer == NULL) {
    244       buffer_ = NewArray<byte>(buffer_size);
    245     } else {
    246       buffer_ = static_cast<byte*>(buffer);
    247     }
    248     buffer_size_ = buffer_size;
    249     own_buffer_ = true;
    250 
    251   } else {
    252     // Use externally provided buffer instead.
    253     ASSERT(buffer_size > 0);
    254     buffer_ = static_cast<byte*>(buffer);
    255     buffer_size_ = buffer_size;
    256     own_buffer_ = false;
    257   }
    258 
    259   // Setup buffer pointers.
    260   ASSERT(buffer_ != NULL);
    261   pc_ = buffer_;
    262   reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
    263   current_statement_position_ = RelocInfo::kNoPosition;
    264   current_position_ = RelocInfo::kNoPosition;
    265   written_statement_position_ = current_statement_position_;
    266   written_position_ = current_position_;
    267 }
    268 
    269 
    270 Assembler::~Assembler() {
    271   if (own_buffer_) {
    272     if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
    273       spare_buffer_ = buffer_;
    274     } else {
    275       DeleteArray(buffer_);
    276     }
    277   }
    278 }
    279 
    280 
    281 void Assembler::GetCode(CodeDesc* desc) {
    282   ASSERT(pc_ <= reloc_info_writer.pos());  // no overlap
    283   // Setup code descriptor.
    284   desc->buffer = buffer_;
    285   desc->buffer_size = buffer_size_;
    286   desc->instr_size = pc_offset();
    287   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
    288 }
    289 
    290 
    291 // Labels refer to positions in the (to be) generated code.
    292 // There are bound, linked, and unused labels.
    293 //
    294 // Bound labels refer to known positions in the already
    295 // generated code. pos() is the position the label refers to.
    296 //
    297 // Linked labels refer to unknown positions in the code
    298 // to be generated; pos() is the position of the last
    299 // instruction using the label.
    300 
    301 
    302 // The link chain is terminated by a negative code position (must be aligned).
    303 const int kEndOfChain = -4;
    304 
    305 bool Assembler::is_branch(Instr instr) {
    306   uint32_t opcode   = ((instr & kOpcodeMask));
    307   uint32_t rt_field = ((instr & kRtFieldMask));
    308   uint32_t rs_field = ((instr & kRsFieldMask));
    309   // Checks if the instruction is a branch.
    310   return opcode == BEQ ||
    311       opcode == BNE ||
    312       opcode == BLEZ ||
    313       opcode == BGTZ ||
    314       opcode == BEQL ||
    315       opcode == BNEL ||
    316       opcode == BLEZL ||
    317       opcode == BGTZL||
    318       (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
    319                             rt_field == BLTZAL || rt_field == BGEZAL)) ||
    320       (opcode == COP1 && rs_field == BC1);  // Coprocessor branch.
    321 }
    322 
    323 
    324 int Assembler::target_at(int32_t pos) {
    325   Instr instr = instr_at(pos);
    326   if ((instr & ~kImm16Mask) == 0) {
    327     // Emitted label constant, not part of a branch.
    328     return instr - (Code::kHeaderSize - kHeapObjectTag);
    329   }
    330   // Check we have a branch instruction.
    331   ASSERT(is_branch(instr));
    332   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
    333   // the compiler uses arithmectic shifts for signed integers.
    334   int32_t imm18 = ((instr &
    335                     static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
    336 
    337   return pos + kBranchPCOffset + imm18;
    338 }
    339 
    340 
    341 void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
    342   Instr instr = instr_at(pos);
    343   if ((instr & ~kImm16Mask) == 0) {
    344     ASSERT(target_pos == kEndOfChain || target_pos >= 0);
    345     // Emitted label constant, not part of a branch.
    346     // Make label relative to Code* of generated Code object.
    347     instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
    348     return;
    349   }
    350 
    351   ASSERT(is_branch(instr));
    352   int32_t imm18 = target_pos - (pos + kBranchPCOffset);
    353   ASSERT((imm18 & 3) == 0);
    354 
    355   instr &= ~kImm16Mask;
    356   int32_t imm16 = imm18 >> 2;
    357   ASSERT(is_int16(imm16));
    358 
    359   instr_at_put(pos, instr | (imm16 & kImm16Mask));
    360 }
    361 
    362 
    363 void Assembler::print(Label* L) {
    364   if (L->is_unused()) {
    365     PrintF("unused label\n");
    366   } else if (L->is_bound()) {
    367     PrintF("bound label to %d\n", L->pos());
    368   } else if (L->is_linked()) {
    369     Label l = *L;
    370     PrintF("unbound label");
    371     while (l.is_linked()) {
    372       PrintF("@ %d ", l.pos());
    373       Instr instr = instr_at(l.pos());
    374       if ((instr & ~kImm16Mask) == 0) {
    375         PrintF("value\n");
    376       } else {
    377         PrintF("%d\n", instr);
    378       }
    379       next(&l);
    380     }
    381   } else {
    382     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
    383   }
    384 }
    385 
    386 
    387 void Assembler::bind_to(Label* L, int pos) {
    388   ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
    389   while (L->is_linked()) {
    390     int32_t fixup_pos = L->pos();
    391     next(L);  // call next before overwriting link with target at fixup_pos
    392     target_at_put(fixup_pos, pos);
    393   }
    394   L->bind_to(pos);
    395 
    396   // Keep track of the last bound label so we don't eliminate any instructions
    397   // before a bound label.
    398   if (pos > last_bound_pos_)
    399     last_bound_pos_ = pos;
    400 }
    401 
    402 
    403 void Assembler::link_to(Label* L, Label* appendix) {
    404   if (appendix->is_linked()) {
    405     if (L->is_linked()) {
    406       // Append appendix to L's list.
    407       int fixup_pos;
    408       int link = L->pos();
    409       do {
    410         fixup_pos = link;
    411         link = target_at(fixup_pos);
    412       } while (link > 0);
    413       ASSERT(link == kEndOfChain);
    414       target_at_put(fixup_pos, appendix->pos());
    415     } else {
    416       // L is empty, simply use appendix
    417       *L = *appendix;
    418     }
    419   }
    420   appendix->Unuse();  // appendix should not be used anymore
    421 }
    422 
    423 
    424 void Assembler::bind(Label* L) {
    425   ASSERT(!L->is_bound());  // label can only be bound once
    426   bind_to(L, pc_offset());
    427 }
    428 
    429 
    430 void Assembler::next(Label* L) {
    431   ASSERT(L->is_linked());
    432   int link = target_at(L->pos());
    433   if (link > 0) {
    434     L->link_to(link);
    435   } else {
    436     ASSERT(link == kEndOfChain);
    437     L->Unuse();
    438   }
    439 }
    440 
    441 
    442 // We have to use a temporary register for things that can be relocated even
    443 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
    444 // space.  There is no guarantee that the relocated location can be similarly
    445 // encoded.
    446 bool Assembler::MustUseAt(RelocInfo::Mode rmode) {
    447   if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
    448     return Serializer::enabled();
    449   } else if (rmode == RelocInfo::NONE) {
    450     return false;
    451   }
    452   return true;
    453 }
    454 
    455 
    456 void Assembler::GenInstrRegister(Opcode opcode,
    457                                  Register rs,
    458                                  Register rt,
    459                                  Register rd,
    460                                  uint16_t sa,
    461                                  SecondaryField func) {
    462   ASSERT(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
    463   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
    464       | (rd.code() << kRdShift) | (sa << kSaShift) | func;
    465   emit(instr);
    466 }
    467 
    468 
    469 void Assembler::GenInstrRegister(Opcode opcode,
    470                                  SecondaryField fmt,
    471                                  FPURegister ft,
    472                                  FPURegister fs,
    473                                  FPURegister fd,
    474                                  SecondaryField func) {
    475   ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
    476   Instr instr = opcode | fmt | (ft.code() << 16) | (fs.code() << kFsShift)
    477       | (fd.code() << 6) | func;
    478   emit(instr);
    479 }
    480 
    481 
    482 void Assembler::GenInstrRegister(Opcode opcode,
    483                                  SecondaryField fmt,
    484                                  Register rt,
    485                                  FPURegister fs,
    486                                  FPURegister fd,
    487                                  SecondaryField func) {
    488   ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
    489   Instr instr = opcode | fmt | (rt.code() << kRtShift)
    490       | (fs.code() << kFsShift) | (fd.code() << 6) | func;
    491   emit(instr);
    492 }
    493 
    494 
    495 // Instructions with immediate value.
    496 // Registers are in the order of the instruction encoding, from left to right.
    497 void Assembler::GenInstrImmediate(Opcode opcode,
    498                                   Register rs,
    499                                   Register rt,
    500                                   int32_t j) {
    501   ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
    502   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
    503       | (j & kImm16Mask);
    504   emit(instr);
    505 }
    506 
    507 
    508 void Assembler::GenInstrImmediate(Opcode opcode,
    509                                   Register rs,
    510                                   SecondaryField SF,
    511                                   int32_t j) {
    512   ASSERT(rs.is_valid() && (is_int16(j) || is_uint16(j)));
    513   Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
    514   emit(instr);
    515 }
    516 
    517 
    518 void Assembler::GenInstrImmediate(Opcode opcode,
    519                                   Register rs,
    520                                   FPURegister ft,
    521                                   int32_t j) {
    522   ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
    523   Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
    524       | (j & kImm16Mask);
    525   emit(instr);
    526 }
    527 
    528 
    529 // Registers are in the order of the instruction encoding, from left to right.
    530 void Assembler::GenInstrJump(Opcode opcode,
    531                               uint32_t address) {
    532   ASSERT(is_uint26(address));
    533   Instr instr = opcode | address;
    534   emit(instr);
    535 }
    536 
    537 
    538 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
    539   int32_t target_pos;
    540   if (L->is_bound()) {
    541     target_pos = L->pos();
    542   } else {
    543     if (L->is_linked()) {
    544       target_pos = L->pos();  // L's link
    545     } else {
    546       target_pos = kEndOfChain;
    547     }
    548     L->link_to(pc_offset());
    549   }
    550 
    551   int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
    552   return offset;
    553 }
    554 
    555 
    556 void Assembler::label_at_put(Label* L, int at_offset) {
    557   int target_pos;
    558   if (L->is_bound()) {
    559     target_pos = L->pos();
    560   } else {
    561     if (L->is_linked()) {
    562       target_pos = L->pos();  // L's link
    563     } else {
    564       target_pos = kEndOfChain;
    565     }
    566     L->link_to(at_offset);
    567     instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
    568   }
    569 }
    570 
    571 
    572 //------- Branch and jump instructions --------
    573 
    574 void Assembler::b(int16_t offset) {
    575   beq(zero_reg, zero_reg, offset);
    576 }
    577 
    578 
    579 void Assembler::bal(int16_t offset) {
    580   bgezal(zero_reg, offset);
    581 }
    582 
    583 
    584 void Assembler::beq(Register rs, Register rt, int16_t offset) {
    585   GenInstrImmediate(BEQ, rs, rt, offset);
    586 }
    587 
    588 
    589 void Assembler::bgez(Register rs, int16_t offset) {
    590   GenInstrImmediate(REGIMM, rs, BGEZ, offset);
    591 }
    592 
    593 
    594 void Assembler::bgezal(Register rs, int16_t offset) {
    595   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
    596 }
    597 
    598 
    599 void Assembler::bgtz(Register rs, int16_t offset) {
    600   GenInstrImmediate(BGTZ, rs, zero_reg, offset);
    601 }
    602 
    603 
    604 void Assembler::blez(Register rs, int16_t offset) {
    605   GenInstrImmediate(BLEZ, rs, zero_reg, offset);
    606 }
    607 
    608 
    609 void Assembler::bltz(Register rs, int16_t offset) {
    610   GenInstrImmediate(REGIMM, rs, BLTZ, offset);
    611 }
    612 
    613 
    614 void Assembler::bltzal(Register rs, int16_t offset) {
    615   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
    616 }
    617 
    618 
    619 void Assembler::bne(Register rs, Register rt, int16_t offset) {
    620   GenInstrImmediate(BNE, rs, rt, offset);
    621 }
    622 
    623 
    624 void Assembler::j(int32_t target) {
    625   ASSERT(is_uint28(target) && ((target & 3) == 0));
    626   GenInstrJump(J, target >> 2);
    627 }
    628 
    629 
    630 void Assembler::jr(Register rs) {
    631   GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
    632 }
    633 
    634 
    635 void Assembler::jal(int32_t target) {
    636   ASSERT(is_uint28(target) && ((target & 3) == 0));
    637   GenInstrJump(JAL, target >> 2);
    638 }
    639 
    640 
    641 void Assembler::jalr(Register rs, Register rd) {
    642   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
    643 }
    644 
    645 
    646 //-------Data-processing-instructions---------
    647 
    648 // Arithmetic.
    649 
    650 void Assembler::add(Register rd, Register rs, Register rt) {
    651   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADD);
    652 }
    653 
    654 
    655 void Assembler::addu(Register rd, Register rs, Register rt) {
    656   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
    657 }
    658 
    659 
    660 void Assembler::addi(Register rd, Register rs, int32_t j) {
    661   GenInstrImmediate(ADDI, rs, rd, j);
    662 }
    663 
    664 
    665 void Assembler::addiu(Register rd, Register rs, int32_t j) {
    666   GenInstrImmediate(ADDIU, rs, rd, j);
    667 }
    668 
    669 
    670 void Assembler::sub(Register rd, Register rs, Register rt) {
    671   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUB);
    672 }
    673 
    674 
    675 void Assembler::subu(Register rd, Register rs, Register rt) {
    676   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
    677 }
    678 
    679 
    680 void Assembler::mul(Register rd, Register rs, Register rt) {
    681   GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
    682 }
    683 
    684 
    685 void Assembler::mult(Register rs, Register rt) {
    686   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
    687 }
    688 
    689 
    690 void Assembler::multu(Register rs, Register rt) {
    691   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
    692 }
    693 
    694 
    695 void Assembler::div(Register rs, Register rt) {
    696   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
    697 }
    698 
    699 
    700 void Assembler::divu(Register rs, Register rt) {
    701   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
    702 }
    703 
    704 
    705 // Logical.
    706 
    707 void Assembler::and_(Register rd, Register rs, Register rt) {
    708   GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
    709 }
    710 
    711 
    712 void Assembler::andi(Register rt, Register rs, int32_t j) {
    713   GenInstrImmediate(ANDI, rs, rt, j);
    714 }
    715 
    716 
    717 void Assembler::or_(Register rd, Register rs, Register rt) {
    718   GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
    719 }
    720 
    721 
    722 void Assembler::ori(Register rt, Register rs, int32_t j) {
    723   GenInstrImmediate(ORI, rs, rt, j);
    724 }
    725 
    726 
    727 void Assembler::xor_(Register rd, Register rs, Register rt) {
    728   GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
    729 }
    730 
    731 
    732 void Assembler::xori(Register rt, Register rs, int32_t j) {
    733   GenInstrImmediate(XORI, rs, rt, j);
    734 }
    735 
    736 
    737 void Assembler::nor(Register rd, Register rs, Register rt) {
    738   GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
    739 }
    740 
    741 
    742 // Shifts.
    743 void Assembler::sll(Register rd, Register rt, uint16_t sa) {
    744   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL);
    745 }
    746 
    747 
    748 void Assembler::sllv(Register rd, Register rt, Register rs) {
    749   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
    750 }
    751 
    752 
    753 void Assembler::srl(Register rd, Register rt, uint16_t sa) {
    754   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL);
    755 }
    756 
    757 
    758 void Assembler::srlv(Register rd, Register rt, Register rs) {
    759   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
    760 }
    761 
    762 
    763 void Assembler::sra(Register rd, Register rt, uint16_t sa) {
    764   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA);
    765 }
    766 
    767 
    768 void Assembler::srav(Register rd, Register rt, Register rs) {
    769   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
    770 }
    771 
    772 
    773 //------------Memory-instructions-------------
    774 
    775 void Assembler::lb(Register rd, const MemOperand& rs) {
    776   GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
    777 }
    778 
    779 
    780 void Assembler::lbu(Register rd, const MemOperand& rs) {
    781   GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
    782 }
    783 
    784 
    785 void Assembler::lw(Register rd, const MemOperand& rs) {
    786   GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
    787 }
    788 
    789 
    790 void Assembler::sb(Register rd, const MemOperand& rs) {
    791   GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
    792 }
    793 
    794 
    795 void Assembler::sw(Register rd, const MemOperand& rs) {
    796   GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
    797 }
    798 
    799 
    800 void Assembler::lui(Register rd, int32_t j) {
    801   GenInstrImmediate(LUI, zero_reg, rd, j);
    802 }
    803 
    804 
    805 //-------------Misc-instructions--------------
    806 
    807 // Break / Trap instructions.
    808 void Assembler::break_(uint32_t code) {
    809   ASSERT((code & ~0xfffff) == 0);
    810   Instr break_instr = SPECIAL | BREAK | (code << 6);
    811   emit(break_instr);
    812 }
    813 
    814 
    815 void Assembler::tge(Register rs, Register rt, uint16_t code) {
    816   ASSERT(is_uint10(code));
    817   Instr instr = SPECIAL | TGE | rs.code() << kRsShift
    818       | rt.code() << kRtShift | code << 6;
    819   emit(instr);
    820 }
    821 
    822 
    823 void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
    824   ASSERT(is_uint10(code));
    825   Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
    826       | rt.code() << kRtShift | code << 6;
    827   emit(instr);
    828 }
    829 
    830 
    831 void Assembler::tlt(Register rs, Register rt, uint16_t code) {
    832   ASSERT(is_uint10(code));
    833   Instr instr =
    834       SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
    835   emit(instr);
    836 }
    837 
    838 
    839 void Assembler::tltu(Register rs, Register rt, uint16_t code) {
    840   ASSERT(is_uint10(code));
    841   Instr instr = SPECIAL | TLTU | rs.code() << kRsShift
    842       | rt.code() << kRtShift | code << 6;
    843   emit(instr);
    844 }
    845 
    846 
    847 void Assembler::teq(Register rs, Register rt, uint16_t code) {
    848   ASSERT(is_uint10(code));
    849   Instr instr =
    850       SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
    851   emit(instr);
    852 }
    853 
    854 
    855 void Assembler::tne(Register rs, Register rt, uint16_t code) {
    856   ASSERT(is_uint10(code));
    857   Instr instr =
    858       SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
    859   emit(instr);
    860 }
    861 
    862 
    863 // Move from HI/LO register.
    864 
    865 void Assembler::mfhi(Register rd) {
    866   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
    867 }
    868 
    869 
    870 void Assembler::mflo(Register rd) {
    871   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
    872 }
    873 
    874 
    875 // Set on less than instructions.
    876 void Assembler::slt(Register rd, Register rs, Register rt) {
    877   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
    878 }
    879 
    880 
    881 void Assembler::sltu(Register rd, Register rs, Register rt) {
    882   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
    883 }
    884 
    885 
    886 void Assembler::slti(Register rt, Register rs, int32_t j) {
    887   GenInstrImmediate(SLTI, rs, rt, j);
    888 }
    889 
    890 
    891 void Assembler::sltiu(Register rt, Register rs, int32_t j) {
    892   GenInstrImmediate(SLTIU, rs, rt, j);
    893 }
    894 
    895 
    896 //--------Coprocessor-instructions----------------
    897 
    898 // Load, store, move.
    899 void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
    900   GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
    901 }
    902 
    903 
    904 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
    905   GenInstrImmediate(LDC1, src.rm(), fd, src.offset_);
    906 }
    907 
    908 
    909 void Assembler::swc1(FPURegister fd, const MemOperand& src) {
    910   GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
    911 }
    912 
    913 
    914 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
    915   GenInstrImmediate(SDC1, src.rm(), fd, src.offset_);
    916 }
    917 
    918 
    919 void Assembler::mtc1(FPURegister fs, Register rt) {
    920   GenInstrRegister(COP1, MTC1, rt, fs, f0);
    921 }
    922 
    923 
    924 void Assembler::mthc1(FPURegister fs, Register rt) {
    925   GenInstrRegister(COP1, MTHC1, rt, fs, f0);
    926 }
    927 
    928 
    929 void Assembler::mfc1(FPURegister fs, Register rt) {
    930   GenInstrRegister(COP1, MFC1, rt, fs, f0);
    931 }
    932 
    933 
    934 void Assembler::mfhc1(FPURegister fs, Register rt) {
    935   GenInstrRegister(COP1, MFHC1, rt, fs, f0);
    936 }
    937 
    938 
    939 // Conversions.
    940 
    941 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
    942   GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
    943 }
    944 
    945 
    946 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
    947   GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
    948 }
    949 
    950 
    951 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
    952   GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
    953 }
    954 
    955 
    956 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
    957   GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
    958 }
    959 
    960 
    961 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
    962   GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
    963 }
    964 
    965 
    966 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
    967   GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
    968 }
    969 
    970 
    971 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
    972   GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
    973 }
    974 
    975 
    976 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
    977   GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
    978 }
    979 
    980 
    981 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
    982   GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
    983 }
    984 
    985 
    986 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
    987   GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
    988 }
    989 
    990 
    991 // Conditions.
    992 void Assembler::c(FPUCondition cond, SecondaryField fmt,
    993     FPURegister ft, FPURegister fs, uint16_t cc) {
    994   ASSERT(is_uint3(cc));
    995   ASSERT((fmt & ~(31 << kRsShift)) == 0);
    996   Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
    997       | cc << 8 | 3 << 4 | cond;
    998   emit(instr);
    999 }
   1000 
   1001 
   1002 void Assembler::bc1f(int16_t offset, uint16_t cc) {
   1003   ASSERT(is_uint3(cc));
   1004   Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
   1005   emit(instr);
   1006 }
   1007 
   1008 
   1009 void Assembler::bc1t(int16_t offset, uint16_t cc) {
   1010   ASSERT(is_uint3(cc));
   1011   Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
   1012   emit(instr);
   1013 }
   1014 
   1015 
   1016 // Debugging.
   1017 void Assembler::RecordJSReturn() {
   1018   WriteRecordedPositions();
   1019   CheckBuffer();
   1020   RecordRelocInfo(RelocInfo::JS_RETURN);
   1021 }
   1022 
   1023 
   1024 void Assembler::RecordComment(const char* msg) {
   1025   if (FLAG_debug_code) {
   1026     CheckBuffer();
   1027     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
   1028   }
   1029 }
   1030 
   1031 
   1032 void Assembler::RecordPosition(int pos) {
   1033   if (pos == RelocInfo::kNoPosition) return;
   1034   ASSERT(pos >= 0);
   1035   current_position_ = pos;
   1036 }
   1037 
   1038 
   1039 void Assembler::RecordStatementPosition(int pos) {
   1040   if (pos == RelocInfo::kNoPosition) return;
   1041   ASSERT(pos >= 0);
   1042   current_statement_position_ = pos;
   1043 }
   1044 
   1045 
   1046 void Assembler::WriteRecordedPositions() {
   1047   // Write the statement position if it is different from what was written last
   1048   // time.
   1049   if (current_statement_position_ != written_statement_position_) {
   1050     CheckBuffer();
   1051     RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
   1052     written_statement_position_ = current_statement_position_;
   1053   }
   1054 
   1055   // Write the position if it is different from what was written last time and
   1056   // also different from the written statement position.
   1057   if (current_position_ != written_position_ &&
   1058       current_position_ != written_statement_position_) {
   1059     CheckBuffer();
   1060     RecordRelocInfo(RelocInfo::POSITION, current_position_);
   1061     written_position_ = current_position_;
   1062   }
   1063 }
   1064 
   1065 
   1066 void Assembler::GrowBuffer() {
   1067   if (!own_buffer_) FATAL("external code buffer is too small");
   1068 
   1069   // Compute new buffer size.
   1070   CodeDesc desc;  // the new buffer
   1071   if (buffer_size_ < 4*KB) {
   1072     desc.buffer_size = 4*KB;
   1073   } else if (buffer_size_ < 1*MB) {
   1074     desc.buffer_size = 2*buffer_size_;
   1075   } else {
   1076     desc.buffer_size = buffer_size_ + 1*MB;
   1077   }
   1078   CHECK_GT(desc.buffer_size, 0);  // no overflow
   1079 
   1080   // Setup new buffer.
   1081   desc.buffer = NewArray<byte>(desc.buffer_size);
   1082 
   1083   desc.instr_size = pc_offset();
   1084   desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
   1085 
   1086   // Copy the data.
   1087   int pc_delta = desc.buffer - buffer_;
   1088   int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
   1089   memmove(desc.buffer, buffer_, desc.instr_size);
   1090   memmove(reloc_info_writer.pos() + rc_delta,
   1091           reloc_info_writer.pos(), desc.reloc_size);
   1092 
   1093   // Switch buffers.
   1094   DeleteArray(buffer_);
   1095   buffer_ = desc.buffer;
   1096   buffer_size_ = desc.buffer_size;
   1097   pc_ += pc_delta;
   1098   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
   1099                                reloc_info_writer.last_pc() + pc_delta);
   1100 
   1101 
   1102   // On ia32 and ARM pc relative addressing is used, and we thus need to apply a
   1103   // shift by pc_delta. But on MIPS the target address it directly loaded, so
   1104   // we do not need to relocate here.
   1105 
   1106   ASSERT(!overflow());
   1107 }
   1108 
   1109 
   1110 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
   1111   RelocInfo rinfo(pc_, rmode, data);  // we do not try to reuse pool constants
   1112   if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) {
   1113     // Adjust code for new modes.
   1114     ASSERT(RelocInfo::IsJSReturn(rmode)
   1115            || RelocInfo::IsComment(rmode)
   1116            || RelocInfo::IsPosition(rmode));
   1117     // These modes do not need an entry in the constant pool.
   1118   }
   1119   if (rinfo.rmode() != RelocInfo::NONE) {
   1120     // Don't record external references unless the heap will be serialized.
   1121     if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
   1122         !Serializer::enabled() &&
   1123         !FLAG_debug_code) {
   1124       return;
   1125     }
   1126     ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
   1127     reloc_info_writer.Write(&rinfo);
   1128   }
   1129 }
   1130 
   1131 
   1132 Address Assembler::target_address_at(Address pc) {
   1133   Instr instr1 = instr_at(pc);
   1134   Instr instr2 = instr_at(pc + kInstrSize);
   1135   // Check we have 2 instructions generated by li.
   1136   ASSERT(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
   1137          ((instr1 == nopInstr) && ((instr2 & kOpcodeMask) == ADDI ||
   1138                             (instr2 & kOpcodeMask) == ORI ||
   1139                             (instr2 & kOpcodeMask) == LUI)));
   1140   // Interpret these 2 instructions.
   1141   if (instr1 == nopInstr) {
   1142     if ((instr2 & kOpcodeMask) == ADDI) {
   1143       return reinterpret_cast<Address>(((instr2 & kImm16Mask) << 16) >> 16);
   1144     } else if ((instr2 & kOpcodeMask) == ORI) {
   1145       return reinterpret_cast<Address>(instr2 & kImm16Mask);
   1146     } else if ((instr2 & kOpcodeMask) == LUI) {
   1147       return reinterpret_cast<Address>((instr2 & kImm16Mask) << 16);
   1148     }
   1149   } else if ((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) {
   1150     // 32 bits value.
   1151     return reinterpret_cast<Address>(
   1152         (instr1 & kImm16Mask) << 16 | (instr2 & kImm16Mask));
   1153   }
   1154 
   1155   // We should never get here.
   1156   UNREACHABLE();
   1157   return (Address)0x0;
   1158 }
   1159 
   1160 
   1161 void Assembler::set_target_address_at(Address pc, Address target) {
   1162   // On MIPS we need to patch the code to generate.
   1163 
   1164   // First check we have a li.
   1165   Instr instr2 = instr_at(pc + kInstrSize);
   1166 #ifdef DEBUG
   1167   Instr instr1 = instr_at(pc);
   1168 
   1169   // Check we have indeed the result from a li with MustUseAt true.
   1170   CHECK(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
   1171         ((instr1 == 0) && ((instr2 & kOpcodeMask)== ADDIU ||
   1172                            (instr2 & kOpcodeMask)== ORI ||
   1173                            (instr2 & kOpcodeMask)== LUI)));
   1174 #endif
   1175 
   1176 
   1177   uint32_t rt_code = (instr2 & kRtFieldMask);
   1178   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
   1179   uint32_t itarget = reinterpret_cast<uint32_t>(target);
   1180 
   1181   if (is_int16(itarget)) {
   1182     // nop
   1183     // addiu rt zero_reg j
   1184     *p = nopInstr;
   1185     *(p+1) = ADDIU | rt_code | (itarget & LOMask);
   1186   } else if (!(itarget & HIMask)) {
   1187     // nop
   1188     // ori rt zero_reg j
   1189     *p = nopInstr;
   1190     *(p+1) = ORI | rt_code | (itarget & LOMask);
   1191   } else if (!(itarget & LOMask)) {
   1192     // nop
   1193     // lui rt (HIMask & itarget)>>16
   1194     *p = nopInstr;
   1195     *(p+1) = LUI | rt_code | ((itarget & HIMask)>>16);
   1196   } else {
   1197     // lui rt (HIMask & itarget)>>16
   1198     // ori rt rt, (LOMask & itarget)
   1199     *p = LUI | rt_code | ((itarget & HIMask)>>16);
   1200     *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & LOMask);
   1201   }
   1202 
   1203   CPU::FlushICache(pc, 2 * sizeof(int32_t));
   1204 }
   1205 
   1206 
   1207 } }  // namespace v8::internal
   1208 
   1209