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 #ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_
     37 #define V8_MIPS_ASSEMBLER_MIPS_INL_H_
     38 
     39 #include "mips/assembler-mips.h"
     40 #include "cpu.h"
     41 #include "debug.h"
     42 
     43 
     44 namespace v8 {
     45 namespace internal {
     46 
     47 // -----------------------------------------------------------------------------
     48 // Operand and MemOperand
     49 
     50 Operand::Operand(int32_t immediate, RelocInfo::Mode rmode)  {
     51   rm_ = no_reg;
     52   imm32_ = immediate;
     53   rmode_ = rmode;
     54 }
     55 
     56 
     57 Operand::Operand(const ExternalReference& f)  {
     58   rm_ = no_reg;
     59   imm32_ = reinterpret_cast<int32_t>(f.address());
     60   rmode_ = RelocInfo::EXTERNAL_REFERENCE;
     61 }
     62 
     63 
     64 Operand::Operand(Smi* value) {
     65   rm_ = no_reg;
     66   imm32_ =  reinterpret_cast<intptr_t>(value);
     67   rmode_ = RelocInfo::NONE;
     68 }
     69 
     70 
     71 Operand::Operand(Register rm) {
     72   rm_ = rm;
     73 }
     74 
     75 
     76 bool Operand::is_reg() const {
     77   return rm_.is_valid();
     78 }
     79 
     80 
     81 
     82 // -----------------------------------------------------------------------------
     83 // RelocInfo
     84 
     85 void RelocInfo::apply(intptr_t delta) {
     86   // On MIPS we do not use pc relative addressing, so we don't need to patch the
     87   // code here.
     88 }
     89 
     90 
     91 Address RelocInfo::target_address() {
     92   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
     93   return Assembler::target_address_at(pc_);
     94 }
     95 
     96 
     97 Address RelocInfo::target_address_address() {
     98   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
     99                               || rmode_ == EMBEDDED_OBJECT
    100                               || rmode_ == EXTERNAL_REFERENCE);
    101   // Read the address of the word containing the target_address in an
    102   // instruction stream.
    103   // The only architecture-independent user of this function is the serializer.
    104   // The serializer uses it to find out how many raw bytes of instruction to
    105   // output before the next target.
    106   // For an instructions like LUI/ORI where the target bits are mixed into the
    107   // instruction bits, the size of the target will be zero, indicating that the
    108   // serializer should not step forward in memory after a target is resolved
    109   // and written.  In this case the target_address_address function should
    110   // return the end of the instructions to be patched, allowing the
    111   // deserializer to deserialize the instructions as raw bytes and put them in
    112   // place, ready to be patched with the target. In our case, that is the
    113   // address of the instruction that follows LUI/ORI instruction pair.
    114   return reinterpret_cast<Address>(
    115     pc_ + Assembler::kInstructionsFor32BitConstant * Assembler::kInstrSize);
    116 }
    117 
    118 
    119 int RelocInfo::target_address_size() {
    120   return Assembler::kExternalTargetSize;
    121 }
    122 
    123 
    124 void RelocInfo::set_target_address(Address target) {
    125   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
    126   Assembler::set_target_address_at(pc_, target);
    127 }
    128 
    129 
    130 Object* RelocInfo::target_object() {
    131   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    132   return reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
    133 }
    134 
    135 
    136 Handle<Object> RelocInfo::target_object_handle(Assembler *origin) {
    137   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    138   return Handle<Object>(reinterpret_cast<Object**>(
    139       Assembler::target_address_at(pc_)));
    140 }
    141 
    142 
    143 Object** RelocInfo::target_object_address() {
    144   // Provide a "natural pointer" to the embedded object,
    145   // which can be de-referenced during heap iteration.
    146   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    147   // TODO(mips): Commenting out, to simplify arch-independent changes.
    148   // GC won't work like this, but this commit is for asm/disasm/sim.
    149   // reconstructed_obj_ptr_ =
    150   //   reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
    151   // return &reconstructed_obj_ptr_;
    152   return NULL;
    153 }
    154 
    155 
    156 void RelocInfo::set_target_object(Object* target) {
    157   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    158   Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target));
    159 }
    160 
    161 
    162 Address* RelocInfo::target_reference_address() {
    163   ASSERT(rmode_ == EXTERNAL_REFERENCE);
    164   // TODO(mips): Commenting out, to simplify arch-independent changes.
    165   // GC won't work like this, but this commit is for asm/disasm/sim.
    166   // reconstructed_adr_ptr_ = Assembler::target_address_at(pc_);
    167   // return &reconstructed_adr_ptr_;
    168   return NULL;
    169 }
    170 
    171 
    172 Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
    173   ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
    174   Address address = Memory::Address_at(pc_);
    175   return Handle<JSGlobalPropertyCell>(
    176       reinterpret_cast<JSGlobalPropertyCell**>(address));
    177 }
    178 
    179 
    180 JSGlobalPropertyCell* RelocInfo::target_cell() {
    181   ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
    182   Address address = Memory::Address_at(pc_);
    183   Object* object = HeapObject::FromAddress(
    184       address - JSGlobalPropertyCell::kValueOffset);
    185   return reinterpret_cast<JSGlobalPropertyCell*>(object);
    186 }
    187 
    188 
    189 void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell) {
    190   ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
    191   Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
    192   Memory::Address_at(pc_) = address;
    193 }
    194 
    195 
    196 Address RelocInfo::call_address() {
    197   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
    198          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
    199   // The pc_ offset of 0 assumes mips patched return sequence per
    200   // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
    201   // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
    202   return Assembler::target_address_at(pc_);
    203 }
    204 
    205 
    206 void RelocInfo::set_call_address(Address target) {
    207   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
    208          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
    209   // The pc_ offset of 0 assumes mips patched return sequence per
    210   // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
    211   // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
    212   Assembler::set_target_address_at(pc_, target);
    213 }
    214 
    215 
    216 Object* RelocInfo::call_object() {
    217   return *call_object_address();
    218 }
    219 
    220 
    221 Object** RelocInfo::call_object_address() {
    222   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
    223          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
    224   return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
    225 }
    226 
    227 
    228 void RelocInfo::set_call_object(Object* target) {
    229   *call_object_address() = target;
    230 }
    231 
    232 
    233 bool RelocInfo::IsPatchedReturnSequence() {
    234   Instr instr0 = Assembler::instr_at(pc_);
    235   Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
    236   Instr instr2 = Assembler::instr_at(pc_ + 2 * Assembler::kInstrSize);
    237   bool patched_return = ((instr0 & kOpcodeMask) == LUI &&
    238                          (instr1 & kOpcodeMask) == ORI &&
    239                          (instr2 & kOpcodeMask) == SPECIAL &&
    240                          (instr2 & kFunctionFieldMask) == JALR);
    241   return patched_return;
    242 }
    243 
    244 
    245 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
    246   Instr current_instr = Assembler::instr_at(pc_);
    247   return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
    248 }
    249 
    250 
    251 void RelocInfo::Visit(ObjectVisitor* visitor) {
    252   RelocInfo::Mode mode = rmode();
    253   if (mode == RelocInfo::EMBEDDED_OBJECT) {
    254     // RelocInfo is needed when pointer must be updated/serialized, such as
    255     // UpdatingVisitor in mark-compact.cc or Serializer in serialize.cc.
    256     // It is ignored by visitors that do not need it.
    257     // Commenting out, to simplify arch-independednt changes.
    258     // GC won't work like this, but this commit is for asm/disasm/sim.
    259     // visitor->VisitPointer(target_object_address(), this);
    260   } else if (RelocInfo::IsCodeTarget(mode)) {
    261     visitor->VisitCodeTarget(this);
    262   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
    263     // RelocInfo is needed when external-references must be serialized by
    264     // Serializer Visitor in serialize.cc. It is ignored by visitors that
    265     // do not need it.
    266     // Commenting out, to simplify arch-independednt changes.
    267     // Serializer won't work like this, but this commit is for asm/disasm/sim.
    268     // visitor->VisitExternalReference(target_reference_address(), this);
    269 #ifdef ENABLE_DEBUGGER_SUPPORT
    270   // TODO(isolates): Get a cached isolate below.
    271   } else if (((RelocInfo::IsJSReturn(mode) &&
    272                IsPatchedReturnSequence()) ||
    273              (RelocInfo::IsDebugBreakSlot(mode) &&
    274                IsPatchedDebugBreakSlotSequence())) &&
    275              Isolate::Current()->debug()->has_break_points()) {
    276     visitor->VisitDebugTarget(this);
    277 #endif
    278   } else if (mode == RelocInfo::RUNTIME_ENTRY) {
    279     visitor->VisitRuntimeEntry(this);
    280   }
    281 }
    282 
    283 
    284 template<typename StaticVisitor>
    285 void RelocInfo::Visit(Heap* heap) {
    286   RelocInfo::Mode mode = rmode();
    287   if (mode == RelocInfo::EMBEDDED_OBJECT) {
    288     StaticVisitor::VisitPointer(heap, target_object_address());
    289   } else if (RelocInfo::IsCodeTarget(mode)) {
    290     StaticVisitor::VisitCodeTarget(this);
    291   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
    292     StaticVisitor::VisitExternalReference(target_reference_address());
    293 #ifdef ENABLE_DEBUGGER_SUPPORT
    294   } else if (heap->isolate()->debug()->has_break_points() &&
    295              ((RelocInfo::IsJSReturn(mode) &&
    296               IsPatchedReturnSequence()) ||
    297              (RelocInfo::IsDebugBreakSlot(mode) &&
    298               IsPatchedDebugBreakSlotSequence()))) {
    299     StaticVisitor::VisitDebugTarget(this);
    300 #endif
    301   } else if (mode == RelocInfo::RUNTIME_ENTRY) {
    302     StaticVisitor::VisitRuntimeEntry(this);
    303   }
    304 }
    305 
    306 
    307 // -----------------------------------------------------------------------------
    308 // Assembler
    309 
    310 
    311 void Assembler::CheckBuffer() {
    312   if (buffer_space() <= kGap) {
    313     GrowBuffer();
    314   }
    315 }
    316 
    317 
    318 void Assembler::CheckTrampolinePoolQuick() {
    319   if (pc_offset() >= next_buffer_check_) {
    320     CheckTrampolinePool();
    321   }
    322 }
    323 
    324 
    325 void Assembler::emit(Instr x) {
    326   CheckBuffer();
    327   *reinterpret_cast<Instr*>(pc_) = x;
    328   pc_ += kInstrSize;
    329   CheckTrampolinePoolQuick();
    330 }
    331 
    332 
    333 } }  // namespace v8::internal
    334 
    335 #endif  // V8_MIPS_ASSEMBLER_MIPS_INL_H_
    336