1// Copyright 2014 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_PPC_MACRO_ASSEMBLER_PPC_H_
6#define V8_PPC_MACRO_ASSEMBLER_PPC_H_
7
8#include "src/assembler.h"
9#include "src/bailout-reason.h"
10#include "src/frames.h"
11#include "src/globals.h"
12
13namespace v8 {
14namespace internal {
15
16// Give alias names to registers for calling conventions.
17const Register kReturnRegister0 = {Register::kCode_r3};
18const Register kReturnRegister1 = {Register::kCode_r4};
19const Register kReturnRegister2 = {Register::kCode_r5};
20const Register kJSFunctionRegister = {Register::kCode_r4};
21const Register kContextRegister = {Register::kCode_r30};
22const Register kAllocateSizeRegister = {Register::kCode_r4};
23const Register kInterpreterAccumulatorRegister = {Register::kCode_r3};
24const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r15};
25const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r16};
26const Register kInterpreterDispatchTableRegister = {Register::kCode_r17};
27const Register kJavaScriptCallArgCountRegister = {Register::kCode_r3};
28const Register kJavaScriptCallNewTargetRegister = {Register::kCode_r6};
29const Register kRuntimeCallFunctionRegister = {Register::kCode_r4};
30const Register kRuntimeCallArgCountRegister = {Register::kCode_r3};
31
32// ----------------------------------------------------------------------------
33// Static helper functions
34
35// Generate a MemOperand for loading a field from an object.
36inline MemOperand FieldMemOperand(Register object, int offset) {
37  return MemOperand(object, offset - kHeapObjectTag);
38}
39
40
41// Flags used for AllocateHeapNumber
42enum TaggingMode {
43  // Tag the result.
44  TAG_RESULT,
45  // Don't tag
46  DONT_TAG_RESULT
47};
48
49
50enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
51enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
52enum PointersToHereCheck {
53  kPointersToHereMaybeInteresting,
54  kPointersToHereAreAlwaysInteresting
55};
56enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
57
58
59Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2 = no_reg,
60                                   Register reg3 = no_reg,
61                                   Register reg4 = no_reg,
62                                   Register reg5 = no_reg,
63                                   Register reg6 = no_reg);
64
65
66#ifdef DEBUG
67bool AreAliased(Register reg1, Register reg2, Register reg3 = no_reg,
68                Register reg4 = no_reg, Register reg5 = no_reg,
69                Register reg6 = no_reg, Register reg7 = no_reg,
70                Register reg8 = no_reg, Register reg9 = no_reg,
71                Register reg10 = no_reg);
72#endif
73
74// These exist to provide portability between 32 and 64bit
75#if V8_TARGET_ARCH_PPC64
76#define LoadPX ldx
77#define LoadPUX ldux
78#define StorePX stdx
79#define StorePUX stdux
80#define ShiftLeftImm sldi
81#define ShiftRightImm srdi
82#define ClearLeftImm clrldi
83#define ClearRightImm clrrdi
84#define ShiftRightArithImm sradi
85#define ShiftLeft_ sld
86#define ShiftRight_ srd
87#define ShiftRightArith srad
88#define Mul mulld
89#define Div divd
90#else
91#define LoadPX lwzx
92#define LoadPUX lwzux
93#define StorePX stwx
94#define StorePUX stwux
95#define ShiftLeftImm slwi
96#define ShiftRightImm srwi
97#define ClearLeftImm clrlwi
98#define ClearRightImm clrrwi
99#define ShiftRightArithImm srawi
100#define ShiftLeft_ slw
101#define ShiftRight_ srw
102#define ShiftRightArith sraw
103#define Mul mullw
104#define Div divw
105#endif
106
107
108// MacroAssembler implements a collection of frequently used macros.
109class MacroAssembler : public Assembler {
110 public:
111  MacroAssembler(Isolate* isolate, void* buffer, int size,
112                 CodeObjectRequired create_code_object);
113
114
115  // Returns the size of a call in instructions. Note, the value returned is
116  // only valid as long as no entries are added to the constant pool between
117  // checking the call size and emitting the actual call.
118  static int CallSize(Register target);
119  int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
120  static int CallSizeNotPredictableCodeSize(Address target,
121                                            RelocInfo::Mode rmode,
122                                            Condition cond = al);
123
124  // Jump, Call, and Ret pseudo instructions implementing inter-working.
125  void Jump(Register target);
126  void JumpToJSEntry(Register target);
127  void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al,
128            CRegister cr = cr7);
129  void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
130  void Call(Register target);
131  void CallJSEntry(Register target);
132  void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
133  int CallSize(Handle<Code> code,
134               RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
135               TypeFeedbackId ast_id = TypeFeedbackId::None(),
136               Condition cond = al);
137  void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
138            TypeFeedbackId ast_id = TypeFeedbackId::None(),
139            Condition cond = al);
140  void Ret() { blr(); }
141  void Ret(Condition cond, CRegister cr = cr7) { bclr(cond, cr); }
142
143  // Emit code that loads |parameter_index|'th parameter from the stack to
144  // the register according to the CallInterfaceDescriptor definition.
145  // |sp_to_caller_sp_offset_in_words| specifies the number of words pushed
146  // below the caller's sp.
147  template <class Descriptor>
148  void LoadParameterFromStack(
149      Register reg, typename Descriptor::ParameterIndices parameter_index,
150      int sp_to_ra_offset_in_words = 0) {
151    DCHECK(Descriptor::kPassLastArgsOnStack);
152    UNIMPLEMENTED();
153  }
154
155  // Emit code to discard a non-negative number of pointer-sized elements
156  // from the stack, clobbering only the sp register.
157  void Drop(int count);
158  void Drop(Register count, Register scratch = r0);
159
160  void Ret(int drop) {
161    Drop(drop);
162    blr();
163  }
164
165  void Call(Label* target);
166
167  // Register move. May do nothing if the registers are identical.
168  void Move(Register dst, Smi* smi) { LoadSmiLiteral(dst, smi); }
169  void Move(Register dst, Handle<Object> value);
170  void Move(Register dst, Register src, Condition cond = al);
171  void Move(DoubleRegister dst, DoubleRegister src);
172
173  void MultiPush(RegList regs, Register location = sp);
174  void MultiPop(RegList regs, Register location = sp);
175
176  void MultiPushDoubles(RegList dregs, Register location = sp);
177  void MultiPopDoubles(RegList dregs, Register location = sp);
178
179  // Load an object from the root table.
180  void LoadRoot(Register destination, Heap::RootListIndex index,
181                Condition cond = al);
182  // Store an object to the root table.
183  void StoreRoot(Register source, Heap::RootListIndex index,
184                 Condition cond = al);
185
186  // ---------------------------------------------------------------------------
187  // GC Support
188
189  void IncrementalMarkingRecordWriteHelper(Register object, Register value,
190                                           Register address);
191
192  enum RememberedSetFinalAction { kReturnAtEnd, kFallThroughAtEnd };
193
194  // Record in the remembered set the fact that we have a pointer to new space
195  // at the address pointed to by the addr register.  Only works if addr is not
196  // in new space.
197  void RememberedSetHelper(Register object,  // Used for debug code.
198                           Register addr, Register scratch,
199                           SaveFPRegsMode save_fp,
200                           RememberedSetFinalAction and_then);
201
202  void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
203                     Label* condition_met);
204
205  // Check if object is in new space.  Jumps if the object is not in new space.
206  // The register scratch can be object itself, but scratch will be clobbered.
207  void JumpIfNotInNewSpace(Register object, Register scratch, Label* branch) {
208    InNewSpace(object, scratch, eq, branch);
209  }
210
211  // Check if object is in new space.  Jumps if the object is in new space.
212  // The register scratch can be object itself, but it will be clobbered.
213  void JumpIfInNewSpace(Register object, Register scratch, Label* branch) {
214    InNewSpace(object, scratch, ne, branch);
215  }
216
217  // Check if an object has a given incremental marking color.
218  void HasColor(Register object, Register scratch0, Register scratch1,
219                Label* has_color, int first_bit, int second_bit);
220
221  void JumpIfBlack(Register object, Register scratch0, Register scratch1,
222                   Label* on_black);
223
224  // Checks the color of an object.  If the object is white we jump to the
225  // incremental marker.
226  void JumpIfWhite(Register value, Register scratch1, Register scratch2,
227                   Register scratch3, Label* value_is_white);
228
229  // Notify the garbage collector that we wrote a pointer into an object.
230  // |object| is the object being stored into, |value| is the object being
231  // stored.  value and scratch registers are clobbered by the operation.
232  // The offset is the offset from the start of the object, not the offset from
233  // the tagged HeapObject pointer.  For use with FieldMemOperand(reg, off).
234  void RecordWriteField(
235      Register object, int offset, Register value, Register scratch,
236      LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
237      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
238      SmiCheck smi_check = INLINE_SMI_CHECK,
239      PointersToHereCheck pointers_to_here_check_for_value =
240          kPointersToHereMaybeInteresting);
241
242  // As above, but the offset has the tag presubtracted.  For use with
243  // MemOperand(reg, off).
244  inline void RecordWriteContextSlot(
245      Register context, int offset, Register value, Register scratch,
246      LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
247      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
248      SmiCheck smi_check = INLINE_SMI_CHECK,
249      PointersToHereCheck pointers_to_here_check_for_value =
250          kPointersToHereMaybeInteresting) {
251    RecordWriteField(context, offset + kHeapObjectTag, value, scratch,
252                     lr_status, save_fp, remembered_set_action, smi_check,
253                     pointers_to_here_check_for_value);
254  }
255
256  // Notify the garbage collector that we wrote a code entry into a
257  // JSFunction. Only scratch is clobbered by the operation.
258  void RecordWriteCodeEntryField(Register js_function, Register code_entry,
259                                 Register scratch);
260
261  void RecordWriteForMap(Register object, Register map, Register dst,
262                         LinkRegisterStatus lr_status, SaveFPRegsMode save_fp);
263
264  // For a given |object| notify the garbage collector that the slot |address|
265  // has been written.  |value| is the object being stored. The value and
266  // address registers are clobbered by the operation.
267  void RecordWrite(
268      Register object, Register address, Register value,
269      LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
270      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
271      SmiCheck smi_check = INLINE_SMI_CHECK,
272      PointersToHereCheck pointers_to_here_check_for_value =
273          kPointersToHereMaybeInteresting);
274
275  void Push(Register src) { push(src); }
276
277  // Push a handle.
278  void Push(Handle<Object> handle);
279  void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
280
281  // Push two registers.  Pushes leftmost register first (to highest address).
282  void Push(Register src1, Register src2) {
283    StorePU(src2, MemOperand(sp, -2 * kPointerSize));
284    StoreP(src1, MemOperand(sp, kPointerSize));
285  }
286
287  // Push three registers.  Pushes leftmost register first (to highest address).
288  void Push(Register src1, Register src2, Register src3) {
289    StorePU(src3, MemOperand(sp, -3 * kPointerSize));
290    StoreP(src2, MemOperand(sp, kPointerSize));
291    StoreP(src1, MemOperand(sp, 2 * kPointerSize));
292  }
293
294  // Push four registers.  Pushes leftmost register first (to highest address).
295  void Push(Register src1, Register src2, Register src3, Register src4) {
296    StorePU(src4, MemOperand(sp, -4 * kPointerSize));
297    StoreP(src3, MemOperand(sp, kPointerSize));
298    StoreP(src2, MemOperand(sp, 2 * kPointerSize));
299    StoreP(src1, MemOperand(sp, 3 * kPointerSize));
300  }
301
302  // Push five registers.  Pushes leftmost register first (to highest address).
303  void Push(Register src1, Register src2, Register src3, Register src4,
304            Register src5) {
305    StorePU(src5, MemOperand(sp, -5 * kPointerSize));
306    StoreP(src4, MemOperand(sp, kPointerSize));
307    StoreP(src3, MemOperand(sp, 2 * kPointerSize));
308    StoreP(src2, MemOperand(sp, 3 * kPointerSize));
309    StoreP(src1, MemOperand(sp, 4 * kPointerSize));
310  }
311
312  void Pop(Register dst) { pop(dst); }
313
314  // Pop two registers. Pops rightmost register first (from lower address).
315  void Pop(Register src1, Register src2) {
316    LoadP(src2, MemOperand(sp, 0));
317    LoadP(src1, MemOperand(sp, kPointerSize));
318    addi(sp, sp, Operand(2 * kPointerSize));
319  }
320
321  // Pop three registers.  Pops rightmost register first (from lower address).
322  void Pop(Register src1, Register src2, Register src3) {
323    LoadP(src3, MemOperand(sp, 0));
324    LoadP(src2, MemOperand(sp, kPointerSize));
325    LoadP(src1, MemOperand(sp, 2 * kPointerSize));
326    addi(sp, sp, Operand(3 * kPointerSize));
327  }
328
329  // Pop four registers.  Pops rightmost register first (from lower address).
330  void Pop(Register src1, Register src2, Register src3, Register src4) {
331    LoadP(src4, MemOperand(sp, 0));
332    LoadP(src3, MemOperand(sp, kPointerSize));
333    LoadP(src2, MemOperand(sp, 2 * kPointerSize));
334    LoadP(src1, MemOperand(sp, 3 * kPointerSize));
335    addi(sp, sp, Operand(4 * kPointerSize));
336  }
337
338  // Pop five registers.  Pops rightmost register first (from lower address).
339  void Pop(Register src1, Register src2, Register src3, Register src4,
340           Register src5) {
341    LoadP(src5, MemOperand(sp, 0));
342    LoadP(src4, MemOperand(sp, kPointerSize));
343    LoadP(src3, MemOperand(sp, 2 * kPointerSize));
344    LoadP(src2, MemOperand(sp, 3 * kPointerSize));
345    LoadP(src1, MemOperand(sp, 4 * kPointerSize));
346    addi(sp, sp, Operand(5 * kPointerSize));
347  }
348
349  // Push a fixed frame, consisting of lr, fp, constant pool.
350  void PushCommonFrame(Register marker_reg = no_reg);
351
352  // Push a standard frame, consisting of lr, fp, constant pool,
353  // context and JS function
354  void PushStandardFrame(Register function_reg);
355
356  void PopCommonFrame(Register marker_reg = no_reg);
357
358  // Restore caller's frame pointer and return address prior to being
359  // overwritten by tail call stack preparation.
360  void RestoreFrameStateForTailCall();
361
362  // Push and pop the registers that can hold pointers, as defined by the
363  // RegList constant kSafepointSavedRegisters.
364  void PushSafepointRegisters();
365  void PopSafepointRegisters();
366  // Store value in register src in the safepoint stack slot for
367  // register dst.
368  void StoreToSafepointRegisterSlot(Register src, Register dst);
369  // Load the value of the src register from its safepoint stack slot
370  // into register dst.
371  void LoadFromSafepointRegisterSlot(Register dst, Register src);
372
373  // Flush the I-cache from asm code. You should use CpuFeatures::FlushICache
374  // from C.
375  // Does not handle errors.
376  void FlushICache(Register address, size_t size, Register scratch);
377
378  // If the value is a NaN, canonicalize the value else, do nothing.
379  void CanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
380  void CanonicalizeNaN(const DoubleRegister value) {
381    CanonicalizeNaN(value, value);
382  }
383
384  // Converts the integer (untagged smi) in |src| to a double, storing
385  // the result to |dst|
386  void ConvertIntToDouble(Register src, DoubleRegister dst);
387
388  // Converts the unsigned integer (untagged smi) in |src| to
389  // a double, storing the result to |dst|
390  void ConvertUnsignedIntToDouble(Register src, DoubleRegister dst);
391
392  // Converts the integer (untagged smi) in |src| to
393  // a float, storing the result in |dst|
394  void ConvertIntToFloat(Register src, DoubleRegister dst);
395
396  // Converts the unsigned integer (untagged smi) in |src| to
397  // a float, storing the result in |dst|
398  void ConvertUnsignedIntToFloat(Register src, DoubleRegister dst);
399
400#if V8_TARGET_ARCH_PPC64
401  void ConvertInt64ToFloat(Register src, DoubleRegister double_dst);
402  void ConvertInt64ToDouble(Register src, DoubleRegister double_dst);
403  void ConvertUnsignedInt64ToFloat(Register src, DoubleRegister double_dst);
404  void ConvertUnsignedInt64ToDouble(Register src, DoubleRegister double_dst);
405#endif
406
407  // Converts the double_input to an integer.  Note that, upon return,
408  // the contents of double_dst will also hold the fixed point representation.
409  void ConvertDoubleToInt64(const DoubleRegister double_input,
410#if !V8_TARGET_ARCH_PPC64
411                            const Register dst_hi,
412#endif
413                            const Register dst, const DoubleRegister double_dst,
414                            FPRoundingMode rounding_mode = kRoundToZero);
415
416#if V8_TARGET_ARCH_PPC64
417  // Converts the double_input to an unsigned integer.  Note that, upon return,
418  // the contents of double_dst will also hold the fixed point representation.
419  void ConvertDoubleToUnsignedInt64(
420      const DoubleRegister double_input, const Register dst,
421      const DoubleRegister double_dst,
422      FPRoundingMode rounding_mode = kRoundToZero);
423#endif
424
425#if !V8_TARGET_ARCH_PPC64
426  void ShiftLeftPair(Register dst_low, Register dst_high, Register src_low,
427                     Register src_high, Register scratch, Register shift);
428  void ShiftLeftPair(Register dst_low, Register dst_high, Register src_low,
429                     Register src_high, uint32_t shift);
430  void ShiftRightPair(Register dst_low, Register dst_high, Register src_low,
431                      Register src_high, Register scratch, Register shift);
432  void ShiftRightPair(Register dst_low, Register dst_high, Register src_low,
433                      Register src_high, uint32_t shift);
434  void ShiftRightAlgPair(Register dst_low, Register dst_high, Register src_low,
435                         Register src_high, Register scratch, Register shift);
436  void ShiftRightAlgPair(Register dst_low, Register dst_high, Register src_low,
437                         Register src_high, uint32_t shift);
438#endif
439
440  // Generates function and stub prologue code.
441  void StubPrologue(StackFrame::Type type, Register base = no_reg,
442                    int prologue_offset = 0);
443  void Prologue(bool code_pre_aging, Register base, int prologue_offset = 0);
444
445  // Enter exit frame.
446  // stack_space - extra stack space, used for parameters before call to C.
447  // At least one slot (for the return address) should be provided.
448  void EnterExitFrame(bool save_doubles, int stack_space = 1,
449                      StackFrame::Type frame_type = StackFrame::EXIT);
450
451  // Leave the current exit frame. Expects the return value in r0.
452  // Expect the number of values, pushed prior to the exit frame, to
453  // remove in a register (or no_reg, if there is nothing to remove).
454  void LeaveExitFrame(bool save_doubles, Register argument_count,
455                      bool restore_context,
456                      bool argument_count_is_length = false);
457
458  // Get the actual activation frame alignment for target environment.
459  static int ActivationFrameAlignment();
460
461  void LoadContext(Register dst, int context_chain_length);
462
463  // Load the global object from the current context.
464  void LoadGlobalObject(Register dst) {
465    LoadNativeContextSlot(Context::EXTENSION_INDEX, dst);
466  }
467
468  // Load the global proxy from the current context.
469  void LoadGlobalProxy(Register dst) {
470    LoadNativeContextSlot(Context::GLOBAL_PROXY_INDEX, dst);
471  }
472
473  void LoadNativeContextSlot(int index, Register dst);
474
475  // Load the initial map from the global function. The registers
476  // function and map can be the same, function is then overwritten.
477  void LoadGlobalFunctionInitialMap(Register function, Register map,
478                                    Register scratch);
479
480  void InitializeRootRegister() {
481    ExternalReference roots_array_start =
482        ExternalReference::roots_array_start(isolate());
483    mov(kRootRegister, Operand(roots_array_start));
484  }
485
486  // ----------------------------------------------------------------
487  // new PPC macro-assembler interfaces that are slightly higher level
488  // than assembler-ppc and may generate variable length sequences
489
490  // load a literal signed int value <value> to GPR <dst>
491  void LoadIntLiteral(Register dst, int value);
492
493  // load an SMI value <value> to GPR <dst>
494  void LoadSmiLiteral(Register dst, Smi* smi);
495
496  // load a literal double value <value> to FPR <result>
497  void LoadDoubleLiteral(DoubleRegister result, double value, Register scratch);
498
499  void LoadWord(Register dst, const MemOperand& mem, Register scratch);
500  void LoadWordArith(Register dst, const MemOperand& mem,
501                     Register scratch = no_reg);
502  void StoreWord(Register src, const MemOperand& mem, Register scratch);
503
504  void LoadHalfWord(Register dst, const MemOperand& mem, Register scratch);
505  void LoadHalfWordArith(Register dst, const MemOperand& mem,
506                         Register scratch = no_reg);
507  void StoreHalfWord(Register src, const MemOperand& mem, Register scratch);
508
509  void LoadByte(Register dst, const MemOperand& mem, Register scratch);
510  void StoreByte(Register src, const MemOperand& mem, Register scratch);
511
512  void LoadRepresentation(Register dst, const MemOperand& mem, Representation r,
513                          Register scratch = no_reg);
514  void StoreRepresentation(Register src, const MemOperand& mem,
515                           Representation r, Register scratch = no_reg);
516
517  void LoadDouble(DoubleRegister dst, const MemOperand& mem,
518                  Register scratch = no_reg);
519  void LoadDoubleU(DoubleRegister dst, const MemOperand& mem,
520                  Register scratch = no_reg);
521
522  void LoadSingle(DoubleRegister dst, const MemOperand& mem,
523                  Register scratch = no_reg);
524  void LoadSingleU(DoubleRegister dst, const MemOperand& mem,
525                   Register scratch = no_reg);
526
527  void StoreDouble(DoubleRegister src, const MemOperand& mem,
528                   Register scratch = no_reg);
529  void StoreDoubleU(DoubleRegister src, const MemOperand& mem,
530                   Register scratch = no_reg);
531
532  void StoreSingle(DoubleRegister src, const MemOperand& mem,
533                   Register scratch = no_reg);
534  void StoreSingleU(DoubleRegister src, const MemOperand& mem,
535                    Register scratch = no_reg);
536
537  // Move values between integer and floating point registers.
538  void MovIntToDouble(DoubleRegister dst, Register src, Register scratch);
539  void MovUnsignedIntToDouble(DoubleRegister dst, Register src,
540                              Register scratch);
541  void MovInt64ToDouble(DoubleRegister dst,
542#if !V8_TARGET_ARCH_PPC64
543                        Register src_hi,
544#endif
545                        Register src);
546#if V8_TARGET_ARCH_PPC64
547  void MovInt64ComponentsToDouble(DoubleRegister dst, Register src_hi,
548                                  Register src_lo, Register scratch);
549#endif
550  void InsertDoubleLow(DoubleRegister dst, Register src, Register scratch);
551  void InsertDoubleHigh(DoubleRegister dst, Register src, Register scratch);
552  void MovDoubleLowToInt(Register dst, DoubleRegister src);
553  void MovDoubleHighToInt(Register dst, DoubleRegister src);
554  void MovDoubleToInt64(
555#if !V8_TARGET_ARCH_PPC64
556      Register dst_hi,
557#endif
558      Register dst, DoubleRegister src);
559  void MovIntToFloat(DoubleRegister dst, Register src);
560  void MovFloatToInt(Register dst, DoubleRegister src);
561
562  void Add(Register dst, Register src, intptr_t value, Register scratch);
563  void Cmpi(Register src1, const Operand& src2, Register scratch,
564            CRegister cr = cr7);
565  void Cmpli(Register src1, const Operand& src2, Register scratch,
566             CRegister cr = cr7);
567  void Cmpwi(Register src1, const Operand& src2, Register scratch,
568             CRegister cr = cr7);
569  void Cmplwi(Register src1, const Operand& src2, Register scratch,
570              CRegister cr = cr7);
571  void And(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
572  void Or(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
573  void Xor(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
574
575  void AddSmiLiteral(Register dst, Register src, Smi* smi, Register scratch);
576  void SubSmiLiteral(Register dst, Register src, Smi* smi, Register scratch);
577  void CmpSmiLiteral(Register src1, Smi* smi, Register scratch,
578                     CRegister cr = cr7);
579  void CmplSmiLiteral(Register src1, Smi* smi, Register scratch,
580                      CRegister cr = cr7);
581  void AndSmiLiteral(Register dst, Register src, Smi* smi, Register scratch,
582                     RCBit rc = LeaveRC);
583
584  // Set new rounding mode RN to FPSCR
585  void SetRoundingMode(FPRoundingMode RN);
586
587  // reset rounding mode to default (kRoundToNearest)
588  void ResetRoundingMode();
589
590  // These exist to provide portability between 32 and 64bit
591  void LoadP(Register dst, const MemOperand& mem, Register scratch = no_reg);
592  void LoadPU(Register dst, const MemOperand& mem, Register scratch = no_reg);
593  void StoreP(Register src, const MemOperand& mem, Register scratch = no_reg);
594  void StorePU(Register src, const MemOperand& mem, Register scratch = no_reg);
595
596  // ---------------------------------------------------------------------------
597  // JavaScript invokes
598
599  // Removes current frame and its arguments from the stack preserving
600  // the arguments and a return address pushed to the stack for the next call.
601  // Both |callee_args_count| and |caller_args_count_reg| do not include
602  // receiver. |callee_args_count| is not modified, |caller_args_count_reg|
603  // is trashed.
604  void PrepareForTailCall(const ParameterCount& callee_args_count,
605                          Register caller_args_count_reg, Register scratch0,
606                          Register scratch1);
607
608  // Invoke the JavaScript function code by either calling or jumping.
609  void InvokeFunctionCode(Register function, Register new_target,
610                          const ParameterCount& expected,
611                          const ParameterCount& actual, InvokeFlag flag,
612                          const CallWrapper& call_wrapper);
613
614  // On function call, call into the debugger if necessary.
615  void CheckDebugHook(Register fun, Register new_target,
616                      const ParameterCount& expected,
617                      const ParameterCount& actual);
618
619  // Invoke the JavaScript function in the given register. Changes the
620  // current context to the context in the function before invoking.
621  void InvokeFunction(Register function, Register new_target,
622                      const ParameterCount& actual, InvokeFlag flag,
623                      const CallWrapper& call_wrapper);
624
625  void InvokeFunction(Register function, const ParameterCount& expected,
626                      const ParameterCount& actual, InvokeFlag flag,
627                      const CallWrapper& call_wrapper);
628
629  void InvokeFunction(Handle<JSFunction> function,
630                      const ParameterCount& expected,
631                      const ParameterCount& actual, InvokeFlag flag,
632                      const CallWrapper& call_wrapper);
633
634  void IsObjectJSStringType(Register object, Register scratch, Label* fail);
635
636  void IsObjectNameType(Register object, Register scratch, Label* fail);
637
638  void DebugBreak();
639  // Frame restart support
640  void MaybeDropFrames();
641
642  // Exception handling
643
644  // Push a new stack handler and link into stack handler chain.
645  void PushStackHandler();
646
647  // Unlink the stack handler on top of the stack from the stack handler chain.
648  // Must preserve the result register.
649  void PopStackHandler();
650
651  // ---------------------------------------------------------------------------
652  // Inline caching support
653
654  void GetNumberHash(Register t0, Register scratch);
655
656  inline void MarkCode(NopMarkerTypes type) { nop(type); }
657
658  // Check if the given instruction is a 'type' marker.
659  // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
660  // These instructions are generated to mark special location in the code,
661  // like some special IC code.
662  static inline bool IsMarkedCode(Instr instr, int type) {
663    DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
664    return IsNop(instr, type);
665  }
666
667
668  static inline int GetCodeMarker(Instr instr) {
669    int dst_reg_offset = 12;
670    int dst_mask = 0xf << dst_reg_offset;
671    int src_mask = 0xf;
672    int dst_reg = (instr & dst_mask) >> dst_reg_offset;
673    int src_reg = instr & src_mask;
674    uint32_t non_register_mask = ~(dst_mask | src_mask);
675    uint32_t mov_mask = al | 13 << 21;
676
677    // Return <n> if we have a mov rn rn, else return -1.
678    int type = ((instr & non_register_mask) == mov_mask) &&
679                       (dst_reg == src_reg) && (FIRST_IC_MARKER <= dst_reg) &&
680                       (dst_reg < LAST_CODE_MARKER)
681                   ? src_reg
682                   : -1;
683    DCHECK((type == -1) ||
684           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
685    return type;
686  }
687
688
689  // ---------------------------------------------------------------------------
690  // Allocation support
691
692  // Allocate an object in new space or old space. The object_size is
693  // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
694  // is passed. If the space is exhausted control continues at the gc_required
695  // label. The allocated object is returned in result. If the flag
696  // tag_allocated_object is true the result is tagged as as a heap object.
697  // All registers are clobbered also when control continues at the gc_required
698  // label.
699  void Allocate(int object_size, Register result, Register scratch1,
700                Register scratch2, Label* gc_required, AllocationFlags flags);
701
702  void Allocate(Register object_size, Register result, Register result_end,
703                Register scratch, Label* gc_required, AllocationFlags flags);
704
705  // FastAllocate is right now only used for folded allocations. It just
706  // increments the top pointer without checking against limit. This can only
707  // be done if it was proved earlier that the allocation will succeed.
708  void FastAllocate(int object_size, Register result, Register scratch1,
709                    Register scratch2, AllocationFlags flags);
710
711  void FastAllocate(Register object_size, Register result, Register result_end,
712                    Register scratch, AllocationFlags flags);
713
714  // Allocates a heap number or jumps to the gc_required label if the young
715  // space is full and a scavenge is needed. All registers are clobbered also
716  // when control continues at the gc_required label.
717  void AllocateHeapNumber(Register result, Register scratch1, Register scratch2,
718                          Register heap_number_map, Label* gc_required,
719                          MutableMode mode = IMMUTABLE);
720  void AllocateHeapNumberWithValue(Register result, DoubleRegister value,
721                                   Register scratch1, Register scratch2,
722                                   Register heap_number_map,
723                                   Label* gc_required);
724
725  // Allocate and initialize a JSValue wrapper with the specified {constructor}
726  // and {value}.
727  void AllocateJSValue(Register result, Register constructor, Register value,
728                       Register scratch1, Register scratch2,
729                       Label* gc_required);
730
731  // Initialize fields with filler values.  |count| fields starting at
732  // |current_address| are overwritten with the value in |filler|.  At the end
733  // the loop, |current_address| points at the next uninitialized field.
734  // |count| is assumed to be non-zero.
735  void InitializeNFieldsWithFiller(Register current_address, Register count,
736                                   Register filler);
737
738  // Initialize fields with filler values.  Fields starting at |current_address|
739  // not including |end_address| are overwritten with the value in |filler|.  At
740  // the end the loop, |current_address| takes the value of |end_address|.
741  void InitializeFieldsWithFiller(Register current_address,
742                                  Register end_address, Register filler);
743
744  // ---------------------------------------------------------------------------
745  // Support functions.
746
747  // Machine code version of Map::GetConstructor().
748  // |temp| holds |result|'s map when done, and |temp2| its instance type.
749  void GetMapConstructor(Register result, Register map, Register temp,
750                         Register temp2);
751
752  // Compare object type for heap object.  heap_object contains a non-Smi
753  // whose object type should be compared with the given type.  This both
754  // sets the flags and leaves the object type in the type_reg register.
755  // It leaves the map in the map register (unless the type_reg and map register
756  // are the same register).  It leaves the heap object in the heap_object
757  // register unless the heap_object register is the same register as one of the
758  // other registers.
759  // Type_reg can be no_reg. In that case ip is used.
760  void CompareObjectType(Register heap_object, Register map, Register type_reg,
761                         InstanceType type);
762
763  // Compare instance type in a map.  map contains a valid map object whose
764  // object type should be compared with the given type.  This both
765  // sets the flags and leaves the object type in the type_reg register.
766  void CompareInstanceType(Register map, Register type_reg, InstanceType type);
767
768  // Compare an object's map with the specified map and its transitioned
769  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
770  // set with result of map compare. If multiple map compares are required, the
771  // compare sequences branches to early_success.
772  void CompareMap(Register obj, Register scratch, Handle<Map> map,
773                  Label* early_success);
774
775  // As above, but the map of the object is already loaded into the register
776  // which is preserved by the code generated.
777  void CompareMap(Register obj_map, Handle<Map> map, Label* early_success);
778
779  // Check if the map of an object is equal to a specified map and branch to
780  // label if not. Skip the smi check if not required (object is known to be a
781  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
782  // against maps that are ElementsKind transition maps of the specified map.
783  void CheckMap(Register obj, Register scratch, Handle<Map> map, Label* fail,
784                SmiCheckType smi_check_type);
785
786
787  void CheckMap(Register obj, Register scratch, Heap::RootListIndex index,
788                Label* fail, SmiCheckType smi_check_type);
789
790
791  // Check if the map of an object is equal to a specified weak map and branch
792  // to a specified target if equal. Skip the smi check if not required
793  // (object is known to be a heap object)
794  void DispatchWeakMap(Register obj, Register scratch1, Register scratch2,
795                       Handle<WeakCell> cell, Handle<Code> success,
796                       SmiCheckType smi_check_type);
797
798  // Compare the given value and the value of weak cell.
799  void CmpWeakValue(Register value, Handle<WeakCell> cell, Register scratch,
800                    CRegister cr = cr7);
801
802  void GetWeakValue(Register value, Handle<WeakCell> cell);
803
804  // Load the value of the weak cell in the value register. Branch to the given
805  // miss label if the weak cell was cleared.
806  void LoadWeakValue(Register value, Handle<WeakCell> cell, Label* miss);
807
808  // Compare the object in a register to a value from the root list.
809  // Uses the ip register as scratch.
810  void CompareRoot(Register obj, Heap::RootListIndex index);
811  void PushRoot(Heap::RootListIndex index) {
812    LoadRoot(r0, index);
813    Push(r0);
814  }
815
816  // Compare the object in a register to a value and jump if they are equal.
817  void JumpIfRoot(Register with, Heap::RootListIndex index, Label* if_equal) {
818    CompareRoot(with, index);
819    beq(if_equal);
820  }
821
822  // Compare the object in a register to a value and jump if they are not equal.
823  void JumpIfNotRoot(Register with, Heap::RootListIndex index,
824                     Label* if_not_equal) {
825    CompareRoot(with, index);
826    bne(if_not_equal);
827  }
828
829  // Load and check the instance type of an object for being a string.
830  // Loads the type into the second argument register.
831  // Returns a condition that will be enabled if the object was a string.
832  Condition IsObjectStringType(Register obj, Register type) {
833    LoadP(type, FieldMemOperand(obj, HeapObject::kMapOffset));
834    lbz(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
835    andi(r0, type, Operand(kIsNotStringMask));
836    DCHECK_EQ(0u, kStringTag);
837    return eq;
838  }
839
840  // Get the number of least significant bits from a register
841  void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
842  void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
843
844  // Load the value of a smi object into a double register.
845  void SmiToDouble(DoubleRegister value, Register smi);
846
847  // Check if a double can be exactly represented as a signed 32-bit integer.
848  // CR_EQ in cr7 is set if true.
849  void TestDoubleIsInt32(DoubleRegister double_input, Register scratch1,
850                         Register scratch2, DoubleRegister double_scratch);
851
852  // Check if a double is equal to -0.0.
853  // CR_EQ in cr7 holds the result.
854  void TestDoubleIsMinusZero(DoubleRegister input, Register scratch1,
855                             Register scratch2);
856
857  // Check the sign of a double.
858  // CR_LT in cr7 holds the result.
859  void TestDoubleSign(DoubleRegister input, Register scratch);
860  void TestHeapNumberSign(Register input, Register scratch);
861
862  // Try to convert a double to a signed 32-bit integer.
863  // CR_EQ in cr7 is set and result assigned if the conversion is exact.
864  void TryDoubleToInt32Exact(Register result, DoubleRegister double_input,
865                             Register scratch, DoubleRegister double_scratch);
866
867  // Floor a double and writes the value to the result register.
868  // Go to exact if the conversion is exact (to be able to test -0),
869  // fall through calling code if an overflow occurred, else go to done.
870  // In return, input_high is loaded with high bits of input.
871  void TryInt32Floor(Register result, DoubleRegister double_input,
872                     Register input_high, Register scratch,
873                     DoubleRegister double_scratch, Label* done, Label* exact);
874
875  // Performs a truncating conversion of a floating point number as used by
876  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
877  // succeeds, otherwise falls through if result is saturated. On return
878  // 'result' either holds answer, or is clobbered on fall through.
879  //
880  // Only public for the test code in test-code-stubs-arm.cc.
881  void TryInlineTruncateDoubleToI(Register result, DoubleRegister input,
882                                  Label* done);
883
884  // Performs a truncating conversion of a floating point number as used by
885  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
886  // Exits with 'result' holding the answer.
887  void TruncateDoubleToI(Register result, DoubleRegister double_input);
888
889  // Performs a truncating conversion of a heap number as used by
890  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
891  // must be different registers.  Exits with 'result' holding the answer.
892  void TruncateHeapNumberToI(Register result, Register object);
893
894  // Converts the smi or heap number in object to an int32 using the rules
895  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
896  // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
897  // different registers.
898  void TruncateNumberToI(Register object, Register result,
899                         Register heap_number_map, Register scratch1,
900                         Label* not_int32);
901
902  // Overflow handling functions.
903  // Usage: call the appropriate arithmetic function and then call one of the
904  // flow control functions with the corresponding label.
905
906  // Compute dst = left + right, setting condition codes. dst may be same as
907  // either left or right (or a unique register). left and right must not be
908  // the same register.
909  void AddAndCheckForOverflow(Register dst, Register left, Register right,
910                              Register overflow_dst, Register scratch = r0);
911  void AddAndCheckForOverflow(Register dst, Register left, intptr_t right,
912                              Register overflow_dst, Register scratch = r0);
913
914  // Compute dst = left - right, setting condition codes. dst may be same as
915  // either left or right (or a unique register). left and right must not be
916  // the same register.
917  void SubAndCheckForOverflow(Register dst, Register left, Register right,
918                              Register overflow_dst, Register scratch = r0);
919
920  void BranchOnOverflow(Label* label) { blt(label, cr0); }
921
922  void BranchOnNoOverflow(Label* label) { bge(label, cr0); }
923
924  void RetOnOverflow(void) { Ret(lt, cr0); }
925
926  void RetOnNoOverflow(void) { Ret(ge, cr0); }
927
928  // ---------------------------------------------------------------------------
929  // Runtime calls
930
931  // Call a code stub.
932  void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None(),
933                Condition cond = al);
934
935  // Call a code stub.
936  void TailCallStub(CodeStub* stub, Condition cond = al);
937
938  // Call a runtime routine.
939  void CallRuntime(const Runtime::Function* f, int num_arguments,
940                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
941  void CallRuntimeSaveDoubles(Runtime::FunctionId fid) {
942    const Runtime::Function* function = Runtime::FunctionForId(fid);
943    CallRuntime(function, function->nargs, kSaveFPRegs);
944  }
945
946  // Convenience function: Same as above, but takes the fid instead.
947  void CallRuntime(Runtime::FunctionId fid,
948                   SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
949    const Runtime::Function* function = Runtime::FunctionForId(fid);
950    CallRuntime(function, function->nargs, save_doubles);
951  }
952
953  // Convenience function: Same as above, but takes the fid instead.
954  void CallRuntime(Runtime::FunctionId fid, int num_arguments,
955                   SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
956    CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
957  }
958
959  // Convenience function: call an external reference.
960  void CallExternalReference(const ExternalReference& ext, int num_arguments);
961
962  // Convenience function: tail call a runtime routine (jump).
963  void TailCallRuntime(Runtime::FunctionId fid);
964
965  int CalculateStackPassedWords(int num_reg_arguments,
966                                int num_double_arguments);
967
968  // Before calling a C-function from generated code, align arguments on stack.
969  // After aligning the frame, non-register arguments must be stored in
970  // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
971  // are word sized. If double arguments are used, this function assumes that
972  // all double arguments are stored before core registers; otherwise the
973  // correct alignment of the double values is not guaranteed.
974  // Some compilers/platforms require the stack to be aligned when calling
975  // C++ code.
976  // Needs a scratch register to do some arithmetic. This register will be
977  // trashed.
978  void PrepareCallCFunction(int num_reg_arguments, int num_double_registers,
979                            Register scratch);
980  void PrepareCallCFunction(int num_reg_arguments, Register scratch);
981
982  // There are two ways of passing double arguments on ARM, depending on
983  // whether soft or hard floating point ABI is used. These functions
984  // abstract parameter passing for the three different ways we call
985  // C functions from generated code.
986  void MovToFloatParameter(DoubleRegister src);
987  void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
988  void MovToFloatResult(DoubleRegister src);
989
990  // Calls a C function and cleans up the space for arguments allocated
991  // by PrepareCallCFunction. The called function is not allowed to trigger a
992  // garbage collection, since that might move the code and invalidate the
993  // return address (unless this is somehow accounted for by the called
994  // function).
995  void CallCFunction(ExternalReference function, int num_arguments);
996  void CallCFunction(Register function, int num_arguments);
997  void CallCFunction(ExternalReference function, int num_reg_arguments,
998                     int num_double_arguments);
999  void CallCFunction(Register function, int num_reg_arguments,
1000                     int num_double_arguments);
1001
1002  void MovFromFloatParameter(DoubleRegister dst);
1003  void MovFromFloatResult(DoubleRegister dst);
1004
1005  // Jump to a runtime routine.
1006  void JumpToExternalReference(const ExternalReference& builtin,
1007                               bool builtin_exit_frame = false);
1008
1009  Handle<Object> CodeObject() {
1010    DCHECK(!code_object_.is_null());
1011    return code_object_;
1012  }
1013
1014
1015  // Emit code for a truncating division by a constant. The dividend register is
1016  // unchanged and ip gets clobbered. Dividend and result must be different.
1017  void TruncatingDiv(Register result, Register dividend, int32_t divisor);
1018
1019  // ---------------------------------------------------------------------------
1020  // StatsCounter support
1021
1022  void SetCounter(StatsCounter* counter, int value, Register scratch1,
1023                  Register scratch2);
1024  void IncrementCounter(StatsCounter* counter, int value, Register scratch1,
1025                        Register scratch2);
1026  void DecrementCounter(StatsCounter* counter, int value, Register scratch1,
1027                        Register scratch2);
1028
1029
1030  // ---------------------------------------------------------------------------
1031  // Debugging
1032
1033  // Calls Abort(msg) if the condition cond is not satisfied.
1034  // Use --debug_code to enable.
1035  void Assert(Condition cond, BailoutReason reason, CRegister cr = cr7);
1036  void AssertFastElements(Register elements);
1037
1038  // Like Assert(), but always enabled.
1039  void Check(Condition cond, BailoutReason reason, CRegister cr = cr7);
1040
1041  // Print a message to stdout and abort execution.
1042  void Abort(BailoutReason reason);
1043
1044  // Verify restrictions about code generated in stubs.
1045  void set_generating_stub(bool value) { generating_stub_ = value; }
1046  bool generating_stub() { return generating_stub_; }
1047  void set_has_frame(bool value) { has_frame_ = value; }
1048  bool has_frame() { return has_frame_; }
1049  inline bool AllowThisStubCall(CodeStub* stub);
1050
1051  // ---------------------------------------------------------------------------
1052  // Number utilities
1053
1054  // Check whether the value of reg is a power of two and not zero. If not
1055  // control continues at the label not_power_of_two. If reg is a power of two
1056  // the register scratch contains the value of (reg - 1) when control falls
1057  // through.
1058  void JumpIfNotPowerOfTwoOrZero(Register reg, Register scratch,
1059                                 Label* not_power_of_two_or_zero);
1060  // Check whether the value of reg is a power of two and not zero.
1061  // Control falls through if it is, with scratch containing the mask
1062  // value (reg - 1).
1063  // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
1064  // zero or negative, or jumps to the 'not_power_of_two' label if the value is
1065  // strictly positive but not a power of two.
1066  void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, Register scratch,
1067                                       Label* zero_and_neg,
1068                                       Label* not_power_of_two);
1069
1070  // ---------------------------------------------------------------------------
1071  // Bit testing/extraction
1072  //
1073  // Bit numbering is such that the least significant bit is bit 0
1074  // (for consistency between 32/64-bit).
1075
1076  // Extract consecutive bits (defined by rangeStart - rangeEnd) from src
1077  // and, if !test, shift them into the least significant bits of dst.
1078  inline void ExtractBitRange(Register dst, Register src, int rangeStart,
1079                              int rangeEnd, RCBit rc = LeaveRC,
1080                              bool test = false) {
1081    DCHECK(rangeStart >= rangeEnd && rangeStart < kBitsPerPointer);
1082    int rotate = (rangeEnd == 0) ? 0 : kBitsPerPointer - rangeEnd;
1083    int width = rangeStart - rangeEnd + 1;
1084    if (rc == SetRC && rangeStart < 16 && (rangeEnd == 0 || test)) {
1085      // Prefer faster andi when applicable.
1086      andi(dst, src, Operand(((1 << width) - 1) << rangeEnd));
1087    } else {
1088#if V8_TARGET_ARCH_PPC64
1089      rldicl(dst, src, rotate, kBitsPerPointer - width, rc);
1090#else
1091      rlwinm(dst, src, rotate, kBitsPerPointer - width, kBitsPerPointer - 1,
1092             rc);
1093#endif
1094    }
1095  }
1096
1097  inline void ExtractBit(Register dst, Register src, uint32_t bitNumber,
1098                         RCBit rc = LeaveRC, bool test = false) {
1099    ExtractBitRange(dst, src, bitNumber, bitNumber, rc, test);
1100  }
1101
1102  // Extract consecutive bits (defined by mask) from src and place them
1103  // into the least significant bits of dst.
1104  inline void ExtractBitMask(Register dst, Register src, uintptr_t mask,
1105                             RCBit rc = LeaveRC, bool test = false) {
1106    int start = kBitsPerPointer - 1;
1107    int end;
1108    uintptr_t bit = (1L << start);
1109
1110    while (bit && (mask & bit) == 0) {
1111      start--;
1112      bit >>= 1;
1113    }
1114    end = start;
1115    bit >>= 1;
1116
1117    while (bit && (mask & bit)) {
1118      end--;
1119      bit >>= 1;
1120    }
1121
1122    // 1-bits in mask must be contiguous
1123    DCHECK(bit == 0 || (mask & ((bit << 1) - 1)) == 0);
1124
1125    ExtractBitRange(dst, src, start, end, rc, test);
1126  }
1127
1128  // Test single bit in value.
1129  inline void TestBit(Register value, int bitNumber, Register scratch = r0) {
1130    ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC, true);
1131  }
1132
1133  // Test consecutive bit range in value.  Range is defined by
1134  // rangeStart - rangeEnd.
1135  inline void TestBitRange(Register value, int rangeStart, int rangeEnd,
1136                           Register scratch = r0) {
1137    ExtractBitRange(scratch, value, rangeStart, rangeEnd, SetRC, true);
1138  }
1139
1140  // Test consecutive bit range in value.  Range is defined by mask.
1141  inline void TestBitMask(Register value, uintptr_t mask,
1142                          Register scratch = r0) {
1143    ExtractBitMask(scratch, value, mask, SetRC, true);
1144  }
1145
1146
1147  // ---------------------------------------------------------------------------
1148  // Smi utilities
1149
1150  // Shift left by kSmiShift
1151  void SmiTag(Register reg, RCBit rc = LeaveRC) { SmiTag(reg, reg, rc); }
1152  void SmiTag(Register dst, Register src, RCBit rc = LeaveRC) {
1153    ShiftLeftImm(dst, src, Operand(kSmiShift), rc);
1154  }
1155
1156#if !V8_TARGET_ARCH_PPC64
1157  // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
1158  void SmiTagCheckOverflow(Register reg, Register overflow);
1159  void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
1160
1161  inline void JumpIfNotSmiCandidate(Register value, Register scratch,
1162                                    Label* not_smi_label) {
1163    // High bits must be identical to fit into an Smi
1164    STATIC_ASSERT(kSmiShift == 1);
1165    addis(scratch, value, Operand(0x40000000u >> 16));
1166    cmpi(scratch, Operand::Zero());
1167    blt(not_smi_label);
1168  }
1169#endif
1170  inline void TestUnsignedSmiCandidate(Register value, Register scratch) {
1171    // The test is different for unsigned int values. Since we need
1172    // the value to be in the range of a positive smi, we can't
1173    // handle any of the high bits being set in the value.
1174    TestBitRange(value, kBitsPerPointer - 1, kBitsPerPointer - 1 - kSmiShift,
1175                 scratch);
1176  }
1177  inline void JumpIfNotUnsignedSmiCandidate(Register value, Register scratch,
1178                                            Label* not_smi_label) {
1179    TestUnsignedSmiCandidate(value, scratch);
1180    bne(not_smi_label, cr0);
1181  }
1182
1183  void SmiUntag(Register reg, RCBit rc = LeaveRC) { SmiUntag(reg, reg, rc); }
1184
1185  void SmiUntag(Register dst, Register src, RCBit rc = LeaveRC) {
1186    ShiftRightArithImm(dst, src, kSmiShift, rc);
1187  }
1188
1189  void SmiToPtrArrayOffset(Register dst, Register src) {
1190#if V8_TARGET_ARCH_PPC64
1191    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kPointerSizeLog2);
1192    ShiftRightArithImm(dst, src, kSmiShift - kPointerSizeLog2);
1193#else
1194    STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kPointerSizeLog2);
1195    ShiftLeftImm(dst, src, Operand(kPointerSizeLog2 - kSmiShift));
1196#endif
1197  }
1198
1199  void SmiToByteArrayOffset(Register dst, Register src) { SmiUntag(dst, src); }
1200
1201  void SmiToShortArrayOffset(Register dst, Register src) {
1202#if V8_TARGET_ARCH_PPC64
1203    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 1);
1204    ShiftRightArithImm(dst, src, kSmiShift - 1);
1205#else
1206    STATIC_ASSERT(kSmiTag == 0 && kSmiShift == 1);
1207    if (!dst.is(src)) {
1208      mr(dst, src);
1209    }
1210#endif
1211  }
1212
1213  void SmiToIntArrayOffset(Register dst, Register src) {
1214#if V8_TARGET_ARCH_PPC64
1215    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 2);
1216    ShiftRightArithImm(dst, src, kSmiShift - 2);
1217#else
1218    STATIC_ASSERT(kSmiTag == 0 && kSmiShift < 2);
1219    ShiftLeftImm(dst, src, Operand(2 - kSmiShift));
1220#endif
1221  }
1222
1223#define SmiToFloatArrayOffset SmiToIntArrayOffset
1224
1225  void SmiToDoubleArrayOffset(Register dst, Register src) {
1226#if V8_TARGET_ARCH_PPC64
1227    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kDoubleSizeLog2);
1228    ShiftRightArithImm(dst, src, kSmiShift - kDoubleSizeLog2);
1229#else
1230    STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kDoubleSizeLog2);
1231    ShiftLeftImm(dst, src, Operand(kDoubleSizeLog2 - kSmiShift));
1232#endif
1233  }
1234
1235  void SmiToArrayOffset(Register dst, Register src, int elementSizeLog2) {
1236    if (kSmiShift < elementSizeLog2) {
1237      ShiftLeftImm(dst, src, Operand(elementSizeLog2 - kSmiShift));
1238    } else if (kSmiShift > elementSizeLog2) {
1239      ShiftRightArithImm(dst, src, kSmiShift - elementSizeLog2);
1240    } else if (!dst.is(src)) {
1241      mr(dst, src);
1242    }
1243  }
1244
1245  void IndexToArrayOffset(Register dst, Register src, int elementSizeLog2,
1246                          bool isSmi) {
1247    if (isSmi) {
1248      SmiToArrayOffset(dst, src, elementSizeLog2);
1249    } else {
1250      ShiftLeftImm(dst, src, Operand(elementSizeLog2));
1251    }
1252  }
1253
1254  // Untag the source value into destination and jump if source is a smi.
1255  // Souce and destination can be the same register.
1256  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
1257
1258  inline void TestIfSmi(Register value, Register scratch) {
1259    TestBitRange(value, kSmiTagSize - 1, 0, scratch);
1260  }
1261
1262  inline void TestIfPositiveSmi(Register value, Register scratch) {
1263#if V8_TARGET_ARCH_PPC64
1264    rldicl(scratch, value, 1, kBitsPerPointer - (1 + kSmiTagSize), SetRC);
1265#else
1266    rlwinm(scratch, value, 1, kBitsPerPointer - (1 + kSmiTagSize),
1267           kBitsPerPointer - 1, SetRC);
1268#endif
1269  }
1270
1271  // Jump the register contains a smi.
1272  inline void JumpIfSmi(Register value, Label* smi_label) {
1273    TestIfSmi(value, r0);
1274    beq(smi_label, cr0);  // branch if SMI
1275  }
1276  // Jump if either of the registers contain a non-smi.
1277  inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
1278    TestIfSmi(value, r0);
1279    bne(not_smi_label, cr0);
1280  }
1281  // Jump if either of the registers contain a non-smi.
1282  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
1283  // Jump if either of the registers contain a smi.
1284  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
1285
1286  // Abort execution if argument is a number, enabled via --debug-code.
1287  void AssertNotNumber(Register object);
1288
1289  // Abort execution if argument is a smi, enabled via --debug-code.
1290  void AssertNotSmi(Register object);
1291  void AssertSmi(Register object);
1292
1293
1294#if V8_TARGET_ARCH_PPC64
1295  inline void TestIfInt32(Register value, Register scratch,
1296                          CRegister cr = cr7) {
1297    // High bits must be identical to fit into an 32-bit integer
1298    extsw(scratch, value);
1299    cmp(scratch, value, cr);
1300  }
1301#else
1302  inline void TestIfInt32(Register hi_word, Register lo_word, Register scratch,
1303                          CRegister cr = cr7) {
1304    // High bits must be identical to fit into an 32-bit integer
1305    srawi(scratch, lo_word, 31);
1306    cmp(scratch, hi_word, cr);
1307  }
1308#endif
1309
1310#if V8_TARGET_ARCH_PPC64
1311  // Ensure it is permissable to read/write int value directly from
1312  // upper half of the smi.
1313  STATIC_ASSERT(kSmiTag == 0);
1314  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
1315#endif
1316#if V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN
1317#define SmiWordOffset(offset) (offset + kPointerSize / 2)
1318#else
1319#define SmiWordOffset(offset) offset
1320#endif
1321
1322  // Abort execution if argument is not a string, enabled via --debug-code.
1323  void AssertString(Register object);
1324
1325  // Abort execution if argument is not a name, enabled via --debug-code.
1326  void AssertName(Register object);
1327
1328  void AssertFunction(Register object);
1329
1330  // Abort execution if argument is not a JSBoundFunction,
1331  // enabled via --debug-code.
1332  void AssertBoundFunction(Register object);
1333
1334  // Abort execution if argument is not a JSGeneratorObject,
1335  // enabled via --debug-code.
1336  void AssertGeneratorObject(Register object);
1337
1338  // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
1339  void AssertReceiver(Register object);
1340
1341  // Abort execution if argument is not undefined or an AllocationSite, enabled
1342  // via --debug-code.
1343  void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1344
1345  // Abort execution if reg is not the root value with the given index,
1346  // enabled via --debug-code.
1347  void AssertIsRoot(Register reg, Heap::RootListIndex index);
1348
1349  // ---------------------------------------------------------------------------
1350  // HeapNumber utilities
1351
1352  void JumpIfNotHeapNumber(Register object, Register heap_number_map,
1353                           Register scratch, Label* on_not_heap_number);
1354
1355  // ---------------------------------------------------------------------------
1356  // String utilities
1357
1358  // Checks if both objects are sequential one-byte strings and jumps to label
1359  // if either is not. Assumes that neither object is a smi.
1360  void JumpIfNonSmisNotBothSequentialOneByteStrings(Register object1,
1361                                                    Register object2,
1362                                                    Register scratch1,
1363                                                    Register scratch2,
1364                                                    Label* failure);
1365
1366  // Checks if both objects are sequential one-byte strings and jumps to label
1367  // if either is not.
1368  void JumpIfNotBothSequentialOneByteStrings(Register first, Register second,
1369                                             Register scratch1,
1370                                             Register scratch2,
1371                                             Label* not_flat_one_byte_strings);
1372
1373  // Checks if both instance types are sequential one-byte strings and jumps to
1374  // label if either is not.
1375  void JumpIfBothInstanceTypesAreNotSequentialOneByte(
1376      Register first_object_instance_type, Register second_object_instance_type,
1377      Register scratch1, Register scratch2, Label* failure);
1378
1379  void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name);
1380
1381  void EmitSeqStringSetCharCheck(Register string, Register index,
1382                                 Register value, uint32_t encoding_mask);
1383
1384  // ---------------------------------------------------------------------------
1385  // Patching helpers.
1386
1387  // Decode offset from constant pool load instruction(s).
1388  // Caller must place the instruction word at <location> in <result>.
1389  void DecodeConstantPoolOffset(Register result, Register location);
1390
1391  void ClampUint8(Register output_reg, Register input_reg);
1392
1393  // Saturate a value into 8-bit unsigned integer
1394  //   if input_value < 0, output_value is 0
1395  //   if input_value > 255, output_value is 255
1396  //   otherwise output_value is the (int)input_value (round to nearest)
1397  void ClampDoubleToUint8(Register result_reg, DoubleRegister input_reg,
1398                          DoubleRegister temp_double_reg);
1399
1400
1401  void LoadInstanceDescriptors(Register map, Register descriptors);
1402  void EnumLength(Register dst, Register map);
1403  void NumberOfOwnDescriptors(Register dst, Register map);
1404  void LoadAccessor(Register dst, Register holder, int accessor_index,
1405                    AccessorComponent accessor);
1406
1407  template <typename Field>
1408  void DecodeField(Register dst, Register src, RCBit rc = LeaveRC) {
1409    ExtractBitRange(dst, src, Field::kShift + Field::kSize - 1, Field::kShift,
1410                    rc);
1411  }
1412
1413  template <typename Field>
1414  void DecodeField(Register reg, RCBit rc = LeaveRC) {
1415    DecodeField<Field>(reg, reg, rc);
1416  }
1417
1418  template <typename Field>
1419  void DecodeFieldToSmi(Register dst, Register src) {
1420#if V8_TARGET_ARCH_PPC64
1421    DecodeField<Field>(dst, src);
1422    SmiTag(dst);
1423#else
1424    // 32-bit can do this in one instruction:
1425    int start = Field::kSize + kSmiShift - 1;
1426    int end = kSmiShift;
1427    int rotate = kSmiShift - Field::kShift;
1428    if (rotate < 0) {
1429      rotate += kBitsPerPointer;
1430    }
1431    rlwinm(dst, src, rotate, kBitsPerPointer - start - 1,
1432           kBitsPerPointer - end - 1);
1433#endif
1434  }
1435
1436  template <typename Field>
1437  void DecodeFieldToSmi(Register reg) {
1438    DecodeFieldToSmi<Field>(reg, reg);
1439  }
1440
1441  // Load the type feedback vector from a JavaScript frame.
1442  void EmitLoadFeedbackVector(Register vector);
1443
1444  // Activation support.
1445  void EnterFrame(StackFrame::Type type,
1446                  bool load_constant_pool_pointer_reg = false);
1447  // Returns the pc offset at which the frame ends.
1448  int LeaveFrame(StackFrame::Type type, int stack_adjustment = 0);
1449
1450  void EnterBuiltinFrame(Register context, Register target, Register argc);
1451  void LeaveBuiltinFrame(Register context, Register target, Register argc);
1452
1453  // Expects object in r3 and returns map with validated enum cache
1454  // in r3.  Assumes that any other register can be used as a scratch.
1455  void CheckEnumCache(Label* call_runtime);
1456
1457  // AllocationMemento support. Arrays may have an associated
1458  // AllocationMemento object that can be checked for in order to pretransition
1459  // to another type.
1460  // On entry, receiver_reg should point to the array object.
1461  // scratch_reg gets clobbered.
1462  // If allocation info is present, condition flags are set to eq.
1463  void TestJSArrayForAllocationMemento(Register receiver_reg,
1464                                       Register scratch_reg,
1465                                       Register scratch2_reg,
1466                                       Label* no_memento_found);
1467
1468  // Loads the constant pool pointer (kConstantPoolRegister).
1469  void LoadConstantPoolPointerRegisterFromCodeTargetAddress(
1470      Register code_target_address);
1471  void LoadConstantPoolPointerRegister();
1472  void LoadConstantPoolPointerRegister(Register base, int code_entry_delta = 0);
1473
1474  void AbortConstantPoolBuilding() {
1475#ifdef DEBUG
1476    // Avoid DCHECK(!is_linked()) failure in ~Label()
1477    bind(ConstantPoolPosition());
1478#endif
1479  }
1480
1481 private:
1482  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1483
1484  void CallCFunctionHelper(Register function, int num_reg_arguments,
1485                           int num_double_arguments);
1486
1487  void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al,
1488            CRegister cr = cr7);
1489
1490  // Helper functions for generating invokes.
1491  void InvokePrologue(const ParameterCount& expected,
1492                      const ParameterCount& actual, Label* done,
1493                      bool* definitely_mismatches, InvokeFlag flag,
1494                      const CallWrapper& call_wrapper);
1495
1496  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
1497  void InNewSpace(Register object, Register scratch,
1498                  Condition cond,  // eq for new space, ne otherwise.
1499                  Label* branch);
1500
1501  // Helper for finding the mark bits for an address.  Afterwards, the
1502  // bitmap register points at the word with the mark bits and the mask
1503  // the position of the first bit.  Leaves addr_reg unchanged.
1504  inline void GetMarkBits(Register addr_reg, Register bitmap_reg,
1505                          Register mask_reg);
1506
1507  static const RegList kSafepointSavedRegisters;
1508  static const int kNumSafepointSavedRegisters;
1509
1510  // Compute memory operands for safepoint stack slots.
1511  static int SafepointRegisterStackIndex(int reg_code);
1512  MemOperand SafepointRegisterSlot(Register reg);
1513  MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1514
1515  bool generating_stub_;
1516  bool has_frame_;
1517  // This handle will be patched with the code object on installation.
1518  Handle<Object> code_object_;
1519
1520  // Needs access to SafepointRegisterStackIndex for compiled frame
1521  // traversal.
1522  friend class StandardFrame;
1523};
1524
1525
1526// The code patcher is used to patch (typically) small parts of code e.g. for
1527// debugging and other types of instrumentation. When using the code patcher
1528// the exact number of bytes specified must be emitted. It is not legal to emit
1529// relocation information. If any of these constraints are violated it causes
1530// an assertion to fail.
1531class CodePatcher {
1532 public:
1533  enum FlushICache { FLUSH, DONT_FLUSH };
1534
1535  CodePatcher(Isolate* isolate, byte* address, int instructions,
1536              FlushICache flush_cache = FLUSH);
1537  ~CodePatcher();
1538
1539  // Macro assembler to emit code.
1540  MacroAssembler* masm() { return &masm_; }
1541
1542  // Emit an instruction directly.
1543  void Emit(Instr instr);
1544
1545  // Emit the condition part of an instruction leaving the rest of the current
1546  // instruction unchanged.
1547  void EmitCondition(Condition cond);
1548
1549 private:
1550  byte* address_;            // The address of the code being patched.
1551  int size_;                 // Number of bytes of the expected patch size.
1552  MacroAssembler masm_;      // Macro assembler used to generate the code.
1553  FlushICache flush_cache_;  // Whether to flush the I cache after patching.
1554};
1555
1556
1557// -----------------------------------------------------------------------------
1558// Static helper functions.
1559
1560inline MemOperand ContextMemOperand(Register context, int index = 0) {
1561  return MemOperand(context, Context::SlotOffset(index));
1562}
1563
1564
1565inline MemOperand NativeContextMemOperand() {
1566  return ContextMemOperand(cp, Context::NATIVE_CONTEXT_INDEX);
1567}
1568
1569#define ACCESS_MASM(masm) masm->
1570
1571}  // namespace internal
1572}  // namespace v8
1573
1574#endif  // V8_PPC_MACRO_ASSEMBLER_PPC_H_
1575