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