Home | History | Annotate | Download | only in mips
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
     29 #define V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
     30 
     31 #include "assembler.h"
     32 #include "mips/assembler-mips.h"
     33 #include "v8globals.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 // Forward declaration.
     39 class JumpTarget;
     40 
     41 // Reserved Register Usage Summary.
     42 //
     43 // Registers t8, t9, and at are reserved for use by the MacroAssembler.
     44 //
     45 // The programmer should know that the MacroAssembler may clobber these three,
     46 // but won't touch other registers except in special cases.
     47 //
     48 // Per the MIPS ABI, register t9 must be used for indirect function call
     49 // via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when
     50 // trying to update gp register for position-independent-code. Whenever
     51 // MIPS generated code calls C code, it must be via t9 register.
     52 
     53 
     54 // Flags used for LeaveExitFrame function.
     55 enum LeaveExitFrameMode {
     56   EMIT_RETURN = true,
     57   NO_EMIT_RETURN = false
     58 };
     59 
     60 // Flags used for AllocateHeapNumber
     61 enum TaggingMode {
     62   // Tag the result.
     63   TAG_RESULT,
     64   // Don't tag
     65   DONT_TAG_RESULT
     66 };
     67 
     68 // Flags used for the ObjectToDoubleFPURegister function.
     69 enum ObjectToDoubleFlags {
     70   // No special flags.
     71   NO_OBJECT_TO_DOUBLE_FLAGS = 0,
     72   // Object is known to be a non smi.
     73   OBJECT_NOT_SMI = 1 << 0,
     74   // Don't load NaNs or infinities, branch to the non number case instead.
     75   AVOID_NANS_AND_INFINITIES = 1 << 1
     76 };
     77 
     78 // Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls.
     79 enum BranchDelaySlot {
     80   USE_DELAY_SLOT,
     81   PROTECT
     82 };
     83 
     84 // Flags used for the li macro-assembler function.
     85 enum LiFlags {
     86   // If the constant value can be represented in just 16 bits, then
     87   // optimize the li to use a single instruction, rather than lui/ori pair.
     88   OPTIMIZE_SIZE = 0,
     89   // Always use 2 instructions (lui/ori pair), even if the constant could
     90   // be loaded with just one, so that this value is patchable later.
     91   CONSTANT_SIZE = 1
     92 };
     93 
     94 
     95 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
     96 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
     97 enum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved };
     98 
     99 Register GetRegisterThatIsNotOneOf(Register reg1,
    100                                    Register reg2 = no_reg,
    101                                    Register reg3 = no_reg,
    102                                    Register reg4 = no_reg,
    103                                    Register reg5 = no_reg,
    104                                    Register reg6 = no_reg);
    105 
    106 bool AreAliased(Register r1, Register r2, Register r3, Register r4);
    107 
    108 
    109 // -----------------------------------------------------------------------------
    110 // Static helper functions.
    111 
    112 inline MemOperand ContextOperand(Register context, int index) {
    113   return MemOperand(context, Context::SlotOffset(index));
    114 }
    115 
    116 
    117 inline MemOperand GlobalObjectOperand()  {
    118   return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX);
    119 }
    120 
    121 
    122 // Generate a MemOperand for loading a field from an object.
    123 inline MemOperand FieldMemOperand(Register object, int offset) {
    124   return MemOperand(object, offset - kHeapObjectTag);
    125 }
    126 
    127 
    128 // Generate a MemOperand for storing arguments 5..N on the stack
    129 // when calling CallCFunction().
    130 inline MemOperand CFunctionArgumentOperand(int index) {
    131   ASSERT(index > kCArgSlotCount);
    132   // Argument 5 takes the slot just past the four Arg-slots.
    133   int offset = (index - 5) * kPointerSize + kCArgsSlotsSize;
    134   return MemOperand(sp, offset);
    135 }
    136 
    137 
    138 // MacroAssembler implements a collection of frequently used macros.
    139 class MacroAssembler: public Assembler {
    140  public:
    141   // The isolate parameter can be NULL if the macro assembler should
    142   // not use isolate-dependent functionality. In this case, it's the
    143   // responsibility of the caller to never invoke such function on the
    144   // macro assembler.
    145   MacroAssembler(Isolate* isolate, void* buffer, int size);
    146 
    147   // Arguments macros.
    148 #define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2
    149 #define COND_ARGS cond, r1, r2
    150 
    151   // Cases when relocation is not needed.
    152 #define DECLARE_NORELOC_PROTOTYPE(Name, target_type) \
    153   void Name(target_type target, BranchDelaySlot bd = PROTECT); \
    154   inline void Name(BranchDelaySlot bd, target_type target) { \
    155     Name(target, bd); \
    156   } \
    157   void Name(target_type target, \
    158             COND_TYPED_ARGS, \
    159             BranchDelaySlot bd = PROTECT); \
    160   inline void Name(BranchDelaySlot bd, \
    161                    target_type target, \
    162                    COND_TYPED_ARGS) { \
    163     Name(target, COND_ARGS, bd); \
    164   }
    165 
    166 #define DECLARE_BRANCH_PROTOTYPES(Name) \
    167   DECLARE_NORELOC_PROTOTYPE(Name, Label*) \
    168   DECLARE_NORELOC_PROTOTYPE(Name, int16_t)
    169 
    170   DECLARE_BRANCH_PROTOTYPES(Branch)
    171   DECLARE_BRANCH_PROTOTYPES(BranchAndLink)
    172 
    173 #undef DECLARE_BRANCH_PROTOTYPES
    174 #undef COND_TYPED_ARGS
    175 #undef COND_ARGS
    176 
    177 
    178   // Jump, Call, and Ret pseudo instructions implementing inter-working.
    179 #define COND_ARGS Condition cond = al, Register rs = zero_reg, \
    180   const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
    181 
    182   void Jump(Register target, COND_ARGS);
    183   void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS);
    184   void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS);
    185   void Jump(Handle<Code> code, RelocInfo::Mode rmode, COND_ARGS);
    186   static int CallSize(Register target, COND_ARGS);
    187   void Call(Register target, COND_ARGS);
    188   static int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS);
    189   void Call(Address target, RelocInfo::Mode rmode, COND_ARGS);
    190   int CallSize(Handle<Code> code,
    191                RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
    192                TypeFeedbackId ast_id = TypeFeedbackId::None(),
    193                COND_ARGS);
    194   void Call(Handle<Code> code,
    195             RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
    196             TypeFeedbackId ast_id = TypeFeedbackId::None(),
    197             COND_ARGS);
    198   void Ret(COND_ARGS);
    199   inline void Ret(BranchDelaySlot bd, Condition cond = al,
    200     Register rs = zero_reg, const Operand& rt = Operand(zero_reg)) {
    201     Ret(cond, rs, rt, bd);
    202   }
    203 
    204   void Branch(Label* L,
    205               Condition cond,
    206               Register rs,
    207               Heap::RootListIndex index,
    208               BranchDelaySlot bdslot = PROTECT);
    209 
    210 #undef COND_ARGS
    211 
    212   // Emit code to discard a non-negative number of pointer-sized elements
    213   // from the stack, clobbering only the sp register.
    214   void Drop(int count,
    215             Condition cond = cc_always,
    216             Register reg = no_reg,
    217             const Operand& op = Operand(no_reg));
    218 
    219   // Trivial case of DropAndRet that utilizes the delay slot and only emits
    220   // 2 instructions.
    221   void DropAndRet(int drop);
    222 
    223   void DropAndRet(int drop,
    224                   Condition cond,
    225                   Register reg,
    226                   const Operand& op);
    227 
    228   // Swap two registers.  If the scratch register is omitted then a slightly
    229   // less efficient form using xor instead of mov is emitted.
    230   void Swap(Register reg1, Register reg2, Register scratch = no_reg);
    231 
    232   void Call(Label* target);
    233 
    234   inline void Move(Register dst, Register src) {
    235     if (!dst.is(src)) {
    236       mov(dst, src);
    237     }
    238   }
    239 
    240   inline void Move(FPURegister dst, FPURegister src) {
    241     if (!dst.is(src)) {
    242       mov_d(dst, src);
    243     }
    244   }
    245 
    246   inline void Move(Register dst_low, Register dst_high, FPURegister src) {
    247     mfc1(dst_low, src);
    248     mfc1(dst_high, FPURegister::from_code(src.code() + 1));
    249   }
    250 
    251   inline void FmoveHigh(Register dst_high, FPURegister src) {
    252     mfc1(dst_high, FPURegister::from_code(src.code() + 1));
    253   }
    254 
    255   inline void FmoveLow(Register dst_low, FPURegister src) {
    256     mfc1(dst_low, src);
    257   }
    258 
    259   inline void Move(FPURegister dst, Register src_low, Register src_high) {
    260     mtc1(src_low, dst);
    261     mtc1(src_high, FPURegister::from_code(dst.code() + 1));
    262   }
    263 
    264   // Conditional move.
    265   void Move(FPURegister dst, double imm);
    266   void Movz(Register rd, Register rs, Register rt);
    267   void Movn(Register rd, Register rs, Register rt);
    268   void Movt(Register rd, Register rs, uint16_t cc = 0);
    269   void Movf(Register rd, Register rs, uint16_t cc = 0);
    270 
    271   void Clz(Register rd, Register rs);
    272 
    273   // Jump unconditionally to given label.
    274   // We NEED a nop in the branch delay slot, as it used by v8, for example in
    275   // CodeGenerator::ProcessDeferred().
    276   // Currently the branch delay slot is filled by the MacroAssembler.
    277   // Use rather b(Label) for code generation.
    278   void jmp(Label* L) {
    279     Branch(L);
    280   }
    281 
    282   void Load(Register dst, const MemOperand& src, Representation r);
    283   void Store(Register src, const MemOperand& dst, Representation r);
    284 
    285   // Load an object from the root table.
    286   void LoadRoot(Register destination,
    287                 Heap::RootListIndex index);
    288   void LoadRoot(Register destination,
    289                 Heap::RootListIndex index,
    290                 Condition cond, Register src1, const Operand& src2);
    291 
    292   // Store an object to the root table.
    293   void StoreRoot(Register source,
    294                  Heap::RootListIndex index);
    295   void StoreRoot(Register source,
    296                  Heap::RootListIndex index,
    297                  Condition cond, Register src1, const Operand& src2);
    298 
    299   // ---------------------------------------------------------------------------
    300   // GC Support
    301 
    302   void IncrementalMarkingRecordWriteHelper(Register object,
    303                                            Register value,
    304                                            Register address);
    305 
    306   enum RememberedSetFinalAction {
    307     kReturnAtEnd,
    308     kFallThroughAtEnd
    309   };
    310 
    311 
    312   // Record in the remembered set the fact that we have a pointer to new space
    313   // at the address pointed to by the addr register.  Only works if addr is not
    314   // in new space.
    315   void RememberedSetHelper(Register object,  // Used for debug code.
    316                            Register addr,
    317                            Register scratch,
    318                            SaveFPRegsMode save_fp,
    319                            RememberedSetFinalAction and_then);
    320 
    321   void CheckPageFlag(Register object,
    322                      Register scratch,
    323                      int mask,
    324                      Condition cc,
    325                      Label* condition_met);
    326 
    327   void CheckMapDeprecated(Handle<Map> map,
    328                           Register scratch,
    329                           Label* if_deprecated);
    330 
    331   // Check if object is in new space.  Jumps if the object is not in new space.
    332   // The register scratch can be object itself, but it will be clobbered.
    333   void JumpIfNotInNewSpace(Register object,
    334                            Register scratch,
    335                            Label* branch) {
    336     InNewSpace(object, scratch, ne, branch);
    337   }
    338 
    339   // Check if object is in new space.  Jumps if the object is in new space.
    340   // The register scratch can be object itself, but scratch will be clobbered.
    341   void JumpIfInNewSpace(Register object,
    342                         Register scratch,
    343                         Label* branch) {
    344     InNewSpace(object, scratch, eq, branch);
    345   }
    346 
    347   // Check if an object has a given incremental marking color.
    348   void HasColor(Register object,
    349                 Register scratch0,
    350                 Register scratch1,
    351                 Label* has_color,
    352                 int first_bit,
    353                 int second_bit);
    354 
    355   void JumpIfBlack(Register object,
    356                    Register scratch0,
    357                    Register scratch1,
    358                    Label* on_black);
    359 
    360   // Checks the color of an object.  If the object is already grey or black
    361   // then we just fall through, since it is already live.  If it is white and
    362   // we can determine that it doesn't need to be scanned, then we just mark it
    363   // black and fall through.  For the rest we jump to the label so the
    364   // incremental marker can fix its assumptions.
    365   void EnsureNotWhite(Register object,
    366                       Register scratch1,
    367                       Register scratch2,
    368                       Register scratch3,
    369                       Label* object_is_white_and_not_data);
    370 
    371   // Detects conservatively whether an object is data-only, i.e. it does need to
    372   // be scanned by the garbage collector.
    373   void JumpIfDataObject(Register value,
    374                         Register scratch,
    375                         Label* not_data_object);
    376 
    377   // Notify the garbage collector that we wrote a pointer into an object.
    378   // |object| is the object being stored into, |value| is the object being
    379   // stored.  value and scratch registers are clobbered by the operation.
    380   // The offset is the offset from the start of the object, not the offset from
    381   // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
    382   void RecordWriteField(
    383       Register object,
    384       int offset,
    385       Register value,
    386       Register scratch,
    387       RAStatus ra_status,
    388       SaveFPRegsMode save_fp,
    389       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    390       SmiCheck smi_check = INLINE_SMI_CHECK);
    391 
    392   // As above, but the offset has the tag presubtracted.  For use with
    393   // MemOperand(reg, off).
    394   inline void RecordWriteContextSlot(
    395       Register context,
    396       int offset,
    397       Register value,
    398       Register scratch,
    399       RAStatus ra_status,
    400       SaveFPRegsMode save_fp,
    401       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    402       SmiCheck smi_check = INLINE_SMI_CHECK) {
    403     RecordWriteField(context,
    404                      offset + kHeapObjectTag,
    405                      value,
    406                      scratch,
    407                      ra_status,
    408                      save_fp,
    409                      remembered_set_action,
    410                      smi_check);
    411   }
    412 
    413   // For a given |object| notify the garbage collector that the slot |address|
    414   // has been written.  |value| is the object being stored. The value and
    415   // address registers are clobbered by the operation.
    416   void RecordWrite(
    417       Register object,
    418       Register address,
    419       Register value,
    420       RAStatus ra_status,
    421       SaveFPRegsMode save_fp,
    422       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    423       SmiCheck smi_check = INLINE_SMI_CHECK);
    424 
    425 
    426   // ---------------------------------------------------------------------------
    427   // Inline caching support.
    428 
    429   // Generate code for checking access rights - used for security checks
    430   // on access to global objects across environments. The holder register
    431   // is left untouched, whereas both scratch registers are clobbered.
    432   void CheckAccessGlobalProxy(Register holder_reg,
    433                               Register scratch,
    434                               Label* miss);
    435 
    436   void GetNumberHash(Register reg0, Register scratch);
    437 
    438   void LoadFromNumberDictionary(Label* miss,
    439                                 Register elements,
    440                                 Register key,
    441                                 Register result,
    442                                 Register reg0,
    443                                 Register reg1,
    444                                 Register reg2);
    445 
    446 
    447   inline void MarkCode(NopMarkerTypes type) {
    448     nop(type);
    449   }
    450 
    451   // Check if the given instruction is a 'type' marker.
    452   // i.e. check if it is a sll zero_reg, zero_reg, <type> (referenced as
    453   // nop(type)). These instructions are generated to mark special location in
    454   // the code, like some special IC code.
    455   static inline bool IsMarkedCode(Instr instr, int type) {
    456     ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
    457     return IsNop(instr, type);
    458   }
    459 
    460 
    461   static inline int GetCodeMarker(Instr instr) {
    462     uint32_t opcode = ((instr & kOpcodeMask));
    463     uint32_t rt = ((instr & kRtFieldMask) >> kRtShift);
    464     uint32_t rs = ((instr & kRsFieldMask) >> kRsShift);
    465     uint32_t sa = ((instr & kSaFieldMask) >> kSaShift);
    466 
    467     // Return <n> if we have a sll zero_reg, zero_reg, n
    468     // else return -1.
    469     bool sllzz = (opcode == SLL &&
    470                   rt == static_cast<uint32_t>(ToNumber(zero_reg)) &&
    471                   rs == static_cast<uint32_t>(ToNumber(zero_reg)));
    472     int type =
    473         (sllzz && FIRST_IC_MARKER <= sa && sa < LAST_CODE_MARKER) ? sa : -1;
    474     ASSERT((type == -1) ||
    475            ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
    476     return type;
    477   }
    478 
    479 
    480 
    481   // ---------------------------------------------------------------------------
    482   // Allocation support.
    483 
    484   // Allocate an object in new space or old pointer space. The object_size is
    485   // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
    486   // is passed. If the space is exhausted control continues at the gc_required
    487   // label. The allocated object is returned in result. If the flag
    488   // tag_allocated_object is true the result is tagged as as a heap object.
    489   // All registers are clobbered also when control continues at the gc_required
    490   // label.
    491   void Allocate(int object_size,
    492                 Register result,
    493                 Register scratch1,
    494                 Register scratch2,
    495                 Label* gc_required,
    496                 AllocationFlags flags);
    497 
    498   void Allocate(Register object_size,
    499                 Register result,
    500                 Register scratch1,
    501                 Register scratch2,
    502                 Label* gc_required,
    503                 AllocationFlags flags);
    504 
    505   // Undo allocation in new space. The object passed and objects allocated after
    506   // it will no longer be allocated. The caller must make sure that no pointers
    507   // are left to the object(s) no longer allocated as they would be invalid when
    508   // allocation is undone.
    509   void UndoAllocationInNewSpace(Register object, Register scratch);
    510 
    511 
    512   void AllocateTwoByteString(Register result,
    513                              Register length,
    514                              Register scratch1,
    515                              Register scratch2,
    516                              Register scratch3,
    517                              Label* gc_required);
    518   void AllocateAsciiString(Register result,
    519                            Register length,
    520                            Register scratch1,
    521                            Register scratch2,
    522                            Register scratch3,
    523                            Label* gc_required);
    524   void AllocateTwoByteConsString(Register result,
    525                                  Register length,
    526                                  Register scratch1,
    527                                  Register scratch2,
    528                                  Label* gc_required);
    529   void AllocateAsciiConsString(Register result,
    530                                Register length,
    531                                Register scratch1,
    532                                Register scratch2,
    533                                Label* gc_required);
    534   void AllocateTwoByteSlicedString(Register result,
    535                                    Register length,
    536                                    Register scratch1,
    537                                    Register scratch2,
    538                                    Label* gc_required);
    539   void AllocateAsciiSlicedString(Register result,
    540                                  Register length,
    541                                  Register scratch1,
    542                                  Register scratch2,
    543                                  Label* gc_required);
    544 
    545   // Allocates a heap number or jumps to the gc_required label if the young
    546   // space is full and a scavenge is needed. All registers are clobbered also
    547   // when control continues at the gc_required label.
    548   void AllocateHeapNumber(Register result,
    549                           Register scratch1,
    550                           Register scratch2,
    551                           Register heap_number_map,
    552                           Label* gc_required,
    553                           TaggingMode tagging_mode = TAG_RESULT);
    554   void AllocateHeapNumberWithValue(Register result,
    555                                    FPURegister value,
    556                                    Register scratch1,
    557                                    Register scratch2,
    558                                    Label* gc_required);
    559 
    560   // ---------------------------------------------------------------------------
    561   // Instruction macros.
    562 
    563 #define DEFINE_INSTRUCTION(instr)                                              \
    564   void instr(Register rd, Register rs, const Operand& rt);                     \
    565   void instr(Register rd, Register rs, Register rt) {                          \
    566     instr(rd, rs, Operand(rt));                                                \
    567   }                                                                            \
    568   void instr(Register rs, Register rt, int32_t j) {                            \
    569     instr(rs, rt, Operand(j));                                                 \
    570   }
    571 
    572 #define DEFINE_INSTRUCTION2(instr)                                             \
    573   void instr(Register rs, const Operand& rt);                                  \
    574   void instr(Register rs, Register rt) {                                       \
    575     instr(rs, Operand(rt));                                                    \
    576   }                                                                            \
    577   void instr(Register rs, int32_t j) {                                         \
    578     instr(rs, Operand(j));                                                     \
    579   }
    580 
    581   DEFINE_INSTRUCTION(Addu);
    582   DEFINE_INSTRUCTION(Subu);
    583   DEFINE_INSTRUCTION(Mul);
    584   DEFINE_INSTRUCTION2(Mult);
    585   DEFINE_INSTRUCTION2(Multu);
    586   DEFINE_INSTRUCTION2(Div);
    587   DEFINE_INSTRUCTION2(Divu);
    588 
    589   DEFINE_INSTRUCTION(And);
    590   DEFINE_INSTRUCTION(Or);
    591   DEFINE_INSTRUCTION(Xor);
    592   DEFINE_INSTRUCTION(Nor);
    593   DEFINE_INSTRUCTION2(Neg);
    594 
    595   DEFINE_INSTRUCTION(Slt);
    596   DEFINE_INSTRUCTION(Sltu);
    597 
    598   // MIPS32 R2 instruction macro.
    599   DEFINE_INSTRUCTION(Ror);
    600 
    601 #undef DEFINE_INSTRUCTION
    602 #undef DEFINE_INSTRUCTION2
    603 
    604 
    605   // ---------------------------------------------------------------------------
    606   // Pseudo-instructions.
    607 
    608   void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
    609 
    610   // Load int32 in the rd register.
    611   void li(Register rd, Operand j, LiFlags mode = OPTIMIZE_SIZE);
    612   inline void li(Register rd, int32_t j, LiFlags mode = OPTIMIZE_SIZE) {
    613     li(rd, Operand(j), mode);
    614   }
    615   void li(Register dst, Handle<Object> value, LiFlags mode = OPTIMIZE_SIZE);
    616 
    617   // Push multiple registers on the stack.
    618   // Registers are saved in numerical order, with higher numbered registers
    619   // saved in higher memory addresses.
    620   void MultiPush(RegList regs);
    621   void MultiPushReversed(RegList regs);
    622 
    623   void MultiPushFPU(RegList regs);
    624   void MultiPushReversedFPU(RegList regs);
    625 
    626   void push(Register src) {
    627     Addu(sp, sp, Operand(-kPointerSize));
    628     sw(src, MemOperand(sp, 0));
    629   }
    630   void Push(Register src) { push(src); }
    631 
    632   // Push a handle.
    633   void Push(Handle<Object> handle);
    634   void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
    635 
    636   // Push two registers. Pushes leftmost register first (to highest address).
    637   void Push(Register src1, Register src2) {
    638     Subu(sp, sp, Operand(2 * kPointerSize));
    639     sw(src1, MemOperand(sp, 1 * kPointerSize));
    640     sw(src2, MemOperand(sp, 0 * kPointerSize));
    641   }
    642 
    643   // Push three registers. Pushes leftmost register first (to highest address).
    644   void Push(Register src1, Register src2, Register src3) {
    645     Subu(sp, sp, Operand(3 * kPointerSize));
    646     sw(src1, MemOperand(sp, 2 * kPointerSize));
    647     sw(src2, MemOperand(sp, 1 * kPointerSize));
    648     sw(src3, MemOperand(sp, 0 * kPointerSize));
    649   }
    650 
    651   // Push four registers. Pushes leftmost register first (to highest address).
    652   void Push(Register src1, Register src2, Register src3, Register src4) {
    653     Subu(sp, sp, Operand(4 * kPointerSize));
    654     sw(src1, MemOperand(sp, 3 * kPointerSize));
    655     sw(src2, MemOperand(sp, 2 * kPointerSize));
    656     sw(src3, MemOperand(sp, 1 * kPointerSize));
    657     sw(src4, MemOperand(sp, 0 * kPointerSize));
    658   }
    659 
    660   void Push(Register src, Condition cond, Register tst1, Register tst2) {
    661     // Since we don't have conditional execution we use a Branch.
    662     Branch(3, cond, tst1, Operand(tst2));
    663     Subu(sp, sp, Operand(kPointerSize));
    664     sw(src, MemOperand(sp, 0));
    665   }
    666 
    667   // Pops multiple values from the stack and load them in the
    668   // registers specified in regs. Pop order is the opposite as in MultiPush.
    669   void MultiPop(RegList regs);
    670   void MultiPopReversed(RegList regs);
    671 
    672   void MultiPopFPU(RegList regs);
    673   void MultiPopReversedFPU(RegList regs);
    674 
    675   void pop(Register dst) {
    676     lw(dst, MemOperand(sp, 0));
    677     Addu(sp, sp, Operand(kPointerSize));
    678   }
    679   void Pop(Register dst) { pop(dst); }
    680 
    681   // Pop two registers. Pops rightmost register first (from lower address).
    682   void Pop(Register src1, Register src2) {
    683     ASSERT(!src1.is(src2));
    684     lw(src2, MemOperand(sp, 0 * kPointerSize));
    685     lw(src1, MemOperand(sp, 1 * kPointerSize));
    686     Addu(sp, sp, 2 * kPointerSize);
    687   }
    688 
    689   // Pop three registers. Pops rightmost register first (from lower address).
    690   void Pop(Register src1, Register src2, Register src3) {
    691     lw(src3, MemOperand(sp, 0 * kPointerSize));
    692     lw(src2, MemOperand(sp, 1 * kPointerSize));
    693     lw(src1, MemOperand(sp, 2 * kPointerSize));
    694     Addu(sp, sp, 3 * kPointerSize);
    695   }
    696 
    697   void Pop(uint32_t count = 1) {
    698     Addu(sp, sp, Operand(count * kPointerSize));
    699   }
    700 
    701   // Push and pop the registers that can hold pointers, as defined by the
    702   // RegList constant kSafepointSavedRegisters.
    703   void PushSafepointRegisters();
    704   void PopSafepointRegisters();
    705   void PushSafepointRegistersAndDoubles();
    706   void PopSafepointRegistersAndDoubles();
    707   // Store value in register src in the safepoint stack slot for
    708   // register dst.
    709   void StoreToSafepointRegisterSlot(Register src, Register dst);
    710   void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst);
    711   // Load the value of the src register from its safepoint stack slot
    712   // into register dst.
    713   void LoadFromSafepointRegisterSlot(Register dst, Register src);
    714 
    715   // Flush the I-cache from asm code. You should use CPU::FlushICache from C.
    716   // Does not handle errors.
    717   void FlushICache(Register address, unsigned instructions);
    718 
    719   // MIPS32 R2 instruction macro.
    720   void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
    721   void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
    722 
    723   // ---------------------------------------------------------------------------
    724   // FPU macros. These do not handle special cases like NaN or +- inf.
    725 
    726   // Convert unsigned word to double.
    727   void Cvt_d_uw(FPURegister fd, FPURegister fs, FPURegister scratch);
    728   void Cvt_d_uw(FPURegister fd, Register rs, FPURegister scratch);
    729 
    730   // Convert double to unsigned word.
    731   void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch);
    732   void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch);
    733 
    734   void Trunc_w_d(FPURegister fd, FPURegister fs);
    735   void Round_w_d(FPURegister fd, FPURegister fs);
    736   void Floor_w_d(FPURegister fd, FPURegister fs);
    737   void Ceil_w_d(FPURegister fd, FPURegister fs);
    738   // Wrapper function for the different cmp/branch types.
    739   void BranchF(Label* target,
    740                Label* nan,
    741                Condition cc,
    742                FPURegister cmp1,
    743                FPURegister cmp2,
    744                BranchDelaySlot bd = PROTECT);
    745 
    746   // Alternate (inline) version for better readability with USE_DELAY_SLOT.
    747   inline void BranchF(BranchDelaySlot bd,
    748                       Label* target,
    749                       Label* nan,
    750                       Condition cc,
    751                       FPURegister cmp1,
    752                       FPURegister cmp2) {
    753     BranchF(target, nan, cc, cmp1, cmp2, bd);
    754   };
    755 
    756   // Truncates a double using a specific rounding mode, and writes the value
    757   // to the result register.
    758   // The except_flag will contain any exceptions caused by the instruction.
    759   // If check_inexact is kDontCheckForInexactConversion, then the inexact
    760   // exception is masked.
    761   void EmitFPUTruncate(FPURoundingMode rounding_mode,
    762                        Register result,
    763                        DoubleRegister double_input,
    764                        Register scratch,
    765                        DoubleRegister double_scratch,
    766                        Register except_flag,
    767                        CheckForInexactConversion check_inexact
    768                            = kDontCheckForInexactConversion);
    769 
    770   // Performs a truncating conversion of a floating point number as used by
    771   // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
    772   // succeeds, otherwise falls through if result is saturated. On return
    773   // 'result' either holds answer, or is clobbered on fall through.
    774   //
    775   // Only public for the test code in test-code-stubs-arm.cc.
    776   void TryInlineTruncateDoubleToI(Register result,
    777                                   DoubleRegister input,
    778                                   Label* done);
    779 
    780   // Performs a truncating conversion of a floating point number as used by
    781   // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
    782   // Exits with 'result' holding the answer.
    783   void TruncateDoubleToI(Register result, DoubleRegister double_input);
    784 
    785   // Performs a truncating conversion of a heap number as used by
    786   // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
    787   // must be different registers. Exits with 'result' holding the answer.
    788   void TruncateHeapNumberToI(Register result, Register object);
    789 
    790   // Converts the smi or heap number in object to an int32 using the rules
    791   // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
    792   // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
    793   // different registers.
    794   void TruncateNumberToI(Register object,
    795                          Register result,
    796                          Register heap_number_map,
    797                          Register scratch,
    798                          Label* not_int32);
    799 
    800   // Loads the number from object into dst register.
    801   // If |object| is neither smi nor heap number, |not_number| is jumped to
    802   // with |object| still intact.
    803   void LoadNumber(Register object,
    804                   FPURegister dst,
    805                   Register heap_number_map,
    806                   Register scratch,
    807                   Label* not_number);
    808 
    809   // Loads the number from object into double_dst in the double format.
    810   // Control will jump to not_int32 if the value cannot be exactly represented
    811   // by a 32-bit integer.
    812   // Floating point value in the 32-bit integer range that are not exact integer
    813   // won't be loaded.
    814   void LoadNumberAsInt32Double(Register object,
    815                                DoubleRegister double_dst,
    816                                Register heap_number_map,
    817                                Register scratch1,
    818                                Register scratch2,
    819                                FPURegister double_scratch,
    820                                Label* not_int32);
    821 
    822   // Loads the number from object into dst as a 32-bit integer.
    823   // Control will jump to not_int32 if the object cannot be exactly represented
    824   // by a 32-bit integer.
    825   // Floating point value in the 32-bit integer range that are not exact integer
    826   // won't be converted.
    827   void LoadNumberAsInt32(Register object,
    828                          Register dst,
    829                          Register heap_number_map,
    830                          Register scratch1,
    831                          Register scratch2,
    832                          FPURegister double_scratch0,
    833                          FPURegister double_scratch1,
    834                          Label* not_int32);
    835 
    836   // Enter exit frame.
    837   // argc - argument count to be dropped by LeaveExitFrame.
    838   // save_doubles - saves FPU registers on stack, currently disabled.
    839   // stack_space - extra stack space.
    840   void EnterExitFrame(bool save_doubles,
    841                       int stack_space = 0);
    842 
    843   // Leave the current exit frame.
    844   void LeaveExitFrame(bool save_doubles,
    845                       Register arg_count,
    846                       bool restore_context,
    847                       bool do_return = NO_EMIT_RETURN);
    848 
    849   // Get the actual activation frame alignment for target environment.
    850   static int ActivationFrameAlignment();
    851 
    852   // Make sure the stack is aligned. Only emits code in debug mode.
    853   void AssertStackIsAligned();
    854 
    855   void LoadContext(Register dst, int context_chain_length);
    856 
    857   // Conditionally load the cached Array transitioned map of type
    858   // transitioned_kind from the native context if the map in register
    859   // map_in_out is the cached Array map in the native context of
    860   // expected_kind.
    861   void LoadTransitionedArrayMapConditional(
    862       ElementsKind expected_kind,
    863       ElementsKind transitioned_kind,
    864       Register map_in_out,
    865       Register scratch,
    866       Label* no_map_match);
    867 
    868   // Load the initial map for new Arrays from a JSFunction.
    869   void LoadInitialArrayMap(Register function_in,
    870                            Register scratch,
    871                            Register map_out,
    872                            bool can_have_holes);
    873 
    874   void LoadGlobalFunction(int index, Register function);
    875   void LoadArrayFunction(Register function);
    876 
    877   // Load the initial map from the global function. The registers
    878   // function and map can be the same, function is then overwritten.
    879   void LoadGlobalFunctionInitialMap(Register function,
    880                                     Register map,
    881                                     Register scratch);
    882 
    883   void InitializeRootRegister() {
    884     ExternalReference roots_array_start =
    885         ExternalReference::roots_array_start(isolate());
    886     li(kRootRegister, Operand(roots_array_start));
    887   }
    888 
    889   // -------------------------------------------------------------------------
    890   // JavaScript invokes.
    891 
    892   // Set up call kind marking in t1. The method takes t1 as an
    893   // explicit first parameter to make the code more readable at the
    894   // call sites.
    895   void SetCallKind(Register dst, CallKind kind);
    896 
    897   // Invoke the JavaScript function code by either calling or jumping.
    898   void InvokeCode(Register code,
    899                   const ParameterCount& expected,
    900                   const ParameterCount& actual,
    901                   InvokeFlag flag,
    902                   const CallWrapper& call_wrapper,
    903                   CallKind call_kind);
    904 
    905   void InvokeCode(Handle<Code> code,
    906                   const ParameterCount& expected,
    907                   const ParameterCount& actual,
    908                   RelocInfo::Mode rmode,
    909                   InvokeFlag flag,
    910                   CallKind call_kind);
    911 
    912   // Invoke the JavaScript function in the given register. Changes the
    913   // current context to the context in the function before invoking.
    914   void InvokeFunction(Register function,
    915                       const ParameterCount& actual,
    916                       InvokeFlag flag,
    917                       const CallWrapper& call_wrapper,
    918                       CallKind call_kind);
    919 
    920   void InvokeFunction(Register function,
    921                       const ParameterCount& expected,
    922                       const ParameterCount& actual,
    923                       InvokeFlag flag,
    924                       const CallWrapper& call_wrapper,
    925                       CallKind call_kind);
    926 
    927   void InvokeFunction(Handle<JSFunction> function,
    928                       const ParameterCount& expected,
    929                       const ParameterCount& actual,
    930                       InvokeFlag flag,
    931                       const CallWrapper& call_wrapper,
    932                       CallKind call_kind);
    933 
    934 
    935   void IsObjectJSObjectType(Register heap_object,
    936                             Register map,
    937                             Register scratch,
    938                             Label* fail);
    939 
    940   void IsInstanceJSObjectType(Register map,
    941                               Register scratch,
    942                               Label* fail);
    943 
    944   void IsObjectJSStringType(Register object,
    945                             Register scratch,
    946                             Label* fail);
    947 
    948   void IsObjectNameType(Register object,
    949                         Register scratch,
    950                         Label* fail);
    951 
    952 #ifdef ENABLE_DEBUGGER_SUPPORT
    953   // -------------------------------------------------------------------------
    954   // Debugger Support.
    955 
    956   void DebugBreak();
    957 #endif
    958 
    959 
    960   // -------------------------------------------------------------------------
    961   // Exception handling.
    962 
    963   // Push a new try handler and link into try handler chain.
    964   void PushTryHandler(StackHandler::Kind kind, int handler_index);
    965 
    966   // Unlink the stack handler on top of the stack from the try handler chain.
    967   // Must preserve the result register.
    968   void PopTryHandler();
    969 
    970   // Passes thrown value to the handler of top of the try handler chain.
    971   void Throw(Register value);
    972 
    973   // Propagates an uncatchable exception to the top of the current JS stack's
    974   // handler chain.
    975   void ThrowUncatchable(Register value);
    976 
    977   // Throw a message string as an exception.
    978   void Throw(BailoutReason reason);
    979 
    980   // Throw a message string as an exception if a condition is not true.
    981   void ThrowIf(Condition cc, BailoutReason reason, Register rs, Operand rt);
    982 
    983   // Copies a fixed number of fields of heap objects from src to dst.
    984   void CopyFields(Register dst, Register src, RegList temps, int field_count);
    985 
    986   // Copies a number of bytes from src to dst. All registers are clobbered. On
    987   // exit src and dst will point to the place just after where the last byte was
    988   // read or written and length will be zero.
    989   void CopyBytes(Register src,
    990                  Register dst,
    991                  Register length,
    992                  Register scratch);
    993 
    994   // Initialize fields with filler values.  Fields starting at |start_offset|
    995   // not including end_offset are overwritten with the value in |filler|.  At
    996   // the end the loop, |start_offset| takes the value of |end_offset|.
    997   void InitializeFieldsWithFiller(Register start_offset,
    998                                   Register end_offset,
    999                                   Register filler);
   1000 
   1001   // -------------------------------------------------------------------------
   1002   // Support functions.
   1003 
   1004   // Try to get function prototype of a function and puts the value in
   1005   // the result register. Checks that the function really is a
   1006   // function and jumps to the miss label if the fast checks fail. The
   1007   // function register will be untouched; the other registers may be
   1008   // clobbered.
   1009   void TryGetFunctionPrototype(Register function,
   1010                                Register result,
   1011                                Register scratch,
   1012                                Label* miss,
   1013                                bool miss_on_bound_function = false);
   1014 
   1015   void GetObjectType(Register function,
   1016                      Register map,
   1017                      Register type_reg);
   1018 
   1019   // Check if a map for a JSObject indicates that the object has fast elements.
   1020   // Jump to the specified label if it does not.
   1021   void CheckFastElements(Register map,
   1022                          Register scratch,
   1023                          Label* fail);
   1024 
   1025   // Check if a map for a JSObject indicates that the object can have both smi
   1026   // and HeapObject elements.  Jump to the specified label if it does not.
   1027   void CheckFastObjectElements(Register map,
   1028                                Register scratch,
   1029                                Label* fail);
   1030 
   1031   // Check if a map for a JSObject indicates that the object has fast smi only
   1032   // elements.  Jump to the specified label if it does not.
   1033   void CheckFastSmiElements(Register map,
   1034                             Register scratch,
   1035                             Label* fail);
   1036 
   1037   // Check to see if maybe_number can be stored as a double in
   1038   // FastDoubleElements. If it can, store it at the index specified by key in
   1039   // the FastDoubleElements array elements. Otherwise jump to fail.
   1040   void StoreNumberToDoubleElements(Register value_reg,
   1041                                    Register key_reg,
   1042                                    Register elements_reg,
   1043                                    Register scratch1,
   1044                                    Register scratch2,
   1045                                    Register scratch3,
   1046                                    Label* fail,
   1047                                    int elements_offset = 0);
   1048 
   1049   // Compare an object's map with the specified map and its transitioned
   1050   // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Jumps to
   1051   // "branch_to" if the result of the comparison is "cond". If multiple map
   1052   // compares are required, the compare sequences branches to early_success.
   1053   void CompareMapAndBranch(Register obj,
   1054                            Register scratch,
   1055                            Handle<Map> map,
   1056                            Label* early_success,
   1057                            Condition cond,
   1058                            Label* branch_to);
   1059 
   1060   // As above, but the map of the object is already loaded into the register
   1061   // which is preserved by the code generated.
   1062   void CompareMapAndBranch(Register obj_map,
   1063                            Handle<Map> map,
   1064                            Label* early_success,
   1065                            Condition cond,
   1066                            Label* branch_to);
   1067 
   1068   // Check if the map of an object is equal to a specified map and branch to
   1069   // label if not. Skip the smi check if not required (object is known to be a
   1070   // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
   1071   // against maps that are ElementsKind transition maps of the specificed map.
   1072   void CheckMap(Register obj,
   1073                 Register scratch,
   1074                 Handle<Map> map,
   1075                 Label* fail,
   1076                 SmiCheckType smi_check_type);
   1077 
   1078 
   1079   void CheckMap(Register obj,
   1080                 Register scratch,
   1081                 Heap::RootListIndex index,
   1082                 Label* fail,
   1083                 SmiCheckType smi_check_type);
   1084 
   1085   // Check if the map of an object is equal to a specified map and branch to a
   1086   // specified target if equal. Skip the smi check if not required (object is
   1087   // known to be a heap object)
   1088   void DispatchMap(Register obj,
   1089                    Register scratch,
   1090                    Handle<Map> map,
   1091                    Handle<Code> success,
   1092                    SmiCheckType smi_check_type);
   1093 
   1094   // Generates code for reporting that an illegal operation has
   1095   // occurred.
   1096   void IllegalOperation(int num_arguments);
   1097 
   1098 
   1099   // Load and check the instance type of an object for being a string.
   1100   // Loads the type into the second argument register.
   1101   // Returns a condition that will be enabled if the object was a string.
   1102   Condition IsObjectStringType(Register obj,
   1103                                Register type,
   1104                                Register result) {
   1105     lw(type, FieldMemOperand(obj, HeapObject::kMapOffset));
   1106     lbu(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
   1107     And(type, type, Operand(kIsNotStringMask));
   1108     ASSERT_EQ(0, kStringTag);
   1109     return eq;
   1110   }
   1111 
   1112 
   1113   // Picks out an array index from the hash field.
   1114   // Register use:
   1115   //   hash - holds the index's hash. Clobbered.
   1116   //   index - holds the overwritten index on exit.
   1117   void IndexFromHash(Register hash, Register index);
   1118 
   1119   // Get the number of least significant bits from a register.
   1120   void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
   1121   void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
   1122 
   1123   // Load the value of a number object into a FPU double register. If the
   1124   // object is not a number a jump to the label not_number is performed
   1125   // and the FPU double register is unchanged.
   1126   void ObjectToDoubleFPURegister(
   1127       Register object,
   1128       FPURegister value,
   1129       Register scratch1,
   1130       Register scratch2,
   1131       Register heap_number_map,
   1132       Label* not_number,
   1133       ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
   1134 
   1135   // Load the value of a smi object into a FPU double register. The register
   1136   // scratch1 can be the same register as smi in which case smi will hold the
   1137   // untagged value afterwards.
   1138   void SmiToDoubleFPURegister(Register smi,
   1139                               FPURegister value,
   1140                               Register scratch1);
   1141 
   1142   // -------------------------------------------------------------------------
   1143   // Overflow handling functions.
   1144   // Usage: first call the appropriate arithmetic function, then call one of the
   1145   // jump functions with the overflow_dst register as the second parameter.
   1146 
   1147   void AdduAndCheckForOverflow(Register dst,
   1148                                Register left,
   1149                                Register right,
   1150                                Register overflow_dst,
   1151                                Register scratch = at);
   1152 
   1153   void SubuAndCheckForOverflow(Register dst,
   1154                                Register left,
   1155                                Register right,
   1156                                Register overflow_dst,
   1157                                Register scratch = at);
   1158 
   1159   void BranchOnOverflow(Label* label,
   1160                         Register overflow_check,
   1161                         BranchDelaySlot bd = PROTECT) {
   1162     Branch(label, lt, overflow_check, Operand(zero_reg), bd);
   1163   }
   1164 
   1165   void BranchOnNoOverflow(Label* label,
   1166                           Register overflow_check,
   1167                           BranchDelaySlot bd = PROTECT) {
   1168     Branch(label, ge, overflow_check, Operand(zero_reg), bd);
   1169   }
   1170 
   1171   void RetOnOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
   1172     Ret(lt, overflow_check, Operand(zero_reg), bd);
   1173   }
   1174 
   1175   void RetOnNoOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
   1176     Ret(ge, overflow_check, Operand(zero_reg), bd);
   1177   }
   1178 
   1179   // -------------------------------------------------------------------------
   1180   // Runtime calls.
   1181 
   1182   // See comments at the beginning of CEntryStub::Generate.
   1183   inline void PrepareCEntryArgs(int num_args) {
   1184     li(s0, num_args);
   1185     li(s1, (num_args - 1) * kPointerSize);
   1186   }
   1187 
   1188   inline void PrepareCEntryFunction(const ExternalReference& ref) {
   1189     li(s2, Operand(ref));
   1190   }
   1191 
   1192   // Call a code stub.
   1193   void CallStub(CodeStub* stub,
   1194                 TypeFeedbackId ast_id = TypeFeedbackId::None(),
   1195                 Condition cond = cc_always,
   1196                 Register r1 = zero_reg,
   1197                 const Operand& r2 = Operand(zero_reg),
   1198                 BranchDelaySlot bd = PROTECT);
   1199 
   1200   // Tail call a code stub (jump).
   1201   void TailCallStub(CodeStub* stub);
   1202 
   1203   void CallJSExitStub(CodeStub* stub);
   1204 
   1205   // Call a runtime routine.
   1206   void CallRuntime(const Runtime::Function* f,
   1207                    int num_arguments,
   1208                    SaveFPRegsMode save_doubles = kDontSaveFPRegs);
   1209   void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
   1210     const Runtime::Function* function = Runtime::FunctionForId(id);
   1211     CallRuntime(function, function->nargs, kSaveFPRegs);
   1212   }
   1213 
   1214   // Convenience function: Same as above, but takes the fid instead.
   1215   void CallRuntime(Runtime::FunctionId id,
   1216                    int num_arguments,
   1217                    SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
   1218     CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
   1219   }
   1220 
   1221   // Convenience function: call an external reference.
   1222   void CallExternalReference(const ExternalReference& ext,
   1223                              int num_arguments,
   1224                              BranchDelaySlot bd = PROTECT);
   1225 
   1226   // Tail call of a runtime routine (jump).
   1227   // Like JumpToExternalReference, but also takes care of passing the number
   1228   // of parameters.
   1229   void TailCallExternalReference(const ExternalReference& ext,
   1230                                  int num_arguments,
   1231                                  int result_size);
   1232 
   1233   // Convenience function: tail call a runtime routine (jump).
   1234   void TailCallRuntime(Runtime::FunctionId fid,
   1235                        int num_arguments,
   1236                        int result_size);
   1237 
   1238   int CalculateStackPassedWords(int num_reg_arguments,
   1239                                 int num_double_arguments);
   1240 
   1241   // Before calling a C-function from generated code, align arguments on stack
   1242   // and add space for the four mips argument slots.
   1243   // After aligning the frame, non-register arguments must be stored on the
   1244   // stack, after the argument-slots using helper: CFunctionArgumentOperand().
   1245   // The argument count assumes all arguments are word sized.
   1246   // Some compilers/platforms require the stack to be aligned when calling
   1247   // C++ code.
   1248   // Needs a scratch register to do some arithmetic. This register will be
   1249   // trashed.
   1250   void PrepareCallCFunction(int num_reg_arguments,
   1251                             int num_double_registers,
   1252                             Register scratch);
   1253   void PrepareCallCFunction(int num_reg_arguments,
   1254                             Register scratch);
   1255 
   1256   // Arguments 1-4 are placed in registers a0 thru a3 respectively.
   1257   // Arguments 5..n are stored to stack using following:
   1258   //  sw(t0, CFunctionArgumentOperand(5));
   1259 
   1260   // Calls a C function and cleans up the space for arguments allocated
   1261   // by PrepareCallCFunction. The called function is not allowed to trigger a
   1262   // garbage collection, since that might move the code and invalidate the
   1263   // return address (unless this is somehow accounted for by the called
   1264   // function).
   1265   void CallCFunction(ExternalReference function, int num_arguments);
   1266   void CallCFunction(Register function, int num_arguments);
   1267   void CallCFunction(ExternalReference function,
   1268                      int num_reg_arguments,
   1269                      int num_double_arguments);
   1270   void CallCFunction(Register function,
   1271                      int num_reg_arguments,
   1272                      int num_double_arguments);
   1273   void GetCFunctionDoubleResult(const DoubleRegister dst);
   1274 
   1275   // There are two ways of passing double arguments on MIPS, depending on
   1276   // whether soft or hard floating point ABI is used. These functions
   1277   // abstract parameter passing for the three different ways we call
   1278   // C functions from generated code.
   1279   void SetCallCDoubleArguments(DoubleRegister dreg);
   1280   void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
   1281   void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
   1282 
   1283   // Calls an API function.  Allocates HandleScope, extracts returned value
   1284   // from handle and propagates exceptions.  Restores context.  stack_space
   1285   // - space to be unwound on exit (includes the call JS arguments space and
   1286   // the additional space allocated for the fast call).
   1287   void CallApiFunctionAndReturn(ExternalReference function,
   1288                                 Address function_address,
   1289                                 ExternalReference thunk_ref,
   1290                                 Register thunk_last_arg,
   1291                                 int stack_space,
   1292                                 MemOperand return_value_operand,
   1293                                 MemOperand* context_restore_operand);
   1294 
   1295   // Jump to the builtin routine.
   1296   void JumpToExternalReference(const ExternalReference& builtin,
   1297                                BranchDelaySlot bd = PROTECT);
   1298 
   1299   // Invoke specified builtin JavaScript function. Adds an entry to
   1300   // the unresolved list if the name does not resolve.
   1301   void InvokeBuiltin(Builtins::JavaScript id,
   1302                      InvokeFlag flag,
   1303                      const CallWrapper& call_wrapper = NullCallWrapper());
   1304 
   1305   // Store the code object for the given builtin in the target register and
   1306   // setup the function in a1.
   1307   void GetBuiltinEntry(Register target, Builtins::JavaScript id);
   1308 
   1309   // Store the function for the given builtin in the target register.
   1310   void GetBuiltinFunction(Register target, Builtins::JavaScript id);
   1311 
   1312   struct Unresolved {
   1313     int pc;
   1314     uint32_t flags;  // See Bootstrapper::FixupFlags decoders/encoders.
   1315     const char* name;
   1316   };
   1317 
   1318   Handle<Object> CodeObject() {
   1319     ASSERT(!code_object_.is_null());
   1320     return code_object_;
   1321   }
   1322 
   1323   // -------------------------------------------------------------------------
   1324   // StatsCounter support.
   1325 
   1326   void SetCounter(StatsCounter* counter, int value,
   1327                   Register scratch1, Register scratch2);
   1328   void IncrementCounter(StatsCounter* counter, int value,
   1329                         Register scratch1, Register scratch2);
   1330   void DecrementCounter(StatsCounter* counter, int value,
   1331                         Register scratch1, Register scratch2);
   1332 
   1333 
   1334   // -------------------------------------------------------------------------
   1335   // Debugging.
   1336 
   1337   // Calls Abort(msg) if the condition cc is not satisfied.
   1338   // Use --debug_code to enable.
   1339   void Assert(Condition cc, BailoutReason reason, Register rs, Operand rt);
   1340   void AssertFastElements(Register elements);
   1341 
   1342   // Like Assert(), but always enabled.
   1343   void Check(Condition cc, BailoutReason reason, Register rs, Operand rt);
   1344 
   1345   // Print a message to stdout and abort execution.
   1346   void Abort(BailoutReason msg);
   1347 
   1348   // Verify restrictions about code generated in stubs.
   1349   void set_generating_stub(bool value) { generating_stub_ = value; }
   1350   bool generating_stub() { return generating_stub_; }
   1351   void set_has_frame(bool value) { has_frame_ = value; }
   1352   bool has_frame() { return has_frame_; }
   1353   inline bool AllowThisStubCall(CodeStub* stub);
   1354 
   1355   // ---------------------------------------------------------------------------
   1356   // Number utilities.
   1357 
   1358   // Check whether the value of reg is a power of two and not zero. If not
   1359   // control continues at the label not_power_of_two. If reg is a power of two
   1360   // the register scratch contains the value of (reg - 1) when control falls
   1361   // through.
   1362   void JumpIfNotPowerOfTwoOrZero(Register reg,
   1363                                  Register scratch,
   1364                                  Label* not_power_of_two_or_zero);
   1365 
   1366   // -------------------------------------------------------------------------
   1367   // Smi utilities.
   1368 
   1369   void SmiTag(Register reg) {
   1370     Addu(reg, reg, reg);
   1371   }
   1372 
   1373   // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
   1374   void SmiTagCheckOverflow(Register reg, Register overflow);
   1375   void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
   1376 
   1377   void SmiTag(Register dst, Register src) {
   1378     Addu(dst, src, src);
   1379   }
   1380 
   1381   // Try to convert int32 to smi. If the value is to large, preserve
   1382   // the original value and jump to not_a_smi. Destroys scratch and
   1383   // sets flags.
   1384   void TrySmiTag(Register reg, Register scratch, Label* not_a_smi) {
   1385     TrySmiTag(reg, reg, scratch, not_a_smi);
   1386   }
   1387   void TrySmiTag(Register dst,
   1388                  Register src,
   1389                  Register scratch,
   1390                  Label* not_a_smi) {
   1391     SmiTagCheckOverflow(at, src, scratch);
   1392     BranchOnOverflow(not_a_smi, scratch);
   1393     mov(dst, at);
   1394   }
   1395 
   1396   void SmiUntag(Register reg) {
   1397     sra(reg, reg, kSmiTagSize);
   1398   }
   1399 
   1400   void SmiUntag(Register dst, Register src) {
   1401     sra(dst, src, kSmiTagSize);
   1402   }
   1403 
   1404   // Test if the register contains a smi.
   1405   inline void SmiTst(Register value, Register scratch) {
   1406     And(scratch, value, Operand(kSmiTagMask));
   1407   }
   1408   inline void NonNegativeSmiTst(Register value, Register scratch) {
   1409     And(scratch, value, Operand(kSmiTagMask | kSmiSignMask));
   1410   }
   1411 
   1412   // Untag the source value into destination and jump if source is a smi.
   1413   // Souce and destination can be the same register.
   1414   void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
   1415 
   1416   // Untag the source value into destination and jump if source is not a smi.
   1417   // Souce and destination can be the same register.
   1418   void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
   1419 
   1420   // Jump the register contains a smi.
   1421   void JumpIfSmi(Register value,
   1422                  Label* smi_label,
   1423                  Register scratch = at,
   1424                  BranchDelaySlot bd = PROTECT);
   1425 
   1426   // Jump if the register contains a non-smi.
   1427   void JumpIfNotSmi(Register value,
   1428                     Label* not_smi_label,
   1429                     Register scratch = at,
   1430                     BranchDelaySlot bd = PROTECT);
   1431 
   1432   // Jump if either of the registers contain a non-smi.
   1433   void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
   1434   // Jump if either of the registers contain a smi.
   1435   void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
   1436 
   1437   // Abort execution if argument is a smi, enabled via --debug-code.
   1438   void AssertNotSmi(Register object);
   1439   void AssertSmi(Register object);
   1440 
   1441   // Abort execution if argument is not a string, enabled via --debug-code.
   1442   void AssertString(Register object);
   1443 
   1444   // Abort execution if argument is not a name, enabled via --debug-code.
   1445   void AssertName(Register object);
   1446 
   1447   // Abort execution if reg is not the root value with the given index,
   1448   // enabled via --debug-code.
   1449   void AssertIsRoot(Register reg, Heap::RootListIndex index);
   1450 
   1451   // ---------------------------------------------------------------------------
   1452   // HeapNumber utilities.
   1453 
   1454   void JumpIfNotHeapNumber(Register object,
   1455                            Register heap_number_map,
   1456                            Register scratch,
   1457                            Label* on_not_heap_number);
   1458 
   1459   // -------------------------------------------------------------------------
   1460   // String utilities.
   1461 
   1462   // Generate code to do a lookup in the number string cache. If the number in
   1463   // the register object is found in the cache the generated code falls through
   1464   // with the result in the result register. The object and the result register
   1465   // can be the same. If the number is not found in the cache the code jumps to
   1466   // the label not_found with only the content of register object unchanged.
   1467   void LookupNumberStringCache(Register object,
   1468                                Register result,
   1469                                Register scratch1,
   1470                                Register scratch2,
   1471                                Register scratch3,
   1472                                Label* not_found);
   1473 
   1474   // Checks if both instance types are sequential ASCII strings and jumps to
   1475   // label if either is not.
   1476   void JumpIfBothInstanceTypesAreNotSequentialAscii(
   1477       Register first_object_instance_type,
   1478       Register second_object_instance_type,
   1479       Register scratch1,
   1480       Register scratch2,
   1481       Label* failure);
   1482 
   1483   // Check if instance type is sequential ASCII string and jump to label if
   1484   // it is not.
   1485   void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
   1486                                               Register scratch,
   1487                                               Label* failure);
   1488 
   1489   void JumpIfNotUniqueName(Register reg, Label* not_unique_name);
   1490 
   1491   void EmitSeqStringSetCharCheck(Register string,
   1492                                  Register index,
   1493                                  Register value,
   1494                                  Register scratch,
   1495                                  uint32_t encoding_mask);
   1496 
   1497   // Test that both first and second are sequential ASCII strings.
   1498   // Assume that they are non-smis.
   1499   void JumpIfNonSmisNotBothSequentialAsciiStrings(Register first,
   1500                                                   Register second,
   1501                                                   Register scratch1,
   1502                                                   Register scratch2,
   1503                                                   Label* failure);
   1504 
   1505   // Test that both first and second are sequential ASCII strings.
   1506   // Check that they are non-smis.
   1507   void JumpIfNotBothSequentialAsciiStrings(Register first,
   1508                                            Register second,
   1509                                            Register scratch1,
   1510                                            Register scratch2,
   1511                                            Label* failure);
   1512 
   1513   void ClampUint8(Register output_reg, Register input_reg);
   1514 
   1515   void ClampDoubleToUint8(Register result_reg,
   1516                           DoubleRegister input_reg,
   1517                           DoubleRegister temp_double_reg);
   1518 
   1519 
   1520   void LoadInstanceDescriptors(Register map, Register descriptors);
   1521   void EnumLength(Register dst, Register map);
   1522   void NumberOfOwnDescriptors(Register dst, Register map);
   1523 
   1524   template<typename Field>
   1525   void DecodeField(Register reg) {
   1526     static const int shift = Field::kShift;
   1527     static const int mask = (Field::kMask >> shift) << kSmiTagSize;
   1528     srl(reg, reg, shift);
   1529     And(reg, reg, Operand(mask));
   1530   }
   1531 
   1532   // Generates function and stub prologue code.
   1533   void Prologue(PrologueFrameMode frame_mode);
   1534 
   1535   // Activation support.
   1536   void EnterFrame(StackFrame::Type type);
   1537   void LeaveFrame(StackFrame::Type type);
   1538 
   1539   // Patch the relocated value (lui/ori pair).
   1540   void PatchRelocatedValue(Register li_location,
   1541                            Register scratch,
   1542                            Register new_value);
   1543   // Get the relocatad value (loaded data) from the lui/ori pair.
   1544   void GetRelocatedValue(Register li_location,
   1545                          Register value,
   1546                          Register scratch);
   1547 
   1548   // Expects object in a0 and returns map with validated enum cache
   1549   // in a0.  Assumes that any other register can be used as a scratch.
   1550   void CheckEnumCache(Register null_value, Label* call_runtime);
   1551 
   1552   // AllocationMemento support. Arrays may have an associated
   1553   // AllocationMemento object that can be checked for in order to pretransition
   1554   // to another type.
   1555   // On entry, receiver_reg should point to the array object.
   1556   // scratch_reg gets clobbered.
   1557   // If allocation info is present, jump to allocation_memento_present.
   1558   void TestJSArrayForAllocationMemento(
   1559       Register receiver_reg,
   1560       Register scratch_reg,
   1561       Label* no_memento_found,
   1562       Condition cond = al,
   1563       Label* allocation_memento_present = NULL);
   1564 
   1565   void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
   1566                                          Register scratch_reg,
   1567                                          Label* memento_found) {
   1568     Label no_memento_found;
   1569     TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
   1570                                     &no_memento_found, eq, memento_found);
   1571     bind(&no_memento_found);
   1572   }
   1573 
   1574   // Jumps to found label if a prototype map has dictionary elements.
   1575   void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
   1576                                         Register scratch1, Label* found);
   1577 
   1578  private:
   1579   void CallCFunctionHelper(Register function,
   1580                            int num_reg_arguments,
   1581                            int num_double_arguments);
   1582 
   1583   void BranchShort(int16_t offset, BranchDelaySlot bdslot = PROTECT);
   1584   void BranchShort(int16_t offset, Condition cond, Register rs,
   1585                    const Operand& rt,
   1586                    BranchDelaySlot bdslot = PROTECT);
   1587   void BranchShort(Label* L, BranchDelaySlot bdslot = PROTECT);
   1588   void BranchShort(Label* L, Condition cond, Register rs,
   1589                    const Operand& rt,
   1590                    BranchDelaySlot bdslot = PROTECT);
   1591   void BranchAndLinkShort(int16_t offset, BranchDelaySlot bdslot = PROTECT);
   1592   void BranchAndLinkShort(int16_t offset, Condition cond, Register rs,
   1593                           const Operand& rt,
   1594                           BranchDelaySlot bdslot = PROTECT);
   1595   void BranchAndLinkShort(Label* L, BranchDelaySlot bdslot = PROTECT);
   1596   void BranchAndLinkShort(Label* L, Condition cond, Register rs,
   1597                           const Operand& rt,
   1598                           BranchDelaySlot bdslot = PROTECT);
   1599   void J(Label* L, BranchDelaySlot bdslot);
   1600   void Jr(Label* L, BranchDelaySlot bdslot);
   1601   void Jalr(Label* L, BranchDelaySlot bdslot);
   1602 
   1603   // Helper functions for generating invokes.
   1604   void InvokePrologue(const ParameterCount& expected,
   1605                       const ParameterCount& actual,
   1606                       Handle<Code> code_constant,
   1607                       Register code_reg,
   1608                       Label* done,
   1609                       bool* definitely_mismatches,
   1610                       InvokeFlag flag,
   1611                       const CallWrapper& call_wrapper,
   1612                       CallKind call_kind);
   1613 
   1614   // Get the code for the given builtin. Returns if able to resolve
   1615   // the function in the 'resolved' flag.
   1616   Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
   1617 
   1618   void InitializeNewString(Register string,
   1619                            Register length,
   1620                            Heap::RootListIndex map_index,
   1621                            Register scratch1,
   1622                            Register scratch2);
   1623 
   1624   // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
   1625   void InNewSpace(Register object,
   1626                   Register scratch,
   1627                   Condition cond,  // eq for new space, ne otherwise.
   1628                   Label* branch);
   1629 
   1630   // Helper for finding the mark bits for an address.  Afterwards, the
   1631   // bitmap register points at the word with the mark bits and the mask
   1632   // the position of the first bit.  Leaves addr_reg unchanged.
   1633   inline void GetMarkBits(Register addr_reg,
   1634                           Register bitmap_reg,
   1635                           Register mask_reg);
   1636 
   1637   // Helper for throwing exceptions.  Compute a handler address and jump to
   1638   // it.  See the implementation for register usage.
   1639   void JumpToHandlerEntry();
   1640 
   1641   // Compute memory operands for safepoint stack slots.
   1642   static int SafepointRegisterStackIndex(int reg_code);
   1643   MemOperand SafepointRegisterSlot(Register reg);
   1644   MemOperand SafepointRegistersAndDoublesSlot(Register reg);
   1645 
   1646   bool generating_stub_;
   1647   bool has_frame_;
   1648   // This handle will be patched with the code object on installation.
   1649   Handle<Object> code_object_;
   1650 
   1651   // Needs access to SafepointRegisterStackIndex for compiled frame
   1652   // traversal.
   1653   friend class StandardFrame;
   1654 };
   1655 
   1656 
   1657 // The code patcher is used to patch (typically) small parts of code e.g. for
   1658 // debugging and other types of instrumentation. When using the code patcher
   1659 // the exact number of bytes specified must be emitted. It is not legal to emit
   1660 // relocation information. If any of these constraints are violated it causes
   1661 // an assertion to fail.
   1662 class CodePatcher {
   1663  public:
   1664   CodePatcher(byte* address, int instructions);
   1665   virtual ~CodePatcher();
   1666 
   1667   // Macro assembler to emit code.
   1668   MacroAssembler* masm() { return &masm_; }
   1669 
   1670   // Emit an instruction directly.
   1671   void Emit(Instr instr);
   1672 
   1673   // Emit an address directly.
   1674   void Emit(Address addr);
   1675 
   1676   // Change the condition part of an instruction leaving the rest of the current
   1677   // instruction unchanged.
   1678   void ChangeBranchCondition(Condition cond);
   1679 
   1680  private:
   1681   byte* address_;  // The address of the code being patched.
   1682   int size_;  // Number of bytes of the expected patch size.
   1683   MacroAssembler masm_;  // Macro assembler used to generate the code.
   1684 };
   1685 
   1686 
   1687 
   1688 #ifdef GENERATED_CODE_COVERAGE
   1689 #define CODE_COVERAGE_STRINGIFY(x) #x
   1690 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
   1691 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
   1692 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
   1693 #else
   1694 #define ACCESS_MASM(masm) masm->
   1695 #endif
   1696 
   1697 } }  // namespace v8::internal
   1698 
   1699 #endif  // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
   1700