• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
6 // are met:
7 //
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the
14 // distribution.
15 //
16 // - Neither the name of Sun Microsystems or the names of contributors may
17 // be used to endorse or promote products derived from this software without
18 // specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 // The original source code covered by the above license above has been
34 // modified significantly by Google Inc.
35 // Copyright 2014 the V8 project authors. All rights reserved.
36 
37 // A light-weight S390 Assembler
38 // Generates user mode instructions for z/Architecture
39 
40 #ifndef V8_S390_ASSEMBLER_S390_H_
41 #define V8_S390_ASSEMBLER_S390_H_
42 #include <stdio.h>
43 #if V8_HOST_ARCH_S390
44 // elf.h include is required for auxv check for STFLE facility used
45 // for hardware detection, which is sensible only on s390 hosts.
46 #include <elf.h>
47 #endif
48 
49 #include <fcntl.h>
50 #include <unistd.h>
51 #include <vector>
52 
53 #include "src/assembler.h"
54 #include "src/s390/constants-s390.h"
55 
56 #define ABI_USES_FUNCTION_DESCRIPTORS 0
57 
58 #define ABI_PASSES_HANDLES_IN_REGS 1
59 
60 // ObjectPair is defined under runtime/runtime-util.h.
61 // On 31-bit, ObjectPair == uint64_t.  ABI dictates long long
62 //            be returned with the lower addressed half in r2
63 //            and the higher addressed half in r3. (Returns in Regs)
64 // On 64-bit, ObjectPair is a Struct.  ABI dictaes Structs be
65 //            returned in a storage buffer allocated by the caller,
66 //            with the address of this buffer passed as a hidden
67 //            argument in r2. (Does NOT return in Regs)
68 // For x86 linux, ObjectPair is returned in registers.
69 #if V8_TARGET_ARCH_S390X
70 #define ABI_RETURNS_OBJECTPAIR_IN_REGS 0
71 #else
72 #define ABI_RETURNS_OBJECTPAIR_IN_REGS 1
73 #endif
74 
75 #define ABI_CALL_VIA_IP 1
76 
77 #define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC
78 
79 namespace v8 {
80 namespace internal {
81 
82 // clang-format off
83 #define GENERAL_REGISTERS(V)                              \
84   V(r0)  V(r1)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  \
85   V(r8)  V(r9)  V(r10) V(fp) V(ip) V(r13) V(r14) V(sp)
86 
87 #define ALLOCATABLE_GENERAL_REGISTERS(V)                  \
88   V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)                \
89   V(r8)  V(r9)  V(r13)
90 
91 #define DOUBLE_REGISTERS(V)                               \
92   V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
93   V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13) V(d14) V(d15)
94 
95 #define FLOAT_REGISTERS DOUBLE_REGISTERS
96 #define SIMD128_REGISTERS DOUBLE_REGISTERS
97 
98 #define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
99   V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)         \
100   V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d15) V(d0)
101 
102 #define C_REGISTERS(V)                                            \
103   V(cr0)  V(cr1)  V(cr2)  V(cr3)  V(cr4)  V(cr5)  V(cr6)  V(cr7)  \
104   V(cr8)  V(cr9)  V(cr10) V(cr11) V(cr12) V(cr15)
105 // clang-format on
106 
107 // Register list in load/store instructions
108 // Note that the bit values must match those used in actual instruction encoding
109 const int kNumRegs = 16;
110 
111 // Caller-saved/arguments registers
112 const RegList kJSCallerSaved = 1 << 1 | 1 << 2 |  // r2  a1
113                                1 << 3 |           // r3  a2
114                                1 << 4 |           // r4  a3
115                                1 << 5;            // r5  a4
116 
117 const int kNumJSCallerSaved = 5;
118 
119 // Callee-saved registers preserved when switching from C to JavaScript
120 const RegList kCalleeSaved =
121     1 << 6 |   // r6 (argument passing in CEntryStub)
122                //    (HandleScope logic in MacroAssembler)
123     1 << 7 |   // r7 (argument passing in CEntryStub)
124                //    (HandleScope logic in MacroAssembler)
125     1 << 8 |   // r8 (argument passing in CEntryStub)
126                //    (HandleScope logic in MacroAssembler)
127     1 << 9 |   // r9 (HandleScope logic in MacroAssembler)
128     1 << 10 |  // r10 (Roots register in Javascript)
129     1 << 11 |  // r11 (fp in Javascript)
130     1 << 12 |  // r12 (ip in Javascript)
131     1 << 13;   // r13 (cp in Javascript)
132 // 1 << 15;   // r15 (sp in Javascript)
133 
134 const int kNumCalleeSaved = 8;
135 
136 #ifdef V8_TARGET_ARCH_S390X
137 
138 const RegList kCallerSavedDoubles = 1 << 0 |  // d0
139                                     1 << 1 |  // d1
140                                     1 << 2 |  // d2
141                                     1 << 3 |  // d3
142                                     1 << 4 |  // d4
143                                     1 << 5 |  // d5
144                                     1 << 6 |  // d6
145                                     1 << 7;   // d7
146 
147 const int kNumCallerSavedDoubles = 8;
148 
149 const RegList kCalleeSavedDoubles = 1 << 8 |   // d8
150                                     1 << 9 |   // d9
151                                     1 << 10 |  // d10
152                                     1 << 11 |  // d11
153                                     1 << 12 |  // d12
154                                     1 << 13 |  // d12
155                                     1 << 14 |  // d12
156                                     1 << 15;   // d13
157 
158 const int kNumCalleeSavedDoubles = 8;
159 
160 #else
161 
162 const RegList kCallerSavedDoubles = 1 << 14 |  // d14
163                                     1 << 15 |  // d15
164                                     1 << 0 |   // d0
165                                     1 << 1 |   // d1
166                                     1 << 2 |   // d2
167                                     1 << 3 |   // d3
168                                     1 << 5 |   // d5
169                                     1 << 7 |   // d7
170                                     1 << 8 |   // d8
171                                     1 << 9 |   // d9
172                                     1 << 10 |  // d10
173                                     1 << 11 |  // d10
174                                     1 << 12 |  // d10
175                                     1 << 13;   // d11
176 
177 const int kNumCallerSavedDoubles = 14;
178 
179 const RegList kCalleeSavedDoubles = 1 << 4 |  // d4
180                                     1 << 6;   // d6
181 
182 const int kNumCalleeSavedDoubles = 2;
183 
184 #endif
185 
186 // Number of registers for which space is reserved in safepoints. Must be a
187 // multiple of 8.
188 // TODO(regis): Only 8 registers may actually be sufficient. Revisit.
189 const int kNumSafepointRegisters = 16;
190 
191 // Define the list of registers actually saved at safepoints.
192 // Note that the number of saved registers may be smaller than the reserved
193 // space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
194 const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
195 const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
196 
197 // The following constants describe the stack frame linkage area as
198 // defined by the ABI.
199 
200 #if V8_TARGET_ARCH_S390X
201 // [0] Back Chain
202 // [1] Reserved for compiler use
203 // [2] GPR 2
204 // [3] GPR 3
205 // ...
206 // [15] GPR 15
207 // [16] FPR 0
208 // [17] FPR 2
209 // [18] FPR 4
210 // [19] FPR 6
211 const int kNumRequiredStackFrameSlots = 20;
212 const int kStackFrameRASlot = 14;
213 const int kStackFrameSPSlot = 15;
214 const int kStackFrameExtraParamSlot = 20;
215 #else
216 // [0] Back Chain
217 // [1] Reserved for compiler use
218 // [2] GPR 2
219 // [3] GPR 3
220 // ...
221 // [15] GPR 15
222 // [16..17] FPR 0
223 // [18..19] FPR 2
224 // [20..21] FPR 4
225 // [22..23] FPR 6
226 const int kNumRequiredStackFrameSlots = 24;
227 const int kStackFrameRASlot = 14;
228 const int kStackFrameSPSlot = 15;
229 const int kStackFrameExtraParamSlot = 24;
230 #endif
231 
232 // zLinux ABI requires caller frames to include sufficient space for
233 // callee preserved register save area.
234 #if V8_TARGET_ARCH_S390X
235 const int kCalleeRegisterSaveAreaSize = 160;
236 #elif V8_TARGET_ARCH_S390
237 const int kCalleeRegisterSaveAreaSize = 96;
238 #else
239 const int kCalleeRegisterSaveAreaSize = 0;
240 #endif
241 
242 enum RegisterCode {
243 #define REGISTER_CODE(R) kRegCode_##R,
244   GENERAL_REGISTERS(REGISTER_CODE)
245 #undef REGISTER_CODE
246       kRegAfterLast
247 };
248 
249 class Register : public RegisterBase<Register, kRegAfterLast> {
250  public:
251 #if V8_TARGET_LITTLE_ENDIAN
252   static constexpr int kMantissaOffset = 0;
253   static constexpr int kExponentOffset = 4;
254 #else
255   static constexpr int kMantissaOffset = 4;
256   static constexpr int kExponentOffset = 0;
257 #endif
258 
259  private:
260   friend class RegisterBase;
Register(int code)261   explicit constexpr Register(int code) : RegisterBase(code) {}
262 };
263 
264 ASSERT_TRIVIALLY_COPYABLE(Register);
265 static_assert(sizeof(Register) == sizeof(int),
266               "Register can efficiently be passed by value");
267 
268 #define DEFINE_REGISTER(R) \
269   constexpr Register R = Register::from_code<kRegCode_##R>();
270 GENERAL_REGISTERS(DEFINE_REGISTER)
271 #undef DEFINE_REGISTER
272 constexpr Register no_reg = Register::no_reg();
273 
274 // Register aliases
275 constexpr Register kRootRegister = r10;   // Roots array pointer.
276 constexpr Register cp = r13;              // JavaScript context pointer.
277 
278 constexpr bool kPadArguments = false;
279 constexpr bool kSimpleFPAliasing = true;
280 constexpr bool kSimdMaskRegisters = false;
281 
282 enum DoubleRegisterCode {
283 #define REGISTER_CODE(R) kDoubleCode_##R,
284   DOUBLE_REGISTERS(REGISTER_CODE)
285 #undef REGISTER_CODE
286       kDoubleAfterLast
287 };
288 
289 // Double word VFP register.
290 class DoubleRegister : public RegisterBase<DoubleRegister, kDoubleAfterLast> {
291  public:
292   // A few double registers are reserved: one as a scratch register and one to
293   // hold 0.0, that does not fit in the immediate field of vmov instructions.
294   // d14: 0.0
295   // d15: scratch register.
296   static constexpr int kSizeInBytes = 8;
297   inline static int NumRegisters();
298 
299  private:
300   friend class RegisterBase;
301 
DoubleRegister(int code)302   explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
303 };
304 
305 ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
306 static_assert(sizeof(DoubleRegister) == sizeof(int),
307               "DoubleRegister can efficiently be passed by value");
308 
309 typedef DoubleRegister FloatRegister;
310 
311 // TODO(john.yan) Define SIMD registers.
312 typedef DoubleRegister Simd128Register;
313 
314 #define DEFINE_REGISTER(R) \
315   constexpr DoubleRegister R = DoubleRegister::from_code<kDoubleCode_##R>();
316 DOUBLE_REGISTERS(DEFINE_REGISTER)
317 #undef DEFINE_REGISTER
318 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
319 
320 constexpr DoubleRegister kDoubleRegZero = d14;
321 constexpr DoubleRegister kScratchDoubleReg = d13;
322 
323 Register ToRegister(int num);
324 
325 enum CRegisterCode {
326 #define REGISTER_CODE(R) kCCode_##R,
327   C_REGISTERS(REGISTER_CODE)
328 #undef REGISTER_CODE
329       kCAfterLast
330 };
331 
332 // Coprocessor register
333 class CRegister : public RegisterBase<CRegister, kCAfterLast> {
334   friend class RegisterBase;
CRegister(int code)335   explicit constexpr CRegister(int code) : RegisterBase(code) {}
336 };
337 
338 constexpr CRegister no_creg = CRegister::no_reg();
339 #define DECLARE_C_REGISTER(R) \
340   constexpr CRegister R = CRegister::from_code<kCCode_##R>();
C_REGISTERS(DECLARE_C_REGISTER)341 C_REGISTERS(DECLARE_C_REGISTER)
342 #undef DECLARE_C_REGISTER
343 
344 // -----------------------------------------------------------------------------
345 // Machine instruction Operands
346 
347 // Class Operand represents a shifter operand in data processing instructions
348 // defining immediate numbers and masks
349 class Operand BASE_EMBEDDED {
350  public:
351   // immediate
352   V8_INLINE explicit Operand(intptr_t immediate,
353                              RelocInfo::Mode rmode = RelocInfo::NONE)
354       : rmode_(rmode) {
355     value_.immediate = immediate;
356   }
357   V8_INLINE static Operand Zero() { return Operand(static_cast<intptr_t>(0)); }
358   V8_INLINE explicit Operand(const ExternalReference& f)
359       : rmode_(RelocInfo::EXTERNAL_REFERENCE) {
360     value_.immediate = static_cast<intptr_t>(f.address());
361   }
362   explicit Operand(Handle<HeapObject> handle);
363   V8_INLINE explicit Operand(Smi* value) : rmode_(RelocInfo::NONE) {
364     value_.immediate = reinterpret_cast<intptr_t>(value);
365   }
366 
367   // rm
368   V8_INLINE explicit Operand(Register rm);
369 
370   static Operand EmbeddedNumber(double value);  // Smi or HeapNumber
371 
372   // Return true if this is a register operand.
373   V8_INLINE bool is_reg() const { return rm_.is_valid(); }
374 
375   bool must_output_reloc_info(const Assembler* assembler) const;
376 
377   inline intptr_t immediate() const {
378     DCHECK(!rm_.is_valid());
379     DCHECK(!is_heap_object_request());
380     return value_.immediate;
381   }
382 
383   HeapObjectRequest heap_object_request() const {
384     DCHECK(is_heap_object_request());
385     return value_.heap_object_request;
386   }
387 
388   inline void setBits(int n) {
389     value_.immediate =
390         (static_cast<uint32_t>(value_.immediate) << (32 - n)) >> (32 - n);
391   }
392 
393   Register rm() const { return rm_; }
394 
395   bool is_heap_object_request() const {
396     DCHECK_IMPLIES(is_heap_object_request_, !rm_.is_valid());
397     DCHECK_IMPLIES(is_heap_object_request_,
398                    rmode_ == RelocInfo::EMBEDDED_OBJECT ||
399                        rmode_ == RelocInfo::CODE_TARGET);
400     return is_heap_object_request_;
401   }
402 
403   RelocInfo::Mode rmode() const { return rmode_; }
404 
405  private:
406   Register rm_ = no_reg;
407   union Value {
408     Value() {}
409     HeapObjectRequest heap_object_request;  // if is_heap_object_request_
410     intptr_t immediate;                     // otherwise
411   } value_;                                 // valid if rm_ == no_reg
412   bool is_heap_object_request_ = false;
413 
414   RelocInfo::Mode rmode_;
415 
416   friend class Assembler;
417   friend class MacroAssembler;
418 };
419 
420 typedef int32_t Disp;
421 
422 // Class MemOperand represents a memory operand in load and store instructions
423 // On S390, we have various flavours of memory operands:
424 //   1) a base register + 16 bit unsigned displacement
425 //   2) a base register + index register + 16 bit unsigned displacement
426 //   3) a base register + index register + 20 bit signed displacement
427 class MemOperand BASE_EMBEDDED {
428  public:
429   explicit MemOperand(Register rx, Disp offset = 0);
430   explicit MemOperand(Register rx, Register rb, Disp offset = 0);
431 
offset()432   int32_t offset() const { return offset_; }
getDisplacement()433   uint32_t getDisplacement() const { return offset(); }
434 
435   // Base register
rb()436   Register rb() const {
437     DCHECK(baseRegister != no_reg);
438     return baseRegister;
439   }
440 
getBaseRegister()441   Register getBaseRegister() const { return rb(); }
442 
443   // Index Register
rx()444   Register rx() const {
445     DCHECK(indexRegister != no_reg);
446     return indexRegister;
447   }
getIndexRegister()448   Register getIndexRegister() const { return rx(); }
449 
450  private:
451   Register baseRegister;   // base
452   Register indexRegister;  // index
453   int32_t offset_;         // offset
454 
455   friend class Assembler;
456 };
457 
458 class DeferredRelocInfo {
459  public:
DeferredRelocInfo()460   DeferredRelocInfo() {}
DeferredRelocInfo(int position,RelocInfo::Mode rmode,intptr_t data)461   DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
462       : position_(position), rmode_(rmode), data_(data) {}
463 
position()464   int position() const { return position_; }
rmode()465   RelocInfo::Mode rmode() const { return rmode_; }
data()466   intptr_t data() const { return data_; }
467 
468  private:
469   int position_;
470   RelocInfo::Mode rmode_;
471   intptr_t data_;
472 };
473 
474 class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
475  public:
476   // Create an assembler. Instructions and relocation information are emitted
477   // into a buffer, with the instructions starting from the beginning and the
478   // relocation information starting from the end of the buffer. See CodeDesc
479   // for a detailed comment on the layout (globals.h).
480   //
481   // If the provided buffer is nullptr, the assembler allocates and grows its
482   // own buffer, and buffer_size determines the initial buffer size. The buffer
483   // is owned by the assembler and deallocated upon destruction of the
484   // assembler.
485   //
486   // If the provided buffer is not nullptr, the assembler uses the provided
487   // buffer for code generation and assumes its size to be buffer_size. If the
488   // buffer is too small, a fatal error occurs. No deallocation of the buffer is
489   // done upon destruction of the assembler.
490   Assembler(const AssemblerOptions& options, void* buffer, int buffer_size);
~Assembler()491   virtual ~Assembler() {}
492 
493   // GetCode emits any pending (non-emitted) code and fills the descriptor
494   // desc. GetCode() is idempotent; it returns the same result if no other
495   // Assembler functions are invoked in between GetCode() calls.
496   void GetCode(Isolate* isolate, CodeDesc* desc);
497 
498   // Label operations & relative jumps (PPUM Appendix D)
499   //
500   // Takes a branch opcode (cc) and a label (L) and generates
501   // either a backward branch or a forward branch and links it
502   // to the label fixup chain. Usage:
503   //
504   // Label L;    // unbound label
505   // j(cc, &L);  // forward branch to unbound label
506   // bind(&L);   // bind label to the current pc
507   // j(cc, &L);  // backward branch to bound label
508   // bind(&L);   // illegal: a label may be bound only once
509   //
510   // Note: The same Label can be used for forward and backward branches
511   // but it may be bound only once.
512 
513   void bind(Label* L);  // binds an unbound label L to the current code position
514 
515   // Links a label at the current pc_offset().  If already bound, returns the
516   // bound position.  If already linked, returns the position of the prior link.
517   // Otherwise, returns the current pc_offset().
518   int link(Label* L);
519 
520   // Determines if Label is bound and near enough so that a single
521   // branch instruction can be used to reach it.
522   bool is_near(Label* L, Condition cond);
523 
524   // Returns the branch offset to the given label from the current code position
525   // Links the label to the current position if it is still unbound
branch_offset(Label * L)526   int branch_offset(Label* L) { return link(L) - pc_offset(); }
527 
528   // Puts a labels target address at the given position.
529   // The high 8 bits are set to zero.
530   void label_at_put(Label* L, int at_offset);
531   void load_label_offset(Register r1, Label* L);
532 
533   // Read/Modify the code target address in the branch/call instruction at pc.
534   // The isolate argument is unused (and may be nullptr) when skipping flushing.
535   V8_INLINE static Address target_address_at(Address pc, Address constant_pool);
536   V8_INLINE static void set_target_address_at(
537       Address pc, Address constant_pool, Address target,
538       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
539 
540   // Return the code target address at a call site from the return address
541   // of that call in the instruction stream.
542   inline static Address target_address_from_return_address(Address pc);
543 
544   // Given the address of the beginning of a call, return the address
545   // in the instruction stream that the call will return to.
546   V8_INLINE static Address return_address_from_call_start(Address pc);
547 
548   inline Handle<Object> code_target_object_handle_at(Address pc);
549   // This sets the branch destination.
550   // This is for calls and branches within generated code.
551   inline static void deserialization_set_special_target_at(
552       Address instruction_payload, Code* code, Address target);
553 
554   // Get the size of the special target encoded at 'instruction_payload'.
555   inline static int deserialization_special_target_size(
556       Address instruction_payload);
557 
558   // This sets the internal reference at the pc.
559   inline static void deserialization_set_target_internal_reference_at(
560       Address pc, Address target,
561       RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
562 
563   // Here we are patching the address in the IIHF/IILF instruction pair.
564   // These values are used in the serialization process and must be zero for
565   // S390 platform, as Code, Embedded Object or External-reference pointers
566   // are split across two consecutive instructions and don't exist separately
567   // in the code, so the serializer should not step forwards in memory after
568   // a target is resolved and written.
569   static constexpr int kSpecialTargetSize = 0;
570 
571 // Number of bytes for instructions used to store pointer sized constant.
572 #if V8_TARGET_ARCH_S390X
573   static constexpr int kBytesForPtrConstant = 12;  // IIHF + IILF
574 #else
575   static constexpr int kBytesForPtrConstant = 6;  // IILF
576 #endif
577 
578   // Distance between the instruction referring to the address of the call
579   // target and the return address.
580 
581   // Offset between call target address and return address
582   // for BRASL calls
583   // Patch will be appiled to other FIXED_SEQUENCE call
584   static constexpr int kCallTargetAddressOffset = 6;
585 
586 // The length of FIXED_SEQUENCE call
587 // iihf    r8, <address_hi>  // <64-bit only>
588 // iilf    r8, <address_lo>
589 // basr    r14, r8
590 #if V8_TARGET_ARCH_S390X
591   static constexpr int kCallSequenceLength = 14;
592 #else
593   static constexpr int kCallSequenceLength = 8;
594 #endif
595 
596   // ---------------------------------------------------------------------------
597   // Code generation
598 
599   template <class T, int size, int lo, int hi>
getfield(T value)600   inline T getfield(T value) {
601     DCHECK(lo < hi);
602     DCHECK_GT(size, 0);
603     int mask = hi - lo;
604     int shift = size * 8 - hi;
605     uint32_t mask_value = (mask == 32) ? 0xffffffff : (1 << mask) - 1;
606     return (value & mask_value) << shift;
607   }
608 
609 #define DECLARE_S390_RIL_AB_INSTRUCTIONS(name, op_name, op_value) \
610   template <class R1>                                             \
611   inline void name(R1 r1, const Operand& i2) {                    \
612     ril_format(op_name, r1.code(), i2.immediate());               \
613   }
614 #define DECLARE_S390_RIL_C_INSTRUCTIONS(name, op_name, op_value) \
615   inline void name(Condition m1, const Operand& i2) {            \
616     ril_format(op_name, m1, i2.immediate());                     \
617   }
618 
ril_format(Opcode opcode,int f1,int f2)619   inline void ril_format(Opcode opcode, int f1, int f2) {
620     uint32_t op1 = opcode >> 4;
621     uint32_t op2 = opcode & 0xf;
622     emit6bytes(
623         getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
624         getfield<uint64_t, 6, 12, 16>(op2) | getfield<uint64_t, 6, 16, 48>(f2));
625   }
626   S390_RIL_A_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)
S390_RIL_B_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)627   S390_RIL_B_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)
628   S390_RIL_C_OPCODE_LIST(DECLARE_S390_RIL_C_INSTRUCTIONS)
629 #undef DECLARE_S390_RIL_AB_INSTRUCTIONS
630 #undef DECLARE_S390_RIL_C_INSTRUCTIONS
631 
632 #define DECLARE_S390_RR_INSTRUCTIONS(name, op_name, op_value) \
633   inline void name(Register r1, Register r2) {                \
634     rr_format(op_name, r1.code(), r2.code());                 \
635   }                                                           \
636   inline void name(DoubleRegister r1, DoubleRegister r2) {    \
637     rr_format(op_name, r1.code(), r2.code());                 \
638   }                                                           \
639   inline void name(Condition m1, Register r2) {               \
640     rr_format(op_name, m1, r2.code());                        \
641   }
642 
643   inline void rr_format(Opcode opcode, int f1, int f2) {
644     emit2bytes(getfield<uint16_t, 2, 0, 8>(opcode) |
645                getfield<uint16_t, 2, 8, 12>(f1) |
646                getfield<uint16_t, 2, 12, 16>(f2));
647   }
S390_RR_OPCODE_LIST(DECLARE_S390_RR_INSTRUCTIONS)648   S390_RR_OPCODE_LIST(DECLARE_S390_RR_INSTRUCTIONS)
649 #undef DECLARE_S390_RR_INSTRUCTIONS
650 
651 #define DECLARE_S390_RRD_INSTRUCTIONS(name, op_name, op_value) \
652   template <class R1, class R2, class R3>                      \
653   inline void name(R1 r1, R3 r3, R2 r2) {                      \
654     rrd_format(op_name, r1.code(), r3.code(), r2.code());      \
655   }
656   inline void rrd_format(Opcode opcode, int f1, int f2, int f3) {
657     emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
658                getfield<uint32_t, 4, 16, 20>(f1) |
659                getfield<uint32_t, 4, 24, 28>(f2) |
660                getfield<uint32_t, 4, 28, 32>(f3));
661   }
S390_RRD_OPCODE_LIST(DECLARE_S390_RRD_INSTRUCTIONS)662   S390_RRD_OPCODE_LIST(DECLARE_S390_RRD_INSTRUCTIONS)
663 #undef DECLARE_S390_RRD_INSTRUCTIONS
664 
665 #define DECLARE_S390_RRE_INSTRUCTIONS(name, op_name, op_value) \
666   template <class R1, class R2>                                \
667   inline void name(R1 r1, R2 r2) {                             \
668     rre_format(op_name, r1.code(), r2.code());                 \
669   }
670   inline void rre_format(Opcode opcode, int f1, int f2) {
671     emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
672                getfield<uint32_t, 4, 24, 28>(f1) |
673                getfield<uint32_t, 4, 28, 32>(f2));
674   }
S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS)675   S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS)
676   // Special format
677   void lzdr(DoubleRegister r1) { rre_format(LZDR, r1.code(), 0); }
678 #undef DECLARE_S390_RRE_INSTRUCTIONS
679 
680 #define DECLARE_S390_RX_INSTRUCTIONS(name, op_name, op_value)            \
681   template <class R1>                                                    \
682   inline void name(R1 r1, Register x2, Register b2, const Operand& d2) { \
683     rx_format(op_name, r1.code(), x2.code(), b2.code(),                  \
684               d2.immediate());                                           \
685   }                                                                      \
686   template <class R1>                                                    \
687   inline void name(R1 r1, const MemOperand& opnd) {                      \
688     name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(),            \
689          Operand(opnd.getDisplacement()));                               \
690   }
691 
rx_format(Opcode opcode,int f1,int f2,int f3,int f4)692   inline void rx_format(Opcode opcode, int f1, int f2, int f3, int f4) {
693     DCHECK(is_uint8(opcode));
694     DCHECK(is_uint12(f4));
695     emit4bytes(getfield<uint32_t, 4, 0, 8>(opcode) |
696                getfield<uint32_t, 4, 8, 12>(f1) |
697                getfield<uint32_t, 4, 12, 16>(f2) |
698                getfield<uint32_t, 4, 16, 20>(f3) |
699                getfield<uint32_t, 4, 20, 32>(f4));
700   }
S390_RX_A_OPCODE_LIST(DECLARE_S390_RX_INSTRUCTIONS)701   S390_RX_A_OPCODE_LIST(DECLARE_S390_RX_INSTRUCTIONS)
702 
703   void bc(Condition cond, const MemOperand& opnd) {
704     bc(cond, opnd.getIndexRegister(),
705        opnd.getBaseRegister(), Operand(opnd.getDisplacement()));
706   }
bc(Condition cond,Register x2,Register b2,const Operand & d2)707   void bc(Condition cond, Register x2, Register b2, const Operand& d2) {
708     rx_format(BC, cond, x2.code(), b2.code(), d2.immediate());
709   }
710 #undef DECLARE_S390_RX_INSTRUCTIONS
711 
712 #define DECLARE_S390_RXY_INSTRUCTIONS(name, op_name, op_value)            \
713   template <class R1, class R2>                                           \
714   inline void name(R1 r1, R2 r2, Register b2, const Operand& d2) {        \
715     rxy_format(op_name, r1.code(), r2.code(), b2.code(), d2.immediate()); \
716   }                                                                       \
717   template <class R1>                                                     \
718   inline void name(R1 r1, const MemOperand& opnd) {                       \
719     name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(),             \
720          Operand(opnd.getDisplacement()));                                \
721   }
722 
rxy_format(Opcode opcode,int f1,int f2,int f3,int f4)723   inline void rxy_format(Opcode opcode, int f1, int f2, int f3, int f4) {
724     DCHECK(is_uint16(opcode));
725     DCHECK(is_int20(f4));
726     emit6bytes(getfield<uint64_t, 6, 0, 8>(opcode >> 8) |
727                getfield<uint64_t, 6, 8, 12>(f1) |
728                getfield<uint64_t, 6, 12, 16>(f2) |
729                getfield<uint64_t, 6, 16, 20>(f3) |
730                getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
731                getfield<uint64_t, 6, 32, 40>(f4 >> 12) |
732                getfield<uint64_t, 6, 40, 48>(opcode & 0x00ff));
733   }
S390_RXY_A_OPCODE_LIST(DECLARE_S390_RXY_INSTRUCTIONS)734   S390_RXY_A_OPCODE_LIST(DECLARE_S390_RXY_INSTRUCTIONS)
735 
736   void pfd(Condition cond, const MemOperand& opnd) {
737     pfd(cond, opnd.getIndexRegister(),
738         opnd.getBaseRegister(), Operand(opnd.getDisplacement()));
739   }
pfd(Condition cond,Register x2,Register b2,const Operand & d2)740   void pfd(Condition cond, Register x2, Register b2, const Operand& d2) {
741     rxy_format(PFD, cond, x2.code(), b2.code(), d2.immediate());
742   }
743 #undef DECLARE_S390_RXY_INSTRUCTIONS
744 
745 
rsy_format(Opcode op,int f1,int f2,int f3,int f4)746 inline void rsy_format(Opcode op, int f1, int f2, int f3, int f4) {
747   DCHECK(is_int20(f4));
748   DCHECK(is_uint16(op));
749   uint64_t code = (getfield<uint64_t, 6, 0, 8>(op >> 8) |
750                    getfield<uint64_t, 6, 8, 12>(f1) |
751                    getfield<uint64_t, 6, 12, 16>(f2) |
752                    getfield<uint64_t, 6, 16, 20>(f3) |
753                    getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
754                    getfield<uint64_t, 6, 32, 40>(f4 >> 12) |
755                    getfield<uint64_t, 6, 40, 48>(op & 0xff));
756   emit6bytes(code);
757 }
758 
759 #define DECLARE_S390_RSY_A_INSTRUCTIONS(name, op_name, op_value)           \
760   void name(Register r1, Register r3, Register b2,                         \
761             const Operand& d2 = Operand::Zero()) {                         \
762     rsy_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate());  \
763   }                                                                        \
764   void name(Register r1, Register r3, Operand d2) {                        \
765     name(r1, r3, r0, d2);                                                  \
766   }                                                                        \
767   void name(Register r1, Register r3, const MemOperand& opnd) {            \
768     name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
769   }
770   S390_RSY_A_OPCODE_LIST(DECLARE_S390_RSY_A_INSTRUCTIONS);
771 #undef DECLARE_S390_RSY_A_INSTRUCTIONS
772 
773 #define DECLARE_S390_RSY_B_INSTRUCTIONS(name, op_name, op_value)            \
774   void name(Register r1, Condition m3, Register b2, const Operand& d2) {    \
775     rsy_format(op_name, r1.code(), m3, b2.code(), d2.immediate());          \
776   }                                                                         \
777   void name(Register r1, Condition m3, const MemOperand& opnd) {            \
778     name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement()));  \
779   }
780   S390_RSY_B_OPCODE_LIST(DECLARE_S390_RSY_B_INSTRUCTIONS);
781 #undef DECLARE_S390_RSY_B_INSTRUCTIONS
782 
783 
rs_format(Opcode op,int f1,int f2,int f3,const int f4)784 inline void rs_format(Opcode op, int f1, int f2, int f3, const int f4) {
785   uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
786                   getfield<uint32_t, 4, 8, 12>(f1) |
787                   getfield<uint32_t, 4, 12, 16>(f2) |
788                   getfield<uint32_t, 4, 16, 20>(f3) |
789                   getfield<uint32_t, 4, 20, 32>(f4);
790   emit4bytes(code);
791 }
792 
793 #define DECLARE_S390_RS_A_INSTRUCTIONS(name, op_name, op_value)             \
794   void name(Register r1, Register r3, Register b2, const Operand& d2) {     \
795     rs_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate());    \
796   }                                                                         \
797   void name(Register r1, Register r3, const MemOperand& opnd) {             \
798     name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement()));  \
799   }
800   S390_RS_A_OPCODE_LIST(DECLARE_S390_RS_A_INSTRUCTIONS);
801 #undef DECLARE_S390_RS_A_INSTRUCTIONS
802 
803 #define DECLARE_S390_RS_B_INSTRUCTIONS(name, op_name, op_value)             \
804   void name(Register r1, Condition m3, Register b2, const Operand& d2) {    \
805     rs_format(op_name, r1.code(), m3, b2.code(), d2.immediate());           \
806   }                                                                         \
807   void name(Register r1, Condition m3, const MemOperand& opnd) {            \
808     name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement()));  \
809   }
810   S390_RS_B_OPCODE_LIST(DECLARE_S390_RS_B_INSTRUCTIONS);
811 #undef DECLARE_S390_RS_B_INSTRUCTIONS
812 
813 #define DECLARE_S390_RS_SHIFT_FORMAT(name, opcode)                          \
814   void name(Register r1, Register r2, const Operand& opnd =                 \
815             Operand::Zero()) {                                              \
816     DCHECK(r2 != r0);                                                       \
817     rs_format(opcode, r1.code(), r0.code(), r2.code(), opnd.immediate());   \
818   }                                                                         \
819   void name(Register r1, const Operand& opnd) {                             \
820     rs_format(opcode, r1.code(), r0.code(), r0.code(), opnd.immediate());   \
821   }
DECLARE_S390_RS_SHIFT_FORMAT(sll,SLL)822   DECLARE_S390_RS_SHIFT_FORMAT(sll, SLL)
823   DECLARE_S390_RS_SHIFT_FORMAT(srl, SRL)
824   DECLARE_S390_RS_SHIFT_FORMAT(sla, SLA)
825   DECLARE_S390_RS_SHIFT_FORMAT(sra, SRA)
826   DECLARE_S390_RS_SHIFT_FORMAT(sldl, SLDL)
827   DECLARE_S390_RS_SHIFT_FORMAT(srda, SRDA)
828   DECLARE_S390_RS_SHIFT_FORMAT(srdl, SRDL)
829 #undef DECLARE_S390_RS_SHIFT_FORMAT
830 
831 
832 inline void rxe_format(Opcode op, int f1, int f2, int f3, int f4, int f5 = 0) {
833   DCHECK(is_uint12(f4));
834   DCHECK(is_uint16(op));
835   uint64_t code = (getfield<uint64_t, 6, 0, 8>(op >> 8) |
836                    getfield<uint64_t, 6, 8, 12>(f1) |
837                    getfield<uint64_t, 6, 12, 16>(f2) |
838                    getfield<uint64_t, 6, 16, 20>(f3) |
839                    getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
840                    getfield<uint64_t, 6, 32, 36>(f5) |
841                    getfield<uint64_t, 6, 40, 48>(op & 0xff));
842   emit6bytes(code);
843 }
844 
845 #define DECLARE_S390_RXE_INSTRUCTIONS(name, op_name, op_value)             \
846   void name(Register r1, Register x2, Register b2, const Operand& d2,      \
847             Condition m3 = static_cast<Condition>(0)) {                    \
848     rxe_format(op_name, r1.code(), x2.code(), b2.code(), d2.immediate(),   \
849                m3);                                                        \
850   }                                                                        \
851   template<class _R1Type>                                                  \
852   void name(_R1Type r1, const MemOperand& opnd) {                          \
853     name(Register::from_code(r1.code()), opnd.rx(), opnd.rb(),             \
854          Operand(opnd.offset()));                                          \
855   }
856   S390_RXE_OPCODE_LIST(DECLARE_S390_RXE_INSTRUCTIONS);
857 #undef DECLARE_S390_RXE_INSTRUCTIONS
858 
859 
ri_format(Opcode opcode,int f1,int f2)860 inline void ri_format(Opcode opcode, int f1, int f2) {
861   uint32_t op1 = opcode >> 4;
862   uint32_t op2 = opcode & 0xf;
863   emit4bytes(getfield<uint32_t, 4, 0, 8>(op1) |
864              getfield<uint32_t, 4, 8, 12>(f1) |
865              getfield<uint32_t, 4, 12, 16>(op2) |
866              getfield<uint32_t, 4, 16, 32>(f2));
867 }
868 
869 #define DECLARE_S390_RI_A_INSTRUCTIONS(name, op_name, op_value)            \
870   void name(Register r, const Operand& i2) {                               \
871     DCHECK(is_uint12(op_name));                                            \
872     DCHECK(is_uint16(i2.immediate()) || is_int16(i2.immediate()));         \
873     ri_format(op_name, r.code(), i2.immediate());                          \
874   }
875   S390_RI_A_OPCODE_LIST(DECLARE_S390_RI_A_INSTRUCTIONS);
876 #undef DECLARE_S390_RI_A_INSTRUCTIONS
877 
878 #define DECLARE_S390_RI_B_INSTRUCTIONS(name, op_name, op_value)            \
879   void name(Register r1, const Operand& imm) {                             \
880     /* 2nd argument encodes # of halfwords, so divide by 2. */             \
881     int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2;      \
882     Operand halfwordOp = Operand(numHalfwords);                            \
883     halfwordOp.setBits(16);                                                \
884     ri_format(op_name, r1.code(), halfwordOp.immediate());                 \
885   }
886   S390_RI_B_OPCODE_LIST(DECLARE_S390_RI_B_INSTRUCTIONS);
887 #undef DECLARE_S390_RI_B_INSTRUCTIONS
888 
889 #define DECLARE_S390_RI_C_INSTRUCTIONS(name, op_name, op_value)            \
890   void name(Condition m, const Operand& i2) {                              \
891     DCHECK(is_uint12(op_name));                                            \
892     DCHECK(is_uint4(m));                                                   \
893     DCHECK(op_name == BRC ?                                                \
894            is_int16(i2.immediate()) : is_uint16(i2.immediate()));          \
895     ri_format(op_name, m, i2.immediate());                                 \
896   }
897   S390_RI_C_OPCODE_LIST(DECLARE_S390_RI_C_INSTRUCTIONS);
898 #undef DECLARE_S390_RI_C_INSTRUCTIONS
899 
900 
rrf_format(Opcode op,int f1,int f2,int f3,int f4)901 inline void rrf_format(Opcode op, int f1, int f2, int f3, int f4) {
902   uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
903                   getfield<uint32_t, 4, 16, 20>(f1) |
904                   getfield<uint32_t, 4, 20, 24>(f2) |
905                   getfield<uint32_t, 4, 24, 28>(f3) |
906                   getfield<uint32_t, 4, 28, 32>(f4);
907   emit4bytes(code);
908 }
909 
910 #define DECLARE_S390_RRF_A_INSTRUCTIONS(name, op_name, op_value)           \
911   void name(Register r1, Condition m4, Register r2, Register r3) {         \
912     rrf_format(op_name, r3.code(), m4, r1.code(), r2.code());              \
913   }                                                                        \
914   void name(Register r1, Register r2, Register r3) {                       \
915     name(r1, Condition(0), r2, r3);                                        \
916   }
917   S390_RRF_A_OPCODE_LIST(DECLARE_S390_RRF_A_INSTRUCTIONS);
918 #undef DECLARE_S390_RRF_A_INSTRUCTIONS
919 
920 
921 #define DECLARE_S390_RRF_B_INSTRUCTIONS(name, op_name, op_value)           \
922   void name(Register r1, Condition m4, Register r2, Register r3) {         \
923     rrf_format(op_name, r3.code(), m4, r1.code(), r2.code());              \
924   }                                                                        \
925   void name(Register r1, Register r2, Register r3) {                       \
926     name(r1, Condition(0), r2, r3);                                        \
927   }
928   S390_RRF_B_OPCODE_LIST(DECLARE_S390_RRF_B_INSTRUCTIONS);
929 #undef DECLARE_S390_RRF_B_INSTRUCTIONS
930 
931 
932 #define DECLARE_S390_RRF_C_INSTRUCTIONS(name, op_name, op_value)           \
933   template <class R1, class R2>                                            \
934   void name(Condition m3, Condition m4, R1 r1, R2 r2) {                    \
935     rrf_format(op_name, m3, m4, r1.code(), r2.code());                     \
936   }                                                                        \
937   template <class R1, class R2>                                            \
938   void name(Condition m3, R1 r1, R2 r2) {                                  \
939     name(m3, Condition(0), r1, r2);                                        \
940   }
941   S390_RRF_C_OPCODE_LIST(DECLARE_S390_RRF_C_INSTRUCTIONS);
942 #undef DECLARE_S390_RRF_C_INSTRUCTIONS
943 
944 
945 #define DECLARE_S390_RRF_D_INSTRUCTIONS(name, op_name, op_value)           \
946   template <class R1, class R2>                                            \
947   void name(Condition m3, Condition m4, R1 r1, R2 r2) {                    \
948     rrf_format(op_name, m3, m4, r1.code(), r2.code());                     \
949   }                                                                        \
950   template <class R1, class R2>                                            \
951   void name(Condition m3, R1 r1, R2 r2) {                                  \
952     name(m3, Condition(0), r1, r2);                                        \
953   }
954   S390_RRF_D_OPCODE_LIST(DECLARE_S390_RRF_D_INSTRUCTIONS);
955 #undef DECLARE_S390_RRF_D_INSTRUCTIONS
956 
957 
958 #define DECLARE_S390_RRF_E_INSTRUCTIONS(name, op_name, op_value)           \
959   template <class M3, class M4, class R1, class R2>                        \
960   void name(M3 m3, M4 m4, R1 r1, R2 r2) {                                  \
961     rrf_format(op_name, m3, m4, r1.code(), r2.code());                     \
962   }                                                                        \
963   template <class M3, class R1, class R2>                                  \
964   void name(M3 m3, R1 r1, R2 r2) {                                         \
965     name(m3, Condition(0), r1, r2);                                        \
966   }
967   S390_RRF_E_OPCODE_LIST(DECLARE_S390_RRF_E_INSTRUCTIONS);
968 #undef DECLARE_S390_RRF_E_INSTRUCTIONS
969 
970 enum FIDBRA_FLAGS {
971   FIDBRA_CURRENT_ROUNDING_MODE = 0,
972   FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0 = 1,
973   // ...
974   FIDBRA_ROUND_TOWARD_0 = 5,
975   FIDBRA_ROUND_TOWARD_POS_INF = 6,
976   FIDBRA_ROUND_TOWARD_NEG_INF = 7
977 };
978 
979 
rsi_format(Opcode op,int f1,int f2,int f3)980 inline void rsi_format(Opcode op, int f1, int f2, int f3) {
981   DCHECK(is_uint8(op));
982   DCHECK(is_uint16(f3) || is_int16(f3));
983   uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
984                   getfield<uint32_t, 4, 8, 12>(f1) |
985                   getfield<uint32_t, 4, 12, 16>(f2) |
986                   getfield<uint32_t, 4, 16, 32>(f3);
987   emit4bytes(code);
988 }
989 
990 #define DECLARE_S390_RSI_INSTRUCTIONS(name, op_name, op_value)           \
991   void name(Register r1, Register r3, const Operand& i2) {               \
992     rsi_format(op_name, r1.code(), r3.code(), i2.immediate());           \
993   }
994   S390_RSI_OPCODE_LIST(DECLARE_S390_RSI_INSTRUCTIONS);
995 #undef DECLARE_S390_RSI_INSTRUCTIONS
996 
997 
rsl_format(Opcode op,uint16_t f1,int f2,int f3,int f4,int f5)998 inline void rsl_format(Opcode op, uint16_t f1, int f2, int f3, int f4,
999                        int f5) {
1000   DCHECK(is_uint16(op));
1001   uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1002                   getfield<uint64_t, 6, 8, 16>(f1) |
1003                   getfield<uint64_t, 6, 16, 20>(f2) |
1004                   getfield<uint64_t, 6, 20, 32>(f3) |
1005                   getfield<uint64_t, 6, 32, 36>(f4) |
1006                   getfield<uint64_t, 6, 36, 40>(f5) |
1007                   getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1008   emit6bytes(code);
1009 }
1010 
1011 #define DECLARE_S390_RSL_A_INSTRUCTIONS(name, op_name, op_value)         \
1012   void name(const Operand& l1, Register b1, const Operand& d1) {         \
1013     uint16_t L = static_cast<uint16_t>(l1.immediate() << 8);             \
1014     rsl_format(op_name, L, b1.code(), d1.immediate(), 0, 0);             \
1015   }
1016   S390_RSL_A_OPCODE_LIST(DECLARE_S390_RSL_A_INSTRUCTIONS);
1017 #undef DECLARE_S390_RSL_A_INSTRUCTIONS
1018 
1019 #define DECLARE_S390_RSL_B_INSTRUCTIONS(name, op_name, op_value)         \
1020   void name(const Operand& l2, Register b2, const Operand& d2,           \
1021             Register r1, Condition m3) {                                 \
1022     uint16_t L = static_cast<uint16_t>(l2.immediate());                  \
1023     rsl_format(op_name, L, b2.code(), d2.immediate(), r1.code(), m3);    \
1024   }
1025   S390_RSL_B_OPCODE_LIST(DECLARE_S390_RSL_B_INSTRUCTIONS);
1026 #undef DECLARE_S390_RSL_B_INSTRUCTIONS
1027 
1028 
s_format(Opcode op,int f1,int f2)1029 inline void s_format(Opcode op, int f1, int f2) {
1030   DCHECK_NE(op & 0xff00, 0);
1031   DCHECK(is_uint12(f2));
1032   uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
1033                   getfield<uint32_t, 4, 16, 20>(f1) |
1034                   getfield<uint32_t, 4, 20, 32>(f2);
1035   emit4bytes(code);
1036 }
1037 
1038 #define DECLARE_S390_S_INSTRUCTIONS(name, op_name, op_value)             \
1039   void name(Register b1, const Operand& d2) {                            \
1040     Opcode op = op_name;                                                 \
1041     if ((op & 0xFF00) == 0) {                                            \
1042       op = (Opcode)(op << 8);                                            \
1043     }                                                                    \
1044     s_format(op, b1.code(), d2.immediate());                             \
1045   }                                                                      \
1046   void name(const MemOperand& opnd) {                                    \
1047     Operand d2 = Operand(opnd.getDisplacement());                        \
1048     name(opnd.getBaseRegister(), d2);                                    \
1049   }
1050   S390_S_OPCODE_LIST(DECLARE_S390_S_INSTRUCTIONS);
1051 #undef DECLARE_S390_S_INSTRUCTIONS
1052 
1053 
si_format(Opcode op,int f1,int f2,int f3)1054 inline void si_format(Opcode op, int f1, int f2, int f3) {
1055   uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
1056                   getfield<uint32_t, 4, 8, 16>(f1) |
1057                   getfield<uint32_t, 4, 16, 20>(f2) |
1058                   getfield<uint32_t, 4, 20, 32>(f3);
1059   emit4bytes(code);
1060 }
1061 
1062 #define DECLARE_S390_SI_INSTRUCTIONS(name, op_name, op_value)            \
1063   void name(const Operand& i2, Register b1, const Operand& d1) {         \
1064     si_format(op_name, i2.immediate(), b1.code(), d1.immediate());       \
1065   }                                                                      \
1066   void name(const MemOperand& opnd, const Operand& i2) {                 \
1067     name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement()));   \
1068   }
1069   S390_SI_OPCODE_LIST(DECLARE_S390_SI_INSTRUCTIONS);
1070 #undef DECLARE_S390_SI_INSTRUCTIONS
1071 
1072 
siy_format(Opcode op,int f1,int f2,int f3)1073 inline void siy_format(Opcode op, int f1, int f2, int f3) {
1074   DCHECK(is_uint20(f3) || is_int20(f3));
1075   DCHECK(is_uint16(op));
1076   DCHECK(is_uint8(f1) || is_int8(f1));
1077   uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1078                   getfield<uint64_t, 6, 8, 16>(f1) |
1079                   getfield<uint64_t, 6, 16, 20>(f2) |
1080                   getfield<uint64_t, 6, 20, 32>(f3) |
1081                   getfield<uint64_t, 6, 32, 40>(f3 >> 12) |
1082                   getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1083   emit6bytes(code);
1084 }
1085 
1086 #define DECLARE_S390_SIY_INSTRUCTIONS(name, op_name, op_value)           \
1087   void name(const Operand& i2, Register b1, const Operand& d1) {         \
1088     siy_format(op_name, i2.immediate(), b1.code(), d1.immediate());      \
1089   }                                                                      \
1090   void name(const MemOperand& opnd, const Operand& i2) {                 \
1091     name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement()));   \
1092   }
1093   S390_SIY_OPCODE_LIST(DECLARE_S390_SIY_INSTRUCTIONS);
1094 #undef DECLARE_S390_SIY_INSTRUCTIONS
1095 
1096 
rrs_format(Opcode op,int f1,int f2,int f3,int f4,int f5)1097 inline void rrs_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
1098   DCHECK(is_uint12(f4));
1099   DCHECK(is_uint16(op));
1100   uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1101                   getfield<uint64_t, 6, 8, 12>(f1) |
1102                   getfield<uint64_t, 6, 12, 16>(f2) |
1103                   getfield<uint64_t, 6, 16, 20>(f3) |
1104                   getfield<uint64_t, 6, 20, 32>(f4) |
1105                   getfield<uint64_t, 6, 32, 36>(f5) |
1106                   getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1107   emit6bytes(code);
1108 }
1109 
1110 #define DECLARE_S390_RRS_INSTRUCTIONS(name, op_name, op_value)           \
1111   void name(Register r1, Register r2, Register b4, const Operand& d4,    \
1112             Condition m3) {                                              \
1113     rrs_format(op_name, r1.code(), r2.code(), b4.code(), d4.immediate(), \
1114                m3);                                                      \
1115   }                                                                      \
1116   void name(Register r1, Register r2, Condition m3,                      \
1117             const MemOperand& opnd) {                                    \
1118     name(r1, r2, opnd.getBaseRegister(),                                 \
1119          Operand(opnd.getDisplacement()), m3);                           \
1120   }
1121   S390_RRS_OPCODE_LIST(DECLARE_S390_RRS_INSTRUCTIONS);
1122 #undef DECLARE_S390_RRS_INSTRUCTIONS
1123 
1124 
ris_format(Opcode op,int f1,int f2,int f3,int f4,int f5)1125 inline void ris_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
1126   DCHECK(is_uint12(f3));
1127   DCHECK(is_uint16(op));
1128   DCHECK(is_uint8(f5));
1129   uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1130                   getfield<uint64_t, 6, 8, 12>(f1) |
1131                   getfield<uint64_t, 6, 12, 16>(f2) |
1132                   getfield<uint64_t, 6, 16, 20>(f3) |
1133                   getfield<uint64_t, 6, 20, 32>(f4) |
1134                   getfield<uint64_t, 6, 32, 40>(f5) |
1135                   getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1136   emit6bytes(code);
1137 }
1138 
1139 #define DECLARE_S390_RIS_INSTRUCTIONS(name, op_name, op_value)           \
1140   void name(Register r1, Condition m3, Register b4, const Operand& d4,   \
1141                        const Operand& i2) {                              \
1142     ris_format(op_name, r1.code(), m3, b4.code(), d4.immediate(),        \
1143                i2.immediate());                                          \
1144   }                                                                      \
1145   void name(Register r1, const Operand& i2, Condition m3,                \
1146                        const MemOperand& opnd) {                         \
1147     name(r1, m3, opnd.getBaseRegister(),                                 \
1148          Operand(opnd.getDisplacement()), i2);                           \
1149   }
1150   S390_RIS_OPCODE_LIST(DECLARE_S390_RIS_INSTRUCTIONS);
1151 #undef DECLARE_S390_RIS_INSTRUCTIONS
1152 
1153 
sil_format(Opcode op,int f1,int f2,int f3)1154 inline void sil_format(Opcode op, int f1, int f2, int f3) {
1155   DCHECK(is_uint12(f2));
1156   DCHECK(is_uint16(op));
1157   DCHECK(is_uint16(f3));
1158   uint64_t code = getfield<uint64_t, 6, 0, 16>(op) |
1159                   getfield<uint64_t, 6, 16, 20>(f1) |
1160                   getfield<uint64_t, 6, 20, 32>(f2) |
1161                   getfield<uint64_t, 6, 32, 48>(f3);
1162   emit6bytes(code);
1163 }
1164 
1165 #define DECLARE_S390_SIL_INSTRUCTIONS(name, op_name, op_value)           \
1166   void name(Register b1, const Operand& d1, const Operand& i2) {         \
1167     sil_format(op_name, b1.code(), d1.immediate(), i2.immediate());      \
1168   }                                                                      \
1169   void name(const MemOperand& opnd, const Operand& i2) {                 \
1170     name(opnd.getBaseRegister(), Operand(opnd.getDisplacement()), i2);   \
1171   }
1172   S390_SIL_OPCODE_LIST(DECLARE_S390_SIL_INSTRUCTIONS);
1173 #undef DECLARE_S390_SIL_INSTRUCTIONS
1174 
1175 
rie_d_format(Opcode opcode,int f1,int f2,int f3,int f4)1176 inline void rie_d_format(Opcode opcode, int f1, int f2, int f3, int f4) {
1177   uint32_t op1 = opcode >> 8;
1178   uint32_t op2 = opcode & 0xff;
1179   uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1180                   getfield<uint64_t, 6, 8, 12>(f1) |
1181                   getfield<uint64_t, 6, 12, 16>(f2) |
1182                   getfield<uint64_t, 6, 16, 32>(f3) |
1183                   getfield<uint64_t, 6, 32, 40>(f4) |
1184                   getfield<uint64_t, 6, 40, 48>(op2);
1185   emit6bytes(code);
1186 }
1187 
1188 #define DECLARE_S390_RIE_D_INSTRUCTIONS(name, op_name, op_value)         \
1189   void name(Register r1, Register r3, const Operand& i2) {               \
1190     rie_d_format(op_name, r1.code(), r3.code(), i2.immediate(), 0);      \
1191   }
S390_RIE_D_OPCODE_LIST(DECLARE_S390_RIE_D_INSTRUCTIONS)1192   S390_RIE_D_OPCODE_LIST(DECLARE_S390_RIE_D_INSTRUCTIONS)
1193 #undef DECLARE_S390_RIE_D_INSTRUCTIONS
1194 
1195 
1196 inline void rie_e_format(Opcode opcode, int f1, int f2, int f3) {
1197   uint32_t op1 = opcode >> 8;
1198   uint32_t op2 = opcode & 0xff;
1199   uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1200                   getfield<uint64_t, 6, 8, 12>(f1) |
1201                   getfield<uint64_t, 6, 12, 16>(f2) |
1202                   getfield<uint64_t, 6, 16, 32>(f3) |
1203                   getfield<uint64_t, 6, 40, 48>(op2);
1204   emit6bytes(code);
1205 }
1206 
1207 #define DECLARE_S390_RIE_E_INSTRUCTIONS(name, op_name, op_value)         \
1208   void name(Register r1, Register r3, const Operand& i2) {               \
1209     rie_e_format(op_name, r1.code(), r3.code(), i2.immediate());         \
1210   }
S390_RIE_E_OPCODE_LIST(DECLARE_S390_RIE_E_INSTRUCTIONS)1211   S390_RIE_E_OPCODE_LIST(DECLARE_S390_RIE_E_INSTRUCTIONS)
1212 #undef DECLARE_S390_RIE_E_INSTRUCTIONS
1213 
1214 
1215 inline void rie_f_format(Opcode opcode, int f1, int f2, int f3, int f4,
1216                          int f5) {
1217   uint32_t op1 = opcode >> 8;
1218   uint32_t op2 = opcode & 0xff;
1219   uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1220                   getfield<uint64_t, 6, 8, 12>(f1) |
1221                   getfield<uint64_t, 6, 12, 16>(f2) |
1222                   getfield<uint64_t, 6, 16, 24>(f3) |
1223                   getfield<uint64_t, 6, 24, 32>(f4) |
1224                   getfield<uint64_t, 6, 32, 40>(f5) |
1225                   getfield<uint64_t, 6, 40, 48>(op2);
1226   emit6bytes(code);
1227 }
1228 
1229 #define DECLARE_S390_RIE_F_INSTRUCTIONS(name, op_name, op_value)         \
1230   void name(Register dst, Register src, const Operand& startBit,         \
1231             const Operand& endBit, const Operand& shiftAmt) {            \
1232     DCHECK(is_uint8(startBit.immediate()));                              \
1233     DCHECK(is_uint8(endBit.immediate()));                                \
1234     DCHECK(is_uint8(shiftAmt.immediate()));                              \
1235     rie_f_format(op_name, dst.code(), src.code(), startBit.immediate(),  \
1236                  endBit.immediate(), shiftAmt.immediate());              \
1237   }
S390_RIE_F_OPCODE_LIST(DECLARE_S390_RIE_F_INSTRUCTIONS)1238   S390_RIE_F_OPCODE_LIST(DECLARE_S390_RIE_F_INSTRUCTIONS)
1239 #undef DECLARE_S390_RIE_F_INSTRUCTIONS
1240 
1241 
1242 inline void ss_a_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
1243   DCHECK(is_uint12(f5));
1244   DCHECK(is_uint12(f3));
1245   DCHECK(is_uint8(f1));
1246   DCHECK(is_uint8(op));
1247   uint64_t code = getfield<uint64_t, 6, 0, 8>(op) |
1248                   getfield<uint64_t, 6, 8, 16>(f1) |
1249                   getfield<uint64_t, 6, 16, 20>(f2) |
1250                   getfield<uint64_t, 6, 20, 32>(f3) |
1251                   getfield<uint64_t, 6, 32, 36>(f4) |
1252                   getfield<uint64_t, 6, 36, 48>(f5);
1253   emit6bytes(code);
1254 }
1255 
1256 #define DECLARE_S390_SS_A_INSTRUCTIONS(name, op_name, op_value)          \
1257   void name(Register b1, const Operand& d1, Register b2,                 \
1258             const Operand& d2, const Operand& length) {                  \
1259     ss_a_format(op_name, length.immediate(), b1.code(), d1.immediate(),  \
1260                 b2.code(), d2.immediate());                              \
1261   }                                                                      \
1262   void name(const MemOperand& opnd1, const MemOperand& opnd2,            \
1263             const Operand& length) {                                     \
1264     ss_a_format(op_name, length.immediate(),                             \
1265                 opnd1.getBaseRegister().code(),                          \
1266                 opnd1.getDisplacement(), opnd2.getBaseRegister().code(), \
1267                 opnd2.getDisplacement());                                \
1268   }
S390_SS_A_OPCODE_LIST(DECLARE_S390_SS_A_INSTRUCTIONS)1269   S390_SS_A_OPCODE_LIST(DECLARE_S390_SS_A_INSTRUCTIONS)
1270 #undef DECLARE_S390_SS_A_INSTRUCTIONS
1271 
1272 
1273   // Helper for unconditional branch to Label with update to save register
1274   void b(Register r, Label* l) {
1275     int32_t halfwords = branch_offset(l) / 2;
1276     brasl(r, Operand(halfwords));
1277   }
1278 
1279   // Conditional Branch Instruction - Generates either BRC / BRCL
1280   void branchOnCond(Condition c, int branch_offset, bool is_bound = false);
1281 
1282   // Helpers for conditional branch to Label
1283   void b(Condition cond, Label* l, Label::Distance dist = Label::kFar) {
1284     branchOnCond(cond, branch_offset(l),
1285                  l->is_bound() || (dist == Label::kNear));
1286   }
1287 
1288   void bc_short(Condition cond, Label* l, Label::Distance dist = Label::kFar) {
1289     b(cond, l, Label::kNear);
1290   }
1291   // Helpers for conditional branch to Label
1292   void beq(Label* l, Label::Distance dist = Label::kFar) { b(eq, l, dist); }
1293   void bne(Label* l, Label::Distance dist = Label::kFar) { b(ne, l, dist); }
1294   void blt(Label* l, Label::Distance dist = Label::kFar) { b(lt, l, dist); }
1295   void ble(Label* l, Label::Distance dist = Label::kFar) { b(le, l, dist); }
1296   void bgt(Label* l, Label::Distance dist = Label::kFar) { b(gt, l, dist); }
1297   void bge(Label* l, Label::Distance dist = Label::kFar) { b(ge, l, dist); }
1298   void b(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); }
1299   void jmp(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); }
1300   void bunordered(Label* l, Label::Distance dist = Label::kFar) {
1301     b(unordered, l, dist);
1302   }
1303   void bordered(Label* l, Label::Distance dist = Label::kFar) {
1304     b(ordered, l, dist);
1305   }
1306 
1307   // Helpers for conditional indirect branch off register
b(Condition cond,Register r)1308   void b(Condition cond, Register r) { bcr(cond, r); }
beq(Register r)1309   void beq(Register r) { b(eq, r); }
bne(Register r)1310   void bne(Register r) { b(ne, r); }
blt(Register r)1311   void blt(Register r) { b(lt, r); }
ble(Register r)1312   void ble(Register r) { b(le, r); }
bgt(Register r)1313   void bgt(Register r) { b(gt, r); }
bge(Register r)1314   void bge(Register r) { b(ge, r); }
b(Register r)1315   void b(Register r) { b(al, r); }
jmp(Register r)1316   void jmp(Register r) { b(al, r); }
bunordered(Register r)1317   void bunordered(Register r) { b(unordered, r); }
bordered(Register r)1318   void bordered(Register r) { b(ordered, r); }
1319 
1320   // wrappers around asm instr
brxh(Register dst,Register inc,Label * L)1321   void brxh(Register dst, Register inc, Label* L) {
1322     int offset_halfwords = branch_offset(L) / 2;
1323     CHECK(is_int16(offset_halfwords));
1324     brxh(dst, inc, Operand(offset_halfwords));
1325   }
1326 
brxhg(Register dst,Register inc,Label * L)1327   void brxhg(Register dst, Register inc, Label* L) {
1328     int offset_halfwords = branch_offset(L) / 2;
1329     CHECK(is_int16(offset_halfwords));
1330     brxhg(dst, inc, Operand(offset_halfwords));
1331   }
1332 
1333   template <class R1, class R2>
ledbr(R1 r1,R2 r2)1334   void ledbr(R1 r1, R2 r2) {
1335     ledbra(Condition(0), Condition(0), r1, r2);
1336   }
1337 
1338   template <class R1, class R2>
cdfbr(R1 r1,R2 r2)1339   void cdfbr(R1 r1, R2 r2) {
1340     cdfbra(Condition(0), Condition(0), r1, r2);
1341   }
1342 
1343   template <class R1, class R2>
cdgbr(R1 r1,R2 r2)1344   void cdgbr(R1 r1, R2 r2) {
1345     cdgbra(Condition(0), Condition(0), r1, r2);
1346   }
1347 
1348   template <class R1, class R2>
cegbr(R1 r1,R2 r2)1349   void cegbr(R1 r1, R2 r2) {
1350     cegbra(Condition(0), Condition(0), r1, r2);
1351   }
1352 
1353   template <class R1, class R2>
cgebr(Condition m3,R1 r1,R2 r2)1354   void cgebr(Condition m3, R1 r1, R2 r2) {
1355     cgebra(m3, Condition(0), r1, r2);
1356   }
1357 
1358   template <class R1, class R2>
cgdbr(Condition m3,R1 r1,R2 r2)1359   void cgdbr(Condition m3, R1 r1, R2 r2) {
1360     cgdbra(m3, Condition(0), r1, r2);
1361   }
1362 
1363   template <class R1, class R2>
cfdbr(Condition m3,R1 r1,R2 r2)1364   void cfdbr(Condition m3, R1 r1, R2 r2) {
1365     cfdbra(m3, Condition(0), r1, r2);
1366   }
1367 
1368   template <class R1, class R2>
cfebr(Condition m3,R1 r1,R2 r2)1369   void cfebr(Condition m3, R1 r1, R2 r2) {
1370     cfebra(m3, Condition(0), r1, r2);
1371   }
1372 
1373   // ---------------------------------------------------------------------------
1374   // Code generation
1375 
1376   // Insert the smallest number of nop instructions
1377   // possible to align the pc offset to a multiple
1378   // of m. m must be a power of 2 (>= 4).
1379   void Align(int m);
1380   // Insert the smallest number of zero bytes possible to align the pc offset
1381   // to a mulitple of m. m must be a power of 2 (>= 2).
1382   void DataAlign(int m);
1383   // Aligns code to something that's optimal for a jump target for the platform.
1384   void CodeTargetAlign();
1385 
breakpoint(bool do_print)1386   void breakpoint(bool do_print) {
1387     if (do_print) {
1388       PrintF("DebugBreak is inserted to %p\n", static_cast<void*>(pc_));
1389     }
1390 #if V8_HOST_ARCH_64_BIT
1391     int64_t value = reinterpret_cast<uint64_t>(&v8::base::OS::DebugBreak);
1392     int32_t hi_32 = static_cast<int64_t>(value) >> 32;
1393     int32_t lo_32 = static_cast<int32_t>(value);
1394 
1395     iihf(r1, Operand(hi_32));
1396     iilf(r1, Operand(lo_32));
1397 #else
1398     iilf(r1, Operand(reinterpret_cast<uint32_t>(&v8::base::OS::DebugBreak)));
1399 #endif
1400     basr(r14, r1);
1401   }
1402 
1403   void call(Handle<Code> target, RelocInfo::Mode rmode);
1404   void call(CodeStub* stub);
1405   void jump(Handle<Code> target, RelocInfo::Mode rmode, Condition cond);
1406 
1407 // S390 instruction generation
1408 #define DECLARE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value)           \
1409   void name(DoubleRegister v1, DoubleRegister v2, Condition m5, Condition m4, \
1410             Condition m3) {                                                   \
1411     uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 |    \
1412                     (static_cast<uint64_t>(v1.code())) * B36 |                \
1413                     (static_cast<uint64_t>(v2.code())) * B32 |                \
1414                     (static_cast<uint64_t>(m5 & 0xF)) * B20 |                 \
1415                     (static_cast<uint64_t>(m4 & 0xF)) * B16 |                 \
1416                     (static_cast<uint64_t>(m3 & 0xF)) * B12 |                 \
1417                     (static_cast<uint64_t>(opcode_value & 0x00FF));           \
1418     emit6bytes(code);                                                         \
1419   }
1420   S390_VRR_A_OPCODE_LIST(DECLARE_VRR_A_INSTRUCTIONS)
1421 #undef DECLARE_VRR_A_INSTRUCTIONS
1422 
1423 #define DECLARE_VRR_C_INSTRUCTIONS(name, opcode_name, opcode_value)        \
1424   void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3,       \
1425             Condition m6, Condition m5, Condition m4) {                    \
1426     uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1427                     (static_cast<uint64_t>(v1.code())) * B36 |             \
1428                     (static_cast<uint64_t>(v2.code())) * B32 |             \
1429                     (static_cast<uint64_t>(v3.code())) * B28 |             \
1430                     (static_cast<uint64_t>(m6 & 0xF)) * B20 |              \
1431                     (static_cast<uint64_t>(m5 & 0xF)) * B16 |              \
1432                     (static_cast<uint64_t>(m4 & 0xF)) * B12 |              \
1433                     (static_cast<uint64_t>(opcode_value & 0x00FF));        \
1434     emit6bytes(code);                                                      \
1435   }
S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS)1436   S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS)
1437 #undef DECLARE_VRR_C_INSTRUCTIONS
1438 
1439   // Single Element format
1440   void vfa(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1441     vfa(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1442         static_cast<Condition>(3));
1443   }
vfs(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)1444   void vfs(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1445     vfs(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1446         static_cast<Condition>(3));
1447   }
vfm(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)1448   void vfm(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1449     vfm(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1450         static_cast<Condition>(3));
1451   }
vfd(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)1452   void vfd(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1453     vfd(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1454         static_cast<Condition>(3));
1455   }
1456 
1457   // Load Address Instructions
1458   void larl(Register r, Label* l);
1459 
1460   // Exception-generating instructions and debugging support
1461   void stop(const char* msg, Condition cond = al,
1462             int32_t code = kDefaultStopCode, CRegister cr = cr7);
1463 
1464   void bkpt(uint32_t imm16);  // v5 and above
1465 
1466   // Different nop operations are used by the code generator to detect certain
1467   // states of the generated code.
1468   enum NopMarkerTypes {
1469     NON_MARKING_NOP = 0,
1470     GROUP_ENDING_NOP,
1471     DEBUG_BREAK_NOP,
1472     // IC markers.
1473     PROPERTY_ACCESS_INLINED,
1474     PROPERTY_ACCESS_INLINED_CONTEXT,
1475     PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1476     // Helper values.
1477     LAST_CODE_MARKER,
1478     FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1479   };
1480 
1481   void nop(int type = 0);  // 0 is the default non-marking type.
1482 
1483   void dumy(int r1, int x2, int b2, int d2);
1484 
1485   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label * label)1486   int SizeOfCodeGeneratedSince(Label* label) {
1487     return pc_offset() - label->pos();
1488   }
1489 
1490   // Record a comment relocation entry that can be used by a disassembler.
1491   // Use --code-comments to enable.
1492   void RecordComment(const char* msg);
1493 
1494   // Record a deoptimization reason that can be used by a log or cpu profiler.
1495   // Use --trace-deopt to enable.
1496   void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
1497                          int id);
1498 
1499   // Writes a single byte or word of data in the code stream.  Used
1500   // for inline tables, e.g., jump-tables.
1501   void db(uint8_t data);
1502   void dd(uint32_t data);
1503   void dq(uint64_t data);
1504   void dp(uintptr_t data);
1505 
PatchConstantPoolAccessInstruction(int pc_offset,int offset,ConstantPoolEntry::Access access,ConstantPoolEntry::Type type)1506   void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1507                                           ConstantPoolEntry::Access access,
1508                                           ConstantPoolEntry::Type type) {
1509     // No embedded constant pool support.
1510     UNREACHABLE();
1511   }
1512 
1513   // Read/patch instructions
instr_at(int pos)1514   SixByteInstr instr_at(int pos) {
1515     return Instruction::InstructionBits(buffer_ + pos);
1516   }
1517   template <typename T>
instr_at_put(int pos,T instr)1518   void instr_at_put(int pos, T instr) {
1519     Instruction::SetInstructionBits<T>(buffer_ + pos, instr);
1520   }
1521 
1522   // Decodes instruction at pos, and returns its length
instr_length_at(int pos)1523   int32_t instr_length_at(int pos) {
1524     return Instruction::InstructionLength(buffer_ + pos);
1525   }
1526 
instr_at(byte * pc)1527   static SixByteInstr instr_at(byte* pc) {
1528     return Instruction::InstructionBits(pc);
1529   }
1530 
1531   static Condition GetCondition(Instr instr);
1532 
1533   static bool IsBranch(Instr instr);
1534 #if V8_TARGET_ARCH_S390X
1535   static bool Is64BitLoadIntoIP(SixByteInstr instr1, SixByteInstr instr2);
1536 #else
1537   static bool Is32BitLoadIntoIP(SixByteInstr instr);
1538 #endif
1539 
1540   static bool IsCmpRegister(Instr instr);
1541   static bool IsCmpImmediate(Instr instr);
1542   static bool IsNop(SixByteInstr instr, int type = NON_MARKING_NOP);
1543 
1544   // The code currently calls CheckBuffer() too often. This has the side
1545   // effect of randomly growing the buffer in the middle of multi-instruction
1546   // sequences.
1547   //
1548   // This function allows outside callers to check and grow the buffer
1549   void EnsureSpaceFor(int space_needed);
1550 
1551   void EmitRelocations();
1552   void emit_label_addr(Label* label);
1553 
1554  public:
buffer_pos()1555   byte* buffer_pos() const { return buffer_; }
1556 
1557  protected:
buffer_space()1558   int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1559 
1560   // Decode instruction(s) at pos and return backchain to previous
1561   // label reference or kEndOfChain.
1562   int target_at(int pos);
1563 
1564   // Patch instruction(s) at pos to target target_pos (e.g. branch)
1565   void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
1566 
1567   // Record reloc info for current pc_
1568   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1569 
1570  private:
1571   // Avoid overflows for displacements etc.
1572   static const int kMaximalBufferSize = 512 * MB;
1573 
1574   // Code generation
1575   // The relocation writer's position is at least kGap bytes below the end of
1576   // the generated instructions. This is so that multi-instruction sequences do
1577   // not have to check for overflow. The same is true for writes of large
1578   // relocation info entries.
1579   static constexpr int kGap = 32;
1580 
1581   // Relocation info generation
1582   // Each relocation is encoded as a variable size value
1583   static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1584   RelocInfoWriter reloc_info_writer;
1585   std::vector<DeferredRelocInfo> relocations_;
1586 
1587   // The bound position, before this we cannot do instruction elimination.
1588   int last_bound_pos_;
1589 
1590   // Code emission
CheckBuffer()1591   void CheckBuffer() {
1592     if (buffer_space() <= kGap) {
1593       GrowBuffer();
1594     }
1595   }
1596   void GrowBuffer(int needed = 0);
1597   inline void TrackBranch();
1598   inline void UntrackBranch();
1599 
1600   // Helper to emit the binary encoding of a 2 byte instruction
emit2bytes(uint16_t x)1601   void emit2bytes(uint16_t x) {
1602     CheckBuffer();
1603 #if V8_TARGET_LITTLE_ENDIAN
1604     // We need to emit instructions in big endian format as disassembler /
1605     // simulator require the first byte of the instruction in order to decode
1606     // the instruction length.  Swap the bytes.
1607     x = ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8);
1608 #endif
1609     *reinterpret_cast<uint16_t*>(pc_) = x;
1610     pc_ += 2;
1611   }
1612 
1613   // Helper to emit the binary encoding of a 4 byte instruction
emit4bytes(uint32_t x)1614   void emit4bytes(uint32_t x) {
1615     CheckBuffer();
1616 #if V8_TARGET_LITTLE_ENDIAN
1617     // We need to emit instructions in big endian format as disassembler /
1618     // simulator require the first byte of the instruction in order to decode
1619     // the instruction length.  Swap the bytes.
1620     x = ((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) |
1621         ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24);
1622 #endif
1623     *reinterpret_cast<uint32_t*>(pc_) = x;
1624     pc_ += 4;
1625   }
1626 
1627   // Helper to emit the binary encoding of a 6 byte instruction
emit6bytes(uint64_t x)1628   void emit6bytes(uint64_t x) {
1629     CheckBuffer();
1630 #if V8_TARGET_LITTLE_ENDIAN
1631     // We need to emit instructions in big endian format as disassembler /
1632     // simulator require the first byte of the instruction in order to decode
1633     // the instruction length.  Swap the bytes.
1634     x = (static_cast<uint64_t>(x & 0xFF) << 40) |
1635         (static_cast<uint64_t>((x >> 8) & 0xFF) << 32) |
1636         (static_cast<uint64_t>((x >> 16) & 0xFF) << 24) |
1637         (static_cast<uint64_t>((x >> 24) & 0xFF) << 16) |
1638         (static_cast<uint64_t>((x >> 32) & 0xFF) << 8) |
1639         (static_cast<uint64_t>((x >> 40) & 0xFF));
1640     x |= (*reinterpret_cast<uint64_t*>(pc_) >> 48) << 48;
1641 #else
1642     // We need to pad two bytes of zeros in order to get the 6-bytes
1643     // stored from low address.
1644     x = x << 16;
1645     x |= *reinterpret_cast<uint64_t*>(pc_) & 0xFFFF;
1646 #endif
1647     // It is safe to store 8-bytes, as CheckBuffer() guarantees we have kGap
1648     // space left over.
1649     *reinterpret_cast<uint64_t*>(pc_) = x;
1650     pc_ += 6;
1651   }
1652 
1653   // Labels
1654   void print(Label* L);
1655   int max_reach_from(int pos);
1656   void bind_to(Label* L, int pos);
1657   void next(Label* L);
1658 
1659   void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
1660 
1661   friend class RegExpMacroAssemblerS390;
1662   friend class RelocInfo;
1663   friend class EnsureSpace;
1664 };
1665 
1666 class EnsureSpace BASE_EMBEDDED {
1667  public:
EnsureSpace(Assembler * assembler)1668   explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1669 };
1670 
1671 }  // namespace internal
1672 }  // namespace v8
1673 
1674 #endif  // V8_S390_ASSEMBLER_S390_H_
1675