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 INCLUDED_FROM_MACRO_ASSEMBLER_H
6#error This header must be included via macro-assembler.h
7#endif
8
9#ifndef V8_CODEGEN_S390_MACRO_ASSEMBLER_S390_H_
10#define V8_CODEGEN_S390_MACRO_ASSEMBLER_S390_H_
11
12#include "src/codegen/bailout-reason.h"
13#include "src/codegen/s390/assembler-s390.h"
14#include "src/common/globals.h"
15#include "src/objects/contexts.h"
16
17namespace v8 {
18namespace internal {
19
20enum class StackLimitKind { kInterruptStackLimit, kRealStackLimit };
21
22// ----------------------------------------------------------------------------
23// Static helper functions
24
25// Generate a MemOperand for loading a field from an object.
26inline MemOperand FieldMemOperand(Register object, int offset) {
27  return MemOperand(object, offset - kHeapObjectTag);
28}
29
30// Generate a MemOperand for loading a field from an object.
31inline MemOperand FieldMemOperand(Register object, Register index, int offset) {
32  return MemOperand(object, index, offset - kHeapObjectTag);
33}
34
35enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
36
37Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2 = no_reg,
38                                   Register reg3 = no_reg,
39                                   Register reg4 = no_reg,
40                                   Register reg5 = no_reg,
41                                   Register reg6 = no_reg);
42
43class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
44 public:
45  using TurboAssemblerBase::TurboAssemblerBase;
46
47  void CallBuiltin(Builtin builtin);
48  void TailCallBuiltin(Builtin builtin);
49  void AtomicCmpExchangeHelper(Register addr, Register output,
50                               Register old_value, Register new_value,
51                               int start, int end, int shift_amount, int offset,
52                               Register temp0, Register temp1);
53  void AtomicCmpExchangeU8(Register addr, Register output, Register old_value,
54                           Register new_value, Register temp0, Register temp1);
55  void AtomicCmpExchangeU16(Register addr, Register output, Register old_value,
56                            Register new_value, Register temp0, Register temp1);
57  void AtomicExchangeHelper(Register addr, Register value, Register output,
58                            int start, int end, int shift_amount, int offset,
59                            Register scratch);
60  void AtomicExchangeU8(Register addr, Register value, Register output,
61                        Register scratch);
62  void AtomicExchangeU16(Register addr, Register value, Register output,
63                         Register scratch);
64
65  void DoubleMax(DoubleRegister result_reg, DoubleRegister left_reg,
66                 DoubleRegister right_reg);
67  void DoubleMin(DoubleRegister result_reg, DoubleRegister left_reg,
68                 DoubleRegister right_reg);
69  void FloatMax(DoubleRegister result_reg, DoubleRegister left_reg,
70                DoubleRegister right_reg);
71  void FloatMin(DoubleRegister result_reg, DoubleRegister left_reg,
72                DoubleRegister right_reg);
73  void CeilF32(DoubleRegister dst, DoubleRegister src);
74  void CeilF64(DoubleRegister dst, DoubleRegister src);
75  void FloorF32(DoubleRegister dst, DoubleRegister src);
76  void FloorF64(DoubleRegister dst, DoubleRegister src);
77  void TruncF32(DoubleRegister dst, DoubleRegister src);
78  void TruncF64(DoubleRegister dst, DoubleRegister src);
79  void NearestIntF32(DoubleRegister dst, DoubleRegister src);
80  void NearestIntF64(DoubleRegister dst, DoubleRegister src);
81
82  void LoadFromConstantsTable(Register destination, int constant_index) final;
83  void LoadRootRegisterOffset(Register destination, intptr_t offset) final;
84  void LoadRootRelative(Register destination, int32_t offset) final;
85
86  // Jump, Call, and Ret pseudo instructions implementing inter-working.
87  void Jump(Register target, Condition cond = al);
88  void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al);
89  void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
90  void Jump(const ExternalReference& reference);
91  // Jump the register contains a smi.
92  inline void JumpIfSmi(Register value, Label* smi_label) {
93    TestIfSmi(value);
94    beq(smi_label /*, cr0*/);  // branch if SMI
95  }
96  void JumpIfEqual(Register x, int32_t y, Label* dest);
97  void JumpIfLessThan(Register x, int32_t y, Label* dest);
98
99  void LoadMap(Register destination, Register object);
100
101  void Call(Register target);
102  void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
103  void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
104            Condition cond = al);
105  void Ret() { b(r14); }
106  void Ret(Condition cond) { b(cond, r14); }
107
108  void CallForDeoptimization(Builtin target, int deopt_id, Label* exit,
109                             DeoptimizeKind kind, Label* ret,
110                             Label* jump_deoptimization_entry_label);
111
112  // Emit code to discard a non-negative number of pointer-sized elements
113  // from the stack, clobbering only the sp register.
114  void Drop(int count);
115  void Drop(Register count, Register scratch = r0);
116
117  void Ret(int drop) {
118    Drop(drop);
119    Ret();
120  }
121
122  void Call(Label* target);
123
124  // Load the builtin given by the Smi in |builtin_index| into the same
125  // register.
126  void LoadEntryFromBuiltinIndex(Register builtin_index);
127  void LoadEntryFromBuiltin(Builtin builtin, Register destination);
128  MemOperand EntryFromBuiltinAsOperand(Builtin builtin);
129  void LoadCodeObjectEntry(Register destination, Register code_object);
130  void CallCodeObject(Register code_object);
131  void JumpCodeObject(Register code_object,
132                      JumpMode jump_mode = JumpMode::kJump);
133
134  void CallBuiltinByIndex(Register builtin_index);
135
136  // Register move. May do nothing if the registers are identical.
137  void Move(Register dst, Smi smi) { LoadSmiLiteral(dst, smi); }
138  void Move(Register dst, Handle<HeapObject> source,
139            RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT);
140  void Move(Register dst, ExternalReference reference);
141  void Move(Register dst, const MemOperand& src);
142  void Move(Register dst, Register src, Condition cond = al);
143  void Move(DoubleRegister dst, DoubleRegister src);
144
145  void MoveChar(const MemOperand& opnd1, const MemOperand& opnd2,
146                const Operand& length);
147
148  void CompareLogicalChar(const MemOperand& opnd1, const MemOperand& opnd2,
149                          const Operand& length);
150
151  void ExclusiveOrChar(const MemOperand& opnd1, const MemOperand& opnd2,
152                       const Operand& length);
153
154  void RotateInsertSelectBits(Register dst, Register src,
155                              const Operand& startBit, const Operand& endBit,
156                              const Operand& shiftAmt, bool zeroBits);
157
158  void BranchRelativeOnIdxHighP(Register dst, Register inc, Label* L);
159
160  void MaybeSaveRegisters(RegList registers);
161  void MaybeRestoreRegisters(RegList registers);
162
163  void CallEphemeronKeyBarrier(Register object, Register slot_address,
164                               SaveFPRegsMode fp_mode);
165
166  void CallRecordWriteStubSaveRegisters(
167      Register object, Register slot_address,
168      RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
169      StubCallMode mode = StubCallMode::kCallBuiltinPointer);
170  void CallRecordWriteStub(
171      Register object, Register slot_address,
172      RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
173      StubCallMode mode = StubCallMode::kCallBuiltinPointer);
174
175  void MultiPush(RegList regs, Register location = sp);
176  void MultiPop(RegList regs, Register location = sp);
177
178  void MultiPushDoubles(DoubleRegList dregs, Register location = sp);
179  void MultiPopDoubles(DoubleRegList dregs, Register location = sp);
180
181  void MultiPushV128(DoubleRegList dregs, Register scratch,
182                     Register location = sp);
183  void MultiPopV128(DoubleRegList dregs, Register scratch,
184                    Register location = sp);
185
186  void MultiPushF64OrV128(DoubleRegList dregs, Register scratch,
187                          Register location = sp);
188  void MultiPopF64OrV128(DoubleRegList dregs, Register scratch,
189                         Register location = sp);
190
191  // Calculate how much stack space (in bytes) are required to store caller
192  // registers excluding those specified in the arguments.
193  int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
194                                      Register exclusion1 = no_reg,
195                                      Register exclusion2 = no_reg,
196                                      Register exclusion3 = no_reg) const;
197
198  // Push caller saved registers on the stack, and return the number of bytes
199  // stack pointer is adjusted.
200  int PushCallerSaved(SaveFPRegsMode fp_mode, Register scratch,
201                      Register exclusion1 = no_reg,
202                      Register exclusion2 = no_reg,
203                      Register exclusion3 = no_reg);
204  // Restore caller saved registers from the stack, and return the number of
205  // bytes stack pointer is adjusted.
206  int PopCallerSaved(SaveFPRegsMode fp_mode, Register scratch,
207                     Register exclusion1 = no_reg, Register exclusion2 = no_reg,
208                     Register exclusion3 = no_reg);
209
210  // Load an object from the root table.
211  void LoadRoot(Register destination, RootIndex index) override {
212    LoadRoot(destination, index, al);
213  }
214  void LoadRoot(Register destination, RootIndex index, Condition cond);
215  //--------------------------------------------------------------------------
216  // S390 Macro Assemblers for Instructions
217  //--------------------------------------------------------------------------
218
219  // Arithmetic Operations
220
221  // Add (Register - Immediate)
222  void AddS32(Register dst, const Operand& imm);
223  void AddS64(Register dst, const Operand& imm);
224  void AddS32(Register dst, Register src, const Operand& imm);
225  void AddS64(Register dst, Register src, const Operand& imm);
226  void AddS32(Register dst, Register src, int32_t imm);
227  void AddS64(Register dst, Register src, int32_t imm);
228
229  // Add (Register - Register)
230  void AddS32(Register dst, Register src);
231  void AddS64(Register dst, Register src);
232  void AddS32(Register dst, Register src1, Register src2);
233  void AddS64(Register dst, Register src1, Register src2);
234
235  // Add (Register - Mem)
236  void AddS32(Register dst, const MemOperand& opnd);
237  void AddS64(Register dst, const MemOperand& opnd);
238
239  // Add (Mem - Immediate)
240  void AddS32(const MemOperand& opnd, const Operand& imm);
241  void AddS64(const MemOperand& opnd, const Operand& imm);
242
243  // Add Logical (Register - Register)
244  void AddU32(Register dst, Register src1, Register src2);
245
246  // Add Logical (Register - Immediate)
247  void AddU32(Register dst, const Operand& imm);
248  void AddU64(Register dst, const Operand& imm);
249  void AddU64(Register dst, Register src1, Register src2);
250
251  // Add Logical (Register - Mem)
252  void AddU32(Register dst, const MemOperand& opnd);
253  void AddU64(Register dst, const MemOperand& opnd);
254
255  // Subtract (Register - Immediate)
256  void SubS32(Register dst, const Operand& imm);
257  void SubS64(Register dst, const Operand& imm);
258  void SubS32(Register dst, Register src, const Operand& imm);
259  void SubS64(Register dst, Register src, const Operand& imm);
260  void SubS32(Register dst, Register src, int32_t imm);
261  void SubS64(Register dst, Register src, int32_t imm);
262
263  // Subtract (Register - Register)
264  void SubS32(Register dst, Register src);
265  void SubS64(Register dst, Register src);
266  void SubS32(Register dst, Register src1, Register src2);
267  void SubS64(Register dst, Register src1, Register src2);
268
269  // Subtract (Register - Mem)
270  void SubS32(Register dst, const MemOperand& opnd);
271  void SubS64(Register dst, const MemOperand& opnd);
272  void LoadAndSub32(Register dst, Register src, const MemOperand& opnd);
273  void LoadAndSub64(Register dst, Register src, const MemOperand& opnd);
274
275  // Subtract Logical (Register - Mem)
276  void SubU32(Register dst, const MemOperand& opnd);
277  void SubU64(Register dst, const MemOperand& opnd);
278  // Subtract Logical 32-bit
279  void SubU32(Register dst, Register src1, Register src2);
280
281  // Multiply
282  void MulS64(Register dst, const Operand& opnd);
283  void MulS64(Register dst, Register src);
284  void MulS64(Register dst, const MemOperand& opnd);
285  void MulS64(Register dst, Register src1, Register src2) {
286    if (CpuFeatures::IsSupported(MISC_INSTR_EXT2)) {
287      msgrkc(dst, src1, src2);
288    } else {
289      if (dst == src2) {
290        MulS64(dst, src1);
291      } else if (dst == src1) {
292        MulS64(dst, src2);
293      } else {
294        mov(dst, src1);
295        MulS64(dst, src2);
296      }
297    }
298  }
299
300  void MulS32(Register dst, const MemOperand& src1);
301  void MulS32(Register dst, Register src1);
302  void MulS32(Register dst, const Operand& src1);
303  void MulS32(Register dst, Register src1, Register src2) {
304    if (CpuFeatures::IsSupported(MISC_INSTR_EXT2)) {
305      msrkc(dst, src1, src2);
306    } else {
307      if (dst == src2) {
308        MulS32(dst, src1);
309      } else if (dst == src1) {
310        MulS32(dst, src2);
311      } else {
312        mov(dst, src1);
313        MulS32(dst, src2);
314      }
315    }
316  }
317
318  void MulHighS32(Register dst, Register src1, const MemOperand& src2);
319  void MulHighS32(Register dst, Register src1, Register src2);
320  void MulHighS32(Register dst, Register src1, const Operand& src2);
321  void MulHighU32(Register dst, Register src1, const MemOperand& src2);
322  void MulHighU32(Register dst, Register src1, Register src2);
323  void MulHighU32(Register dst, Register src1, const Operand& src2);
324  void Mul32WithOverflowIfCCUnequal(Register dst, Register src1,
325                                    const MemOperand& src2);
326  void Mul32WithOverflowIfCCUnequal(Register dst, Register src1, Register src2);
327  void Mul32WithOverflowIfCCUnequal(Register dst, Register src1,
328                                    const Operand& src2);
329  // Divide
330  void DivS32(Register dst, Register src1, const MemOperand& src2);
331  void DivS32(Register dst, Register src1, Register src2);
332  void DivU32(Register dst, Register src1, const MemOperand& src2);
333  void DivU32(Register dst, Register src1, Register src2);
334  void DivS64(Register dst, Register src1, const MemOperand& src2);
335  void DivS64(Register dst, Register src1, Register src2);
336  void DivU64(Register dst, Register src1, const MemOperand& src2);
337  void DivU64(Register dst, Register src1, Register src2);
338
339  // Mod
340  void ModS32(Register dst, Register src1, const MemOperand& src2);
341  void ModS32(Register dst, Register src1, Register src2);
342  void ModU32(Register dst, Register src1, const MemOperand& src2);
343  void ModU32(Register dst, Register src1, Register src2);
344  void ModS64(Register dst, Register src1, const MemOperand& src2);
345  void ModS64(Register dst, Register src1, Register src2);
346  void ModU64(Register dst, Register src1, const MemOperand& src2);
347  void ModU64(Register dst, Register src1, Register src2);
348
349  // Square root
350  void Sqrt(DoubleRegister result, DoubleRegister input);
351  void Sqrt(DoubleRegister result, const MemOperand& input);
352
353  // Compare
354  void CmpS32(Register src1, Register src2);
355  void CmpS64(Register src1, Register src2);
356  void CmpS32(Register dst, const Operand& opnd);
357  void CmpS64(Register dst, const Operand& opnd);
358  void CmpS32(Register dst, const MemOperand& opnd);
359  void CmpS64(Register dst, const MemOperand& opnd);
360  void CmpAndSwap(Register old_val, Register new_val, const MemOperand& opnd);
361  void CmpAndSwap64(Register old_val, Register new_val, const MemOperand& opnd);
362  // TODO(john.yan): remove this
363  template <class T>
364  void CmpP(Register src1, T src2) {
365    CmpS64(src1, src2);
366  }
367
368  // Compare Logical
369  void CmpU32(Register src1, Register src2);
370  void CmpU64(Register src1, Register src2);
371  void CmpU32(Register src1, const Operand& opnd);
372  void CmpU64(Register src1, const Operand& opnd);
373  void CmpU32(Register dst, const MemOperand& opnd);
374  void CmpU64(Register dst, const MemOperand& opnd);
375
376  // Load
377  void LoadU64(Register dst, const MemOperand& mem, Register scratch = no_reg);
378  void LoadS32(Register dst, const MemOperand& opnd, Register scratch = no_reg);
379  void LoadS32(Register dst, Register src);
380  void LoadU32(Register dst, const MemOperand& opnd, Register scratch = no_reg);
381  void LoadU32(Register dst, Register src);
382  void LoadU16(Register dst, const MemOperand& opnd);
383  void LoadU16(Register dst, Register src);
384  void LoadS16(Register dst, Register src);
385  void LoadS16(Register dst, const MemOperand& mem, Register scratch = no_reg);
386  void LoadS8(Register dst, const MemOperand& opnd);
387  void LoadS8(Register dst, Register src);
388  void LoadU8(Register dst, const MemOperand& opnd);
389  void LoadU8(Register dst, Register src);
390  void LoadV128(Simd128Register dst, const MemOperand& mem, Register scratch);
391  void LoadF64(DoubleRegister dst, const MemOperand& opnd);
392  void LoadF32(DoubleRegister dst, const MemOperand& opnd);
393  // LE Load
394  void LoadU64LE(Register dst, const MemOperand& mem,
395                 Register scratch = no_reg);
396  void LoadS32LE(Register dst, const MemOperand& opnd,
397                 Register scratch = no_reg);
398  void LoadU32LE(Register dst, const MemOperand& opnd,
399                 Register scratch = no_reg);
400  void LoadU16LE(Register dst, const MemOperand& opnd);
401  void LoadS16LE(Register dst, const MemOperand& opnd);
402  void LoadV128LE(DoubleRegister dst, const MemOperand& mem, Register scratch0,
403                  Register scratch1);
404  void LoadF64LE(DoubleRegister dst, const MemOperand& opnd, Register scratch);
405  void LoadF32LE(DoubleRegister dst, const MemOperand& opnd, Register scratch);
406  // Vector LE Load and Transform instructions.
407  void LoadAndSplat64x2LE(Simd128Register dst, const MemOperand& mem,
408                          Register scratch);
409  void LoadAndSplat32x4LE(Simd128Register dst, const MemOperand& mem,
410                          Register scratch);
411  void LoadAndSplat16x8LE(Simd128Register dst, const MemOperand& me,
412                          Register scratch);
413  void LoadAndSplat8x16LE(Simd128Register dst, const MemOperand& mem,
414                          Register scratch);
415  void LoadAndExtend8x8ULE(Simd128Register dst, const MemOperand& mem,
416                           Register scratch);
417  void LoadAndExtend8x8SLE(Simd128Register dst, const MemOperand& mem,
418                           Register scratch);
419  void LoadAndExtend16x4ULE(Simd128Register dst, const MemOperand& mem,
420                            Register scratch);
421  void LoadAndExtend16x4SLE(Simd128Register dst, const MemOperand& mem,
422                            Register scratch);
423  void LoadAndExtend32x2ULE(Simd128Register dst, const MemOperand& mem,
424                            Register scratch);
425  void LoadAndExtend32x2SLE(Simd128Register dst, const MemOperand& mem,
426                            Register scratch);
427  void LoadV32ZeroLE(Simd128Register dst, const MemOperand& mem,
428                     Register scratch);
429  void LoadV64ZeroLE(Simd128Register dst, const MemOperand& mem,
430                     Register scratch);
431  void LoadLane8LE(Simd128Register dst, const MemOperand& mem, int lane,
432                   Register scratch);
433  void LoadLane16LE(Simd128Register dst, const MemOperand& mem, int lane,
434                    Register scratch);
435  void LoadLane32LE(Simd128Register dst, const MemOperand& mem, int lane,
436                    Register scratch);
437  void LoadLane64LE(Simd128Register dst, const MemOperand& mem, int lane,
438                    Register scratch);
439  void StoreLane8LE(Simd128Register src, const MemOperand& mem, int lane,
440                    Register scratch);
441  void StoreLane16LE(Simd128Register src, const MemOperand& mem, int lane,
442                     Register scratch);
443  void StoreLane32LE(Simd128Register src, const MemOperand& mem, int lane,
444                     Register scratch);
445  void StoreLane64LE(Simd128Register src, const MemOperand& mem, int lane,
446                     Register scratch);
447
448  // Load And Test
449  void LoadAndTest32(Register dst, Register src);
450  void LoadAndTestP(Register dst, Register src);
451
452  void LoadAndTest32(Register dst, const MemOperand& opnd);
453  void LoadAndTestP(Register dst, const MemOperand& opnd);
454
455  // Store
456  void StoreU64(const MemOperand& mem, const Operand& opnd,
457                Register scratch = no_reg);
458  void StoreU64(Register src, const MemOperand& mem, Register scratch = no_reg);
459  void StoreU32(Register src, const MemOperand& mem, Register scratch = no_reg);
460
461  void StoreU16(Register src, const MemOperand& mem, Register scratch = r0);
462  void StoreU8(Register src, const MemOperand& mem, Register scratch = r0);
463  void StoreF64(DoubleRegister dst, const MemOperand& opnd);
464  void StoreF32(DoubleRegister dst, const MemOperand& opnd);
465  void StoreV128(Simd128Register src, const MemOperand& mem, Register scratch);
466
467  // Store LE
468  void StoreU64LE(Register src, const MemOperand& mem,
469                  Register scratch = no_reg);
470  void StoreU32LE(Register src, const MemOperand& mem,
471                  Register scratch = no_reg);
472
473  void StoreU16LE(Register src, const MemOperand& mem, Register scratch = r0);
474  void StoreF64LE(DoubleRegister src, const MemOperand& opnd, Register scratch);
475  void StoreF32LE(DoubleRegister src, const MemOperand& opnd, Register scratch);
476  void StoreV128LE(Simd128Register src, const MemOperand& mem,
477                   Register scratch1, Register scratch2);
478
479  void AddF32(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs);
480  void SubF32(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs);
481  void MulF32(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs);
482  void DivF32(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs);
483
484  void AddF64(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs);
485  void SubF64(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs);
486  void MulF64(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs);
487  void DivF64(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs);
488
489  void AddFloat32(DoubleRegister dst, const MemOperand& opnd,
490                  DoubleRegister scratch);
491  void AddFloat64(DoubleRegister dst, const MemOperand& opnd,
492                  DoubleRegister scratch);
493  void SubFloat32(DoubleRegister dst, const MemOperand& opnd,
494                  DoubleRegister scratch);
495  void SubFloat64(DoubleRegister dst, const MemOperand& opnd,
496                  DoubleRegister scratch);
497  void MulFloat32(DoubleRegister dst, const MemOperand& opnd,
498                  DoubleRegister scratch);
499  void MulFloat64(DoubleRegister dst, const MemOperand& opnd,
500                  DoubleRegister scratch);
501  void DivFloat32(DoubleRegister dst, const MemOperand& opnd,
502                  DoubleRegister scratch);
503  void DivFloat64(DoubleRegister dst, const MemOperand& opnd,
504                  DoubleRegister scratch);
505  void LoadF32AsF64(DoubleRegister dst, const MemOperand& opnd,
506                    DoubleRegister scratch);
507
508  // Load On Condition
509  void LoadOnConditionP(Condition cond, Register dst, Register src);
510
511  void LoadPositiveP(Register result, Register input);
512  void LoadPositive32(Register result, Register input);
513
514  void Branch(Condition c, const Operand& opnd);
515  void BranchOnCount(Register r1, Label* l);
516
517  // Shifts
518  void ShiftLeftU32(Register dst, Register src, Register val,
519                    const Operand& val2 = Operand::Zero());
520  void ShiftLeftU32(Register dst, Register src, const Operand& val);
521  void ShiftLeftU64(Register dst, Register src, Register val,
522                    const Operand& val2 = Operand::Zero());
523  void ShiftLeftU64(Register dst, Register src, const Operand& val);
524  void ShiftRightU32(Register dst, Register src, Register val,
525                     const Operand& val2 = Operand::Zero());
526  void ShiftRightU32(Register dst, Register src, const Operand& val);
527  void ShiftRightU64(Register dst, Register src, Register val,
528                     const Operand& val2 = Operand::Zero());
529  void ShiftRightU64(Register dst, Register src, const Operand& val);
530  void ShiftRightS32(Register dst, Register src, Register shift,
531                     const Operand& val2 = Operand::Zero());
532  void ShiftRightS32(Register dst, Register src, const Operand& val);
533  void ShiftRightS64(Register dst, Register src, Register shift,
534                     const Operand& val2 = Operand::Zero());
535  void ShiftRightS64(Register dst, Register src, const Operand& val);
536
537  void ClearRightImm(Register dst, Register src, const Operand& val);
538
539  // Bitwise operations
540  void And(Register dst, Register src);
541  void AndP(Register dst, Register src);
542  void And(Register dst, Register src1, Register src2);
543  void AndP(Register dst, Register src1, Register src2);
544  void And(Register dst, const MemOperand& opnd);
545  void AndP(Register dst, const MemOperand& opnd);
546  void And(Register dst, const Operand& opnd);
547  void AndP(Register dst, const Operand& opnd);
548  void And(Register dst, Register src, const Operand& opnd);
549  void AndP(Register dst, Register src, const Operand& opnd);
550  void Or(Register dst, Register src);
551  void OrP(Register dst, Register src);
552  void Or(Register dst, Register src1, Register src2);
553  void OrP(Register dst, Register src1, Register src2);
554  void Or(Register dst, const MemOperand& opnd);
555  void OrP(Register dst, const MemOperand& opnd);
556  void Or(Register dst, const Operand& opnd);
557  void OrP(Register dst, const Operand& opnd);
558  void Or(Register dst, Register src, const Operand& opnd);
559  void OrP(Register dst, Register src, const Operand& opnd);
560  void Xor(Register dst, Register src);
561  void XorP(Register dst, Register src);
562  void Xor(Register dst, Register src1, Register src2);
563  void XorP(Register dst, Register src1, Register src2);
564  void Xor(Register dst, const MemOperand& opnd);
565  void XorP(Register dst, const MemOperand& opnd);
566  void Xor(Register dst, const Operand& opnd);
567  void XorP(Register dst, const Operand& opnd);
568  void Xor(Register dst, Register src, const Operand& opnd);
569  void XorP(Register dst, Register src, const Operand& opnd);
570  void Popcnt32(Register dst, Register src);
571  void Not32(Register dst, Register src = no_reg);
572  void Not64(Register dst, Register src = no_reg);
573  void NotP(Register dst, Register src = no_reg);
574
575#ifdef V8_TARGET_ARCH_S390X
576  void Popcnt64(Register dst, Register src);
577#endif
578
579  void mov(Register dst, const Operand& src);
580  void mov(Register dst, Register src);
581
582  void CleanUInt32(Register x) {
583#ifdef V8_TARGET_ARCH_S390X
584    llgfr(x, x);
585#endif
586  }
587
588  void push(DoubleRegister src) {
589    lay(sp, MemOperand(sp, -kSystemPointerSize));
590    StoreF64(src, MemOperand(sp));
591  }
592
593  void push(Register src) {
594    lay(sp, MemOperand(sp, -kSystemPointerSize));
595    StoreU64(src, MemOperand(sp));
596  }
597
598  void pop(DoubleRegister dst) {
599    LoadF64(dst, MemOperand(sp));
600    la(sp, MemOperand(sp, kSystemPointerSize));
601  }
602
603  void pop(Register dst) {
604    LoadU64(dst, MemOperand(sp));
605    la(sp, MemOperand(sp, kSystemPointerSize));
606  }
607
608  void pop() { la(sp, MemOperand(sp, kSystemPointerSize)); }
609
610  void Push(Register src) { push(src); }
611
612  // Push a handle.
613  void Push(Handle<HeapObject> handle);
614  void Push(Smi smi);
615
616  // Push two registers.  Pushes leftmost register first (to highest address).
617  void Push(Register src1, Register src2) {
618    lay(sp, MemOperand(sp, -kSystemPointerSize * 2));
619    StoreU64(src1, MemOperand(sp, kSystemPointerSize));
620    StoreU64(src2, MemOperand(sp, 0));
621  }
622
623  // Push three registers.  Pushes leftmost register first (to highest address).
624  void Push(Register src1, Register src2, Register src3) {
625    lay(sp, MemOperand(sp, -kSystemPointerSize * 3));
626    StoreU64(src1, MemOperand(sp, kSystemPointerSize * 2));
627    StoreU64(src2, MemOperand(sp, kSystemPointerSize));
628    StoreU64(src3, MemOperand(sp, 0));
629  }
630
631  // Push four registers.  Pushes leftmost register first (to highest address).
632  void Push(Register src1, Register src2, Register src3, Register src4) {
633    lay(sp, MemOperand(sp, -kSystemPointerSize * 4));
634    StoreU64(src1, MemOperand(sp, kSystemPointerSize * 3));
635    StoreU64(src2, MemOperand(sp, kSystemPointerSize * 2));
636    StoreU64(src3, MemOperand(sp, kSystemPointerSize));
637    StoreU64(src4, MemOperand(sp, 0));
638  }
639
640  // Push five registers.  Pushes leftmost register first (to highest address).
641  void Push(Register src1, Register src2, Register src3, Register src4,
642            Register src5) {
643    DCHECK(src1 != src2);
644    DCHECK(src1 != src3);
645    DCHECK(src2 != src3);
646    DCHECK(src1 != src4);
647    DCHECK(src2 != src4);
648    DCHECK(src3 != src4);
649    DCHECK(src1 != src5);
650    DCHECK(src2 != src5);
651    DCHECK(src3 != src5);
652    DCHECK(src4 != src5);
653
654    lay(sp, MemOperand(sp, -kSystemPointerSize * 5));
655    StoreU64(src1, MemOperand(sp, kSystemPointerSize * 4));
656    StoreU64(src2, MemOperand(sp, kSystemPointerSize * 3));
657    StoreU64(src3, MemOperand(sp, kSystemPointerSize * 2));
658    StoreU64(src4, MemOperand(sp, kSystemPointerSize));
659    StoreU64(src5, MemOperand(sp, 0));
660  }
661
662  enum PushArrayOrder { kNormal, kReverse };
663  void PushArray(Register array, Register size, Register scratch,
664                 Register scratch2, PushArrayOrder order = kNormal);
665
666  void Pop(Register dst) { pop(dst); }
667
668  // Pop two registers. Pops rightmost register first (from lower address).
669  void Pop(Register src1, Register src2) {
670    LoadU64(src2, MemOperand(sp, 0));
671    LoadU64(src1, MemOperand(sp, kSystemPointerSize));
672    la(sp, MemOperand(sp, 2 * kSystemPointerSize));
673  }
674
675  // Pop three registers.  Pops rightmost register first (from lower address).
676  void Pop(Register src1, Register src2, Register src3) {
677    LoadU64(src3, MemOperand(sp, 0));
678    LoadU64(src2, MemOperand(sp, kSystemPointerSize));
679    LoadU64(src1, MemOperand(sp, 2 * kSystemPointerSize));
680    la(sp, MemOperand(sp, 3 * kSystemPointerSize));
681  }
682
683  // Pop four registers.  Pops rightmost register first (from lower address).
684  void Pop(Register src1, Register src2, Register src3, Register src4) {
685    LoadU64(src4, MemOperand(sp, 0));
686    LoadU64(src3, MemOperand(sp, kSystemPointerSize));
687    LoadU64(src2, MemOperand(sp, 2 * kSystemPointerSize));
688    LoadU64(src1, MemOperand(sp, 3 * kSystemPointerSize));
689    la(sp, MemOperand(sp, 4 * kSystemPointerSize));
690  }
691
692  // Pop five registers.  Pops rightmost register first (from lower address).
693  void Pop(Register src1, Register src2, Register src3, Register src4,
694           Register src5) {
695    LoadU64(src5, MemOperand(sp, 0));
696    LoadU64(src4, MemOperand(sp, kSystemPointerSize));
697    LoadU64(src3, MemOperand(sp, 2 * kSystemPointerSize));
698    LoadU64(src2, MemOperand(sp, 3 * kSystemPointerSize));
699    LoadU64(src1, MemOperand(sp, 4 * kSystemPointerSize));
700    la(sp, MemOperand(sp, 5 * kSystemPointerSize));
701  }
702
703  // Push a fixed frame, consisting of lr, fp, constant pool.
704  void PushCommonFrame(Register marker_reg = no_reg);
705
706  // Push a standard frame, consisting of lr, fp, constant pool,
707  // context and JS function
708  void PushStandardFrame(Register function_reg);
709
710  void PopCommonFrame(Register marker_reg = no_reg);
711
712  // Restore caller's frame pointer and return address prior to being
713  // overwritten by tail call stack preparation.
714  void RestoreFrameStateForTailCall();
715
716  void InitializeRootRegister() {
717    ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
718    mov(kRootRegister, Operand(isolate_root));
719  }
720
721  // If the value is a NaN, canonicalize the value else, do nothing.
722  void CanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
723  void CanonicalizeNaN(const DoubleRegister value) {
724    CanonicalizeNaN(value, value);
725  }
726
727  // Converts the integer (untagged smi) in |src| to a double, storing
728  // the result to |dst|
729  void ConvertIntToDouble(DoubleRegister dst, Register src);
730
731  // Converts the unsigned integer (untagged smi) in |src| to
732  // a double, storing the result to |dst|
733  void ConvertUnsignedIntToDouble(DoubleRegister dst, Register src);
734
735  // Converts the integer (untagged smi) in |src| to
736  // a float, storing the result in |dst|
737  void ConvertIntToFloat(DoubleRegister dst, Register src);
738
739  // Converts the unsigned integer (untagged smi) in |src| to
740  // a float, storing the result in |dst|
741  void ConvertUnsignedIntToFloat(DoubleRegister dst, Register src);
742
743  void ConvertInt64ToFloat(DoubleRegister double_dst, Register src);
744  void ConvertInt64ToDouble(DoubleRegister double_dst, Register src);
745  void ConvertUnsignedInt64ToFloat(DoubleRegister double_dst, Register src);
746  void ConvertUnsignedInt64ToDouble(DoubleRegister double_dst, Register src);
747
748  void MovIntToFloat(DoubleRegister dst, Register src);
749  void MovFloatToInt(Register dst, DoubleRegister src);
750  void MovDoubleToInt64(Register dst, DoubleRegister src);
751  void MovInt64ToDouble(DoubleRegister dst, Register src);
752  // Converts the double_input to an integer.  Note that, upon return,
753  // the contents of double_dst will also hold the fixed point representation.
754  void ConvertFloat32ToInt64(const Register dst,
755                             const DoubleRegister double_input,
756                             FPRoundingMode rounding_mode = kRoundToZero);
757
758  // Converts the double_input to an integer.  Note that, upon return,
759  // the contents of double_dst will also hold the fixed point representation.
760  void ConvertDoubleToInt64(const Register dst,
761                            const DoubleRegister double_input,
762                            FPRoundingMode rounding_mode = kRoundToZero);
763  void ConvertDoubleToInt32(const Register dst,
764                            const DoubleRegister double_input,
765                            FPRoundingMode rounding_mode = kRoundToZero);
766
767  void ConvertFloat32ToInt32(const Register result,
768                             const DoubleRegister double_input,
769                             FPRoundingMode rounding_mode);
770  void ConvertFloat32ToUnsignedInt32(
771      const Register result, const DoubleRegister double_input,
772      FPRoundingMode rounding_mode = kRoundToZero);
773  // Converts the double_input to an unsigned integer.  Note that, upon return,
774  // the contents of double_dst will also hold the fixed point representation.
775  void ConvertDoubleToUnsignedInt64(
776      const Register dst, const DoubleRegister double_input,
777      FPRoundingMode rounding_mode = kRoundToZero);
778  void ConvertDoubleToUnsignedInt32(
779      const Register dst, const DoubleRegister double_input,
780      FPRoundingMode rounding_mode = kRoundToZero);
781  void ConvertFloat32ToUnsignedInt64(
782      const Register result, const DoubleRegister double_input,
783      FPRoundingMode rounding_mode = kRoundToZero);
784
785  // Generates function and stub prologue code.
786  void StubPrologue(StackFrame::Type type, Register base = no_reg,
787                    int prologue_offset = 0);
788  void Prologue(Register base, int prologue_offset = 0);
789
790  enum ArgumentsCountMode { kCountIncludesReceiver, kCountExcludesReceiver };
791  enum ArgumentsCountType { kCountIsInteger, kCountIsSmi, kCountIsBytes };
792  void DropArguments(Register count, ArgumentsCountType type,
793                     ArgumentsCountMode mode);
794  void DropArgumentsAndPushNewReceiver(Register argc, Register receiver,
795                                       ArgumentsCountType type,
796                                       ArgumentsCountMode mode);
797
798  // Get the actual activation frame alignment for target environment.
799  static int ActivationFrameAlignment();
800  // ----------------------------------------------------------------
801  // new S390 macro-assembler interfaces that are slightly higher level
802  // than assembler-s390 and may generate variable length sequences
803
804  // load an SMI value <value> to GPR <dst>
805  void LoadSmiLiteral(Register dst, Smi smi);
806
807  // load a literal double value <value> to FPR <result>
808  template <class T>
809  void LoadF64(DoubleRegister result, T value, Register scratch) {
810    static_assert(sizeof(T) == kDoubleSize, "Expect input size to be 8");
811    uint64_t int_val = bit_cast<uint64_t, T>(value);
812    // Load the 64-bit value into a GPR, then transfer it to FPR via LDGR
813    uint32_t hi_32 = int_val >> 32;
814    uint32_t lo_32 = static_cast<uint32_t>(int_val);
815
816    if (int_val == 0) {
817      lzdr(result);
818    } else if (lo_32 == 0) {
819      llihf(scratch, Operand(hi_32));
820      ldgr(result, scratch);
821    } else {
822      iihf(scratch, Operand(hi_32));
823      iilf(scratch, Operand(lo_32));
824      ldgr(result, scratch);
825    }
826  }
827
828  template <class T>
829  void LoadF32(DoubleRegister result, T value, Register scratch) {
830    static_assert(sizeof(T) == kFloatSize, "Expect input size to be 4");
831    uint32_t int_val = bit_cast<uint32_t, T>(value);
832    LoadF64(result, static_cast<uint64_t>(int_val) << 32, scratch);
833  }
834
835  void CmpSmiLiteral(Register src1, Smi smi, Register scratch);
836
837  // Set new rounding mode RN to FPSCR
838  void SetRoundingMode(FPRoundingMode RN);
839
840  // reset rounding mode to default (kRoundToNearest)
841  void ResetRoundingMode();
842
843  // These exist to provide portability between 32 and 64bit
844  void LoadMultipleP(Register dst1, Register dst2, const MemOperand& mem);
845  void StoreMultipleP(Register dst1, Register dst2, const MemOperand& mem);
846  void LoadMultipleW(Register dst1, Register dst2, const MemOperand& mem);
847  void StoreMultipleW(Register dst1, Register dst2, const MemOperand& mem);
848
849  void SwapP(Register src, Register dst, Register scratch);
850  void SwapP(Register src, MemOperand dst, Register scratch);
851  void SwapP(MemOperand src, MemOperand dst, Register scratch_0,
852             Register scratch_1);
853  void SwapFloat32(DoubleRegister src, DoubleRegister dst,
854                   DoubleRegister scratch);
855  void SwapFloat32(DoubleRegister src, MemOperand dst, DoubleRegister scratch);
856  void SwapFloat32(MemOperand src, MemOperand dst, DoubleRegister scratch);
857  void SwapDouble(DoubleRegister src, DoubleRegister dst,
858                  DoubleRegister scratch);
859  void SwapDouble(DoubleRegister src, MemOperand dst, DoubleRegister scratch);
860  void SwapDouble(MemOperand src, MemOperand dst, DoubleRegister scratch);
861  void SwapSimd128(Simd128Register src, Simd128Register dst,
862                   Simd128Register scratch);
863  void SwapSimd128(Simd128Register src, MemOperand dst,
864                   Simd128Register scratch);
865  void SwapSimd128(MemOperand src, MemOperand dst, Simd128Register scratch);
866
867  // Cleanse pointer address on 31bit by zero out top  bit.
868  // This is a NOP on 64-bit.
869  void CleanseP(Register src) {
870#if (V8_HOST_ARCH_S390 && !(V8_TARGET_ARCH_S390X))
871    nilh(src, Operand(0x7FFF));
872#endif
873  }
874
875  // ---------------------------------------------------------------------------
876  // Runtime calls
877
878  // Before calling a C-function from generated code, align arguments on stack.
879  // After aligning the frame, non-register arguments must be stored in
880  // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
881  // are word sized. If double arguments are used, this function assumes that
882  // all double arguments are stored before core registers; otherwise the
883  // correct alignment of the double values is not guaranteed.
884  // Some compilers/platforms require the stack to be aligned when calling
885  // C++ code.
886  // Needs a scratch register to do some arithmetic. This register will be
887  // trashed.
888  void PrepareCallCFunction(int num_reg_arguments, int num_double_registers,
889                            Register scratch);
890  void PrepareCallCFunction(int num_reg_arguments, Register scratch);
891
892  // There are two ways of passing double arguments on ARM, depending on
893  // whether soft or hard floating point ABI is used. These functions
894  // abstract parameter passing for the three different ways we call
895  // C functions from generated code.
896  void MovToFloatParameter(DoubleRegister src);
897  void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
898  void MovToFloatResult(DoubleRegister src);
899
900  // Calls a C function and cleans up the space for arguments allocated
901  // by PrepareCallCFunction. The called function is not allowed to trigger a
902  // garbage collection, since that might move the code and invalidate the
903  // return address (unless this is somehow accounted for by the called
904  // function).
905  void CallCFunction(ExternalReference function, int num_arguments);
906  void CallCFunction(Register function, int num_arguments);
907  void CallCFunction(ExternalReference function, int num_reg_arguments,
908                     int num_double_arguments);
909  void CallCFunction(Register function, int num_reg_arguments,
910                     int num_double_arguments);
911
912  void MovFromFloatParameter(DoubleRegister dst);
913  void MovFromFloatResult(DoubleRegister dst);
914
915  void Trap();
916  void DebugBreak();
917
918  // Emit code for a truncating division by a constant. The dividend register is
919  // unchanged and ip gets clobbered. Dividend and result must be different.
920  void TruncateDoubleToI(Isolate* isolate, Zone* zone, Register result,
921                         DoubleRegister double_input, StubCallMode stub_mode);
922  void TryInlineTruncateDoubleToI(Register result, DoubleRegister double_input,
923                                  Label* done);
924
925  // ---------------------------------------------------------------------------
926  // Debugging
927
928  // Calls Abort(msg) if the condition cond is not satisfied.
929  // Use --debug_code to enable.
930  void Assert(Condition cond, AbortReason reason, CRegister cr = cr7);
931
932  // Like Assert(), but without condition.
933  // Use --debug-code to enable.
934  void AssertUnreachable(AbortReason reason);
935
936  // Like Assert(), but always enabled.
937  void Check(Condition cond, AbortReason reason, CRegister cr = cr7);
938
939  // Print a message to stdout and abort execution.
940  void Abort(AbortReason reason);
941
942  // ---------------------------------------------------------------------------
943  // Bit testing/extraction
944  //
945  // Bit numbering is such that the least significant bit is bit 0
946  // (for consistency between 32/64-bit).
947
948  // Extract consecutive bits (defined by rangeStart - rangeEnd) from src
949  // and place them into the least significant bits of dst.
950  inline void ExtractBitRange(Register dst, Register src, int rangeStart,
951                              int rangeEnd) {
952    DCHECK(rangeStart >= rangeEnd && rangeStart < kBitsPerSystemPointer);
953
954    // Try to use RISBG if possible.
955    if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
956      int shiftAmount = (64 - rangeEnd) % 64;  // Convert to shift left.
957      int endBit = 63;  // End is always LSB after shifting.
958      int startBit = 63 - rangeStart + rangeEnd;
959      RotateInsertSelectBits(dst, src, Operand(startBit), Operand(endBit),
960                             Operand(shiftAmount), true);
961    } else {
962      if (rangeEnd > 0)  // Don't need to shift if rangeEnd is zero.
963        ShiftRightU64(dst, src, Operand(rangeEnd));
964      else if (dst != src)  // If we didn't shift, we might need to copy
965        mov(dst, src);
966      int width = rangeStart - rangeEnd + 1;
967#if V8_TARGET_ARCH_S390X
968      uint64_t mask = (static_cast<uint64_t>(1) << width) - 1;
969      nihf(dst, Operand(mask >> 32));
970      nilf(dst, Operand(mask & 0xFFFFFFFF));
971      ltgr(dst, dst);
972#else
973      uint32_t mask = (1 << width) - 1;
974      AndP(dst, Operand(mask));
975#endif
976    }
977  }
978
979  inline void ExtractBit(Register dst, Register src, uint32_t bitNumber) {
980    ExtractBitRange(dst, src, bitNumber, bitNumber);
981  }
982
983  // Extract consecutive bits (defined by mask) from src and place them
984  // into the least significant bits of dst.
985  inline void ExtractBitMask(Register dst, Register src, uintptr_t mask,
986                             RCBit rc = LeaveRC) {
987    int start = kBitsPerSystemPointer - 1;
988    int end;
989    uintptr_t bit = (1L << start);
990
991    while (bit && (mask & bit) == 0) {
992      start--;
993      bit >>= 1;
994    }
995    end = start;
996    bit >>= 1;
997
998    while (bit && (mask & bit)) {
999      end--;
1000      bit >>= 1;
1001    }
1002
1003    // 1-bits in mask must be contiguous
1004    DCHECK(bit == 0 || (mask & ((bit << 1) - 1)) == 0);
1005
1006    ExtractBitRange(dst, src, start, end);
1007  }
1008
1009  // Test single bit in value.
1010  inline void TestBit(Register value, int bitNumber, Register scratch = r0) {
1011    ExtractBitRange(scratch, value, bitNumber, bitNumber);
1012  }
1013
1014  // Test consecutive bit range in value.  Range is defined by
1015  // rangeStart - rangeEnd.
1016  inline void TestBitRange(Register value, int rangeStart, int rangeEnd,
1017                           Register scratch = r0) {
1018    ExtractBitRange(scratch, value, rangeStart, rangeEnd);
1019  }
1020
1021  // Test consecutive bit range in value.  Range is defined by mask.
1022  inline void TestBitMask(Register value, uintptr_t mask,
1023                          Register scratch = r0) {
1024    ExtractBitMask(scratch, value, mask, SetRC);
1025  }
1026  inline void TestIfSmi(Register value) { tmll(value, Operand(1)); }
1027
1028  inline void TestIfSmi(MemOperand value) {
1029    if (is_uint12(value.offset())) {
1030      tm(value, Operand(1));
1031    } else if (is_int20(value.offset())) {
1032      tmy(value, Operand(1));
1033    } else {
1034      LoadS8(r0, value);
1035      tmll(r0, Operand(1));
1036    }
1037  }
1038
1039  inline void TestIfInt32(Register value) {
1040    // High bits must be identical to fit into an 32-bit integer
1041    cgfr(value, value);
1042  }
1043  void SmiUntag(Register reg) { SmiUntag(reg, reg); }
1044
1045  void SmiUntag(Register dst, const MemOperand& src);
1046  void SmiUntag(Register dst, Register src) {
1047    if (SmiValuesAre31Bits()) {
1048      ShiftRightS32(dst, src, Operand(kSmiShift));
1049    } else {
1050      ShiftRightS64(dst, src, Operand(kSmiShift));
1051    }
1052    lgfr(dst, dst);
1053  }
1054  void SmiToInt32(Register smi) {
1055    if (FLAG_enable_slow_asserts) {
1056      AssertSmi(smi);
1057    }
1058    DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits());
1059    SmiUntag(smi);
1060  }
1061
1062  // Shift left by kSmiShift
1063  void SmiTag(Register reg) { SmiTag(reg, reg); }
1064  void SmiTag(Register dst, Register src) {
1065    ShiftLeftU64(dst, src, Operand(kSmiShift));
1066  }
1067
1068  // Abort execution if argument is a smi, enabled via --debug-code.
1069  void AssertNotSmi(Register object);
1070  void AssertSmi(Register object);
1071
1072  // Activation support.
1073  void EnterFrame(StackFrame::Type type,
1074                  bool load_constant_pool_pointer_reg = false);
1075  // Returns the pc offset at which the frame ends.
1076  int LeaveFrame(StackFrame::Type type, int stack_adjustment = 0);
1077
1078  void AllocateStackSpace(int bytes) {
1079    DCHECK_GE(bytes, 0);
1080    if (bytes == 0) return;
1081    lay(sp, MemOperand(sp, -bytes));
1082  }
1083
1084  void AllocateStackSpace(Register bytes) { SubS64(sp, sp, bytes); }
1085
1086  void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
1087                     Label* condition_met);
1088
1089  void ComputeCodeStartAddress(Register dst);
1090  void LoadPC(Register dst);
1091
1092  // Control-flow integrity:
1093
1094  // Define a function entrypoint. This doesn't emit any code for this
1095  // architecture, as control-flow integrity is not supported for it.
1096  void CodeEntry() {}
1097  // Define an exception handler.
1098  void ExceptionHandler() {}
1099  // Define an exception handler and bind a label.
1100  void BindExceptionHandler(Label* label) { bind(label); }
1101
1102  // Generates an instruction sequence s.t. the return address points to the
1103  // instruction following the call.
1104  // The return address on the stack is used by frame iteration.
1105  void StoreReturnAddressAndCall(Register target);
1106
1107  // ---------------------------------------------------------------------------
1108  // Simd Support.
1109  void F64x2Splat(Simd128Register dst, Simd128Register src);
1110  void F32x4Splat(Simd128Register dst, Simd128Register src);
1111  void I64x2Splat(Simd128Register dst, Register src);
1112  void I32x4Splat(Simd128Register dst, Register src);
1113  void I16x8Splat(Simd128Register dst, Register src);
1114  void I8x16Splat(Simd128Register dst, Register src);
1115  void F64x2ExtractLane(DoubleRegister dst, Simd128Register src,
1116                        uint8_t imm_lane_idx, Register = r0);
1117  void F32x4ExtractLane(DoubleRegister dst, Simd128Register src,
1118                        uint8_t imm_lane_idx, Register = r0);
1119  void I64x2ExtractLane(Register dst, Simd128Register src, uint8_t imm_lane_idx,
1120                        Register = r0);
1121  void I32x4ExtractLane(Register dst, Simd128Register src, uint8_t imm_lane_idx,
1122                        Register = r0);
1123  void I16x8ExtractLaneU(Register dst, Simd128Register src,
1124                         uint8_t imm_lane_idx, Register = r0);
1125  void I16x8ExtractLaneS(Register dst, Simd128Register src,
1126                         uint8_t imm_lane_idx, Register scratch);
1127  void I8x16ExtractLaneU(Register dst, Simd128Register src,
1128                         uint8_t imm_lane_idx, Register = r0);
1129  void I8x16ExtractLaneS(Register dst, Simd128Register src,
1130                         uint8_t imm_lane_idx, Register scratch);
1131  void F64x2ReplaceLane(Simd128Register dst, Simd128Register src1,
1132                        DoubleRegister src2, uint8_t imm_lane_idx,
1133                        Register scratch);
1134  void F32x4ReplaceLane(Simd128Register dst, Simd128Register src1,
1135                        DoubleRegister src2, uint8_t imm_lane_idx,
1136                        Register scratch);
1137  void I64x2ReplaceLane(Simd128Register dst, Simd128Register src1,
1138                        Register src2, uint8_t imm_lane_idx, Register = r0);
1139  void I32x4ReplaceLane(Simd128Register dst, Simd128Register src1,
1140                        Register src2, uint8_t imm_lane_idx, Register = r0);
1141  void I16x8ReplaceLane(Simd128Register dst, Simd128Register src1,
1142                        Register src2, uint8_t imm_lane_idx, Register = r0);
1143  void I8x16ReplaceLane(Simd128Register dst, Simd128Register src1,
1144                        Register src2, uint8_t imm_lane_idx, Register = r0);
1145  void I64x2Mul(Simd128Register dst, Simd128Register src1, Simd128Register src2,
1146                Register scratch1, Register scratch2, Register scratch3);
1147  void I32x4GeU(Simd128Register dst, Simd128Register src1, Simd128Register src2,
1148                Simd128Register scratch);
1149  void I16x8GeU(Simd128Register dst, Simd128Register src1, Simd128Register src2,
1150                Simd128Register scratch);
1151  void I8x16GeU(Simd128Register dst, Simd128Register src1, Simd128Register src2,
1152                Simd128Register scratch);
1153  void I64x2BitMask(Register dst, Simd128Register src, Register scratch1,
1154                    Simd128Register scratch2);
1155  void I32x4BitMask(Register dst, Simd128Register src, Register scratch1,
1156                    Simd128Register scratch2);
1157  void I16x8BitMask(Register dst, Simd128Register src, Register scratch1,
1158                    Simd128Register scratch2);
1159  void I8x16BitMask(Register dst, Simd128Register src, Register scratch1,
1160                    Register scratch2, Simd128Register scratch3);
1161  void V128AnyTrue(Register dst, Simd128Register src, Register scratch);
1162  void I32x4SConvertF32x4(Simd128Register dst, Simd128Register src,
1163                          Simd128Register scratch1, Register scratch2);
1164  void I32x4UConvertF32x4(Simd128Register dst, Simd128Register src,
1165                          Simd128Register scratch1, Register scratch2);
1166  void F32x4SConvertI32x4(Simd128Register dst, Simd128Register src,
1167                          Simd128Register scratch1, Register scratch2);
1168  void F32x4UConvertI32x4(Simd128Register dst, Simd128Register src,
1169                          Simd128Register scratch1, Register scratch2);
1170  void I16x8SConvertI32x4(Simd128Register dst, Simd128Register src1,
1171                          Simd128Register src2);
1172  void I8x16SConvertI16x8(Simd128Register dst, Simd128Register src1,
1173                          Simd128Register src2);
1174  void I16x8UConvertI32x4(Simd128Register dst, Simd128Register src1,
1175                          Simd128Register src2, Simd128Register scratch);
1176  void I8x16UConvertI16x8(Simd128Register dst, Simd128Register src1,
1177                          Simd128Register src2, Simd128Register scratch);
1178  void F64x2PromoteLowF32x4(Simd128Register dst, Simd128Register src,
1179                            Simd128Register scratch1, Register scratch2,
1180                            Register scratch3, Register scratch4);
1181  void F32x4DemoteF64x2Zero(Simd128Register dst, Simd128Register src,
1182                            Simd128Register scratch1, Register scratch2,
1183                            Register scratch3, Register scratch4);
1184  void I32x4TruncSatF64x2SZero(Simd128Register dst, Simd128Register src,
1185                               Simd128Register scratch);
1186  void I32x4TruncSatF64x2UZero(Simd128Register dst, Simd128Register src,
1187                               Simd128Register scratch);
1188  void I8x16Swizzle(Simd128Register dst, Simd128Register src1,
1189                    Simd128Register src2, Register scratch1, Register scratch2,
1190                    Simd128Register scratch3, Simd128Register scratch4);
1191  void S128Const(Simd128Register dst, uint64_t high, uint64_t low,
1192                 Register scratch1, Register scratch2);
1193  void I8x16Shuffle(Simd128Register dst, Simd128Register src1,
1194                    Simd128Register src2, uint64_t high, uint64_t low,
1195                    Register scratch1, Register scratch2,
1196                    Simd128Register scratch3);
1197  void I32x4DotI16x8S(Simd128Register dst, Simd128Register src1,
1198                      Simd128Register src2, Simd128Register scratch);
1199  void I16x8Q15MulRSatS(Simd128Register dst, Simd128Register src1,
1200                        Simd128Register src2, Simd128Register scratch1,
1201                        Simd128Register scratch2, Simd128Register scratch3);
1202  void S128Select(Simd128Register dst, Simd128Register src1,
1203                  Simd128Register src2, Simd128Register mask);
1204
1205#define SIMD_SHIFT_LIST(V) \
1206  V(I64x2Shl)              \
1207  V(I64x2ShrS)             \
1208  V(I64x2ShrU)             \
1209  V(I32x4Shl)              \
1210  V(I32x4ShrS)             \
1211  V(I32x4ShrU)             \
1212  V(I16x8Shl)              \
1213  V(I16x8ShrS)             \
1214  V(I16x8ShrU)             \
1215  V(I8x16Shl)              \
1216  V(I8x16ShrS)             \
1217  V(I8x16ShrU)
1218
1219#define PROTOTYPE_SIMD_SHIFT(name)                                          \
1220  void name(Simd128Register dst, Simd128Register src1, Register src2,       \
1221            Simd128Register scratch);                                       \
1222  void name(Simd128Register dst, Simd128Register src1, const Operand& src2, \
1223            Register scratch1, Simd128Register scratch2);
1224  SIMD_SHIFT_LIST(PROTOTYPE_SIMD_SHIFT)
1225#undef PROTOTYPE_SIMD_SHIFT
1226#undef SIMD_SHIFT_LIST
1227
1228#define SIMD_UNOP_LIST(V)   \
1229  V(F64x2Abs)               \
1230  V(F64x2Neg)               \
1231  V(F64x2Sqrt)              \
1232  V(F64x2Ceil)              \
1233  V(F64x2Floor)             \
1234  V(F64x2Trunc)             \
1235  V(F64x2NearestInt)        \
1236  V(F64x2ConvertLowI32x4S)  \
1237  V(F64x2ConvertLowI32x4U)  \
1238  V(F32x4Abs)               \
1239  V(F32x4Neg)               \
1240  V(F32x4Sqrt)              \
1241  V(F32x4Ceil)              \
1242  V(F32x4Floor)             \
1243  V(F32x4Trunc)             \
1244  V(F32x4NearestInt)        \
1245  V(I64x2Abs)               \
1246  V(I64x2SConvertI32x4Low)  \
1247  V(I64x2SConvertI32x4High) \
1248  V(I64x2UConvertI32x4Low)  \
1249  V(I64x2UConvertI32x4High) \
1250  V(I64x2Neg)               \
1251  V(I32x4Abs)               \
1252  V(I32x4Neg)               \
1253  V(I32x4SConvertI16x8Low)  \
1254  V(I32x4SConvertI16x8High) \
1255  V(I32x4UConvertI16x8Low)  \
1256  V(I32x4UConvertI16x8High) \
1257  V(I16x8Abs)               \
1258  V(I16x8Neg)               \
1259  V(I16x8SConvertI8x16Low)  \
1260  V(I16x8SConvertI8x16High) \
1261  V(I16x8UConvertI8x16Low)  \
1262  V(I16x8UConvertI8x16High) \
1263  V(I8x16Abs)               \
1264  V(I8x16Neg)               \
1265  V(I8x16Popcnt)            \
1266  V(S128Not)                \
1267  V(S128Zero)               \
1268  V(S128AllOnes)
1269
1270#define PROTOTYPE_SIMD_UNOP(name) \
1271  void name(Simd128Register dst, Simd128Register src);
1272  SIMD_UNOP_LIST(PROTOTYPE_SIMD_UNOP)
1273#undef PROTOTYPE_SIMD_UNOP
1274#undef SIMD_UNOP_LIST
1275
1276#define SIMD_BINOP_LIST(V) \
1277  V(F64x2Add)              \
1278  V(F64x2Sub)              \
1279  V(F64x2Mul)              \
1280  V(F64x2Div)              \
1281  V(F64x2Min)              \
1282  V(F64x2Max)              \
1283  V(F64x2Eq)               \
1284  V(F64x2Ne)               \
1285  V(F64x2Lt)               \
1286  V(F64x2Le)               \
1287  V(F64x2Pmin)             \
1288  V(F64x2Pmax)             \
1289  V(F32x4Add)              \
1290  V(F32x4Sub)              \
1291  V(F32x4Mul)              \
1292  V(F32x4Div)              \
1293  V(F32x4Min)              \
1294  V(F32x4Max)              \
1295  V(F32x4Eq)               \
1296  V(F32x4Ne)               \
1297  V(F32x4Lt)               \
1298  V(F32x4Le)               \
1299  V(F32x4Pmin)             \
1300  V(F32x4Pmax)             \
1301  V(I64x2Add)              \
1302  V(I64x2Sub)              \
1303  V(I64x2Eq)               \
1304  V(I64x2Ne)               \
1305  V(I64x2GtS)              \
1306  V(I64x2GeS)              \
1307  V(I32x4Add)              \
1308  V(I32x4Sub)              \
1309  V(I32x4Mul)              \
1310  V(I32x4Eq)               \
1311  V(I32x4Ne)               \
1312  V(I32x4GtS)              \
1313  V(I32x4GeS)              \
1314  V(I32x4GtU)              \
1315  V(I32x4MinS)             \
1316  V(I32x4MinU)             \
1317  V(I32x4MaxS)             \
1318  V(I32x4MaxU)             \
1319  V(I16x8Add)              \
1320  V(I16x8Sub)              \
1321  V(I16x8Mul)              \
1322  V(I16x8Eq)               \
1323  V(I16x8Ne)               \
1324  V(I16x8GtS)              \
1325  V(I16x8GeS)              \
1326  V(I16x8GtU)              \
1327  V(I16x8MinS)             \
1328  V(I16x8MinU)             \
1329  V(I16x8MaxS)             \
1330  V(I16x8MaxU)             \
1331  V(I16x8RoundingAverageU) \
1332  V(I8x16Add)              \
1333  V(I8x16Sub)              \
1334  V(I8x16Eq)               \
1335  V(I8x16Ne)               \
1336  V(I8x16GtS)              \
1337  V(I8x16GeS)              \
1338  V(I8x16GtU)              \
1339  V(I8x16MinS)             \
1340  V(I8x16MinU)             \
1341  V(I8x16MaxS)             \
1342  V(I8x16MaxU)             \
1343  V(I8x16RoundingAverageU) \
1344  V(S128And)               \
1345  V(S128Or)                \
1346  V(S128Xor)               \
1347  V(S128AndNot)
1348
1349#define PROTOTYPE_SIMD_BINOP(name) \
1350  void name(Simd128Register dst, Simd128Register src1, Simd128Register src2);
1351  SIMD_BINOP_LIST(PROTOTYPE_SIMD_BINOP)
1352#undef PROTOTYPE_SIMD_BINOP
1353#undef SIMD_BINOP_LIST
1354
1355#define SIMD_EXT_MUL_LIST(V) \
1356  V(I64x2ExtMulLowI32x4S)    \
1357  V(I64x2ExtMulHighI32x4S)   \
1358  V(I64x2ExtMulLowI32x4U)    \
1359  V(I64x2ExtMulHighI32x4U)   \
1360  V(I32x4ExtMulLowI16x8S)    \
1361  V(I32x4ExtMulHighI16x8S)   \
1362  V(I32x4ExtMulLowI16x8U)    \
1363  V(I32x4ExtMulHighI16x8U)   \
1364  V(I16x8ExtMulLowI8x16S)    \
1365  V(I16x8ExtMulHighI8x16S)   \
1366  V(I16x8ExtMulLowI8x16U)    \
1367  V(I16x8ExtMulHighI8x16U)
1368
1369#define PROTOTYPE_SIMD_EXT_MUL(name)                                         \
1370  void name(Simd128Register dst, Simd128Register src1, Simd128Register src2, \
1371            Simd128Register scratch);
1372  SIMD_EXT_MUL_LIST(PROTOTYPE_SIMD_EXT_MUL)
1373#undef PROTOTYPE_SIMD_EXT_MUL
1374#undef SIMD_EXT_MUL_LIST
1375
1376#define SIMD_ALL_TRUE_LIST(V) \
1377  V(I64x2AllTrue)             \
1378  V(I32x4AllTrue)             \
1379  V(I16x8AllTrue)             \
1380  V(I8x16AllTrue)
1381
1382#define PROTOTYPE_SIMD_ALL_TRUE(name)                             \
1383  void name(Register dst, Simd128Register src, Register scratch1, \
1384            Simd128Register scratch2);
1385  SIMD_ALL_TRUE_LIST(PROTOTYPE_SIMD_ALL_TRUE)
1386#undef PROTOTYPE_SIMD_ALL_TRUE
1387#undef SIMD_ALL_TRUE_LIST
1388
1389#define SIMD_QFM_LIST(V) \
1390  V(F64x2Qfma)           \
1391  V(F64x2Qfms)           \
1392  V(F32x4Qfma)           \
1393  V(F32x4Qfms)
1394
1395#define PROTOTYPE_SIMD_QFM(name)                                             \
1396  void name(Simd128Register dst, Simd128Register src1, Simd128Register src2, \
1397            Simd128Register src3);
1398  SIMD_QFM_LIST(PROTOTYPE_SIMD_QFM)
1399#undef PROTOTYPE_SIMD_QFM
1400#undef SIMD_QFM_LIST
1401
1402#define SIMD_ADD_SUB_SAT_LIST(V) \
1403  V(I16x8AddSatS)                \
1404  V(I16x8SubSatS)                \
1405  V(I16x8AddSatU)                \
1406  V(I16x8SubSatU)                \
1407  V(I8x16AddSatS)                \
1408  V(I8x16SubSatS)                \
1409  V(I8x16AddSatU)                \
1410  V(I8x16SubSatU)
1411
1412#define PROTOTYPE_SIMD_ADD_SUB_SAT(name)                                     \
1413  void name(Simd128Register dst, Simd128Register src1, Simd128Register src2, \
1414            Simd128Register scratch1, Simd128Register scratch2);
1415  SIMD_ADD_SUB_SAT_LIST(PROTOTYPE_SIMD_ADD_SUB_SAT)
1416#undef PROTOTYPE_SIMD_ADD_SUB_SAT
1417#undef SIMD_ADD_SUB_SAT_LIST
1418
1419#define SIMD_EXT_ADD_PAIRWISE_LIST(V) \
1420  V(I32x4ExtAddPairwiseI16x8S)        \
1421  V(I32x4ExtAddPairwiseI16x8U)        \
1422  V(I16x8ExtAddPairwiseI8x16S)        \
1423  V(I16x8ExtAddPairwiseI8x16U)
1424
1425#define PROTOTYPE_SIMD_EXT_ADD_PAIRWISE(name)         \
1426  void name(Simd128Register dst, Simd128Register src, \
1427            Simd128Register scratch1, Simd128Register scratch2);
1428  SIMD_EXT_ADD_PAIRWISE_LIST(PROTOTYPE_SIMD_EXT_ADD_PAIRWISE)
1429#undef PROTOTYPE_SIMD_EXT_ADD_PAIRWISE
1430#undef SIMD_EXT_ADD_PAIRWISE_LIST
1431
1432  // ---------------------------------------------------------------------------
1433  // Pointer compression Support
1434
1435  void SmiToPtrArrayOffset(Register dst, Register src) {
1436#if defined(V8_COMPRESS_POINTERS) || defined(V8_31BIT_SMIS_ON_64BIT_ARCH)
1437    STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kSystemPointerSizeLog2);
1438    ShiftLeftU64(dst, src, Operand(kSystemPointerSizeLog2 - kSmiShift));
1439#else
1440    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kSystemPointerSizeLog2);
1441    ShiftRightS64(dst, src, Operand(kSmiShift - kSystemPointerSizeLog2));
1442#endif
1443  }
1444
1445  // Loads a field containing a HeapObject and decompresses it if pointer
1446  // compression is enabled.
1447  void LoadTaggedPointerField(const Register& destination,
1448                              const MemOperand& field_operand,
1449                              const Register& scratch = no_reg);
1450  void LoadTaggedSignedField(Register destination, MemOperand field_operand);
1451
1452  // Loads a field containing any tagged value and decompresses it if necessary.
1453  void LoadAnyTaggedField(const Register& destination,
1454                          const MemOperand& field_operand,
1455                          const Register& scratch = no_reg);
1456
1457  // Loads a field containing smi value and untags it.
1458  void SmiUntagField(Register dst, const MemOperand& src);
1459
1460  // Compresses and stores tagged value to given on-heap location.
1461  void StoreTaggedField(const Register& value,
1462                        const MemOperand& dst_field_operand,
1463                        const Register& scratch = no_reg);
1464
1465  void DecompressTaggedSigned(Register destination, MemOperand field_operand);
1466  void DecompressTaggedSigned(Register destination, Register src);
1467  void DecompressTaggedPointer(Register destination, MemOperand field_operand);
1468  void DecompressTaggedPointer(Register destination, Register source);
1469  void DecompressAnyTagged(Register destination, MemOperand field_operand);
1470  void DecompressAnyTagged(Register destination, Register source);
1471
1472  // CountLeadingZeros will corrupt the scratch register pair (eg. r0:r1)
1473  void CountLeadingZerosU32(Register dst, Register src,
1474                            Register scratch_pair = r0);
1475  void CountLeadingZerosU64(Register dst, Register src,
1476                            Register scratch_pair = r0);
1477  void CountTrailingZerosU32(Register dst, Register src,
1478                             Register scratch_pair = r0);
1479  void CountTrailingZerosU64(Register dst, Register src,
1480                             Register scratch_pair = r0);
1481
1482 private:
1483  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1484
1485  void CallCFunctionHelper(Register function, int num_reg_arguments,
1486                           int num_double_arguments);
1487
1488  void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
1489  int CalculateStackPassedWords(int num_reg_arguments,
1490                                int num_double_arguments);
1491};
1492
1493// MacroAssembler implements a collection of frequently used macros.
1494class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
1495 public:
1496  using TurboAssembler::TurboAssembler;
1497
1498  void LoadStackLimit(Register destination, StackLimitKind kind);
1499  // It assumes that the arguments are located below the stack pointer.
1500  // argc is the number of arguments not including the receiver.
1501  // TODO(victorgomes): Remove this function once we stick with the reversed
1502  // arguments order.
1503  void LoadReceiver(Register dest, Register argc) {
1504    LoadU64(dest, MemOperand(sp, 0));
1505  }
1506
1507  void StoreReceiver(Register rec, Register argc, Register scratch) {
1508    StoreU64(rec, MemOperand(sp, 0));
1509  }
1510
1511  void CallRuntime(const Runtime::Function* f, int num_arguments,
1512                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore);
1513  void CallRuntimeSaveDoubles(Runtime::FunctionId fid) {
1514    const Runtime::Function* function = Runtime::FunctionForId(fid);
1515    CallRuntime(function, function->nargs, SaveFPRegsMode::kSave);
1516  }
1517
1518  // Convenience function: Same as above, but takes the fid instead.
1519  void CallRuntime(Runtime::FunctionId fid,
1520                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) {
1521    const Runtime::Function* function = Runtime::FunctionForId(fid);
1522    CallRuntime(function, function->nargs, save_doubles);
1523  }
1524
1525  // Convenience function: Same as above, but takes the fid instead.
1526  void CallRuntime(Runtime::FunctionId fid, int num_arguments,
1527                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) {
1528    CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
1529  }
1530
1531  // Convenience function: tail call a runtime routine (jump).
1532  void TailCallRuntime(Runtime::FunctionId fid);
1533
1534  // ---------------------------------------------------------------------------
1535  // Support functions.
1536
1537  // Compare object type for heap object.  heap_object contains a non-Smi
1538  // whose object type should be compared with the given type.  This both
1539  // sets the flags and leaves the object type in the type_reg register.
1540  // It leaves the map in the map register (unless the type_reg and map register
1541  // are the same register).  It leaves the heap object in the heap_object
1542  // register unless the heap_object register is the same register as one of the
1543  // other registers.
1544  // Type_reg can be no_reg. In that case ip is used.
1545  void CompareObjectType(Register heap_object, Register map, Register type_reg,
1546                         InstanceType type);
1547
1548  // Compare instance type in a map.  map contains a valid map object whose
1549  // object type should be compared with the given type.  This both
1550  // sets the flags and leaves the object type in the type_reg register.
1551  void CompareInstanceType(Register map, Register type_reg, InstanceType type);
1552
1553  // Compare instance type ranges for a map (lower_limit and higher_limit
1554  // inclusive).
1555  //
1556  // Always use unsigned comparisons: ls for a positive result.
1557  void CompareInstanceTypeRange(Register map, Register type_reg,
1558                                InstanceType lower_limit,
1559                                InstanceType higher_limit);
1560
1561  // Compare the object in a register to a value from the root list.
1562  // Uses the ip register as scratch.
1563  void CompareRoot(Register obj, RootIndex index);
1564  void PushRoot(RootIndex index) {
1565    LoadRoot(r0, index);
1566    Push(r0);
1567  }
1568
1569  template <class T>
1570  void CompareTagged(Register src1, T src2) {
1571    if (COMPRESS_POINTERS_BOOL) {
1572      CmpS32(src1, src2);
1573    } else {
1574      CmpS64(src1, src2);
1575    }
1576  }
1577
1578  // Jump to a runtime routine.
1579  void JumpToExternalReference(const ExternalReference& builtin,
1580                               bool builtin_exit_frame = false);
1581
1582  // Generates a trampoline to jump to the off-heap instruction stream.
1583  void JumpToOffHeapInstructionStream(Address entry);
1584
1585  // Compare the object in a register to a value and jump if they are equal.
1586  void JumpIfRoot(Register with, RootIndex index, Label* if_equal) {
1587    CompareRoot(with, index);
1588    beq(if_equal);
1589  }
1590
1591  // Compare the object in a register to a value and jump if they are not equal.
1592  void JumpIfNotRoot(Register with, RootIndex index, Label* if_not_equal) {
1593    CompareRoot(with, index);
1594    bne(if_not_equal);
1595  }
1596
1597  // Checks if value is in range [lower_limit, higher_limit] using a single
1598  // comparison.
1599  void CompareRange(Register value, unsigned lower_limit,
1600                    unsigned higher_limit);
1601  void JumpIfIsInRange(Register value, unsigned lower_limit,
1602                       unsigned higher_limit, Label* on_in_range);
1603
1604  // ---------------------------------------------------------------------------
1605  // In-place weak references.
1606  void LoadWeakValue(Register out, Register in, Label* target_if_cleared);
1607
1608  // ---------------------------------------------------------------------------
1609  // StatsCounter support
1610
1611  void IncrementCounter(StatsCounter* counter, int value, Register scratch1,
1612                        Register scratch2) {
1613    if (!FLAG_native_code_counters) return;
1614    EmitIncrementCounter(counter, value, scratch1, scratch2);
1615  }
1616  void EmitIncrementCounter(StatsCounter* counter, int value, Register scratch1,
1617                            Register scratch2);
1618  void DecrementCounter(StatsCounter* counter, int value, Register scratch1,
1619                        Register scratch2) {
1620    if (!FLAG_native_code_counters) return;
1621    EmitDecrementCounter(counter, value, scratch1, scratch2);
1622  }
1623  void EmitDecrementCounter(StatsCounter* counter, int value, Register scratch1,
1624                            Register scratch2);
1625
1626  // ---------------------------------------------------------------------------
1627  // Stack limit utilities
1628
1629  MemOperand StackLimitAsMemOperand(StackLimitKind kind);
1630  void StackOverflowCheck(Register num_args, Register scratch,
1631                          Label* stack_overflow);
1632
1633  // ---------------------------------------------------------------------------
1634  // JavaScript invokes
1635
1636  // Set up call kind marking in ecx. The method takes ecx as an
1637  // explicit first parameter to make the code more readable at the
1638  // call sites.
1639  // void SetCallKind(Register dst, CallKind kind);
1640
1641  // Removes current frame and its arguments from the stack preserving
1642  // the arguments and a return address pushed to the stack for the next call.
1643  // Both |callee_args_count| and |caller_args_count| do not include
1644  // receiver. |callee_args_count| is not modified. |caller_args_count|
1645  // is trashed.
1646
1647  // Invoke the JavaScript function code by either calling or jumping.
1648  void InvokeFunctionCode(Register function, Register new_target,
1649                          Register expected_parameter_count,
1650                          Register actual_parameter_count, InvokeType type);
1651
1652  // On function call, call into the debugger if necessary.
1653  void CheckDebugHook(Register fun, Register new_target,
1654                      Register expected_parameter_count,
1655                      Register actual_parameter_count);
1656
1657  // Invoke the JavaScript function in the given register. Changes the
1658  // current context to the context in the function before invoking.
1659  void InvokeFunctionWithNewTarget(Register function, Register new_target,
1660                                   Register actual_parameter_count,
1661                                   InvokeType type);
1662  void InvokeFunction(Register function, Register expected_parameter_count,
1663                      Register actual_parameter_count, InvokeType type);
1664
1665  // Exception handling
1666
1667  // Push a new stack handler and link into stack handler chain.
1668  void PushStackHandler();
1669
1670  // Unlink the stack handler on top of the stack from the stack handler chain.
1671  // Must preserve the result register.
1672  void PopStackHandler();
1673
1674  // Enter exit frame.
1675  // stack_space - extra stack space, used for parameters before call to C.
1676  // At least one slot (for the return address) should be provided.
1677  void EnterExitFrame(bool save_doubles, int stack_space = 1,
1678                      StackFrame::Type frame_type = StackFrame::EXIT);
1679
1680  // Leave the current exit frame. Expects the return value in r0.
1681  // Expect the number of values, pushed prior to the exit frame, to
1682  // remove in a register (or no_reg, if there is nothing to remove).
1683  void LeaveExitFrame(bool save_doubles, Register argument_count,
1684                      bool argument_count_is_length = false);
1685
1686  // Load the global proxy from the current context.
1687  void LoadGlobalProxy(Register dst) {
1688    LoadNativeContextSlot(dst, Context::GLOBAL_PROXY_INDEX);
1689  }
1690
1691  void LoadNativeContextSlot(Register dst, int index);
1692
1693  // ---------------------------------------------------------------------------
1694  // Smi utilities
1695
1696  // Jump if either of the registers contain a non-smi.
1697  inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
1698    TestIfSmi(value);
1699    bne(not_smi_label /*, cr0*/);
1700  }
1701
1702#if !defined(V8_COMPRESS_POINTERS) && !defined(V8_31BIT_SMIS_ON_64BIT_ARCH)
1703  // Ensure it is permissible to read/write int value directly from
1704  // upper half of the smi.
1705  STATIC_ASSERT(kSmiTag == 0);
1706  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
1707#endif
1708#if V8_TARGET_LITTLE_ENDIAN
1709#define SmiWordOffset(offset) (offset + kSystemPointerSize / 2)
1710#else
1711#define SmiWordOffset(offset) offset
1712#endif
1713
1714  // Abort execution if argument is not a Constructor, enabled via --debug-code.
1715  void AssertConstructor(Register object, Register scratch);
1716
1717  // Abort execution if argument is not a JSFunction, enabled via --debug-code.
1718  void AssertFunction(Register object);
1719
1720  // Abort execution if argument is not a callable JSFunction, enabled via
1721  // --debug-code.
1722  void AssertCallableFunction(Register object);
1723
1724  // Abort execution if argument is not a JSBoundFunction,
1725  // enabled via --debug-code.
1726  void AssertBoundFunction(Register object);
1727
1728  // Abort execution if argument is not a JSGeneratorObject (or subclass),
1729  // enabled via --debug-code.
1730  void AssertGeneratorObject(Register object);
1731
1732  // Abort execution if argument is not undefined or an AllocationSite, enabled
1733  // via --debug-code.
1734  void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1735
1736  template <typename Field>
1737  void DecodeField(Register dst, Register src) {
1738    ExtractBitRange(dst, src, Field::kShift + Field::kSize - 1, Field::kShift);
1739  }
1740
1741  template <typename Field>
1742  void DecodeField(Register reg) {
1743    DecodeField<Field>(reg, reg);
1744  }
1745
1746  // ---------------------------------------------------------------------------
1747  // GC Support
1748
1749  void IncrementalMarkingRecordWriteHelper(Register object, Register value,
1750                                           Register address);
1751
1752  void CallJSEntry(Register target);
1753  static int CallSizeNotPredictableCodeSize(Address target,
1754                                            RelocInfo::Mode rmode,
1755                                            Condition cond = al);
1756  // Notify the garbage collector that we wrote a pointer into an object.
1757  // |object| is the object being stored into, |value| is the object being
1758  // stored.  value and scratch registers are clobbered by the operation.
1759  // The offset is the offset from the start of the object, not the offset from
1760  // the tagged HeapObject pointer.  For use with FieldMemOperand(reg, off).
1761  void RecordWriteField(
1762      Register object, int offset, Register value, Register slot_address,
1763      LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
1764      RememberedSetAction remembered_set_action = RememberedSetAction::kEmit,
1765      SmiCheck smi_check = SmiCheck::kInline);
1766
1767  // For a given |object| notify the garbage collector that the slot |address|
1768  // has been written.  |value| is the object being stored. The value and
1769  // address registers are clobbered by the operation.
1770  void RecordWrite(
1771      Register object, Register slot_address, Register value,
1772      LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
1773      RememberedSetAction remembered_set_action = RememberedSetAction::kEmit,
1774      SmiCheck smi_check = SmiCheck::kInline);
1775
1776 private:
1777  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1778  // Helper functions for generating invokes.
1779  void InvokePrologue(Register expected_parameter_count,
1780                      Register actual_parameter_count, Label* done,
1781                      InvokeType type);
1782
1783  DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
1784};
1785
1786#define ACCESS_MASM(masm) masm->
1787
1788}  // namespace internal
1789}  // namespace v8
1790
1791#endif  // V8_CODEGEN_S390_MACRO_ASSEMBLER_S390_H_
1792