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
12namespace v8 {
13namespace internal {
14
15// Forward declaration.
16class 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.
32enum LeaveExitFrameMode {
33  EMIT_RETURN = true,
34  NO_EMIT_RETURN = false
35};
36
37// Flags used for AllocateHeapNumber
38enum 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.
46enum 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.
56enum BranchDelaySlot {
57  USE_DELAY_SLOT,
58  PROTECT
59};
60
61// Flags used for the li macro-assembler function.
62enum 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
78enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
79enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
80enum PointersToHereCheck {
81  kPointersToHereMaybeInteresting,
82  kPointersToHereAreAlwaysInteresting
83};
84enum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved };
85
86Register 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
93bool 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
106inline MemOperand ContextOperand(Register context, int index) {
107  return MemOperand(context, Context::SlotOffset(index));
108}
109
110
111inline MemOperand GlobalObjectOperand()  {
112  return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX);
113}
114
115
116// Generate a MemOperand for loading a field from an object.
117inline MemOperand FieldMemOperand(Register object, int offset) {
118  return MemOperand(object, offset - kHeapObjectTag);
119}
120
121
122inline 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
129inline 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.
139inline 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.
148class 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, \
1211const 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.
1736class 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