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