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