V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
macro-assembler-s390.h
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_S390_MACRO_ASSEMBLER_S390_H_
10 #define V8_S390_MACRO_ASSEMBLER_S390_H_
11 
12 #include "src/bailout-reason.h"
13 #include "src/contexts.h"
14 #include "src/globals.h"
15 #include "src/s390/assembler-s390.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 // Give alias names to registers for calling conventions.
21 constexpr Register kReturnRegister0 = r2;
22 constexpr Register kReturnRegister1 = r3;
23 constexpr Register kReturnRegister2 = r4;
24 constexpr Register kJSFunctionRegister = r3;
25 constexpr Register kContextRegister = r13;
26 constexpr Register kAllocateSizeRegister = r3;
27 constexpr Register kSpeculationPoisonRegister = r9;
28 constexpr Register kInterpreterAccumulatorRegister = r2;
29 constexpr Register kInterpreterBytecodeOffsetRegister = r6;
30 constexpr Register kInterpreterBytecodeArrayRegister = r7;
31 constexpr Register kInterpreterDispatchTableRegister = r8;
32 
33 constexpr Register kJavaScriptCallArgCountRegister = r2;
34 constexpr Register kJavaScriptCallCodeStartRegister = r4;
35 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
36 constexpr Register kJavaScriptCallNewTargetRegister = r5;
37 constexpr Register kJavaScriptCallExtraArg1Register = r4;
38 
39 constexpr Register kOffHeapTrampolineRegister = ip;
40 constexpr Register kRuntimeCallFunctionRegister = r3;
41 constexpr Register kRuntimeCallArgCountRegister = r2;
42 constexpr Register kRuntimeCallArgvRegister = r4;
43 constexpr Register kWasmInstanceRegister = r6;
44 constexpr Register kWasmCompileLazyFuncIndexRegister = r7;
45 
46 // ----------------------------------------------------------------------------
47 // Static helper functions
48 
49 // Generate a MemOperand for loading a field from an object.
50 inline MemOperand FieldMemOperand(Register object, int offset) {
51  return MemOperand(object, offset - kHeapObjectTag);
52 }
53 
54 // Generate a MemOperand for loading a field from an object.
55 inline MemOperand FieldMemOperand(Register object, Register index, int offset) {
56  return MemOperand(object, index, offset - kHeapObjectTag);
57 }
58 
59 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
60 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
61 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
62 
63 Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2 = no_reg,
64  Register reg3 = no_reg,
65  Register reg4 = no_reg,
66  Register reg5 = no_reg,
67  Register reg6 = no_reg);
68 
69 // These exist to provide portability between 32 and 64bit
70 #if V8_TARGET_ARCH_S390X
71 
72 // The length of the arithmetic operation is the length
73 // of the register.
74 
75 // Length:
76 // H = halfword
77 // W = word
78 
79 // arithmetics and bitwise
80 #define AddMI agsi
81 #define AddRR agr
82 #define SubRR sgr
83 #define AndRR ngr
84 #define OrRR ogr
85 #define XorRR xgr
86 #define LoadComplementRR lcgr
87 #define LoadNegativeRR lngr
88 
89 // Distinct Operands
90 #define AddP_RRR agrk
91 #define AddPImm_RRI aghik
92 #define AddLogicalP_RRR algrk
93 #define SubP_RRR sgrk
94 #define SubLogicalP_RRR slgrk
95 #define AndP_RRR ngrk
96 #define OrP_RRR ogrk
97 #define XorP_RRR xgrk
98 
99 // Load / Store
100 #define LoadRR lgr
101 #define LoadAndTestRR ltgr
102 #define LoadImmP lghi
103 
104 // Compare
105 #define CmpPH cghi
106 #define CmpLogicalPW clgfi
107 
108 // Shifts
109 #define ShiftLeftP sllg
110 #define ShiftRightP srlg
111 #define ShiftLeftArithP slag
112 #define ShiftRightArithP srag
113 #else
114 
115 // arithmetics and bitwise
116 // Reg2Reg
117 #define AddMI asi
118 #define AddRR ar
119 #define SubRR sr
120 #define AndRR nr
121 #define OrRR or_z
122 #define XorRR xr
123 #define LoadComplementRR lcr
124 #define LoadNegativeRR lnr
125 
126 // Distinct Operands
127 #define AddP_RRR ark
128 #define AddPImm_RRI ahik
129 #define AddLogicalP_RRR alrk
130 #define SubP_RRR srk
131 #define SubLogicalP_RRR slrk
132 #define AndP_RRR nrk
133 #define OrP_RRR ork
134 #define XorP_RRR xrk
135 
136 // Load / Store
137 #define LoadRR lr
138 #define LoadAndTestRR ltr
139 #define LoadImmP lhi
140 
141 // Compare
142 #define CmpPH chi
143 #define CmpLogicalPW clfi
144 
145 // Shifts
146 #define ShiftLeftP ShiftLeft
147 #define ShiftRightP ShiftRight
148 #define ShiftLeftArithP ShiftLeftArith
149 #define ShiftRightArithP ShiftRightArith
150 
151 #endif
152 
153 class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
154  public:
155  TurboAssembler(const AssemblerOptions& options, void* buffer, int buffer_size)
156  : TurboAssemblerBase(options, buffer, buffer_size) {}
157 
158  TurboAssembler(Isolate* isolate, const AssemblerOptions& options,
159  void* buffer, int buffer_size,
160  CodeObjectRequired create_code_object)
161  : TurboAssemblerBase(isolate, options, buffer, buffer_size,
162  create_code_object) {}
163 
164  void LoadFromConstantsTable(Register destination,
165  int constant_index) override;
166  void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
167  void LoadRootRelative(Register destination, int32_t offset) override;
168 
169  // Jump, Call, and Ret pseudo instructions implementing inter-working.
170  void Jump(Register target, Condition cond = al);
171  void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al);
172  void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
173  // Jump the register contains a smi.
174  inline void JumpIfSmi(Register value, Label* smi_label) {
175  TestIfSmi(value);
176  beq(smi_label /*, cr0*/); // branch if SMI
177  }
178  void JumpIfEqual(Register x, int32_t y, Label* dest);
179  void JumpIfLessThan(Register x, int32_t y, Label* dest);
180 
181  void Call(Register target);
182  void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
183  void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
184  Condition cond = al);
185  void Ret() { b(r14); }
186  void Ret(Condition cond) { b(cond, r14); }
187 
188  void CallForDeoptimization(Address target, int deopt_id,
189  RelocInfo::Mode rmode) {
190  USE(deopt_id);
191  Call(target, rmode);
192  }
193 
194  // Emit code to discard a non-negative number of pointer-sized elements
195  // from the stack, clobbering only the sp register.
196  void Drop(int count);
197  void Drop(Register count, Register scratch = r0);
198 
199  void Ret(int drop) {
200  Drop(drop);
201  Ret();
202  }
203 
204  void Call(Label* target);
205 
206  // Register move. May do nothing if the registers are identical.
207  void Move(Register dst, Smi smi) { LoadSmiLiteral(dst, smi); }
208  void Move(Register dst, Handle<HeapObject> value);
209  void Move(Register dst, ExternalReference reference);
210  void Move(Register dst, Register src, Condition cond = al);
211  void Move(DoubleRegister dst, DoubleRegister src);
212 
213  void MoveChar(const MemOperand& opnd1, const MemOperand& opnd2,
214  const Operand& length);
215 
216  void CompareLogicalChar(const MemOperand& opnd1, const MemOperand& opnd2,
217  const Operand& length);
218 
219  void ExclusiveOrChar(const MemOperand& opnd1, const MemOperand& opnd2,
220  const Operand& length);
221 
222  void RotateInsertSelectBits(Register dst, Register src,
223  const Operand& startBit, const Operand& endBit,
224  const Operand& shiftAmt, bool zeroBits);
225 
226  void BranchRelativeOnIdxHighP(Register dst, Register inc, Label* L);
227 
228  void SaveRegisters(RegList registers);
229  void RestoreRegisters(RegList registers);
230 
231  void CallRecordWriteStub(Register object, Register address,
232  RememberedSetAction remembered_set_action,
233  SaveFPRegsMode fp_mode);
234  void CallRecordWriteStub(Register object, Register address,
235  RememberedSetAction remembered_set_action,
236  SaveFPRegsMode fp_mode, Address wasm_target);
237 
238  void MultiPush(RegList regs, Register location = sp);
239  void MultiPop(RegList regs, Register location = sp);
240 
241  void MultiPushDoubles(RegList dregs, Register location = sp);
242  void MultiPopDoubles(RegList dregs, Register location = sp);
243 
244  // Calculate how much stack space (in bytes) are required to store caller
245  // registers excluding those specified in the arguments.
246  int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
247  Register exclusion1 = no_reg,
248  Register exclusion2 = no_reg,
249  Register exclusion3 = no_reg) const;
250 
251  // Push caller saved registers on the stack, and return the number of bytes
252  // stack pointer is adjusted.
253  int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
254  Register exclusion2 = no_reg,
255  Register exclusion3 = no_reg);
256  // Restore caller saved registers from the stack, and return the number of
257  // bytes stack pointer is adjusted.
258  int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
259  Register exclusion2 = no_reg,
260  Register exclusion3 = no_reg);
261 
262  // Load an object from the root table.
263  void LoadRoot(Register destination, RootIndex index) override {
264  LoadRoot(destination, index, al);
265  }
266  void LoadRoot(Register destination, RootIndex index, Condition cond);
267  //--------------------------------------------------------------------------
268  // S390 Macro Assemblers for Instructions
269  //--------------------------------------------------------------------------
270 
271  // Arithmetic Operations
272 
273  // Add (Register - Immediate)
274  void Add32(Register dst, const Operand& imm);
275  void Add32_RI(Register dst, const Operand& imm);
276  void AddP(Register dst, const Operand& imm);
277  void Add32(Register dst, Register src, const Operand& imm);
278  void Add32_RRI(Register dst, Register src, const Operand& imm);
279  void AddP(Register dst, Register src, const Operand& imm);
280 
281  // Add (Register - Register)
282  void Add32(Register dst, Register src);
283  void AddP(Register dst, Register src);
284  void AddP_ExtendSrc(Register dst, Register src);
285  void Add32(Register dst, Register src1, Register src2);
286  void AddP(Register dst, Register src1, Register src2);
287  void AddP_ExtendSrc(Register dst, Register src1, Register src2);
288 
289  // Add (Register - Mem)
290  void Add32(Register dst, const MemOperand& opnd);
291  void AddP(Register dst, const MemOperand& opnd);
292  void AddP_ExtendSrc(Register dst, const MemOperand& opnd);
293 
294  // Add (Mem - Immediate)
295  void Add32(const MemOperand& opnd, const Operand& imm);
296  void AddP(const MemOperand& opnd, const Operand& imm);
297 
298  // Add Logical (Register - Register)
299  void AddLogical32(Register dst, Register src1, Register src2);
300 
301  // Add Logical With Carry (Register - Register)
302  void AddLogicalWithCarry32(Register dst, Register src1, Register src2);
303 
304  // Add Logical (Register - Immediate)
305  void AddLogical(Register dst, const Operand& imm);
306  void AddLogicalP(Register dst, const Operand& imm);
307 
308  // Add Logical (Register - Mem)
309  void AddLogical(Register dst, const MemOperand& opnd);
310  void AddLogicalP(Register dst, const MemOperand& opnd);
311 
312  // Subtract (Register - Immediate)
313  void Sub32(Register dst, const Operand& imm);
314  void Sub32_RI(Register dst, const Operand& imm) { Sub32(dst, imm); }
315  void SubP(Register dst, const Operand& imm);
316  void Sub32(Register dst, Register src, const Operand& imm);
317  void Sub32_RRI(Register dst, Register src, const Operand& imm) {
318  Sub32(dst, src, imm);
319  }
320  void SubP(Register dst, Register src, const Operand& imm);
321 
322  // Subtract (Register - Register)
323  void Sub32(Register dst, Register src);
324  void SubP(Register dst, Register src);
325  void SubP_ExtendSrc(Register dst, Register src);
326  void Sub32(Register dst, Register src1, Register src2);
327  void SubP(Register dst, Register src1, Register src2);
328  void SubP_ExtendSrc(Register dst, Register src1, Register src2);
329 
330  // Subtract (Register - Mem)
331  void Sub32(Register dst, const MemOperand& opnd);
332  void SubP(Register dst, const MemOperand& opnd);
333  void SubP_ExtendSrc(Register dst, const MemOperand& opnd);
334  void LoadAndSub32(Register dst, Register src, const MemOperand& opnd);
335  void LoadAndSub64(Register dst, Register src, const MemOperand& opnd);
336 
337  // Subtract Logical (Register - Mem)
338  void SubLogical(Register dst, const MemOperand& opnd);
339  void SubLogicalP(Register dst, const MemOperand& opnd);
340  void SubLogicalP_ExtendSrc(Register dst, const MemOperand& opnd);
341  // Subtract Logical 32-bit
342  void SubLogical32(Register dst, Register src1, Register src2);
343  // Subtract Logical With Borrow 32-bit
344  void SubLogicalWithBorrow32(Register dst, Register src1, Register src2);
345 
346  // Multiply
347  void MulP(Register dst, const Operand& opnd);
348  void MulP(Register dst, Register src);
349  void MulP(Register dst, const MemOperand& opnd);
350  void Mul(Register dst, Register src1, Register src2);
351  void Mul32(Register dst, const MemOperand& src1);
352  void Mul32(Register dst, Register src1);
353  void Mul32(Register dst, const Operand& src1);
354  void MulHigh32(Register dst, Register src1, const MemOperand& src2);
355  void MulHigh32(Register dst, Register src1, Register src2);
356  void MulHigh32(Register dst, Register src1, const Operand& src2);
357  void MulHighU32(Register dst, Register src1, const MemOperand& src2);
358  void MulHighU32(Register dst, Register src1, Register src2);
359  void MulHighU32(Register dst, Register src1, const Operand& src2);
360  void Mul32WithOverflowIfCCUnequal(Register dst, Register src1,
361  const MemOperand& src2);
362  void Mul32WithOverflowIfCCUnequal(Register dst, Register src1, Register src2);
363  void Mul32WithOverflowIfCCUnequal(Register dst, Register src1,
364  const Operand& src2);
365  void Mul64(Register dst, const MemOperand& src1);
366  void Mul64(Register dst, Register src1);
367  void Mul64(Register dst, const Operand& src1);
368  void MulPWithCondition(Register dst, Register src1, Register src2);
369 
370  // Divide
371  void DivP(Register dividend, Register divider);
372  void Div32(Register dst, Register src1, const MemOperand& src2);
373  void Div32(Register dst, Register src1, Register src2);
374  void DivU32(Register dst, Register src1, const MemOperand& src2);
375  void DivU32(Register dst, Register src1, Register src2);
376  void Div64(Register dst, Register src1, const MemOperand& src2);
377  void Div64(Register dst, Register src1, Register src2);
378  void DivU64(Register dst, Register src1, const MemOperand& src2);
379  void DivU64(Register dst, Register src1, Register src2);
380 
381  // Mod
382  void Mod32(Register dst, Register src1, const MemOperand& src2);
383  void Mod32(Register dst, Register src1, Register src2);
384  void ModU32(Register dst, Register src1, const MemOperand& src2);
385  void ModU32(Register dst, Register src1, Register src2);
386  void Mod64(Register dst, Register src1, const MemOperand& src2);
387  void Mod64(Register dst, Register src1, Register src2);
388  void ModU64(Register dst, Register src1, const MemOperand& src2);
389  void ModU64(Register dst, Register src1, Register src2);
390 
391  // Square root
392  void Sqrt(DoubleRegister result, DoubleRegister input);
393  void Sqrt(DoubleRegister result, const MemOperand& input);
394 
395  // Compare
396  void Cmp32(Register src1, Register src2);
397  void CmpP(Register src1, Register src2);
398  void Cmp32(Register dst, const Operand& opnd);
399  void CmpP(Register dst, const Operand& opnd);
400  void Cmp32(Register dst, const MemOperand& opnd);
401  void CmpP(Register dst, const MemOperand& opnd);
402  void CmpAndSwap(Register old_val, Register new_val, const MemOperand& opnd);
403  void CmpAndSwap64(Register old_val, Register new_val, const MemOperand& opnd);
404 
405  // Compare Logical
406  void CmpLogical32(Register src1, Register src2);
407  void CmpLogicalP(Register src1, Register src2);
408  void CmpLogical32(Register src1, const Operand& opnd);
409  void CmpLogicalP(Register src1, const Operand& opnd);
410  void CmpLogical32(Register dst, const MemOperand& opnd);
411  void CmpLogicalP(Register dst, const MemOperand& opnd);
412 
413  // Compare Logical Byte (CLI/CLIY)
414  void CmpLogicalByte(const MemOperand& mem, const Operand& imm);
415 
416  // Load 32bit
417  void Load(Register dst, const MemOperand& opnd);
418  void Load(Register dst, const Operand& opnd);
419  void LoadW(Register dst, const MemOperand& opnd, Register scratch = no_reg);
420  void LoadW(Register dst, Register src);
421  void LoadlW(Register dst, const MemOperand& opnd, Register scratch = no_reg);
422  void LoadlW(Register dst, Register src);
423  void LoadLogicalHalfWordP(Register dst, const MemOperand& opnd);
424  void LoadLogicalHalfWordP(Register dst, Register src);
425  void LoadB(Register dst, const MemOperand& opnd);
426  void LoadB(Register dst, Register src);
427  void LoadlB(Register dst, const MemOperand& opnd);
428  void LoadlB(Register dst, Register src);
429 
430  void LoadLogicalReversedWordP(Register dst, const MemOperand& opnd);
431  void LoadLogicalReversedHalfWordP(Register dst, const MemOperand& opnd);
432 
433  // Load And Test
434  void LoadAndTest32(Register dst, Register src);
435  void LoadAndTestP_ExtendSrc(Register dst, Register src);
436  void LoadAndTestP(Register dst, Register src);
437 
438  void LoadAndTest32(Register dst, const MemOperand& opnd);
439  void LoadAndTestP(Register dst, const MemOperand& opnd);
440 
441  // Load Floating Point
442  void LoadDouble(DoubleRegister dst, const MemOperand& opnd);
443  void LoadFloat32(DoubleRegister dst, const MemOperand& opnd);
444  void LoadFloat32ConvertToDouble(DoubleRegister dst, const MemOperand& mem);
445 
446  void AddFloat32(DoubleRegister dst, const MemOperand& opnd,
447  DoubleRegister scratch);
448  void AddFloat64(DoubleRegister dst, const MemOperand& opnd,
449  DoubleRegister scratch);
450  void SubFloat32(DoubleRegister dst, const MemOperand& opnd,
451  DoubleRegister scratch);
452  void SubFloat64(DoubleRegister dst, const MemOperand& opnd,
453  DoubleRegister scratch);
454  void MulFloat32(DoubleRegister dst, const MemOperand& opnd,
455  DoubleRegister scratch);
456  void MulFloat64(DoubleRegister dst, const MemOperand& opnd,
457  DoubleRegister scratch);
458  void DivFloat32(DoubleRegister dst, const MemOperand& opnd,
459  DoubleRegister scratch);
460  void DivFloat64(DoubleRegister dst, const MemOperand& opnd,
461  DoubleRegister scratch);
462  void LoadFloat32ToDouble(DoubleRegister dst, const MemOperand& opnd,
463  DoubleRegister scratch);
464 
465  // Load On Condition
466  void LoadOnConditionP(Condition cond, Register dst, Register src);
467 
468  void LoadPositiveP(Register result, Register input);
469  void LoadPositive32(Register result, Register input);
470 
471  // Store Floating Point
472  void StoreDouble(DoubleRegister dst, const MemOperand& opnd);
473  void StoreFloat32(DoubleRegister dst, const MemOperand& opnd);
474  void StoreDoubleAsFloat32(DoubleRegister src, const MemOperand& mem,
475  DoubleRegister scratch);
476 
477  void Branch(Condition c, const Operand& opnd);
478  void BranchOnCount(Register r1, Label* l);
479 
480  // Shifts
481  void ShiftLeft(Register dst, Register src, Register val);
482  void ShiftLeft(Register dst, Register src, const Operand& val);
483  void ShiftRight(Register dst, Register src, Register val);
484  void ShiftRight(Register dst, Register src, const Operand& val);
485  void ShiftLeftArith(Register dst, Register src, Register shift);
486  void ShiftLeftArith(Register dst, Register src, const Operand& val);
487  void ShiftRightArith(Register dst, Register src, Register shift);
488  void ShiftRightArith(Register dst, Register src, const Operand& val);
489 
490  void ClearRightImm(Register dst, Register src, const Operand& val);
491 
492  // Bitwise operations
493  void And(Register dst, Register src);
494  void AndP(Register dst, Register src);
495  void And(Register dst, Register src1, Register src2);
496  void AndP(Register dst, Register src1, Register src2);
497  void And(Register dst, const MemOperand& opnd);
498  void AndP(Register dst, const MemOperand& opnd);
499  void And(Register dst, const Operand& opnd);
500  void AndP(Register dst, const Operand& opnd);
501  void And(Register dst, Register src, const Operand& opnd);
502  void AndP(Register dst, Register src, const Operand& opnd);
503  void Or(Register dst, Register src);
504  void OrP(Register dst, Register src);
505  void Or(Register dst, Register src1, Register src2);
506  void OrP(Register dst, Register src1, Register src2);
507  void Or(Register dst, const MemOperand& opnd);
508  void OrP(Register dst, const MemOperand& opnd);
509  void Or(Register dst, const Operand& opnd);
510  void OrP(Register dst, const Operand& opnd);
511  void Or(Register dst, Register src, const Operand& opnd);
512  void OrP(Register dst, Register src, const Operand& opnd);
513  void Xor(Register dst, Register src);
514  void XorP(Register dst, Register src);
515  void Xor(Register dst, Register src1, Register src2);
516  void XorP(Register dst, Register src1, Register src2);
517  void Xor(Register dst, const MemOperand& opnd);
518  void XorP(Register dst, const MemOperand& opnd);
519  void Xor(Register dst, const Operand& opnd);
520  void XorP(Register dst, const Operand& opnd);
521  void Xor(Register dst, Register src, const Operand& opnd);
522  void XorP(Register dst, Register src, const Operand& opnd);
523  void Popcnt32(Register dst, Register src);
524  void Not32(Register dst, Register src = no_reg);
525  void Not64(Register dst, Register src = no_reg);
526  void NotP(Register dst, Register src = no_reg);
527 
528 #ifdef V8_TARGET_ARCH_S390X
529  void Popcnt64(Register dst, Register src);
530 #endif
531 
532  void mov(Register dst, const Operand& src);
533 
534  void CleanUInt32(Register x) {
535 #ifdef V8_TARGET_ARCH_S390X
536  llgfr(x, x);
537 #endif
538  }
539 
540 
541  void push(Register src) {
542  lay(sp, MemOperand(sp, -kPointerSize));
543  StoreP(src, MemOperand(sp));
544  }
545 
546  void pop(Register dst) {
547  LoadP(dst, MemOperand(sp));
548  la(sp, MemOperand(sp, kPointerSize));
549  }
550 
551  void pop() { la(sp, MemOperand(sp, kPointerSize)); }
552 
553  void Push(Register src) { push(src); }
554 
555  // Push a handle.
556  void Push(Handle<HeapObject> handle);
557  void Push(Smi smi);
558 
559  // Push two registers. Pushes leftmost register first (to highest address).
560  void Push(Register src1, Register src2) {
561  lay(sp, MemOperand(sp, -kPointerSize * 2));
562  StoreP(src1, MemOperand(sp, kPointerSize));
563  StoreP(src2, MemOperand(sp, 0));
564  }
565 
566  // Push three registers. Pushes leftmost register first (to highest address).
567  void Push(Register src1, Register src2, Register src3) {
568  lay(sp, MemOperand(sp, -kPointerSize * 3));
569  StoreP(src1, MemOperand(sp, kPointerSize * 2));
570  StoreP(src2, MemOperand(sp, kPointerSize));
571  StoreP(src3, MemOperand(sp, 0));
572  }
573 
574  // Push four registers. Pushes leftmost register first (to highest address).
575  void Push(Register src1, Register src2, Register src3, Register src4) {
576  lay(sp, MemOperand(sp, -kPointerSize * 4));
577  StoreP(src1, MemOperand(sp, kPointerSize * 3));
578  StoreP(src2, MemOperand(sp, kPointerSize * 2));
579  StoreP(src3, MemOperand(sp, kPointerSize));
580  StoreP(src4, MemOperand(sp, 0));
581  }
582 
583  // Push five registers. Pushes leftmost register first (to highest address).
584  void Push(Register src1, Register src2, Register src3, Register src4,
585  Register src5) {
586  DCHECK(src1 != src2);
587  DCHECK(src1 != src3);
588  DCHECK(src2 != src3);
589  DCHECK(src1 != src4);
590  DCHECK(src2 != src4);
591  DCHECK(src3 != src4);
592  DCHECK(src1 != src5);
593  DCHECK(src2 != src5);
594  DCHECK(src3 != src5);
595  DCHECK(src4 != src5);
596 
597  lay(sp, MemOperand(sp, -kPointerSize * 5));
598  StoreP(src1, MemOperand(sp, kPointerSize * 4));
599  StoreP(src2, MemOperand(sp, kPointerSize * 3));
600  StoreP(src3, MemOperand(sp, kPointerSize * 2));
601  StoreP(src4, MemOperand(sp, kPointerSize));
602  StoreP(src5, MemOperand(sp, 0));
603  }
604 
605  void Pop(Register dst) { pop(dst); }
606 
607  // Pop two registers. Pops rightmost register first (from lower address).
608  void Pop(Register src1, Register src2) {
609  LoadP(src2, MemOperand(sp, 0));
610  LoadP(src1, MemOperand(sp, kPointerSize));
611  la(sp, MemOperand(sp, 2 * kPointerSize));
612  }
613 
614  // Pop three registers. Pops rightmost register first (from lower address).
615  void Pop(Register src1, Register src2, Register src3) {
616  LoadP(src3, MemOperand(sp, 0));
617  LoadP(src2, MemOperand(sp, kPointerSize));
618  LoadP(src1, MemOperand(sp, 2 * kPointerSize));
619  la(sp, MemOperand(sp, 3 * kPointerSize));
620  }
621 
622  // Pop four registers. Pops rightmost register first (from lower address).
623  void Pop(Register src1, Register src2, Register src3, Register src4) {
624  LoadP(src4, MemOperand(sp, 0));
625  LoadP(src3, MemOperand(sp, kPointerSize));
626  LoadP(src2, MemOperand(sp, 2 * kPointerSize));
627  LoadP(src1, MemOperand(sp, 3 * kPointerSize));
628  la(sp, MemOperand(sp, 4 * kPointerSize));
629  }
630 
631  // Pop five registers. Pops rightmost register first (from lower address).
632  void Pop(Register src1, Register src2, Register src3, Register src4,
633  Register src5) {
634  LoadP(src5, MemOperand(sp, 0));
635  LoadP(src4, MemOperand(sp, kPointerSize));
636  LoadP(src3, MemOperand(sp, 2 * kPointerSize));
637  LoadP(src2, MemOperand(sp, 3 * kPointerSize));
638  LoadP(src1, MemOperand(sp, 4 * kPointerSize));
639  la(sp, MemOperand(sp, 5 * kPointerSize));
640  }
641 
642  // Push a fixed frame, consisting of lr, fp, constant pool.
643  void PushCommonFrame(Register marker_reg = no_reg);
644 
645  // Push a standard frame, consisting of lr, fp, constant pool,
646  // context and JS function
647  void PushStandardFrame(Register function_reg);
648 
649  void PopCommonFrame(Register marker_reg = no_reg);
650 
651  // Restore caller's frame pointer and return address prior to being
652  // overwritten by tail call stack preparation.
653  void RestoreFrameStateForTailCall();
654 
655  void InitializeRootRegister() {
656  ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
657  mov(kRootRegister, Operand(isolate_root));
658  }
659 
660  // If the value is a NaN, canonicalize the value else, do nothing.
661  void CanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
662  void CanonicalizeNaN(const DoubleRegister value) {
663  CanonicalizeNaN(value, value);
664  }
665 
666  // Converts the integer (untagged smi) in |src| to a double, storing
667  // the result to |dst|
668  void ConvertIntToDouble(DoubleRegister dst, Register src);
669 
670  // Converts the unsigned integer (untagged smi) in |src| to
671  // a double, storing the result to |dst|
672  void ConvertUnsignedIntToDouble(DoubleRegister dst, Register src);
673 
674  // Converts the integer (untagged smi) in |src| to
675  // a float, storing the result in |dst|
676  void ConvertIntToFloat(DoubleRegister dst, Register src);
677 
678  // Converts the unsigned integer (untagged smi) in |src| to
679  // a float, storing the result in |dst|
680  void ConvertUnsignedIntToFloat(DoubleRegister dst, Register src);
681 
682  void ConvertInt64ToFloat(DoubleRegister double_dst, Register src);
683  void ConvertInt64ToDouble(DoubleRegister double_dst, Register src);
684  void ConvertUnsignedInt64ToFloat(DoubleRegister double_dst, Register src);
685  void ConvertUnsignedInt64ToDouble(DoubleRegister double_dst, Register src);
686 
687  void MovIntToFloat(DoubleRegister dst, Register src);
688  void MovFloatToInt(Register dst, DoubleRegister src);
689  void MovDoubleToInt64(Register dst, DoubleRegister src);
690  void MovInt64ToDouble(DoubleRegister dst, Register src);
691  // Converts the double_input to an integer. Note that, upon return,
692  // the contents of double_dst will also hold the fixed point representation.
693  void ConvertFloat32ToInt64(const Register dst,
694  const DoubleRegister double_input,
695  FPRoundingMode rounding_mode = kRoundToZero);
696 
697  // Converts the double_input to an integer. Note that, upon return,
698  // the contents of double_dst will also hold the fixed point representation.
699  void ConvertDoubleToInt64(const Register dst,
700  const DoubleRegister double_input,
701  FPRoundingMode rounding_mode = kRoundToZero);
702  void ConvertDoubleToInt32(const Register dst,
703  const DoubleRegister double_input,
704  FPRoundingMode rounding_mode = kRoundToZero);
705 
706  void ConvertFloat32ToInt32(const Register result,
707  const DoubleRegister double_input,
708  FPRoundingMode rounding_mode);
709  void ConvertFloat32ToUnsignedInt32(
710  const Register result, const DoubleRegister double_input,
711  FPRoundingMode rounding_mode = kRoundToZero);
712  // Converts the double_input to an unsigned integer. Note that, upon return,
713  // the contents of double_dst will also hold the fixed point representation.
714  void ConvertDoubleToUnsignedInt64(
715  const Register dst, const DoubleRegister double_input,
716  FPRoundingMode rounding_mode = kRoundToZero);
717  void ConvertDoubleToUnsignedInt32(
718  const Register dst, const DoubleRegister double_input,
719  FPRoundingMode rounding_mode = kRoundToZero);
720  void ConvertFloat32ToUnsignedInt64(
721  const Register result, const DoubleRegister double_input,
722  FPRoundingMode rounding_mode = kRoundToZero);
723 
724 #if !V8_TARGET_ARCH_S390X
725  void ShiftLeftPair(Register dst_low, Register dst_high, Register src_low,
726  Register src_high, Register scratch, Register shift);
727  void ShiftLeftPair(Register dst_low, Register dst_high, Register src_low,
728  Register src_high, uint32_t shift);
729  void ShiftRightPair(Register dst_low, Register dst_high, Register src_low,
730  Register src_high, Register scratch, Register shift);
731  void ShiftRightPair(Register dst_low, Register dst_high, Register src_low,
732  Register src_high, uint32_t shift);
733  void ShiftRightArithPair(Register dst_low, Register dst_high,
734  Register src_low, Register src_high,
735  Register scratch, Register shift);
736  void ShiftRightArithPair(Register dst_low, Register dst_high,
737  Register src_low, Register src_high, uint32_t shift);
738 #endif
739 
740  // Generates function and stub prologue code.
741  void StubPrologue(StackFrame::Type type, Register base = no_reg,
742  int prologue_offset = 0);
743  void Prologue(Register base, int prologue_offset = 0);
744 
745  // Get the actual activation frame alignment for target environment.
746  static int ActivationFrameAlignment();
747  // ----------------------------------------------------------------
748  // new S390 macro-assembler interfaces that are slightly higher level
749  // than assembler-s390 and may generate variable length sequences
750 
751  // load a literal signed int value <value> to GPR <dst>
752  void LoadIntLiteral(Register dst, int value);
753 
754  // load an SMI value <value> to GPR <dst>
755  void LoadSmiLiteral(Register dst, Smi smi);
756 
757  // load a literal double value <value> to FPR <result>
758  void LoadDoubleLiteral(DoubleRegister result, double value, Register scratch);
759  void LoadDoubleLiteral(DoubleRegister result, uint64_t value,
760  Register scratch);
761 
762  void LoadFloat32Literal(DoubleRegister result, float value, Register scratch);
763 
764  void StoreW(Register src, const MemOperand& mem, Register scratch = no_reg);
765 
766  void LoadHalfWordP(Register dst, Register src);
767 
768  void LoadHalfWordP(Register dst, const MemOperand& mem,
769  Register scratch = no_reg);
770 
771  void StoreHalfWord(Register src, const MemOperand& mem,
772  Register scratch = r0);
773  void StoreByte(Register src, const MemOperand& mem, Register scratch = r0);
774  void CmpSmiLiteral(Register src1, Smi smi, Register scratch);
775 
776  // Set new rounding mode RN to FPSCR
777  void SetRoundingMode(FPRoundingMode RN);
778 
779  // reset rounding mode to default (kRoundToNearest)
780  void ResetRoundingMode();
781 
782  // These exist to provide portability between 32 and 64bit
783  void LoadP(Register dst, const MemOperand& mem, Register scratch = no_reg);
784  void StoreP(Register src, const MemOperand& mem, Register scratch = no_reg);
785  void StoreP(const MemOperand& mem, const Operand& opnd,
786  Register scratch = no_reg);
787  void LoadMultipleP(Register dst1, Register dst2, const MemOperand& mem);
788  void StoreMultipleP(Register dst1, Register dst2, const MemOperand& mem);
789  void LoadMultipleW(Register dst1, Register dst2, const MemOperand& mem);
790  void StoreMultipleW(Register dst1, Register dst2, const MemOperand& mem);
791 
792  void SwapP(Register src, Register dst, Register scratch);
793  void SwapP(Register src, MemOperand dst, Register scratch);
794  void SwapP(MemOperand src, MemOperand dst, Register scratch_0,
795  Register scratch_1);
796  void SwapFloat32(DoubleRegister src, DoubleRegister dst,
797  DoubleRegister scratch);
798  void SwapFloat32(DoubleRegister src, MemOperand dst, DoubleRegister scratch);
799  void SwapFloat32(MemOperand src, MemOperand dst, DoubleRegister scratch_0,
800  DoubleRegister scratch_1);
801  void SwapDouble(DoubleRegister src, DoubleRegister dst,
802  DoubleRegister scratch);
803  void SwapDouble(DoubleRegister src, MemOperand dst, DoubleRegister scratch);
804  void SwapDouble(MemOperand src, MemOperand dst, DoubleRegister scratch_0,
805  DoubleRegister scratch_1);
806 
807  // Cleanse pointer address on 31bit by zero out top bit.
808  // This is a NOP on 64-bit.
809  void CleanseP(Register src) {
810 #if (V8_HOST_ARCH_S390 && !(V8_TARGET_ARCH_S390X))
811  nilh(src, Operand(0x7FFF));
812 #endif
813  }
814 
815  void PrepareForTailCall(const ParameterCount& callee_args_count,
816  Register caller_args_count_reg, Register scratch0,
817  Register scratch1);
818 
819  // ---------------------------------------------------------------------------
820  // Runtime calls
821 
822  // Call a runtime routine. This expects {centry} to contain a fitting CEntry
823  // builtin for the target runtime function and uses an indirect call.
824  void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
825 
826  // Before calling a C-function from generated code, align arguments on stack.
827  // After aligning the frame, non-register arguments must be stored in
828  // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
829  // are word sized. If double arguments are used, this function assumes that
830  // all double arguments are stored before core registers; otherwise the
831  // correct alignment of the double values is not guaranteed.
832  // Some compilers/platforms require the stack to be aligned when calling
833  // C++ code.
834  // Needs a scratch register to do some arithmetic. This register will be
835  // trashed.
836  void PrepareCallCFunction(int num_reg_arguments, int num_double_registers,
837  Register scratch);
838  void PrepareCallCFunction(int num_reg_arguments, Register scratch);
839 
840  // There are two ways of passing double arguments on ARM, depending on
841  // whether soft or hard floating point ABI is used. These functions
842  // abstract parameter passing for the three different ways we call
843  // C functions from generated code.
844  void MovToFloatParameter(DoubleRegister src);
845  void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
846  void MovToFloatResult(DoubleRegister src);
847 
848  // Calls a C function and cleans up the space for arguments allocated
849  // by PrepareCallCFunction. The called function is not allowed to trigger a
850  // garbage collection, since that might move the code and invalidate the
851  // return address (unless this is somehow accounted for by the called
852  // function).
853  void CallCFunction(ExternalReference function, int num_arguments);
854  void CallCFunction(Register function, int num_arguments);
855  void CallCFunction(ExternalReference function, int num_reg_arguments,
856  int num_double_arguments);
857  void CallCFunction(Register function, int num_reg_arguments,
858  int num_double_arguments);
859 
860  void MovFromFloatParameter(DoubleRegister dst);
861  void MovFromFloatResult(DoubleRegister dst);
862 
863  // Emit code for a truncating division by a constant. The dividend register is
864  // unchanged and ip gets clobbered. Dividend and result must be different.
865  void TruncateDoubleToI(Isolate* isolate, Zone* zone, Register result,
866  DoubleRegister double_input, StubCallMode stub_mode);
867  void TryInlineTruncateDoubleToI(Register result, DoubleRegister double_input,
868  Label* done);
869 
870  // ---------------------------------------------------------------------------
871  // Debugging
872 
873  // Calls Abort(msg) if the condition cond is not satisfied.
874  // Use --debug_code to enable.
875  void Assert(Condition cond, AbortReason reason, CRegister cr = cr7);
876 
877  // Like Assert(), but always enabled.
878  void Check(Condition cond, AbortReason reason, CRegister cr = cr7);
879 
880  // Print a message to stdout and abort execution.
881  void Abort(AbortReason reason);
882 
883  inline bool AllowThisStubCall(CodeStub* stub);
884 
885  // ---------------------------------------------------------------------------
886  // Bit testing/extraction
887  //
888  // Bit numbering is such that the least significant bit is bit 0
889  // (for consistency between 32/64-bit).
890 
891  // Extract consecutive bits (defined by rangeStart - rangeEnd) from src
892  // and place them into the least significant bits of dst.
893  inline void ExtractBitRange(Register dst, Register src, int rangeStart,
894  int rangeEnd) {
895  DCHECK(rangeStart >= rangeEnd && rangeStart < kBitsPerSystemPointer);
896 
897  // Try to use RISBG if possible.
898  if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
899  int shiftAmount = (64 - rangeEnd) % 64; // Convert to shift left.
900  int endBit = 63; // End is always LSB after shifting.
901  int startBit = 63 - rangeStart + rangeEnd;
902  RotateInsertSelectBits(dst, src, Operand(startBit), Operand(endBit),
903  Operand(shiftAmount), true);
904  } else {
905  if (rangeEnd > 0) // Don't need to shift if rangeEnd is zero.
906  ShiftRightP(dst, src, Operand(rangeEnd));
907  else if (dst != src) // If we didn't shift, we might need to copy
908  LoadRR(dst, src);
909  int width = rangeStart - rangeEnd + 1;
910 #if V8_TARGET_ARCH_S390X
911  uint64_t mask = (static_cast<uint64_t>(1) << width) - 1;
912  nihf(dst, Operand(mask >> 32));
913  nilf(dst, Operand(mask & 0xFFFFFFFF));
914  ltgr(dst, dst);
915 #else
916  uint32_t mask = (1 << width) - 1;
917  AndP(dst, Operand(mask));
918 #endif
919  }
920  }
921 
922  inline void ExtractBit(Register dst, Register src, uint32_t bitNumber) {
923  ExtractBitRange(dst, src, bitNumber, bitNumber);
924  }
925 
926  // Extract consecutive bits (defined by mask) from src and place them
927  // into the least significant bits of dst.
928  inline void ExtractBitMask(Register dst, Register src, uintptr_t mask,
929  RCBit rc = LeaveRC) {
930  int start = kBitsPerSystemPointer - 1;
931  int end;
932  uintptr_t bit = (1L << start);
933 
934  while (bit && (mask & bit) == 0) {
935  start--;
936  bit >>= 1;
937  }
938  end = start;
939  bit >>= 1;
940 
941  while (bit && (mask & bit)) {
942  end--;
943  bit >>= 1;
944  }
945 
946  // 1-bits in mask must be contiguous
947  DCHECK(bit == 0 || (mask & ((bit << 1) - 1)) == 0);
948 
949  ExtractBitRange(dst, src, start, end);
950  }
951 
952  // Test single bit in value.
953  inline void TestBit(Register value, int bitNumber, Register scratch = r0) {
954  ExtractBitRange(scratch, value, bitNumber, bitNumber);
955  }
956 
957  // Test consecutive bit range in value. Range is defined by
958  // rangeStart - rangeEnd.
959  inline void TestBitRange(Register value, int rangeStart, int rangeEnd,
960  Register scratch = r0) {
961  ExtractBitRange(scratch, value, rangeStart, rangeEnd);
962  }
963 
964  // Test consecutive bit range in value. Range is defined by mask.
965  inline void TestBitMask(Register value, uintptr_t mask,
966  Register scratch = r0) {
967  ExtractBitMask(scratch, value, mask, SetRC);
968  }
969  inline void TestIfSmi(Register value) { tmll(value, Operand(1)); }
970 
971  inline void TestIfSmi(MemOperand value) {
972  if (is_uint12(value.offset())) {
973  tm(value, Operand(1));
974  } else if (is_int20(value.offset())) {
975  tmy(value, Operand(1));
976  } else {
977  LoadB(r0, value);
978  tmll(r0, Operand(1));
979  }
980  }
981 
982  inline void TestIfInt32(Register value) {
983  // High bits must be identical to fit into an 32-bit integer
984  cgfr(value, value);
985  }
986  void SmiUntag(Register reg, int scale = 0) { SmiUntag(reg, reg, scale); }
987 
988  void SmiUntag(Register dst, Register src, int scale = 0) {
989  if (scale > kSmiShift) {
990  ShiftLeftP(dst, src, Operand(scale - kSmiShift));
991  } else if (scale < kSmiShift) {
992  ShiftRightArithP(dst, src, Operand(kSmiShift - scale));
993  } else {
994  // do nothing
995  }
996  }
997 
998  // Activation support.
999  void EnterFrame(StackFrame::Type type,
1000  bool load_constant_pool_pointer_reg = false);
1001  // Returns the pc offset at which the frame ends.
1002  int LeaveFrame(StackFrame::Type type, int stack_adjustment = 0);
1003 
1004  void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
1005  Label* condition_met);
1006 
1007  void ResetSpeculationPoisonRegister();
1008  void ComputeCodeStartAddress(Register dst);
1009 
1010  private:
1011  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1012 
1013  void CallCFunctionHelper(Register function, int num_reg_arguments,
1014  int num_double_arguments);
1015 
1016  void CallRecordWriteStub(Register object, Register address,
1017  RememberedSetAction remembered_set_action,
1018  SaveFPRegsMode fp_mode, Handle<Code> code_target,
1019  Address wasm_target);
1020 
1021  void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
1022  int CalculateStackPassedWords(int num_reg_arguments,
1023  int num_double_arguments);
1024 };
1025 
1026 // MacroAssembler implements a collection of frequently used macros.
1027 class MacroAssembler : public TurboAssembler {
1028  public:
1029  MacroAssembler(const AssemblerOptions& options, void* buffer, int size)
1030  : TurboAssembler(options, buffer, size) {}
1031 
1032  MacroAssembler(Isolate* isolate, void* buffer, int size,
1033  CodeObjectRequired create_code_object)
1034  : MacroAssembler(isolate, AssemblerOptions::Default(isolate), buffer,
1035  size, create_code_object) {}
1036 
1037  MacroAssembler(Isolate* isolate, const AssemblerOptions& options,
1038  void* buffer, int size, CodeObjectRequired create_code_object);
1039 
1040  // Call a code stub.
1041  void TailCallStub(CodeStub* stub, Condition cond = al);
1042 
1043  void CallStub(CodeStub* stub, Condition cond = al);
1044  void CallRuntime(const Runtime::Function* f, int num_arguments,
1045  SaveFPRegsMode save_doubles = kDontSaveFPRegs);
1046  void CallRuntimeSaveDoubles(Runtime::FunctionId fid) {
1047  const Runtime::Function* function = Runtime::FunctionForId(fid);
1048  CallRuntime(function, function->nargs, kSaveFPRegs);
1049  }
1050 
1051  // Convenience function: Same as above, but takes the fid instead.
1052  void CallRuntime(Runtime::FunctionId fid,
1053  SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1054  const Runtime::Function* function = Runtime::FunctionForId(fid);
1055  CallRuntime(function, function->nargs, save_doubles);
1056  }
1057 
1058  // Convenience function: Same as above, but takes the fid instead.
1059  void CallRuntime(Runtime::FunctionId fid, int num_arguments,
1060  SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1061  CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
1062  }
1063 
1064  // Convenience function: tail call a runtime routine (jump).
1065  void TailCallRuntime(Runtime::FunctionId fid);
1066 
1067  // ---------------------------------------------------------------------------
1068  // Support functions.
1069 
1070  // Compare object type for heap object. heap_object contains a non-Smi
1071  // whose object type should be compared with the given type. This both
1072  // sets the flags and leaves the object type in the type_reg register.
1073  // It leaves the map in the map register (unless the type_reg and map register
1074  // are the same register). It leaves the heap object in the heap_object
1075  // register unless the heap_object register is the same register as one of the
1076  // other registers.
1077  // Type_reg can be no_reg. In that case ip is used.
1078  void CompareObjectType(Register heap_object, Register map, Register type_reg,
1079  InstanceType type);
1080 
1081  // Compare instance type in a map. map contains a valid map object whose
1082  // object type should be compared with the given type. This both
1083  // sets the flags and leaves the object type in the type_reg register.
1084  void CompareInstanceType(Register map, Register type_reg, InstanceType type);
1085 
1086  // Compare the object in a register to a value from the root list.
1087  // Uses the ip register as scratch.
1088  void CompareRoot(Register obj, RootIndex index);
1089  void PushRoot(RootIndex index) {
1090  LoadRoot(r0, index);
1091  Push(r0);
1092  }
1093 
1094  // Jump to a runtime routine.
1095  void JumpToExternalReference(const ExternalReference& builtin,
1096  bool builtin_exit_frame = false);
1097 
1098  // Generates a trampoline to jump to the off-heap instruction stream.
1099  void JumpToInstructionStream(Address entry);
1100 
1101  // Compare the object in a register to a value and jump if they are equal.
1102  void JumpIfRoot(Register with, RootIndex index, Label* if_equal) {
1103  CompareRoot(with, index);
1104  beq(if_equal);
1105  }
1106 
1107  // Compare the object in a register to a value and jump if they are not equal.
1108  void JumpIfNotRoot(Register with, RootIndex index, Label* if_not_equal) {
1109  CompareRoot(with, index);
1110  bne(if_not_equal);
1111  }
1112 
1113  // Try to convert a double to a signed 32-bit integer.
1114  // CR_EQ in cr7 is set and result assigned if the conversion is exact.
1115  void TryDoubleToInt32Exact(Register result, DoubleRegister double_input,
1116  Register scratch, DoubleRegister double_scratch);
1117 
1118  // ---------------------------------------------------------------------------
1119  // In-place weak references.
1120  void LoadWeakValue(Register out, Register in, Label* target_if_cleared);
1121 
1122  // ---------------------------------------------------------------------------
1123  // StatsCounter support
1124 
1125  void IncrementCounter(StatsCounter* counter, int value, Register scratch1,
1126  Register scratch2);
1127  void DecrementCounter(StatsCounter* counter, int value, Register scratch1,
1128  Register scratch2);
1129  // ---------------------------------------------------------------------------
1130  // JavaScript invokes
1131 
1132  // Set up call kind marking in ecx. The method takes ecx as an
1133  // explicit first parameter to make the code more readable at the
1134  // call sites.
1135  // void SetCallKind(Register dst, CallKind kind);
1136 
1137  // Removes current frame and its arguments from the stack preserving
1138  // the arguments and a return address pushed to the stack for the next call.
1139  // Both |callee_args_count| and |caller_args_count_reg| do not include
1140  // receiver. |callee_args_count| is not modified, |caller_args_count_reg|
1141  // is trashed.
1142 
1143  // Invoke the JavaScript function code by either calling or jumping.
1144  void InvokeFunctionCode(Register function, Register new_target,
1145  const ParameterCount& expected,
1146  const ParameterCount& actual, InvokeFlag flag);
1147 
1148  // On function call, call into the debugger if necessary.
1149  void CheckDebugHook(Register fun, Register new_target,
1150  const ParameterCount& expected,
1151  const ParameterCount& actual);
1152 
1153  // Invoke the JavaScript function in the given register. Changes the
1154  // current context to the context in the function before invoking.
1155  void InvokeFunction(Register function, Register new_target,
1156  const ParameterCount& actual, InvokeFlag flag);
1157 
1158  void InvokeFunction(Register function, const ParameterCount& expected,
1159  const ParameterCount& actual, InvokeFlag flag);
1160 
1161  // Frame restart support
1162  void MaybeDropFrames();
1163 
1164  // Exception handling
1165 
1166  // Push a new stack handler and link into stack handler chain.
1167  void PushStackHandler();
1168 
1169  // Unlink the stack handler on top of the stack from the stack handler chain.
1170  // Must preserve the result register.
1171  void PopStackHandler();
1172 
1173  // Enter exit frame.
1174  // stack_space - extra stack space, used for parameters before call to C.
1175  // At least one slot (for the return address) should be provided.
1176  void EnterExitFrame(bool save_doubles, int stack_space = 1,
1177  StackFrame::Type frame_type = StackFrame::EXIT);
1178 
1179  // Leave the current exit frame. Expects the return value in r0.
1180  // Expect the number of values, pushed prior to the exit frame, to
1181  // remove in a register (or no_reg, if there is nothing to remove).
1182  void LeaveExitFrame(bool save_doubles, Register argument_count,
1183  bool argument_count_is_length = false);
1184 
1185  // Load the global proxy from the current context.
1186  void LoadGlobalProxy(Register dst) {
1187  LoadNativeContextSlot(Context::GLOBAL_PROXY_INDEX, dst);
1188  }
1189 
1190  void LoadNativeContextSlot(int index, Register dst);
1191 
1192  // ---------------------------------------------------------------------------
1193  // Smi utilities
1194 
1195  // Shift left by kSmiShift
1196  void SmiTag(Register reg) { SmiTag(reg, reg); }
1197  void SmiTag(Register dst, Register src) {
1198  ShiftLeftP(dst, src, Operand(kSmiShift));
1199  }
1200 
1201  void SmiToPtrArrayOffset(Register dst, Register src) {
1202 #if V8_TARGET_ARCH_S390X
1203  STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kPointerSizeLog2);
1204  ShiftRightArithP(dst, src, Operand(kSmiShift - kPointerSizeLog2));
1205 #else
1206  STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kPointerSizeLog2);
1207  ShiftLeftP(dst, src, Operand(kPointerSizeLog2 - kSmiShift));
1208 #endif
1209  }
1210 
1211  // Untag the source value into destination and jump if source is a smi.
1212  // Souce and destination can be the same register.
1213  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
1214 
1215  // Jump if either of the registers contain a non-smi.
1216  inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
1217  TestIfSmi(value);
1218  bne(not_smi_label /*, cr0*/);
1219  }
1220  // Jump if either of the registers contain a smi.
1221  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
1222 
1223  // Abort execution if argument is a smi, enabled via --debug-code.
1224  void AssertNotSmi(Register object);
1225  void AssertSmi(Register object);
1226 
1227 #if V8_TARGET_ARCH_S390X
1228  // Ensure it is permissible to read/write int value directly from
1229  // upper half of the smi.
1230  STATIC_ASSERT(kSmiTag == 0);
1231  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
1232 #endif
1233 #if V8_TARGET_LITTLE_ENDIAN
1234 #define SmiWordOffset(offset) (offset + kPointerSize / 2)
1235 #else
1236 #define SmiWordOffset(offset) offset
1237 #endif
1238 
1239  // Abort execution if argument is not a Constructor, enabled via --debug-code.
1240  void AssertConstructor(Register object, Register scratch);
1241 
1242  // Abort execution if argument is not a JSFunction, enabled via --debug-code.
1243  void AssertFunction(Register object);
1244 
1245  // Abort execution if argument is not a JSBoundFunction,
1246  // enabled via --debug-code.
1247  void AssertBoundFunction(Register object);
1248 
1249  // Abort execution if argument is not a JSGeneratorObject (or subclass),
1250  // enabled via --debug-code.
1251  void AssertGeneratorObject(Register object);
1252 
1253  // Abort execution if argument is not undefined or an AllocationSite, enabled
1254  // via --debug-code.
1255  void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1256 
1257  template <typename Field>
1258  void DecodeField(Register dst, Register src) {
1259  ExtractBitRange(dst, src, Field::kShift + Field::kSize - 1, Field::kShift);
1260  }
1261 
1262  template <typename Field>
1263  void DecodeField(Register reg) {
1264  DecodeField<Field>(reg, reg);
1265  }
1266 
1267  // ---------------------------------------------------------------------------
1268  // GC Support
1269 
1270  void IncrementalMarkingRecordWriteHelper(Register object, Register value,
1271  Register address);
1272 
1273  void CallJSEntry(Register target);
1274  static int CallSizeNotPredictableCodeSize(Address target,
1275  RelocInfo::Mode rmode,
1276  Condition cond = al);
1277  void JumpToJSEntry(Register target);
1278 
1279  // Notify the garbage collector that we wrote a pointer into an object.
1280  // |object| is the object being stored into, |value| is the object being
1281  // stored. value and scratch registers are clobbered by the operation.
1282  // The offset is the offset from the start of the object, not the offset from
1283  // the tagged HeapObject pointer. For use with FieldMemOperand(reg, off).
1284  void RecordWriteField(
1285  Register object, int offset, Register value, Register scratch,
1286  LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
1287  RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
1288  SmiCheck smi_check = INLINE_SMI_CHECK);
1289 
1290  // For a given |object| notify the garbage collector that the slot |address|
1291  // has been written. |value| is the object being stored. The value and
1292  // address registers are clobbered by the operation.
1293  void RecordWrite(
1294  Register object, Register address, Register value,
1295  LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
1296  RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
1297  SmiCheck smi_check = INLINE_SMI_CHECK);
1298 
1299  // Push and pop the registers that can hold pointers, as defined by the
1300  // RegList constant kSafepointSavedRegisters.
1301  void PushSafepointRegisters();
1302  void PopSafepointRegisters();
1303 
1304  void LoadRepresentation(Register dst, const MemOperand& mem, Representation r,
1305  Register scratch = no_reg);
1306  void StoreRepresentation(Register src, const MemOperand& mem,
1307  Representation r, Register scratch = no_reg);
1308 
1309  private:
1310  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1311  // Helper functions for generating invokes.
1312  void InvokePrologue(const ParameterCount& expected,
1313  const ParameterCount& actual, Label* done,
1314  bool* definitely_mismatches, InvokeFlag flag);
1315 
1316  // Compute memory operands for safepoint stack slots.
1317  static int SafepointRegisterStackIndex(int reg_code);
1318 
1319  // Needs access to SafepointRegisterStackIndex for compiled frame
1320  // traversal.
1321  friend class StandardFrame;
1322 };
1323 
1324 // -----------------------------------------------------------------------------
1325 // Static helper functions.
1326 
1327 inline MemOperand ContextMemOperand(Register context, int index = 0) {
1328  return MemOperand(context, Context::SlotOffset(index));
1329 }
1330 
1331 inline MemOperand NativeContextMemOperand() {
1332  return ContextMemOperand(cp, Context::NATIVE_CONTEXT_INDEX);
1333 }
1334 
1335 #define ACCESS_MASM(masm) masm->
1336 
1337 } // namespace internal
1338 } // namespace v8
1339 
1340 #endif // V8_S390_MACRO_ASSEMBLER_S390_H_
Definition: libplatform.h:13